From 9560dd167754ae15ebddbc108eb79e51799333be Mon Sep 17 00:00:00 2001 From: MacroGreg Date: Thu, 20 Aug 2020 13:35:02 -0700 Subject: [PATCH] Forking the DataDog .NET Tracer to seed the OTel .NET Auto-Instrumentation-Agent. This is a fork of the DataDog .NET Tracer (aka "in-process agent", aka "auto-instrumentation agent"). It acts as the initial seed for the official Open Telemetry .NET Tracer. We are doing this by merging the current master of https://github.com/DataDog/dd-trace-dotnet into an empty master of https://github.com/open-telemetry/opentelemetry-dotnet-instrumentation. In addition, I cleaned up all auxiliary files not directly related to the product (e.g., demos, tools, vendor-specific integration tests and benchmarks, we well as others). We can add them in later from the original repo if the community requires. Everything builds, all unit tests are passing. --- .clang-format | 3 + .editorconfig | 80 + .gitattributes | 68 + .github/ISSUE_TEMPLATE/bug_report.md | 38 + .github/ISSUE_TEMPLATE/feature_request.md | 22 + .github/pull_request_template.md | 8 + .gitignore | 271 + Datadog.Trace.Native.sln | 120 + Datadog.Trace.sln | 391 + Datadog.Trace.sln.DotSettings | 111 + Datadog.Trace.snk | Bin 0 -> 596 bytes Directory.Build.props | 22 + GlobalSuppressions.cs | 15 + LICENSE-3rdparty.csv | 13 + NOTICE | 4 + datadog-logo-256x256.png | Bin 0 -> 19779 bytes datadog-logo-64x64.png | Bin 0 -> 3194 bytes devenv.bat | 87 + docker/Datadog.Trace.ClrProfiler.Native.sh | 18 + docker/native.alpine.dockerfile | 19 + docker/native.dockerfile | 56 + docs/CHANGELOG.md | 29 + docs/CODE_OF_CONDUCT.md | 76 + docs/CONTRIBUTING.md | 6 + docs/README.md | 129 + git-clean.cmd | 1 + integrations.json | 2395 ++ lib/coreclr/src/inc/CMakeLists.txt | 90 + lib/coreclr/src/inc/CrstTypeTool.cs | 994 + lib/coreclr/src/inc/CrstTypes.def | 711 + lib/coreclr/src/inc/MSCOREE.IDL | 326 + lib/coreclr/src/inc/OpCodeGen.pl | 483 + lib/coreclr/src/inc/allocacheck.h | 84 + lib/coreclr/src/inc/apithreadstress.cpp | 171 + lib/coreclr/src/inc/apithreadstress.h | 57 + lib/coreclr/src/inc/appxutil.h | 51 + lib/coreclr/src/inc/arrayholder.h | 80 + lib/coreclr/src/inc/arraylist.h | 296 + lib/coreclr/src/inc/bbsweep.h | 425 + lib/coreclr/src/inc/bitmask.h | 103 + lib/coreclr/src/inc/bitmask.inl | 292 + lib/coreclr/src/inc/bitposition.h | 59 + lib/coreclr/src/inc/bitvector.h | 462 + lib/coreclr/src/inc/blobfetcher.h | 174 + lib/coreclr/src/inc/cahlpr.h | 41 + lib/coreclr/src/inc/caparser.h | 377 + lib/coreclr/src/inc/ceefilegenwriter.h | 245 + lib/coreclr/src/inc/ceegen.h | 437 + lib/coreclr/src/inc/ceegentokenmapper.h | 142 + lib/coreclr/src/inc/ceesectionstring.h | 55 + lib/coreclr/src/inc/cfi.h | 33 + lib/coreclr/src/inc/check.h | 740 + lib/coreclr/src/inc/check.inl | 367 + lib/coreclr/src/inc/circularlog.h | 38 + lib/coreclr/src/inc/clr/fs.h | 16 + lib/coreclr/src/inc/clr/fs/dir.h | 129 + lib/coreclr/src/inc/clr/fs/file.h | 40 + lib/coreclr/src/inc/clr/fs/path.h | 141 + lib/coreclr/src/inc/clr/stack.h | 99 + lib/coreclr/src/inc/clr/str.h | 28 + lib/coreclr/src/inc/clr/win32.h | 38 + lib/coreclr/src/inc/clr_std/algorithm | 119 + lib/coreclr/src/inc/clr_std/string | 426 + lib/coreclr/src/inc/clr_std/type_traits | 549 + lib/coreclr/src/inc/clr_std/utility | 254 + lib/coreclr/src/inc/clr_std/vector | 431 + lib/coreclr/src/inc/clrconfig.h | 231 + lib/coreclr/src/inc/clrconfigvalues.h | 829 + lib/coreclr/src/inc/clrdata.idl | 313 + lib/coreclr/src/inc/clrhost.h | 392 + lib/coreclr/src/inc/clrinternal.idl | 296 + lib/coreclr/src/inc/clrnt.h | 1042 + lib/coreclr/src/inc/clrprivappxhosting.idl | 66 + lib/coreclr/src/inc/clrprivbinderutil.h | 717 + lib/coreclr/src/inc/clrprivbinding.idl | 295 + lib/coreclr/src/inc/clrprivhosting.idl | 92 + lib/coreclr/src/inc/clrprivruntimebinders.idl | 39 + lib/coreclr/src/inc/clrtypes.h | 411 + lib/coreclr/src/inc/complex.h | 80 + lib/coreclr/src/inc/configuration.h | 63 + lib/coreclr/src/inc/contract.h | 2370 ++ lib/coreclr/src/inc/contract.inl | 640 + lib/coreclr/src/inc/contxt.h | 3472 +++ lib/coreclr/src/inc/cor.h | 2430 ++ lib/coreclr/src/inc/corbbtprof.h | 592 + lib/coreclr/src/inc/corcompile.h | 1827 ++ lib/coreclr/src/inc/cordbpriv.h | 68 + lib/coreclr/src/inc/cordebug.idl | 7574 +++++++ lib/coreclr/src/inc/cordebuginfo.h | 337 + lib/coreclr/src/inc/coredistools.h | 149 + lib/coreclr/src/inc/coregen.h | 25 + lib/coreclr/src/inc/corerror.xml | 2369 ++ lib/coreclr/src/inc/corexcep.h | 36 + lib/coreclr/src/inc/corhdr.h | 1931 ++ lib/coreclr/src/inc/corhlpr.cpp | 307 + lib/coreclr/src/inc/corhlpr.h | 698 + lib/coreclr/src/inc/corhlprpriv.cpp | 313 + lib/coreclr/src/inc/corhlprpriv.h | 773 + lib/coreclr/src/inc/corhost.h | 278 + lib/coreclr/src/inc/corimage.h | 67 + lib/coreclr/src/inc/corinfo.h | 3267 +++ lib/coreclr/src/inc/corjit.h | 461 + lib/coreclr/src/inc/corjitflags.h | 250 + lib/coreclr/src/inc/corjithost.h | 58 + lib/coreclr/src/inc/corpriv.h | 474 + lib/coreclr/src/inc/corprof.idl | 4058 ++++ lib/coreclr/src/inc/corpub.idl | 265 + lib/coreclr/src/inc/corsym.idl | 1785 ++ lib/coreclr/src/inc/cortypeinfo.h | 57 + lib/coreclr/src/inc/crosscomp.h | 378 + lib/coreclr/src/inc/crsttypes.h | 513 + lib/coreclr/src/inc/crtwrap.h | 30 + lib/coreclr/src/inc/cvconst.h | 3728 ++++ lib/coreclr/src/inc/cvinfo.h | 4989 +++++ lib/coreclr/src/inc/cycletimer.h | 56 + lib/coreclr/src/inc/daccess.h | 2462 ++ lib/coreclr/src/inc/dacprivate.h | 1069 + lib/coreclr/src/inc/dacvars.h | 263 + lib/coreclr/src/inc/dbgconfigstrings.h | 23 + lib/coreclr/src/inc/dbgenginemetrics.h | 30 + lib/coreclr/src/inc/dbgmeta.h | 38 + lib/coreclr/src/inc/dbgportable.h | 141 + lib/coreclr/src/inc/debugmacros.h | 269 + lib/coreclr/src/inc/debugmacrosext.h | 46 + lib/coreclr/src/inc/debugreturn.h | 125 + lib/coreclr/src/inc/defaultallocator.h | 49 + lib/coreclr/src/inc/delayloadhelpers.h | 113 + lib/coreclr/src/inc/dlwrap.h | 205 + lib/coreclr/src/inc/eetwain.h | 799 + lib/coreclr/src/inc/eexcp.h | 156 + lib/coreclr/src/inc/entrypoints.h | 29 + lib/coreclr/src/inc/eventtrace.h | 361 + lib/coreclr/src/inc/eventtracebase.h | 1473 ++ lib/coreclr/src/inc/ex.h | 1423 ++ lib/coreclr/src/inc/factory.h | 49 + lib/coreclr/src/inc/factory.inl | 32 + lib/coreclr/src/inc/fixuppointer.h | 1090 + lib/coreclr/src/inc/formattype.cpp | 1570 ++ lib/coreclr/src/inc/formattype.h | 181 + lib/coreclr/src/inc/fstream.h | 50 + lib/coreclr/src/inc/fstring.h | 45 + lib/coreclr/src/inc/fusion.idl | 242 + lib/coreclr/src/inc/gcdecoder.cpp | 624 + lib/coreclr/src/inc/gcdump.h | 102 + lib/coreclr/src/inc/gcinfo.h | 95 + lib/coreclr/src/inc/gcinfoarraylist.h | 114 + lib/coreclr/src/inc/gcinfodecoder.h | 706 + lib/coreclr/src/inc/gcinfodumper.h | 122 + lib/coreclr/src/inc/gcinfoencoder.h | 567 + lib/coreclr/src/inc/gcinfotypes.h | 839 + lib/coreclr/src/inc/gcrefmap.h | 247 + lib/coreclr/src/inc/genheaders.cs | 233 + lib/coreclr/src/inc/genrops.pl | 91 + lib/coreclr/src/inc/getproductversionnumber.h | 77 + lib/coreclr/src/inc/guidfromname.h | 19 + lib/coreclr/src/inc/holder.h | 1399 ++ lib/coreclr/src/inc/holderinst.h | 33 + lib/coreclr/src/inc/iallocator.h | 77 + lib/coreclr/src/inc/iceefilegen.h | 237 + lib/coreclr/src/inc/il_kywd.h | 304 + lib/coreclr/src/inc/ildbsymlib.h | 21 + lib/coreclr/src/inc/ilformatter.h | 76 + lib/coreclr/src/inc/internalunknownimpl.h | 494 + lib/coreclr/src/inc/intrinsic.h | 25 + lib/coreclr/src/inc/iterator.h | 641 + lib/coreclr/src/inc/jithelpers.h | 376 + lib/coreclr/src/inc/jitperf.h | 97 + lib/coreclr/src/inc/lazycow.h | 99 + lib/coreclr/src/inc/livedatatarget.h | 107 + lib/coreclr/src/inc/llvm/Dwarf.def | 393 + lib/coreclr/src/inc/llvm/Dwarf.h | 711 + lib/coreclr/src/inc/llvm/ELF.h | 1273 ++ lib/coreclr/src/inc/loaderheap.h | 1081 + lib/coreclr/src/inc/log.h | 99 + lib/coreclr/src/inc/loglf.h | 42 + lib/coreclr/src/inc/longfilepathwrappers.h | 156 + lib/coreclr/src/inc/md5.h | 134 + lib/coreclr/src/inc/mdcommon.h | 54 + lib/coreclr/src/inc/memorypool.h | 143 + lib/coreclr/src/inc/memoryrange.h | 98 + lib/coreclr/src/inc/metadata.h | 1557 ++ lib/coreclr/src/inc/metadataexports.h | 57 + lib/coreclr/src/inc/metadatatracker.h | 360 + lib/coreclr/src/inc/metahost.idl | 548 + lib/coreclr/src/inc/metamodelpub.h | 1672 ++ lib/coreclr/src/inc/mpl/type_list | 76 + lib/coreclr/src/inc/mscorsvc.idl | 683 + lib/coreclr/src/inc/msodw.h | 35 + lib/coreclr/src/inc/msodwwrap.h | 11 + lib/coreclr/src/inc/nativevaraccessors.h | 48 + lib/coreclr/src/inc/new.hpp | 27 + lib/coreclr/src/inc/ngen.h | 153 + lib/coreclr/src/inc/nibblemapmacros.h | 56 + lib/coreclr/src/inc/nibblestream.h | 300 + lib/coreclr/src/inc/nsutilpriv.h | 266 + lib/coreclr/src/inc/opcode.def | 359 + lib/coreclr/src/inc/openum.h | 51 + lib/coreclr/src/inc/opinfo.h | 83 + lib/coreclr/src/inc/optdefault.h | 12 + lib/coreclr/src/inc/optsmallperfcritical.h | 21 + lib/coreclr/src/inc/ostype.h | 104 + lib/coreclr/src/inc/outstring.h | 157 + lib/coreclr/src/inc/palclr.h | 631 + lib/coreclr/src/inc/palclr_win.h | 144 + lib/coreclr/src/inc/pedecoder.h | 477 + lib/coreclr/src/inc/pedecoder.inl | 1401 ++ lib/coreclr/src/inc/peinformation.h | 75 + lib/coreclr/src/inc/perflog.h | 142 + lib/coreclr/src/inc/pesectionman.h | 213 + lib/coreclr/src/inc/posterror.h | 50 + lib/coreclr/src/inc/predeftlsslot.h | 86 + lib/coreclr/src/inc/prettyprintsig.h | 91 + lib/coreclr/src/inc/profilepriv.h | 162 + lib/coreclr/src/inc/profilepriv.inl | 864 + lib/coreclr/src/inc/random.h | 279 + lib/coreclr/src/inc/rangetree.h | 141 + lib/coreclr/src/inc/readytorun.h | 363 + lib/coreclr/src/inc/readytorunhelpers.h | 121 + lib/coreclr/src/inc/regdisp.h | 551 + lib/coreclr/src/inc/regex_base.h | 973 + lib/coreclr/src/inc/regex_util.h | 209 + lib/coreclr/src/inc/registrywrapper.h | 20 + lib/coreclr/src/inc/releaseholder.h | 77 + lib/coreclr/src/inc/safemath.h | 858 + lib/coreclr/src/inc/safewrap.h | 171 + lib/coreclr/src/inc/sarray.h | 229 + lib/coreclr/src/inc/sarray.inl | 376 + lib/coreclr/src/inc/sbuffer.h | 575 + lib/coreclr/src/inc/sbuffer.inl | 1698 ++ lib/coreclr/src/inc/securityutil.h | 53 + lib/coreclr/src/inc/securitywrapper.h | 103 + lib/coreclr/src/inc/shash.h | 1106 + lib/coreclr/src/inc/shash.inl | 943 + lib/coreclr/src/inc/shim/locationinfo.h | 42 + lib/coreclr/src/inc/shim/runtimeselector.h | 55 + lib/coreclr/src/inc/shim/runtimeselector.inl | 105 + lib/coreclr/src/inc/shim/shimselector.h | 55 + lib/coreclr/src/inc/shim/shimselector.inl | 104 + .../src/inc/shim/versionandlocationinfo.h | 36 + .../src/inc/shim/versionandlocationinfo.inl | 35 + lib/coreclr/src/inc/shim/versioninfo.h | 46 + lib/coreclr/src/inc/shim/versioninfo.inl | 170 + lib/coreclr/src/inc/shimload.h | 27 + lib/coreclr/src/inc/sigbuilder.h | 79 + lib/coreclr/src/inc/sigparser.h | 985 + lib/coreclr/src/inc/simplerhash.h | 423 + lib/coreclr/src/inc/simplerhash.inl | 350 + lib/coreclr/src/inc/slist.h | 387 + lib/coreclr/src/inc/sospriv.idl | 379 + lib/coreclr/src/inc/sstring.h | 1031 + lib/coreclr/src/inc/sstring.inl | 2232 ++ lib/coreclr/src/inc/stack.h | 87 + lib/coreclr/src/inc/stackframe.h | 127 + lib/coreclr/src/inc/stacktrace.h | 91 + lib/coreclr/src/inc/static_assert.h | 28 + lib/coreclr/src/inc/staticcontract.h | 359 + lib/coreclr/src/inc/stdmacros.h | 360 + lib/coreclr/src/inc/stgpool.h | 1548 ++ lib/coreclr/src/inc/stgpooli.h | 256 + lib/coreclr/src/inc/stresslog.h | 846 + lib/coreclr/src/inc/stringarraylist.h | 31 + lib/coreclr/src/inc/stringarraylist.inl | 76 + lib/coreclr/src/inc/strongname.h | 9 + lib/coreclr/src/inc/switches.h | 200 + lib/coreclr/src/inc/tls.h | 28 + lib/coreclr/src/inc/utilcode.h | 5316 +++++ lib/coreclr/src/inc/utsem.h | 63 + lib/coreclr/src/inc/vererror.h | 137 + lib/coreclr/src/inc/volatile.h | 532 + lib/coreclr/src/inc/vptr_list.h | 121 + lib/coreclr/src/inc/warningcontrol.h | 48 + lib/coreclr/src/inc/win64unwind.h | 126 + lib/coreclr/src/inc/winrt/ntassert.h | 210 + lib/coreclr/src/inc/winrt/paraminstanceapi.h | 1756 ++ lib/coreclr/src/inc/winrt/windowsruntime.h | 52 + lib/coreclr/src/inc/winrt/windowsstring.h | 774 + lib/coreclr/src/inc/winrtprojectedtypes.h | 271 + lib/coreclr/src/inc/winwrap.h | 533 + lib/coreclr/src/inc/xclrdata.idl | 2552 +++ lib/coreclr/src/inc/xcordebug.idl | 56 + lib/coreclr/src/inc/zapper.h | 452 + lib/coreclr/src/pal/inc/mbusafecrt.h | 116 + lib/coreclr/src/pal/inc/pal.h | 5411 +++++ lib/coreclr/src/pal/inc/pal_assert.h | 61 + lib/coreclr/src/pal/inc/pal_char16.h | 55 + lib/coreclr/src/pal/inc/pal_endian.h | 169 + lib/coreclr/src/pal/inc/pal_error.h | 142 + lib/coreclr/src/pal/inc/pal_mstypes.h | 718 + lib/coreclr/src/pal/inc/pal_safecrt.h | 55 + lib/coreclr/src/pal/inc/pal_unwind.h | 91 + lib/coreclr/src/pal/inc/palprivate.h | 287 + lib/coreclr/src/pal/inc/rt/accctrl.h | 13 + lib/coreclr/src/pal/inc/rt/aclapi.h | 13 + lib/coreclr/src/pal/inc/rt/atl.h | 557 + lib/coreclr/src/pal/inc/rt/atlcom.h | 13 + lib/coreclr/src/pal/inc/rt/atlwin.h | 13 + lib/coreclr/src/pal/inc/rt/commctrl.h | 13 + lib/coreclr/src/pal/inc/rt/commdlg.h | 13 + lib/coreclr/src/pal/inc/rt/conio.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/cstdlib | 14 + lib/coreclr/src/pal/inc/rt/cpp/ctype.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/fcntl.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/float.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/io.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/limits.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/malloc.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/math.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/memory.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/stdarg.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/stddef.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/stdint.h | 5 + lib/coreclr/src/pal/inc/rt/cpp/stdio.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/stdlib.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/string.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/time.h | 13 + lib/coreclr/src/pal/inc/rt/cpp/wchar.h | 13 + lib/coreclr/src/pal/inc/rt/crtdbg.h | 13 + lib/coreclr/src/pal/inc/rt/dbghelp.h | 37 + lib/coreclr/src/pal/inc/rt/eh.h | 5 + lib/coreclr/src/pal/inc/rt/errorrep.h | 5 + lib/coreclr/src/pal/inc/rt/guiddef.h | 26 + lib/coreclr/src/pal/inc/rt/hstring.h | 5 + lib/coreclr/src/pal/inc/rt/htmlhelp.h | 13 + lib/coreclr/src/pal/inc/rt/imagehlp.h | 64 + lib/coreclr/src/pal/inc/rt/intrin.h | 5 + lib/coreclr/src/pal/inc/rt/intsafe.h | 1409 ++ lib/coreclr/src/pal/inc/rt/mbstring.h | 13 + lib/coreclr/src/pal/inc/rt/new.h | 13 + lib/coreclr/src/pal/inc/rt/no_sal2.h | 534 + lib/coreclr/src/pal/inc/rt/ntimage.h | 1790 ++ lib/coreclr/src/pal/inc/rt/oaidl.h | 111 + lib/coreclr/src/pal/inc/rt/objbase.h | 9 + lib/coreclr/src/pal/inc/rt/objidl.h | 293 + lib/coreclr/src/pal/inc/rt/ocidl.h | 13 + lib/coreclr/src/pal/inc/rt/ole2.h | 12 + lib/coreclr/src/pal/inc/rt/oleauto.h | 134 + lib/coreclr/src/pal/inc/rt/olectl.h | 13 + lib/coreclr/src/pal/inc/rt/oleidl.h | 13 + lib/coreclr/src/pal/inc/rt/palrt.h | 1536 ++ lib/coreclr/src/pal/inc/rt/poppack.h | 39 + lib/coreclr/src/pal/inc/rt/process.h | 13 + lib/coreclr/src/pal/inc/rt/psapi.h | 5 + lib/coreclr/src/pal/inc/rt/pshpack1.h | 38 + lib/coreclr/src/pal/inc/rt/pshpack2.h | 37 + lib/coreclr/src/pal/inc/rt/pshpack4.h | 38 + lib/coreclr/src/pal/inc/rt/pshpack8.h | 38 + lib/coreclr/src/pal/inc/rt/pshpck16.h | 38 + lib/coreclr/src/pal/inc/rt/richedit.h | 13 + lib/coreclr/src/pal/inc/rt/rpc.h | 34 + lib/coreclr/src/pal/inc/rt/rpcndr.h | 20 + lib/coreclr/src/pal/inc/rt/safecrt.h | 3370 +++ lib/coreclr/src/pal/inc/rt/sal.h | 2953 +++ lib/coreclr/src/pal/inc/rt/servprov.h | 32 + lib/coreclr/src/pal/inc/rt/share.h | 5 + lib/coreclr/src/pal/inc/rt/shellapi.h | 13 + lib/coreclr/src/pal/inc/rt/shlobj.h | 13 + lib/coreclr/src/pal/inc/rt/shlwapi.h | 13 + lib/coreclr/src/pal/inc/rt/specstrings.h | 533 + lib/coreclr/src/pal/inc/rt/specstrings_adt.h | 58 + .../src/pal/inc/rt/specstrings_strict.h | 1190 + .../src/pal/inc/rt/specstrings_undef.h | 464 + lib/coreclr/src/pal/inc/rt/symcrypt.h | 13 + lib/coreclr/src/pal/inc/rt/tchar.h | 5 + lib/coreclr/src/pal/inc/rt/tlhelp32.h | 13 + lib/coreclr/src/pal/inc/rt/unknwn.h | 66 + lib/coreclr/src/pal/inc/rt/urlmon.h | 13 + lib/coreclr/src/pal/inc/rt/verrsrc.h | 13 + lib/coreclr/src/pal/inc/rt/vsassert.h | 93 + lib/coreclr/src/pal/inc/rt/winapifamily.h | 40 + lib/coreclr/src/pal/inc/rt/winbase.h | 13 + lib/coreclr/src/pal/inc/rt/wincrypt.h | 13 + lib/coreclr/src/pal/inc/rt/windef.h | 13 + lib/coreclr/src/pal/inc/rt/windows.h | 13 + lib/coreclr/src/pal/inc/rt/winerror.h | 13 + lib/coreclr/src/pal/inc/rt/wininet.h | 13 + lib/coreclr/src/pal/inc/rt/winnls.h | 13 + lib/coreclr/src/pal/inc/rt/winnt.h | 13 + lib/coreclr/src/pal/inc/rt/winresrc.h | 15 + lib/coreclr/src/pal/inc/rt/winternl.h | 13 + lib/coreclr/src/pal/inc/rt/winuser.h | 13 + lib/coreclr/src/pal/inc/rt/winver.h | 30 + lib/coreclr/src/pal/inc/rt/wtsapi32.h | 13 + lib/coreclr/src/pal/inc/rt/x86intrin.h | 1 + lib/coreclr/src/pal/inc/strsafe.h | 4162 ++++ lib/coreclr/src/pal/inc/unixasmmacros.inc | 43 + .../src/pal/inc/unixasmmacrosamd64.inc | 364 + lib/coreclr/src/pal/inc/unixasmmacrosarm.inc | 268 + .../src/pal/inc/unixasmmacrosarm64.inc | 344 + lib/coreclr/src/pal/inc/unixasmmacrosx86.inc | 118 + .../src/pal/prebuilt/inc/CMakeLists.txt | 6 + .../src/pal/prebuilt/inc/asm_version.h | 22 + .../src/pal/prebuilt/inc/buildnumber.h | 23 + lib/coreclr/src/pal/prebuilt/inc/clrdata.h | 1146 + .../src/pal/prebuilt/inc/clrinternal.h | 847 + .../src/pal/prebuilt/inc/clrprivbinding.h | 1057 + .../src/pal/prebuilt/inc/clrprivhosting.h | 236 + .../pal/prebuilt/inc/clrprivruntimebinders.h | 107 + lib/coreclr/src/pal/prebuilt/inc/cordebug.h | 18527 ++++++++++++++++ lib/coreclr/src/pal/prebuilt/inc/corerror.h | 421 + lib/coreclr/src/pal/prebuilt/inc/corprof.h | 16493 ++++++++++++++ lib/coreclr/src/pal/prebuilt/inc/corpub.h | 821 + lib/coreclr/src/pal/prebuilt/inc/corsym.h | 5706 +++++ lib/coreclr/src/pal/prebuilt/inc/fusion.h | 407 + lib/coreclr/src/pal/prebuilt/inc/fxver.h | 203 + lib/coreclr/src/pal/prebuilt/inc/fxver.rc | 100 + .../src/pal/prebuilt/inc/fxverstrings.h | 17 + lib/coreclr/src/pal/prebuilt/inc/metahost.h | 809 + lib/coreclr/src/pal/prebuilt/inc/mscoree.h | 911 + lib/coreclr/src/pal/prebuilt/inc/mscorsvc.h | 2824 +++ lib/coreclr/src/pal/prebuilt/inc/ndpversion.h | 4 + .../pal/prebuilt/inc/ndpversion_generated.h | 15 + .../src/pal/prebuilt/inc/product_version.h | 113 + lib/coreclr/src/pal/prebuilt/inc/readme.txt | 1 + lib/coreclr/src/pal/prebuilt/inc/sospriv.h | 2365 ++ lib/coreclr/src/pal/prebuilt/inc/version.h | 17 + lib/coreclr/src/pal/prebuilt/inc/xclrdata.h | 7909 +++++++ lib/coreclr/src/pal/prebuilt/inc/xcordebug.h | 268 + pre-build-events-cpp.bat | 21 + sample-libs/Directory.Build.props | 6 + sample-libs/Samples.ExampleLibrary/Class1.cs | 136 + .../Directory.Build.props | 6 + .../FakeClient/Biscuit.cs | 27 + .../FakeClient/DogClient.cs | 76 + .../FakeClient/DogTrick.cs | 13 + .../GenericTests/ComprehensiveCaller.cs | 136 + .../GenericTests/GenericTarget.cs | 25 + .../GenericTests/PointStruct.cs | 13 + .../GenericTests/StructContainer.cs | 17 + .../Samples.ExampleLibrary.csproj | 7 + .../Samples.ExampleLibraryTracer/Class1.cs | 17 + .../Directory.Build.props | 6 + .../Samples.ExampleLibraryTracer.csproj | 7 + .../Samples.Shared/Samples.Shared.csproj | 13 + .../Web/DistributedTracingModel.cs | 45 + .../Web/HttpClientExtensions.cs | 25 + .../AspNetScopeManager.cs | 37 + src/Datadog.Trace.AspNet/AssemblyInfo.cs | 4 + .../Datadog.Trace.AspNet.csproj | 35 + .../HttpApplicationStartup.cs | 35 + src/Datadog.Trace.AspNet/TracingHttpModule.cs | 192 + src/Datadog.Trace.Ci.Shared/BuildTags.cs | 138 + .../CIEnvironmentValues.cs | 279 + src/Datadog.Trace.Ci.Shared/CommonTags.cs | 78 + .../Datadog.Trace.Ci.Shared.projitems | 17 + .../Datadog.Trace.Ci.Shared.shproj | 13 + src/Datadog.Trace.Ci.Shared/TestTags.cs | 73 + .../AssemblyInfo.cs | 6 + .../ClrNames.cs | 35 + ...adog.Trace.ClrProfiler.Managed.Core.csproj | 16 + .../IntegrationVersionRange.cs | 94 + .../InterceptMethodAttribute.cs | 112 + .../MethodReplacementActionType.cs | 27 + .../TypeExtensions.cs | 77 + ...og.Trace.ClrProfiler.Managed.Loader.csproj | 13 + .../FileSink.cs | 56 + .../ManagedProfilerAssemblyLoadContext.cs | 15 + .../Startup.NetCore.cs | 58 + .../Startup.NetFramework.cs | 57 + .../Startup.cs | 58 + .../StartupLogger.cs | 167 + .../AssemblyInfo.cs | 5 + .../Datadog.Trace.ClrProfiler.Managed.csproj | 52 + ...ace.ClrProfiler.Managed.csproj.DotSettings | 5 + .../DynamicMethodBuilder.cs | 63 + .../Emit/DelegateMetadata.cs | 52 + .../Emit/DynamicMethodBuilder.cs | 327 + .../Emit/MemberResult.cs | 87 + .../Emit/MethodBuilder.cs | 810 + .../Emit/ModuleLookup.cs | 93 + .../Emit/ObjectExtensions.cs | 360 + .../Emit/OpCodeValues.cs | 11 + .../GlobalSuppressions.cs | 9 + .../Helpers/AsyncHelper.cs | 147 + .../Helpers/Interception.cs | 51 + .../Helpers/PointerHelpers.cs | 21 + .../ReflectionHttpHeadersCollection.cs | 44 + .../Helpers/TaskExtensions.cs | 32 + .../Instrumentation.cs | 61 + .../Integrations/AdoNet/AdoNetConstants.cs | 42 + .../AdoNet/DbCommandIntegration.cs | 577 + .../AdoNet/IDbCommandIntegration.cs | 305 + .../AdoNet/NpgsqlCommandIntegration.cs | 608 + .../AdoNet/SqlCommandIntegration.cs | 519 + .../AspNet/AspNetMvcIntegration.cs | 362 + .../AspNet/AspNetWebApi2Integration.cs | 330 + .../ElasticsearchNet5Integration.cs | 199 + .../ElasticsearchNet6Integration.cs | 187 + .../Integrations/ElasticsearchNetCommon.cs | 72 + .../Integrations/GraphQLIntegration.cs | 413 + .../HttpMessageHandlerIntegration.cs | 296 + .../Integrations/LoggerExtensions.cs | 47 + .../Integrations/MongoDbIntegration.cs | 488 + .../Integrations/RedisHelper.cs | 58 + .../ServiceStackRedisIntegration.cs | 130 + .../ConnectionMultiplexer.cs | 238 + .../StackExchange.Redis/RedisBatch.cs | 168 + .../StackExchangeRedisHelper.cs | 77 + .../Integrations/Testing/AsyncTool.cs | 215 + .../Testing/TestLoggerExtensions.cs | 18 + .../Integrations/Testing/XUnitIntegration.cs | 522 + .../Integrations/WcfIntegration.cs | 170 + .../Integrations/WebRequestIntegration.cs | 201 + .../MemberAccessor.cs | 52 + .../MetadataNames.cs | 38 + .../NativeMethods.cs | 36 + .../ScopeFactory.cs | 162 + .../CMakeLists.txt | 72 + ...tadog.Trace.ClrProfiler.Native.DLL.vcxproj | 213 + .../Datadog.Trace.ClrProfiler.Native.def | 7 + .../Datadog.Trace.ClrProfiler.Native.vcxproj | 196 + .../Directory.Build.props | 2 + .../Resource.rc | 110 + .../class_factory.cpp | 61 + .../class_factory.h | 27 + .../clr_helpers.cpp | 1002 + .../clr_helpers.h | 378 + .../com_ptr.h | 144 + .../cor_profiler.cpp | 1896 ++ .../cor_profiler.h | 118 + .../cor_profiler_base.cpp | 478 + .../cor_profiler_base.h | 228 + .../dd_profiler_constants.h | 63 + .../dllmain.cpp | 51 + .../dllmain.h | 8 + .../environment_variables.h | 101 + .../il_rewriter.cpp | 654 + .../il_rewriter.h | 130 + .../il_rewriter_wrapper.cpp | 156 + .../il_rewriter_wrapper.h | 36 + .../integration.cpp | 131 + .../integration.h | 306 + .../integration_loader.cpp | 227 + .../integration_loader.h | 38 + .../interop.cpp | 17 + .../logging.cpp | 44 + .../logging.h | 43 + src/Datadog.Trace.ClrProfiler.Native/macros.h | 15 + .../metadata_builder.cpp | 150 + .../metadata_builder.h | 42 + .../miniutf.cpp | 408 + .../miniutf.hpp | 110 + .../miniutfdata.h | 1901 ++ .../module_metadata.h | 111 + .../packages.config | 4 + src/Datadog.Trace.ClrProfiler.Native/pal.h | 75 + .../resource.h | 18 + .../sig_helpers.cpp | 266 + .../sig_helpers.h | 9 + .../string.cpp | 35 + src/Datadog.Trace.ClrProfiler.Native/string.h | 26 + src/Datadog.Trace.ClrProfiler.Native/util.cpp | 85 + src/Datadog.Trace.ClrProfiler.Native/util.h | 41 + .../version.h | 3 + src/Datadog.Trace.OpenTracing/AssemblyInfo.cs | 5 + .../Datadog.Trace.OpenTracing.csproj | 24 + src/Datadog.Trace.OpenTracing/DatadogTags.cs | 28 + .../HttpHeadersCodec.cs | 50 + src/Datadog.Trace.OpenTracing/ICodec.cs | 9 + .../OpenTracingHttpHeadersCarrier.cs | 79 + .../OpenTracingSpan.cs | 129 + .../OpenTracingSpanBuilder.cs | 177 + .../OpenTracingSpanContext.cs | 28 + .../OpenTracingTracer.cs | 73 + .../OpenTracingTracerFactory.cs | 40 + .../TextMapHeadersCollection.cs | 43 + src/Datadog.Trace/Abstractions/IScope.cs | 9 + src/Datadog.Trace/Abstractions/ISpan.cs | 22 + src/Datadog.Trace/Agent/AgentWriter.cs | 132 + src/Datadog.Trace/Agent/AgentWriterBuffer.cs | 53 + src/Datadog.Trace/Agent/Api.cs | 211 + src/Datadog.Trace/Agent/ApiWebRequest.cs | 52 + .../Agent/ApiWebRequestFactory.cs | 13 + src/Datadog.Trace/Agent/ApiWebResponse.cs | 38 + src/Datadog.Trace/Agent/IAgentWriter.cs | 17 + src/Datadog.Trace/Agent/IApi.cs | 9 + src/Datadog.Trace/Agent/IApiRequest.cs | 17 + src/Datadog.Trace/Agent/IApiRequestFactory.cs | 13 + src/Datadog.Trace/Agent/IApiResponse.cs | 14 + .../MessagePack/FormatterResolverWrapper.cs | 20 + .../MessagePack/SpanFormatterResolver.cs | 27 + .../MessagePack/SpanMessagePackFormatter.cs | 108 + src/Datadog.Trace/AgentHttpHeaderNames.cs | 41 + src/Datadog.Trace/AssemblyInfo.cs | 16 + src/Datadog.Trace/AsyncLocalCompat.cs | 50 + src/Datadog.Trace/AsyncLocalScopeManager.cs | 23 + .../CompositeConfigurationSource.cs | 110 + .../Configuration/ConfigurationKeys.cs | 251 + .../EnvironmentConfigurationSource.cs | 17 + .../Configuration/GlobalSettings.cs | 127 + .../Configuration/IConfigurationSource.cs | 50 + .../Configuration/IntegrationSettings.cs | 59 + .../IntegrationSettingsCollection.cs | 34 + .../Configuration/JsonConfigurationSource.cs | 148 + .../NameValueConfigurationSource.cs | 29 + .../StringConfigurationSource.cs | 94 + .../Configuration/TracerSettings.cs | 320 + src/Datadog.Trace/CorrelationIdentifier.cs | 73 + src/Datadog.Trace/Datadog.Trace.csproj | 57 + .../AspNetCoreDiagnosticObserver.cs | 290 + .../AspNetCoreDiagnosticOptions.cs | 42 + .../DiagnosticListeners/DiagnosticManager.cs | 94 + .../DiagnosticListeners/DiagnosticObserver.cs | 67 + .../DiagnosticListeners/IDiagnosticManager.cs | 9 + src/Datadog.Trace/DisposableObjectHandle.cs | 52 + src/Datadog.Trace/DogStatsd/NoOpStatsd.cs | 63 + .../DogStatsd/StatsdExtensions.cs | 53 + .../DogStatsd/TracerMetricNames.cs | 94 + .../ExtensionMethods/DictionaryExtensions.cs | 67 + .../NameValueCollectionExtensions.cs | 27 + .../ExtensionMethods/SpanExtensions.cs | 80 + .../ExtensionMethods/StringExtensions.cs | 68 + .../ExtensionMethods/TimeExtensions.cs | 22 + .../ExtensionMethods/WebHeadersExtensions.cs | 31 + .../FrameworkDescription.NetCore.cs | 99 + .../FrameworkDescription.NetFramework.cs | 65 + src/Datadog.Trace/FrameworkDescription.cs | 98 + .../Headers/DictionaryHeadersCollection.cs | 63 + .../Headers/IHeadersCollection.cs | 37 + .../Headers/NameValueHeadersCollection.cs | 37 + .../Headers/WebHeadersCollection.cs | 33 + src/Datadog.Trace/HttpHeaderNames.cs | 34 + src/Datadog.Trace/IDatadogTracer.cs | 40 + src/Datadog.Trace/IScopeManager.cs | 26 + src/Datadog.Trace/ISpanContext.cs | 23 + src/Datadog.Trace/ITraceContext.cs | 21 + src/Datadog.Trace/Logging/DatadogLogging.cs | 183 + .../Logging/LibLogScopeEventSubscriber.cs | 180 + .../Logging/LoggingExtensions.cs | 13 + src/Datadog.Trace/Metrics.cs | 25 + .../PlatformHelpers/AzureAppservices.cs | 133 + .../PlatformHelpers/ContainerMetadata.cs | 80 + .../Sampling/CustomSamplingRule.cs | 155 + .../Sampling/DefaultSamplingRule.cs | 62 + .../Sampling/GlobalSamplingRule.cs | 37 + src/Datadog.Trace/Sampling/IRateLimiter.cs | 9 + src/Datadog.Trace/Sampling/ISampler.cs | 13 + src/Datadog.Trace/Sampling/ISamplingRule.cs | 21 + src/Datadog.Trace/Sampling/RateLimiter.cs | 150 + .../Sampling/RuleBasedSampler.cs | 106 + src/Datadog.Trace/SamplingPriority.cs | 28 + src/Datadog.Trace/Scope.cs | 66 + src/Datadog.Trace/ScopeManagerBase.cs | 72 + src/Datadog.Trace/Span.cs | 420 + src/Datadog.Trace/SpanContext.cs | 118 + src/Datadog.Trace/SpanContextPropagator.cs | 183 + src/Datadog.Trace/SpanEventArgs.cs | 19 + src/Datadog.Trace/SpanKinds.cs | 34 + src/Datadog.Trace/SpanTypes.cs | 60 + src/Datadog.Trace/Tags.cs | 214 + src/Datadog.Trace/TimeConstants.cs | 11 + src/Datadog.Trace/TraceContext.cs | 156 + src/Datadog.Trace/Tracer.cs | 675 + src/Datadog.Trace/TracerConstants.cs | 14 + src/Datadog.Trace/TracingProcessManager.cs | 667 + src/Datadog.Trace/Util/DbCommandCache.cs | 104 + src/Datadog.Trace/Util/DomainMetadata.cs | 127 + src/Datadog.Trace/Util/EnvironmentHelpers.cs | 53 + src/Datadog.Trace/Util/PropertyFetcher.cs | 112 + src/Datadog.Trace/Util/SpanIdGenerator.cs | 58 + src/Datadog.Trace/Util/StopwatchHelpers.cs | 21 + src/Datadog.Trace/Util/UriHelpers.cs | 84 + .../Vendors/MessagePack/Attributes.cs | 79 + .../Vendors/MessagePack/BitOperations.cs | 40 + .../Vendors/MessagePack/FloatBits.cs | 122 + .../Formatters/CollectionFormatter.cs | 1103 + .../Formatters/CollectionHelpers`2.cs | 57 + .../Formatters/DictionaryFormatter.cs | 457 + .../DynamicObjectTypeFallbackFormatter.cs | 102 + .../Formatters/EnumAsStringFormatter.cs | 54 + .../Formatters/ForceSizePrimitiveFormatter.cs | 833 + .../Formatters/ForceSizePrimitiveFormatter.tt | 138 + .../Formatters/IMessagePackFormatter.cs | 19 + .../MessagePack/Formatters/IgnoreFormatter.cs | 20 + .../MultiDimentionalArrayFormatter.cs | 307 + .../Formatters/NullableFormatter.cs | 75 + .../Formatters/OldSpecFormatter.cs | 264 + .../Formatters/PrimitiveFormatter.cs | 1335 ++ .../Formatters/PrimitiveFormatter.tt | 139 + .../Formatters/PrimitiveObjectFormatter.cs | 257 + .../StandardClassLibraryFormatter.cs | 574 + .../MessagePack/Formatters/TupleFormatter.cs | 457 + .../MessagePack/Formatters/TupleFormatter.tt | 71 + .../Formatters/ValueTupleFormatter.tt | 62 + .../Vendors/MessagePack/HashCode.cs | 485 + .../Vendors/MessagePack/IFormatterResolver.cs | 67 + ...essagePackSerializationCallbackReceiver.cs | 16 + .../Vendors/MessagePack/Internal/ArrayPool.cs | 71 + .../MessagePack/Internal/ByteArrayComparer.cs | 143 + .../Internal/ByteArrayStringHashTable.cs | 196 + .../MessagePack/Internal/ExpressionUtility.cs | 92 + .../Vendors/MessagePack/Internal/GuidBits.cs | 376 + .../Internal/ReflectionExtensions.cs | 61 + .../Internal/ThreadsafeTypeKeyHashTable.cs | 236 + .../MessagePack/Internal/TinyJsonReader.cs | 359 + .../MessagePack/Internal/UnsafeMemory.tt | 67 + .../MessagePack/LZ4/Codec/LZ4Codec.Helper.cs | 89 + .../MessagePack/LZ4/Codec/LZ4Codec.Safe.cs | 441 + .../LZ4/Codec/LZ4Codec.Safe32.Dirty.cs | 669 + .../LZ4/Codec/LZ4Codec.Safe64.Dirty.cs | 682 + .../MessagePack/LZ4/Codec/LZ4Codec.Unsafe.cs | 226 + .../LZ4/Codec/LZ4Codec.Unsafe32.Dirty.cs | 684 + .../LZ4/Codec/LZ4Codec.Unsafe64.Dirty.cs | 686 + .../Vendors/MessagePack/LZ4/Codec/LZ4Codec.cs | 162 + .../LZ4/LZ4MessagePackSerializer.JSON.cs | 263 + .../LZ4MessagePackSerializer.NonGeneric.cs | 281 + .../LZ4/LZ4MessagePackSerializer.cs | 365 + .../MessagePack/MessagePack.csproj.txt | 98 + .../Vendors/MessagePack/MessagePackBinary.cs | 5929 +++++ .../Vendors/MessagePack/MessagePackCode.cs | 203 + .../MessagePack/MessagePackSecurity.cs | 364 + .../MessagePack/MessagePackSerializer.Json.cs | 339 + .../MessagePackSerializer.NonGeneric.cs | 324 + .../MessagePack/MessagePackSerializer.cs | 331 + src/Datadog.Trace/Vendors/MessagePack/Nil.cs | 77 + .../Resolvers/AttributeFormatterResolver.cs | 56 + .../MessagePack/Resolvers/BuiltinResolver.cs | 155 + .../Resolvers/CompositeResolver.cs | 111 + .../ContractlessReflectionObjectResolver.cs | 309 + .../Resolvers/DynamicEnumAsStringResolver.cs | 64 + .../Resolvers/DynamicGenericResolver.cs | 266 + .../Resolvers/NativeDateTimeResolver.cs | 59 + .../MessagePack/Resolvers/OldSpecResolver.cs | 59 + .../Resolvers/PrimitiveObjectResolver.cs | 69 + .../MessagePack/Resolvers/StandardResolver.cs | 349 + .../Vendors/MessagePack/StringEncoding.cs | 13 + .../FileLoggerConfigurationExtensions.cs | 343 + .../Serilog.Sinks.File/RollingInterval.cs | 56 + .../Serilog.Sinks.File.csproj.txt | 54 + .../Serilog.Sinks.File/Sinks/File/Clock.cs | 42 + .../Serilog.Sinks.File/Sinks/File/FileSink.cs | 125 + .../Sinks/File/IFileSink.cs | 33 + .../Sinks/File/IFlushableFileSink.cs | 31 + .../Serilog.Sinks.File/Sinks/File/IOErrors.cs | 35 + .../Serilog.Sinks.File/Sinks/File/NullSink.cs | 34 + .../Sinks/File/PathRoller.cs | 120 + .../Sinks/File/PeriodicFlushToDiskSink.cs | 78 + .../Sinks/File/RollingFileSink.cs | 237 + .../Sinks/File/RollingIntervalExtensions.cs | 90 + .../Sinks/File/RollingLogFile.cs | 38 + .../Sinks/File/SharedFileSink.AtomicAppend.cs | 178 + .../Sinks/File/SharedFileSink.OSMutex.cs | 172 + .../Sinks/File/WriteCountingStream.cs | 80 + .../Vendors/Serilog/Capturing/DepthLimiter.cs | 85 + .../Capturing/GetablePropertyFinder.cs | 56 + .../Capturing/MessageTemplateProcessor.cs | 50 + .../Serilog/Capturing/PropertyBinder.cs | 136 + .../Capturing/PropertyValueConverter.cs | 378 + .../Serilog/Configuration/ILoggerSettings.cs | 32 + .../LoggerAuditSinkConfiguration.cs | 110 + .../LoggerDestructuringConfiguration.cs | 198 + .../LoggerEnrichmentConfiguration.cs | 98 + .../LoggerFilterConfiguration.cs | 96 + .../LoggerMinimumLevelConfiguration.cs | 160 + .../LoggerSettingsConfiguration.cs | 73 + .../Configuration/LoggerSinkConfiguration.cs | 247 + .../Vendors/Serilog/Context/ImmutableStack.cs | 71 + .../Vendors/Serilog/Context/LogContext.cs | 283 + .../Vendors/Serilog/Core/Constants.cs | 33 + .../Serilog/Core/Enrichers/EmptyEnricher.cs | 29 + .../Core/Enrichers/FixedPropertyEnricher.cs | 39 + .../Core/Enrichers/PropertyEnricher.cs | 65 + .../Core/Enrichers/SafeAggregateEnricher.cs | 52 + .../Serilog/Core/Filters/DelegateFilter.cs | 40 + .../Serilog/Core/IDestructuringPolicy.cs | 38 + .../Vendors/Serilog/Core/ILogEventEnricher.cs | 35 + .../Vendors/Serilog/Core/ILogEventFilter.cs | 36 + .../Serilog/Core/ILogEventPropertyFactory.cs | 40 + .../Core/ILogEventPropertyValueFactory.cs | 26 + .../Vendors/Serilog/Core/ILogEventSink.cs | 34 + .../Serilog/Core/IMessageTemplateParser.cs | 27 + .../Serilog/Core/IScalarConversionPolicy.cs | 23 + .../Vendors/Serilog/Core/LevelOverrideMap.cs | 85 + .../Vendors/Serilog/Core/Logger.cs | 1386 ++ .../Serilog/Core/LoggingLevelSwitch.cs | 52 + .../MessageTemplateFormatMethodAttribute.cs | 45 + .../Core/Pipeline/MessageTemplateCache.cs | 91 + .../Serilog/Core/Pipeline/SilentLogger.cs | 361 + .../Serilog/Core/Sinks/AggregateSink.cs | 58 + .../Serilog/Core/Sinks/FilteringSink.cs | 63 + .../Serilog/Core/Sinks/RestrictedSink.cs | 52 + .../Serilog/Core/Sinks/SafeAggregateSink.cs | 52 + .../Serilog/Core/Sinks/SecondaryLoggerSink.cs | 66 + .../Data/LogEventPropertyValueRewriter.cs | 158 + .../Data/LogEventPropertyValueVisitor.cs | 117 + .../Debugging/LoggingFailedException.cs | 38 + .../Vendors/Serilog/Debugging/SelfLog.cs | 106 + .../Serilog/Enrichers/LogContextEnricher.cs | 32 + .../Vendors/Serilog/Events/DictionaryValue.cs | 73 + .../Vendors/Serilog/Events/LevelAlias.cs | 39 + .../Vendors/Serilog/Events/LogEvent.cs | 132 + .../Vendors/Serilog/Events/LogEventLevel.cs | 61 + .../Serilog/Events/LogEventProperty.cs | 65 + .../Serilog/Events/LogEventPropertyValue.cs | 69 + .../Vendors/Serilog/Events/MessageTemplate.cs | 170 + .../Vendors/Serilog/Events/ScalarValue.cs | 126 + .../Vendors/Serilog/Events/SequenceValue.cs | 74 + .../Vendors/Serilog/Events/StructureValue.cs | 102 + .../Vendors/Serilog/Filters/Matching.cs | 109 + .../Formatting/Display/LevelOutputFormat.cs | 101 + .../Display/MessageTemplateTextFormatter.cs | 133 + .../Display/Obsolete/LiteralStringValue.cs | 54 + .../Display/Obsolete/LogEventLevelValue.cs | 44 + .../Obsolete/LogEventPropertiesValue.cs | 45 + .../Obsolete/LogEventPropertyMessageValue.cs | 43 + .../Formatting/Display/OutputProperties.cs | 104 + .../Display/PropertiesOutputFormat.cs | 96 + .../Serilog/Formatting/ITextFormatter.cs | 36 + .../Serilog/Formatting/Json/JsonFormatter.cs | 454 + .../Formatting/Json/JsonValueFormatter.cs | 368 + .../Serilog/Formatting/Raw/RawFormatter.cs | 52 + src/Datadog.Trace/Vendors/Serilog/ILogger.cs | 948 + src/Datadog.Trace/Vendors/Serilog/Log.cs | 1209 + .../Vendors/Serilog/LoggerConfiguration.cs | 208 + .../Vendors/Serilog/LoggerExtensions.cs | 42 + .../Vendors/Serilog/Parsing/Alignment.cs | 47 + .../Serilog/Parsing/AlignmentDirection.cs | 35 + .../Vendors/Serilog/Parsing/Destructuring.cs | 43 + .../Serilog/Parsing/MessageTemplateParser.cs | 309 + .../Serilog/Parsing/MessageTemplateToken.cs | 60 + .../Vendors/Serilog/Parsing/PropertyToken.cs | 176 + .../Vendors/Serilog/Parsing/TextToken.cs | 96 + .../ByteArrayScalarConversionPolicy.cs | 55 + .../Policies/DelegateDestructuringPolicy.cs | 40 + .../Policies/EnumScalarConversionPolicy.cs | 39 + .../Policies/ProjectedDestructuringPolicy.cs | 53 + ...eflectionTypesScalarDestructuringPolicy.cs | 42 + .../Policies/SimpleScalarConversionPolicy.cs | 47 + .../Vendors/Serilog/Rendering/Casing.cs | 41 + .../Rendering/MessageTemplateRenderer.cs | 113 + .../Vendors/Serilog/Rendering/Padding.cs | 58 + .../Vendors/Serilog/Serilog.csproj.txt | 63 + .../CallableConfigurationMethodFinder.cs | 69 + .../KeyValuePairs/KeyValuePairSettings.cs | 287 + .../KeyValuePairs/SettingValueConversions.cs | 144 + .../SurrogateConfigurationMethods.cs | 115 + .../Vendors/StatsdClient/ICommandType.cs | 10 + .../Vendors/StatsdClient/IRandomGenerator.cs | 12 + .../Vendors/StatsdClient/IStatsd.cs | 31 + .../Vendors/StatsdClient/IStatsdUDP.cs | 11 + .../Vendors/StatsdClient/IStopWatchFactory.cs | 11 + .../Vendors/StatsdClient/IStopwatch.cs | 13 + .../Vendors/StatsdClient/RandomGenerator.cs | 22 + .../Vendors/StatsdClient/Statsd.cs | 363 + .../StatsdClient/StatsdClient.csproj.txt | 19 + .../Vendors/StatsdClient/StatsdConfig.cs | 29 + .../Vendors/StatsdClient/StatsdUDP.cs | 146 + .../Vendors/StatsdClient/StopWatchFactory.cs | 14 + .../Vendors/StatsdClient/Stopwatch.cs | 26 + .../Vendors/StatsdClient/ThreadSafeRandom.cs | 38 + src/Directory.Build.props | 34 + src/GlobalSuppressions.cs | 6 + stylecop.json | 16 + ...dog.Trace.ClrProfiler.Managed.Tests.csproj | 15 + .../IntegrationSignatureTests.cs | 98 + .../IntegrationVersionRangeTests.cs | 116 + .../MemberAccessorTests.cs | 87 + .../ObjectExtensionTests.cs | 79 + .../Reflection/AbstractAlphabetClass.cs | 6 + .../Reflection/ClassA.cs | 6 + .../Reflection/ClassB.cs | 6 + .../Reflection/ClassC.cs | 6 + .../Reflection/ClosedGenericClass.cs | 6 + .../Reflection/MethodBuilderTests.cs | 262 + .../Reflection/MethodCallMetadata.cs | 11 + .../Reflection/MethodReference.cs | 69 + .../Reflection/ModuleLookupTests.cs | 70 + .../Reflection/NestedOpenGenericClass.cs | 6 + .../Reflection/ObscenelyAnnoyingClass.cs | 86 + .../ObscenelyAnnoyingGenericClass.cs | 32 + .../Reflection/OpenGenericClass.cs | 6 + .../ReflectionHttpHeadersCollectionTests.cs | 187 + .../ScopeFactoryTests.cs | 125 + .../TypeNameTests.cs | 78 + ...dog.Trace.ClrProfiler.Native.Tests.vcxproj | 181 + .../Directory.Build.props | 2 + .../clr_helper_test.cpp | 443 + .../clr_helper_type_check_test.cpp | 123 + .../integration_loader_test.cpp | 225 + .../integration_test.cpp | 46 + .../metadata_builder_test.cpp | 157 + .../packages.config | 5 + .../pch.cpp | 6 + .../pch.h | 18 + .../test_helpers.h | 77 + .../version_struct_test.cpp | 50 + .../ContainerTaggingTests.cs | 57 + .../Datadog.Trace.IntegrationTests.csproj | 15 + .../SendTracesToAgent.cs | 118 + ....Trace.OpenTracing.IntegrationTests.csproj | 16 + .../OpenTracingSendTracesToAgent.cs | 97 + .../Datadog.Trace.OpenTracing.Tests.csproj | 16 + .../HttpHeaderCodecTests.cs | 69 + .../HttpHeadersCarrierTests.cs | 62 + .../MockTextMap.cs | 32 + .../OpenTracingSpanBuilderTests.cs | 230 + .../OpenTracingSpanTests.cs | 169 + .../OpenTracingTracerTests.cs | 372 + .../AlphabeticalOrderer.cs | 19 + .../Datadog.Trace.TestHelpers.csproj | 21 + .../EnvironmentHelper.cs | 416 + test/Datadog.Trace.TestHelpers/EventArgs.cs | 14 + .../HeadersCollectionTestHelpers.cs | 25 + .../HttpMessageHandlers/RecordHttpHandler.cs | 88 + .../HttpMessageHandlers/SetResponseHandler.cs | 24 + .../MockTracerAgent.cs | 262 + .../MsgPackHelpers.cs | 108 + .../ProfilerHelper.cs | 56 + test/Datadog.Trace.TestHelpers/TestRunners.cs | 18 + test/Datadog.Trace.TestHelpers/TestSpan.cs | 50 + .../AgentWriterBufferTests.cs | 52 + test/Datadog.Trace.Tests/AgentWriterTests.cs | 52 + test/Datadog.Trace.Tests/ApiTests.cs | 78 + .../ApiWebRequestFactoryTests.cs | 57 + .../Configuration/ConfigurationSourceTests.cs | 275 + .../Configuration/IntegrationSettingsTests.cs | 55 + .../CorrelationIdentifierTests.cs | 102 + .../Datadog.Trace.Tests.csproj | 26 + .../DistributedTraceTests.cs | 41 + test/Datadog.Trace.Tests/DogStatsDTests.cs | 157 + .../ExtensionMethods/SpanExtensionsTests.cs | 97 + .../ExtensionMethods/StringExtensionsTests.cs | 24 + .../HeadersCollectionTests.cs | 187 + .../Logging/Log4NetLogProviderTests.cs | 191 + .../Logging/LoggingProviderTestHelpers.cs | 117 + .../Logging/NLogLogProviderTests.cs | 145 + .../Logging/SerilogLogProviderTests.cs | 137 + .../AzureAppServicesMetadataTests.cs | 135 + .../PlatformHelpers/ContainerMetadataTests.cs | 115 + .../Sampling/CustomSamplingRuleTests.cs | 124 + .../Sampling/RateLimiterTests.cs | 233 + .../Sampling/RuleBasedSamplerTests.cs | 141 + .../SpanStatisticalTests.cs | 174 + test/Datadog.Trace.Tests/SpanTests.cs | 139 + test/Datadog.Trace.Tests/TimeUtilsTests.cs | 25 + test/Datadog.Trace.Tests/TraceContextTests.cs | 33 + .../TracerSettingsTests.cs | 85 + test/Datadog.Trace.Tests/TracerTests.cs | 480 + .../Util/DomainMetadataTests.cs | 42 + .../Util/StopwatchTests.cs | 30 + test/Directory.Build.props | 21 + test/GlobalSuppressions.cs | 10 + tools/Datadog.Core.Tools/ConcurrencyHelper.cs | 152 + .../Datadog.Core.Tools.csproj | 13 + tools/Datadog.Core.Tools/DependencyHelpers.cs | 34 + tools/Datadog.Core.Tools/EnvironmentTools.cs | 127 + .../Extensions/AssemblyExtensions.cs | 43 + tools/Datadog.Core.Tools/TcpPortProvider.cs | 29 + tools/Datadog.Core.Tools/TracerVersion.cs | 28 + tools/Directory.Build.props | 8 + tools/GlobalSuppressions.cs | 10 + .../GenerateIntegrationDefinitions.cs | 170 + tools/PrepareRelease/PrepareRelease.csproj | 13 + tools/PrepareRelease/Program.cs | 64 + .../Properties/launchSettings.json | 8 + tools/PrepareRelease/SetAllVersions.cs | 217 + tools/PrepareRelease/SyncMsiContent.cs | 110 + tools/PrepareRelease/publish-all.bat | 12 + tools/UpdateVendors/Program.cs | 220 + tools/UpdateVendors/UpdateVendors.csproj | 8 + 959 files changed, 300384 insertions(+) create mode 100644 .clang-format create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/pull_request_template.md create mode 100644 .gitignore create mode 100644 Datadog.Trace.Native.sln create mode 100644 Datadog.Trace.sln create mode 100644 Datadog.Trace.sln.DotSettings create mode 100644 Datadog.Trace.snk create mode 100644 Directory.Build.props create mode 100644 GlobalSuppressions.cs create mode 100644 LICENSE-3rdparty.csv create mode 100644 NOTICE create mode 100644 datadog-logo-256x256.png create mode 100644 datadog-logo-64x64.png create mode 100644 devenv.bat create mode 100755 docker/Datadog.Trace.ClrProfiler.Native.sh create mode 100644 docker/native.alpine.dockerfile create mode 100644 docker/native.dockerfile create mode 100644 docs/CHANGELOG.md create mode 100644 docs/CODE_OF_CONDUCT.md create mode 100644 docs/CONTRIBUTING.md create mode 100644 docs/README.md create mode 100644 git-clean.cmd create mode 100644 integrations.json create mode 100644 lib/coreclr/src/inc/CMakeLists.txt create mode 100644 lib/coreclr/src/inc/CrstTypeTool.cs create mode 100644 lib/coreclr/src/inc/CrstTypes.def create mode 100644 lib/coreclr/src/inc/MSCOREE.IDL create mode 100644 lib/coreclr/src/inc/OpCodeGen.pl create mode 100644 lib/coreclr/src/inc/allocacheck.h create mode 100644 lib/coreclr/src/inc/apithreadstress.cpp create mode 100644 lib/coreclr/src/inc/apithreadstress.h create mode 100644 lib/coreclr/src/inc/appxutil.h create mode 100644 lib/coreclr/src/inc/arrayholder.h create mode 100644 lib/coreclr/src/inc/arraylist.h create mode 100644 lib/coreclr/src/inc/bbsweep.h create mode 100644 lib/coreclr/src/inc/bitmask.h create mode 100644 lib/coreclr/src/inc/bitmask.inl create mode 100644 lib/coreclr/src/inc/bitposition.h create mode 100644 lib/coreclr/src/inc/bitvector.h create mode 100644 lib/coreclr/src/inc/blobfetcher.h create mode 100644 lib/coreclr/src/inc/cahlpr.h create mode 100644 lib/coreclr/src/inc/caparser.h create mode 100644 lib/coreclr/src/inc/ceefilegenwriter.h create mode 100644 lib/coreclr/src/inc/ceegen.h create mode 100644 lib/coreclr/src/inc/ceegentokenmapper.h create mode 100644 lib/coreclr/src/inc/ceesectionstring.h create mode 100644 lib/coreclr/src/inc/cfi.h create mode 100644 lib/coreclr/src/inc/check.h create mode 100644 lib/coreclr/src/inc/check.inl create mode 100644 lib/coreclr/src/inc/circularlog.h create mode 100644 lib/coreclr/src/inc/clr/fs.h create mode 100644 lib/coreclr/src/inc/clr/fs/dir.h create mode 100644 lib/coreclr/src/inc/clr/fs/file.h create mode 100644 lib/coreclr/src/inc/clr/fs/path.h create mode 100644 lib/coreclr/src/inc/clr/stack.h create mode 100644 lib/coreclr/src/inc/clr/str.h create mode 100644 lib/coreclr/src/inc/clr/win32.h create mode 100644 lib/coreclr/src/inc/clr_std/algorithm create mode 100644 lib/coreclr/src/inc/clr_std/string create mode 100644 lib/coreclr/src/inc/clr_std/type_traits create mode 100644 lib/coreclr/src/inc/clr_std/utility create mode 100644 lib/coreclr/src/inc/clr_std/vector create mode 100644 lib/coreclr/src/inc/clrconfig.h create mode 100644 lib/coreclr/src/inc/clrconfigvalues.h create mode 100644 lib/coreclr/src/inc/clrdata.idl create mode 100644 lib/coreclr/src/inc/clrhost.h create mode 100644 lib/coreclr/src/inc/clrinternal.idl create mode 100644 lib/coreclr/src/inc/clrnt.h create mode 100644 lib/coreclr/src/inc/clrprivappxhosting.idl create mode 100644 lib/coreclr/src/inc/clrprivbinderutil.h create mode 100644 lib/coreclr/src/inc/clrprivbinding.idl create mode 100644 lib/coreclr/src/inc/clrprivhosting.idl create mode 100644 lib/coreclr/src/inc/clrprivruntimebinders.idl create mode 100644 lib/coreclr/src/inc/clrtypes.h create mode 100644 lib/coreclr/src/inc/complex.h create mode 100644 lib/coreclr/src/inc/configuration.h create mode 100644 lib/coreclr/src/inc/contract.h create mode 100644 lib/coreclr/src/inc/contract.inl create mode 100644 lib/coreclr/src/inc/contxt.h create mode 100644 lib/coreclr/src/inc/cor.h create mode 100644 lib/coreclr/src/inc/corbbtprof.h create mode 100644 lib/coreclr/src/inc/corcompile.h create mode 100644 lib/coreclr/src/inc/cordbpriv.h create mode 100644 lib/coreclr/src/inc/cordebug.idl create mode 100644 lib/coreclr/src/inc/cordebuginfo.h create mode 100644 lib/coreclr/src/inc/coredistools.h create mode 100644 lib/coreclr/src/inc/coregen.h create mode 100644 lib/coreclr/src/inc/corerror.xml create mode 100644 lib/coreclr/src/inc/corexcep.h create mode 100644 lib/coreclr/src/inc/corhdr.h create mode 100644 lib/coreclr/src/inc/corhlpr.cpp create mode 100644 lib/coreclr/src/inc/corhlpr.h create mode 100644 lib/coreclr/src/inc/corhlprpriv.cpp create mode 100644 lib/coreclr/src/inc/corhlprpriv.h create mode 100644 lib/coreclr/src/inc/corhost.h create mode 100644 lib/coreclr/src/inc/corimage.h create mode 100644 lib/coreclr/src/inc/corinfo.h create mode 100644 lib/coreclr/src/inc/corjit.h create mode 100644 lib/coreclr/src/inc/corjitflags.h create mode 100644 lib/coreclr/src/inc/corjithost.h create mode 100644 lib/coreclr/src/inc/corpriv.h create mode 100644 lib/coreclr/src/inc/corprof.idl create mode 100644 lib/coreclr/src/inc/corpub.idl create mode 100644 lib/coreclr/src/inc/corsym.idl create mode 100644 lib/coreclr/src/inc/cortypeinfo.h create mode 100644 lib/coreclr/src/inc/crosscomp.h create mode 100644 lib/coreclr/src/inc/crsttypes.h create mode 100644 lib/coreclr/src/inc/crtwrap.h create mode 100644 lib/coreclr/src/inc/cvconst.h create mode 100644 lib/coreclr/src/inc/cvinfo.h create mode 100644 lib/coreclr/src/inc/cycletimer.h create mode 100644 lib/coreclr/src/inc/daccess.h create mode 100644 lib/coreclr/src/inc/dacprivate.h create mode 100644 lib/coreclr/src/inc/dacvars.h create mode 100644 lib/coreclr/src/inc/dbgconfigstrings.h create mode 100644 lib/coreclr/src/inc/dbgenginemetrics.h create mode 100644 lib/coreclr/src/inc/dbgmeta.h create mode 100644 lib/coreclr/src/inc/dbgportable.h create mode 100644 lib/coreclr/src/inc/debugmacros.h create mode 100644 lib/coreclr/src/inc/debugmacrosext.h create mode 100644 lib/coreclr/src/inc/debugreturn.h create mode 100644 lib/coreclr/src/inc/defaultallocator.h create mode 100644 lib/coreclr/src/inc/delayloadhelpers.h create mode 100644 lib/coreclr/src/inc/dlwrap.h create mode 100644 lib/coreclr/src/inc/eetwain.h create mode 100644 lib/coreclr/src/inc/eexcp.h create mode 100644 lib/coreclr/src/inc/entrypoints.h create mode 100644 lib/coreclr/src/inc/eventtrace.h create mode 100644 lib/coreclr/src/inc/eventtracebase.h create mode 100644 lib/coreclr/src/inc/ex.h create mode 100644 lib/coreclr/src/inc/factory.h create mode 100644 lib/coreclr/src/inc/factory.inl create mode 100644 lib/coreclr/src/inc/fixuppointer.h create mode 100644 lib/coreclr/src/inc/formattype.cpp create mode 100644 lib/coreclr/src/inc/formattype.h create mode 100644 lib/coreclr/src/inc/fstream.h create mode 100644 lib/coreclr/src/inc/fstring.h create mode 100644 lib/coreclr/src/inc/fusion.idl create mode 100644 lib/coreclr/src/inc/gcdecoder.cpp create mode 100644 lib/coreclr/src/inc/gcdump.h create mode 100644 lib/coreclr/src/inc/gcinfo.h create mode 100644 lib/coreclr/src/inc/gcinfoarraylist.h create mode 100644 lib/coreclr/src/inc/gcinfodecoder.h create mode 100644 lib/coreclr/src/inc/gcinfodumper.h create mode 100644 lib/coreclr/src/inc/gcinfoencoder.h create mode 100644 lib/coreclr/src/inc/gcinfotypes.h create mode 100644 lib/coreclr/src/inc/gcrefmap.h create mode 100644 lib/coreclr/src/inc/genheaders.cs create mode 100644 lib/coreclr/src/inc/genrops.pl create mode 100644 lib/coreclr/src/inc/getproductversionnumber.h create mode 100644 lib/coreclr/src/inc/guidfromname.h create mode 100644 lib/coreclr/src/inc/holder.h create mode 100644 lib/coreclr/src/inc/holderinst.h create mode 100644 lib/coreclr/src/inc/iallocator.h create mode 100644 lib/coreclr/src/inc/iceefilegen.h create mode 100644 lib/coreclr/src/inc/il_kywd.h create mode 100644 lib/coreclr/src/inc/ildbsymlib.h create mode 100644 lib/coreclr/src/inc/ilformatter.h create mode 100644 lib/coreclr/src/inc/internalunknownimpl.h create mode 100644 lib/coreclr/src/inc/intrinsic.h create mode 100644 lib/coreclr/src/inc/iterator.h create mode 100644 lib/coreclr/src/inc/jithelpers.h create mode 100644 lib/coreclr/src/inc/jitperf.h create mode 100644 lib/coreclr/src/inc/lazycow.h create mode 100644 lib/coreclr/src/inc/livedatatarget.h create mode 100644 lib/coreclr/src/inc/llvm/Dwarf.def create mode 100644 lib/coreclr/src/inc/llvm/Dwarf.h create mode 100644 lib/coreclr/src/inc/llvm/ELF.h create mode 100644 lib/coreclr/src/inc/loaderheap.h create mode 100644 lib/coreclr/src/inc/log.h create mode 100644 lib/coreclr/src/inc/loglf.h create mode 100644 lib/coreclr/src/inc/longfilepathwrappers.h create mode 100644 lib/coreclr/src/inc/md5.h create mode 100644 lib/coreclr/src/inc/mdcommon.h create mode 100644 lib/coreclr/src/inc/memorypool.h create mode 100644 lib/coreclr/src/inc/memoryrange.h create mode 100644 lib/coreclr/src/inc/metadata.h create mode 100644 lib/coreclr/src/inc/metadataexports.h create mode 100644 lib/coreclr/src/inc/metadatatracker.h create mode 100644 lib/coreclr/src/inc/metahost.idl create mode 100644 lib/coreclr/src/inc/metamodelpub.h create mode 100644 lib/coreclr/src/inc/mpl/type_list create mode 100644 lib/coreclr/src/inc/mscorsvc.idl create mode 100644 lib/coreclr/src/inc/msodw.h create mode 100644 lib/coreclr/src/inc/msodwwrap.h create mode 100644 lib/coreclr/src/inc/nativevaraccessors.h create mode 100644 lib/coreclr/src/inc/new.hpp create mode 100644 lib/coreclr/src/inc/ngen.h create mode 100644 lib/coreclr/src/inc/nibblemapmacros.h create mode 100644 lib/coreclr/src/inc/nibblestream.h create mode 100644 lib/coreclr/src/inc/nsutilpriv.h create mode 100644 lib/coreclr/src/inc/opcode.def create mode 100644 lib/coreclr/src/inc/openum.h create mode 100644 lib/coreclr/src/inc/opinfo.h create mode 100644 lib/coreclr/src/inc/optdefault.h create mode 100644 lib/coreclr/src/inc/optsmallperfcritical.h create mode 100644 lib/coreclr/src/inc/ostype.h create mode 100644 lib/coreclr/src/inc/outstring.h create mode 100644 lib/coreclr/src/inc/palclr.h create mode 100644 lib/coreclr/src/inc/palclr_win.h create mode 100644 lib/coreclr/src/inc/pedecoder.h create mode 100644 lib/coreclr/src/inc/pedecoder.inl create mode 100644 lib/coreclr/src/inc/peinformation.h create mode 100644 lib/coreclr/src/inc/perflog.h create mode 100644 lib/coreclr/src/inc/pesectionman.h create mode 100644 lib/coreclr/src/inc/posterror.h create mode 100644 lib/coreclr/src/inc/predeftlsslot.h create mode 100644 lib/coreclr/src/inc/prettyprintsig.h create mode 100644 lib/coreclr/src/inc/profilepriv.h create mode 100644 lib/coreclr/src/inc/profilepriv.inl create mode 100644 lib/coreclr/src/inc/random.h create mode 100644 lib/coreclr/src/inc/rangetree.h create mode 100644 lib/coreclr/src/inc/readytorun.h create mode 100644 lib/coreclr/src/inc/readytorunhelpers.h create mode 100644 lib/coreclr/src/inc/regdisp.h create mode 100644 lib/coreclr/src/inc/regex_base.h create mode 100644 lib/coreclr/src/inc/regex_util.h create mode 100644 lib/coreclr/src/inc/registrywrapper.h create mode 100644 lib/coreclr/src/inc/releaseholder.h create mode 100644 lib/coreclr/src/inc/safemath.h create mode 100644 lib/coreclr/src/inc/safewrap.h create mode 100644 lib/coreclr/src/inc/sarray.h create mode 100644 lib/coreclr/src/inc/sarray.inl create mode 100644 lib/coreclr/src/inc/sbuffer.h create mode 100644 lib/coreclr/src/inc/sbuffer.inl create mode 100644 lib/coreclr/src/inc/securityutil.h create mode 100644 lib/coreclr/src/inc/securitywrapper.h create mode 100644 lib/coreclr/src/inc/shash.h create mode 100644 lib/coreclr/src/inc/shash.inl create mode 100644 lib/coreclr/src/inc/shim/locationinfo.h create mode 100644 lib/coreclr/src/inc/shim/runtimeselector.h create mode 100644 lib/coreclr/src/inc/shim/runtimeselector.inl create mode 100644 lib/coreclr/src/inc/shim/shimselector.h create mode 100644 lib/coreclr/src/inc/shim/shimselector.inl create mode 100644 lib/coreclr/src/inc/shim/versionandlocationinfo.h create mode 100644 lib/coreclr/src/inc/shim/versionandlocationinfo.inl create mode 100644 lib/coreclr/src/inc/shim/versioninfo.h create mode 100644 lib/coreclr/src/inc/shim/versioninfo.inl create mode 100644 lib/coreclr/src/inc/shimload.h create mode 100644 lib/coreclr/src/inc/sigbuilder.h create mode 100644 lib/coreclr/src/inc/sigparser.h create mode 100644 lib/coreclr/src/inc/simplerhash.h create mode 100644 lib/coreclr/src/inc/simplerhash.inl create mode 100644 lib/coreclr/src/inc/slist.h create mode 100644 lib/coreclr/src/inc/sospriv.idl create mode 100644 lib/coreclr/src/inc/sstring.h create mode 100644 lib/coreclr/src/inc/sstring.inl create mode 100644 lib/coreclr/src/inc/stack.h create mode 100644 lib/coreclr/src/inc/stackframe.h create mode 100644 lib/coreclr/src/inc/stacktrace.h create mode 100644 lib/coreclr/src/inc/static_assert.h create mode 100644 lib/coreclr/src/inc/staticcontract.h create mode 100644 lib/coreclr/src/inc/stdmacros.h create mode 100644 lib/coreclr/src/inc/stgpool.h create mode 100644 lib/coreclr/src/inc/stgpooli.h create mode 100644 lib/coreclr/src/inc/stresslog.h create mode 100644 lib/coreclr/src/inc/stringarraylist.h create mode 100644 lib/coreclr/src/inc/stringarraylist.inl create mode 100644 lib/coreclr/src/inc/strongname.h create mode 100644 lib/coreclr/src/inc/switches.h create mode 100644 lib/coreclr/src/inc/tls.h create mode 100644 lib/coreclr/src/inc/utilcode.h create mode 100644 lib/coreclr/src/inc/utsem.h create mode 100644 lib/coreclr/src/inc/vererror.h create mode 100644 lib/coreclr/src/inc/volatile.h create mode 100644 lib/coreclr/src/inc/vptr_list.h create mode 100644 lib/coreclr/src/inc/warningcontrol.h create mode 100644 lib/coreclr/src/inc/win64unwind.h create mode 100644 lib/coreclr/src/inc/winrt/ntassert.h create mode 100644 lib/coreclr/src/inc/winrt/paraminstanceapi.h create mode 100644 lib/coreclr/src/inc/winrt/windowsruntime.h create mode 100644 lib/coreclr/src/inc/winrt/windowsstring.h create mode 100644 lib/coreclr/src/inc/winrtprojectedtypes.h create mode 100644 lib/coreclr/src/inc/winwrap.h create mode 100644 lib/coreclr/src/inc/xclrdata.idl create mode 100644 lib/coreclr/src/inc/xcordebug.idl create mode 100644 lib/coreclr/src/inc/zapper.h create mode 100644 lib/coreclr/src/pal/inc/mbusafecrt.h create mode 100644 lib/coreclr/src/pal/inc/pal.h create mode 100644 lib/coreclr/src/pal/inc/pal_assert.h create mode 100644 lib/coreclr/src/pal/inc/pal_char16.h create mode 100644 lib/coreclr/src/pal/inc/pal_endian.h create mode 100644 lib/coreclr/src/pal/inc/pal_error.h create mode 100644 lib/coreclr/src/pal/inc/pal_mstypes.h create mode 100644 lib/coreclr/src/pal/inc/pal_safecrt.h create mode 100644 lib/coreclr/src/pal/inc/pal_unwind.h create mode 100644 lib/coreclr/src/pal/inc/palprivate.h create mode 100644 lib/coreclr/src/pal/inc/rt/accctrl.h create mode 100644 lib/coreclr/src/pal/inc/rt/aclapi.h create mode 100644 lib/coreclr/src/pal/inc/rt/atl.h create mode 100644 lib/coreclr/src/pal/inc/rt/atlcom.h create mode 100644 lib/coreclr/src/pal/inc/rt/atlwin.h create mode 100644 lib/coreclr/src/pal/inc/rt/commctrl.h create mode 100644 lib/coreclr/src/pal/inc/rt/commdlg.h create mode 100644 lib/coreclr/src/pal/inc/rt/conio.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/cstdlib create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/ctype.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/fcntl.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/float.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/io.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/limits.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/malloc.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/math.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/memory.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/stdarg.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/stddef.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/stdint.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/stdio.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/stdlib.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/string.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/time.h create mode 100644 lib/coreclr/src/pal/inc/rt/cpp/wchar.h create mode 100644 lib/coreclr/src/pal/inc/rt/crtdbg.h create mode 100644 lib/coreclr/src/pal/inc/rt/dbghelp.h create mode 100644 lib/coreclr/src/pal/inc/rt/eh.h create mode 100644 lib/coreclr/src/pal/inc/rt/errorrep.h create mode 100644 lib/coreclr/src/pal/inc/rt/guiddef.h create mode 100644 lib/coreclr/src/pal/inc/rt/hstring.h create mode 100644 lib/coreclr/src/pal/inc/rt/htmlhelp.h create mode 100644 lib/coreclr/src/pal/inc/rt/imagehlp.h create mode 100644 lib/coreclr/src/pal/inc/rt/intrin.h create mode 100644 lib/coreclr/src/pal/inc/rt/intsafe.h create mode 100644 lib/coreclr/src/pal/inc/rt/mbstring.h create mode 100644 lib/coreclr/src/pal/inc/rt/new.h create mode 100644 lib/coreclr/src/pal/inc/rt/no_sal2.h create mode 100644 lib/coreclr/src/pal/inc/rt/ntimage.h create mode 100644 lib/coreclr/src/pal/inc/rt/oaidl.h create mode 100644 lib/coreclr/src/pal/inc/rt/objbase.h create mode 100644 lib/coreclr/src/pal/inc/rt/objidl.h create mode 100644 lib/coreclr/src/pal/inc/rt/ocidl.h create mode 100644 lib/coreclr/src/pal/inc/rt/ole2.h create mode 100644 lib/coreclr/src/pal/inc/rt/oleauto.h create mode 100644 lib/coreclr/src/pal/inc/rt/olectl.h create mode 100644 lib/coreclr/src/pal/inc/rt/oleidl.h create mode 100644 lib/coreclr/src/pal/inc/rt/palrt.h create mode 100644 lib/coreclr/src/pal/inc/rt/poppack.h create mode 100644 lib/coreclr/src/pal/inc/rt/process.h create mode 100644 lib/coreclr/src/pal/inc/rt/psapi.h create mode 100644 lib/coreclr/src/pal/inc/rt/pshpack1.h create mode 100644 lib/coreclr/src/pal/inc/rt/pshpack2.h create mode 100644 lib/coreclr/src/pal/inc/rt/pshpack4.h create mode 100644 lib/coreclr/src/pal/inc/rt/pshpack8.h create mode 100644 lib/coreclr/src/pal/inc/rt/pshpck16.h create mode 100644 lib/coreclr/src/pal/inc/rt/richedit.h create mode 100644 lib/coreclr/src/pal/inc/rt/rpc.h create mode 100644 lib/coreclr/src/pal/inc/rt/rpcndr.h create mode 100644 lib/coreclr/src/pal/inc/rt/safecrt.h create mode 100644 lib/coreclr/src/pal/inc/rt/sal.h create mode 100644 lib/coreclr/src/pal/inc/rt/servprov.h create mode 100644 lib/coreclr/src/pal/inc/rt/share.h create mode 100644 lib/coreclr/src/pal/inc/rt/shellapi.h create mode 100644 lib/coreclr/src/pal/inc/rt/shlobj.h create mode 100644 lib/coreclr/src/pal/inc/rt/shlwapi.h create mode 100644 lib/coreclr/src/pal/inc/rt/specstrings.h create mode 100644 lib/coreclr/src/pal/inc/rt/specstrings_adt.h create mode 100644 lib/coreclr/src/pal/inc/rt/specstrings_strict.h create mode 100644 lib/coreclr/src/pal/inc/rt/specstrings_undef.h create mode 100644 lib/coreclr/src/pal/inc/rt/symcrypt.h create mode 100644 lib/coreclr/src/pal/inc/rt/tchar.h create mode 100644 lib/coreclr/src/pal/inc/rt/tlhelp32.h create mode 100644 lib/coreclr/src/pal/inc/rt/unknwn.h create mode 100644 lib/coreclr/src/pal/inc/rt/urlmon.h create mode 100644 lib/coreclr/src/pal/inc/rt/verrsrc.h create mode 100644 lib/coreclr/src/pal/inc/rt/vsassert.h create mode 100644 lib/coreclr/src/pal/inc/rt/winapifamily.h create mode 100644 lib/coreclr/src/pal/inc/rt/winbase.h create mode 100644 lib/coreclr/src/pal/inc/rt/wincrypt.h create mode 100644 lib/coreclr/src/pal/inc/rt/windef.h create mode 100644 lib/coreclr/src/pal/inc/rt/windows.h create mode 100644 lib/coreclr/src/pal/inc/rt/winerror.h create mode 100644 lib/coreclr/src/pal/inc/rt/wininet.h create mode 100644 lib/coreclr/src/pal/inc/rt/winnls.h create mode 100644 lib/coreclr/src/pal/inc/rt/winnt.h create mode 100644 lib/coreclr/src/pal/inc/rt/winresrc.h create mode 100644 lib/coreclr/src/pal/inc/rt/winternl.h create mode 100644 lib/coreclr/src/pal/inc/rt/winuser.h create mode 100644 lib/coreclr/src/pal/inc/rt/winver.h create mode 100644 lib/coreclr/src/pal/inc/rt/wtsapi32.h create mode 100644 lib/coreclr/src/pal/inc/rt/x86intrin.h create mode 100644 lib/coreclr/src/pal/inc/strsafe.h create mode 100644 lib/coreclr/src/pal/inc/unixasmmacros.inc create mode 100644 lib/coreclr/src/pal/inc/unixasmmacrosamd64.inc create mode 100644 lib/coreclr/src/pal/inc/unixasmmacrosarm.inc create mode 100644 lib/coreclr/src/pal/inc/unixasmmacrosarm64.inc create mode 100644 lib/coreclr/src/pal/inc/unixasmmacrosx86.inc create mode 100644 lib/coreclr/src/pal/prebuilt/inc/CMakeLists.txt create mode 100644 lib/coreclr/src/pal/prebuilt/inc/asm_version.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/buildnumber.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/clrdata.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/clrinternal.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/clrprivbinding.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/clrprivhosting.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/clrprivruntimebinders.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/cordebug.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/corerror.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/corprof.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/corpub.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/corsym.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/fusion.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/fxver.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/fxver.rc create mode 100644 lib/coreclr/src/pal/prebuilt/inc/fxverstrings.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/metahost.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/mscoree.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/mscorsvc.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/ndpversion.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/ndpversion_generated.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/product_version.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/readme.txt create mode 100644 lib/coreclr/src/pal/prebuilt/inc/sospriv.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/version.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/xclrdata.h create mode 100644 lib/coreclr/src/pal/prebuilt/inc/xcordebug.h create mode 100644 pre-build-events-cpp.bat create mode 100644 sample-libs/Directory.Build.props create mode 100644 sample-libs/Samples.ExampleLibrary/Class1.cs create mode 100644 sample-libs/Samples.ExampleLibrary/Directory.Build.props create mode 100644 sample-libs/Samples.ExampleLibrary/FakeClient/Biscuit.cs create mode 100644 sample-libs/Samples.ExampleLibrary/FakeClient/DogClient.cs create mode 100644 sample-libs/Samples.ExampleLibrary/FakeClient/DogTrick.cs create mode 100644 sample-libs/Samples.ExampleLibrary/GenericTests/ComprehensiveCaller.cs create mode 100644 sample-libs/Samples.ExampleLibrary/GenericTests/GenericTarget.cs create mode 100644 sample-libs/Samples.ExampleLibrary/GenericTests/PointStruct.cs create mode 100644 sample-libs/Samples.ExampleLibrary/GenericTests/StructContainer.cs create mode 100644 sample-libs/Samples.ExampleLibrary/Samples.ExampleLibrary.csproj create mode 100644 sample-libs/Samples.ExampleLibraryTracer/Class1.cs create mode 100644 sample-libs/Samples.ExampleLibraryTracer/Directory.Build.props create mode 100644 sample-libs/Samples.ExampleLibraryTracer/Samples.ExampleLibraryTracer.csproj create mode 100644 sample-libs/Samples.Shared/Samples.Shared.csproj create mode 100644 sample-libs/Samples.Shared/Web/DistributedTracingModel.cs create mode 100644 sample-libs/Samples.Shared/Web/HttpClientExtensions.cs create mode 100644 src/Datadog.Trace.AspNet/AspNetScopeManager.cs create mode 100644 src/Datadog.Trace.AspNet/AssemblyInfo.cs create mode 100644 src/Datadog.Trace.AspNet/Datadog.Trace.AspNet.csproj create mode 100644 src/Datadog.Trace.AspNet/HttpApplicationStartup.cs create mode 100644 src/Datadog.Trace.AspNet/TracingHttpModule.cs create mode 100644 src/Datadog.Trace.Ci.Shared/BuildTags.cs create mode 100644 src/Datadog.Trace.Ci.Shared/CIEnvironmentValues.cs create mode 100644 src/Datadog.Trace.Ci.Shared/CommonTags.cs create mode 100644 src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.projitems create mode 100644 src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.shproj create mode 100644 src/Datadog.Trace.Ci.Shared/TestTags.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/AssemblyInfo.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/ClrNames.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/IntegrationVersionRange.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/InterceptMethodAttribute.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/MethodReplacementActionType.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Core/TypeExtensions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/FileSink.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/ManagedProfilerAssemblyLoadContext.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetCore.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetFramework.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed.Loader/StartupLogger.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/AssemblyInfo.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj.DotSettings create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/DynamicMethodBuilder.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/DelegateMetadata.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/DynamicMethodBuilder.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/MemberResult.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/MethodBuilder.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/ModuleLookup.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/ObjectExtensions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Emit/OpCodeValues.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/GlobalSuppressions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Helpers/AsyncHelper.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Helpers/Interception.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Helpers/PointerHelpers.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Helpers/ReflectionHttpHeadersCollection.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Helpers/TaskExtensions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Instrumentation.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/AdoNetConstants.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/DbCommandIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/IDbCommandIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/NpgsqlCommandIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/SqlCommandIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetMvcIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetWebApi2Integration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet5Integration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet6Integration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNetCommon.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/GraphQLIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/HttpMessageHandlerIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/LoggerExtensions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/MongoDbIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/RedisHelper.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/ServiceStackRedisIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/ConnectionMultiplexer.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/RedisBatch.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/StackExchangeRedisHelper.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/AsyncTool.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/TestLoggerExtensions.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/XUnitIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/WcfIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/Integrations/WebRequestIntegration.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/MemberAccessor.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/MetadataNames.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/NativeMethods.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Managed/ScopeFactory.cs create mode 100644 src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt create mode 100644 src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.DLL.vcxproj create mode 100644 src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.def create mode 100644 src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.vcxproj create mode 100644 src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props create mode 100644 src/Datadog.Trace.ClrProfiler.Native/Resource.rc create mode 100644 src/Datadog.Trace.ClrProfiler.Native/class_factory.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/class_factory.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/clr_helpers.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/com_ptr.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/cor_profiler.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/cor_profiler.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/dd_profiler_constants.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/dllmain.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/dllmain.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/environment_variables.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/il_rewriter.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/il_rewriter.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/integration.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/integration.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/integration_loader.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/integration_loader.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/interop.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/logging.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/logging.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/macros.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/metadata_builder.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/metadata_builder.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/miniutf.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/miniutf.hpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/miniutfdata.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/module_metadata.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/packages.config create mode 100644 src/Datadog.Trace.ClrProfiler.Native/pal.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/resource.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/sig_helpers.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/sig_helpers.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/string.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/string.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/util.cpp create mode 100644 src/Datadog.Trace.ClrProfiler.Native/util.h create mode 100644 src/Datadog.Trace.ClrProfiler.Native/version.h create mode 100644 src/Datadog.Trace.OpenTracing/AssemblyInfo.cs create mode 100644 src/Datadog.Trace.OpenTracing/Datadog.Trace.OpenTracing.csproj create mode 100644 src/Datadog.Trace.OpenTracing/DatadogTags.cs create mode 100644 src/Datadog.Trace.OpenTracing/HttpHeadersCodec.cs create mode 100644 src/Datadog.Trace.OpenTracing/ICodec.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingHttpHeadersCarrier.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingSpan.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingSpanBuilder.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingSpanContext.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingTracer.cs create mode 100644 src/Datadog.Trace.OpenTracing/OpenTracingTracerFactory.cs create mode 100644 src/Datadog.Trace.OpenTracing/TextMapHeadersCollection.cs create mode 100644 src/Datadog.Trace/Abstractions/IScope.cs create mode 100644 src/Datadog.Trace/Abstractions/ISpan.cs create mode 100644 src/Datadog.Trace/Agent/AgentWriter.cs create mode 100644 src/Datadog.Trace/Agent/AgentWriterBuffer.cs create mode 100644 src/Datadog.Trace/Agent/Api.cs create mode 100644 src/Datadog.Trace/Agent/ApiWebRequest.cs create mode 100644 src/Datadog.Trace/Agent/ApiWebRequestFactory.cs create mode 100644 src/Datadog.Trace/Agent/ApiWebResponse.cs create mode 100644 src/Datadog.Trace/Agent/IAgentWriter.cs create mode 100644 src/Datadog.Trace/Agent/IApi.cs create mode 100644 src/Datadog.Trace/Agent/IApiRequest.cs create mode 100644 src/Datadog.Trace/Agent/IApiRequestFactory.cs create mode 100644 src/Datadog.Trace/Agent/IApiResponse.cs create mode 100644 src/Datadog.Trace/Agent/MessagePack/FormatterResolverWrapper.cs create mode 100644 src/Datadog.Trace/Agent/MessagePack/SpanFormatterResolver.cs create mode 100644 src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs create mode 100644 src/Datadog.Trace/AgentHttpHeaderNames.cs create mode 100644 src/Datadog.Trace/AssemblyInfo.cs create mode 100644 src/Datadog.Trace/AsyncLocalCompat.cs create mode 100644 src/Datadog.Trace/AsyncLocalScopeManager.cs create mode 100644 src/Datadog.Trace/Configuration/CompositeConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/ConfigurationKeys.cs create mode 100644 src/Datadog.Trace/Configuration/EnvironmentConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/GlobalSettings.cs create mode 100644 src/Datadog.Trace/Configuration/IConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/IntegrationSettings.cs create mode 100644 src/Datadog.Trace/Configuration/IntegrationSettingsCollection.cs create mode 100644 src/Datadog.Trace/Configuration/JsonConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/NameValueConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/StringConfigurationSource.cs create mode 100644 src/Datadog.Trace/Configuration/TracerSettings.cs create mode 100644 src/Datadog.Trace/CorrelationIdentifier.cs create mode 100644 src/Datadog.Trace/Datadog.Trace.csproj create mode 100644 src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticObserver.cs create mode 100644 src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticOptions.cs create mode 100644 src/Datadog.Trace/DiagnosticListeners/DiagnosticManager.cs create mode 100644 src/Datadog.Trace/DiagnosticListeners/DiagnosticObserver.cs create mode 100644 src/Datadog.Trace/DiagnosticListeners/IDiagnosticManager.cs create mode 100644 src/Datadog.Trace/DisposableObjectHandle.cs create mode 100644 src/Datadog.Trace/DogStatsd/NoOpStatsd.cs create mode 100644 src/Datadog.Trace/DogStatsd/StatsdExtensions.cs create mode 100644 src/Datadog.Trace/DogStatsd/TracerMetricNames.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/DictionaryExtensions.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/NameValueCollectionExtensions.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/SpanExtensions.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/StringExtensions.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/TimeExtensions.cs create mode 100644 src/Datadog.Trace/ExtensionMethods/WebHeadersExtensions.cs create mode 100644 src/Datadog.Trace/FrameworkDescription.NetCore.cs create mode 100644 src/Datadog.Trace/FrameworkDescription.NetFramework.cs create mode 100644 src/Datadog.Trace/FrameworkDescription.cs create mode 100644 src/Datadog.Trace/Headers/DictionaryHeadersCollection.cs create mode 100644 src/Datadog.Trace/Headers/IHeadersCollection.cs create mode 100644 src/Datadog.Trace/Headers/NameValueHeadersCollection.cs create mode 100644 src/Datadog.Trace/Headers/WebHeadersCollection.cs create mode 100644 src/Datadog.Trace/HttpHeaderNames.cs create mode 100644 src/Datadog.Trace/IDatadogTracer.cs create mode 100644 src/Datadog.Trace/IScopeManager.cs create mode 100644 src/Datadog.Trace/ISpanContext.cs create mode 100644 src/Datadog.Trace/ITraceContext.cs create mode 100644 src/Datadog.Trace/Logging/DatadogLogging.cs create mode 100644 src/Datadog.Trace/Logging/LibLogScopeEventSubscriber.cs create mode 100644 src/Datadog.Trace/Logging/LoggingExtensions.cs create mode 100644 src/Datadog.Trace/Metrics.cs create mode 100644 src/Datadog.Trace/PlatformHelpers/AzureAppservices.cs create mode 100644 src/Datadog.Trace/PlatformHelpers/ContainerMetadata.cs create mode 100644 src/Datadog.Trace/Sampling/CustomSamplingRule.cs create mode 100644 src/Datadog.Trace/Sampling/DefaultSamplingRule.cs create mode 100644 src/Datadog.Trace/Sampling/GlobalSamplingRule.cs create mode 100644 src/Datadog.Trace/Sampling/IRateLimiter.cs create mode 100644 src/Datadog.Trace/Sampling/ISampler.cs create mode 100644 src/Datadog.Trace/Sampling/ISamplingRule.cs create mode 100644 src/Datadog.Trace/Sampling/RateLimiter.cs create mode 100644 src/Datadog.Trace/Sampling/RuleBasedSampler.cs create mode 100644 src/Datadog.Trace/SamplingPriority.cs create mode 100644 src/Datadog.Trace/Scope.cs create mode 100644 src/Datadog.Trace/ScopeManagerBase.cs create mode 100644 src/Datadog.Trace/Span.cs create mode 100644 src/Datadog.Trace/SpanContext.cs create mode 100644 src/Datadog.Trace/SpanContextPropagator.cs create mode 100644 src/Datadog.Trace/SpanEventArgs.cs create mode 100644 src/Datadog.Trace/SpanKinds.cs create mode 100644 src/Datadog.Trace/SpanTypes.cs create mode 100644 src/Datadog.Trace/Tags.cs create mode 100644 src/Datadog.Trace/TimeConstants.cs create mode 100644 src/Datadog.Trace/TraceContext.cs create mode 100644 src/Datadog.Trace/Tracer.cs create mode 100644 src/Datadog.Trace/TracerConstants.cs create mode 100644 src/Datadog.Trace/TracingProcessManager.cs create mode 100644 src/Datadog.Trace/Util/DbCommandCache.cs create mode 100644 src/Datadog.Trace/Util/DomainMetadata.cs create mode 100644 src/Datadog.Trace/Util/EnvironmentHelpers.cs create mode 100644 src/Datadog.Trace/Util/PropertyFetcher.cs create mode 100644 src/Datadog.Trace/Util/SpanIdGenerator.cs create mode 100644 src/Datadog.Trace/Util/StopwatchHelpers.cs create mode 100644 src/Datadog.Trace/Util/UriHelpers.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Attributes.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/BitOperations.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/FloatBits.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionHelpers`2.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/DictionaryFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/DynamicObjectTypeFallbackFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/EnumAsStringFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.tt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/IMessagePackFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/IgnoreFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/MultiDimentionalArrayFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/NullableFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/OldSpecFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.tt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveObjectFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/StandardClassLibraryFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.tt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Formatters/ValueTupleFormatter.tt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/HashCode.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/IFormatterResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/IMessagePackSerializationCallbackReceiver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ArrayPool.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayComparer.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayStringHashTable.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ExpressionUtility.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/GuidBits.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ReflectionExtensions.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/ThreadsafeTypeKeyHashTable.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/TinyJsonReader.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Internal/UnsafeMemory.tt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Helper.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe32.Dirty.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe64.Dirty.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe32.Dirty.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe64.Dirty.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.JSON.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.NonGeneric.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePack.csproj.txt create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackBinary.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackCode.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackSecurity.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.Json.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.NonGeneric.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Nil.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/AttributeFormatterResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/BuiltinResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/CompositeResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/ContractlessReflectionObjectResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicEnumAsStringResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicGenericResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/NativeDateTimeResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/OldSpecResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/PrimitiveObjectResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/Resolvers/StandardResolver.cs create mode 100644 src/Datadog.Trace/Vendors/MessagePack/StringEncoding.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/RollingInterval.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Serilog.Sinks.File.csproj.txt create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/Clock.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/FileSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFileSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IOErrors.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/NullSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PathRoller.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.AtomicAppend.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Capturing/DepthLimiter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Capturing/GetablePropertyFinder.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Capturing/MessageTemplateProcessor.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyBinder.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyValueConverter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/ILoggerSettings.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerAuditSinkConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerDestructuringConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerEnrichmentConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerFilterConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerMinimumLevelConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSettingsConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSinkConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Context/ImmutableStack.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Context/LogContext.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Constants.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/EmptyEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/FixedPropertyEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/PropertyEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/SafeAggregateEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Filters/DelegateFilter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/IDestructuringPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/ILogEventEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/ILogEventFilter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyFactory.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyValueFactory.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/ILogEventSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/IMessageTemplateParser.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/IScalarConversionPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/LevelOverrideMap.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Logger.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/LoggingLevelSwitch.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/MessageTemplateFormatMethodAttribute.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/MessageTemplateCache.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/SilentLogger.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Sinks/AggregateSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Sinks/FilteringSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Sinks/RestrictedSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SafeAggregateSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SecondaryLoggerSink.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueRewriter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueVisitor.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Debugging/LoggingFailedException.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Debugging/SelfLog.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Enrichers/LogContextEnricher.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/DictionaryValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/LevelAlias.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/LogEvent.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/LogEventLevel.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/LogEventProperty.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/LogEventPropertyValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/MessageTemplate.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/ScalarValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/SequenceValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Events/StructureValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Filters/Matching.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/LevelOutputFormat.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/MessageTemplateTextFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LiteralStringValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventLevelValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertiesValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertyMessageValue.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/OutputProperties.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Display/PropertiesOutputFormat.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/ITextFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonValueFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Formatting/Raw/RawFormatter.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/ILogger.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Log.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/LoggerConfiguration.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/LoggerExtensions.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/Alignment.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/AlignmentDirection.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/Destructuring.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateParser.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateToken.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/PropertyToken.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Parsing/TextToken.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/ByteArrayScalarConversionPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/DelegateDestructuringPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/EnumScalarConversionPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/ProjectedDestructuringPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Policies/SimpleScalarConversionPolicy.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Rendering/Casing.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Rendering/MessageTemplateRenderer.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Rendering/Padding.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Serilog.csproj.txt create mode 100644 src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/CallableConfigurationMethodFinder.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs create mode 100644 src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SurrogateConfigurationMethods.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/ICommandType.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/IRandomGenerator.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/IStatsd.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/IStatsdUDP.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/IStopWatchFactory.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/IStopwatch.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/RandomGenerator.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/Statsd.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/StatsdClient.csproj.txt create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/StatsdConfig.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/StatsdUDP.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/StopWatchFactory.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/Stopwatch.cs create mode 100644 src/Datadog.Trace/Vendors/StatsdClient/ThreadSafeRandom.cs create mode 100644 src/Directory.Build.props create mode 100644 src/GlobalSuppressions.cs create mode 100644 stylecop.json create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationSignatureTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationVersionRangeTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/MemberAccessorTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/ObjectExtensionTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/AbstractAlphabetClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassA.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassB.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassC.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClosedGenericClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodBuilderTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodCallMetadata.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodReference.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ModuleLookupTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/NestedOpenGenericClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingGenericClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/OpenGenericClass.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/ReflectionHttpHeadersCollectionTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/ScopeFactoryTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Managed.Tests/TypeNameTests.cs create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/Datadog.Trace.ClrProfiler.Native.Tests.vcxproj create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_test.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_type_check_test.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/integration_loader_test.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/integration_test.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/metadata_builder_test.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/packages.config create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/pch.cpp create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/pch.h create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/test_helpers.h create mode 100644 test/Datadog.Trace.ClrProfiler.Native.Tests/version_struct_test.cpp create mode 100644 test/Datadog.Trace.IntegrationTests/ContainerTaggingTests.cs create mode 100644 test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj create mode 100644 test/Datadog.Trace.IntegrationTests/SendTracesToAgent.cs create mode 100644 test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj create mode 100644 test/Datadog.Trace.OpenTracing.IntegrationTests/OpenTracingSendTracesToAgent.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj create mode 100644 test/Datadog.Trace.OpenTracing.Tests/HttpHeaderCodecTests.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/HttpHeadersCarrierTests.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/MockTextMap.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanBuilderTests.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanTests.cs create mode 100644 test/Datadog.Trace.OpenTracing.Tests/OpenTracingTracerTests.cs create mode 100644 test/Datadog.Trace.TestHelpers/AlphabeticalOrderer.cs create mode 100644 test/Datadog.Trace.TestHelpers/Datadog.Trace.TestHelpers.csproj create mode 100644 test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs create mode 100644 test/Datadog.Trace.TestHelpers/EventArgs.cs create mode 100644 test/Datadog.Trace.TestHelpers/HeadersCollectionTestHelpers.cs create mode 100644 test/Datadog.Trace.TestHelpers/HttpMessageHandlers/RecordHttpHandler.cs create mode 100644 test/Datadog.Trace.TestHelpers/HttpMessageHandlers/SetResponseHandler.cs create mode 100644 test/Datadog.Trace.TestHelpers/MockTracerAgent.cs create mode 100644 test/Datadog.Trace.TestHelpers/MsgPackHelpers.cs create mode 100644 test/Datadog.Trace.TestHelpers/ProfilerHelper.cs create mode 100644 test/Datadog.Trace.TestHelpers/TestRunners.cs create mode 100644 test/Datadog.Trace.TestHelpers/TestSpan.cs create mode 100644 test/Datadog.Trace.Tests/AgentWriterBufferTests.cs create mode 100644 test/Datadog.Trace.Tests/AgentWriterTests.cs create mode 100644 test/Datadog.Trace.Tests/ApiTests.cs create mode 100644 test/Datadog.Trace.Tests/ApiWebRequestFactoryTests.cs create mode 100644 test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs create mode 100644 test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs create mode 100644 test/Datadog.Trace.Tests/CorrelationIdentifierTests.cs create mode 100644 test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj create mode 100644 test/Datadog.Trace.Tests/DistributedTraceTests.cs create mode 100644 test/Datadog.Trace.Tests/DogStatsDTests.cs create mode 100644 test/Datadog.Trace.Tests/ExtensionMethods/SpanExtensionsTests.cs create mode 100644 test/Datadog.Trace.Tests/ExtensionMethods/StringExtensionsTests.cs create mode 100644 test/Datadog.Trace.Tests/HeadersCollectionTests.cs create mode 100644 test/Datadog.Trace.Tests/Logging/Log4NetLogProviderTests.cs create mode 100644 test/Datadog.Trace.Tests/Logging/LoggingProviderTestHelpers.cs create mode 100644 test/Datadog.Trace.Tests/Logging/NLogLogProviderTests.cs create mode 100644 test/Datadog.Trace.Tests/Logging/SerilogLogProviderTests.cs create mode 100644 test/Datadog.Trace.Tests/PlatformHelpers/AzureAppServicesMetadataTests.cs create mode 100644 test/Datadog.Trace.Tests/PlatformHelpers/ContainerMetadataTests.cs create mode 100644 test/Datadog.Trace.Tests/Sampling/CustomSamplingRuleTests.cs create mode 100644 test/Datadog.Trace.Tests/Sampling/RateLimiterTests.cs create mode 100644 test/Datadog.Trace.Tests/Sampling/RuleBasedSamplerTests.cs create mode 100644 test/Datadog.Trace.Tests/SpanStatisticalTests.cs create mode 100644 test/Datadog.Trace.Tests/SpanTests.cs create mode 100644 test/Datadog.Trace.Tests/TimeUtilsTests.cs create mode 100644 test/Datadog.Trace.Tests/TraceContextTests.cs create mode 100644 test/Datadog.Trace.Tests/TracerSettingsTests.cs create mode 100644 test/Datadog.Trace.Tests/TracerTests.cs create mode 100644 test/Datadog.Trace.Tests/Util/DomainMetadataTests.cs create mode 100644 test/Datadog.Trace.Tests/Util/StopwatchTests.cs create mode 100644 test/Directory.Build.props create mode 100644 test/GlobalSuppressions.cs create mode 100644 tools/Datadog.Core.Tools/ConcurrencyHelper.cs create mode 100644 tools/Datadog.Core.Tools/Datadog.Core.Tools.csproj create mode 100644 tools/Datadog.Core.Tools/DependencyHelpers.cs create mode 100644 tools/Datadog.Core.Tools/EnvironmentTools.cs create mode 100644 tools/Datadog.Core.Tools/Extensions/AssemblyExtensions.cs create mode 100644 tools/Datadog.Core.Tools/TcpPortProvider.cs create mode 100644 tools/Datadog.Core.Tools/TracerVersion.cs create mode 100644 tools/Directory.Build.props create mode 100644 tools/GlobalSuppressions.cs create mode 100644 tools/PrepareRelease/GenerateIntegrationDefinitions.cs create mode 100644 tools/PrepareRelease/PrepareRelease.csproj create mode 100644 tools/PrepareRelease/Program.cs create mode 100644 tools/PrepareRelease/Properties/launchSettings.json create mode 100644 tools/PrepareRelease/SetAllVersions.cs create mode 100644 tools/PrepareRelease/SyncMsiContent.cs create mode 100644 tools/PrepareRelease/publish-all.bat create mode 100644 tools/UpdateVendors/Program.cs create mode 100644 tools/UpdateVendors/UpdateVendors.csproj diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..5f775353ed --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +--- +# We'll use defaults from the LLVM style, but with 4 columns indentation. +BasedOnStyle: Google \ No newline at end of file diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..fb33a25390 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,80 @@ +# EditorConfig is awesome:http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Don't use tabs for indentation. +[*] +indent_style = space +# (Please don't specify an indent_size here; that has too many unintended consequences.) + +# Code files +[*.{cs,csx,vb,vbx}] +indent_size = 4 +insert_final_newline = true +charset = utf-8 + +# Xml project files +[*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}] +indent_size = 2 + +# Xml config files +[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}] +indent_size = 2 + +# JSON files +[*.json] +indent_size = 2 + +# Dotnet code style settings: +[*.{cs,vb}] +# Sort using and Import directives with System.* appearing first +dotnet_sort_system_directives_first = true +# Avoid "this." and "Me." if not necessary +dotnet_style_qualification_for_field = false:suggestion +dotnet_style_qualification_for_property = false:suggestion +dotnet_style_qualification_for_method = false:suggestion +dotnet_style_qualification_for_event = false:suggestion + +# Use language keywords instead of framework type names for type references +dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion +dotnet_style_predefined_type_for_member_access = true:suggestion + +# Suggest more modern language features when available +dotnet_style_object_initializer = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion + +# CSharp code style settings: +[*.cs] +# Prefer "var" everywhere +csharp_style_var_for_built_in_types = true:suggestion +csharp_style_var_when_type_is_apparent = true:suggestion +csharp_style_var_elsewhere = true:suggestion + +# Prefer method-like constructs to have a block body +csharp_style_expression_bodied_methods = false:none +csharp_style_expression_bodied_constructors = false:none +csharp_style_expression_bodied_operators = false:none + +# Prefer property-like constructs to have an expression-body +csharp_style_expression_bodied_properties = true:none +csharp_style_expression_bodied_indexers = true:none +csharp_style_expression_bodied_accessors = true:none + +# Suggest more modern language features when available +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_conditional_delegate_call = true:suggestion + +# Newline settings +csharp_new_line_before_open_brace = all +csharp_new_line_before_else = true +csharp_new_line_before_catch = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_members_in_anonymous_types = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..220275c2c2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,68 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails. +# See https://help.github.com/articles/dealing-with-line-endings/ +*.sh text eol=lf +*.bash text eol=lf + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000..89ccfb6bf1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Runtime environment (please complete the following information):** +- Instrumentation mode: [e.g. automatic with msi installer or manual with NuGet package] +- Tracer version: [e.g. 1.0.0] +- OS: [e.g. Windows Server 2012 R2 ] +- CLR: [e.g. .NET Framework 4.6.2, .NET Core 2.1] + +**Additional context** +Add any other context about the problem here. + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000..3cfd4dde3a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,22 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +**Are you requesting automatic instrumentation for a framework or library? Please describe.** +- Framework or library name : [e.g. `ASP.NET MVC`, `StackExchange.Redis`] +- Library type: [e.g. web framework, data store, cache] +- Library version: [e.g. 5.2] + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000..5c93bbe2b4 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +Fixes # + +Changes proposed in this pull request: + + + + +@DataDog/apm-dotnet \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..dd080c13a9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,271 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc +# vscode +.vscode/ +# Benchmark results +BenchmarkDotNet.Artifacts/ + +# VSTest results +*.trx + +deploy/linux/ +deploy/AzureAppServices/ diff --git a/Datadog.Trace.Native.sln b/Datadog.Trace.Native.sln new file mode 100644 index 0000000000..58f5c2ac28 --- /dev/null +++ b/Datadog.Trace.Native.sln @@ -0,0 +1,120 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.329 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9E5F0022-0A50-40BF-AC6A-C3078585ECAB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8CEC2042-F11C-49F5-A674-2355793B600A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native.Tests", "test\Datadog.Trace.ClrProfiler.Native.Tests\Datadog.Trace.ClrProfiler.Native.Tests.vcxproj", "{5728056A-51AA-4FF5-AD0C-E86E44E36102}" + ProjectSection(ProjectDependencies) = postProject + {6CE95C50-9533-4650-8F11-BCE30908DCDF} = {6CE95C50-9533-4650-8F11-BCE30908DCDF} + {901F02A8-8776-4D18-80C9-05C58262C1C7} = {901F02A8-8776-4D18-80C9-05C58262C1C7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native", "src\Datadog.Trace.ClrProfiler.Native\Datadog.Trace.ClrProfiler.Native.vcxproj", "{91B6272F-5780-4C94-8071-DBBA7B4F67F3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native.DLL", "src\Datadog.Trace.ClrProfiler.Native\Datadog.Trace.ClrProfiler.Native.DLL.vcxproj", "{C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}" + ProjectSection(ProjectDependencies) = postProject + {0686E907-996A-4D6D-A685-D9C0F932C405} = {0686E907-996A-4D6D-A685-D9C0F932C405} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample-libs", "sample-libs", "{B9AA20A4-0F9A-47FB-B3BE-A5BDEA42EFF0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.ExampleLibrary", "sample-libs\Samples.ExampleLibrary\Samples.ExampleLibrary.csproj", "{901F02A8-8776-4D18-80C9-05C58262C1C7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.ExampleLibraryTracer", "sample-libs\Samples.ExampleLibraryTracer\Samples.ExampleLibraryTracer.csproj", "{6CE95C50-9533-4650-8F11-BCE30908DCDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed.Loader", "src\Datadog.Trace.ClrProfiler.Managed.Loader\Datadog.Trace.ClrProfiler.Managed.Loader.csproj", "{0686E907-996A-4D6D-A685-D9C0F932C405}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x64.ActiveCfg = Debug|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x64.Build.0 = Debug|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x86.ActiveCfg = Debug|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|Any CPU.ActiveCfg = Release|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x64.ActiveCfg = Release|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x64.Build.0 = Release|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x86.ActiveCfg = Release|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x86.Build.0 = Release|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x64.ActiveCfg = Debug|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x64.Build.0 = Debug|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x86.ActiveCfg = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x86.Build.0 = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|Any CPU.ActiveCfg = Release|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x64.ActiveCfg = Release|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x64.Build.0 = Release|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x86.ActiveCfg = Release|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x86.Build.0 = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x64.ActiveCfg = Debug|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x64.Build.0 = Debug|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x86.ActiveCfg = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x86.Build.0 = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|Any CPU.ActiveCfg = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x64.ActiveCfg = Release|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x64.Build.0 = Release|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x86.ActiveCfg = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x86.Build.0 = Release|Win32 + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|x64.ActiveCfg = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|x64.Build.0 = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|x86.ActiveCfg = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Debug|x86.Build.0 = Debug|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|Any CPU.Build.0 = Release|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|x64.ActiveCfg = Release|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|x64.Build.0 = Release|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|x86.ActiveCfg = Release|Any CPU + {901F02A8-8776-4D18-80C9-05C58262C1C7}.Release|x86.Build.0 = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|x64.Build.0 = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Debug|x86.Build.0 = Debug|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|Any CPU.Build.0 = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|x64.ActiveCfg = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|x64.Build.0 = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|x86.ActiveCfg = Release|Any CPU + {6CE95C50-9533-4650-8F11-BCE30908DCDF}.Release|x86.Build.0 = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|x64.ActiveCfg = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|x64.Build.0 = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|x86.ActiveCfg = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Debug|x86.Build.0 = Debug|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|Any CPU.Build.0 = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|x64.ActiveCfg = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|x64.Build.0 = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|x86.ActiveCfg = Release|Any CPU + {0686E907-996A-4D6D-A685-D9C0F932C405}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {5728056A-51AA-4FF5-AD0C-E86E44E36102} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {91B6272F-5780-4C94-8071-DBBA7B4F67F3} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {901F02A8-8776-4D18-80C9-05C58262C1C7} = {B9AA20A4-0F9A-47FB-B3BE-A5BDEA42EFF0} + {6CE95C50-9533-4650-8F11-BCE30908DCDF} = {B9AA20A4-0F9A-47FB-B3BE-A5BDEA42EFF0} + {0686E907-996A-4D6D-A685-D9C0F932C405} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} + EndGlobalSection +EndGlobal diff --git a/Datadog.Trace.sln b/Datadog.Trace.sln new file mode 100644 index 0000000000..152efb5d0b --- /dev/null +++ b/Datadog.Trace.sln @@ -0,0 +1,391 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.28803.452 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native", "src\Datadog.Trace.ClrProfiler.Native\Datadog.Trace.ClrProfiler.Native.vcxproj", "{91B6272F-5780-4C94-8071-DBBA7B4F67F3}" + ProjectSection(ProjectDependencies) = postProject + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77} = {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native.DLL", "src\Datadog.Trace.ClrProfiler.Native\Datadog.Trace.ClrProfiler.Native.DLL.vcxproj", "{C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}" + ProjectSection(ProjectDependencies) = postProject + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77} = {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace", "src\Datadog.Trace\Datadog.Trace.csproj", "{5DFDF781-F24C-45B1-82EF-9125875A80A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.Tests", "test\Datadog.Trace.Tests\Datadog.Trace.Tests.csproj", "{73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.IntegrationTests", "test\Datadog.Trace.IntegrationTests\Datadog.Trace.IntegrationTests.csproj", "{0434F813-5F94-4195-8A2C-E2E755513822}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.OpenTracing", "src\Datadog.Trace.OpenTracing\Datadog.Trace.OpenTracing.csproj", "{188219D1-D123-46C9-B905-A9ED30E6AAA7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.OpenTracing.Tests", "test\Datadog.Trace.OpenTracing.Tests\Datadog.Trace.OpenTracing.Tests.csproj", "{3BCE5D99-147B-4305-9970-AB0F683A6E8D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.OpenTracing.IntegrationTests", "test\Datadog.Trace.OpenTracing.IntegrationTests\Datadog.Trace.OpenTracing.IntegrationTests.csproj", "{EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.TestHelpers", "test\Datadog.Trace.TestHelpers\Datadog.Trace.TestHelpers.csproj", "{237A1C92-DE9E-4649-961B-BBB7CF0DFE01}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{FEBCE7DC-9FD1-48A6-B911-71ABB240A030}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitattributes = .gitattributes + .gitignore = .gitignore + Datadog.Trace.snk = Datadog.Trace.snk + Directory.Build.props = Directory.Build.props + GlobalSuppressions.cs = GlobalSuppressions.cs + integrations.json = integrations.json + LICENSE = LICENSE + LICENSE-3rdparty.csv = LICENSE-3rdparty.csv + docs\README.md = docs\README.md + stylecop.json = stylecop.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9E5F0022-0A50-40BF-AC6A-C3078585ECAB}" + ProjectSection(SolutionItems) = preProject + src\Directory.Build.props = src\Directory.Build.props + src\GlobalSuppressions.cs = src\GlobalSuppressions.cs + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8CEC2042-F11C-49F5-A674-2355793B600A}" + ProjectSection(SolutionItems) = preProject + test\Directory.Build.props = test\Directory.Build.props + test\GlobalSuppressions.cs = test\GlobalSuppressions.cs + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed", "src\Datadog.Trace.ClrProfiler.Managed\Datadog.Trace.ClrProfiler.Managed.csproj", "{85F35AAF-D102-4960-8B41-3BD9CBD0E77F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Datadog.Trace.ClrProfiler.Native.Tests", "test\Datadog.Trace.ClrProfiler.Native.Tests\Datadog.Trace.ClrProfiler.Native.Tests.vcxproj", "{5728056A-51AA-4FF5-AD0C-E86E44E36102}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.ExampleLibrary", "sample-libs\Samples.ExampleLibrary\Samples.ExampleLibrary.csproj", "{FDB5C8D0-018D-4FF9-9680-C6A5078F819B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.ExampleLibraryTracer", "sample-libs\Samples.ExampleLibraryTracer\Samples.ExampleLibraryTracer.csproj", "{4B243CF1-4269-45C6-A238-1A9BFA58B8CC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{5D8E1F81-B820-4736-B797-271B0FE787EE}" + ProjectSection(SolutionItems) = preProject + tools\Directory.Build.props = tools\Directory.Build.props + tools\GlobalSuppressions.cs = tools\GlobalSuppressions.cs + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed.Tests", "test\Datadog.Trace.ClrProfiler.Managed.Tests\Datadog.Trace.ClrProfiler.Managed.Tests.csproj", "{5B52C0C0-A554-4E53-9D17-B121E78FF919}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample-libs", "sample-libs", "{FA03944C-2391-4C25-8979-2E078A8CE0DD}" + ProjectSection(SolutionItems) = preProject + sample-libs\Directory.Build.props = sample-libs\Directory.Build.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Samples.Shared", "sample-libs\Samples.Shared\Samples.Shared.csproj", "{B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed.Loader", "src\Datadog.Trace.ClrProfiler.Managed.Loader\Datadog.Trace.ClrProfiler.Managed.Loader.csproj", "{AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UpdateVendors", "tools\UpdateVendors\UpdateVendors.csproj", "{72FB583A-A1B0-4B5F-8658-617B100DCD8E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Core.Tools", "tools\Datadog.Core.Tools\Datadog.Core.Tools.csproj", "{3BEACB10-89FE-4F74-8022-1A52F223CE82}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.AspNet", "src\Datadog.Trace.AspNet\Datadog.Trace.AspNet.csproj", "{B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PrepareRelease", "tools\PrepareRelease\PrepareRelease.csproj", "{DAA6B000-5BED-4081-B5E0-B698BFB89415}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Datadog.Trace.ClrProfiler.Managed.Core", "src\Datadog.Trace.ClrProfiler.Managed.Core\Datadog.Trace.ClrProfiler.Managed.Core.csproj", "{D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Datadog.Trace.Ci.Shared", "src\Datadog.Trace.Ci.Shared\Datadog.Trace.Ci.Shared.shproj", "{A1D7653A-C409-414A-B9B0-7879953EBCDD}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docker", "docker", "{E8B98BFD-AFDC-43DA-9CDB-72E3CDC728B3}" + ProjectSection(SolutionItems) = preProject + docker\Datadog.Trace.ClrProfiler.Native.sh = docker\Datadog.Trace.ClrProfiler.Native.sh + docker\native.alpine.dockerfile = docker\native.alpine.dockerfile + docker\native.dockerfile = docker\native.dockerfile + EndProjectSection +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + src\Datadog.Trace.Ci.Shared\Datadog.Trace.Ci.Shared.projitems*{85f35aaf-d102-4960-8b41-3bd9cbd0e77f}*SharedItemsImports = 5 + src\Datadog.Trace.Ci.Shared\Datadog.Trace.Ci.Shared.projitems*{a1d7653a-c409-414a-b9b0-7879953ebcdd}*SharedItemsImports = 13 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x64.ActiveCfg = Debug|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x64.Build.0 = Debug|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x86.ActiveCfg = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Debug|x86.Build.0 = Debug|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|Any CPU.ActiveCfg = Release|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x64.ActiveCfg = Release|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x64.Build.0 = Release|x64 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x86.ActiveCfg = Release|Win32 + {91B6272F-5780-4C94-8071-DBBA7B4F67F3}.Release|x86.Build.0 = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x64.ActiveCfg = Debug|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x64.Build.0 = Debug|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x86.ActiveCfg = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Debug|x86.Build.0 = Debug|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|Any CPU.ActiveCfg = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x64.ActiveCfg = Release|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x64.Build.0 = Release|x64 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x86.ActiveCfg = Release|Win32 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A}.Release|x86.Build.0 = Release|Win32 + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|x64.ActiveCfg = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|x64.Build.0 = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|x86.ActiveCfg = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Debug|x86.Build.0 = Debug|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|Any CPU.Build.0 = Release|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|x64.ActiveCfg = Release|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|x64.Build.0 = Release|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|x86.ActiveCfg = Release|Any CPU + {5DFDF781-F24C-45B1-82EF-9125875A80A4}.Release|x86.Build.0 = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|x64.ActiveCfg = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|x64.Build.0 = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|x86.ActiveCfg = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Debug|x86.Build.0 = Debug|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|Any CPU.Build.0 = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|x64.ActiveCfg = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|x64.Build.0 = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|x86.ActiveCfg = Release|Any CPU + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB}.Release|x86.Build.0 = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|x64.ActiveCfg = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|x64.Build.0 = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|x86.ActiveCfg = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Debug|x86.Build.0 = Debug|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|Any CPU.Build.0 = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|x64.ActiveCfg = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|x64.Build.0 = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|x86.ActiveCfg = Release|Any CPU + {0434F813-5F94-4195-8A2C-E2E755513822}.Release|x86.Build.0 = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|x64.ActiveCfg = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|x64.Build.0 = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|x86.ActiveCfg = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Debug|x86.Build.0 = Debug|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|Any CPU.Build.0 = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|x64.ActiveCfg = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|x64.Build.0 = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|x86.ActiveCfg = Release|Any CPU + {188219D1-D123-46C9-B905-A9ED30E6AAA7}.Release|x86.Build.0 = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|x64.ActiveCfg = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|x64.Build.0 = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|x86.ActiveCfg = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Debug|x86.Build.0 = Debug|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|Any CPU.Build.0 = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|x64.ActiveCfg = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|x64.Build.0 = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|x86.ActiveCfg = Release|Any CPU + {3BCE5D99-147B-4305-9970-AB0F683A6E8D}.Release|x86.Build.0 = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|x64.ActiveCfg = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|x64.Build.0 = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|x86.ActiveCfg = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Debug|x86.Build.0 = Debug|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|Any CPU.Build.0 = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|x64.ActiveCfg = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|x64.Build.0 = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|x86.ActiveCfg = Release|Any CPU + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F}.Release|x86.Build.0 = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|x64.ActiveCfg = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|x64.Build.0 = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|x86.ActiveCfg = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Debug|x86.Build.0 = Debug|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|Any CPU.Build.0 = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|x64.ActiveCfg = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|x64.Build.0 = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|x86.ActiveCfg = Release|Any CPU + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01}.Release|x86.Build.0 = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|x64.ActiveCfg = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|x64.Build.0 = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|x86.ActiveCfg = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Debug|x86.Build.0 = Debug|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|Any CPU.Build.0 = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|x64.ActiveCfg = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|x64.Build.0 = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|x86.ActiveCfg = Release|Any CPU + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F}.Release|x86.Build.0 = Release|Any CPU + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x64.ActiveCfg = Debug|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x64.Build.0 = Debug|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x86.ActiveCfg = Debug|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Debug|x86.Build.0 = Debug|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|Any CPU.ActiveCfg = Release|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x64.ActiveCfg = Release|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x64.Build.0 = Release|x64 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x86.ActiveCfg = Release|Win32 + {5728056A-51AA-4FF5-AD0C-E86E44E36102}.Release|x86.Build.0 = Release|Win32 + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|x64.ActiveCfg = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|x64.Build.0 = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|x86.ActiveCfg = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Debug|x86.Build.0 = Debug|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|Any CPU.Build.0 = Release|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|x64.ActiveCfg = Release|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|x64.Build.0 = Release|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|x86.ActiveCfg = Release|Any CPU + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B}.Release|x86.Build.0 = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|x64.ActiveCfg = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|x64.Build.0 = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Debug|x86.Build.0 = Debug|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|Any CPU.Build.0 = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|x64.ActiveCfg = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|x64.Build.0 = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|x86.ActiveCfg = Release|Any CPU + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC}.Release|x86.Build.0 = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|x64.ActiveCfg = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|x64.Build.0 = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|x86.ActiveCfg = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Debug|x86.Build.0 = Debug|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|Any CPU.Build.0 = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|x64.ActiveCfg = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|x64.Build.0 = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|x86.ActiveCfg = Release|Any CPU + {5B52C0C0-A554-4E53-9D17-B121E78FF919}.Release|x86.Build.0 = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|x64.ActiveCfg = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|x64.Build.0 = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|x86.ActiveCfg = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Debug|x86.Build.0 = Debug|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|Any CPU.Build.0 = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|x64.ActiveCfg = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|x64.Build.0 = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|x86.ActiveCfg = Release|Any CPU + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964}.Release|x86.Build.0 = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|x64.ActiveCfg = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|x64.Build.0 = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|x86.ActiveCfg = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Debug|x86.Build.0 = Debug|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|Any CPU.Build.0 = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|x64.ActiveCfg = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|x64.Build.0 = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|x86.ActiveCfg = Release|Any CPU + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77}.Release|x86.Build.0 = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|x64.ActiveCfg = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|x64.Build.0 = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|x86.ActiveCfg = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Debug|x86.Build.0 = Debug|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|Any CPU.Build.0 = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|x64.ActiveCfg = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|x64.Build.0 = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|x86.ActiveCfg = Release|Any CPU + {72FB583A-A1B0-4B5F-8658-617B100DCD8E}.Release|x86.Build.0 = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|x64.ActiveCfg = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|x64.Build.0 = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|x86.ActiveCfg = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Debug|x86.Build.0 = Debug|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|Any CPU.Build.0 = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|x64.ActiveCfg = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|x64.Build.0 = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|x86.ActiveCfg = Release|Any CPU + {3BEACB10-89FE-4F74-8022-1A52F223CE82}.Release|x86.Build.0 = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|x64.ActiveCfg = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|x64.Build.0 = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|x86.ActiveCfg = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Debug|x86.Build.0 = Debug|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|Any CPU.Build.0 = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|x64.ActiveCfg = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|x64.Build.0 = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|x86.ActiveCfg = Release|Any CPU + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD}.Release|x86.Build.0 = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|x64.ActiveCfg = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|x64.Build.0 = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|x86.ActiveCfg = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Debug|x86.Build.0 = Debug|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|Any CPU.Build.0 = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|x64.ActiveCfg = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|x64.Build.0 = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|x86.ActiveCfg = Release|Any CPU + {DAA6B000-5BED-4081-B5E0-B698BFB89415}.Release|x86.Build.0 = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.ActiveCfg = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x64.Build.0 = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.ActiveCfg = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Debug|x86.Build.0 = Debug|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|Any CPU.Build.0 = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.ActiveCfg = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x64.Build.0 = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.ActiveCfg = Release|Any CPU + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {91B6272F-5780-4C94-8071-DBBA7B4F67F3} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {5DFDF781-F24C-45B1-82EF-9125875A80A4} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {73A1BE1C-9C8A-43FA-86A8-BF2744B4C1BB} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {0434F813-5F94-4195-8A2C-E2E755513822} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {188219D1-D123-46C9-B905-A9ED30E6AAA7} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {3BCE5D99-147B-4305-9970-AB0F683A6E8D} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {EFBFC324-B459-4D39-8E19-CE4AD0DBF15F} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {237A1C92-DE9E-4649-961B-BBB7CF0DFE01} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {85F35AAF-D102-4960-8B41-3BD9CBD0E77F} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {5728056A-51AA-4FF5-AD0C-E86E44E36102} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {FDB5C8D0-018D-4FF9-9680-C6A5078F819B} = {FA03944C-2391-4C25-8979-2E078A8CE0DD} + {4B243CF1-4269-45C6-A238-1A9BFA58B8CC} = {FA03944C-2391-4C25-8979-2E078A8CE0DD} + {5B52C0C0-A554-4E53-9D17-B121E78FF919} = {8CEC2042-F11C-49F5-A674-2355793B600A} + {B4AE8B0F-C2B2-41DF-88BB-D97E267D8964} = {FA03944C-2391-4C25-8979-2E078A8CE0DD} + {AB8596C1-CFDA-4A5E-9E9C-74A3DF9AED77} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {72FB583A-A1B0-4B5F-8658-617B100DCD8E} = {5D8E1F81-B820-4736-B797-271B0FE787EE} + {3BEACB10-89FE-4F74-8022-1A52F223CE82} = {5D8E1F81-B820-4736-B797-271B0FE787EE} + {B34EDBC7-C5FB-409D-8472-BC7469D6F2BD} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {DAA6B000-5BED-4081-B5E0-B698BFB89415} = {5D8E1F81-B820-4736-B797-271B0FE787EE} + {D95D5E26-F32A-481D-A15A-EF7B3B56D2E0} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + {A1D7653A-C409-414A-B9B0-7879953EBCDD} = {9E5F0022-0A50-40BF-AC6A-C3078585ECAB} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {160A1D00-1F5B-40F8-A155-621B4459D78F} + EndGlobalSection +EndGlobal diff --git a/Datadog.Trace.sln.DotSettings b/Datadog.Trace.sln.DotSettings new file mode 100644 index 0000000000..725bd2cf47 --- /dev/null +++ b/Datadog.Trace.sln.DotSettings @@ -0,0 +1,111 @@ + + True + Named + Required + Required + Required + Required + True + True + True + True + True + True + True + True + True + True + True + True + 1 + True + COMPACT + True + True + True + NEVER + False + NEVER + False + True + False + True + True + True + CHOP_IF_LONG + CHOP_IF_LONG + False + + False + True + False + True + True + True + True + OS + True + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="False" Prefix="_" Suffix="" Style="aaBb" /> + <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="Method" Suffix="" Style="AaBb" /></Policy> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True \ No newline at end of file diff --git a/Datadog.Trace.snk b/Datadog.Trace.snk new file mode 100644 index 0000000000000000000000000000000000000000..b9001cc8c64e4bb499862f2bb6aa2ac5d8288a55 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096cxK+r!L9x_+cYnf1IVqXSZ&f_o0}rf@ zJJ1jp9qpNdR1KJgQasvwP#lUd z%NsGVR36rDC)t8AY3wK!ung|*%#B(b^gXtHDPg1OzM(mP1U|rYk#LqtB`;NFw^qet z=_d+%ReNg+>kcN^Cd^ZaJjnul$$)#AOoz~pD+0l9n<*< zon|2k^!boIYp?^kiYco47u2M+MSD1WGgK+QX~0ls?YCeEl{MHHI26SixrQ1>lH_D! zOA_uUHF8a29h7Bw#2;_xxB$zrFaJ?#RZF`ggR1AO>p4O{$vuKaBe~#PObB`G3F^Jj z9a?_KnxjTJT>7#MmJHk+=|VB{9%lC0)i)qA5}zirCp-_9CS%hhks@xJi`q3*H6xb? zStRglh)68pj$TDkrZR2${WIB*msa3zG9873506-P+z~;s2Y;C3@H?8VWtxQy`$%LG iKcZmjjEBIxHT8Hdc95CPTCLc*5Vl2<4<+3o9)TFw$`5=1 literal 0 HcmV?d00001 diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..22ee0de9b1 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,22 @@ + + + false + true + false + latest + + + true + ..\..\Datadog.Trace.snk + true + false + + + + + + + + + + diff --git a/GlobalSuppressions.cs b/GlobalSuppressions.cs new file mode 100644 index 0000000000..eb341d382c --- /dev/null +++ b/GlobalSuppressions.cs @@ -0,0 +1,15 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:FieldNamesMustNotBeginWithUnderscore", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1633:File must have header", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:Prefix local calls with this", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:UsingDirectivesMustBePlacedWithinNamespace", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments must not be followed by blank line", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment must be preceded by blank line", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1501:Statement must not be on a single line", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:StatementMustNotUseUnnecessaryParenthesis", Justification = "Reviewed.")] diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv new file mode 100644 index 0000000000..ed96460bac --- /dev/null +++ b/LICENSE-3rdparty.csv @@ -0,0 +1,13 @@ +Component,Origin,License,Copyright +opentracing-csharp,https://github.com/opentracing/opentracing-csharp,MIT,Copyright 2016-2017 The OpenTracing Authors +MessagePack-CSharp,https://github.com/neuecc/MessagePack-CSharp,MIT,Copyright (c) 2017 Yoshifumi Kawai and contributors +liblog,https://github.com/damianh/LibLog,MIT,Copyright (C) 2011-2017 Damian Hickey +dotnet/runtime,https://github.com/dotnet/runtime,MIT,Copyright (c) .NET Foundation and contributors. All rights reserved. +clr-samples,https://github.com/Microsoft/clr-samples,MIT,Copyright (c) .NET Foundation and contributors. All rights reserved. +clrprofiler,https://github.com/MicrosoftArchive/clrprofiler,MIT,Copyright (c) Microsoft Corporation. All rights reserved. +JSON for Modern C++,https://github.com/nlohmann/json,MIT,Copyright (c) 2013-2018 Niels Lohmann +Sigil,https://github.com/kevin-montrose/Sigil,MS-PL,2013-2016 Kevin Montrose +miniutf,https://github.com/dropbox/miniutf,MIT,"Copyright (c) 2013 Dropbox, Inc." +Serilog,https://github.com/serilog/serilog,Apache-2.0,"Copyright (c) 2013-2018 Serilog Contributors" +Serilog.Sinks.File,https://github.com/serilog/serilog-sinks-file,Apache-2.0,"Copyright (c) 2016 Serilog Contributors" +opentracing-contrib/csharp-netcore,https://github.com/opentracing-contrib/csharp-netcore,Apache-2.0, diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000000..90b7bbbcdc --- /dev/null +++ b/NOTICE @@ -0,0 +1,4 @@ +Datadog .NET Tracer for APM (dd-trace-dotnet) +Copyright 2017 Datadog, Inc. + +This product includes software developed at Datadog (https://www.datadoghq.com/). \ No newline at end of file diff --git a/datadog-logo-256x256.png b/datadog-logo-256x256.png new file mode 100644 index 0000000000000000000000000000000000000000..ad0bd7444088ae4c617f7044ec02e382802c7e44 GIT binary patch literal 19779 zcmZsCRa{hExc3Z0cMRPmv`DG!zyrPTan4xP4yYcvxy+gwUzJExj=*Wx_{d zO2n6?yLNsNxayj^l5%hL_ikV5?%sL2pCnTMy|R+!J?>&tXfG%GzaJn51_oK+@W_UH z2e^nx=;G)7_bx-D=`aG6@5qFNZwsCY=!&(svE%)%%sLLEd zKoSU}a>uJ^ksR_~Hp#GLC#e`~OkRa(owR%#!#0$e4hI$nZFhorUGSMeY#r!Nw3pF$ zo!P)p5@yBRJ0UwN_fjA)8llcu$)J61RB~7{bE>GOvSF%`FiHYwJ4wQC(dW+Z$2)sK zNLZMzD++*6YbM;?wxrq3`}@$oP8id9G_A=_n-RM&9=AQflb+t#Bb_W&T{zsCRpWGC z)&PAdUeQe+ewD#h+we`45`f|BKGJUeefGDJhtB1;h-wWOjOxOz_Y8k>O*sm!w*bujbkWb(Xps(-)w0g9vQ|~&q*38U2bA&x+CFj zCS_VdYG;|&G1wg4Le9@!ZBg4m8ISH)Vr@J15Ixh+*X>vGd(Z@Vh)+k3gR`(iA4?J= zj&xz7N(*FD@(cQyJ4g5h+iAM%#0F=l9(@uQ4orCT4RkHeL8HG`lszb)aviFoOjWR! zgdUy#eGs6m6Px2e^IergnakO_;hS^0Px@Uxljv&)?&_&%#W;(YYdC^Rp?*`gWwhsaA~U`U~@l59C-n% zpS#BOdqsxwS9i+l-63WyTjIFXdGn3yh~)sBzzI$GoXyl&5ABePu#oIfrCo3_L%<>h#7HTGv zJ%C-yF=@muh0M*D=V0xvl=<5JpisTv1@}7<2TC8{KEMyh5htNb5=m!ftHuh@_}_g| z(o&@_rrUnj7_sd`d3y^~xFBXImA27fP=9b|rjjT=*=s$@#lY+G;btcITFjU=1IQ$G zNejO2yLQw=;dWtW8j?;O;Fd)Dj(LHBd$;gZE`z;>M!VrZSLH-;{5ueRo`(lXqFJgI zW%cUs`@~Et%W&xXT0y{GA*yvonr7$V&N~qThm{xKQ!1bR$m-1!)7nrxR#P0K>D_Y1vQ=I$O5@4B&Pq?5?*;ik8g$9+GBPE+)ntA5d zM&|+8E1qUhor>`YI5TQHYj4`DyjAQ&S@;_~c`R?bkJ4FpD-nb%as0*fYWk|9U*OCX zz0%&z$U7mX(K4h~*pC?(ztBKDZ_tX4B9O_%V@1XF2eSl{o;oh^D0h0gZvUp-+$S;$ z82vy(sQErEUez*{7*ZKD{ee88gC>hmJ6 znD1-t$C~u9^U)xsdbLjnX2g?EP6Dj^`JaNolp&apRP8g}d_*rh;w6Q*Fla^J6xxHg z!46X&hzBQfGvmhbS0xp(_4d(MF&#AVZ^vjsW(kc1O^I?Ly!1J?0{@+}n=HvN?cA89 zuR0rzlxT1dS`%bpDOZZ-!$cZf7xV~WR7xIZ<&i0rN)V)W4%3a7bA~w~WP={$B z0E<||6q)K86b$x2fQrIJz&y_i&ZiKfDB<7U?D8Y>;SNG(x&Iw1VZ+ZMb(evPSD^};+GAbxS zk+|y6XB>#HV(+C_9{*C>NeF98u`5GDuMaez|B*udr@)yv0|pQtam>DAf#KglPd!77r_8t4ve4HT>oQEt zKzD<3c-Fz%dZhKJAq_?UIIWD?z-TUzU}Y++ku8xZFC{CZXvCr^=iy+uh-nPJa4Z#R z>AD;(k=#+U%L8cSymDrO>&dY>m?vY`LH|{5KNKlt$yVz;gt0DOK)Q zsq5n(;QcqBLe$~{HJvBi+`@v-Ld6GMPA-3IH8)Wq0p7&_!~I}sqeq8Y7A^>|(MS3W z`dDJVDvodR^ynVL#@0k#B_sv{oh1L7g%ncJV>q$695ux%DxMnh>09#nPF=_cFbPOL0;+X2ekVv=@jCZI$}k-YS{V6qEYXdUeKugQ3WOY6ePo z!rv(zps^jkW(U3&CB11dH}*Fd_KQv2m7*04u1$l`0W6off!f~68gckTZ-Ftl zx~>}G#52O3Q+aC>pW!Z221r#DnWU~aLlUEz*<&b)sBorZ{>EcIyLU=HH=(f=`A(x` zRmb{c(;a~nk2l+5FI&3dN870zjG=JdwWtsz=()#Kt^1wxqt2qStCmt$R`Z~o?C+&d z4(TNQUF+YFNmR}5zx~7b3TN8MF6Ws6fXU&grN;s+|1=_2`0_O-J_|RhL=gL)%>33e z@Pk&-<4aGCb#WL+_N)$oQwkjlA3Y5B$f7wj224fdh+&C~% z5wfjsX8Ah*=x#C#K57g9c&5a@L&f3MsYGKJi3up9_s5Z-2Q8!#kf6U!-QX*E!06mY*2q#u09`V ziC9{_9evpcbUkjkoL}v8_#)K;w1%s`kT>64SIZW-b(n64JF$}W#Y;U(sRkjgkHoF zpRX&uz~rp;U>gZacnf|`z~}3nIo|F4>rcO1aqnovskFb;U}m7gsf5hx%cMU=d6A~} z?O;?V+IuCUzgms5V5qo{_;(>(yDZ1tXd}*bH{QV7&n)~GtRXLndGq~oWJbFI(YeL*xc*mPoG@%R|1$n3f{L1ap*4vqKnnX#>Ez= zzjf~CqjYooNfiNr)LWh6(oFtTm*G^xMX4Q3w@?6b-+s^gwnX|hYcaJ;?05w)!AvNEa=*ns(f`qjlI6=W<8Uk$<&>C$MgDlAi2B(kfL3&2*gTAOL0Zib-PLh5qB-c zs6}iUOwgJZ8Mu?{aZIjJS~_y|kuHj2LY@?(7WZ5>NrQ|5ezP;mmK zBA5?%>zG~xe-LBU)z?k2-D`PVDD%g~rcf=DQ9Dxm4@4GG?V8nZ_p%1IC$p7p zhWRtj6oo2fkuR!C`(yaZPFuFBheSF*V$diS8DsZua!33r`RF{UvRwL$$l`0~k+jTM zI%3EE*ac3%mcfM2;|!fI{H+(-J_j@0Qiu3^rOOEb&y*ocZ-58}Luj2rSR_anCi;wL z^aA3{DVV~Lmd%MLpWZJOGBe*%2AL7|=}1$;EnN-w4JsN-L@i{~M3?m0fCRi;G`h}hP<}>v%HmJIpV zLItUnx7-Qag9Ua@upM74UEIE+0IJ9HvsEm>pw%oOfk|UxZX9WI2-=%~t4)hq>`e6R zPjVdfP(sU=3h;2S@S#pMC)dUxkr!V;n6by1loVR$;d98CXal zlv?QJjUn3FDwj<7aN8Gf!CCnJivTg^HyRjz2<=vMK^-ja*IkLve$PtDF+P*>Az!<2 zLep_@@ue$Hz-J7ZCe@Naw3c9V#*RNMw?-OivM4lL*@a$S8|xpheT)1l}=W3Kaob8ryV1z@AG2H2JH;WgwtGHL4us{{7wYdfyx z4@3)FY_9v>pD}^p>y$)C^`*~hcyRduiGMaSsQkDwQ4;F`7A$Ea2ZA`mC$=$1x0%*& z^-eOo^;QHgkwUnxw2x`kAu?skCcmu-MZWd!R|;$%V|99bEcCc_JeV(M-bJ&^U=RT4 zExh=vkbDHXCt;UL6G?;RQN5yBW%$x-4HF#u%Aj2yf2l)#Dl3X1pE@7Kd6#bQ4Y8tZ zrCEDx`wo|S_3C3)qm97O?)Q3?6c(3ja5A#1vp0qGfBxjY>*w6>jzNF6)80Y29K~=F{eB23sU63 zk2ksPZmOPI2H?Xzn*14%NSKZ}3CbI7nD;-;7ki0h+vnit^5y{)Mrt<?v%bC{L?$|375rR(!xndi7PGYg4bXk=3wVe`ie_t& z=^Vq2jFY40C`KU5uLhXvF6`C)#8CjV{&0wSleR|iD9Egs--x3_1rGs=b7)M$ul~CYXX)5rPUl9 z*|bdG`&6G;)+L0=42ZcO*Ftiy(TEiwgfE5x@x)ahJ3ZSr{z#tpk7U5VZbw{Jxia#4 zTD?_ef4G!ZjxwBz)rrhqL8%>LAF*`#945*7t>IDjXKdXW8f&gq`^^Sb7P25|Cq1WD zyVq}&l{ezIqY3pY9j*9t8@Isx%RDYIL2tsgOWS~OY1g)MC*u69RO{V}^P z?mk=Q#Oey^I8yojbs1{9U9tQsAt4alos5pOzCw8_igI>e2bCFR7)=%hcw7PYL2xE; z=h%ff;oBb}L_g=|&+*A(2!1MB2!f~B&-B9xu+CH2Sdq!pgr=N zw-BHDt7U=E7n1R>t^fqVCO&^m#l8fUa`ZkM1y?^v?>oQ$&WoIgx&csS&cws|ewq@c z`PqiT4LjnMx#E9~vtv__3N;fqJmc*&V5{5Rm-Z8#ye@!-Y#Z z*Fzicln$FwM^EoHqWl;gV}htNeV@}qkTuCV9_CZ}+tq)WKUcZh1H54O8_P}CbZ!VO zM8pl9kA6U3W&+?K=Leu)W(U{$ypav6rElUY8IW^qjIq>baY<4+v0INR76eAJUOjD!{5IIrpd-p}&ZYee`vdSKY z`SI~56HC71z#9TjZsRK zqDQ}lNe?x_YaK=JJf`i+otHMzLGFrplsq`FXxD5_)UC*b8?<_?Kf+8R`2}}N?moxq z1?DqvIedGHwf-tf&;1!IoDvXKezlHdRTSJ5T8RJ(fJwB@+J6_o8(PANebU0My5h9; z(oz|J!gePe8PHuzs;ei|rg#tmMNZ8U^ESo4r$3UTTHE*kC+xJh^*jbl`Br+rEn z;=gZUELuDKfSQ6J*cDq)>34;$qP(uk%_o__gdWL|E}((J-Yot`hHuQp?t#qR_A)Jd zwS|s0Sz;*2p$y2|0IrCzmlu(W>im}Rb6^68; zdE83fxstu9qgj_A&x&;{+1Oj%uxd*IQU&{mZa^bPqIUBYop%LSZa0n}&g8ZP04Nhe z{PLeh7B%62!LoPF5i?y+10Pds=>l!|)Z7+$`)Xc-k^D?kd22CAO#sHOtVyJq!I661 zt5{}}@vv&(MzyOCuTW>4&>vUtWoFBV_hwD;^3;A7Q>#xLA4wu&Gx$l%#8qumtx~xl zq0;~=M+17;4pRL}uSK86;#*I2+jCOTX5IP=fpd*~n~e|&aoFpHORZYDL)KKMOFnt za~7HD=kQq&u-qg111k%%aNW`X>$I)QGY&#D$X+WG*DTOaJWIG;EQs*qMMgr0YOp%SB1yebj4TVLgQHtvHo z%cjHXn34LxM+>x1q17Bfm_+?Yj+mPC?~RnBc!;XdziMbiQ6@dBxnUhd3^>Zor0MdD zu0+AqkX^gnz!%Xn!f=t~14;UCyXeQDBl+{3NeWO}Y!`!m8%^)(>IcQ#HJ>{pQTX4{8v>>|*eLk7h~SZv{4NFsvXo5?t?>mubW zobF=Cu77F{qoH_%uF6`Vpt#{#Tat1773R&ybN+ngkx6H%J>6{D^+UAlXPbfs!(ZxE z5~RMWp-x`BHy=_PQ-I9YK7W2|Bl;uhK+2hsbi^$_M9YO;Mwu{} z?A}b`Tu$J=TCc0te|U^7qQx9@$m60ZA6rAsbF&;u3*EU(LndXY45}NS0WN%+epzV@hd+N9I)zVSSfGo`l}^l2^pd^n6_ zv+Ttf(_8WrD)z|K_Cj>as0lGgFYAGWw)W2(igS4^aE=uc#R%%LGP7Cinw2|sr9xU9 zywcV?*zkg0z|DsG_14g$9|_n|g6^4nT50WT&;`y@k^g%7CRt(M=1>2r@4JJhp)0|v zSs?<*?mqoz!GV!WuBRgjZCTMc?~T8vq`lL=Yq`_%B83#zE2YlylP`O!kEBRY85{f+QW<~ldBiOwzK*|3Bhw0&(~8k3+5#ys+Rl+aAfyJr&=5ny&IVeEJw zl9RagdFnN$uih!FXIw96%D6ejybthN0_^ z?o!tOWL#eIfDg}?*X(x)WoakL2cqR|^v!KA{5P-X=m6Ow5EVw4^h>-CilSiu=!~jY z=Gr$*9g?*aotTrM$|}YNE%<}*&a{_K%=mweIA=9;yc9gG@n;%O102&-q%F00AblfB zFf?gAsn;Xs%mM@f{3h;lQu?Wy>zPxpJn&U3Tzf3=-f|jzdmTO-NsAWRP@0)dK+9is zxoV$d&QC$-zD+z7WbIuv&6@=7N}qR{oerNWET!tasLZ-ZM940zohXH+r9<}24~^Q` z{D2uyp~DO9I9a`<$QsSZr5@o1vIN^^+o>uDp{L)0r3ndOb$Be8L*oFa+1RlvvewzyYXDTART29`%K$$4@ zLOi@HqC8N(iKJDrI&^)WDma>3Ug@JAH2DZ}quBPxxOC7jD5sj?rQ=1{ zYm*T@Rj!Cz3s-8D@2r(eT++|p1Z|5@5PoC_I0X&R;lSSm&izZz$qjZ``mSh=)m1o& zuyF;J4pR5!&E}HCidnB@e>6UE*4w@nz2?sRfQ**A9RKGyHz!Jv^Q99o=l~GbBDH(Q zx_#|%X3aO&Y6qxISCQVX$17vkiQv&KM53vzdDRcVkB(S%`GCo=%W{d$ymsK?E?Qqz z6^{cP`Te&5M}57_ds#GZ^TA&uT7K8oQtW!=mFsf5aUuOyB2ESGHr_GKc0V@4Lx|L3 zXBY&yJ{rffx{~-I(W7!aq4E3(71Or7ZFDdVqhZ>sd)sUF7b6w4IZcn$S2N_4qgKeu z&qc{VFRI_?Z^*F+Xk(=8))n^yY9L%3)LqUb;3?s%sgeCJ8cB9OoyXV3X}hG?o{~@Z zOv8jE8S{R4lc65mr@^eNZmGVc>$J@iQ}Ve%QvO0l7j?k|)sNR7x$jOQTM&VX!meK) zb}Blm>Ysm`*P&>ZQi_u+Q@~0f%=n@kXrlo9-Lw?X5oz;UG21I~#%{0a`gm7KT>SR? z;Msa6Uz%OU%%Z#hXi_K-o^A0A7amS9sZ=|%RKCW#W*8+uiB;F5cH~#JdtpXDR{zyl;#iT|_hcDnyM_>&y!Ypo+oAdk{}HAf>vN5KrTF0Vl%dyC-% z1Pm)+l5W&sbq-|uYXU*=rxz?6XQDIqbIG2!y(B50w)t`VCH5=Rf=JJ zMC#((W9- zn%Scfz&0!~*k>b5rjW)v;q`DFt|(I`YlGvbVE;w=K~@^T5$+HwCdK>mjM7R5gux+> z^r!D(BmLKnu>nk`Ff32$(I7?-EqXXyEJ)o*b5bgSYfvP%zUZx$no2^Gy*j!RGY;&+ zs!%KnU}eQ>-lT>}h8#a|GBT~LM^ix{!gO;cfgQW=bgP_gaXGuP!@&HCYpqOMi1|My z2elZytHqQH3DlSz2+J~W5SaTbx^foZn9PVT!nCKcvemvVlN%r_^(BNDwYsSzzctBC;2Sn2~SgK8>bK$f#)R zX~QdJP-74h~x8We!w5^wR>oIM*6 z9$qTaS1bzQ*R!xmyPhIoCQbSKj~{0R02bqQ^d4Ya&85<%#;=f#SAxnK(H{7GIMAdJ zLIh!ISOk&`>$T<&lKTlDn#)!#S@Wxmruo-62>q;|GGPk+e)Rf2$Z@VZmzTP&t7d%Q zZg5ziu8ohD_6h582o1|+4E0pdLXi@2qXB=ySaWZn| zL%jb}i=m`&)oX6&%I@34CIAM58AB%4hAVB{S0p?Pdy0*4)@JI_f!Sh-;Dp~|(di|G z@5}j!KKpu#QEIN|hm1sh%tf_|Rdcl)GT>7Bf1I+c&5m_cf{e&y}@#etSl8vzY!#ejLqH#2W;fD_i9j#a7U?4Ry>vw0!YazTHP z=5Ic7x$rnB(NDAkf4fyu>*ptvZ#wU_XQu%Qn`ViAS~9V?j)=p8U=98?TBn^y(E_dy zE;;o$@TizZf!#$MDx``JJFL$=pMsLs1ENZfaV8@XCJhil#)4_)xmIx6mRJFrgS+3c z8dzC|*eO~?Cl;Oc>;bvvdq}RDk9h|-DVLE1U3+2z9Kr0sQ>(%#ThNcJMhxP1!RdKx zn$(BY-f}oCg+Km*hX9MyMrr=KRy*Ow#r`?D>xb#!rZO}$PHK@{E4tIxpp7Aqq@yX; zpv9zU8rU+Oy#lLUX>nTx(wD;6HDxcR-e;cm_vm#{!928pHp`U=!o~VVNa5}42Dj@z zEDR2nIbHylRxyH5l5`G8U+n7XCp>y1d!FXw6uz^0ff?pb=J=0dMJ*1lPnp(8hhsfF zX#c#0r+7ai%?25uz3QjaxQ|c&QU&xU36PS&L(*ehN{&iKjgX^&Q3#~HwB@&-Z>SCU zs;7p-t>{{riK$*P6dGvSzYm(phSEeVBo-v+S!3@SiL zfw5Nq3((9z30$^ANZA+SNbGPkx^>DQy;XRt&!bv2LrxN|vdQh}r+f|<`2+a&nFt@k zW*-kmti4%A50PYJ8MkS*Z%B0iZ#^Ql$3IgaS`WttWhgOeHAE zxmFK*1I*`}YF8Uy%We8rG^axFOmibY9uJ+bBplfV3SG?muH{x$MUYhqmLhkScm`QB zec#?5G$rp?A_>*VU=~JJP#RI38^@;$D1*y_#2zwd{!Mf2Z{|PFXJRD;9W z*Q)^@Bh01)K}k-+c*cI%E|71x?IHg2b(Bk3F~}9{DZyP0K)pGX89+O#J`+W&85-s01l$I78Y!XvKX{0Wxe8QcU$DSHTX#qj7yi~V`x?Z>FLx!};g zdjC@`sJ|_TrT^+B3sdS-2bECW(nP5Es`PMZ(A(0YtwN2(%4epa0&_bc%ds zQ5BFPR@>{(n=psVijb@<8F%6lp@MUvONhXnO!Twne=JxX|g11>y;mlWFu53>9?oTi8d+``Bpfp{@6uNVkV53w;hGiB6 z3|gGaEM1Ql>25vS_-2NJEz%-k6g`LJoti-%{&wW)$7{$lL+fkyZlPAxbjE;XR192| zPxpSr?ax5(pY6F_b@-G4-!9*st?)cx66FUeZNUjOX66^fDL;qCe%lPhV5ELW0egg5 zp3BGg_3>)~ezcdO>0>Tamyj_l??3&$zE3r~S^&{a4d?Z0NKyW^%EuVB+sTx?V}j_h z`aqPBLpbPKa87NJu0e~b+2{XR=4Q5q@dL9ns>Bpu()wGxvA4ntPM!D16~x<* zzf=X+V(p`)FPn$vO%AwqA#3Fi3=~>Cv!Jevf4|shV_U>c4;BOjJQRpl-^kr~f1%$u$ZNoxp+cAIL z<)i0eQs~i;xX<8IO0PlXg2Jde+_UxLX3Pu(1XmMcu~?+vOp+=lbQ%aQ!aTKhwHLL9 zjLiVZVhw_Dq%}-p!oNHmr1(Xct`QZNoY3&yU!tJ+z4y{Uj?tmZIPu|)qF7|RxiaY+w`(< zOp(j+H5%gJlbl~TM&szqYau_9%e0dgT;68zrG z>~hG#w1cxhPLS>mZ#&3^9Va%Rf}5rbDEjqPJDww5Pe8{0 zg)pB2tM-yZ|7MJ1xe~gLsmHkc5#RdmkqsGJ<&io?=?snB%K|Y zi37vMY|U_Y_+TU}D35M;!5WF=ka4mXsS90%#nGB>^(K!D^WZV@Duqf^5G`nfgJVs?9!Rm%tSZBJR)`;C8iZbC5f38^ z=B8@Zk40T*@o=bgn9c6K@Og01{?v57wmc^Jz9ji4as<}aHfY?Q$ByHnP6Y6XWp zI-Pp)7dj}v7enV=T;GO(m>WYi&}VS2=~kl%LsFl4t+1Y8`;7#bME;)e^q7XV4$XRg zUe2Vc0D#-E%*&i797_VidJ1#h>~R0M5YKOYR_iYAj1}L1%ZMq#X{z{zhMBZl4-Ikk z=g|W&01F|sWS`z^w*5&bVk~2a#{{jntcy2%afwvixLa#KU(DI}&n+$Jy%wI#?CQfT zm*VJ{*e!M_LZ-?PSn*Vk6skDR%(NUD@e^n3Bv_~}Zd^zsc`J6iRT+PU=R-D;-!JE7 z)c9e*UfBzJukxK(=T5PZk^=UcAGvVBqm1VPtf*3wWdJ32qKCe$3 zddB^#F#3YH@%gR#T0dniHq=xTp((Qo7aW|3*{)xjDnmvM=N&~|hI^~%? zZKYjsk9hp@PcszR;TBzMSju21lEN_t2U--vKI&|a{zeO%Fo`v-0G(=0(~*|66Jj;jCwGG-MfBEIC#J z{9?MDQ1S&@cP=Jr#py)4(~r}E75?4`M0Q()K$%%-QU7paDR=ugDD0^_tJwm{irX>*ZOY0gbJPqufw(X5Ab4XTPW-hR~nUSze@< zRJo%bt^`x&`!_l$mfp}ghvI3nK?{+cPbc~|e0zvbX>dskv6+hq;)J^nZ>f!ro(lG- zir##W5yvlf8+ymwe&rlBe{PATa6iUv;bsByE5o^p;V(MY0PEU320%5*oFi4^RYbkE zX9c#GT1Fhu+Z!1j8gMf*MclHgh?EjMba30TFrCfft17D!hNt@#ZN;`S=l9WNvk`Jk zsD=#m-bS;vj#Z z#|>>X?gzM#(t4L1C!xZ-3nruD(&6?|yGE50$&Bx+J+e{2q;1*Kc6@m`S1O@W6)B2^=4*LqVMu!GlS2Wq*7P{=ctwMI_MfkP0A-T@hmYXjAQI9^H8UTuxJl8pczE&|;maCp&nftJCY%N=&u)cY_#&N(;qBDQOR_RJBD=Yk zwv}UwhvX9IO`L}=6&93;d3BSZ`*yBec)IM#r~8>qj*qOAhRC-kjhZO#IyHC%Lq@}M zy)uqMMbKJk6220zJ1^!cp%4DkfzI0RRaM<@N9#G^>-u=|<$!tX%K9MxZHoU|Gd+%U z(n{*aiEQ5s0qxcOAo!GuJ$^PJ`xdMK@EXek3zP6r8ju~d%}r2YZ?rAw1GGq|e%BUnvEg(~dL2;8 z>Bn0U$WA9u`RN`T2(oj{=oWaZ*`i2u{{TXzdcZeCynrJ5EnfKKp9^0(oCK6dTBN-uy@a zppmmj+Y3?k*6Y=HcY;5D7H?hi_^|u+QIQOgFH+!JY;D}{!ItzujK>8LH+dEYeQ z$Z4duw@dnTarI!tGkzvdj%OYmCJ2~8Pdp0b)<;dZG=WE@thd+KomBidmDJ_G)nv(bz*PEOzbtfltR70vS-E{JByKU2_V zC}L2;vq#tO`G-|E2QC7+Fp6_&Z8m4eqfHG+RmX-gh) z2nqQy?4pg4J*5hC^n9R_eMO!KdZR(HOwe&N9$flM#9}Q;@R&!-{yES%u8Bs;XpTFp zb)e&0%OPNTaG443Vs7S=P);0aiCj%3 z{OID=dkIK4Hdv+7y>W-;9ynGQr}`N9k-n?-XV*tjk&5C=ZPNU4v|ii>ZE}mDBNYV| z`DnMCaG!VTMpd$vB+N^$M&%%8edR_Unr*G)EraU8mh?_1>EgcXI0_6QirpnMS_?Pr zT??IKMcvX}Ks`kne6(R|3;3jJ%V&o%?%KosGEK1SP2>%%krt(W9D#g6ci2|ZT~3gz zFxxNcA}y7v@!pmMmpJx0FwM-er&3$hW9wEp0uESx$U$1mCC&Je`QInZ-QGbtUN)w< z3AY#Kw_ee_YBS2^sJ*gEUE30C3cFOYKUg()lkzUA=|3`N@N{N9%aPBpS>`=0(FgU)I3bkjVlAX>^~L~CcB(|2-eTQsTj@07v+JP&+NgI4Q|DzS2TL6cc=9)0Mh&qxU(HBJVC)K| z(p#+NN+{=v(~*_kZnijM>_Y)L_06P(>hkYl*9fcoTAK$&qO$ZZ>?AvZ>+NhQE;+WzLGDMZ0Llx z!JR$q6gH|znVPggy0~~95(VNI06|<5i;*kd83Q(KiLe7dAN&f4mI#KYy}VBq*4C-% zC6%5`xOH1zRG8=2h(daBoyHl=X`loQ3wyD2*TaLYI)3yQ90muubkkx~TYTc`Nh;Qs z(H`oqMp=hk3kU>|t4;v0PkPVyPx*cJf>2`5_8BpmHC8!>@GJub#y@pEkK8{5a_C2# z)5N2#R}jT&-$dQE>lnSMYU_Q^aOHeeq=rB_0}cU8Qx3X=eYdaz484rDZ)u`b~n;FvjT>r5X>gL_`8 z7n!W+%W~Q#vi$w^uL+o&^p8wcctcQ!z9yzMeIJ5_sPEHWc@9*pwJrpA!=g2sJ!vnA zqgapZ$v?wmkRn+pCFVyz(+K4Y=?}&HTc+8SPf|YS>CmKKWQWDLOR!J81?EqB6=mK= zN6rJ6Go{yw?7H>34pRh;wtBT^1ZkqWJxk8dh$A4}#(@tdYMfPPa??9h4ukhP+ofQ+ltm z%lFdGOl8qCj#(BbrN#Z%E$)zE@9c0Jo(I7l{;oS@zZ2DwUhLV4UT5EOC<g0 z_2Er`32~b%;E)B#7Sy^CjU4?N^H3=mEsF=Ehqo&Y!0MQoe~Ip%Su9M;(xJ$+c~a); zU}tX-`BWsJJ%0+^wcUP2m}c%v7Xa2ye$174{bbEMpcQe4zCK*|_k1&NmBmZ4*1-`Y z&@gSFDq}IG(Mx z^}%r-DTqd*aUb1R@kWo=QKH*ffvk%e`s>cv14z3j;q|p!d`$& z7yvCdxSK}&uf-TF=K~>x5IY(F(x+g1CMk8ESC^Rn>})Pfz-6F~)_#`$DByKyB>$#q zlz*0M!DG#peC`~pSsl1#h`zfK!>t;qYo zP3u1D#QRfF@;UqOiJS5FzG~rp10^Um8odtb8b(3uP}^Zp3;HfW^0I4OV`2klWR{Q8 zUorRzLHy~&2~q#B9q&Pfl{|nl&_=u;3NacbRl|~guaiZc&g?$#xQ5?2>!G_&{rfvq z;zK%0^u5k0dJ$L`l_>RoKOg#~++r{Wr8?Ib&DZI9jf##3a3p|)a0@|xo9|oL^BrWh z5TIU{E~<|VHUQo+n-hK-u-O#qkNy%x)rcc6u;A%`qlTrgLitp${)_ksrBbIP7z5UX zQzr*t5Ae`90>wPwk zo`^%a(W1nlcpXo$N`v>I1qT=dhmMg_y?D7bppCcy@^YS)y)h^lJSiza>Pv0q6|cDADdL$Dxb<2aPF!8@ilsP zCT7& zw2_7~n!JcGC;x6ov1z!w-!y11y$mH*=e6p&`8VP3NVHhb!wEXqycIl=uaj8rgo+bq z#37~=UhG$F%26){;INJ%?g+l&64k2yUgX0_@c@#@is`(-EgA}O4J)T7Y6Tg_>Gr*2 zQIueGPz<*yf$-pXl(V#Y&hfSGXb={4hQ=dX+}n>V((@3*t-spXsFDAv&=?7qCBmF_ zAwI-T(s{p4YrN%YYM@ka#BpoVhrA8SqS*P^3 zt^w7vOCX6ni`B{b;Svg&tl=Sj+#n-7I>-sK3d$JWQ_}qKu&<75y-uTFUyGZcXh6qj ziVq{TrV$L-;V4N>nhGqk_&4jg;LEXA@6AoRP{U}bC==*s+?3}!&Z-8F+xdFUM;6Kz zD2m3M|Ah@GuxCT?=z}uED$|a26k!v}J}u8k+rTl)Gckk)`cxm(@%i8#vvl$RJy6bW z>b(GG`5@c;!nJzOy63Gr6@wq#ekNA9fwTOSB`8iE2Hsg=D*biPFm_)yAhz^IS?K3$ zovBk{i4pW*hXn?nj0J7X)F=ZIrs;gGKgy-3yrC*lKBN=>@6+iyS%gxgqm$3$HKsN} z1Hg*hMvUi*(dpXyO{0afk5=*z-M=Cbu-R?Zps=wx$4@yIPr5T9bI-$T{_$bRwMk(+Z`K7%8!^!cm8^pi|7x<5Iygr(l_BMFO z>Ecvc3FhEL5}iJV9UiT-fhpNn#B;CnzF>rENj~ z#_vBEsU83;FG`-6e?AMPrw{VaTVDF1JE5GXlTcX>!Q%^^xH8$K0UB&5#p$AG(40RD z!KkPr?v~U9mp?PiIv7xLRTb_OC->begwDpH7uZM`i;g-;p!IwL1_{v;{W&Rs25BUnbhD8QVq5U@;hWu< zCNlkl*_9TpyuL17b4rkBscoG2y=gjQ#Xb-#)24{uyBVcSQIuN2%O{UBM;MIZEWV%P zVw7ii;EnJ1;3@GtJNqzJKcK9~@1HKZ`nHNNq8ddN`j#z*=nOW}04QQc`BQ#;pPeMY zA&W0~Io%Rb#_06H^AOAsC2mB9r*jU~rLW&rjoIr0O4~z2RQB?eDw`VUF#o^zx%s+pR zzm#fn?NO<(5${8;kM(GMg*+rY!D^8Rb_q&wytvLN0}OznO%5YZ?EKTn$-VE21acV| zhXW#U`d(w2$Hca%5$;5`rp^O!3NpvF;^Z&ZVG9n_N&YQ`&|{rWiN=m{s}V{ejNKg? zM){~1Z|(~5P)iUYO|6bW>H+4%C3yXJ3gzD! zb+4ET>@vX9R>Ro~po+xBDsk#h;Z8RFZ9ijlvaRDa6(V@o_)U@Yi_+jD^kXtdNWs5z zkWT!&0*t|8u{&{?MzZb}7IRQ44De5)({XT$FtxmdbRIr6^+5JJ{V>^^Akx+9qXy+{! z`JvT|wyK3*6pOa#jp8|8D|D_l zkR;&55G0&b5Fe48p>lmT@VM%7o!{*;I7GQ!Z_*1vXFc{CjTj&Gwocj21;*kxl-~mw zr!^a8t^v=7nL7vekciTnO^8CG;X1n%1zfn2+sx}ErQS+H2~Cgd)YJg#M&YhLPua zzBliC@Ar<0xtm~qc-#G^xII5K#W~`v5AFW^U9~yd(ChK`ZMc%?xBt8UUBkoJ}LXVhs-fC!SP*7ob6$Ay!|`6X^7n|mtTqd-lC^?p_`(HQ6 zKfpI;Fd6NC!ws&&&Drp08E&8rmun_Au>R%!P;;;e+As7$S>}0I{-+Ev1sJ4cVGo*U zkj!SIJr%WAfI`mV*}Fl)?(|yw=RBAgbpoO7Tn`ZXt`5VxzvkJh$l zb{b@)R6<8%KY#*^3)NTg;T_@bV>6akm-CxkIwuWQF36g;c?Z-MHG@Ac)^tL7c0H)* z?-~K?+)N!lKt3gY-VO5UFhco(i)^Q1WN;Gv;cCTPQl*IHISKd3<`FffNO1oFdc2@dtt|tL*S3oWo>$VKu;tJ*c(cqCEgBc zZyklM)zer2r4{ z3o!*4?HfV~w9d_da~16n3U$RT;F@v+!RuA{9ACM39U{TxxC?GvANOrmVTIb0kANRY zzNQsWcotHC$zWR;OwhXL^Vt!FL(i2PP<@~Yq6GH-Wf|weIq8POS@pc3+QMdkD?o=B zJ}Mw({+U=LFiMXG2tx0^-BJou6K)6tep4U3@exE5T`dE!%~ZmXfZymN4!Bs`2`X~m ztJY$J2|@}WE*?zK@dJ&Z2da;VCazr`f>nOef|O91e~~RiT2&t20*tnog%n^(aC|w? z`N=RoG6g!o4|Z_ZNr*Pu8~QNxIs%-sj!0k?&dP#t0X9V);E=WcrF{^6uyP~G2U251 zfj2cw7nJqxG2J1HEoOKMq5$?gHHA%Z3D3RPqrj$r7Kkb!F9I$g?GHEx33fI^Ee!RJ z(LGFbqJfdY30UG|ml^9SDb$K8pjO-h47SZ7m>fS)XfPe-drp+Lgp3sRRUN#Ut%=1@ zBA?Mvz~n9Ty75GpXhzr`fdZt(p#*OD`+iPHf3yNT9;O z<@7+Y?F{VOS_d7MuEUCXnL<`zowe@^VxiC=|3X73JG$N0GN{_$$ZRe7shpb|+L2Vs zRCqe-k97obrAn%nr;Oo8sy)L*98pHgqGmkP1S1R!y!rsI6741 zUf|UEc2HB;ET91CsR$gQ+^8iuYkd`bOyERl_wq8mkzlbn7cfdi8iLsee2n1wz!H@n zhh5T!NEEPDOYqx&*$XodCRap&I2_tml~cya2@)aw?W1}WkQNCYPSTD9c7C`S1l1jb z7F$mrz6=PeKj=9EWx@)uVDC-O`8t|+0cH@CSOqPts^ztY<5%@4;G(z%#7n=@qk#R} zPryuKxPKgWEj@J0hRV{wgwd^ASRwx}3bcAxV z&Q1;`D9q^dx)Fz?`N zneQB9THSoATdQVCdCNG-c-64!bNUq!FD;9pxyj`#J-FJ`f3wk{JzjKl=oL;_=GVw~N7^(1}>ihU04Kj(Q8^n8$s2fkTuGmFwO7^2ahb_G)3v zYen2cyd8`VO_BqpmO1@9fN^5~P<<|%Eux6y>vl;MqGV`~j?J^FwVdq%ZEz0HO1K?l zZ>Ul?NR3k-%20tJ)Bo8htWw8HJpwJFM_?rh(HNUyFRl|jVw3!IE<^|(y08S+2)I++ z-8RTYTL0^3uy){_a$}8CQcRo~!aX8QlIK-HAqFQz6C4_XA`|r|G$O=?s>$JsGy&I; zo>MNNAgSU)?~Ajx>F*QJXlsbg^X!jGLC1!ts2ReEPVT1TkhAePx3PjST>3qd!HrZw zs1+cgb&yK$3c%_ovRMI1v5p6ID}bnD5TR6;3&;7ngR^;IAvH+?oYX+~D9dOK>NB{@ z#I5kY&f$Q*!piwsq6$zu+tjxh^-Yn->Q(@?m8dQ-y+7!h(oA^R#BD1N(@Y>$cKlmi z%wn8xEr`Gr%F>-3e7}=^KAZDB)BIsrK=&0|zMgS%%BtuPYi={K1@u|4l*bf$gzJHiuPKr+SqBz`kHuba5A=DN(`{=M- zEm$I#Us4tD?u+{<7DqDc!v)kgv22x$ORd*YCCKCQl4BLvD93y1OfmT>wV$QdJEzr( z5-?)pY&y~9EYE3hZZ#E8vJBCwk;So+!B5L{cGZMOw68zzSD{s?<1>0=Qb8Y~MYE}f zNPm}j20O~Bao2SJ;pu7}aMqQyIQMU_b8R=5POX@q=?o!rOlXEUDR%dR(*$sMbGw9? z9B!a$3?1q<9AEvuI)s6y@5RDJKw%Tf3$?$fe&F8+U`B_@j_Xowm$NM6oHK20g$u`J zr%;(*p`&7uzo?%JAaxA#%@6ehyo!J!p#Kmhp!9I3CrPtufM5Vujzxyg4o!KU%{m0fhyT26k$pI@NLq~O1B_S`U0?3kZ zqY{0EM%Sr#hnDrd7k|F(voW6@umbLz7;~0}8FZe+kmtrt4kgasd7moauKQ>iTU8BM ze57#X>A5oGZm8;TBL7AYO?^4ZV=>wn#N5rG&r{IT7UNR<9TuM7I=uF~nEw|nL`Bem g1udF6{G@N-ziNpax(iIjZ~y=R07*qoM6N<$f)Kd^X8-^I literal 0 HcmV?d00001 diff --git a/devenv.bat b/devenv.bat new file mode 100644 index 0000000000..6ad780e8bc --- /dev/null +++ b/devenv.bat @@ -0,0 +1,87 @@ +@echo off +rem This batch script sets up the development environment +rem by enabling the Profiler API and starting Visual Studio. +rem Any process started by VS will inherit the environment variables, +rem enabling the profiler for apps run from VS, including while debugging. + +rem Set default values +set profiler_platform=x64 +set profiler_configuration=Debug +set start_visual_studio=true +set vs_sln_name=Datadog.Trace.sln + +:next_argument +set devenv_arg1=%1 + +if not "%devenv_arg1%" == "" ( + if /i "%devenv_arg1%" == "Debug" ( + set profiler_configuration=Debug + ) else if /i "%devenv_arg1%" == "Release" ( + set profiler_configuration=Release + ) else if /i "%devenv_arg1%" == "x64" ( + set profiler_platform=x64 + ) else if /i "%devenv_arg1%" == "x86" ( + set profiler_platform=x86 + ) else if /i "%devenv_arg1%" == "vs+" ( + set start_visual_studio=true + ) else if /i "%devenv_arg1%" == "vs-" ( + set start_visual_studio=false + ) else ( + echo Invalid option: "%devenv_arg1%". + goto show_usage + ) + + shift + goto next_argument +) + +echo Enabling profiler for "%profiler_configuration%/%profiler_platform%". + +rem Enable .NET Framework Profiling API +SET COR_ENABLE_PROFILING=1 +SET COR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8} +SET COR_PROFILER_PATH=%~dp0\src\Datadog.Trace.ClrProfiler.Native\bin\%profiler_configuration%\%profiler_platform%\Datadog.Trace.ClrProfiler.Native.dll + +rem Enable .NET Core Profiling API +SET CORECLR_ENABLE_PROFILING=1 +SET CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8} +SET CORECLR_PROFILER_PATH=%~dp0\src\Datadog.Trace.ClrProfiler.Native\bin\%profiler_configuration%\%profiler_platform%\Datadog.Trace.ClrProfiler.Native.dll + +rem Don't attach the profiler to these processes +SET DD_PROFILER_EXCLUDE_PROCESSES=devenv.exe;Microsoft.ServiceHub.Controller.exe;ServiceHub.Host.CLR.exe;ServiceHub.TestWindowStoreHost.exe;ServiceHub.DataWarehouseHost.exe;sqlservr.exe;VBCSCompiler.exe;iisexpresstray.exe;msvsmon.exe + +rem Set dotnet tracer home path +SET DD_DOTNET_TRACER_HOME=%~dp0 +SET DD_INTEGRATIONS=%DD_DOTNET_TRACER_HOME%\integrations.json + +if "%start_visual_studio%" == "true" ( + echo Starting Visual Studio... + + IF EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe" ( + START "Visual Studio" "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe" "%~dp0\%vs_sln_name%" + ) ELSE IF EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe" ( + START "Visual Studio" "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe" "%~dp0\%vs_sln_name%" + ) ELSE IF EXIST "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe" ( + START "Visual Studio" "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe" "%~dp0\%vs_sln_name%" + ) ELSE ( + START "Visual Studio" "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\Common7\IDE\devenv.exe" "%~dp0\%vs_sln_name%" + ) +) +goto end + +:show_usage +echo Usage: %0 [Release^|Debug] [x64^|x86] [vs+^|vs-] +echo All arguments are optional and can be provided in any order. +echo If an argument is provided multiple times, the last value wins. +echo The default configuration is "Release". +echo The default platform is "x64". +echo Visual Studio is started unless "vs-" is specified. + +:end +rem Clear temporary values +set profiler_platform= +set profiler_configuration= +set start_visual_studio= +set vs_sln_name= +set devenv_arg1= +set devenv_arg1_sub7= \ No newline at end of file diff --git a/docker/Datadog.Trace.ClrProfiler.Native.sh b/docker/Datadog.Trace.ClrProfiler.Native.sh new file mode 100755 index 0000000000..d2e7aa417b --- /dev/null +++ b/docker/Datadog.Trace.ClrProfiler.Native.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -euxo pipefail + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +cd "$DIR/.." + +PUBLISH_OUTPUT="$( pwd )/src/bin/managed-publish/netstandard2.0" + +cd src/Datadog.Trace.ClrProfiler.Native +mkdir -p obj/Debug/x64 +(cd obj/Debug/x64 && cmake ../../.. && make) + +mkdir -p bin/Debug/x64 +cp -f obj/Debug/x64/Datadog.Trace.ClrProfiler.Native.so bin/Debug/x64/Datadog.Trace.ClrProfiler.Native.so + +mkdir -p bin/Debug/x64/netstandard2.0 +cp -f $PUBLISH_OUTPUT/*.dll bin/Debug/x64/netstandard2.0/ diff --git a/docker/native.alpine.dockerfile b/docker/native.alpine.dockerfile new file mode 100644 index 0000000000..e2e6e06330 --- /dev/null +++ b/docker/native.alpine.dockerfile @@ -0,0 +1,19 @@ +FROM alpine:3.11 + +RUN apk update && apk upgrade + +RUN apk add --no-cache --update clang cmake git bash make alpine-sdk + +# libraries + +RUN mkdir -p /opt +ENV CXX=clang++ +ENV CC=clang-9 + +# - nlohmann/json +RUN cd /opt && git clone --depth 1 --branch v3.3.0 https://github.com/nlohmann/json.git +# RUN cd /opt/json && cmake -G Ninja . && cmake --build . + +# - re2 +RUN cd /opt && git clone --depth 1 --branch 2018-10-01 https://github.com/google/re2.git +RUN cd /opt/re2 && env CXXFLAGS="-O3 -g -fPIC" make \ No newline at end of file diff --git a/docker/native.dockerfile b/docker/native.dockerfile new file mode 100644 index 0000000000..b3485c753e --- /dev/null +++ b/docker/native.dockerfile @@ -0,0 +1,56 @@ +FROM ubuntu:14.04 + +RUN apt-get update && \ + apt-get install -y \ + git \ + wget + +RUN echo "deb http://llvm.org/apt/trusty/ llvm-toolchain-trusty-3.9 main" | sudo tee /etc/apt/sources.list.d/llvm.list +RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - +RUN sudo apt-get update + +RUN sudo apt-get install -y \ + cmake \ + llvm-3.9 \ + clang-3.9 \ + lldb-3.9 \ + liblldb-3.9-dev \ + libunwind8 \ + libunwind8-dev \ + gettext \ + libicu-dev \ + liblttng-ust-dev \ + libcurl4-openssl-dev \ + libssl-dev \ + libnuma-dev \ + libkrb5-dev + +RUN cd /usr/lib/llvm-3.9/lib && ln -s ../../x86_64-linux-gnu/liblldb-3.9.so.1 liblldb-3.9.so.1 + +RUN apt-get update && apt-get install -y \ + python-software-properties \ + software-properties-common + +RUN add-apt-repository ppa:ubuntu-toolchain-r/test && \ + apt-get update && \ + apt-get install -y \ + curl \ + ninja-build +# cmake +RUN apt-get remove -y cmake && \ + curl -o /tmp/cmake.sh https://cmake.org/files/v3.12/cmake-3.12.3-Linux-x86_64.sh && \ + sh /tmp/cmake.sh --prefix=/usr/local --exclude-subdir --skip-license + +# libraries + +RUN mkdir -p /opt +ENV CXX=clang++-3.9 +ENV CC=clang-3.9 + +# - nlohmann/json +RUN cd /opt && git clone --depth 1 --branch v3.3.0 https://github.com/nlohmann/json.git +# RUN cd /opt/json && cmake -G Ninja . && cmake --build . + +# - re2 +RUN cd /opt && git clone --depth 1 --branch 2018-10-01 https://github.com/google/re2.git +RUN cd /opt/re2 && env CXXFLAGS="-O3 -g -fPIC" make diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 0000000000..5096f6f6e1 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,29 @@ +# Datadog .NET Tracer (`dd-trace-dotnet`) Release Notes + +## [Release 1.10.0](https://github.com/DataDog/dd-trace-dotnet/releases/tag/v1.10.0) + +### New +- Add ASP.NET Core MVC 3 integration (#555) +- Add `IDbCommand` instrumentation to the ADO.NET integration (#562) + +### Fixed +- Fix `DD_LOGS_INJECTION` crash with the ASP.NET integration (#551) +- Fix scope creation failing in ASP.NET MVC integration when URL is empty (#553) +- Fix crash when Profiler and NuGet package versions do not match (#570) +- Add missing tags to GraphQL integration (#547) +- Get the instrumented type instead of using build-time `typeof()` in `HttpMessageHandler` integration (#558) + +### Builds and Tests +- Enable `Samples.MySql` test in CI (#548) +- Reduce permutations of minors in package versions tool (#545) +- Refactor "expectations" test framework (#554) +- Enable prerelease version tags (#556) +- Make timing and statistics tests less flaky (#559) +- Clean up `MockTraceAgent`, add event-based API (#501) +- Clean up project settings (#565) + +[All commits](https://github.com/DataDog/dd-trace-dotnet/compare/v1.9.0...v1.10.0) | [Full diff](https://github.com/DataDog/dd-trace-dotnet/compare/v1.9.0..v1.10.0) + +--- + +### Release notes for releases before 1.10.0 can be found in the [releases page](https://github.com/DataDog/dd-trace-dotnet/releases) on GitHub. \ No newline at end of file diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..c55065f9c8 --- /dev/null +++ b/docs/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at info@datadoghq.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq \ No newline at end of file diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 0000000000..9016a7907a --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,6 @@ +As an open source project we welcome contributions of many forms. Please reach out before starting +work on any major code changes. This will ensure we avoid duplicating work, or that +your code can't be merged due to a rapidly changing code base. If you would like support +for a library that is not listed, [contact support][1] to share a request. + +[1]: https://docs.datadoghq.com/help diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..03a77f4417 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,129 @@ +# .NET Tracer for Datadog APM + +## Installation and Usage + +Please [read our documentation](https://docs.datadoghq.com/tracing/setup/dotnet) for instructions on setting up .NET tracing and details about supported frameworks. + +## Downloads +Package|Download +-|- +Windows and Linux Installers|[See releases](https://github.com/DataDog/dd-trace-dotnet/releases) +`Datadog.Trace`|[![Datadog.Trace](https://img.shields.io/nuget/vpre/Datadog.Trace.svg)](https://www.nuget.org/packages/Datadog.Trace) +`Datadog.Trace.OpenTracing`|[![Datadog.Trace.OpenTracing](https://img.shields.io/nuget/vpre/Datadog.Trace.OpenTracing.svg)](https://www.nuget.org/packages/Datadog.Trace.OpenTracing) + +## Build Status on `master` + +Pipeline | Build Status +------------------|------------- +Unit tests | [![Build Status](https://dev.azure.com/datadog-apm/dd-trace-dotnet/_apis/build/status/unit-tests?branchName=master)](https://dev.azure.com/datadog-apm/dd-trace-dotnet/_build/latest?definitionId=28&branchName=master) +Integration tests | [![Build Status](https://dev.azure.com/datadog-apm/dd-trace-dotnet/_apis/build/status/integration-tests?branchName=master)](https://dev.azure.com/datadog-apm/dd-trace-dotnet/_build/latest?definitionId=27&branchName=master) + +# Development + +## Components + +**[Datadog Agent](https://github.com/DataDog/datadog-agent)**: A service that runs on your application servers, accepting trace data from the Datadog Tracer and sending it to Datadog. The Agent is not part of this repo; it's the same Agent to which all Datadog tracers (e.g. Go, Python, Java, Ruby) send data. + +**[Datadog .NET Tracer](https://github.com/DataDog/dd-trace-dotnet)**: This repository. A set of .NET libraries that let you trace any piece of your .NET code. Supports manual instrumentation and can automatically instrument supported libraries out-of-the-box. + +## Windows + +### Minimum requirements + +- [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) or newer + - Workloads + - Desktop development with C++ + - .NET desktop development + - .NET Core cross-platform development + - Optional: ASP.NET and web development (to build samples) + - Individual components + - .NET Framework 4.7 targeting pack +- [.NET Core 3.1 SDK](https://dotnet.microsoft.com/download/dotnet-core/3.1) +- Optional: [.NET Core 2.1 Runtime](https://dotnet.microsoft.com/download/dotnet-core/2.1) to test in .NET Core 2.1 locally. +- Optional: [.NET Core 3.0 Runtime](https://dotnet.microsoft.com/download/dotnet-core/3.0) to test in .NET Core 3.0 locally. +- Optional: [nuget.exe CLI](https://www.nuget.org/downloads) v5.3 or newer +- Optional: [WiX Toolset 3.11.1](http://wixtoolset.org/releases/) or newer to build Windows installer (msi) + - Requires .NET Framework 3.5 SP2 (install from Windows Features control panel: `OptionalFeatures.exe`) + - [WiX Toolset Visual Studio Extension](https://wixtoolset.org/releases/) to build installer from Visual Studio +- Optional: [Docker for Windows](https://docs.docker.com/docker-for-windows/) to build Linux binaries and run integration tests on Linux containers. See [section on Docker Compose](#building-and-running-tests-with-docker-compose). + - Requires Windows 10 (1607 Anniversary Update, Build 14393 or newer) + +Microsoft provides [evaluation developer VMs](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines) with Windows 10 and Visual Studio pre-installed. + +### Building from a command line + +From a _Developer Command Prompt for VS 2019_: + +```cmd +rem Restore NuGet packages +rem nuget.exe is required for command line restore because msbuild doesn't support packages.config +rem (see https://github.com/NuGet/Home/issues/7386) +nuget restore Datadog.Trace.sln + +rem Build C# projects (Platform: always AnyCPU) +msbuild Datadog.Trace.proj /t:BuildCsharp /p:Configuration=Release + +rem Build NuGet packages +dotnet pack src\Datadog.Trace\Datadog.Trace.csproj +dotnet pack src\Datadog.Trace.OpenTracing\Datadog.Trace.OpenTracing.csproj + +rem Build C++ projects +rem The native profiler depends on the Datadog.Trace.ClrProfiler.Managed.Loader C# project so be sure that is built first +msbuild Datadog.Trace.proj /t:BuildCpp /p:Configuration=Release;Platform=x64 +msbuild Datadog.Trace.proj /t:BuildCpp /p:Configuration=Release;Platform=x86 + +rem Build MSI installer for Windows x64 (supports both x64 and x86 apps) +msbuild Datadog.Trace.proj /t:msi /p:Configuration=Release;Platform=x64 + +rem Build MSI installer for Windows x86 (supports x86 apps only) +msbuild Datadog.Trace.proj /t:msi /p:Configuration=Release;Platform=x86 + +rem Build tracer home directory for Windows. +rem Valid values for property `Platform` are `x64`, `x86`, and `All`. +msbuild Datadog.Trace.proj /t:CreateHomeDirectory /p:Configuration=Release;Platform=All +``` + +## Linux + +### Minimum requirements + +To build C# projects and NuGet packages only +- [.NET Core SDK 3.1](https://dotnet.microsoft.com/download/dotnet-core/3.1) + +To build everything and run integration tests +- [Docker Compose](https://docs.docker.com/compose/install/) + +### Building and running tests with Docker Compose + +You can use [Docker Compose](https://docs.docker.com/compose/) with Linux containers to build Linux binaries and run the test suites. This works on both Linux and Windows hosts. + +```bash +# build C# projects +docker-compose run build + +# build C++ project +docker-compose run Profiler + +# run integration tests +docker-compose run IntegrationTests +``` + +## Further Reading + +Datadog APM +- [Datadog APM](https://docs.datadoghq.com/tracing/) +- [Datadog APM - Tracing .NET Applications](https://docs.datadoghq.com/tracing/setup/dotnet/) +- [Datadog APM - Advanced Usage](https://docs.datadoghq.com/tracing/advanced_usage/?tab=dotnet) + +Microsoft .NET Profiling APIs +- [Profiling API](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/profiling/) +- [Metadata API](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/metadata/) +- [The Book of the Runtime - Profiling](https://github.com/dotnet/coreclr/blob/master/Documentation/botr/profiling.md) + +OpenTracing +- [OpenTracing documentation](https://github.com/opentracing/opentracing-csharp) +- [OpenTracing terminology](https://github.com/opentracing/specification/blob/master/specification.md) + +## Get in touch + +If you have questions, feedback, or feature requests, reach our [support](https://docs.datadoghq.com/help). diff --git a/git-clean.cmd b/git-clean.cmd new file mode 100644 index 0000000000..3092bf2e1c --- /dev/null +++ b/git-clean.cmd @@ -0,0 +1 @@ +git clean -dxf -e *.user -e *.bat -e *.cmd -e packages/ -e .vs/ -e .vscode/ \ No newline at end of file diff --git a/integrations.json b/integrations.json new file mode 100644 index 0000000000..a920533505 --- /dev/null +++ b/integrations.json @@ -0,0 +1,2395 @@ +[ + { + "name": "AspNetMvc", + "method_replacements": [ + { + "caller": { + "assembly": "System.Web.Mvc" + }, + "target": { + "assembly": "System.Web.Mvc", + "type": "System.Web.Mvc.Async.IAsyncActionInvoker", + "method": "BeginInvokeAction", + "signature_types": [ + "System.IAsyncResult", + "System.Web.Mvc.ControllerContext", + "System.String", + "System.AsyncCallback", + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AspNetMvcIntegration", + "method": "BeginInvokeAction", + "signature": "00 08 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "System.Web.Mvc" + }, + "target": { + "assembly": "System.Web.Mvc", + "type": "System.Web.Mvc.Async.IAsyncActionInvoker", + "method": "EndInvokeAction", + "signature_types": [ + "System.Boolean", + "System.IAsyncResult" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AspNetMvcIntegration", + "method": "EndInvokeAction", + "signature": "00 05 02 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "AspNetWebApi2", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.Web.Http", + "type": "System.Web.Http.Controllers.IHttpController", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Web.Http.Controllers.HttpControllerContext", + "System.Threading.CancellationToken" + ], + "minimum_major": 5, + "minimum_minor": 1, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AspNetWebApi2Integration", + "method": "ExecuteAsync", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "DbCommand", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.Common.DbDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.Common.DbCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.DbCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "ElasticsearchNet5", + "method_replacements": [ + { + "caller": { + "assembly": "Elasticsearch.Net" + }, + "target": { + "assembly": "Elasticsearch.Net", + "type": "Elasticsearch.Net.IRequestPipeline", + "method": "CallElasticsearch", + "signature_types": [ + "Elasticsearch.Net.ElasticsearchResponse`1", + "Elasticsearch.Net.RequestData" + ], + "minimum_major": 5, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.ElasticsearchNet5Integration", + "method": "CallElasticsearch", + "signature": "10 01 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "Elasticsearch.Net" + }, + "target": { + "assembly": "Elasticsearch.Net", + "type": "Elasticsearch.Net.IRequestPipeline", + "method": "CallElasticsearchAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1>", + "Elasticsearch.Net.RequestData", + "System.Threading.CancellationToken" + ], + "minimum_major": 5, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.ElasticsearchNet5Integration", + "method": "CallElasticsearchAsync", + "signature": "10 01 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "ElasticsearchNet6", + "method_replacements": [ + { + "caller": { + "assembly": "Elasticsearch.Net" + }, + "target": { + "assembly": "Elasticsearch.Net", + "type": "Elasticsearch.Net.IRequestPipeline", + "method": "CallElasticsearch", + "signature_types": [ + "T", + "Elasticsearch.Net.RequestData" + ], + "minimum_major": 6, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 6, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.ElasticsearchNet6Integration", + "method": "CallElasticsearch", + "signature": "10 01 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "Elasticsearch.Net" + }, + "target": { + "assembly": "Elasticsearch.Net", + "type": "Elasticsearch.Net.IRequestPipeline", + "method": "CallElasticsearchAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "Elasticsearch.Net.RequestData", + "System.Threading.CancellationToken" + ], + "minimum_major": 6, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 6, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.ElasticsearchNet6Integration", + "method": "CallElasticsearchAsync", + "signature": "10 01 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "GraphQL", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "GraphQL", + "type": "GraphQL.Validation.IDocumentValidator", + "method": "Validate", + "signature_types": [ + "GraphQL.Validation.IValidationResult", + "System.String", + "GraphQL.Types.ISchema", + "GraphQL.Language.AST.Document", + "System.Collections.Generic.IEnumerable`1", + "_", + "GraphQL.Inputs" + ], + "minimum_major": 2, + "minimum_minor": 3, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.GraphQLIntegration", + "method": "Validate", + "signature": "00 0A 1C 1C 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "GraphQL", + "type": "GraphQL.Execution.IExecutionStrategy", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "GraphQL.Execution.ExecutionContext" + ], + "minimum_major": 2, + "minimum_minor": 3, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.GraphQLIntegration", + "method": "ExecuteAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "HttpMessageHandler", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.Net.Http", + "type": "System.Net.Http.HttpMessageHandler", + "method": "SendAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Net.Http.HttpRequestMessage", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.HttpMessageHandlerIntegration", + "method": "HttpMessageHandler_SendAsync", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Net.Http", + "type": "System.Net.Http.HttpClientHandler", + "method": "SendAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Net.Http.HttpRequestMessage", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.HttpMessageHandlerIntegration", + "method": "HttpClientHandler_SendAsync", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "IDbCommand", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.IDbCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.IDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.IDbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.IDbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.IDbCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.IDbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.Common", + "type": "System.Data.IDbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "netstandard", + "type": "System.Data.IDbCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 2, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.IDbCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "MongoDb", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "MongoDB.Driver.Core", + "type": "MongoDB.Driver.Core.WireProtocol.IWireProtocol", + "method": "Execute", + "signature_types": [ + "System.Void", + "MongoDB.Driver.Core.Connections.IConnection", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.MongoDbIntegration", + "method": "Execute", + "signature": "00 06 01 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "MongoDB.Driver.Core", + "type": "MongoDB.Driver.Core.WireProtocol.IWireProtocol`1", + "method": "Execute", + "signature_types": [ + "T", + "MongoDB.Driver.Core.Connections.IConnection", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.MongoDbIntegration", + "method": "ExecuteGeneric", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "MongoDB.Driver.Core", + "type": "MongoDB.Driver.Core.WireProtocol.IWireProtocol", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task", + "MongoDB.Driver.Core.Connections.IConnection", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 1, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.MongoDbIntegration", + "method": "ExecuteAsync", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "MongoDB.Driver.Core", + "type": "MongoDB.Driver.Core.WireProtocol.IWireProtocol`1", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "MongoDB.Driver.Core.Connections.IConnection", + "System.Threading.CancellationToken" + ], + "minimum_major": 2, + "minimum_minor": 1, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.MongoDbIntegration", + "method": "ExecuteAsyncGeneric", + "signature": "00 06 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "NpgsqlCommand", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "Npgsql.NpgsqlDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "Npgsql.NpgsqlDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteReaderAsyncWithBehaviorAndCancellation", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "Npgsql", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "Npgsql.NpgsqlCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.NpgsqlCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "ServiceStackRedis", + "method_replacements": [ + { + "caller": { + "assembly": "ServiceStack.Redis" + }, + "target": { + "assembly": "ServiceStack.Redis", + "type": "ServiceStack.Redis.RedisNativeClient", + "method": "SendReceive", + "signature_types": [ + "T", + "System.Byte[][]", + "System.Func`1", + "System.Action`1>", + "System.Boolean" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 5, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.ServiceStackRedisIntegration", + "method": "SendReceive", + "signature": "10 01 08 1E 00 1C 1D 1D 05 1C 1C 02 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "SqlCommand", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.SqlClient.SqlDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.SqlClient.SqlDataReader" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReader", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.SqlClient.SqlDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReader", + "signature_types": [ + "System.Data.SqlClient.SqlDataReader", + "System.Data.CommandBehavior" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReaderWithBehavior", + "signature": "00 05 1C 1C 08 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteReaderAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Data.CommandBehavior", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteReaderAsync", + "signature": "00 06 1C 1C 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteNonQuery", + "signature_types": [ + "System.Int32" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteNonQuery", + "signature": "00 04 08 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteNonQueryAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteNonQueryAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteScalar", + "signature_types": [ + "System.Object" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteScalar", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Data.SqlClient", + "type": "System.Data.SqlClient.SqlCommand", + "method": "ExecuteScalarAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "System.Threading.CancellationToken" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.AdoNet.SqlCommandIntegration", + "method": "ExecuteScalarAsync", + "signature": "00 05 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "StackExchangeRedis", + "method_replacements": [ + { + "caller": { + "assembly": "StackExchange.Redis" + }, + "target": { + "assembly": "StackExchange.Redis", + "type": "StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteSyncImpl", + "signature_types": [ + "T", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteSyncImpl", + "signature": "10 01 07 1E 00 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "StackExchange.Redis.StrongName" + }, + "target": { + "assembly": "StackExchange.Redis.StrongName", + "type": "StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteSyncImpl", + "signature_types": [ + "T", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteSyncImpl", + "signature": "10 01 07 1E 00 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "StackExchange.Redis" + }, + "target": { + "assembly": "StackExchange.Redis", + "type": "StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteAsyncImpl", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "System.Object", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteAsyncImpl", + "signature": "10 01 08 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "StackExchange.Redis.StrongName" + }, + "target": { + "assembly": "StackExchange.Redis.StrongName", + "type": "StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteAsyncImpl", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "System.Object", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.ConnectionMultiplexer", + "method": "ExecuteAsyncImpl", + "signature": "10 01 08 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "StackExchange.Redis" + }, + "target": { + "assembly": "StackExchange.Redis", + "type": "StackExchange.Redis.RedisBase", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.RedisBatch", + "method": "ExecuteAsync", + "signature": "10 01 07 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": { + "assembly": "StackExchange.Redis.StrongName" + }, + "target": { + "assembly": "StackExchange.Redis.StrongName", + "type": "StackExchange.Redis.RedisBase", + "method": "ExecuteAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "StackExchange.Redis.ServerEndPoint" + ], + "minimum_major": 1, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis.RedisBatch", + "method": "ExecuteAsync", + "signature": "10 01 07 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "Wcf", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System.ServiceModel", + "type": "System.ServiceModel.Dispatcher.ChannelHandler", + "method": "HandleRequest", + "signature_types": [ + "System.Boolean", + "System.ServiceModel.Channels.RequestContext", + "System.ServiceModel.OperationContext" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.WcfIntegration", + "method": "HandleRequest", + "signature": "00 06 02 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "WebRequest", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "System", + "type": "System.Net.WebRequest", + "method": "GetResponse", + "signature_types": [ + "System.Net.WebResponse" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.WebRequestIntegration", + "method": "GetResponse", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Net.Requests", + "type": "System.Net.WebRequest", + "method": "GetResponse", + "signature_types": [ + "System.Net.WebResponse" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.WebRequestIntegration", + "method": "GetResponse", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System", + "type": "System.Net.WebRequest", + "method": "GetResponseAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.WebRequestIntegration", + "method": "GetResponseAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "System.Net.Requests", + "type": "System.Net.WebRequest", + "method": "GetResponseAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 4, + "minimum_minor": 0, + "minimum_patch": 0, + "maximum_major": 4, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.WebRequestIntegration", + "method": "GetResponseAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + }, + { + "name": "XUnit", + "method_replacements": [ + { + "caller": {}, + "target": { + "assembly": "xunit.execution.dotnet", + "type": "Xunit.Sdk.TestInvoker`1", + "method": "RunAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestInvoker_RunAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.desktop", + "type": "Xunit.Sdk.TestInvoker`1", + "method": "RunAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestInvoker_RunAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.dotnet", + "type": "Xunit.Sdk.TestRunner`1", + "method": "RunAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestRunner_RunAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.desktop", + "type": "Xunit.Sdk.TestRunner`1", + "method": "RunAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestRunner_RunAsync", + "signature": "00 04 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.dotnet", + "type": "Xunit.Sdk.TestAssemblyRunner`1", + "method": "RunTestCollectionAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "Xunit.Sdk.IMessageBus", + "Xunit.Abstractions.ITestCollection", + "System.Collections.Generic.IEnumerable`1", + "System.Threading.CancellationTokenSource" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "AssemblyRunner_RunAsync", + "signature": "00 08 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.desktop", + "type": "Xunit.Sdk.TestAssemblyRunner`1", + "method": "RunTestCollectionAsync", + "signature_types": [ + "System.Threading.Tasks.Task`1", + "Xunit.Sdk.IMessageBus", + "Xunit.Abstractions.ITestCollection", + "System.Collections.Generic.IEnumerable`1", + "System.Threading.CancellationTokenSource" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "AssemblyRunner_RunAsync", + "signature": "00 08 1C 1C 1C 1C 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.dotnet", + "type": "Xunit.Sdk.TestOutputHelper", + "method": "QueueTestOutput", + "signature_types": [ + "System.Void", + "System.String" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestOutputHelper_QueueTestOutput", + "signature": "00 05 01 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + }, + { + "caller": {}, + "target": { + "assembly": "xunit.execution.desktop", + "type": "Xunit.Sdk.TestOutputHelper", + "method": "QueueTestOutput", + "signature_types": [ + "System.Void", + "System.String" + ], + "minimum_major": 2, + "minimum_minor": 2, + "minimum_patch": 0, + "maximum_major": 2, + "maximum_minor": 65535, + "maximum_patch": 65535 + }, + "wrapper": { + "assembly": "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb", + "type": "Datadog.Trace.ClrProfiler.Integrations.Testing.XUnitIntegration", + "method": "TestOutputHelper_QueueTestOutput", + "signature": "00 05 01 1C 1C 08 08 0A", + "action": "ReplaceTargetMethod" + } + } + ] + } +] \ No newline at end of file diff --git a/lib/coreclr/src/inc/CMakeLists.txt b/lib/coreclr/src/inc/CMakeLists.txt new file mode 100644 index 0000000000..c38d59587a --- /dev/null +++ b/lib/coreclr/src/inc/CMakeLists.txt @@ -0,0 +1,90 @@ +set( CORGUIDS_IDL_SOURCES + cordebug.idl + xcordebug.idl + clrdata.idl + clrinternal.idl + xclrdata.idl + corprof.idl + corpub.idl + mscorsvc.idl + clrprivappxhosting.idl + clrprivbinding.idl + clrprivhosting.idl + clrprivruntimebinders.idl + corsym.idl + sospriv.idl +) + +if(WIN32) +#Build for corguids is done in two steps: +#1. compile .idl to *_i.c : This is done using custom midl command +#2. compile *_i.c to .lib + +# Get the current list of definitions to pass to midl +get_compile_definitions(MIDL_DEFINITIONS) +get_include_directories(MIDL_INCLUDE_DIRECTORIES) + + +# Run custom midl command over each idl file +FIND_PROGRAM( MIDL midl.exe ) +foreach(GENERATE_IDL IN LISTS CORGUIDS_IDL_SOURCES) + get_filename_component(IDLNAME ${GENERATE_IDL} NAME_WE) + set(OUT_NAME ${CMAKE_CURRENT_BINARY_DIR}/idls_out/${IDLNAME}_i.c) + list(APPEND CORGUIDS_SOURCES ${OUT_NAME}) + add_custom_command(OUTPUT ${OUT_NAME} + COMMAND ${MIDL} ${MIDL_INCLUDE_DIRECTORIES} /h ${CMAKE_CURRENT_BINARY_DIR}/idls_out/${IDLNAME}.h ${MIDL_DEFINITIONS} /out ${CMAKE_CURRENT_BINARY_DIR}/idls_out ${CMAKE_CURRENT_SOURCE_DIR}/${GENERATE_IDL} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${GENERATE_IDL} + COMMENT "Compiling ${GENERATE_IDL}") +endforeach(GENERATE_IDL) + +set_source_files_properties(${CORGUIDS_SOURCES} + PROPERTIES GENERATED TRUE) + +# Compile *_i.c as C files +add_compile_options(/TC) + +else() + +#The MIDL tool exists for Windows only, so for other systems, we have the prebuilt xxx_i.cpp files checked in + +# The prebuilt files contain extra '!_MIDL_USE_GUIDDEF_' after the #endif, but not in the comment. +# In order to not to have to modify these prebuilt files, we disable the extra tokens warning. +if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") +add_compile_options(-Wno-extra-tokens) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +add_compile_options(-Wno-endif-labels) +endif() + +add_compile_options(-D_MIDL_USE_GUIDDEF_) +foreach(IDL_SOURCE IN LISTS CORGUIDS_IDL_SOURCES) + get_filename_component(IDLNAME ${IDL_SOURCE} NAME_WE) + set(C_SOURCE ../pal/prebuilt/idl/${IDLNAME}_i.cpp) + list(APPEND CORGUIDS_SOURCES ${C_SOURCE}) +endforeach(IDL_SOURCE) + +add_compile_options(-fPIC) +endif(WIN32) + +if(FEATURE_JIT_PITCHING) + add_definitions(-DFEATURE_JIT_PITCHING) +endif(FEATURE_JIT_PITCHING) + +# Compile *_i.cpp to lib +_add_library(corguids ${CORGUIDS_SOURCES}) + +# Binplace the inc files for packaging later. + +_install (FILES cfi.h + cor.h + cordebuginfo.h + coredistools.h + corhdr.h + corinfo.h + corjit.h + corjithost.h + opcode.def + openum.h + gcinfoencoder.h + gcinfotypes.h + DESTINATION inc) +_install (TARGETS corguids DESTINATION lib) diff --git a/lib/coreclr/src/inc/CrstTypeTool.cs b/lib/coreclr/src/inc/CrstTypeTool.cs new file mode 100644 index 0000000000..0310ec3fb1 --- /dev/null +++ b/lib/coreclr/src/inc/CrstTypeTool.cs @@ -0,0 +1,994 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// This tool exists to transform a high level description of Crst dependencies (i.e. which Crst type may be +// acquired before or after other Crst types) into a header file that defines a enum to describe each Crst +// type and tables that map type to numerical ranking and a string based name. +// +// To use the tool, run "csc.exe CrstTypeTool.cs" and run the resulting executable. +// +// The Crst type definition file is written in a very simple language. Comments begin with '//' and continue +// to the end of the line. All remaining tokens after comment removal are simply sequences of non-whitespace +// characters separated by whitespace. Keywords are case-insensitive and identifiers (which are always Crst +// type names) are case sensitive. The language grammar is given below in EBNF-like form: +// +// TopLevel ::= CrstDefinition* +// +// CrstDefinition ::= 'Crst' CrstDependency* 'End' +// +// CrstDependency ::= 'AcquiredBefore' * +// | 'AcquiredAfter' * +// | 'SameLevelAs' * +// | 'Unordered' +// +// Crst type names match the CrstType enums used in the source code minus the 'Crst' prefix. For example +// CrstAppDomainCache is written as 'AppDomainCache' in the .def file. +// +// The dependency "A 'AcquiredBefore' B" indicates that CrstA may be legally held while CrstB is acquired. +// Similarly "A 'AcquiredAfter' B" indicates that CrstA may be legally acquired while CrstB is held. "A +// 'AcquiredBefore' B" is logically equivalent to "B 'AcquiredAfter' A" and authors may enter the dependency +// is whichever seems to make the most sense to them (or add both rules if they so desire). +// +// 'Unordered' indicates that the Crst type does not participate in ranking (there should be very few Crsts +// like this and those that are know how to avoid or deal with deadlocks manually). +// +// 'SameLevelAs' indicates the given Crst type may be acquired alongside any number of instances of the Crst +// types indicated. "A 'SameLevel' B" automatically implies "B 'SameLevel' A" so it's not necessary to specify +// the dependency both ways though authors can do so if they wish. +// +// Simple validation of the .def file (over and above syntax checking) is performed by this tool prior to +// emitting the header file. This will catch logic errors such as referencing a Crst type that is not +// defined or using the 'Unordered' attribute along with any other attribute within a single definition. It +// will also catch cycles in the dependency graph (i.e. definitions that logically describe a system where the +// Crst types can't be ranked). +// + +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Text.RegularExpressions; + +// The main application class containing the program entry point. +class CrstTypeTool +{ + // A hash containing every Crst type defined by the input .def file along with its attributes. Keyed by + // Crst type name (which is case sensitive and doesn't include the 'Crst' enum prefix). + Dictionary m_crsts = new Dictionary(); + + // The program entry point. + public static int Main() + { + try + { + // Calculate the filenames of the input and output files. + string inputFile = "CrstTypes.def"; + string outputFile = "CrstTypes.h"; + + // A common error is to forget to check out the CrstTypes.h file first. Handle this case specially + // so we can give a good error message. + if (File.Exists(outputFile) && (File.GetAttributes(outputFile) & FileAttributes.ReadOnly) != 0) + { + Console.WriteLine(outputFile + " is read-only, you must check it out of TFS/SD first"); + return 2; + } + + // Create an instance of our application class to store state in (specifically the collection of + // Crst type definitions). + CrstTypeTool app = new CrstTypeTool(); + + // Create a parser for the CrstTypes.def file and run it over the input file (errors are signalled + // via exception, in common with all the following steps except validation). + new TypeFileParser().ParseFile(inputFile, app.m_crsts); + + // Validate the collection of Crst type definitions we built up during parsing for common logic + // errors and the presence of dependency cycles. False is returned from ValidateCrsts if an error + // was detected (an error message will have already been output to the console at this point). + if (!app.ValidateCrsts()) + return 3; + + // Perform a topological sort to map each Crst type to a numeric ranking. + app.LevelCrsts(); + + // Emit the new header file containing Crst type definitions and ranking information. + app.WriteHeaderFile(outputFile); + + // If we get here the transformation was successful; inform the user and we're done. + Console.WriteLine(outputFile + " successfully updated"); + return 0; + } + catch (TypeFileParser.ParseError pe) + { + // Syntax errors specific to parsing the input file. + Console.WriteLine("ParseError: " + pe.Message); + return 4; + } + catch (Exception e) + { + // Any other general errors (file I/O problems, out of memory etc.). + Console.WriteLine("Unexpected exception:"); + Console.WriteLine(e); + return 5; + } + } + + // Emit the CrstTypes.h output file. + void WriteHeaderFile(string fileName) + { + FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); + StreamWriter writer = new StreamWriter(stream); + + // Create a collection based on all the Crst types we've stored in the hash. We do this so we can sort + // the Crst types we emit (lexically, based on type name). + Dictionary.ValueCollection crstCollection = m_crsts.Values; + CrstType[] crsts = new CrstType[crstCollection.Count]; + crstCollection.CopyTo(crsts, 0); + Array.Sort(crsts); + + // Emit the header. Contains copyright information, the usual goop to avoid multiple inclusion and a + // header comment to discourage direct editing and point the user at the CrstTypes.def file instead + // (where all will be explained in greater detail). + writer.WriteLine("//"); + writer.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); + writer.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); + writer.WriteLine("// See the LICENSE file in the project root for more information."); + writer.WriteLine("//"); + writer.WriteLine(); + writer.WriteLine("#ifndef __CRST_TYPES_INCLUDED"); + writer.WriteLine("#define __CRST_TYPES_INCLUDED"); + writer.WriteLine(); + writer.WriteLine("// **** THIS IS AN AUTOMATICALLY GENERATED HEADER FILE -- DO NOT EDIT!!! ****"); + writer.WriteLine(); + writer.WriteLine("// This file describes the range of Crst types available and their mapping to a numeric level (used by the"); + writer.WriteLine("// runtime in debug mode to validate we're deadlock free). To modify these settings edit the"); + writer.WriteLine("// file:CrstTypes.def file and run the clr\\bin\\CrstTypeTool utility to generate a new version of this file."); + writer.WriteLine(); + + // Emit the CrstType enum to define a value for each crst type (along with the kNumberOfCrstTypes + // constant). + writer.WriteLine("// Each Crst type is declared as a value in the following CrstType enum."); + writer.WriteLine("enum CrstType"); + writer.WriteLine("{"); + for (int i = 0; i < crsts.Length; i++) + writer.WriteLine(" Crst" + crsts[i].Name + " = " + i.ToString() + ","); + writer.WriteLine(" kNumberOfCrstTypes = " + crsts.Length.ToString()); + writer.WriteLine("};"); + writer.WriteLine(); + + // This is the end of the regular part of the header included by most files. + writer.WriteLine("#endif // __CRST_TYPES_INCLUDED"); + writer.WriteLine(); + + // There is a second section of the header intended for inclusion only by vm\Crst.cpp. This contains + // some data tables used to map crst type to rank or name. We could instead define two separate + // headers, but on the whole it seems simpler to do it this way. + writer.WriteLine("// Define some debug data in one module only -- vm\\crst.cpp."); + writer.WriteLine("#if defined(__IN_CRST_CPP) && defined(_DEBUG)"); + writer.WriteLine(); + + // Emit the crst type to rank mapping table. + writer.WriteLine("// An array mapping CrstType to level."); + writer.WriteLine("int g_rgCrstLevelMap[] ="); + writer.WriteLine("{"); + foreach (CrstType crst in crsts) + { + string crstLine = " " + crst.Level + ","; + crstLine = crstLine + new string(' ', 16 - crstLine.Length); + writer.WriteLine(crstLine + "// Crst" + crst.Name); + } + writer.WriteLine("};"); + writer.WriteLine(); + + // Emit the crst type to name mapping table. + writer.WriteLine("// An array mapping CrstType to a stringized name."); + writer.WriteLine("LPCSTR g_rgCrstNameMap[] ="); + writer.WriteLine("{"); + foreach (CrstType crst in crsts) + writer.WriteLine(" \"Crst" + crst.Name + "\","); + writer.WriteLine("};"); + writer.WriteLine(); + + // Emit the constant Crst.cpp uses to record an unordered rank. + writer.WriteLine("// Define a special level constant for unordered locks."); + writer.WriteLine("#define CRSTUNORDERED (-1)"); + writer.WriteLine(); + + // Emit a couple of inline helpers to map type to rank or name (and validate the type while they're at + // it). + writer.WriteLine("// Define inline helpers to map Crst types to names and levels."); + writer.WriteLine("inline static int GetCrstLevel(CrstType crstType)"); + writer.WriteLine("{"); + writer.WriteLine(" LIMITED_METHOD_CONTRACT;"); + writer.WriteLine(" _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes);"); + writer.WriteLine(" return g_rgCrstLevelMap[crstType];"); + writer.WriteLine("}"); + writer.WriteLine("inline static LPCSTR GetCrstName(CrstType crstType)"); + writer.WriteLine("{"); + writer.WriteLine(" LIMITED_METHOD_CONTRACT;"); + writer.WriteLine(" _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes);"); + writer.WriteLine(" return g_rgCrstNameMap[crstType];"); + writer.WriteLine("}"); + writer.WriteLine(); + + // And that's the end of the second section of the header file. + writer.WriteLine("#endif // defined(__IN_CRST_CPP) && defined(_DEBUG)"); + + writer.Close(); + stream.Close(); + } + + // Peform checking of the Crst type definitions we've read just read. Various forms of logic error are + // scanned for including cycles in the dependency graph. Returns true if no errors are found. If false is + // returned a descriptive error message will have already been written to the console. + bool ValidateCrsts() + { + // Look at each Crst type definition in turn. + foreach (CrstType crst in m_crsts.Values) + { + // Catch Crst types that are referenced but never defined. + if (!crst.Defined) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is referenced without being defined", + crst.Name)); + return false; + } + + // Catch the use of the 'Unordered' attribute alongside the 'AcquiredBefore' attribute (which + // indicates an ordering). + if (crst.Level == CrstType.CrstUnordered && (crst.AcquiredBeforeList.Count > 0 || + crst.Group != null)) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and acquired before 'Crst{1}'", + crst.Name, crst.AcquiredBeforeList[0].Name)); + return false; + } + + // Catch the use of the 'Unordered' attribute alongside the 'SameLevelAs' attribute (which + // indicates an ordering). + if (crst.Level == CrstType.CrstUnordered && crst.Group != null) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and in the same level as another CrstType", + crst.Name)); + return false; + } + + // Catch the simple cycle where the Crst type depends on itself. + if (crst.AcquiredBeforeList.Contains(crst)) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as being acquired before itself", + crst.Name)); + return false; + } + + // Look for deeper cycles using a recursive algorithm in 'FindCycle()'. + List cycleList = new List(); + if (FindCycle(crst, crst, cycleList)) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", + crst.Name)); + foreach (CrstType cycleCrst in cycleList) + Console.WriteLine(String.Format(" Crst{0}", cycleCrst.Name)); + return false; + } + } + + // Perform normalization of each set of Crst types that are included in the same group (i.e. have a + // 'SameLevelAs' relationship). Normalization means that each Crst type in a group will have exactly + // the same set of dependency rules as all the others. + CrstTypeGroup.NormalizeAllRules(); + + // The normalization process could have introduced cycles in the dependency graph so run the cycle + // detection pass again. We do separate passes like this since normalizing can lead to less intuitive + // error messages if a cycle is found: so if the cycle exists before normalization takes place we want + // to generate an error message then. + foreach (CrstType crst in m_crsts.Values) + { + List cycleList = new List(); + if (FindCycle(crst, crst, cycleList)) + { + Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", + crst.Name)); + foreach (CrstType cycleCrst in cycleList) + Console.WriteLine(String.Format(" Crst{0}", cycleCrst)); + Console.WriteLine("Note that the cycle was detected only after 'SameLevelAs' processing was performed so some CrstType dependencies are implied by peer CrstTypes"); + return false; + } + } + + return true; + } + + // Recursively determine if a cycle exists in the Crst type dependency graph rooted at the 'rootCrst' + // type. The 'currCrst' indicates the next dependency to be examined (it will be the same as the + // 'rootCrst' when we're first called). The 'cycleList' argument contains a list of Crst types we've + // already examined in this branch of the algorithm and serves both to avoid checking the same node twice + // and to provide a list of the involved Crst types should a cycle be detected. + // Note that this algorithm is not designed to detect general cycles in the graph, only those that involve + // the 'rootCrst' directly. This is somewhat inefficient but gives us a simple way to generate clear error + // messages. + bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) + { + // Add the current Crst type to the list of those we've seen. + cycleList.Add(currCrst); + + // Look through all the dependencies of the current Crst type. + foreach (CrstType childCrst in currCrst.AcquiredBeforeList) + { + // If we find a reference back to the root Crst type then we've found a cycle. Start backing out + // from the recursion (keeping the list of nodes we visited intact) by returning true. + if (childCrst == rootCrst) + return true; + + // Otherwise iterate over the dependencies of the current node and for each one that we haven't + // already seen and recursively extend the search. + if (!cycleList.Contains(childCrst)) + if (FindCycle(rootCrst, childCrst, cycleList)) + return true; + } + + // Didn't find any cycles involving the root and this node; remove this node from the potential cycle + // list and return up to our caller indicating such. + cycleList.RemoveAt(cycleList.Count - 1); + + return false; + } + + // Topologically sort all the Crsts so we can assign a total ordering to them (in the form of a numeric + // ranking). Ranks start from 0 (Crst types that may be acquired at any time) and increment from there + // (Crst types that may only be acquired if a lower type is not already held). + // **** NOTE: The leveling process is destructive in that we will lose all dependency information from the + // Crst type definitions during the course of the algorithm. + void LevelCrsts() + { + // Note that Crst type dependency rules have been normalized (by the input parser) so that all + // AcquiredBefore/AcquiredAfter relationships have been reduced to AcquiredBefore relationships (i.e. + // any rule of the form "A AcquiredAfter B" has been converted to "B AcquiredBefore A". Any + // normalization makes the algorithm easier to program, but a normaliztion to AcquiredBefore + // relationships was chosen since it makes it particularly easy to implement an algorithm that assigns + // ranks beginning with zero and moving up to an arbitrary level. Any type that doesn't have any + // AcquiredBefore dependencies can always be ranked at a lower level than any remaining unranked types + // by definition and from this we can derive a simple iterative process to rank all the crst types. + + // Calculate how many Crst types we have left to rank (some are not included in this step because + // they've been marked as 'Unordered' in the input file). + int unsorted = 0; + foreach (CrstType crst in m_crsts.Values) + if (crst.Level == CrstType.CrstUnassigned) + unsorted++; + + // The ranking level we're going to assign to Crst types on the next pass of the algorithm. + int currLevel = 0; + + // Iterate while we still have Crst types left to rank. On each pass we'll assign a rank to those + // types that no longer have any dependencies forcing them to have a higher rank and then remove + // dependency rules involving those newly ranked types from the remaining types. + while (unsorted > 0) + { + // Record a flag indicating whether we manage to assign a rank to at least one Crst type on this + // pass. If we ever fail to do this we've hit a cycle (this is just paranoia, the Crst declaration + // validation performed in ValidateCrsts() should have detected such a cycle first). + bool madeProgress = false; + + // If we spot any types that are in a group (SameLevelAs relationship) then we defer assigning a + // rank till we've dealt with any non-group types (we wish to always place type groups in their + // very own rank else the Crst rank violation detection code won't detect violations between + // members of the group and singleton types that happened to be assigned rank on the same pass). + List deferredGroups = new List(); + + // Scan through all the Crst types. + foreach (CrstType crst in m_crsts.Values) + { + // Skip those types that already have a rank assigned. + if (crst.Level != CrstType.CrstUnassigned) + continue; + + // We're looking for Crst types that no longer have any types that can be acquired while they + // are already held. This indicates that it's safe to assign the current rank to them (since + // there are no remaining dependencies that need to be ranked first (i.e. with a lower rank + // value than this type). + if (crst.AcquiredBeforeList.Count == 0) + { + if (crst.Group == null) + { + // If this type is not part of the group we can go and assign the rank right away. + crst.Level = currLevel; + madeProgress = true; + unsorted--; + } + else if (!deferredGroups.Contains(crst.Group)) + // Otherwise we'll defer ranking this group member until all the singletons are + // processed. + deferredGroups.Add(crst.Group); + } + } + + // We've gone through the entire collection of Crst types and assigned the current rank level to + // any singleton Crst types that qualify. Now deal with any group members we detected (it's + // possible that more than one group qualifies for ranking at this level but we need to be careful + // to assign distinct rank values to each group to avoid hiding lock rank violations (since group + // members are always allowed to be acquired alongside any other type with the same rank value). + // Iterate over each distinct group that we found in this pass. + foreach (CrstTypeGroup group in deferredGroups) + { + // Look at our progress flag here. If it is false then we didn't have any singleton Crst types + // ranked at this level and we haven't processed any other groups at this level either. Thus + // we can rank this group at the current level. Otherwise at least one type was already ranked + // with this level so we need to increment to a new, distinct level to avoid ranking + // ambiguity. + if (madeProgress) + currLevel++; + + // Iterate through each Crst type that is a member of this group assigning them the (same) + // current rank. + foreach (CrstType crst in group.Members) + { + // Double check that each member has the same dependencies (i.e. they should all be empty + // by now). There should be no way that this error should ever occur, it's just paranoia + // on my part. + if (crst.AcquiredBeforeList.Count != 0) + throw new Exception("Internal error: SameLevel CrstTypes with differing rulesets"); + + crst.Level = currLevel; + unsorted--; + } + + // Once we've processed at least one group we've made progress this iteration. + madeProgress = true; + } + + // If we didn't manage to assign rank to at least one Crst type then we're not going to do any + // better next iteration either (because no state was updated in this iteration). This should only + // occur in the presence of a dependency cycle and we shouldn't get that here after a successful + // call to ValidateCrsts(), so this check is pure paranoia. + if (!madeProgress) + { + Console.WriteLine(String.Format("{0} unsorted remain", unsorted)); + throw new Exception("Cycle detected trying to assign level " + currLevel.ToString()); + } + + // Loop through all the unranked Crsts types and remove any AcquiredBefore relationships that + // involve types we've already leveled (since those types, by definition, have already been + // assigned a lower rank). + foreach (CrstType crst in m_crsts.Values) + { + if (crst.Level != CrstType.CrstUnassigned) + continue; + List prunedCrsts = crst.AcquiredBeforeList.FindAll(Unleveled); + crst.AcquiredBeforeList = prunedCrsts; + } + + // Done with this rank level, move to the next. + currLevel++; + } + } + + // Predicate method used with List.FindAll() to locate Crst types that haven't had their rank assigned + // yet. + static bool Unleveled(CrstType crst) + { + return crst.Level == CrstType.CrstUnassigned; + } +} + +// Class used to parse a CrstTypes.def file into a dictionary of Crst type definitions. It uses a simple lexer +// that removes comments then forms tokens out of any consecutive non-whitespace characters. An equally simple +// recursive descent parser forms Crst instances by parsing the token stream. +class TypeFileParser +{ + // Remember the input file name and the dictionary we're meant to populate. + string m_typeFileName; + Dictionary m_crsts; + + // Compile regular expressions for detecting comments and tokens in the parser input. + Regex m_commentRegex = new Regex(@"//.*"); + Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); + + // Input is lexed into an array of tokens. We record the index of the token being currently parsed. + Token[] m_tokens; + int m_currToken; + + // Parse the given file into Crst type definitions and place these definitions in the dictionary provided. + // Syntax errors are signalled via ParseError derived exceptions. + public void ParseFile(string typeFileName, Dictionary crsts) + { + m_typeFileName = typeFileName; + m_crsts = crsts; + + // Lex the file into tokens. + InitTokenStream(); + + // Parse the tokens according to the grammar set out at the top of this file. + // Loop until we have no further tokens to process. + while (!IsEof()) + { + // Grab the next token. + Token token = NextToken(); + + // We're at the top level, so the token had better be 'Crst'. + if (token.Id != KeywordId.Crst) + throw new UnexpectedTokenError(token, KeywordId.Crst); + + // OK, parse the rest of this single Crst type definition. + ParseCrst(); + } + } + + // Parse a single Crst type definition. + void ParseCrst() + { + // The next token had better be an identifier (the Crst type name). + Token token = NextToken(); + if (token.Id != KeywordId.Id) + throw new UnexpectedTokenError(token, KeywordId.Id); + + // The Crst instance might already exist in the dictionary (forward references to a Crst type cause + // these entries to auto-vivify). But in that case the entry better not be marked as 'Defined' which + // would indicate a double declaration. + CrstType crst; + if (m_crsts.ContainsKey(token.Text)) + { + crst = m_crsts[token.Text]; + if (crst.Defined) + throw new ParseError(String.Format("Duplicate definition for CrstType '{0}'", token.Text), token); + } + else + { + // Otherwise this Crst type hasn't been seen thus far so we allocate a new instance and add it to + // the dictionary. + crst = new CrstType(token.Text); + m_crsts.Add(crst.Name, crst); + } + + // We're defining, not just referencing this type. + crst.Defined = true; + + // Parse any attributes inside this definition (until we see an 'End' token). + bool parsingCrst = true; + while (parsingCrst) + { + // Get the next token. Either some attribute keyword or 'End'. + token = NextToken(); + List list; + + switch (token.Id) + { + + case KeywordId.AcquiredBefore: + // Simply parse the following list of Crst types into the current type's AcquiredBefore list. + ParseList(crst.AcquiredBeforeList); + break; + + case KeywordId.AcquiredAfter: + // AcquiredAfter is trickier. To make the ranking algorithm's life easier we actually + // normalize all rules to the AcquiredBefore form (see LevelCrsts() for the reasoning). So we + // capture the list of Crst types that follow the AcquiredAfter keyword and then append the + // current type to the AcquiredBefore list of each type found. + list = new List(); + ParseList(list); + foreach (CrstType priorCrst in list) + priorCrst.AcquiredBeforeList.Add(crst); + break; + + case KeywordId.SameLevelAs: + // Parse the following list of Crst types them let the CrstTypeGroup class handle the + // resulting updates to the type groups we're currently maintaining. See the comments for the + // CrstTypeGroup class for more details. + list = new List(); + ParseList(list); + foreach (CrstType sameLevelCrst in list) + CrstTypeGroup.Join(crst, sameLevelCrst); + break; + + case KeywordId.Unordered: + crst.Level = CrstType.CrstUnordered; + break; + + case KeywordId.End: + parsingCrst = false; + break; + + default: + throw new UnexpectedTokenError(token, + KeywordId.AcquiredBefore, + KeywordId.AcquiredAfter, + KeywordId.SameLevelAs, + KeywordId.Unordered); + } + } + } + + // Parse a list of Crst type names. Any other token terminates the list (without error and without + // consuming that token from the stream). The list of tokens is returned as a list of corresponding + // CrstTypes (which are auto-vivified in the output dictionary if they haven't been declared yet). + void ParseList(List list) + { + // Parse tokens until we find a non-indentifier. + while (true) + { + Token token = NextToken(); + if (token.Id != KeywordId.Id) + { + // We found the list terminator. Push the non-identifier token back into the stream for our + // caller to parse correctly. + UnwindToken(); + return; + } + + // Look up or add a new CrstType corresponding to this type name. + CrstType crst; + if (m_crsts.ContainsKey(token.Text)) + crst = m_crsts[token.Text]; + else + { + crst = new CrstType(token.Text); + m_crsts[crst.Name] = crst; + } + + // Add the type to the output list we're building. + list.Add(crst); + } + } + + // Lex the input file into an array of tokens. + void InitTokenStream() + { + StreamReader file = new StreamReader(m_typeFileName); + int lineNumber = 1; + List tokenList = new List(); + + // Read the file a line at a time. + string line; + while ((line = file.ReadLine()) != null) + { + // Remove comments from the current line. + line = m_commentRegex.Replace(line, ""); + + // Match all contiguous non-whitespace characters as individual tokens. + Match match = m_tokenRegex.Match(line); + if (match.Success) + { + // For each token captured build a token instance and record the token text and the file, line + // and column at which it was encountered (these latter in order to produce useful syntax + // error messages). + CaptureCollection cap = match.Groups[2].Captures; + for (int i = 0; i < cap.Count; i++) + tokenList.Add(new Token(m_typeFileName, cap[i].Value, lineNumber, cap[i].Index)); + } + + lineNumber++; + } + + // Record the list of tokens we captured as an array and reset the index of the next token to be + // handled by the parser. + m_tokens = tokenList.ToArray(); + m_currToken = 0; + } + + // Have we run out of tokens to parse? + bool IsEof() + { + return m_currToken >= m_tokens.Length; + } + + // Get the next token and throw an exception if we ran out. + Token NextToken() + { + if (m_currToken >= m_tokens.Length) + throw new UnexpectedEofError(); + return m_tokens[m_currToken++]; + } + + // Push the last token parsed back into the stream. + void UnwindToken() + { + if (m_currToken <= 0) + throw new InvalidOperationException(); + m_currToken--; + } + + // The various keywords we can encounter (plus Id for identifiers, which are currently always Crst type + // names). + internal enum KeywordId + { + Id, + Crst, + End, + AcquiredBefore, + AcquiredAfter, + Unordered, + SameLevelAs, + } + + // Class encapsulating a single token captured from the input file. + internal class Token + { + // Hash of keyword text to enum values. + static Dictionary s_keywords; + + // The characters comprising the text of the token from the input file. + string m_text; + + // Where the token was found (for error messages). + string m_file; + int m_line; + int m_column; + + // The ID of the keyword this token represents (or KeywordId.Id). + KeywordId m_id; + + // Static class initialization. + static Token() + { + // Populate the keyword hash. No sense building complex finite state machines to improve the + // efficiency of keyword lexing here since the input file (and keyword set) is never going to be + // big enough to justify the extra work. + s_keywords = new Dictionary(); + s_keywords.Add("crst", KeywordId.Crst); + s_keywords.Add("end", KeywordId.End); + s_keywords.Add("acquiredbefore", KeywordId.AcquiredBefore); + s_keywords.Add("acquiredafter", KeywordId.AcquiredAfter); + s_keywords.Add("unordered", KeywordId.Unordered); + s_keywords.Add("samelevelas", KeywordId.SameLevelAs); + } + + public Token(string file, string text, int line, int column) + { + m_file = file; + m_text = text; + m_line = line; + m_column = column; + + // Map token text to keyword ID. True keywords (not identifiers) are case insensitive so normalize + // the text to lower case before performing the keyword hash lookup. + string canonName = m_text.ToLower(); + if (s_keywords.ContainsKey(canonName)) + m_id = s_keywords[canonName]; + else + m_id = KeywordId.Id; + } + + public string Text {get { return m_text; }} + public string Location {get { return String.Format("{0} line {1}, column {2}", m_file, m_line, m_column); }} + public KeywordId Id {get { return m_id; }} + } + + // Base class for all syntax errors reported by the parser. + internal class ParseError : Exception + { + // A raw error message. + public ParseError(string message) + : base(message) + {} + + // An error message tagged with a file, line and column (coming from an error token). + public ParseError(string message, Token errorToken) + : base(String.Format("{0}: {1}", errorToken.Location, message)) + {} + + // Produce a textual name for the given keyword type. + protected static string IdToName(KeywordId id) + { + if (id == KeywordId.Id) + return "a CrstType name"; + return String.Format("'{0}'", id.ToString()); + } + } + + // Syntax error used when an unexpected token is encountered which further lists the valid tokens that + // would otherwise have been accepted. + internal class UnexpectedTokenError : ParseError + { + // Produce an unexpected token message with a file, line and column coming from an error token and + // optionally the names of zero or more tokens that would have been accepted. + public UnexpectedTokenError(Token errorToken, params KeywordId[] expected) + : base(FormatErrorMessage(errorToken, expected)) + {} + + static string FormatErrorMessage(Token errorToken, KeywordId[] expected) + { + StringBuilder message = new StringBuilder(String.Format("Unexpected token '{0}' at {1}", + errorToken.Text, errorToken.Location)); + if (expected.Length == 0) + { + } + else if (expected.Length == 1) + { + message.Append(String.Format("; expected {0}", IdToName(expected[0]))); + } + else + { + message.Append("; expected one of "); + for (int i = 0; i < expected.Length - 1; i++) + message.Append(String.Format("{0}, ", IdToName(expected[i]))); + message.Append(IdToName(expected[expected.Length - 1])); + + } + + return message.ToString(); + } + } + + // Syntax error used when we unexpectedly ran out of tokens. + internal class UnexpectedEofError : ParseError + { + public UnexpectedEofError() + : base("Unexpected end of file") + {} + } +} + +// This class represents an instance of a Crst type. These are unqiuely identified by case-sensitive name (the +// same as the enum name used in vm code, minus the 'Crst' prefix). +class CrstType : IComparable +{ + // Special level constants used to indicate unordered Crst types or those types we haven't gotten around + // to ranking yet. + public static readonly int CrstUnordered = -1; + public static readonly int CrstUnassigned = -2; + + // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. + string m_name; + + // The numeric ranking assigned to this type. Starts as CrstUnassigned and then becomes either + // CrstUnordered (while parsing the input file) or a number >= 0 (during LevelCrsts()). + int m_level; + + // List of Crst types that can be legally acquired while this one is held. (AcquiredAfter relationships + // are by switching the terms and adding to the second type's AcquiredBefore list). + List m_acquiredBeforeCrsts; + + // Either null if this Crst type is not in (or has not yet been determined to be in) a SameLevelAs + // relationship or points to a CrstTypeGroup that records all the sibling types at the same level (that + // have been discovered thus far during parsing). + CrstTypeGroup m_group; + + // Set once a definition for this type has been discovered. Used to detect double definitions and types + // referenced without definitions. + bool m_defined; + + public CrstType(string name) + { + m_name = name; + m_level = CrstUnassigned; + m_acquiredBeforeCrsts = new List(); + m_group = null; + m_defined = false; + } + + public string Name {get { return m_name; }} + public int Level {get { return m_level; } set { m_level = value; }} + public List AcquiredBeforeList {get { return m_acquiredBeforeCrsts; } set { m_acquiredBeforeCrsts = value; }} + public CrstTypeGroup Group {get { return m_group; } set { m_group = value; }} + public bool Defined {get {return m_defined; } set { m_defined = value; }} + + // Helper used to sort CrstTypes. The sort order is lexical based on the type name. + public int CompareTo(object other) + { + return m_name.CompareTo(((CrstType)other).m_name); + } +} + +// Every time a SameLevelAs relationship is used we need to be careful to keep track of the transitive closure +// of all types bound in the relationship. That's because such a relationship impacts the other dependency +// rules (each member of a SameLevelAs group must behave as though it has exactly the same dependency rules as +// all the others). Identifying all the members is tricky because "A SameLevelAs B" and "B SameLevelAs C" +// implies "A SameLevelAs C". So we use a separate tracking structure, instances of the CrstTypeGroup type, to +// do the bookkeeping for us. Each Crst type belongs to either zero or one CrstTypeGroups. As we find new +// SameLevelAs relationships we create new groups, add types to existing groups or merge groups (as previous +// distinct groups are merged by the discovery of a SameLevelAs relationship that links them). By the time +// parsing has finished we are guaranteed to have discovered all the distinct, disjoint groups and to have +// fully populated them with the transitive closure of all related types. We can them normalize all groups +// members so they share the same AcquiredBefore relationships. +class CrstTypeGroup +{ + // We record every group that has been formed so far. This makes normalizing all groups easier. + static List s_groups = new List(); + + // Crst types that are members of the current group. There are no duplicates in this list. + List m_members = new List(); + + // Declare a SameLevelAs relationship between the two Crst types given. Groups will be assigned, created + // or merged as required to maintain our guarantees (each CrstType is a member of at most one group and + // all CrstTypes involved in the same transitive closure of a SameLevelAs relationship are members of one + // group). + public static void Join(CrstType crst1, CrstType crst2) + { + CrstTypeGroup group; + + if (crst1 == crst2) + { + // In this case the type refers to itself. Create a singleton group for this type if it doesn't + // already exist. + if (crst1.Group == null) + { + group = new CrstTypeGroup(); + group.m_members.Add(crst1); + + s_groups.Add(group); + + crst1.Group = group; + } + } + else if (crst1.Group == null && crst2.Group == null) + { + // Neither types belong to a group already. So we can create a new one and add both types to it. + group = new CrstTypeGroup(); + group.m_members.Add(crst1); + group.m_members.Add(crst2); + + s_groups.Add(group); + + crst1.Group = group; + crst2.Group = group; + } + else if (crst1.Group == null) + { + // The first type doesn't belong to a group yet but the second does. So we can simply add the + // first type to the second group. + group = crst2.Group; + group.m_members.Add(crst1); + + crst1.Group = group; + } + else if (crst2.Group == null) + { + // As for the case above but the group/no-group positions are reversed. + group = crst1.Group; + group.m_members.Add(crst2); + + crst2.Group = group; + } + else if (crst1.Group != crst2.Group) + { + // Both types belong to different groups so we'll have to merge them. Add the members of group 2 + // to group 1 and throw away group 2. + group = crst1.Group; + CrstTypeGroup absorbGroup = crst2.Group; + foreach (CrstType crst in absorbGroup.m_members) + { + group.m_members.Add(crst); + crst.Group = group; + } + + s_groups.Remove(absorbGroup); + } + + // The only case left is when both types are already in the same group and there's no work needed in + // this case. + } + + // Normalize all the groups we created during parsing. See below for the definition of normalization. + public static void NormalizeAllRules() + { + foreach (CrstTypeGroup group in s_groups) + group.NormalizeRules(); + } + + // Normalize this group. This involves adjusting the AcquiredBefore list of each member to be the union of + // all such rules within the group. This step allows us to detect cycles in the dependency graph that + // would otherwise remain hidden if we only examined the unnormalized AcquiredBefore rules. + void NormalizeRules() + { + // This local will contain the union of all AcquiredBefore rules. + List acquiredBeforeList = new List(); + + // Iterate through each member of the group. + foreach (CrstType crst in m_members) + { + // Add each AcquiredBefore rule we haven't already seen to the union. + foreach (CrstType afterCrst in crst.AcquiredBeforeList) + if (!acquiredBeforeList.Contains(afterCrst)) + acquiredBeforeList.Add(afterCrst); + } + + // Reset each member's AcquiredBefore list to a copy of the union we calculated. Note it's important + // to make a (shallow) copy because the ranking process modifies this list and so a shared copy would + // cause unexpected results. + foreach (CrstType crst in m_members) + crst.AcquiredBeforeList = acquiredBeforeList.GetRange(0, acquiredBeforeList.Count); + } + + public List Members {get { return m_members; }} +} diff --git a/lib/coreclr/src/inc/CrstTypes.def b/lib/coreclr/src/inc/CrstTypes.def new file mode 100644 index 0000000000..4dce8f243a --- /dev/null +++ b/lib/coreclr/src/inc/CrstTypes.def @@ -0,0 +1,711 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// This file is used to describe the different types of Crst and their dependencies on other Crst types (in +// terms of which types may be legally held while others are acquired). +// +// The CrstTypeTool utility is used to parse this file, verify that there are no logical inconsistencies (such +// as a cycle in the dependencies) and generate an enum value and numerical ranking for each type. This +// ranking is used by the runtime (in checked builds) to verify that none of the rules described below are +// violated (which could lead to a deadlock). +// +// When you add a new Crst type you need to be aware of which Crst types may be already held when your Crst is +// acquired and which other types may be subsequently acquired. You can then add a Crst definition to this +// file and annotate it with those dependencies. Running CrstTypeTool will check to see if this introduces a +// potential deadlock problem and if everything checks out will generate a new version of +// file:CrstTypes.h (be sure to check this file out from TFS/SD before running CrstTypeTool). +// +// The format of this file is a very simple language. Comments are introduced with '//' and continue to the +// end of the line. Keywords are case insensitive (Crst type names, however, are case sensitive since they'll +// be translated directly to C++ enum values). Crst type names are used without the 'Crst' prefix used in C++ +// code (e.g. CrstAppDomainCache is referred to as AppDomainCache). The following words are reserved keywords +// and may not be used as the names of Crst types: +// Crst +// End +// AcquiredBefore +// AcquiredAfter +// Unordered +// SameLevelAs +// +// Each Crst type definition has the following format (where [] indicates optional and ... indicates zero or +// more repetitions): +// Crst +// [AcquiredBefore ...] +// [AcquiredAfter ...] +// [SameLevelAs ...] +// [Unordered] +// End +// +// For example: +// Crst Foo +// AcquiredBefore Bar +// AcquiredAfter Zob Baz +// SameLevelAs Foo +// End +// +// This introduces a new Crst type Foo (CrstFoo inside the runtime). This type may be legally acquired when +// the current thread holds Crst instances of type Zob, Bar or even other instances of Foo. While Foo is held +// it is legal to acquire Crsts of type Bar. Assuming that this definition does not introduce any dependency +// cycles, CrstTypeTool will assign a numeric rank to CrstFoo that maximizes the chance that any other Crst +// type interaction you didn't explicitly specify (e.g. holding Foo while taking a Crst of type Wibble) will +// generate a ranking violation assert in the checked build. +// +// Note that the following set of definitions: +// Crst A AcquiredBefore B End +// Crst B End +// +// Crst A End +// Crst B AcquiredAfter A End +// +// Crst A AcquiredBefore B End +// Crst B AcquiredAfter A End +// +// are all equivalent. You are free to use whichever variant seems clearest to you (CrstTypeTool will tell you +// if you introduce conflicting rules). Similarly "A SameLevelAs B" implies "B SameLevelAs A". The initial +// contents of this file uses AcquiredBefore in preference to AcquiredAfter purely because it was generated +// automatically by a profiling mechanism (the initial rules were seeded from observations of Crst usage while +// running our test suites). Feel free to add meaningful comments to existing rules if you feel they can +// usefully clarify the reasons for particular dependencies. +// +// See CrstTypeTool.cs for how to consume this file. +// +// Each Crst type definition is currently in alphabetical order. Please maintain this convention. +// + +Crst AllowedFiles + AcquiredBefore JumpStubCache UniqueStack +End + +Crst AppDomainCache + AcquiredBefore UniqueStack UnresolvedClassLock +End + +Crst AppDomainHandleTable + AcquiredBefore AvailableParamTypes HandleTable IbcProfile SyncBlockCache SystemDomainDelayedUnloadList + ThreadStore SystemDomain +End + +Crst ArgBasedStubCache +End + +Crst AssemblyIdentityCache +End + +Crst AssemblyLoader + AcquiredBefore DeadlockDetection UniqueStack +End + +Crst AvailableClass + AcquiredBefore LoaderHeap +End + +Crst AssemblyDependencyGraph +End + +Crst AvailableParamTypes + AcquiredBefore IbcProfile LoaderHeap +End + +Crst BaseDomain + AcquiredBefore LoaderHeap UniqueStack +End + +Crst CCompRC + Unordered +End + +Crst Cer + AcquiredBefore JumpStubCache UniqueStack +End + +Crst ClassFactInfoHash + AcquiredBefore SyncBlockCache ThreadStore +End + +Crst ClassInit + AcquiredBefore DeadlockDetection IbcProfile + SameLevelAs Jit +End + +Crst ClrNotification + Unordered +End + +Crst CrstCLRPrivBinderLocalWinMDPath +End + +Crst CLRPrivBinderMaps +End + +Crst CLRPrivBinderMapsAdd + AcquiredBefore CLRPrivBinderMaps +End + +Crst COMWrapperCache + AcquiredBefore HandleTable UniqueStack +End + +Crst ConnectionNameTable +End + +Crst Contexts + AcquiredBefore AvailableParamTypes Cer ClassInit DeadlockDetection DomainLocalBlock FuncPtrStubs + GlobalStrLiteralMap Jit LoaderHeap ModuleLookupTable RWLock SigConvert SingleUseLock + StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock +End + +Crst CoreCLRBinderLog + Unordered +End + +Crst CSPCache + AcquiredBefore JumpStubCache +End + +Crst DeadlockDetection +End + +Crst DebuggerController + // AcquiredBefore DebuggerHeapLock DebuggerJitInfo LoaderHeap + + // See bug: 581892. This has a conflict with CrstInstMethodHashTableRanking. + // The controller logic will be moved to OOP in V3, and so this lock will no longer be necessary. + // Fixing this in-proc would be difficult, and it would all be throwaway as we go oop. + Unordered +End + +// This is a leaf debugger lock. +Crst DebuggerFavorLock + AcquiredAfter DebuggerJitInfo DebuggerMutex +End + +// This is the lock used by the DebuggerHeapExecutableMemoryAllocator for allocating/freeing memory. +Crst DebuggerHeapExecMemLock +End + +// Debugger Heap lock is the smallest of the debugger locks. +Crst DebuggerHeapLock + AcquiredAfter DebuggerFavorLock DebuggerJitInfo DebuggerMutex + // Disabled per bug 581892 + // AcquiredAfter DebuggerController +End + +Crst DebuggerJitInfo + AcquiredBefore DebuggerHeapLock +End + +// This is the major debugger lock. +// It's the largest of the debugger locks. +Crst DebuggerMutex + AcquiredBefore AvailableParamTypes ConnectionNameTable + DynamicIL LoaderHeap ModuleLookupTable + + // Disabled per bug 581892 + // AcquiredBefore DebuggerController + AcquiredBefore DebuggerHeapLock DebuggerJitInfo + +End + +// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) +// and is released before taking any other lock except for CrstDataTest2 +Crst DataTest1 + AcquiredAfter DebuggerMutex +End + +// This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) +// and is released before taking any other lockCrst DataTest2 +Crst DataTest2 + AcquiredAfter DataTest1 +End + + +Crst DbgTransport +End + +Crst DelegateToFPtrHash +End + +Crst DomainLocalBlock + AcquiredBefore AppDomainHandleTable IbcProfile LoaderHeap SystemDomainDelayedUnloadList UniqueStack +End + +Crst DynamicIL +End + +Crst DynamicMT + AcquiredBefore IbcProfile +End + +Crst DynLinkZapItems + AcquiredBefore LoaderHeap +End + +Crst EventStore +End + +Crst Exception +End + +Crst ExecuteManLock + AcquiredBefore UniqueStack +End + +Crst ExecuteManRangeLock +End + +Crst FCall + AcquiredBefore LoaderHeap +End + +Crst RetThunkCache + AcquiredBefore LoaderHeap +End + +Crst FriendAccessCache + AcquiredBefore JumpStubCache UniqueStack +End + +Crst FuncPtrStubs + AcquiredBefore IbcProfile LoaderHeap UniqueStack CodeFragmentHeap JumpStubCache PatchEntryPoint +End + +Crst FusionAppCtx + AcquiredBefore PEImage +End + +Crst NativeBinderInit + Unordered +End + +Crst NativeImageCache + Unordered +End + +Crst GCCover + AcquiredBefore LoaderHeap ReJITDomainTable +End + +Crst GCMemoryPressure +End + +Crst GlobalStrLiteralMap + AcquiredBefore HandleTable IbcProfile SyncBlockCache SystemDomainDelayedUnloadList ThreadStore UniqueStack +End + +Crst HandleTable + SameLevelAs HandleTable +End + +Crst HostAssemblyMap +End + +Crst HostAssemblyMapAdd + AcquiredBefore HostAssemblyMap +End + +Crst IbcProfile +End + +Crst IJWFixupData + AcquiredBefore FuncPtrStubs IJWHash LoaderHeap +End + +Crst IJWHash +End + +Crst ILStubGen + AcquiredBefore DeadlockDetection UniqueStack +End + +Crst InstMethodHashTable + AcquiredBefore LoaderHeap UniqueStack JumpStubCache +End + +Crst InterfaceVTableMap +End + +Crst Interop + AcquiredBefore AppDomainHandleTable AvailableParamTypes Cer ClassInit DeadlockDetection DomainLocalBlock + HandleTable InstMethodHashTable InteropData JitGenericHandleCache LoaderHeap SigConvert + StubDispatchCache StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock +End + +Crst InteropData + AcquiredBefore LoaderHeap UniqueStack +End + +Crst IOThreadpoolWorker + AcquiredBefore ThreadIdDispenser ThreadStore +End + +Crst IsJMCMethod +End + +Crst ISymUnmanagedReader + AcquiredBefore PEImagePDBStream UniqueStack JumpStubCache +End + +Crst Jit + AcquiredBefore DeadlockDetection JumpStubCache + SameLevelAs ClassInit +End + +Crst JitGenericHandleCache +End + +Crst JitPerf + Unordered +End + +Crst JumpStubCache + AcquiredBefore ExecuteManRangeLock LoaderHeap SingleUseLock + AcquiredAfter AppDomainCache ExecuteManLock + ILStubGen ThreadpoolTimerQueue ThreadpoolWaitThreads + TPMethodTable TypeIDMap BaseDomain AssemblyLoader +End + +Crst ListLock + Unordered +End + +// Leaflock leveling, used for crsts that explicitly want to be a leaf lock +Crst LeafLock +End + +Crst LoaderAllocator + AcquiredBefore AppDomainHandleTable HandleTable UniqueStack ThreadStore + AcquiredAfter DomainLocalBlock +End + +Crst LoaderAllocatorReferences + AcquiredBefore LoaderAllocator + AcquiredAfter PendingTypeLoadEntry InstMethodHashTable +End + +Crst AssemblyList + AcquiredAfter LoaderAllocatorReferences ThreadStore AssemblyLoader +End + +Crst LoaderHeap +End + +Crst Mda +End + +Crst MetadataTracker + Unordered +End + +Crst StubCache + AcquiredBefore LoaderHeap +End + +Crst ModIntPairList +End + +Crst Module + AcquiredBefore LoaderHeap UniqueStack +End + +Crst ModuleFixup + AcquiredBefore AppDomainHandleTable GlobalStrLiteralMap IbcProfile SyncBlockCache +End + +Crst ModuleLookupTable + AcquiredBefore LoaderHeap +End + +Crst MUThunkHash +End + +Crst Nls +End + +Crst ObjectList + SameLevelAs ObjectList +End + +Crst OnEventManager +End + +Crst PatchEntryPoint +End + +Crst PEImage + AcquiredBefore UniqueStack +End + +Crst PEImagePDBStream +End + +Crst PendingTypeLoadEntry + AcquiredBefore AppDomainCache AppDomainHandleTable AssemblyLoader AvailableClass AvailableParamTypes + BaseDomain ClassInit DeadlockDetection DebuggerController DebuggerJitInfo DebuggerMutex + DomainLocalBlock DynLinkZapItems Exception ExecuteManRangeLock FuncPtrStubs + FusionAppCtx GlobalStrLiteralMap HandleTable IbcProfile + IJWFixupData IJWHash ISymUnmanagedReader Jit JumpStubCache LoaderHeap ModIntPairList + Module ModuleLookupTable PEImage SecurityStackwalkCache SharedAssemblyCreate + SigConvert SingleUseLock StubDispatchCache StubUnwindInfoHeapSegments + SyncBlockCache SystemDomain ThreadIdDispenser ThreadStore TypeIDMap UnresolvedClassLock + SameLevelAs PendingTypeLoadEntry +End + +Crst PinHandle +End + +// ProfilerGCRefDataFreeList synchronizes access to the profiler API's list of +// free, previously allocated structures that track moved references and +// root references during a GC. +Crst ProfilerGCRefDataFreeList +End + +// ProfilingAPIStatus serializes attempts to transition the global status +// from state to state, and access to the ProfilerDetachInfo structure +// between the thread executing DetachProfiler(), and the DetachThread +// carrying out the evacuation order. +Crst ProfilingAPIStatus +End + +Crst PublisherCertificate +End + +Crst RCWCache + AcquiredBefore IbcProfile LoaderHeap RCWCleanupList +End + +Crst RCWRefCache + AcquiredBefore HandleTable +End + +Crst RCWCleanupList +End + +Crst ReDacl +End + +Crst Reflection + AcquiredBefore LoaderHeap UnresolvedClassLock +End + +// Used to synchronize all rejit information stored in a given AppDomain. +Crst ReJITDomainTable + AcquiredBefore LoaderHeap SingleUseLock DeadlockDetection JumpStubCache DebuggerController FuncPtrStubs + AcquiredAfter ReJITGlobalRequest ThreadStore GlobalStrLiteralMap SystemDomain DebuggerMutex MethodDescBackpatchInfoTracker +End + +// Used to synchronize all global requests (which may span multiple AppDomains) which add +// new functions to rejit tables, or request Reverts on existing functions in the rejit +// tables. One of these crsts exist per runtime. +Crst ReJITGlobalRequest + AcquiredBefore ThreadStore ReJITDomainTable SystemDomain +End + +// ETW infrastructure uses this crst to protect a hash table of TypeHandles which is +// used to remember which types have been logged (to avoid duplicate logging of the +// same type). +Crst EtwTypeLogHash + AcquiredAfter ThreadStore AllowedFiles Cer TPMethodTable + AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController + DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile + JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilingAPIStatus + ProfilerGCRefDataFreeList RWLock SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList + ThreadIdDispenser ThreadStaticDataHashTable +End + +Crst Remoting + AcquiredBefore AppDomainHandleTable AvailableParamTypes Cer ClassInit DeadlockDetection DebuggerController + DebuggerHeapLock DebuggerJitInfo DebuggerMutex DomainLocalBlock ExecuteManRangeLock + FuncPtrStubs GlobalStrLiteralMap HandleTable InstMethodHashTable Jit JitGenericHandleCache + JumpStubCache LoaderHeap StubCache Module ModuleLookupTable SecurityStackwalkCache SigConvert + SingleUseLock StubUnwindInfoHeapSegments SyncBlockCache SystemDomainDelayedUnloadList + ThreadStore UnresolvedClassLock PendingTypeLoadEntry +End + +Crst RWLock +End + +Crst SavedExceptionInfo + AcquiredBefore DebuggerController +End + +Crst SaveModuleProfileData +End + +Crst SecurityStackwalkCache +End + +Crst SharedAssemblyCreate + AcquiredBefore DeadlockDetection UniqueStack +End + +Crst SigConvert + AcquiredBefore LoaderHeap +End + +Crst SingleUseLock + AcquiredBefore ExecuteManRangeLock LoaderHeap UniqueStack DebuggerJitInfo +End + +Crst UnwindInfoTableLock + AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock + AcquiredBefore StressLog +End + +Crst SpecialStatics +End + +Crst StressLog + Unordered +End + +Crst StrongName +End + +Crst CodeFragmentHeap + AcquiredBefore SingleUseLock +End + +Crst StubDispatchCache +End + +Crst StubUnwindInfoHeapSegments + AcquiredAfter StubCache +End + +Crst SyncBlockCache + AcquiredBefore ThreadIdDispenser +End + +Crst SyncHashLock +End + +Crst SystemBaseDomain + AcquiredBefore LoaderHeap UniqueStack +End + +Crst SystemDomain + AcquiredBefore DebuggerMutex HandleTable IbcProfile SaveModuleProfileData + ThreadIdDispenser ThreadStore +End + +Crst SystemDomainDelayedUnloadList +End + +Crst ThreadIdDispenser +End + +Crst ThreadpoolEventCache +End + +Crst ThreadpoolTimerQueue + AcquiredBefore UniqueStack +End + +Crst ThreadpoolWaitThreads + AcquiredBefore UniqueStack +End + +Crst ThreadpoolWorker + AcquiredBefore ThreadIdDispenser ThreadStore +End + +Crst ThreadStaticDataHashTable + AcquiredBefore SyncBlockCache +End + +Crst ThreadStore + AcquiredBefore AvailableParamTypes ConnectionNameTable DeadlockDetection DebuggerController + DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile + JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilingAPIStatus + ProfilerGCRefDataFreeList RWLock SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList + ThreadIdDispenser ThreadStaticDataHashTable DebuggerMutex +End + +Crst TPMethodTable + AcquiredBefore DebuggerHeapLock LoaderHeap UniqueStack AvailableParamTypes +End + +Crst TypeIDMap + AcquiredBefore UniqueStack +End + +Crst TypeEquivalenceMap + AcquiredBefore LoaderHeap +End + +Crst UMThunkHash +End + +Crst UniqueStack + AcquiredBefore LoaderHeap +End + +Crst UnresolvedClassLock + AcquiredBefore AvailableParamTypes DynLinkZapItems IbcProfile JumpStubCache +End + +Crst WrapperTemplate + AcquiredBefore IbcProfile +End + +Crst UMEntryThunkCache + AcquiredBefore LoaderHeap +End + +Crst PinnedByrefValidation +End + +Crst VSDIndirectionCellLock + AcquiredBefore LoaderHeap +End + +Crst MulticoreJitHash +End + +Crst MulticoreJitManager + AcquiredBefore MulticoreJitHash ThreadStore +End + +Crst WinRTFactoryCache + AcquiredBefore HandleTable +End + +Crst SqmManager +End + +Crst StackSampler +End + +Crst InlineTrackingMap + AcquiredBefore IbcProfile +End + +Crst JitInlineTrackingMap + AcquiredBefore ReJITDomainTable ThreadStore LoaderAllocator +End + +Crst EventPipe + AcquiredAfter PendingTypeLoadEntry + AcquiredBefore ThreadIdDispenser ThreadStore DomainLocalBlock InstMethodHashTable +End + +Crst NotifyGdb +End + +Crst ReadyToRunEntryPointToMethodDescMap + AcquiredBefore ExecuteManRangeLock UniqueStack +End + +Crst TieredCompilation + AcquiredBefore ThreadpoolTimerQueue +End + +Crst COMCallWrapper +End + +Crst MethodDescBackpatchInfoTracker + AcquiredBefore FuncPtrStubs ThreadStore SystemDomain + AcquiredAfter ReJITGlobalRequest +End diff --git a/lib/coreclr/src/inc/MSCOREE.IDL b/lib/coreclr/src/inc/MSCOREE.IDL new file mode 100644 index 0000000000..ce368f3f80 --- /dev/null +++ b/lib/coreclr/src/inc/MSCOREE.IDL @@ -0,0 +1,326 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +/************************************************************************************** + ** ** + ** Mscoree.idl - interface definitions for mscoree.dll ** + ** ** + **************************************************************************************/ + +cpp_quote("#define DECLARE_DEPRECATED ") +cpp_quote("#define DEPRECATED_CLR_STDAPI STDAPI") + +cpp_quote("") + +// +// Interface descriptions +// +import "unknwn.idl"; + +cpp_quote("struct IActivationFactory;") +interface IActivationFactory; + +cpp_quote("struct IHostControl;") +interface IHostControl; + +cpp_quote("struct ICLRControl;") +interface ICLRControl; + +// CLSID ComCallUnmarshal2 +cpp_quote("EXTERN_GUID(CLSID_ComCallUnmarshalV4, 0x45fb4600,0xe6e8,0x4928,0xb2,0x5e,0x50,0x47,0x6f,0xf7,0x94,0x25);") + +// IID ICLRRuntimeHost: uuid(90F1A06C-7712-4762-86B5-7A5EBA6BDB02) +cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);") + +// IID ICLRRuntimeHost2: uuid(712AB73F-2C22-4807-AD7E-F501D7B72C2D) +cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D);") + +// IID ICLRRuntimeHost4: uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF) +cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF);") + +#pragma midl_echo("typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk);") + +typedef HRESULT (__stdcall *FExecuteInAppDomainCallback) (void* cookie); + +// By default GC is concurrent and only the base system library is loaded into the domain-neutral area. +typedef enum { + STARTUP_CONCURRENT_GC = 0x1, + + STARTUP_LOADER_OPTIMIZATION_MASK = 0x3<<1, // loader optimization mask + STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = 0x1<<1, // no domain neutral loading + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = 0x2<<1, // all domain neutral loading + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = 0x3<<1, // strong name domain neutral loading + + + STARTUP_LOADER_SAFEMODE = 0x10, // Do not apply runtime version policy to the version passed in + STARTUP_LOADER_SETPREFERENCE = 0x100, // Set preferred runtime. Do not actally start it + + STARTUP_SERVER_GC = 0x1000, // Use server GC + STARTUP_HOARD_GC_VM = 0x2000, // GC keeps virtual address used + STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, // Disallow mixing hosting interface + STARTUP_LEGACY_IMPERSONATION = 0x10000, // Do not flow impersonation across async points by default + STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, // Don't eagerly commit thread stack + STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, // Force flow impersonation across async points + // (impersonations achieved thru p/invoke and managed will flow. + // default is to flow only managed impersonation) + STARTUP_TRIM_GC_COMMIT = 0x80000, // GC uses less committed space when system memory low + STARTUP_ETW = 0x100000, + STARTUP_ARM = 0x400000, // Enable the ARM feature. + STARTUP_SINGLE_APPDOMAIN = 0x800000, // application runs in default domain, no more domains are created + STARTUP_APPX_APP_MODEL = 0x1000000, // jupiter app + STARTUP_DISABLE_RANDOMIZED_STRING_HASHING = 0x2000000 // Disable the randomized string hashing (not supported) +} STARTUP_FLAGS; + +typedef enum +{ + APPDOMAIN_SECURITY_DEFAULT =0x0, + APPDOMAIN_SECURITY_SANDBOXED = 0x1, // appdomain is sandboxed + APPDOMAIN_SECURITY_FORBID_CROSSAD_REVERSE_PINVOKE = 0x2, // no cross ad reverse pinvokes + APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS = 0x4, // + APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS = 0x08, // do not pump messages during wait operations, do not call sync context + // When passed by the host, this flag will allow any assembly to perform PInvoke or COMInterop operations. + // Otherwise, by default, only platform assemblies can perform those operations. + APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, + + APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS = 0x40, + APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE = 0x80, + + APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT = 0x100, +} APPDOMAIN_SECURITY_FLAGS; + +typedef enum { + WAIT_MSGPUMP = 0x1, + WAIT_ALERTABLE = 0x2, + WAIT_NOTINDEADLOCK = 0x4 +}WAIT_OPTION; + +typedef enum ETaskType +{ + TT_DEBUGGERHELPER = 0x1, + TT_GC = 0x2, + TT_FINALIZER = 0x4, + TT_THREADPOOL_TIMER = 0x8, + TT_THREADPOOL_GATE = 0x10, + TT_THREADPOOL_WORKER = 0x20, + TT_THREADPOOL_IOCOMPLETION = 0x40, + TT_ADUNLOAD = 0x80, + TT_USER = 0x100, + TT_THREADPOOL_WAIT = 0x200, + + TT_UNKNOWN = 0x80000000, +} ETaskType; + +typedef enum { + // Default to minidump + DUMP_FLAVOR_Mini = 0, + + // Include critical CLR state + DUMP_FLAVOR_CriticalCLRState = 1, + + // Include critical CLR state and ngen images without including hosted heap + // It is host's responsibility to report hosted heap. + DUMP_FLAVOR_NonHeapCLRState = 2, + + DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini + +} ECustomDumpFlavor; + +const DWORD BucketParamsCount = 10; +const DWORD BucketParamLength = 255; + +// used for indexing into BucketParameters::pszParams +typedef enum +{ + Parameter1 = 0, + Parameter2, + Parameter3, + Parameter4, + Parameter5, + Parameter6, + Parameter7, + Parameter8, + Parameter9, + InvalidBucketParamIndex +} BucketParameterIndex; + +typedef struct _BucketParameters +{ + BOOL fInited; // Set to TRUE if the rest of this structure is valid. + WCHAR pszEventTypeName[BucketParamLength]; // Name of the event type. + WCHAR pszParams[BucketParamsCount][BucketParamLength]; // Parameter strings. +} BucketParameters; + + +typedef enum +{ + OPR_ThreadAbort, + OPR_ThreadRudeAbortInNonCriticalRegion, + OPR_ThreadRudeAbortInCriticalRegion, + OPR_AppDomainUnload, + OPR_AppDomainRudeUnload, + OPR_ProcessExit, + OPR_FinalizerRun, + MaxClrOperation + // Do not add anything after this +} EClrOperation; + +typedef enum +{ + FAIL_NonCriticalResource, + FAIL_CriticalResource, + FAIL_FatalRuntime, + FAIL_OrphanedLock, + FAIL_StackOverflow, + // In CoreCLR, we will treat AV specially, based upon the escalation policy. + // Currently only used in CoreCLR. + FAIL_AccessViolation, + FAIL_CodeContract, + MaxClrFailure + // Do not add anything after this +} EClrFailure; + +typedef enum +{ + eRuntimeDeterminedPolicy, // default + eHostDeterminedPolicy, // revert back to Everett behavior, i.e. swallow all exception +} EClrUnhandledException; + +typedef enum +{ + // !!! Please keep these ordered by severity + // !!! If you don't, you need to change EEPolicy::IsValidActionForOperation + // !!! and EEPolicy::IsValidActionForFailure + eNoAction, + eThrowException, + eAbortThread, + eRudeAbortThread, + eUnloadAppDomain, + eRudeUnloadAppDomain, + eExitProcess, + // Look at CorHost2::Stop. For eFastExitProcess, eRudeExitProcess, eDisableRuntime, + // Stop bypasses finalizer run. + eFastExitProcess, + eRudeExitProcess, + MaxPolicyAction +} EPolicyAction; + + +//***************************************************************************** +// New interface for hosting mscoree +//***************************************************************************** +[ + uuid(90F1A06C-7712-4762-86B5-7A5EBA6BDB02), + version(1.0), + helpstring("Common Language Runtime Hosting Interface"), + pointer_default(unique), + local +] +interface ICLRRuntimeHost : IUnknown +{ + // Starts the runtime. This is equivalent to CoInitializeCor(). + HRESULT Start(); + + // Terminates the runtime, This is equivalent CoUninitializeCor(); + HRESULT Stop(); + + // Returns an object for configuring runtime, e.g. threading, lock + // prior it starts. If the runtime has been initialized this + // routine returns an error. See IHostControl. + HRESULT SetHostControl([in] IHostControl* pHostControl); + + HRESULT GetCLRControl([out] ICLRControl** pCLRControl); + + HRESULT UnloadAppDomain([in] DWORD dwAppDomainId, + [in] BOOL fWaitUntilDone); + + HRESULT ExecuteInAppDomain([in] DWORD dwAppDomainId, + [in] FExecuteInAppDomainCallback pCallback, + [in] void* cookie); + + HRESULT GetCurrentAppDomainId([out] DWORD *pdwAppDomainId); + + HRESULT ExecuteApplication([in] LPCWSTR pwzAppFullName, + [in] DWORD dwManifestPaths, + [in] LPCWSTR *ppwzManifestPaths, // optional + [in] DWORD dwActivationData, + [in] LPCWSTR *ppwzActivationData, // optional + [out] int *pReturnValue); + + HRESULT ExecuteInDefaultAppDomain([in] LPCWSTR pwzAssemblyPath, + [in] LPCWSTR pwzTypeName, + [in] LPCWSTR pwzMethodName, + [in] LPCWSTR pwzArgument, + [out] DWORD *pReturnValue); +}; + +//***************************************************************************** +// New interface for hosting mscoree +//***************************************************************************** +[ + object, + uuid(712AB73F-2C22-4807-AD7E-F501D7B72C2D), + version(2.0), + helpstring("Common Language Runtime Hosting Interface"), + pointer_default(unique), + local +] +interface ICLRRuntimeHost2 : ICLRRuntimeHost +{ + // Creates an app domain (sandboxed or not) with the given manager class and the given + // set of properties. + HRESULT CreateAppDomainWithManager([in] LPCWSTR wszFriendlyName, + [in] DWORD dwFlags, + [in] LPCWSTR wszAppDomainManagerAssemblyName, + [in] LPCWSTR wszAppDomainManagerTypeName, + [in] int nProperties, + [in] LPCWSTR* pPropertyNames, + [in] LPCWSTR* pPropertyValues, + [out] DWORD* pAppDomainID); + + HRESULT CreateDelegate([in] DWORD appDomainID, + [in] LPCWSTR wszAssemblyName, + [in] LPCWSTR wszClassName, + [in] LPCWSTR wszMethodName, + [out] INT_PTR* fnPtr); + + // Authenticates a host based upon a key value. No longer required. + HRESULT Authenticate([in] ULONGLONG authKey); + + // Ensures CLR-set Mac (Mach) EH port is registered. + HRESULT RegisterMacEHPort(); + + HRESULT SetStartupFlags([in] STARTUP_FLAGS dwFlags); + + HRESULT DllGetActivationFactory([in] DWORD appDomainID, + [in] LPCWSTR wszTypeName, + [out] IActivationFactory ** factory); + + HRESULT ExecuteAssembly([in] DWORD dwAppDomainId, + [in] LPCWSTR pwzAssemblyPath, + [in] int argc, + [in] LPCWSTR* argv, + [out] DWORD *pReturnValue); + +}; + +[ + object, + uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF), + version(4.0), + helpstring("Common Language Runtime Hosting Interface"), + pointer_default(unique), + local +] +interface ICLRRuntimeHost4 : ICLRRuntimeHost2 +{ + HRESULT UnloadAppDomain2([in] DWORD dwAppDomainId, + [in] BOOL fWaitUntilDone, + [out] int *pLatchedExitCode); +}; + +cpp_quote("#undef DEPRECATED_CLR_STDAPI") +cpp_quote("#undef DECLARE_DEPRECATED") +cpp_quote("#undef DEPRECATED_CLR_API_MESG") diff --git a/lib/coreclr/src/inc/OpCodeGen.pl b/lib/coreclr/src/inc/OpCodeGen.pl new file mode 100644 index 0000000000..64ba130da4 --- /dev/null +++ b/lib/coreclr/src/inc/OpCodeGen.pl @@ -0,0 +1,483 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. +# +# OpCodeGen.pl +# +# PERL script used to generate the numbering of the reference opcodes +# +#use strict 'vars'; +#use strict 'subs'; +#use strict 'refs'; + + +my $ret = 0; +my %opcodeEnum; +my %oneByte; +my %twoByte; +my %controlFlow; +my @singleByteArg; +my %stackbehav; +my %opcodetype; +my %operandtype; +my %opcodes; +my $popstate; +my $pushstate; + +$ctrlflowcount = 0; + +$count = 0; + +my @lowercaseAlphabet = ('a'..'z','0'..'9'); +my %upcaseAlphabet = (); + +foreach $letter (@lowercaseAlphabet) { + $j = $letter; + $j=~tr/a-z/A-Z/; + $upcaseAlphabet{$letter}=$j; +} + +$license = "// Licensed to the .NET Foundation under one or more agreements.\n"; +$license .= "// The .NET Foundation licenses this file to you under the MIT license.\n"; +$license .= "// See the LICENSE file in the project root for more information.\n\n"; + +$startHeaderComment = "/*============================================================\n**\n"; +$endHeaderComment = "**\n** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n"; +$endHeaderComment .= "** See \$(RepoRoot)\\src\\inc\\OpCodeGen.pl for more information.**\n"; +$endHeaderComment .= "==============================================================*/\n\n"; + +$usingAndRefEmitNmsp = "namespace System.Reflection.Emit\n{\n\n"; +$obsoleteAttr = " [Obsolete(\"This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202\")]\n"; + +# Open source file and target files + +open (OPCODE, "opcode.def") or die "Couldn't open opcode.def: $!\n"; +open (OUTPUT, ">OpCodes.cs") or die "Couldn't open OpCodes.cs: $!\n"; +open (FCOUTPUT, ">FlowControl.cs") or die "Couldn't open FlowControl.cs: $!\n"; +open (SOUTPUT, ">StackBehaviour.cs") or die "Couldn't open StackBehaviour.cs: $!\n"; +open (OCOUTPUT, ">OpCodeType.cs") or die "Couldn't open OpCodeType.cs: $!\n"; +open (OPOUTPUT, ">OperandType.cs") or die "Couldn't open OperandType.cs: $!\n"; + +print OUTPUT $license; +print OUTPUT $startHeaderComment; +print OUTPUT "** Class: OpCodes\n"; +print OUTPUT "**\n"; +print OUTPUT "** Purpose: Exposes all of the IL instructions supported by the runtime.\n"; +print OUTPUT $endHeaderComment; + +print OUTPUT $usingAndRefEmitNmsp; + +print FCOUTPUT $license; +print FCOUTPUT $startHeaderComment; +print FCOUTPUT "** Enumeration: FlowControl\n"; +print FCOUTPUT "**\n"; +print FCOUTPUT "** Purpose: Exposes FlowControl Attribute of IL.\n"; +print FCOUTPUT $endHeaderComment; + +print FCOUTPUT $usingAndRefEmitNmsp; +print FCOUTPUT " public enum FlowControl\n {\n"; + +print SOUTPUT $license; +print SOUTPUT $startHeaderComment; +print SOUTPUT "** Enumeration: StackBehaviour\n"; +print SOUTPUT "**\n"; +print SOUTPUT "** Purpose: Exposes StackBehaviour Attribute of IL.\n"; +print SOUTPUT $endHeaderComment; + +print SOUTPUT $usingAndRefEmitNmsp; +print SOUTPUT " public enum StackBehaviour\n {\n"; + +print OCOUTPUT $license; +print OCOUTPUT $startHeaderComment; +print OCOUTPUT "** Enumeration: OpCodeType\n"; +print OCOUTPUT "**\n"; +print OCOUTPUT "** Purpose: Exposes OpCodeType Attribute of IL.\n"; +print OCOUTPUT $endHeaderComment; + +print OCOUTPUT $usingAndRefEmitNmsp; +print OCOUTPUT " public enum OpCodeType\n {\n"; + +print OPOUTPUT $license; +print OPOUTPUT $startHeaderComment; +print OPOUTPUT "** Enumeration: OperandType\n"; +print OPOUTPUT "**\n"; +print OPOUTPUT "** Purpose: Exposes OperandType Attribute of IL.\n"; +print OPOUTPUT $endHeaderComment; + +print OPOUTPUT $usingAndRefEmitNmsp; +print OPOUTPUT " public enum OperandType\n {\n"; + +while () +{ + # Process only OPDEF(....) lines + if (/OPDEF\(\s*/) + { + chop; # Strip off trailing CR + s/^OPDEF\(\s*//; # Strip off "OP(" + s/,\s*/,/g; # Remove whitespace + s/\).*$//; # Strip off ")" and everything behind it at end + + # Split the line up into its basic parts + ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/); + $s1 =~ s/0x//; + $s1 = hex($s1); + $s2 =~ s/0x//; + $s2 = hex($s2); + + if ($size == 0) + { + next; + } + + next if ($enumname =~ /UNUSED/); + + #Remove the prefix + $enumname=~s/CEE_//g; + + #Convert name to our casing convention + $enumname=~tr/A-Z/a-z/; + $enumname=~s/^(.)/\u$1/g; + $enumname=~s/_(.)/_\u$1/g; + + #Convert pop to our casing convention + $pop=~tr/A-Z/a-z/; + $pop=~s/^(.)/\u$1/g; + $pop=~s/_(.)/_\u$1/g; + + #Convert push to our casing convention + $push=~tr/A-Z/a-z/; + $push=~s/^(.)/\u$1/g; + $push=~s/_(.)/_\u$1/g; + + #Convert operand to our casing convention + #$operand=~tr/A-Z/a-z/; + #$operand=~s/^(.)/\u$1/g; + #$operand=~s/_(.)/_\u$1/g; + + #Remove the I prefix on type + $type=~s/I//g; + + #Convert Type to our casing convention + $type=~tr/A-Z/a-z/; + $type=~s/^(.)/\u$1/g; + $type=~s/_(.)/_\u$1/g; + + #Convert ctrl to our casing convention + $ctrl=~tr/A-Z/a-z/; + $ctrl=~s/^(.)/\u$1/g; + $ctrl=~s/_(.)/_\u$1/g; + + # Make a list of the flow Control type + + # Make a list of the opcodes and their values + if ($opcodes{$enumname}) + { + } + elsif ($size == 1) + { + $opcodes{$enumname} = $s2; + } + elsif ($size == 2) + { + $opcodes{$enumname} = ($s2 + 256 * $s1); + } + + #Make a list of the instructions which only take one-byte arguments + if ($enumname =~ /^.*_S$/) { + #but exclude the deprecated expressions (sometimes spelled "depricated") + if (!($enumname=~/^Depr.cated.*/)) { + my $caseStatement = sprintf(" case %-20s: \n", $enumname); + push(@singleByteArg, $caseStatement); + } + } + + #make a list of the control Flow Types + if ($controlFlow{$ctrl}) + { + #printf("DUPE Control Flow\n"); + } + else + { + $controlFlow{$ctrl} = $ctrlflowcount; + $ctrlflowcount++; + } + + $ctrlflowcount = 0; + #make a list of the StackBehaviour Types + $pop=~s/\+/_/g; + if ($stackbehav{$pop}) + { + #printf("DUPE stack behaviour pop\n"); + } + else + { + $stackbehav{$pop} = $ctrlflowcount; + $ctrlflowcount++; + } + + #make a list of the StackBehaviour Types + $push=~s/\+/_/g; + if ($stackbehav{$push}) + { + #printf("DUPE stack behaviour push\n"); + } + else + { + $stackbehav{$push} = $ctrlflowcount; + $ctrlflowcount++; + } + #make a list of operand types + if ($operandtype{$operand}) + { + #printf("DUPE operand type\n"); + } + else + { + $operandtype{$operand} = $ctrlflowcount; + $ctrlflowcount++; + } + + + #make a list of opcode types + if ($opcodetype{$type}) + { + #printf("DUPE opcode type\n"); + } + else + { + $opcodetype{$type} = $ctrlflowcount; + $ctrlflowcount++; + } + + my $opcodeName = $enumname; + + # Tailcall OpCode enum name does not comply with convention + # that all enum names are exactly the same as names in opcode.def + # file less leading CEE_ and changed casing convention + $enumname = substr $enumname, 0, 4 unless $enumname !~ m/Tailcall$/; + + # If string name ends with dot OpCode enum name ends with underscore + $enumname .= "_" unless $stringname !~ m/\."$/; + + printf(" OpCode name:%20s,\t\tEnum label:%20s,\t\tString name:%20s\n", $opcodeName, $enumname, $stringname); + if ($stringname eq "arglist") + { + print "This is arglist----------\n"; + } + + my $lineEnum; + if ($size == 1) + { + $lineEnum = sprintf(" %s = 0x%.2x,\n", $enumname, $s2); + $opcodeEnum{$s2} = $lineEnum; + } + elsif ($size == 2) + { + $lineEnum = sprintf(" %s = 0x%.4x,\n", $enumname, $s2 + 256 * $s1); + $opcodeEnum{$s2 + 256 * $s1} = $lineEnum; + } + + my $line; + $line = sprintf(" public static readonly OpCode %s = new OpCode(OpCodeValues.%s,\n", $opcodeName, $enumname); + $line .= sprintf(" ((int)OperandType.%s) |\n", $operand); + $line .= sprintf(" ((int)FlowControl.%s << OpCode.FlowControlShift) |\n", $ctrl); + $line .= sprintf(" ((int)OpCodeType.%s << OpCode.OpCodeTypeShift) |\n", $type); + $line .= sprintf(" ((int)StackBehaviour.%s << OpCode.StackBehaviourPopShift) |\n", $pop); + $line .= sprintf(" ((int)StackBehaviour.%s << OpCode.StackBehaviourPushShift) |\n", $push); + + $popstate = 0; + if($pop eq "Pop0" || $pop eq "Varpop") + { + $popstate = 0; + } + elsif ($pop eq "Pop1" || $pop eq "Popi" || $pop eq "Popref") + { + $popstate = $popstate -1; + } + elsif ($pop eq "Pop1_pop1" || $pop eq "Popi_pop1" || $pop eq "Popi_popi" || $pop eq "Popi_popi8" || $pop eq "Popi_popr4" || $pop eq "Popi_popr8" || $pop eq "Popref_pop1" || $pop eq "Popref_popi") + { + $popstate = $popstate -2; + } + elsif ($pop eq "Popi_popi_popi" || $pop eq "Popref_popi_popi" || $pop eq "Popref_popi_popi8" || $pop eq "Popref_popi_popr4" || $pop eq "Popref_popi_popr8" || $pop eq "Popref_popi_popref" || $pop eq "Popref_popi_pop1") + { + $popstate = $popstate -3; + } + + if ($push eq "Push1" || $push eq "Pushi" ||$push eq "Pushi8" ||$push eq "Pushr4" ||$push eq "Pushr8" ||$push eq "Pushref") + { + $popstate = $popstate + 1; + } + elsif($push eq "Push1_push1") + { + $popstate = $popstate + 2; + } + + $line .= sprintf(" (%s << OpCode.SizeShift) |\n", $size); + if ($ctrl =~ m/Return/ || $ctrl =~ m/^Branch/ || $ctrl =~ m/^Throw/ || $enumname =~ m/Jmp/){ + $line .= sprintf(" OpCode.EndsUncondJmpBlkFlag |\n", $size); + } + $line .= sprintf(" (%d << OpCode.StackChangeShift)\n", $popstate); + $line .= sprintf(" );\n\n"); + + if ($size == 1) + { + if ($oneByte{$s2}) + { + printf("Error opcode 0x%x already defined!\n", $s2); + print " Old = $oneByte{$s2}"; + print " New = $line"; + $ret = -1; + } + $oneByte{$s2} = $line; + } + elsif ($size == 2) + { + if ($twoByte{$s2}) + { + printf("Error opcode 0x%x%x already defined!\n", $s1, $s2); + print " Old = $oneByte{$s2}"; + print " New = $line"; + $ret = -1; + } + + $twoByte{$s2 + 256 * $s1} = $line; + } + else + { + $line .= "\n"; + push(@deprecated, $line); + printf("deprecated code!\n"); + } + $count++; + } +} + +# Generate the Flow Control enum +$ctrlflowcount = 0; +foreach $key (sort {$a cmp $b} keys (%controlFlow)) +{ + print FCOUTPUT " $key"; + print FCOUTPUT " = $ctrlflowcount,\n"; + $ctrlflowcount++; + if ($key =~ m/Next/){ + print FCOUTPUT $obsoleteAttr; + print FCOUTPUT " Phi"; + print FCOUTPUT " = $ctrlflowcount,\n"; + $ctrlflowcount++; + } +} +#end the flowcontrol enum +print FCOUTPUT " }\n}\n"; + +# Generate the StackBehaviour enum +$ctrlflowcount = 0; +foreach $key (sort {$a cmp $b} keys (%stackbehav)) +{ + if ($key !~ m/Popref_popi_pop1/){ + print SOUTPUT " $key"; + print SOUTPUT " = $ctrlflowcount,\n"; + $ctrlflowcount++; + } +} +print SOUTPUT " Popref_popi_pop1 = $ctrlflowcount,\n"; +#end the StackBehaviour enum +print SOUTPUT " }\n}\n"; + +# Generate OpCodeType enum +$ctrlflowcount = 0; +foreach $key (sort {$a cmp $b} keys (%opcodetype)) +{ + if ($ctrlflowcount == 0){ + print OCOUTPUT $obsoleteAttr; + print OCOUTPUT " Annotation = 0,\n"; + $ctrlflowcount++; + } + print OCOUTPUT " $key"; + print OCOUTPUT " = $ctrlflowcount,\n"; + $ctrlflowcount++; +} +# end the OpCodeType enum +print OCOUTPUT " }\n}\n"; + +# Generate OperandType enum +$ctrlflowcount = 0; +foreach $key (sort {$a cmp $b} keys (%operandtype)) +{ + print OPOUTPUT " $key"; + print OPOUTPUT " = $ctrlflowcount,\n"; + $ctrlflowcount++; + if ($key =~ m/InlineNone/){ + print OPOUTPUT $obsoleteAttr; + print OPOUTPUT " InlinePhi = 6,\n"; + $ctrlflowcount++; + } + if ($key =~ m/^InlineR$/){ + $ctrlflowcount++; + } +} +#end the OperandType enum +print OPOUTPUT " }\n}\n"; + +# Generate OpCodeValues internal enum +print OUTPUT " ///\n"; +print OUTPUT " /// Internal enum OpCodeValues for opcode values.\n"; +print OUTPUT " ///\n"; +print OUTPUT " ///\n"; +print OUTPUT " /// Note that the value names are used to construct publicly visible\n"; +print OUTPUT " /// ilasm-compatible opcode names, so their exact form is important!\n"; +print OUTPUT " ///\n"; +print OUTPUT " internal enum OpCodeValues\n"; +print OUTPUT " {\n"; + +foreach $opcodeValue (sort {$a <=> $b} keys(%opcodeEnum)) { + print OUTPUT $opcodeEnum{$opcodeValue}; +} + +# End generating OpCodeValues internal enum +print OUTPUT " }\n\n"; + + +# Generate public OpCodes class +print OUTPUT " /// \n"; +print OUTPUT " /// \n"; +print OUTPUT " /// The IL instruction opcodes supported by the runtime.\n"; +print OUTPUT " /// The Specification of IL Instruction describes each Opcode.\n"; +print OUTPUT " /// \n"; +print OUTPUT " /// \n"; +print OUTPUT " /// \n"; +print OUTPUT " public class OpCodes\n"; +print OUTPUT " {\n\n";; +print OUTPUT " private OpCodes()\n {\n }\n\n"; + +my $opcode; +my $lastOp = -1; +foreach $opcode (sort {$a <=> $b} keys(%oneByte)) { + printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); + print OUTPUT $oneByte{$opcode}; + $lastOp = $opcode; +} + +$lastOp = -1; +foreach $opcode (sort {$a <=> $b} keys(%twoByte)) { + printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); + print OUTPUT $twoByte{$opcode}; + $lastOp = $opcode; +} + +print OUTPUT "\n";; +print OUTPUT " public static bool TakesSingleByteArgument(OpCode inst)\n"; +print OUTPUT " {\n"; +print OUTPUT " switch (inst.OperandType)\n"; +print OUTPUT " {\n"; +print OUTPUT " case OperandType.ShortInlineBrTarget:\n"; +print OUTPUT " case OperandType.ShortInlineI:\n"; +print OUTPUT " case OperandType.ShortInlineVar:\n"; +print OUTPUT " return true;\n"; +print OUTPUT " }\n"; +print OUTPUT " return false;\n"; +print OUTPUT " }\n"; + +# End Generate public OpCodes class and close namespace +print OUTPUT " }\n}\n"; + +exit($ret); diff --git a/lib/coreclr/src/inc/allocacheck.h b/lib/coreclr/src/inc/allocacheck.h new file mode 100644 index 0000000000..3ba2e4da43 --- /dev/null +++ b/lib/coreclr/src/inc/allocacheck.h @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/*********************************************************************/ +/* AllocaCheck */ +/*********************************************************************/ + +/* check for alloca overruns (which otherwise are hard to track down + and often only repro on optimized builds). + + USAGE: + + void foo() { + ALLOCA_CHECK(); // Declare at function level scope + + .... + void* mem = ALLOCA(size); // does an alloca, + + } // destructor of ALLOCA_CHECK for buffer overruns. +*/ + +/* */ +/*********************************************************************/ + +#ifndef AllocaCheck_h +#define AllocaCheck_h +#include // for alloca itself + +#if defined(assert) && !defined(_ASSERTE) +#define _ASSERTE assert +#endif + +#if defined(_DEBUG) || defined(DEBUG) + +/*********************************************************************/ +class AllocaCheck { +public: + enum { CheckBytes = 0xCCCDCECF, + }; + + struct AllocaSentinal { + int check; + AllocaSentinal* next; + }; + +public: + /***************************************************/ + AllocaCheck() { + sentinals = 0; + } + + ~AllocaCheck() { + AllocaSentinal* ptr = sentinals; + while (ptr != 0) { + if (ptr->check != (int)CheckBytes) + _ASSERTE(!"alloca buffer overrun"); + ptr = ptr->next; + } + } + + void* add(void* allocaBuff, unsigned size) { + AllocaSentinal* newSentinal = (AllocaSentinal*) ((char*) allocaBuff + size); + newSentinal->check = CheckBytes; + newSentinal->next = sentinals; + sentinals = newSentinal; + memset(allocaBuff, 0xDD, size); + return allocaBuff; + } + +private: + AllocaSentinal* sentinals; +}; + +#define ALLOCA_CHECK() AllocaCheck __allocaChecker +#define ALLOCA(size) __allocaChecker.add(_alloca(size+sizeof(AllocaCheck::AllocaSentinal)), size); + +#else + +#define ALLOCA_CHECK() +#define ALLOCA(size) _alloca(size) + +#endif + +#endif diff --git a/lib/coreclr/src/inc/apithreadstress.cpp b/lib/coreclr/src/inc/apithreadstress.cpp new file mode 100644 index 0000000000..0a802a2f11 --- /dev/null +++ b/lib/coreclr/src/inc/apithreadstress.cpp @@ -0,0 +1,171 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// --------------------------------------------------------------------------- +// APIThreadStress.cpp (API thread stresser) +// --------------------------------------------------------------------------- + +#include "stdafx.h" + +#ifdef _DEBUG +#define LOGGING 1 +#endif + +#include "apithreadstress.h" +#include "clrhost.h" +#include "ex.h" +#include "log.h" + + + +// For now, thread stress is incompatible with hosting. We need a host CreateThread +// to fix this. +#undef SetEvent +#undef ResetEvent + +int APIThreadStress::s_threadStressCount = 0; + +APIThreadStress::APIThreadStress() +{ + m_threadCount = 0; + + // Don't "fork" stress threads + if (ClrFlsGetValue(TlsIdx_StressThread) == NULL) + m_threadCount = s_threadStressCount; + + if (m_threadCount != 0) + { + m_setupOK = TRUE; + + m_hThreadArray = new (nothrow) HANDLE [ m_threadCount ]; + if (m_hThreadArray == NULL) + m_setupOK = FALSE; + else + { + HANDLE *p = m_hThreadArray; + HANDLE *pEnd = p + m_threadCount; + + while (p < pEnd) + { + DWORD id; + *p = ::CreateThread(NULL, 0, StartThread, this, 0, &id); + if (*p == NULL) + m_setupOK = FALSE; + p++; + } + } + + m_syncEvent = ClrCreateManualEvent(FALSE); + if (m_syncEvent == INVALID_HANDLE_VALUE) + m_setupOK = FALSE; + } +} + +APIThreadStress::~APIThreadStress() +{ + if (m_threadCount > 0) + { + HANDLE *p = m_hThreadArray; + HANDLE *pEnd = p + m_threadCount; + + if (p != NULL) + { + while (p < pEnd) + { + if (*p != NULL) + { + if (m_threadCount > 0 && m_setupOK) + WaitForSingleObjectEx(*p, INFINITE, FALSE); + + ::CloseHandle(*p); + } + p++; + } + delete [] m_hThreadArray; + } + + if (m_syncEvent != INVALID_HANDLE_VALUE) + CloseHandle(m_syncEvent); + } +} + +void APIThreadStress::SetThreadStressCount(int threadCount) +{ + s_threadStressCount = threadCount; +} + + +DWORD WINAPI APIThreadStress::StartThread(void *arg) +{ + APIThreadStress *pThis = (APIThreadStress *) arg; + + ClrFlsSetValue(TlsIdx_StressThread, pThis); + + EX_TRY + { + // Perform initial synchronization + WaitForSingleObjectEx(pThis->m_syncEvent, INFINITE, FALSE); + InterlockedIncrement(&pThis->m_runCount); + + LOG((LF_SYNC, LL_INFO100, "Stressing operation on thread %d\n", GetCurrentThreadId())); + ((APIThreadStress *)arg)->Invoke(); + LOG((LF_SYNC, LL_INFO100, "End stress operation on thread %d\n", GetCurrentThreadId())); + + if (InterlockedDecrement(&pThis->m_runCount) == 0) + ::SetEvent(pThis->m_syncEvent); + } + EX_CATCH + { + LOG((LF_SYNC, LL_ERROR, "Exception during stress operation on thread %d\n", GetCurrentThreadId())); + } + EX_END_CATCH(SwallowAllExceptions); + + return 0; +} + +BOOL APIThreadStress::DoThreadStress() +{ + if (m_threadCount > 0 && m_setupOK) + { + HANDLE *p = m_hThreadArray; + HANDLE *pEnd = p + m_threadCount; + + while (p < pEnd) + { + ::ResumeThread(*p); + p++; + } + + // Start the threads at the same time + ::SetEvent(m_syncEvent); + + return TRUE; + } + else + { + SyncThreadStress(); + return FALSE; + } +} + +void APIThreadStress::SyncThreadStress() +{ + APIThreadStress *pThis = (APIThreadStress *) ClrFlsGetValue(TlsIdx_StressThread); + + if (pThis != NULL) + { + LOG((LF_SYNC, LL_INFO1000, "Syncing stress operation on thread %d\n", GetCurrentThreadId())); + + ::ResetEvent(pThis->m_syncEvent); + + if (InterlockedDecrement(&pThis->m_runCount) == 0) + ::SetEvent(pThis->m_syncEvent); + else + WaitForSingleObjectEx(pThis->m_syncEvent, INFINITE, FALSE); + InterlockedIncrement(&pThis->m_runCount); + + LOG((LF_SYNC, LL_INFO1000, "Resuming stress operation on thread %d\n", GetCurrentThreadId())); + } +} + diff --git a/lib/coreclr/src/inc/apithreadstress.h b/lib/coreclr/src/inc/apithreadstress.h new file mode 100644 index 0000000000..a0c6cdeb0b --- /dev/null +++ b/lib/coreclr/src/inc/apithreadstress.h @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// APIThreadStress.h (API thread stresser) +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// This class provides a simple base to wrap "thread stress" logic around an API, +// which will (in thread stress mode) cause an API to "fork" onto many threads +// executing the same operation simulatenously. This can help to expose race +// conditions. +// +// Usage: +// +// First, subtype APIThreadStress and override Invoke to implement the operation. +// You will likely need to add data members for the arguments. +// +// Next, inside the API, write code like this: +// +// void MyRoutine(int a1, void *a2) +// { +// class stress : APIThreadStress +// { +// int a1; +// void *a2; +// stress(int a1, void *a2) : a1(a1), a2(a2) +// { DoThreadStress(); } +// void Invoke() { MyRoutine(a1, a2); } +// } ts (a1, a2); +// +// // implementation +// +// // perhaps we have a common sub-point in the routine where we want the threads to +// // queue up and race again +// +// ts.SyncThreadStress(); +// +// // more implementation +// } +// --------------------------------------------------------------------------- + + +#ifndef _APITHREADSTRESS_H_ +#define _APITHREADSTRESS_H_ + +#include "utilcode.h" + +class APIThreadStress +{ + public: + BOOL DoThreadStress() { return FALSE; } + static void SyncThreadStress() { } + static void SetThreadStressCount(int count) { } +}; + +#endif // _APITHREADSTRESS_H_ diff --git a/lib/coreclr/src/inc/appxutil.h b/lib/coreclr/src/inc/appxutil.h new file mode 100644 index 0000000000..411c18b695 --- /dev/null +++ b/lib/coreclr/src/inc/appxutil.h @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + + +#pragma once + +#ifdef FEATURE_APPX + +#include "clrtypes.h" +#include "appmodel.h" + +#define PACKAGE_FILTER_CLR_DEFAULT (PACKAGE_FILTER_HEAD|PACKAGE_FILTER_DIRECT) + + +typedef PACKAGE_INFO * PPACKAGE_INFO; +typedef PACKAGE_INFO const * PCPACKAGE_INFO; + +//--------------------------------------------------------------------------------------------- +// Forward declarations +template +class NewArrayHolder; +BOOL WinRTSupported(); + + +namespace AppX +{ + // Returns true if process is immersive (or if running in mockup environment). + bool IsAppXProcess(); + + // On CoreCLR, the host is in charge of determining whether the process is AppX or not. + void SetIsAppXProcess(bool); + +#ifdef DACCESS_COMPILE + bool DacIsAppXProcess(); +#endif // DACCESS_COMPILE +}; + + +#else // FEATURE_APPX + +namespace AppX +{ + inline bool IsAppXProcess() + { + return false; + } +} + +#endif // FEATURE_APPX diff --git a/lib/coreclr/src/inc/arrayholder.h b/lib/coreclr/src/inc/arrayholder.h new file mode 100644 index 0000000000..681014fc95 --- /dev/null +++ b/lib/coreclr/src/inc/arrayholder.h @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +template +class ArrayHolder +{ +public: + ArrayHolder(T *ptr) + : m_ptr(ptr) + { + } + + ~ArrayHolder() + { + Clear(); + } + + ArrayHolder(const ArrayHolder &rhs) + { + m_ptr = const_cast(&rhs)->Detach(); + } + + ArrayHolder &operator=(T *ptr) + { + Clear(); + m_ptr = ptr; + return *this; + } + + const T &operator[](int i) const + { + return m_ptr[i]; + } + + T &operator[](int i) + { + return m_ptr[i]; + } + + operator const T *() const + { + return m_ptr; + } + + operator T *() + { + return m_ptr; + } + + T **operator&() + { + return &m_ptr; + } + + T *GetPtr() + { + return m_ptr; + } + + T *Detach() + { + T *ret = m_ptr; + m_ptr = NULL; + return ret; + } + +private: + void Clear() + { + if (m_ptr) + { + delete [] m_ptr; + m_ptr = NULL; + } + } + +private: + T *m_ptr; +}; diff --git a/lib/coreclr/src/inc/arraylist.h b/lib/coreclr/src/inc/arraylist.h new file mode 100644 index 0000000000..b8c149f8eb --- /dev/null +++ b/lib/coreclr/src/inc/arraylist.h @@ -0,0 +1,296 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef ARRAYLIST_H_ +#define ARRAYLIST_H_ + +#include +#include +#include // offsetof + +// +// ArrayList is a simple class which is used to contain a growable +// list of pointers, stored in chunks. Modification is by appending +// only currently. Access is by index (efficient if the number of +// elements stays small) and iteration (efficient in all cases). +// +// An important property of an ArrayList is that the list remains +// coherent while it is being modified. This means that readers +// never need to lock when accessing it. +// + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4200) // Disable zero-sized array warning +#endif + +class ArrayListBase +{ + public: + + enum + { + ARRAY_BLOCK_SIZE_START = 5, + }; + + private: + + struct ArrayListBlock + { + SPTR(ArrayListBlock) m_next; + DWORD m_blockSize; +#ifdef _WIN64 + DWORD m_padding; +#endif + PTR_VOID m_array[0]; + +#ifdef DACCESS_COMPILE + static ULONG32 DacSize(TADDR addr) + { + LIMITED_METHOD_CONTRACT; + return offsetof(ArrayListBlock, m_array) + + (*PTR_DWORD(addr + offsetof(ArrayListBlock, m_blockSize)) * sizeof(void*)); + } +#endif + }; + typedef SPTR(ArrayListBlock) PTR_ArrayListBlock; + + struct FirstArrayListBlock + { + PTR_ArrayListBlock m_next; + DWORD m_blockSize; +#ifdef _WIN64 + DWORD m_padding; +#endif + void * m_array[ARRAY_BLOCK_SIZE_START]; + }; + + typedef DPTR(FirstArrayListBlock) PTR_FirstArrayListBlock; + + DWORD m_count; + FirstArrayListBlock m_firstBlock; + + public: + + PTR_VOID *GetPtr(DWORD index) const; + PTR_VOID Get(DWORD index) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return *GetPtr(index); + } + + void Set(DWORD index, PTR_VOID element) + { + WRAPPER_NO_CONTRACT; + *GetPtr(index) = element; + } + + DWORD GetCount() const { LIMITED_METHOD_DAC_CONTRACT; return m_count; } + + HRESULT Append(void *element); + + enum { NOT_FOUND = -1 }; + DWORD FindElement(DWORD start, PTR_VOID element) const; + + void Clear(); + + void Init() + { + LIMITED_METHOD_CONTRACT; + + m_count = 0; + m_firstBlock.m_next = NULL; + m_firstBlock.m_blockSize = ARRAY_BLOCK_SIZE_START; + } + + void Destroy() + { + WRAPPER_NO_CONTRACT; + Clear(); + } + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); +#endif + + class ConstIterator; + + class Iterator + { + friend class ArrayListBase; + friend class ConstIterator; + + public: + BOOL Next(); + + void SetEmpty() + { + LIMITED_METHOD_CONTRACT; + + m_block = NULL; + m_index = (DWORD)-1; + m_remaining = 0; + m_total = 0; + } + + PTR_VOID GetElement() {LIMITED_METHOD_DAC_CONTRACT; return m_block->m_array[m_index]; } + PTR_VOID * GetElementPtr() {LIMITED_METHOD_CONTRACT; return m_block->m_array + m_index; } + DWORD GetIndex() {LIMITED_METHOD_CONTRACT; return m_index + m_total; } + void *GetBlock() { return m_block; } + + private: + ArrayListBlock* m_block; + DWORD m_index; + DWORD m_remaining; + DWORD m_total; + static Iterator Create(ArrayListBlock* block, DWORD remaining) + { + LIMITED_METHOD_DAC_CONTRACT; + Iterator i; + i.m_block = block; + i.m_index = (DWORD) -1; + i.m_remaining = remaining; + i.m_total = 0; + return i; + } + }; + + class ConstIterator + { + public: + ConstIterator(ArrayListBlock *pBlock, DWORD dwRemaining) : m_iterator(Iterator::Create(pBlock, dwRemaining)) + { + } + + BOOL Next() + { + WRAPPER_NO_CONTRACT; + return m_iterator.Next(); + } + + PTR_VOID GetElement() + { + WRAPPER_NO_CONTRACT; + return m_iterator.GetElement(); + } + + private: + Iterator m_iterator; + }; + + Iterator Iterate() + { + WRAPPER_NO_CONTRACT; + return Iterator::Create((ArrayListBlock*)&m_firstBlock, m_count); + } + + ConstIterator Iterate() const + { + // Const cast is safe because ConstIterator does not expose any way to modify the block + ArrayListBlock *pFirstBlock = const_cast(reinterpret_cast(&m_firstBlock)); + return ConstIterator(pFirstBlock, m_count); + } + + // BlockIterator is used for only memory walking, such as prejit save/fixup. + // It is not appropriate for other more typical ArrayList use. + class BlockIterator + { + private: + + ArrayListBlock *m_block; + DWORD m_remaining; + + friend class ArrayListBase; + BlockIterator(ArrayListBlock *block, DWORD remaining) + : m_block(block), m_remaining(remaining) + { + } + + public: + + BOOL Next() + { + if (m_block != NULL) + { + // Prevent m_remaining from underflowing - we can have completely empty block at the end. + if (m_remaining > m_block->m_blockSize) + m_remaining -= m_block->m_blockSize; + else + m_remaining = 0; + + m_block = m_block->m_next; + } + return m_block != NULL; + } + + void ClearUnusedMemory() + { + if (m_remaining < m_block->m_blockSize) + ZeroMemory(&(m_block->m_array[m_remaining]), (m_block->m_blockSize - m_remaining) * sizeof(void*)); +#ifdef _WIN64 + m_block->m_padding = 0; +#endif + } + + void **GetNextPtr() + { + return (void **) &m_block->m_next; + } + + void *GetBlock() + { + return m_block; + } + + SIZE_T GetBlockSize() + { + return offsetof(ArrayListBlock, m_array) + (m_block->m_blockSize * sizeof(void*)); + } + }; + + void **GetInitialNextPtr() + { + return (void **) &m_firstBlock.m_next; + } + + BlockIterator IterateBlocks() + { + return BlockIterator((ArrayListBlock *) &m_firstBlock, m_count); + } + +}; + +class ArrayList : public ArrayListBase +{ +public: +#ifndef DACCESS_COMPILE + ArrayList() + { + WRAPPER_NO_CONTRACT; + Init(); + } + + ~ArrayList() + { + WRAPPER_NO_CONTRACT; + Destroy(); + } +#endif +}; + +/* to be used as static variable - no constructor/destructor, assumes zero + initialized memory */ +class ArrayListStatic : public ArrayListBase +{ +}; + +typedef DPTR(ArrayListStatic) PTR_ArrayListStatic; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/lib/coreclr/src/inc/bbsweep.h b/lib/coreclr/src/inc/bbsweep.h new file mode 100644 index 0000000000..d5526d8e5c --- /dev/null +++ b/lib/coreclr/src/inc/bbsweep.h @@ -0,0 +1,425 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*****************************************************************************\ +* * +* BBSweep.h - Classes for sweeping profile data to disk * +* * +* Version 1.0 * +******************************************************************************* +* * +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +* PURPOSE. * +* * +\*****************************************************************************/ + +#ifndef _BBSWEEP_H_ +#define _BBSWEEP_H_ + +#ifndef FEATURE_PAL +#include +#endif // !FEATURE_PAL + +// The CLR headers don't allow us to use methods like SetEvent directly (instead +// we need to use the host APIs). However, this file is included both in the CLR +// and in the BBSweep tool, and the host API is not available in the tool. Moreover, +// BBSweep is not designed to work in an environment where the host controls +// synchronization. For this reason, we work around the problem by undefining +// these APIs (the CLR redefines them so that they will not be used). +#pragma push_macro("SetEvent") +#pragma push_macro("ResetEvent") +#pragma push_macro("ReleaseSemaphore") +#pragma push_macro("LocalFree") +#undef SetEvent +#undef ResetEvent +#undef ReleaseSemaphore +#undef LocalFree + +// MAX_COUNT is the maximal number of runtime processes that can run at a given time +#define MAX_COUNT 20 + +#define INVALID_PID -1 + +/* CLRBBSweepCallback is implemented by the CLR which passes it as an argument to WatchForSweepEvents. + * It is used by BBSweep to tell the CLR to write the profile data to disk at the right time. + */ + +class ICLRBBSweepCallback +{ +public: + virtual HRESULT WriteProfileData() = NULL; // tells the runtime to write the profile data to disk +}; + +/* BBSweep is used by both the CLR and the BBSweep utility. + * BBSweep: calls the PerformSweep method which returns after all the CLR processes + * have written their profile data to disk. + * CLR: starts up a sweeper thread which calls WatchForSweepEvents and waits until the + * sweeper program is invoked. At that point, all the CLR processes will synchronize + * and write their profile data to disk one at a time. The sweeper threads will then + * wait for the next sweep event. The CLR also calls ShutdownBBSweepThread at + * shutdown which returns when the BBSweep thread has terminated. + */ + +class BBSweep +{ +public: + BBSweep() + { + // The BBSweep constructor could be called even the the object is not used, so + // don't do any work here. + bInitialized = false; + bTerminate = false; + hSweepMutex = NULL; + hProfDataWriterMutex = NULL; + hSweepEvent = NULL; + hTerminationEvent = NULL; + hProfWriterSemaphore = NULL; + hBBSweepThread = NULL; + } + + ~BBSweep() + { + // When the destructor is called, everything should be cleaned up already. + } + + // Called by the sweeper utility to tell all the CLR threads to write their profile + // data to disk. + // THIS FUNCTIONALITY IS ALSO DUPLICATED IN TOOLBOX\MPGO\BBSWEEP.CS + // IF YOU CHANGE THIS CODE, YOU MUST ALSO CHANGE THAT TO MATCH! + bool PerformSweep(DWORD processID = INVALID_PID) + { + bool success = true; + + if (!Initialize(processID, FALSE)) return false; + + ::WaitForSingleObject(hSweepMutex, INFINITE); + { + success = success && ::SetEvent(hSweepEvent); + { + for (int i=0; iWriteProfileData())) + success = false; + } + ::ReleaseMutex(hProfDataWriterMutex); + + ::ReleaseSemaphore(hProfWriterSemaphore, 1, NULL); + } + + return success; + } + + void SetBBSweepThreadHandle(HANDLE threadHandle) + { + hBBSweepThread = threadHandle; + } + + void ShutdownBBSweepThread() + { + // Set the termination event and wait for the BBSweep thread to terminate on its own. + // Note that this is called by the shutdown thread (and never called by the BBSweep thread). + if (hBBSweepThread && bInitialized) + { + bTerminate = true; + ::SetEvent(hTerminationEvent); + ::WaitForSingleObject(hBBSweepThread, INFINITE); + Cleanup(); + } + } + + void Cleanup() + { + if (hSweepMutex) { ::CloseHandle(hSweepMutex); hSweepMutex = NULL;} + if (hProfDataWriterMutex) { ::CloseHandle(hProfDataWriterMutex); hProfDataWriterMutex = NULL;} + if (hSweepEvent) { ::CloseHandle(hSweepEvent); hSweepEvent = NULL;} + if (hTerminationEvent) { ::CloseHandle(hTerminationEvent); hTerminationEvent = NULL;} + if (hProfWriterSemaphore) { ::CloseHandle(hProfWriterSemaphore); hProfWriterSemaphore = NULL;} + } + +private: + + // THIS FUNCTIONALITY IS ALSO DUPLICATED IN TOOLBOX\MPGO\BBSWEEP.CS + // IF YOU CHANGE THIS CODE, YOU MUST ALSO CHANGE THAT TO MATCH! + bool Initialize(DWORD processID = INVALID_PID, BOOL fromRuntime = TRUE) + { + if (!bInitialized) + { + SECURITY_ATTRIBUTES * pSecurityAttributes = NULL; + +#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO + PSECURITY_DESCRIPTOR pSD = NULL; + PSID pAdminSid = NULL; + HANDLE hToken = NULL; + PACL pACL = NULL; + LPVOID buffer = NULL; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + goto cleanup; + + // don't set pSecurityAttributes for Metro processes + if(!IsAppContainerProcess(hToken)) + { + SECURITY_ATTRIBUTES securityAttributes; + PSID pUserSid = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + DWORD retLength; + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6211) // PREfast warning: Leaking memory 'pSD' due to an exception. +#endif /*_PREFAST_ */ + pSD = (PSECURITY_DESCRIPTOR) new char[SECURITY_DESCRIPTOR_MIN_LENGTH]; + if (!pSD) + goto cleanup; + + if (GetTokenInformation(hToken, TokenOwner, NULL, 0, &retLength)) + goto cleanup; + + buffer = (LPVOID) new char[retLength]; + if (!buffer) + goto cleanup; +#ifdef _PREFAST_ +#pragma warning(pop) +#endif /*_PREFAST_*/ + + // Get the SID for the current user + if (!GetTokenInformation(hToken, TokenOwner, (LPVOID) buffer, retLength, &retLength)) + goto cleanup; + + pUserSid = ((TOKEN_OWNER *) buffer)->Owner; + + // Get the SID for the admin group + // Create a SID for the BUILTIN\Administrators group. + if(! AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSid)) + goto cleanup; + + EXPLICIT_ACCESS ea[2]; + ZeroMemory(ea, 2 * sizeof(EXPLICIT_ACCESS)); + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow the current user full access + ea[0].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; // KEY_ALL_ACCESS; + ea[0].grfAccessMode = SET_ACCESS; + ea[0].grfInheritance= NO_INHERITANCE; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_USER; + ea[0].Trustee.ptstrName = (LPTSTR) pUserSid; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow admins full access + ea[1].grfAccessPermissions = STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; //KEY_ALL_ACCESS; + ea[1].grfAccessMode = SET_ACCESS; + ea[1].grfInheritance= NO_INHERITANCE; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (LPTSTR) pAdminSid; + + if (SetEntriesInAcl(2, ea, NULL, &pACL) != ERROR_SUCCESS) + goto cleanup; + + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) + goto cleanup; + + if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) + goto cleanup; + + memset((void *) &securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); + securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); + securityAttributes.lpSecurityDescriptor = pSD; + securityAttributes.bInheritHandle = FALSE; + + pSecurityAttributes = &securityAttributes; + } +#endif // !FEATURE_CORESYSTEM + + WCHAR objectName[MAX_LONGPATH] = {0}; + WCHAR objectNamePrefix[MAX_LONGPATH] = {0}; + GetObjectNamePrefix(processID, fromRuntime, objectNamePrefix); + // if there is a non-empty name prefix, append a '\' + if (objectNamePrefix[0] != '\0') + wcscat_s(objectNamePrefix, ARRAYSIZE(objectNamePrefix), W("\\")); + swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hSweepMutex"), objectNamePrefix); + hSweepMutex = ::WszCreateMutex(pSecurityAttributes, false, objectName); + swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hProfDataWriterMutex"), objectNamePrefix); + hProfDataWriterMutex = ::WszCreateMutex(pSecurityAttributes, false, objectName); + swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hSweepEvent"), objectNamePrefix); + hSweepEvent = ::WszCreateEvent(pSecurityAttributes, true, false, objectName); + + // Note that hTerminateEvent is not a named event. That is because it is not + // shared amongst the CLR processes (each process terminates at a different time) + hTerminationEvent = ::WszCreateEvent(pSecurityAttributes, true, false, NULL); + swprintf_s(objectName, MAX_LONGPATH, W("%sBBSweep_hProfWriterSemaphore"), objectNamePrefix); + hProfWriterSemaphore = ::WszCreateSemaphore(pSecurityAttributes, MAX_COUNT, MAX_COUNT, objectName); + +#ifndef FEATURE_CORESYSTEM // @CORESYSTEMTODO +cleanup: + if (pSD) delete [] ((char *) pSD); + if (pAdminSid) FreeSid(pAdminSid); + if (hToken) CloseHandle(hToken); + if (pACL) LocalFree(pACL); + if (buffer) delete [] ((char *) buffer); +#endif + } + + bInitialized = hSweepMutex && + hProfDataWriterMutex && + hSweepEvent && + hTerminationEvent && + hProfWriterSemaphore; + + if (!bInitialized) Cleanup(); + return bInitialized; + } + +#ifndef FEATURE_PAL + BOOL IsAppContainerProcess(HANDLE hToken) + { +#ifndef TokenIsAppContainer +#define TokenIsAppContainer ((TOKEN_INFORMATION_CLASS) 29) +#endif + BOOL fIsAppContainerProcess; + DWORD dwReturnLength; + if (!GetTokenInformation(hToken, TokenIsAppContainer, &fIsAppContainerProcess, sizeof(BOOL), &dwReturnLength) || + dwReturnLength != sizeof(BOOL)) + { + fIsAppContainerProcess = FALSE; + } + return fIsAppContainerProcess; + } +#endif // !FEATURE_PAL + + // helper to get the correct object name prefix + void GetObjectNamePrefix(DWORD processID, BOOL fromRuntime, __inout_z WCHAR* objectNamePrefix) + { + // default prefix + swprintf_s(objectNamePrefix, MAX_LONGPATH, W("Global")); +#ifndef FEATURE_PAL + // + // This method can be called: + // 1. From process init code + // 2. From bbsweepclr.exe + // + // When called from process init code, processID is always INVALID_PID. + // In case it is a Win8-Metro/WP8 process, we need to add the AppContainerNamedObjectPath to prefix. + // And if it is a non-Metro process, we will continue to use the default prefix (Global). + // We use IsAppContainerProcess(CurrentProcessId) to make this decision. + // + // + // When called from bbsweepclr, processID is valid when sweeping a Metro or WP8 process. + // We use this valid processID to determine if the process being swept is Metro/WP8 indeed and then + // add AppContainerNamedObjectPath to prefix. This is done by IsAppContainerProcess(processID). + // + // In case INVALID_PID is passed(non-Metro process), we have to use default prefix. To handle this + // case we use IsAppContainerProcess(CurrentProcessId) and since bbsweepclr is a non-Metro process, + // this check always returns false and we end up using the intended(default) prefix. + // + if(processID == INVALID_PID) { + // we reach here when: + // * called from process init code: + // * called from bbsweepclr.exe and no processID has been passed as argument, that is, when sweeping a non-Metro process + processID = GetCurrentProcessId(); + } + + HandleHolder hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processID); + if (hProcess != INVALID_HANDLE_VALUE) + { + HandleHolder hToken = NULL; + // if in the process init code of a Metro app or if bbsweepclr is used to sweep a Metro app, + // construct the object name prefix using AppContainerNamedObjectPath + if (OpenProcessToken(hProcess, TOKEN_QUERY, &hToken) && IsAppContainerProcess(hToken)) + { + WCHAR appxNamedObjPath[MAX_LONGPATH] = { 0 }; + ULONG appxNamedObjPathBufLen = 0; + + if (fromRuntime) + { + // for Metro apps, create the object in the "default" object path, i.e. do not provide any prefix + objectNamePrefix[0] = W('\0'); + } + else + { +#if defined (FEATURE_CORESYSTEM) && !defined(CROSSGEN_COMPILE) && !defined(DACCESS_COMPILE) +#define MODULE_NAME W("api-ms-win-security-appcontainer-l1-1-0.dll") +#else +#define MODULE_NAME W("kernel32.dll") +#endif + typedef BOOL(WINAPI *PFN_GetAppContainerNamedObjectPath) + (HANDLE Token, PSID AppContainerSid, ULONG ObjectPathLength, WCHAR * ObjectPath, PULONG ReturnLength); + + PFN_GetAppContainerNamedObjectPath pfnGetAppContainerNamedObjectPath = (PFN_GetAppContainerNamedObjectPath) + GetProcAddress(WszGetModuleHandle(MODULE_NAME), "GetAppContainerNamedObjectPath"); + if (pfnGetAppContainerNamedObjectPath) + { + // for bbsweepclr sweeping a Metro app, create the object specifying the AppContainer's path + DWORD sessionId = 0; + ProcessIdToSessionId(processID, &sessionId); + pfnGetAppContainerNamedObjectPath(hToken, NULL, sizeof (appxNamedObjPath) / sizeof (WCHAR), appxNamedObjPath, &appxNamedObjPathBufLen); + swprintf_s(objectNamePrefix, MAX_LONGPATH, W("Global\\Session\\%d\\%s"), sessionId, appxNamedObjPath); + } + } + } + } +#endif // FEATURE_PAL + } +private: + + bool bInitialized; // true when the BBSweep object has initialized successfully + bool bTerminate; // set to true when the CLR wants us to terminate + HANDLE hSweepMutex; // prevents processing from incrementing the semaphore after the sweep has began + HANDLE hProfDataWriterMutex; // guarantees that profile data will be written by one process at a time + HANDLE hSweepEvent; // tells the CLR processes to sweep their profile data + HANDLE hTerminationEvent; // set when the CLR process is ready to terminate + HANDLE hProfWriterSemaphore; // helps determine when all the writers are finished + HANDLE hBBSweepThread; // a handle to the CLR sweeper thread (that calls watch for sweep events) +}; + +#pragma pop_macro("LocalFree") +#pragma pop_macro("ReleaseSemaphore") +#pragma pop_macro("ResetEvent") +#pragma pop_macro("SetEvent") + +#endif //_BBSWEEP_H diff --git a/lib/coreclr/src/inc/bitmask.h b/lib/coreclr/src/inc/bitmask.h new file mode 100644 index 0000000000..a59d2e252d --- /dev/null +++ b/lib/coreclr/src/inc/bitmask.h @@ -0,0 +1,103 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +// -------------------------------------------------------------------------------- +// BitMask.h +// -------------------------------------------------------------------------------- + +// -------------------------------------------------------------------------------- +// BitMask is an arbitrarily large sized bitfield which has optimal storage +// for 32 bits or less. +// Storage is proportional to the highest index which is set. +// -------------------------------------------------------------------------------- + + +#include + +#ifndef _BITMASK_H_ +#define _BITMASK_H_ + +class BitMask +{ + public: + + BitMask(); + ~BitMask(); + + BOOL TestBit(int bit); + void SetBit(int bit); + void ClearBit(int bit); + + // returns true if any bit is set + BOOL TestAnyBit(); + + void ClearAllBits(); + + // Allocation exposed for ngen save/fixup + size_t GetAllocatedBlockOffset(); + void *GetAllocatedBlock(); + COUNT_T GetAllocatedBlockSize(); + + private: + + static const int BIT_SIZE_SHIFT = 5; + static const int BIT_SIZE = (1<writer so be very careful + // when taking this lock else you might deadlock your own thread! + SimpleRWLock m_bitMaskLock; +}; + +#include + +#endif // _BITMASK_H_ diff --git a/lib/coreclr/src/inc/bitmask.inl b/lib/coreclr/src/inc/bitmask.inl new file mode 100644 index 0000000000..00bfe0138e --- /dev/null +++ b/lib/coreclr/src/inc/bitmask.inl @@ -0,0 +1,292 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +// -------------------------------------------------------------------------------- +// BitMask.inl +// -------------------------------------------------------------------------------- + +#include + +#ifndef _BITMASK_INL_ +#define _BITMASK_INL_ + +inline BOOL BitMask::IsArray() +{ + LIMITED_METHOD_CONTRACT; + return (m_mask&1) == 0; +} + +// Indexing computations +inline COUNT_T BitMask::BitToIndex(int bit) +{ + LIMITED_METHOD_CONTRACT; + // First word has one less bit due to tag + return (bit+1) >> BIT_SIZE_SHIFT; +} + +inline COUNT_T BitMask::BitToShift(int bit) +{ + LIMITED_METHOD_CONTRACT; + // First word has one less bit due to tag + return (bit+1) & BIT_SIZE_MASK; +} + +// Array access. Note the first array element is the count of the +// rest of the elements + +inline COUNT_T *BitMask::GetMaskArray() +{ + LIMITED_METHOD_CONTRACT; + if (IsArray()) + { + CONSISTENCY_CHECK(CheckPointer(m_maskArray)); + return m_maskArray+1; + } + else + return &m_mask; +} + +inline COUNT_T BitMask::GetMaskArraySize() +{ + LIMITED_METHOD_CONTRACT; + if (IsArray()) + return *m_maskArray; + else + return 1; +} + +inline void BitMask::GrowArray(COUNT_T newSize) +{ + CONTRACTL + { + THROWS; + } + CONTRACTL_END; + + // Ensure we don't grow too often + + COUNT_T oldSize = GetMaskArraySize(); + if (newSize <= oldSize) + return; + + if (newSize < oldSize*2) + newSize = oldSize*2; + if (newSize < MIN_ARRAY_ALLOCATION) + newSize = MIN_ARRAY_ALLOCATION; + + // Allocate new array + + COUNT_T *newArray = new COUNT_T [newSize+1]; + *newArray = newSize; + + CopyMemory(newArray+1, GetMaskArray(), oldSize * sizeof(COUNT_T)); + ZeroMemory(newArray+oldSize+1, (newSize - oldSize) * sizeof(COUNT_T)); + + if (IsArray()) + delete [] m_maskArray; + + m_maskArray = newArray; +} + +inline BitMask::BitMask() + : m_mask(1) +{ + LIMITED_METHOD_CONTRACT; +} + +inline BitMask::~BitMask() +{ + LIMITED_METHOD_CONTRACT; + + if (IsArray()) + delete [] m_maskArray; +} + +inline BOOL BitMask::TestBit(int bit) +{ + LIMITED_METHOD_CONTRACT; + + COUNT_T index = BitToIndex(bit); + + if (index >= GetMaskArraySize()) + return FALSE; + + return ( GetMaskArray()[index] >> BitToShift(bit) ) & 1; +} + +inline void BitMask::SetBit(int bit) +{ + CONTRACTL + { + THROWS; + } + CONTRACTL_END; + + COUNT_T index = BitToIndex(bit); + + if (index >= GetMaskArraySize()) + GrowArray(index+1); + + GetMaskArray()[index] |= (1 << BitToShift(bit)); +} + +inline void BitMask::ClearBit(int bit) +{ + LIMITED_METHOD_CONTRACT; + + COUNT_T index = BitToIndex(bit); + + if (index >= GetMaskArraySize()) + return; + + GetMaskArray()[index] &= ~(1 << BitToShift(bit)); +} + +inline BOOL BitMask::TestAnyBit() +{ + LIMITED_METHOD_CONTRACT; + + if (IsArray()) + { + COUNT_T *mask = m_maskArray+1; + COUNT_T *maskEnd = mask + m_maskArray[0]; + + while (mask < maskEnd) + { + if (*mask != 0) + return TRUE; + mask++; + } + + return FALSE; + } + else + return m_mask != (COUNT_T) 1; +} + +inline void BitMask::ClearAllBits() +{ + LIMITED_METHOD_CONTRACT; + + if (IsArray()) + delete [] m_maskArray; + + m_mask = 1; +} + +inline size_t BitMask::GetAllocatedBlockOffset() +{ + LIMITED_METHOD_CONTRACT; + + return offsetof(BitMask, m_maskArray); +} + +inline void *BitMask::GetAllocatedBlock() +{ + LIMITED_METHOD_CONTRACT; + + if (IsArray()) + return m_maskArray; + else + return NULL; +} + +inline COUNT_T BitMask::GetAllocatedBlockSize() +{ + LIMITED_METHOD_CONTRACT; + + if (IsArray()) + return (GetMaskArraySize()+1) * sizeof(COUNT_T); + else + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// + +inline SynchronizedBitMask::SynchronizedBitMask() + : m_bitMaskLock(PREEMPTIVE, LOCK_TYPE_DEFAULT) +{ + LIMITED_METHOD_CONTRACT; +} + +inline BOOL SynchronizedBitMask::TestBit(int bit) +{ + CONTRACTL + { + NOTHROW; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + SimpleReadLockHolder holder(&m_bitMaskLock); + + return m_bitMask.TestBit(bit); +} + +inline void SynchronizedBitMask::SetBit(int bit) +{ + CONTRACTL + { + THROWS; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + SimpleWriteLockHolder holder(&m_bitMaskLock); + + m_bitMask.SetBit(bit); +} + +inline void SynchronizedBitMask::ClearBit(int bit) +{ + CONTRACTL + { + NOTHROW; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + SimpleWriteLockHolder holder(&m_bitMaskLock); + + m_bitMask.ClearBit(bit); +} + +inline BOOL SynchronizedBitMask::TestAnyBit() +{ + CONTRACTL + { + NOTHROW; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + SimpleReadLockHolder holder(&m_bitMaskLock); + + return m_bitMask.TestAnyBit(); +} + +inline void SynchronizedBitMask::ClearAllBits() +{ + CONTRACTL + { + NOTHROW; + MODE_ANY; + CAN_TAKE_LOCK; + } + CONTRACTL_END; + + SimpleWriteLockHolder holder(&m_bitMaskLock); + + m_bitMask.ClearAllBits(); +} + +#endif // _BITMASK_INL_ + diff --git a/lib/coreclr/src/inc/bitposition.h b/lib/coreclr/src/inc/bitposition.h new file mode 100644 index 0000000000..df7915546a --- /dev/null +++ b/lib/coreclr/src/inc/bitposition.h @@ -0,0 +1,59 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _BITPOSITION_H_ +#define _BITPOSITION_H_ + +//------------------------------------------------------------------------ +// BitPosition: Return the position of the single bit that is set in 'value'. +// +// Return Value: +// The position (0 is LSB) of bit that is set in 'value' +// +// Notes: +// 'value' must have exactly one bit set. +// The algorithm is as follows: +// - PRIME is a prime bigger than sizeof(unsigned int), which is not of the +// form 2^n-1. +// - Taking the modulo of 'value' with this will produce a unique hash for all +// powers of 2 (which is what "value" is). +// - Entries in hashTable[] which are -1 should never be used. There +// should be PRIME-8*sizeof(value) entries which are -1 . +// +inline +unsigned BitPosition(unsigned value) +{ + _ASSERTE((value != 0) && ((value & (value-1)) == 0)); +#if defined(_ARM_) && defined(__llvm__) + // use intrinsic functions for arm32 + // this is applied for LLVM only but it may work for some compilers + DWORD index = __builtin_clz(__builtin_arm_rbit(value)); +#elif !defined(_AMD64_) + const unsigned PRIME = 37; + + static const char hashTable[PRIME] = + { + -1, 0, 1, 26, 2, 23, 27, -1, 3, 16, + 24, 30, 28, 11, -1, 13, 4, 7, 17, -1, + 25, 22, 31, 15, 29, 10, 12, 6, -1, 21, + 14, 9, 5, 20, 8, 19, 18 + }; + + _ASSERTE(PRIME >= 8*sizeof(value)); + _ASSERTE(sizeof(hashTable) == PRIME); + + + unsigned hash = value % PRIME; + unsigned index = hashTable[hash]; + _ASSERTE(index != (unsigned char)-1); +#else + // not enabled for x86 because BSF is extremely slow on Atom + // (15 clock cycles vs 1-3 on any other Intel CPU post-P4) + DWORD index; + BitScanForward(&index, value); +#endif + return index; +} + +#endif diff --git a/lib/coreclr/src/inc/bitvector.h b/lib/coreclr/src/inc/bitvector.h new file mode 100644 index 0000000000..a4181dbb8a --- /dev/null +++ b/lib/coreclr/src/inc/bitvector.h @@ -0,0 +1,462 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/***************************************************************************/ +/* BitVector.h */ +/***************************************************************************/ +// Routines to support a growable bitvector +/***************************************************************************/ + +#ifndef BITVECTOR_H +#define BITVECTOR_H 1 + + +#ifndef LIMITED_METHOD_CONTRACT +#define LIMITED_METHOD_CONTRACT +#define UNDEF_LIMITED_METHOD_CONTRACT +#endif + +#ifndef WRAPPER_NO_CONTRACT +#define WRAPPER_NO_CONTRACT +#define UNDEF_WRAPPER_NO_CONTRACT +#endif + +#ifndef SUPPORTS_DAC +#define SUPPORTS_DAC +#define UNDEF_SUPPORTS_DAC +#endif + +#ifndef _ASSERTE +#define _ASSERTE(x) +#define UNDEF_ASSERTE +#endif + +#define USE_BITVECTOR 1 +#if USE_BITVECTOR + +/* The bitvector class is meant to be a drop in replacement for an integer + (that is you use it like an integer), however it grows as needed. + + Features: + plug compatible with normal integers; + grows as needed + Optimized for the small case when the vector fits in machine word + Uses one machine word if vector fits in machine word (minus a bit) + + Some caveates: + You should use mutator operators &=, |= ... instead of the + non-mutators whenever possible to avoid creating a temps + + Specifically did NOT supply automatic coersions to + and from short types so that the programmer is aware of + when code was being injected on his behalf. The upshot of this + is that you have to use the BitVector() toUnsigned() to convert +*/ + +/***************************************************************************/ + +class BitVector { + // Set this to be unsigned char to do testing, should be UINT_PTR for real life + + typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly +// typedef BYTE ChunkType; // Use for testing + + // Maximum number of bits in our bitvector +#define MAX_PTRARG_OFS 1024 + + enum { + IS_BIG = 1, // The low bit is used to discrimate m_val and m_vals + CHUNK_BITS = sizeof(ChunkType)*8, // The number of bits that we can manipuate as a chunk + SMALL_BITS = CHUNK_BITS - 1, // The number of bits we can fit in the small representation +// SMALL_BITS = 5, // TESTING ONLY: The number of bits we can fit in the small representation + VALS_COUNT = MAX_PTRARG_OFS / CHUNK_BITS, // The number of ChunkType elements in the Vals array + }; + +public: + BitVector() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + m_val = 0; + } + + BOOL isBig() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return ((m_val & IS_BIG) != 0); + } + + void toBig() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + if (!isBig()) + { + doBigInit(smallBits()); + } + } + + explicit BitVector(ChunkType arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (arg > MaxVal) + { + doBigInit(arg); + } + else + { + m_val = ChunkType(arg << 1); + } + } + + BitVector(ChunkType arg, UINT shift) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if ((arg > MaxVal) || (shift >= SMALL_BITS) || (arg > (MaxVal >> shift))) + { + doBigInit(arg); + doBigLeftShiftAssign(shift); + } + else + { + m_val = ChunkType(arg << (shift+1)); + } + } + +#define CONSTRUCT_ptrArgTP(arg,shift) BitVector((arg), (shift)) + + BitVector(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (arg.isBig()) + { + doBigInit(arg); + } + else + { + m_val = arg.m_val; + } + } + + void operator <<=(unsigned shift) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything + return; + + if (isBig() || (shift >= SMALL_BITS) || (m_val > (MaxVal >> (shift-1)))) + { + doBigLeftShiftAssign(shift); + } + else + { + m_val <<= shift; + } + } + + void operator >>=(unsigned shift) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (isBig()) + { + doBigRightShiftAssign(shift); + } + else + { + m_val >>= shift; + m_val &= ~IS_BIG; // clear the isBig bit if it got set + } + } + + void operator |=(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (((m_val | arg.m_val) & IS_BIG) != 0) + { + doBigOrAssign(arg); + } + else + { + m_val |= arg.m_val; + } + } + + // Note that that is set difference, not subtration + void operator -=(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (((m_val | arg.m_val) & IS_BIG) != 0) + { + doBigDiffAssign(arg); + } + else + { + m_val &= ~arg.m_val; + } + } + + void operator &=(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (((m_val | arg.m_val) & IS_BIG) != 0) + { + doBigAndAssign(arg); + } + else + { + m_val &= arg.m_val; + } + } + + friend void setDiff(BitVector& target, const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + target -= arg; + } + + friend BOOL intersect(const BitVector& arg1, const BitVector& arg2) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (((arg1.m_val | arg2.m_val) & IS_BIG) != 0) + { + return arg1.doBigIntersect(arg2); + } + else + { + return ((arg1.m_val & arg2.m_val) != 0); + } + } + + BOOL operator ==(const BitVector& arg) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if ((m_val | arg.m_val) & IS_BIG) + { + return doBigEquals(arg); + } + else + { + return m_val == arg.m_val; + } + } + + BOOL operator !=(const BitVector& arg) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return !(*this == arg); + } + + friend ChunkType toUnsigned(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (arg.isBig()) + { + return arg.m_vals.m_chunks[0]; // Note truncation + } + else + { + return arg.smallBits(); + } + } + + // Note that we require the invariant that zero is always stored in the + // small form so that this works bitvector is zero iff (m_val == 0) + friend BOOL isZero(const BitVector& arg) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return arg.m_val == 0; + } + + /* currently only used in asserts */ + BitVector operator &(const BitVector& arg) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + BitVector ret = *this; + ret &= arg; + return ret; + } + + int NumBits() const; + +private: + + static const ChunkType MaxVal = ((ChunkType)1 << SMALL_BITS) - 1; // Maximum value that can be stored in m_val + + // This is the structure that we use when the bit vector overflows. + // It is a simple vector. + struct Vals { + unsigned m_encodedLength; // An encoding of the current length of the 'm_chunks' array + ChunkType m_chunks[VALS_COUNT]; + + BOOL isBig() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return ((m_encodedLength & IS_BIG) != 0); + } + + unsigned GetLength() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + if (isBig()) + { + unsigned length = (m_encodedLength >> 1); + _ASSERTE(length > 0); + return length; + } + else + { + return 0; + } + } + + void SetLength(unsigned length) + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(length > 0); + _ASSERTE(length <= VALS_COUNT); + + m_encodedLength = (ChunkType) (length << 1); + m_encodedLength |= (ChunkType) IS_BIG; + } + }; + + // + // This is the instance data for the bitvector + // + // We discrimininate on this + union { + ChunkType m_val; // if m_val bit 0 is false, then bits 1-N are the bit vector + Vals m_vals; // if m_val bit 1 is true, then use Vals + }; + + + ChunkType smallBits() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(!isBig()); + return (m_val >> 1); + } + +#ifdef STRIKE + void doBigInit(ChunkType arg) {} +#else + void doBigInit(ChunkType arg); +#endif + void doBigInit(const BitVector& arg); + void doBigLeftShiftAssign(unsigned arg); + void doBigRightShiftAssign(unsigned arg); + void doBigDiffAssign(const BitVector&); + void doBigAndAssign(const BitVector&); + void doBigOrAssign(const BitVector& arg); + BOOL doBigEquals(const BitVector&) const; + BOOL doBigIntersect(const BitVector&) const; +}; + +typedef BitVector ptrArgTP; + +#else // !USE_BITVECTOR + +typedef unsigned __int64 ptrArgTP; + + // Maximum number of bits in our bitvector +#define MAX_PTRARG_OFS (sizeof(ptrArgTP) * 8) + +#define CONSTRUCT_ptrArgTP(arg,shift) (((ptrArgTP) (arg)) << (shift)) + +inline BOOL isZero(const ptrArgTP& arg) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + return (arg == 0); +} + +inline ptrArgTP toUnsigned(const ptrArgTP& arg) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + return arg; +} + +inline void setDiff(ptrArgTP& target, const ptrArgTP& arg) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + target &= ~arg; +} + +inline BOOL intersect(const ptrArgTP arg1, const ptrArgTP arg2) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return ((arg1 & arg2) != 0); +} + +#endif // !USE_BITVECTOR + +#ifdef UNDEF_LIMITED_METHOD_CONTRACT +#undef LIMITED_METHOD_CONTRACT +#undef UNDEF_LIMITED_METHOD_CONTRACT +#endif + +#ifdef UNDEF_WRAPPER_NO_CONTRACT +#undef WRAPPER_NO_CONTRACT +#undef UNDEF_WRAPPER_NO_CONTRACT +#endif + +#ifdef UNDEF_SUPPORTS_DAC +#undef SUPPORTS_DAC +#undef UNDEF_SUPPORTS_DAC +#endif + +#ifdef UNDEF_ASSERTE +#undef _ASSERTE +#undef UNDEF_ASSERTE +#endif + +#endif // BITVECTOR_H diff --git a/lib/coreclr/src/inc/blobfetcher.h b/lib/coreclr/src/inc/blobfetcher.h new file mode 100644 index 0000000000..0c640f0d6d --- /dev/null +++ b/lib/coreclr/src/inc/blobfetcher.h @@ -0,0 +1,174 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// CBlobFetcher - it fetches binary chunks, similar to new, but more controlled +// +// Fast, dynamic, memory management which doesn't relocate blocks +// m_pIndex has array of pillars, where each pillar starts off empty and has +// just-in-time allocation. As each pillar fills up, we move to the next pillar +// If the entire array of pillars fill up, we need to allocate a new array and +// copy the pillars over. But the actual data returned from GetBlock() never +// gets moved. So everyone's happy. +// +//***************************************************************************** + + +#ifndef __BLOB_FETCHER_H_ +#define __BLOB_FETCHER_H_ + +#include + + +class CBlobFetcher +{ +protected: + + class CPillar { + public: + CPillar(); + ~CPillar(); + + void SetAllocateSize(unsigned nSize); + unsigned GetAllocateSize() const; + + char* MakeNewBlock(unsigned len, unsigned pad); + void StealDataFrom(CPillar & src); + unsigned GetDataLen() const; + char* GetRawDataStart(); + BOOL Contains(__in char *ptr); + ULONG32 GetOffset(__in char *ptr); + + protected: + unsigned m_nTargetSize; // when we allocate, make it this large + + // Make these public so CBlobFetcher can do easy manipulation + public: + char* m_dataAlloc; + char* m_dataStart; + char* m_dataCur; + char* m_dataEnd; + }; + + + CPillar * m_pIndex; // array of pillars + + unsigned m_nIndexMax; // actual size of m_ppIndex + unsigned m_nIndexUsed; // current pillar, so start at 0 + + unsigned m_nDataLen; // sum of all pillars' lengths + +// Don't allow these because they'll mess up the ownership + CBlobFetcher(const CBlobFetcher & src); + CBlobFetcher& operator=(const CBlobFetcher & src); + +public: +#if defined(_WIN64) + // needs to be 64 so that we can purposefully cache align code in ngen'd images + enum { maxAlign = 64 }; // maximum alignment we support +#else + enum { maxAlign = 32 }; // maximum alignment we support +#endif + CBlobFetcher(); + ~CBlobFetcher(); + +// get a block to write on (use instead of write to avoid copy) + char * MakeNewBlock(unsigned int nSize, unsigned align=1); + +// Index segment as if this were linear + char * ComputePointer(unsigned offset) const; + +// Determine if pointer came from this fetcher + BOOL ContainsPointer(__in char *ptr) const; + +// Find an offset as if this were linear + unsigned ComputeOffset(__in char *ptr) const; + +// Write out the section to the stream + HRESULT Write(HANDLE file); + +// Write out the section to memory + HRESULT WriteMem(void ** pMem); + +// Get the total length of all our data (sum of all the pillar's data length's) +// cached value, so light weight & no computations + unsigned GetDataLen() const; + + HRESULT Merge(CBlobFetcher *destination); + +// Set the blob fetcher to slow growth mode. This should be done before any allocations + void SetInitialGrowth(unsigned growth); +}; + + +//***************************************************************************** +// Inlines +//***************************************************************************** + +// Set the size that the Pillar will allocate if we call getBlock() +inline void CBlobFetcher::CPillar::SetAllocateSize(unsigned nSize) +{ + LIMITED_METHOD_CONTRACT; + m_nTargetSize = nSize; +} + +// Get the size we will allocate so we can decide if we need to change it +// This is not the same as the GetDataLen() and is only useful +// before we do the allocation +inline unsigned CBlobFetcher::CPillar::GetAllocateSize() const +{ + LIMITED_METHOD_CONTRACT; + return m_nTargetSize; +} + +inline char* CBlobFetcher::CPillar::GetRawDataStart() +{ + LIMITED_METHOD_CONTRACT; + return m_dataStart; +} + +inline BOOL CBlobFetcher::CPillar::Contains(__in char *ptr) +{ + LIMITED_METHOD_CONTRACT; + + return ptr >= m_dataStart && ptr < m_dataCur; +} + +inline ULONG32 CBlobFetcher::CPillar::GetOffset(__in char *ptr) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(Contains(ptr)); + + return (ULONG32)(ptr - m_dataStart); +} + +//----------------------------------------------------------------------------- +// Calculate the length of data being used, (not the length allocated) +//----------------------------------------------------------------------------- +inline unsigned CBlobFetcher::CPillar::GetDataLen() const +{ + LIMITED_METHOD_CONTRACT; + + _ASSERTE((m_dataCur >= m_dataStart) && (m_dataCur <= m_dataEnd)); + + return (unsigned)(m_dataCur - m_dataStart); +} + +inline unsigned CBlobFetcher::GetDataLen() const +{ + LIMITED_METHOD_CONTRACT; + + return m_nDataLen; +} + +// Set the blob fetcher to slow growth mode. This should be done before any allocations +inline void CBlobFetcher::SetInitialGrowth(unsigned growth) +{ + _ASSERTE(GetDataLen() == 0); + if (GetDataLen() == 0) + { + m_pIndex[0].SetAllocateSize(growth); + } +} + +#endif // __BLOB_FETCHER_H_ diff --git a/lib/coreclr/src/inc/cahlpr.h b/lib/coreclr/src/inc/cahlpr.h new file mode 100644 index 0000000000..903d3abddf --- /dev/null +++ b/lib/coreclr/src/inc/cahlpr.h @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// File: CAHLPR.H +// +// +// +//***************************************************************************** +#ifndef __CAHLPR_H__ +#define __CAHLPR_H__ + +#include "caparser.h" + +//***************************************************************************** +// This class assists in the parsing of CustomAttribute blobs. +//***************************************************************************** +struct CaValue +{ + union + { + signed __int8 i1; + unsigned __int8 u1; + signed __int16 i2; + unsigned __int16 u2; + signed __int32 i4; + unsigned __int32 u4; + signed __int64 i8; + unsigned __int64 u8; + float r4; + double r8; + struct + { + LPCUTF8 pStr; + ULONG cbStr; + } str; + }; + unsigned __int8 tag; +}; + +#endif // __CAHLPR_H__ diff --git a/lib/coreclr/src/inc/caparser.h b/lib/coreclr/src/inc/caparser.h new file mode 100644 index 0000000000..0dfbb918b2 --- /dev/null +++ b/lib/coreclr/src/inc/caparser.h @@ -0,0 +1,377 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: caparser.h +// + + +// + +// +// ============================================================================ + +#ifndef __CAPARSER_H__ +#define __CAPARSER_H__ + +#include "stgpooli.h" + +class CustomAttributeParser { +public: + CustomAttributeParser( // Constructor for CustomAttributeParser. + const void *pvBlob, // Pointer to the CustomAttribute blob. + ULONG cbBlob) // Size of the CustomAttribute blob. + : m_pbCur(reinterpret_cast(pvBlob)), + m_pbBlob(reinterpret_cast(pvBlob)), + m_cbBlob(cbBlob) + { + LIMITED_METHOD_CONTRACT; + } + +private: + signed __int8 GetI1() + { + LIMITED_METHOD_CONTRACT; + signed __int8 tmp = *reinterpret_cast(m_pbCur); + m_pbCur += sizeof(signed __int8); + return tmp; + } + unsigned __int8 GetU1() + { + LIMITED_METHOD_CONTRACT; + unsigned __int8 tmp = *reinterpret_cast(m_pbCur); + m_pbCur += sizeof(unsigned __int8); + return tmp; + } + + signed __int16 GetI2() + { + LIMITED_METHOD_CONTRACT; + signed __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); + m_pbCur += sizeof(signed __int16); + return tmp; + } + unsigned __int16 GetU2() + { + LIMITED_METHOD_CONTRACT; + unsigned __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); + m_pbCur += sizeof(unsigned __int16 ); + return tmp; + } + + signed __int32 GetI4() + { + LIMITED_METHOD_CONTRACT; + signed __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); + m_pbCur += sizeof(signed __int32 ); + return tmp; + } + unsigned __int32 GetU4() + { + LIMITED_METHOD_CONTRACT; + unsigned __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); + m_pbCur += sizeof(unsigned __int32 ); + return tmp; + } + + signed __int64 GetI8() + { + LIMITED_METHOD_CONTRACT; + signed __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); + m_pbCur += sizeof(signed __int64 ); + return tmp; + } + unsigned __int64 GetU8() + { + LIMITED_METHOD_CONTRACT; + unsigned __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); + m_pbCur += sizeof(unsigned __int64 ); + return tmp; + } + +public: + float GetR4() + { + LIMITED_METHOD_CONTRACT; + __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); + _ASSERTE(sizeof(__int32) == sizeof(float)); + m_pbCur += sizeof(float); + return (float &)tmp; + } + + double GetR8() + { + LIMITED_METHOD_CONTRACT; + __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); + _ASSERTE(sizeof(__int64) == sizeof(double)); + m_pbCur += sizeof(double); + return (double &)tmp; + } + +private: + unsigned __int16 GetProlog() + { + WRAPPER_NO_CONTRACT; + unsigned __int16 val; + VERIFY(SUCCEEDED(GetProlog(&val))); + return val; + } + + LPCUTF8 GetString(ULONG *pcbString) + { + WRAPPER_NO_CONTRACT; + LPCUTF8 val; + VERIFY(SUCCEEDED(GetString(&val, pcbString))); + return val; + } + +public: + HRESULT GetI1(signed __int8 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(signed __int8)) + return META_E_CA_INVALID_BLOB; + *pVal = GetI1(); + return S_OK; + } + + HRESULT GetTag(CorSerializationType *pVal) + { + WRAPPER_NO_CONTRACT; + HRESULT hr; + signed __int8 tmp; + IfFailRet(GetI1(&tmp)); + *pVal = (CorSerializationType)((unsigned __int8)tmp); + return hr; + } + + HRESULT GetU1(unsigned __int8 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(unsigned __int8)) + return META_E_CA_INVALID_BLOB; + *pVal = GetU1(); + return S_OK; + } + + HRESULT GetI2(signed __int16 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(signed __int16)) + return META_E_CA_INVALID_BLOB; + *pVal = GetI2(); + return S_OK; + } + HRESULT GetU2(unsigned __int16 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(unsigned __int16)) + return META_E_CA_INVALID_BLOB; + *pVal = GetU2(); + return S_OK; + } + + HRESULT GetI4(signed __int32 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(signed __int32)) + return META_E_CA_INVALID_BLOB; + *pVal = GetI4(); + return S_OK; + } + HRESULT GetU4(unsigned __int32 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(unsigned __int32)) + return META_E_CA_INVALID_BLOB; + *pVal = GetU4(); + return S_OK; + } + + HRESULT GetI8(signed __int64 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(signed __int64)) + return META_E_CA_INVALID_BLOB; + *pVal = GetI8(); + return S_OK; + } + HRESULT GetU8(unsigned __int64 *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(unsigned __int64)) + return META_E_CA_INVALID_BLOB; + *pVal = GetU8(); + return S_OK; + } + + HRESULT GetR4(float *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(float)) + return META_E_CA_INVALID_BLOB; + *pVal = GetR4(); + return S_OK; + } + HRESULT GetR8(double *pVal) + { + WRAPPER_NO_CONTRACT; + + if (BytesLeft() < (int) sizeof(double)) + return META_E_CA_INVALID_BLOB; + *pVal = GetR8(); + return S_OK; + } + + HRESULT GetProlog(unsigned __int16 *pVal) + { + WRAPPER_NO_CONTRACT; + + m_pbCur = m_pbBlob; + + if (BytesLeft() < (int)(sizeof(BYTE) * 2)) + return META_E_CA_INVALID_BLOB; + + return GetU2(pVal); + } + + // Added for compatibility with anyone that may emit + // blobs where the prolog is the only incorrect data. + HRESULT SkipProlog() + { + unsigned __int16 val; + return GetProlog(&val); + } + + HRESULT ValidateProlog() + { + HRESULT hr; + unsigned __int16 val; + IfFailRet(GetProlog(&val)); + + if (val != 0x0001) + return META_E_CA_INVALID_BLOB; + + return hr; + } + + // + // IMPORTANT: the returned string is typically not null-terminated. + // + // This can return any of three distinct valid results: + // - NULL string, indicated by *pszString==NULL, *pcbString==0 + // - empty string, indicated by *pszString!=NULL, *pcbString==0 + // - non-empty string, indicated by *pdzString!=NULL, *pcbString!=0 + // If you expect non-null or non-empty strings in your usage scenario, + // call the GetNonNullString and GetNonEmptyString helpers below. + // + HRESULT GetString(LPCUTF8 *pszString, ULONG *pcbString) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + HRESULT hr; + + if (BytesLeft() == 0) + { // Need to check for NULL string sentinal (see below), + // so need to have at least one byte to read. + IfFailRet(META_E_CA_INVALID_BLOB); + } + + if (*m_pbCur == 0xFF) + { // 0xFF indicates the NULL string, which is semantically + // different than the empty string. + *pszString = NULL; + *pcbString = 0; + m_pbCur++; + return S_OK; + } + + // Get the length, pointer to data following the length. + return GetData((BYTE const **)pszString, pcbString); + } + + // + // This can return any of two distinct valid results: + // - empty string, indicated by *pszString!=NULL, *pcbString==0 + // - non-empty string, indicated by *pszString!=NULL, *pcbString!=0 + // If you expect non-null or non-empty strings in your usage scenario, + // call the GetNonNullString and GetNonEmptyString helpers below. + // + HRESULT GetNonNullString(LPCUTF8 *pszString, ULONG *pcbString) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + HRESULT hr; + + IfFailRet(GetString(pszString, pcbString)); + + if (*pszString == NULL) + { + return META_E_CA_INVALID_BLOB; + } + + return S_OK; + } + + // + // This function will only return success if the string is valid, + // non-NULL and non-empty; i.e., *pszString!=NULL, *pcbString!=0 + // + HRESULT GetNonEmptyString(LPCUTF8 *pszString, ULONG *pcbString) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + HRESULT hr; + + IfFailRet(GetNonNullString(pszString, pcbString)); + + if (*pcbString == 0) + { + return META_E_CA_INVALID_BLOB; + } + + return S_OK; + } + + // IMPORTANT: do not use with string fetching - use GetString instead. + HRESULT GetData(BYTE const **ppbData, ULONG *pcbData) + { + HRESULT hr; + IfFailRet(CPackedLen::SafeGetData(m_pbCur, m_pbBlob + m_cbBlob, pcbData, ppbData)); + // Move past the data we just recovered + m_pbCur = *ppbData + *pcbData; + + return S_OK; + } + + // IMPORTANT: do not use with string fetching - use GetString instead. + HRESULT GetPackedValue(ULONG *pcbData) + { + return CPackedLen::SafeGetLength(m_pbCur, m_pbBlob + m_cbBlob, pcbData, &m_pbCur); + } + + int BytesLeft() + { + LIMITED_METHOD_CONTRACT; + return (int)(m_cbBlob - (m_pbCur - m_pbBlob)); + } + +private: + const BYTE *m_pbCur; + const BYTE *m_pbBlob; + ULONG m_cbBlob; +}; + +#endif // __CAPARSER_H__ diff --git a/lib/coreclr/src/inc/ceefilegenwriter.h b/lib/coreclr/src/inc/ceefilegenwriter.h new file mode 100644 index 0000000000..8bfea464cc --- /dev/null +++ b/lib/coreclr/src/inc/ceefilegenwriter.h @@ -0,0 +1,245 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: CeeFileGenWriter.h +// +// =========================================================================== + +#ifndef _CEEFILEGENWRITER_H_ +#define _CEEFILEGENWRITER_H_ +// + +// CeeFileGenWriter contains all the code necessary to actually write an exe +// while CCeeGen contains everything else. This lets CeeGen.exe and the VM +// share more code without forcing the VM to carry the extra code to write an +// exe. +#include +#include "ceegen.h" +#include "iceefilegen.h" + +class PEWriter; +class CeeFileGenWriter; + +// default setting for PE file +const UINT32 CEE_IMAGE_BASE_32 = 0x00400000; +const UINT64 CEE_IMAGE_BASE_64 = UI64(0x0000000140000000); +const int CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION = 4; +const int CEE_IMAGE_SUBSYSTEM_MINOR_VERSION = 0; + +class CeeFileGenWriter : public CCeeGen +{ + mdToken m_entryPoint; // token for entry point + DWORD m_comImageFlags; + + LPWSTR m_outputFileName; + LPWSTR m_resourceFileName; + LPWSTR m_libraryName; + GUID m_libraryGuid; + bool m_dllSwitch; + + ULONG m_iatOffset; + DWORD m_dwMacroDefinitionRVA; + DWORD m_dwMacroDefinitionSize; + + DWORD m_dwManifestRVA; + DWORD m_dwManifestSize; + + DWORD m_dwStrongNameRVA; + DWORD m_dwStrongNameSize; + + DWORD m_dwVTableRVA; + DWORD m_dwVTableSize; + + bool m_linked; + bool m_fixed; + + HRESULT checkForErrors(); + + struct IDataDllInfo { + const char *m_name; + int m_numMethods; + const char **m_methodName; + int m_iltOffset; + int m_ibnOffset; + int m_iatOffset; + int m_nameOffset; + } *m_iDataDlls; + int m_dllCount; + + CeeSection *m_iDataSectionIAT; + int m_iDataOffsetIAT; + char *m_iDataIAT; + +#ifdef EMIT_FIXUPS + + CeeSection * m_sectionFixups; + IMAGE_DEBUG_DIRECTORY * m_pDebugDir; + bool m_fFixupsUpdated; + bool m_fEmitFixups; + +#endif + + HRESULT allocateIAT(); +public: + // Create with one of these two methods, not operator new + static HRESULT CreateNewInstance(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, + DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); + // See ICeeFileGen.h for the definition of the bits used in createFlags + static HRESULT CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, + DWORD createFlags, LPCWSTR seedFileName = NULL); + + virtual HRESULT Cleanup(); + + PEWriter &getPEWriter(); + + HRESULT link(); // Layout the sections and assign their starting addresses + HRESULT fixup(); // Apply relocations to any pointer data. Also generate PE base relocs + HRESULT generateImage(void **ppImage); + + HRESULT setImageBase(size_t imageBase); + HRESULT setImageBase64(ULONGLONG imageBase); + HRESULT setFileAlignment(ULONG fileAlignment); + HRESULT setSubsystem(DWORD subsystem, DWORD major, DWORD minor); + + HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA); + + HRESULT setEntryPoint(mdMethodDef method); + mdMethodDef getEntryPoint(); + + HRESULT setComImageFlags(DWORD mask); + HRESULT clearComImageFlags(DWORD mask); + DWORD getComImageFlags(); + + HRESULT setOutputFileName(__in LPWSTR outputFileName); + LPWSTR getOutputFileName(); + + HRESULT setResourceFileName(__in LPWSTR resourceFileName); + LPWSTR getResourceFileName(); + + HRESULT setLibraryName(__in LPWSTR libraryName); + LPWSTR getLibraryName(); + + HRESULT setDirectoryEntry(CeeSection §ion, ULONG entry, ULONG size, ULONG offset=0); + HRESULT computeSectionOffset(CeeSection §ion, __in char *ptr, + unsigned *offset); + HRESULT computeOffset(__in char *ptr, CeeSection **pSection, + unsigned *offset); + HRESULT getCorHeader(IMAGE_COR20_HEADER **ppHeader); + + HRESULT getFileTimeStamp(DWORD *pTimeStamp); + +//@FUTURE: this entry point is only here so that down level clients of this interface +// can import the method by name in the exports table using the original name. +// These things really ought to be exported through a v-table so there is no +// name mangling issues. It would make the export table much smaller as well. + HRESULT emitLibraryName(IMetaDataEmit *emitter); + HRESULT setLibraryGuid(__in LPWSTR libraryGuid); + + HRESULT setDllSwitch(bool dllSwitch); + bool getDllSwitch(); + HRESULT setObjSwitch(bool objSwitch); + bool getObjSwitch(); + HRESULT EmitMacroDefinitions(void *pData, DWORD cData); + HRESULT setManifestEntry(ULONG size, ULONG offset); + HRESULT setStrongNameEntry(ULONG size, ULONG offset); + HRESULT setEnCRvaBase(ULONG dataBase, ULONG rdataBase); + HRESULT setVTableEntry(ULONG size, ULONG offset); + HRESULT setVTableEntry64(ULONG size, void* ptr); + +protected: + CeeFileGenWriter(); // ctor is protected + + HRESULT emitResourceSection(); + HRESULT emitExeMain(); + + HRESULT setAddrReloc(UCHAR *instrAddr, DWORD value); + HRESULT addAddrReloc(CeeSection &thisSection, UCHAR *instrAddr, DWORD offset, CeeSection *targetSection); + + HRESULT MapTokens(CeeGenTokenMapper *pMapper, IMetaDataImport *pImport); + HRESULT MapTokensForMethod(CeeGenTokenMapper *pMapper,BYTE *pCode, LPCWSTR szMethodName); + +#ifdef EMIT_FIXUPS + + HRESULT InitFixupSection(); + HRESULT UpdateFixups(); + HRESULT setEmitFixups(); + +#ifdef TEST_EMIT_FIXUPS + HRESULT TestEmitFixups(); +#endif + +public: + HRESULT addFixup(CeeSection& secFixups, unsigned offset, CeeSectionRelocType reloc, CeeSection * relativeTo = NULL, CeeSectionRelocExtra *extra = 0); +#endif +}; + + +inline PEWriter &CeeFileGenWriter::getPEWriter() +{ + return (PEWriter &) *m_peSectionMan; +} + +inline LPWSTR CeeFileGenWriter::getOutputFileName() { + return m_outputFileName; +} + +inline LPWSTR CeeFileGenWriter::getResourceFileName() { + return m_resourceFileName; +} + +inline HRESULT CeeFileGenWriter::setDllSwitch(bool dllSwitch) { + if((m_dllSwitch = dllSwitch)) m_objSwitch = FALSE; return S_OK; +} + +inline bool CeeFileGenWriter::getDllSwitch() { + return m_dllSwitch; +} + +inline HRESULT CeeFileGenWriter::setObjSwitch(bool objSwitch) { + if((m_objSwitch = objSwitch)) m_dllSwitch = FALSE; return S_OK; +} + +inline bool CeeFileGenWriter::getObjSwitch() { + return m_objSwitch; +} + +inline LPWSTR CeeFileGenWriter::getLibraryName() { + return m_libraryName; +} + +inline mdMethodDef CeeFileGenWriter::getEntryPoint() { + return m_entryPoint; +} + +inline HRESULT CeeFileGenWriter::setEntryPoint(mdMethodDef method) { + m_entryPoint = method; + return S_OK; +} + +inline HRESULT CeeFileGenWriter::setComImageFlags(DWORD mask) { + m_comImageFlags |= mask; return S_OK; +} + +inline HRESULT CeeFileGenWriter::clearComImageFlags(DWORD mask) { + m_comImageFlags &= ~mask; return S_OK; +} + +inline DWORD CeeFileGenWriter::getComImageFlags() { + return m_comImageFlags; +} + + +// +#if defined(_IMAGE_FILE_4K_SECTION_ALIGNMENT_) +#define IMAGE_NT_OPTIONAL_HDR_SECTION_ALIGNMENT 0x1000 +#else +#define IMAGE_NT_OPTIONAL_HDR_SECTION_ALIGNMENT 0x2000 +#endif + +// The stub is always x86 so we always mark the image as x86 +#define IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_I386 + + +#endif // _CEEFILEGENWRITER_H_ + diff --git a/lib/coreclr/src/inc/ceegen.h b/lib/coreclr/src/inc/ceegen.h new file mode 100644 index 0000000000..c7d2af2615 --- /dev/null +++ b/lib/coreclr/src/inc/ceegen.h @@ -0,0 +1,437 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: CEEGEN.H +// +// =========================================================================== + +#ifndef _CEEGEN_H_ +#define _CEEGEN_H_ + +#include "cor.h" +#include "iceefilegen.h" +#include "ceegentokenmapper.h" + +class CeeSection; +class CeeSectionString; +class CCeeGen; +class PESectionMan; +class PESection; + +typedef DWORD StringRef; + +#if 0 + + This is a description of the current implementation of these types for generating + CLR modules. + + ICeeGen - interface to generate in-memory CLR module. + + CCeeGen - implementation of ICeeGen. Currently it uses both CeeSections + as well as PESections (inside PESectionMan), and maintains a + 1:1 relation between them. This is ugly. + + CeeFileGenWriter - Provides functionality to write in-memory module to + PE format file. Uses PEWriter (m_pSectionMan) for + file-writing functionality + + PEWriter - It can generate a PE format file. It also knows to apply + pointer relocs when it lays out the PESections. + + + ICeeFileGen - Interface used by compilers, ngen, etc, to generate + a CLR file. + Has a bunch of methods to emit signatures, tokens, methods, + etc which are not implemented. These are left over from before + + +----------------------------+ + | ICeeGen | + | | + | COM-style version of | + | ICeeFileGen. HCEEFILE is | + | replaced with "this" | + +-------------------------+ | | + | CeeSectionImpl | +----------------------------+ + +-------------------------+ | + | | | + | | v + | v +---------------------------+ + | +------------+ | CCeeGen | + | | | +---------------------------+ + | | CeeSection | contains | | + | | |<-------------| CeeSection* m_sections | + | +------------+ | | + | /| PESectionMan m_pSectionMan| + | / | | + | +-----------------+ / +---------------------------+ + v | PESectionMan |<----+ | + +-----------+ | | contains | + | PESection | +-----------------+ | + | | contains | PESection * | v + | |<----------| sectStart, | +------------------------------+ + +-----------+ | sectCur, | | CeeFileGenWriter | + | sectEnd | +------------------------------+ + +-----------------+ | Does meta-data specific | + | | stuff and then dispatches to | + | | m_pSectionMan.PEWriter::***()| + | | | + v +------------------------------+ + +------------------------+ ^ + | PEWriter | |wraps + +------------------------+ | + | Low -level file writer | +----------------------------+ + | Knows how to do | | ICeeFileGen | + | pointer relocs | | | + | | | C-style inteface. Deals | + +------------------------+ | with HCEEFILE, HCEESECTION | + | etc. It is mostly just a | + | thin wrapper for a | + | CeeFileGenWriter | + +----------------------------+ + +#endif // 0 + +// ***** CeeSection classes + +class CeeSectionImpl { + public: + virtual unsigned dataLen() = 0; + virtual char * getBlock( + unsigned len, + unsigned align = 1) = 0; + virtual HRESULT addSectReloc( + unsigned offset, + CeeSection & relativeTo, + CeeSectionRelocType reloc = srRelocAbsolute, + CeeSectionRelocExtra * extra = NULL) = 0; + virtual HRESULT addBaseReloc( + unsigned offset, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra * extra = NULL) = 0; + virtual HRESULT directoryEntry(unsigned num) = 0; + virtual unsigned char * name() = 0; + virtual char * computePointer(unsigned offset) const = 0; + virtual BOOL containsPointer(__in char * ptr) const = 0; + virtual unsigned computeOffset(__in char * ptr) const = 0; + virtual unsigned getBaseRVA() = 0; + virtual void SetInitialGrowth(unsigned growth) = 0; +}; + +class CeeSection { + // m_ceeFile allows inter-section communication + CCeeGen &m_ceeFile; + + // abstract away implementation to allow inheritance from CeeSection + CeeSectionImpl &m_impl; + + public: + enum RelocFlags { + RELOC_NONE = 0, + + // address should be fixed up to be a RVA not a normal address + RELOC_RVA = 1 + }; + + CeeSection(CCeeGen &ceeFile, CeeSectionImpl &impl) + : m_ceeFile(ceeFile), m_impl(impl) { LIMITED_METHOD_CONTRACT; } + + virtual ~CeeSection() {LIMITED_METHOD_CONTRACT; } + + // bytes in this section at present + unsigned dataLen(); + + // section base, after linking + unsigned getBaseRVA(); + + // get a block to write on (use instead of write to avoid copy) + char* getBlock(unsigned len, unsigned align=1); + + // Indicates that the DWORD at 'offset' in the current section should + // have the base of section 'relativeTo added to it + HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, + CeeSectionRelocType = srRelocAbsolute, CeeSectionRelocExtra *extra = 0); + // Add a base reloc for the given offset in the current section + virtual HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0); + + + // this section will be directory entry 'num' + HRESULT directoryEntry(unsigned num); + + // return section name + unsigned char *name(); + + // simulate the base + offset with a more complex data storage + char * computePointer(unsigned offset) const; + BOOL containsPointer(__in char *ptr) const; + unsigned computeOffset(__in char *ptr) const; + + CeeSectionImpl &getImpl(); + CCeeGen &ceeFile(); + void SetInitialGrowth(unsigned growth); +}; + +// ***** CCeeGen class +// Only handles in memory stuff +// Base class for CeeFileGenWriter (which actually generates PEFiles) + +class CCeeGen : public ICeeGen, ICeeGenInternal { + LONG m_cRefs; + BOOL m_encMode; + protected: + short m_textIdx; // m_sections[] index for the .text section + short m_metaIdx; // m_sections[] index for metadata (.text, or .cormeta for obj files) + short m_corHdrIdx; // m_sections[] index for the COM+ header (.text0) + short m_stringIdx; // m_sections[] index for strings (.text, or .rdata for EnC) + short m_ilIdx; // m_sections[] index for IL (.text) + bool m_objSwitch; + + CeeGenTokenMapper *m_pTokenMap; + BOOLEAN m_fTokenMapSupported; // temporary to support both models + IMapToken *m_pRemapHandler; + + CeeSection **m_sections; + short m_numSections; + short m_allocSections; + + PESectionMan * m_peSectionMan; + + IMAGE_COR20_HEADER *m_corHeader; + DWORD m_corHeaderOffset; + + HRESULT allocateCorHeader(); + + HRESULT addSection(CeeSection *section, short *sectionIdx); + + HRESULT setEnCMode(); + +// Init process: Call static CreateNewInstance() , not operator new + protected: + HRESULT Init(); + CCeeGen(); + + public: + + virtual ~CCeeGen() {} + + static HRESULT CreateNewInstance(CCeeGen* & pCeeFileGen); // call this to instantiate + + virtual HRESULT Cleanup(); + + // ICeeGen interfaces + + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + STDMETHODIMP QueryInterface( + REFIID riid, + void **ppInterface); + + STDMETHODIMP EmitString ( + __in LPWSTR lpString, // [IN] String to emit + ULONG *RVA); + + STDMETHODIMP GetString ( + ULONG RVA, + __inout LPWSTR *lpString); + + STDMETHODIMP AllocateMethodBuffer ( + ULONG cchBuffer, // [IN] Length of string to emit + UCHAR **lpBuffer, // [OUT] Returned buffer + ULONG *RVA); + + STDMETHODIMP GetMethodBuffer ( + ULONG RVA, + UCHAR **lpBuffer); + + STDMETHODIMP GetIMapTokenIface ( + IUnknown **pIMapToken); + + STDMETHODIMP GenerateCeeFile (); + + STDMETHODIMP GetIlSection ( + HCEESECTION *section); + + STDMETHODIMP GetStringSection ( + HCEESECTION *section); + + STDMETHODIMP AddSectionReloc ( + HCEESECTION section, + ULONG offset, + HCEESECTION relativeTo, + CeeSectionRelocType relocType); + + STDMETHODIMP GetSectionCreate ( + const char *name, + DWORD flags, + HCEESECTION *section); + + STDMETHODIMP GetSectionDataLen ( + HCEESECTION section, + ULONG *dataLen); + + STDMETHODIMP GetSectionBlock ( + HCEESECTION section, + ULONG len, + ULONG align=1, + void **ppBytes=0); + + STDMETHODIMP TruncateSection ( + HCEESECTION section, + ULONG len); + + STDMETHODIMP GenerateCeeMemoryImage (void **ppImage); + + STDMETHODIMP ComputePointer ( + HCEESECTION section, + ULONG RVA, // [IN] RVA for method to return + UCHAR **lpBuffer); // [OUT] Returned buffer + + + STDMETHODIMP AddNotificationHandler(IUnknown *pHandler); + + // Write the metadata in "emitter" to the default metadata section is "section" is 0 + // If 'section != 0, it will put the data in 'buffer'. This + // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' + // (should use GetSaveSize to insure that buffer is big enough + virtual HRESULT emitMetaData(IMetaDataEmit *emitter, + CeeSection* section=0, DWORD offset=0, BYTE* buffer=0, unsigned buffLen=0); + virtual HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA); + + STDMETHODIMP SetInitialGrowth(DWORD growth); + + CeeSection &getTextSection(); + CeeSection &getMetaSection(); + CeeSection &getCorHeaderSection(); + CeeSectionString &getStringSection(); + CeeSection &getIlSection(); + + virtual HRESULT getSectionCreate (const char *name, DWORD flags, CeeSection **section=NULL, short *sectionIdx = NULL); + + PESectionMan* getPESectionMan() { + LIMITED_METHOD_CONTRACT; + return m_peSectionMan; + } + + virtual HRESULT getMapTokenIface(IUnknown **pIMapToken, IMetaDataEmit *emitter=0); + + CeeGenTokenMapper *getTokenMapper() { + LIMITED_METHOD_CONTRACT; + return m_pTokenMap; + } + + virtual HRESULT addNotificationHandler(IUnknown *pHandler); + + //Clone is actually a misnomer here. This method will copy all of the + //instance variables and then do a deep copy (as necessary) of the sections. + //Section data will be appended onto any information already in the section. + //This is done to support the DynamicIL -> PersistedIL transform. + virtual HRESULT cloneInstance(CCeeGen *destination); + +#ifdef EMIT_FIXUPS +public: + virtual HRESULT addFixup(CeeSection& sectionSource, unsigned offset, CeeSectionRelocType reloc, CeeSection * sectionTarget = NULL, CeeSectionRelocExtra *extra = 0) { + LIMITED_METHOD_CONTRACT; + + return(E_NOTIMPL); + } +#endif +}; + +// ***** CeeSection inline methods + +inline unsigned CeeSection::dataLen() { + WRAPPER_NO_CONTRACT; + return m_impl.dataLen(); } + +inline unsigned CeeSection::getBaseRVA() { + WRAPPER_NO_CONTRACT; + return m_impl.getBaseRVA(); } + +inline char *CeeSection::getBlock(unsigned len, unsigned align) { + WRAPPER_NO_CONTRACT; + return m_impl.getBlock(len, align); } + +inline HRESULT CeeSection::addSectReloc( + unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) { + WRAPPER_NO_CONTRACT; + return(m_impl.addSectReloc(offset, relativeTo, reloc, extra)); +} + +inline HRESULT CeeSection::addBaseReloc(unsigned offset, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) { + WRAPPER_NO_CONTRACT; + return(m_impl.addBaseReloc(offset, reloc, extra)); +} + + +inline HRESULT CeeSection::directoryEntry(unsigned num) { + WRAPPER_NO_CONTRACT; + TESTANDRETURN(num < IMAGE_NUMBEROF_DIRECTORY_ENTRIES, E_INVALIDARG); + m_impl.directoryEntry(num); + return S_OK; +} + +inline CCeeGen &CeeSection::ceeFile() { + LIMITED_METHOD_CONTRACT; + return m_ceeFile; } + +inline CeeSectionImpl &CeeSection::getImpl() { + LIMITED_METHOD_CONTRACT; + return m_impl; } + +inline unsigned char *CeeSection::name() { + WRAPPER_NO_CONTRACT; + return m_impl.name(); +} + +inline char * CeeSection::computePointer(unsigned offset) const +{ + WRAPPER_NO_CONTRACT; + return m_impl.computePointer(offset); +} + +inline BOOL CeeSection::containsPointer(__in char *ptr) const +{ + WRAPPER_NO_CONTRACT; + return m_impl.containsPointer(ptr); +} + +inline unsigned CeeSection::computeOffset(__in char *ptr) const +{ + WRAPPER_NO_CONTRACT; + return m_impl.computeOffset(ptr); +} + +inline void CeeSection::SetInitialGrowth(unsigned growth) +{ + WRAPPER_NO_CONTRACT; + m_impl.SetInitialGrowth(growth); +} + +// ***** CCeeGen inline methods + +inline CeeSection &CCeeGen::getTextSection() { + LIMITED_METHOD_CONTRACT; + + return *m_sections[m_textIdx]; } + +inline CeeSection &CCeeGen::getMetaSection() { + LIMITED_METHOD_CONTRACT; + + return *m_sections[m_metaIdx]; } + +inline CeeSection &CCeeGen::getCorHeaderSection() { + LIMITED_METHOD_CONTRACT; + _ASSERTE(m_corHdrIdx >= 0); + return *m_sections[m_corHdrIdx]; } + +inline CeeSectionString &CCeeGen::getStringSection() { + LIMITED_METHOD_CONTRACT; + + return *(CeeSectionString*)m_sections[m_stringIdx]; } + +inline CeeSection &CCeeGen::getIlSection() { + LIMITED_METHOD_CONTRACT; + + return *m_sections[m_ilIdx]; } + +#endif diff --git a/lib/coreclr/src/inc/ceegentokenmapper.h b/lib/coreclr/src/inc/ceegentokenmapper.h new file mode 100644 index 0000000000..b323ee48b6 --- /dev/null +++ b/lib/coreclr/src/inc/ceegentokenmapper.h @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// CeeGenTokenMapper.h +// +// This helper class tracks mapped tokens from their old value to the new value +// which can happen when the data is optimized on save. +// +//***************************************************************************** + +#ifndef __CeeGenTokenMapper_h__ +#define __CeeGenTokenMapper_h__ + +#include "utilcode.h" + +typedef CDynArray TOKENMAP; + +#define INDEX_OF_TYPE(type) ((type) >> 24) +//r#define INDEX_FROM_TYPE(type) case INDEX_OF_TYPE(mdt ## type): return (tkix ## type) + +// Define the list of CeeGen tracked tokens +#define CEEGEN_TRACKED_TOKENS() \ + CEEGEN_TRACKED_TOKEN(TypeDef) \ + CEEGEN_TRACKED_TOKEN(InterfaceImpl) \ + CEEGEN_TRACKED_TOKEN(MethodDef) \ + CEEGEN_TRACKED_TOKEN(TypeRef) \ + CEEGEN_TRACKED_TOKEN(MemberRef) \ + CEEGEN_TRACKED_TOKEN(CustomAttribute) \ + CEEGEN_TRACKED_TOKEN(FieldDef) \ + CEEGEN_TRACKED_TOKEN(ParamDef) \ + CEEGEN_TRACKED_TOKEN(File) \ + CEEGEN_TRACKED_TOKEN(GenericParam) \ + +class CCeeGen; + +#define CEEGEN_TRACKED_TOKEN(x) tkix ## x, + +class CeeGenTokenMapper : public IMapToken +{ +friend class CCeeGen; +friend class PESectionMan; +public: + enum + { + CEEGEN_TRACKED_TOKENS() + MAX_TOKENMAP + }; + + static int IndexForType(mdToken tk); + + CeeGenTokenMapper() : m_pIImport(0), m_cRefs(1), m_pIMapToken(NULL) { LIMITED_METHOD_CONTRACT; } + virtual ~CeeGenTokenMapper() {} + +//***************************************************************************** +// IUnknown implementation. +//***************************************************************************** + virtual ULONG STDMETHODCALLTYPE AddRef() + {LIMITED_METHOD_CONTRACT; return ++m_cRefs; } + + virtual ULONG STDMETHODCALLTYPE Release() + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + SUPPORTS_DAC_HOST_ONLY; + + ULONG cRefs = --m_cRefs; + if (cRefs == 0) + { + if (m_pIMapToken) + { + m_pIMapToken->Release(); + m_pIMapToken = NULL; + } + + delete this; + } + return cRefs; + } + + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, PVOID *ppIUnk); + +//***************************************************************************** +// Called by the meta data engine when a token is remapped to a new location. +// This value is recorded in the m_rgMap array based on type and rid of the +// from token value. +//***************************************************************************** + virtual HRESULT STDMETHODCALLTYPE Map(mdToken tkImp, mdToken tkEmit); + +//***************************************************************************** +// Check the given token to see if it has moved to a new location. If so, +// return true and give back the new token. +//***************************************************************************** + virtual int HasTokenMoved(mdToken tkFrom, mdToken &tkTo); + + int GetMaxMapSize() const + { LIMITED_METHOD_CONTRACT; return (MAX_TOKENMAP); } + + IUnknown *GetMapTokenIface() const + { LIMITED_METHOD_CONTRACT; return ((IUnknown *) this); } + + +//***************************************************************************** +// Hand out a copy of the meta data information. +//***************************************************************************** + virtual HRESULT GetMetaData(IMetaDataImport **ppIImport); + +//***************************************************************************** +// Add another token mapper. +//***************************************************************************** + virtual HRESULT AddTokenMapper(IMapToken *pIMapToken) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + // Add the token mapper, if there isn't already one. + if (m_pIMapToken == NULL) + { + m_pIMapToken = pIMapToken; + m_pIMapToken->AddRef(); + return S_OK; + } + else + { + _ASSERTE(!"Token mapper already set!"); + return E_FAIL; + } + } + +protected: +// m_rgMap is an array indexed by token type. For each type, an array of +// tokens is kept, indexed by from rid. To see if a token has been moved, +// do a lookup by type to get the right array, then use the from rid to +// find the to rid. + TOKENMAP m_rgMap[MAX_TOKENMAP]; + IMetaDataImport *m_pIImport; + ULONG m_cRefs; // Ref count. + IMapToken *m_pIMapToken; + +}; + +#endif // __CeeGenTokenMapper_h__ diff --git a/lib/coreclr/src/inc/ceesectionstring.h b/lib/coreclr/src/inc/ceesectionstring.h new file mode 100644 index 0000000000..06a534a0c1 --- /dev/null +++ b/lib/coreclr/src/inc/ceesectionstring.h @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: CeeSectionString.h +// +// =========================================================================== + +#ifndef CeeSectionString_H +#define CeeSectionString_H + +#include +#include "ceegen.h" + +// This class is responsible for managing all the strings that have +// been emitted for the PE file. + +// This class manages the strings that are added to the .rdata section. +// It keeps track of each string that has been added using a hashtable. +// The hash table is effectively 2-dimensional. There is a large "virtual +// hash space" that is used to get a wide hash code distribution. The +// virtual hash space is mapped into a real hash table where each n +// hash values in the virtual space fall into a given hash bucket for +// real hash table size n. Within the bucket, elements are stored in a linked +// list in-order. When an virtual hash entry corresponds to a given bucket, +// that bucket is searched for the matching hash id. If not found, it is +// inserted, otherwise, the value is returned. The idea is that for smaller +// apps, there won't be a large number of strings, so that collisions are +// minimal and the length of each bucket's chain is small. For larger +// numbers of strings, having a large hash space also reduces numbers +// of collisions, avoiding string compares unless the hash codes match. + +struct StringTableEntry; + +class CeeSectionString : public CeeSection { + enum { MaxRealEntries = 100, MaxVirtualEntries = 10000 }; + StringTableEntry *stringTable[MaxRealEntries]; + + StringTableEntry *createEntry(__in_z LPWSTR target, ULONG hashId); + StringTableEntry *findStringInsert( + StringTableEntry *&entry, __in_z LPWSTR targetValue, ULONG hashId); + void deleteEntries(StringTableEntry *e); +#ifdef RDATA_STATS + int dumpEntries(StringTableEntry *e); + void dumpTable(); +#endif + + public: + ~CeeSectionString(); + CeeSectionString(CCeeGen &ceeFile, CeeSectionImpl &impl); + virtual HRESULT getEmittedStringRef(__in_z LPWSTR targetValue, StringRef *ref); +}; + +#endif + diff --git a/lib/coreclr/src/inc/cfi.h b/lib/coreclr/src/inc/cfi.h new file mode 100644 index 0000000000..d5d77840ec --- /dev/null +++ b/lib/coreclr/src/inc/cfi.h @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef CFI_H_ +#define CFI_H_ + +#define DWARF_REG_ILLEGAL -1 +enum CFI_OPCODE +{ + CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one. + CFI_DEF_CFA_REGISTER, // New register is used to compute CFA + CFI_REL_OFFSET // Register is saved at offset from the current CFA +}; + +struct CFI_CODE +{ + unsigned char CodeOffset;// Offset from the start of code the frame covers. + unsigned char CfiOpCode; + short DwarfReg; // Dwarf register number. 0~32 for x64. + int Offset; + CFI_CODE(unsigned char codeOffset, unsigned char cfiOpcode, + short dwarfReg, int offset) + : CodeOffset(codeOffset) + , CfiOpCode(cfiOpcode) + , DwarfReg(dwarfReg) + , Offset(offset) + {} +}; +typedef CFI_CODE* PCFI_CODE; + +#endif // CFI_H + diff --git a/lib/coreclr/src/inc/check.h b/lib/coreclr/src/inc/check.h new file mode 100644 index 0000000000..a05960f332 --- /dev/null +++ b/lib/coreclr/src/inc/check.h @@ -0,0 +1,740 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// Check.h +// + +// +// Assertion checking infrastructure +// --------------------------------------------------------------------------- + + +#ifndef CHECK_H_ +#define CHECK_H_ + +#include "static_assert.h" +#include "daccess.h" + +#ifdef _DEBUG + +#ifdef _MSC_VER +// Make sure we can recurse deep enough for FORCEINLINE +#pragma inline_recursion(on) +#pragma inline_depth(16) +#pragma warning(disable:4714) +#endif // _MSC_VER + +#if !defined(DISABLE_CONTRACTS) +#define CHECK_INVARIANTS 1 +#define VALIDATE_OBJECTS 1 +#endif + +#endif // _DEBUG + +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +#ifdef _DEBUG +#define DEBUG_ARG(x) , x +#else +#define DEBUG_ARG(x) +#endif + +#define CHECK_STRESS 1 + +//-------------------------------------------------------------------------------- +// A CHECK is an object which encapsulates a potential assertion +// failure. It not only contains the result of the check, but if the check fails, +// also records information about the condition and call site. +// +// CHECK also serves as a holder to prevent recursive CHECKS. These can be +// particularly common when putting preconditions inside predicates, especially +// routines called by an invariant. +// +// Note that using CHECK is perfectly efficient in a free build - the CHECK becomes +// a simple string constant pointer (typically either NULL or (LPCSTR)1, although some +// check failures may include messages) +// +// NOTE: you should NEVER use the CHECK class API directly - use the macros below. +//-------------------------------------------------------------------------------- + +class SString; + +class CHECK +{ +protected: + // On retail, this is a pointer to a string literal, null or (LPCSTR)1. + // On debug, this is a pointer to dynamically allocated memory - that + // lets us have formatted strings in debug builds. + LPCSTR m_message; + +#ifdef _DEBUG + LPCSTR m_condition; + LPCSTR m_file; + INT m_line; + LONG *m_pCount; + + // Keep leakage counters. + static size_t s_cLeakedBytes; + static size_t s_cNumFailures; +#endif + + static BOOL s_neverEnforceAsserts; + +public: // !!! NOTE: Called from macros only!!! + + // If we are not in a check, return TRUE and PushCheck; otherwise return FALSE + BOOL EnterAssert(); + + // Pops check count + void LeaveAssert(); + + // Just return if we are in a check + BOOL IsInAssert(); + + // Should we skip enforcing asserts + static BOOL EnforceAssert(); + + static BOOL EnforceAssert_StaticCheckOnly(); + + static void ResetAssert(); + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4702) // Disable bogus unreachable code warning +#endif // _MSC_VER + CHECK() : m_message(NULL) +#ifdef _DEBUG + , m_condition (NULL) + , m_file(NULL) + , m_line(NULL) + , m_pCount(NULL) +#endif + {} +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + + // Fail records the result of a condition check. Can take either a + // boolean value or another check result + BOOL Fail(BOOL condition); + BOOL Fail(const CHECK &check); + + // Setup records context info after a failure. + void Setup(LPCSTR message DEBUG_ARG(LPCSTR condition) DEBUG_ARG(LPCSTR file) DEBUG_ARG(INT line)); + static LPCSTR FormatMessage(LPCSTR messageFormat, ...); + + // Trigger triggers the actual check failure. The trigger may provide a reason + // to include in the failure message. + void Trigger(LPCSTR reason); + + // Finally, convert to a BOOL to allow just testing the result of a Check function + operator BOOL(); + + BOOL operator!(); + + CHECK &operator()() { return *this; } + + static inline const CHECK OK() { + return CHECK(); + } + + static void SetAssertEnforcement(BOOL value); + + static void ReleaseTls(void* pCountTLS); + + private: + static LONG* InitTls(); +#ifdef _DEBUG + static LPCSTR AllocateDynamicMessage(const SString &s); +#endif +}; + + +//-------------------------------------------------------------------------------- +// These CHECK macros are the correct way to propagate an assertion. These +// routines are designed for use inside "Check" routines. Such routines may +// be Invariants, Validate routines, or any other assertional predicates. +// +// A Check routine should return a value of type CHECK. +// +// It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate +// control flow) and should end with CHECK_OK() if all other checks pass. +// +// It may contain a CONTRACT_CHECK contract, but this is only appropriate if the +// check is used for non-assertional purposes (otherwise the contract will never execute). +// Note that CONTRACT_CHECK contracts do not support postconditions. +// +// CHECK: Check the given condition, return a CHECK failure if FALSE +// CHECK_MSG: Same, but include a message paramter if the check fails +// CHECK_OK: Return a successful check value; +//-------------------------------------------------------------------------------- + +#ifdef _DEBUG +#define DEBUG_ONLY_MESSAGE(msg) msg +#else +// On retail, we don't want to add a bunch of string literals to the image, +// so we just use the same one everywhere. +#define DEBUG_ONLY_MESSAGE(msg) ((LPCSTR)1) +#endif + +#define CHECK_MSG_EX(_condition, _message, _RESULT) \ +do \ +{ \ + CHECK _check; \ + if (_check.Fail(_condition)) \ + { \ + ENTER_DEBUG_ONLY_CODE; \ + _check.Setup(DEBUG_ONLY_MESSAGE(_message) \ + DEBUG_ARG(#_condition) \ + DEBUG_ARG(__FILE__) \ + DEBUG_ARG(__LINE__)); \ + _RESULT(_check); \ + LEAVE_DEBUG_ONLY_CODE; \ + } \ +} while (0) + +#define RETURN_RESULT(r) return r + +#define CHECK_MSG(_condition, _message) \ + CHECK_MSG_EX(_condition, _message, RETURN_RESULT) + +#define CHECK(_condition) \ + CHECK_MSG(_condition, "") + +#define CHECK_MSGF(_condition, _args) \ + CHECK_MSG(_condition, CHECK::FormatMessage _args) + +#define CHECK_FAIL(_message) \ + CHECK_MSG(FALSE, _message); UNREACHABLE() + +#define CHECK_FAILF(_args) \ + CHECK_MSGF(FALSE, _args); UNREACHABLE() + +#define CHECK_OK \ + return CHECK::OK() + +//-------------------------------------------------------------------------------- +// ASSERT_CHECK is the proper way to trigger a check result. If the CHECK +// has failed, the diagnostic assertion routines will fire with appropriate +// context information. +// +// Note that the condition may either be a raw boolean expression or a CHECK result +// returned from a Check routine. +// +// Recursion note: ASSERT_CHECKs are only performed if there is no current check in +// progress. +//-------------------------------------------------------------------------------- + +#ifndef ENTER_DEBUG_ONLY_CODE +#define ENTER_DEBUG_ONLY_CODE +#endif + +#ifndef LEAVE_DEBUG_ONLY_CODE +#define LEAVE_DEBUG_ONLY_CODE +#endif + +#define ASSERT_CHECK(_condition, _message, _reason) \ +do \ +{ \ + CHECK _check; \ + if (_check.EnterAssert()) \ + { \ + ENTER_DEBUG_ONLY_CODE; \ + if (_check.Fail(_condition)) \ + { \ + _check.Setup(_message \ + DEBUG_ARG(#_condition) \ + DEBUG_ARG(__FILE__) \ + DEBUG_ARG(__LINE__)); \ + _check.Trigger(_reason); \ + } \ + LEAVE_DEBUG_ONLY_CODE; \ + _check.LeaveAssert(); \ + } \ +} while (0) + +// ex: ASSERT_CHECKF(1+2==4, "my reason", ("Woah %d", 1+3)); +// note that the double parenthesis, the 'args' param below will include one pair of parens. +#define ASSERT_CHECKF(_condition, _reason, _args) \ + ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason) + +//-------------------------------------------------------------------------------- +// INVARIANTS are descriptions of conditions which are always true at well defined +// points of execution. Invariants may be checked by the caller or callee at any +// time as paranoia requires. +// +// There are really two flavors of invariant. The "public invariant" describes +// to the caller invariant behavior about the abstraction which is visible from +// the public API (and of course it should be expressible in that public API). +// +// The "internal invariant" (or representation invariant), on the other hand, is +// a description of the private implementation of the abstraction, which may examine +// internal state of the abstraction or use private entry points. +// +// Classes with invariants should introduce methods called +// void Invariant(); +// and +// void InternalInvariant(); +// to allow invariant checks. +//-------------------------------------------------------------------------------- + +#if CHECK_INVARIANTS + +template +CHECK CheckInvariant(TYPENAME &obj) +{ +#if defined(_MSC_VER) || defined(__llvm__) + __if_exists(TYPENAME::Invariant) + { + CHECK(obj.Invariant()); + } + __if_exists(TYPENAME::InternalInvariant) + { + CHECK(obj.InternalInvariant()); + } +#endif + + CHECK_OK; +} + +#define CHECK_INVARIANT(o) \ + ASSERT_CHECK(CheckInvariant(o), NULL, "Invariant failure") + +#else + +#define CHECK_INVARIANT(o) do { } while (0) + +#endif + +//-------------------------------------------------------------------------------- +// VALIDATE is a check to be made on an object type which identifies a pointer as +// a valid instance of the object, by calling CheckPointer on it. Normally a null +// pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK)) +// may be used when a null pointer is acceptible. +// +// In addition to the null/non-null check, a type may provide a specific Check method +// for more sophisticated identification. In general, the Check method +// should answer the question +// "Is this a valid instance of its declared compile-time type?". For instance, if +// runtype type identification were supported for the type, it should be invoked here. +// +// Note that CheckPointer will also check the invariant(s) if appropriate, so the +// invariants should NOT be explicitly invoked from the Check method. +//-------------------------------------------------------------------------------- + +enum IsNullOK +{ + NULL_NOT_OK = 0, + NULL_OK = 1 +}; + +#if CHECK_INVARIANTS +template +CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) +{ + if (o == NULL) + { + CHECK_MSG(ok, "Illegal null pointer"); + } + else + { +#if defined(_MSC_VER) || defined(__llvm__) + __if_exists(TYPENAME::Check) + { + CHECK(o->Check()); + } +#endif + } + + CHECK_OK; +} + +template +CHECK CheckValue(TYPENAME &val) +{ +#if defined(_MSC_VER) || defined(__llvm__) + __if_exists(TYPENAME::Check) + { + CHECK(val.Check()); + } +#endif + + CHECK(CheckInvariant(val)); + + CHECK_OK; +} +#else // CHECK_INVARIANTS + +#ifdef _DEBUG_IMPL +// Don't defined these functions to be nops for the non-debug +// build as it may hide important checks +template +CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) +{ + if (o == NULL) + { + CHECK_MSG(ok, "Illegal null pointer"); + } + + CHECK_OK; +} + +template +CHECK CheckValue(TYPENAME &val) +{ + CHECK_OK; +} +#endif + +#endif // CHECK_INVARIANTS + +#if VALIDATE_OBJECTS + +#define VALIDATE(o) \ + ASSERT_CHECK(CheckPointer(o), "Validation failure") +#define VALIDATE_NULL(o) \ + ASSERT_CHECK(CheckPointer(o, NULL_OK), "Validation failure") + +#else + +#define VALIDATE(o) do { } while (0) +#define VALIDATE_NULL(o) do { } while (0) + +#endif + +//-------------------------------------------------------------------------------- +// CONSISTENCY_CHECKS are ad-hoc assertions about the expected state of the program +// at a given time. A failure in one of these indicates a bug in the code. +// +// Note that the condition may either be a raw boolean expression or a CHECK result +// returned from a Check routine. +//-------------------------------------------------------------------------------- + +#define CONSISTENCY_CHECK(_condition) \ + CONSISTENCY_CHECK_MSG(_condition, "") + +#ifdef _DEBUG_IMPL + +#define CONSISTENCY_CHECK_MSG(_condition, _message) \ + ASSERT_CHECK(_condition, _message, "Consistency check failed") + +#define CONSISTENCY_CHECK_MSGF(_condition, args) \ + ASSERT_CHECKF(_condition, "Consistency check failed", args) + +#else + +#define CONSISTENCY_CHECK_MSG(_condition, _message) do { } while (0) +#define CONSISTENCY_CHECK_MSGF(_condition, args) do { } while (0) + +#endif + +//-------------------------------------------------------------------------------- +// SIMPLIFYING_ASSUMPTIONS are workarounds which are placed in the code to allow progress +// to be made in the case of difficult corner cases. These should NOT be left in the +// code; they are really just markers of things which need to be fixed. +// +// Note that the condition may either be a raw boolean expression or a CHECK result +// returned from a Check routine. +//-------------------------------------------------------------------------------- + +// Ex usage: +// SIMPLIFYING_ASSUMPTION(SomeExpression()); +#define SIMPLIFYING_ASSUMPTION(_condition) \ + SIMPLIFYING_ASSUMPTION_MSG(_condition, "") + + +// Helper for HRs. Will provide formatted message showing the failure code. +#define SIMPLIFYING_ASSUMPTION_SUCCEEDED(__hr) \ + { \ + HRESULT __hr2 = (__hr); \ + (void)__hr2; \ + SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(__hr2), ("HRESULT failed.\n Expected success.\n Actual=0x%x\n", __hr2)); \ + } + +#ifdef _DEBUG_IMPL + +// Ex usage: +// SIMPLIFYING_ASSUMPTION_MSG(SUCCEEDED(hr), "It failed!"); +#define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) \ + ASSERT_CHECK(_condition, _message, "Unhandled special case detected") + +// use a formatted string. Ex usage: +// SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(hr), ("Woah it failed! 0x%08x", hr)); +#define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) \ + ASSERT_CHECKF(_condition, "Unhandled special case detected", args) + +#else // !_DEBUG_IMPL + +#define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) do { } while (0) +#define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) do { } while (0) + +#endif // !_DEBUG_IMPL + +//-------------------------------------------------------------------------------- +// COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the +// condition is true. In a checked build these turn into asserts; +// in a free build they are passed through to the compiler to use in optimization. +//-------------------------------------------------------------------------------- + +#if defined(_PREFAST_) || defined(_PREFIX_) || defined(__clang_analyzer__) +#define COMPILER_ASSUME_MSG(_condition, _message) if (!(_condition)) __UNREACHABLE(); +#define COMPILER_ASSUME_MSGF(_condition, args) if (!(_condition)) __UNREACHABLE(); +#else + +#if defined(DACCESS_COMPILE) +#define COMPILER_ASSUME_MSG(_condition, _message) do { } while (0) +#define COMPILER_ASSUME_MSGF(_condition, args) do { } while (0) +#else + +#if defined(_DEBUG) +#define COMPILER_ASSUME_MSG(_condition, _message) \ + ASSERT_CHECK(_condition, _message, "Compiler optimization assumption invalid") +#define COMPILER_ASSUME_MSGF(_condition, args) \ + ASSERT_CHECKF(_condition, "Compiler optimization assumption invalid", args) +#else +#define COMPILER_ASSUME_MSG(_condition, _message) __assume(_condition) +#define COMPILER_ASSUME_MSGF(_condition, args) __assume(_condition) +#endif // _DEBUG + +#endif // DACCESS_COMPILE + +#endif // _PREFAST_ || _PREFIX_ + + +#define COMPILER_ASSUME(_condition) \ + COMPILER_ASSUME_MSG(_condition, "") + + +//-------------------------------------------------------------------------------- +// PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name +// for COMPILER_ASSUME_MSG +// In a checked build these turn into asserts; in a free build +// they are passed through to the compiler to use in optimization; +// via an __assume(_condition) optimization hint. +//-------------------------------------------------------------------------------- + +#define PREFIX_ASSUME_MSG(_condition, _message) \ + COMPILER_ASSUME_MSG(_condition, _message) + +#define PREFIX_ASSUME_MSGF(_condition, args) \ + COMPILER_ASSUME_MSGF(_condition, args) + +#define PREFIX_ASSUME(_condition) \ + COMPILER_ASSUME_MSG(_condition, "") + +#define PREFAST_ASSUME_MSG(_condition, _message) \ + COMPILER_ASSUME_MSG(_condition, _message) + +#define PREFAST_ASSUME_MSGF(_condition, args) \ + COMPILER_ASSUME_MSGF(_condition, args) + +#define PREFAST_ASSUME(_condition) \ + COMPILER_ASSUME_MSG(_condition, "") + +//-------------------------------------------------------------------------------- +// UNREACHABLE points are locations in the code which should not be able to be +// reached under any circumstances (e.g. a default in a switch which is supposed to +// cover all cases.). This macro tells the compiler this, and also embeds a check +// to make sure it is always true. +//-------------------------------------------------------------------------------- + +#define UNREACHABLE() \ + UNREACHABLE_MSG("") + +#ifdef __llvm__ + +// LLVM complains if a function does not return what it says. +#define UNREACHABLE_RET() do { UNREACHABLE(); return 0; } while (0) +#define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message); return 0; + +#else // __llvm__ + +#define UNREACHABLE_RET() UNREACHABLE() +#define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message) + +#endif // __llvm__ else + +#if defined(_MSC_VER) || defined(_PREFIX_) +#if defined(_TARGET_AMD64_) +// Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method +// which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT +// Remove when we get a VC compiler that fixes VSW 449170 +# define __UNREACHABLE() DebugBreak(); __assume(0); +#else +# define __UNREACHABLE() __assume(0) +#endif +#else +#define __UNREACHABLE() __builtin_unreachable() +#endif + +#ifdef _DEBUG_IMPL + +// Note that the "do { } while (0)" syntax trick here doesn't work, as the compiler +// gives an error that the while(0) is unreachable code +#define UNREACHABLE_MSG(_message) \ +{ \ + CHECK _check; \ + _check.Setup(_message, "", __FILE__, __LINE__); \ + _check.Trigger("Reached the \"unreachable\""); \ +} __UNREACHABLE() + +#else + +#define UNREACHABLE_MSG(_message) __UNREACHABLE() + +#endif + + +//-------------------------------------------------------------------------------- +// STRESS_CHECK represents a check which is included in a free build +// @todo: behavior on trigger +// +// Note that the condition may either be a raw boolean expression or a CHECK result +// returned from a Check routine. +// +// Since Retail builds don't allow formatted checks, there's no STRESS_CHECK_MSGF. +//-------------------------------------------------------------------------------- + +#if CHECK_STRESS + +#define STRESS_CHECK(_condition, _message) \ + ASSERT_CHECK(_condition, _message, "Stress Assertion Failure") + +#else + +#define STRESS_CHECK(_condition, _message) do { } while (0) + +#endif + +//-------------------------------------------------------------------------------- +// CONTRACT_CHECK is used to put contracts on Check function. Note that it does +// not support postconditions. +//-------------------------------------------------------------------------------- + +#define CONTRACT_CHECK CONTRACTL +#define CONTRACT_CHECK_END CONTRACTL_END + +//-------------------------------------------------------------------------------- +// CCHECK is used for Check functions which may fail due to out of memory +// or other transient failures. These failures should be ignored when doing +// assertions, but they cannot be ignored when the Check function is used in +// normal code. +// @todo: really crufty to have 2 sets of CHECK macros +//-------------------------------------------------------------------------------- + +#ifdef _DEBUG + +#define CCHECK_START \ + { \ + BOOL ___exception = FALSE; \ + BOOL ___transient = FALSE; \ + CHECK ___result = CHECK::OK(); \ + EX_TRY { + +#define CCHECK_END \ + } EX_CATCH { \ + if (___result.IsInAssert()) \ + { \ + ___exception = TRUE; \ + ___transient = GET_EXCEPTION()->IsTransient(); \ + } \ + else \ + EX_RETHROW; \ + } EX_END_CATCH(RethrowTerminalExceptions); \ + \ + if (___exception) \ + { \ + if (___transient) \ + CHECK_OK; \ + else \ + CHECK_FAIL("Nontransient exception occurred during check"); \ + } \ + CHECK(___result); \ + } + +#define CRETURN_RESULT(r) ___result = r + +#define CCHECK_MSG(_condition, _message) \ + CHECK_MSG_EX(_condition, _message, CRETURN_RESULT) + +#define CCHECK(_condition) \ + CCHECK_MSG(_condition, "") + +#define CCHECK_MSGF(_condition, _args) \ + CCHECK_MSG(_condition, CHECK::FormatMessage _args) + +#define CCHECK_FAIL(_message) \ + CCHECK_MSG(FALSE, _message); UNREACHABLE() + +#define CCHECK_FAILF(_args) \ + CCHECK_MSGF(FALSE, _args); UNREACHABLE() + +#else // _DEBUG + +#define CCHECK_START +#define CCHECK_END + +#define CCHECK CHECK +#define CCHECK_MSG CHECK_MSG +#define CCHECK_MSGF CHECK_MSGF +#define CCHECK_FAIL CHECK_FAIL +#define CCHECK_FAILF CHECK_FAILF + +#endif + + + +//-------------------------------------------------------------------------------- +// Common base level checks +//-------------------------------------------------------------------------------- + +CHECK CheckAlignment(UINT alignment); + +CHECK CheckAligned(UINT value, UINT alignment); +#if defined(_MSC_VER) +CHECK CheckAligned(ULONG value, UINT alignment); +#endif +CHECK CheckAligned(UINT64 value, UINT alignment); +CHECK CheckAligned(const void *address, UINT alignment); + +CHECK CheckOverflow(UINT value1, UINT value2); +#if defined(_MSC_VER) +CHECK CheckOverflow(ULONG value1, ULONG value2); +#endif +CHECK CheckOverflow(UINT64 value1, UINT64 value2); +CHECK CheckOverflow(PTR_CVOID address, UINT offset); +#if defined(_MSC_VER) +CHECK CheckOverflow(const void *address, ULONG offset); +#endif +CHECK CheckOverflow(const void *address, UINT64 offset); + +CHECK CheckUnderflow(UINT value1, UINT value2); +#if defined(_MSC_VER) +CHECK CheckUnderflow(ULONG value1, ULONG value2); +#endif +CHECK CheckUnderflow(UINT64 value1, UINT64 value2); +CHECK CheckUnderflow(const void *address, UINT offset); +#if defined(_MSC_VER) +CHECK CheckUnderflow(const void *address, ULONG offset); +#endif +CHECK CheckUnderflow(const void *address, UINT64 offset); +CHECK CheckUnderflow(const void *address, void *address2); + +CHECK CheckZeroedMemory(const void *memory, SIZE_T size); + +// These include overflow checks +CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset); +CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size); + +void WINAPI ReleaseCheckTls(LPVOID pTlsData); + +// ================================================================================ +// Inline definitions +// ================================================================================ + +#include "check.inl" + +#endif // CHECK_H_ diff --git a/lib/coreclr/src/inc/check.inl b/lib/coreclr/src/inc/check.inl new file mode 100644 index 0000000000..9a3597ef81 --- /dev/null +++ b/lib/coreclr/src/inc/check.inl @@ -0,0 +1,367 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef CHECK_INL_ +#define CHECK_INL_ + +#include "check.h" +#include "clrhost.h" +#include "debugmacros.h" +#include "clrtypes.h" + +inline LONG *CHECK::InitTls() +{ +#pragma push_macro("HeapAlloc") +#pragma push_macro("GetProcessHeap") +#undef HeapAlloc +#undef GetProcessHeap + + LONG *pCount = (LONG *)::HeapAlloc(GetProcessHeap(), 0, sizeof(LONG)); + if (pCount) + *pCount = 0; + +#pragma pop_macro("HeapAlloc") +#pragma pop_macro("GetProcessHeap") + ClrFlsSetValue(TlsIdx_Check, pCount); + ClrFlsAssociateCallback(TlsIdx_Check, ReleaseCheckTls); + return pCount; +} + +inline void CHECK::ReleaseTls(void* pCountTLS) +{ +#pragma push_macro("HeapFree") +#pragma push_macro("GetProcessHeap") +#undef HeapFree +#undef GetProcessHeap + LONG* pCount = (LONG*) pCountTLS; + if (pCount) + ::HeapFree(GetProcessHeap(), 0, pCount); + +#pragma pop_macro("HeapFree") +#pragma pop_macro("GetProcessHeap") +} + +FORCEINLINE BOOL CHECK::EnterAssert() +{ + if (s_neverEnforceAsserts) + return FALSE; + +#ifdef _DEBUG_IMPL + m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check); + if (!m_pCount) + { + m_pCount = InitTls(); + if (!m_pCount) + return FALSE; + } + + if (!*m_pCount) + { + *m_pCount = 1; + return TRUE; + } + else + return FALSE; +#else + // Don't bother doing recursive checks on a free build, since checks should + // be extremely isolated + return TRUE; +#endif +} + +FORCEINLINE void CHECK::LeaveAssert() +{ +#ifdef _DEBUG_IMPL + *m_pCount = 0; +#endif +} + +FORCEINLINE BOOL CHECK::IsInAssert() +{ +#ifdef _DEBUG_IMPL + if (!m_pCount) + m_pCount = (LONG *)ClrFlsGetValue(TlsIdx_Check); + + if (!m_pCount) + return FALSE; + else + return *m_pCount; +#else + return FALSE; +#endif +} + +FORCEINLINE BOOL CHECK::EnforceAssert() +{ + if (s_neverEnforceAsserts) + return FALSE; + else + { + CHECK chk; + return !chk.IsInAssert(); + } +} + +FORCEINLINE void CHECK::ResetAssert() +{ + CHECK chk; + if (chk.IsInAssert()) + chk.LeaveAssert(); +} + +inline void CHECK::SetAssertEnforcement(BOOL value) +{ + s_neverEnforceAsserts = !value; +} + +// Fail records the result of a condition check. Can take either a +// boolean value or another check result +FORCEINLINE BOOL CHECK::Fail(BOOL condition) +{ +#ifdef _DEBUG + if (!condition) + { + m_condition = NULL; + m_file = NULL; + m_line = 0; + } +#endif + return !condition; +} + +FORCEINLINE BOOL CHECK::Fail(const CHECK &check) +{ + m_message = check.m_message; +#ifdef _DEBUG + if (m_message != NULL) + { + m_condition = check.m_condition; + m_file = check.m_file; + m_line = check.m_line; + } +#endif + return m_message != NULL; +} + +#ifndef _DEBUG +FORCEINLINE void CHECK::Setup(LPCSTR message) +{ + m_message = message; +} + +FORCEINLINE LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...) +{ + return messageFormat; +} +#endif + +FORCEINLINE CHECK::operator BOOL () +{ + return m_message == NULL; +} + +FORCEINLINE BOOL CHECK::operator!() +{ + return m_message != NULL; +} + +inline CHECK CheckAlignment(UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + CHECK((alignment & (alignment-1)) == 0); + CHECK_OK; +} + +inline CHECK CheckAligned(UINT value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + CHECK(AlignmentTrim(value, alignment) == 0); + CHECK_OK; +} + +#ifndef PLATFORM_UNIX +// For Unix this and the previous function get the same types. +// So, exclude this one. +inline CHECK CheckAligned(ULONG value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + CHECK(AlignmentTrim(value, alignment) == 0); + CHECK_OK; +} +#endif // PLATFORM_UNIX + +inline CHECK CheckAligned(UINT64 value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + CHECK(AlignmentTrim(value, alignment) == 0); + CHECK_OK; +} + +inline CHECK CheckAligned(const void *address, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + CHECK(AlignmentTrim((SIZE_T)address, alignment) == 0); + CHECK_OK; +} + +inline CHECK CheckOverflow(UINT value1, UINT value2) +{ + CHECK(value1 + value2 >= value1); + CHECK_OK; +} + +#if defined(_MSC_VER) +inline CHECK CheckOverflow(ULONG value1, ULONG value2) +{ + CHECK(value1 + value2 >= value1); + CHECK_OK; +} +#endif + +inline CHECK CheckOverflow(UINT64 value1, UINT64 value2) +{ + CHECK(value1 + value2 >= value1); + CHECK_OK; +} + +inline CHECK CheckOverflow(PTR_CVOID address, UINT offset) +{ + TADDR targetAddr = dac_cast(address); +#if POINTER_BITS == 32 + CHECK((UINT) (SIZE_T)(targetAddr) + offset >= (UINT) (SIZE_T) (targetAddr)); +#else + CHECK((UINT64) targetAddr + offset >= (UINT64) targetAddr); +#endif + + CHECK_OK; +} + +#if defined(_MSC_VER) +inline CHECK CheckOverflow(const void *address, ULONG offset) +{ +#if POINTER_BITS == 32 + CHECK((ULONG) (SIZE_T) address + offset >= (ULONG) (SIZE_T) address); +#else + CHECK((UINT64) address + offset >= (UINT64) address); +#endif + + CHECK_OK; +} +#endif + +inline CHECK CheckOverflow(const void *address, UINT64 offset) +{ +#if POINTER_BITS == 32 + CHECK(offset >> 32 == 0); + CHECK((UINT) (SIZE_T) address + (UINT) offset >= (UINT) (SIZE_T) address); +#else + CHECK((UINT64) address + offset >= (UINT64) address); +#endif + + CHECK_OK; +} + + +inline CHECK CheckUnderflow(UINT value1, UINT value2) +{ + CHECK(value1 - value2 <= value1); + + CHECK_OK; +} + +#ifndef PLATFORM_UNIX +// For Unix this and the previous function get the same types. +// So, exclude this one. +inline CHECK CheckUnderflow(ULONG value1, ULONG value2) +{ + CHECK(value1 - value2 <= value1); + + CHECK_OK; +} +#endif // PLATFORM_UNIX + +inline CHECK CheckUnderflow(UINT64 value1, UINT64 value2) +{ + CHECK(value1 - value2 <= value1); + + CHECK_OK; +} + +inline CHECK CheckUnderflow(const void *address, UINT offset) +{ +#if POINTER_BITS == 32 + CHECK((UINT) (SIZE_T) address - offset <= (UINT) (SIZE_T) address); +#else + CHECK((UINT64) address - offset <= (UINT64) address); +#endif + + CHECK_OK; +} + +#if defined(_MSC_VER) +inline CHECK CheckUnderflow(const void *address, ULONG offset) +{ +#if POINTER_BITS == 32 + CHECK((ULONG) (SIZE_T) address - offset <= (ULONG) (SIZE_T) address); +#else + CHECK((UINT64) address - offset <= (UINT64) address); +#endif + + CHECK_OK; +} +#endif + +inline CHECK CheckUnderflow(const void *address, UINT64 offset) +{ +#if POINTER_BITS == 32 + CHECK(offset >> 32 == 0); + CHECK((UINT) (SIZE_T) address - (UINT) offset <= (UINT) (SIZE_T) address); +#else + CHECK((UINT64) address - offset <= (UINT64) address); +#endif + + CHECK_OK; +} + +inline CHECK CheckUnderflow(const void *address, void *address2) +{ +#if POINTER_BITS == 32 + CHECK((UINT) (SIZE_T) address - (UINT) (SIZE_T) address2 <= (UINT) (SIZE_T) address); +#else + CHECK((UINT64) address - (UINT64) address2 <= (UINT64) address); +#endif + + CHECK_OK; +} + +inline CHECK CheckZeroedMemory(const void *memory, SIZE_T size) +{ + CHECK(CheckOverflow(memory, size)); + + BYTE *p = (BYTE *) memory; + BYTE *pEnd = p + size; + + while (p < pEnd) + CHECK(*p++ == 0); + + CHECK_OK; +} + +inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset) +{ + CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); + CHECK(offset <= rangeSize); + CHECK_OK; +} + +inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size) +{ + CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); + CHECK(CheckOverflow(offset, size)); + CHECK(offset + size <= rangeSize); + CHECK_OK; +} + +#endif // CHECK_INL_ + diff --git a/lib/coreclr/src/inc/circularlog.h b/lib/coreclr/src/inc/circularlog.h new file mode 100644 index 0000000000..4ee8d2fa99 --- /dev/null +++ b/lib/coreclr/src/inc/circularlog.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _CIRCULARLOG_H__ + +#define _CIRCULARLOG_H__ + +#include "sstring.h" + +class CircularLog +{ +public: + CircularLog(); + ~CircularLog(); + + bool Init(const WCHAR* logname, const WCHAR* logHeader, DWORD maxSize = 1024*1024); + void Shutdown(); + void Log(const WCHAR* string); + +protected: + + void CheckForLogReset(BOOL fOverflow); + BOOL CheckLogHeader(); + HANDLE OpenFile(); + void CloseFile(); + + bool m_bInit; + SString m_LogFilename; + SString m_LogHeader; + SString m_OldLogFilename; + SString m_LockFilename; + DWORD m_MaxSize; + unsigned m_uLogCount; +}; + +#endif diff --git a/lib/coreclr/src/inc/clr/fs.h b/lib/coreclr/src/inc/clr/fs.h new file mode 100644 index 0000000000..d6bcb75309 --- /dev/null +++ b/lib/coreclr/src/inc/clr/fs.h @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header will include all headers relating to file system functionality. + +#ifndef _clr_fs_h_ +#define _clr_fs_h_ + +#include "fs/path.h" +#include "fs/file.h" +#include "fs/dir.h" + +#endif // _clr_fs_h_ diff --git a/lib/coreclr/src/inc/clr/fs/dir.h b/lib/coreclr/src/inc/clr/fs/dir.h new file mode 100644 index 0000000000..2516151a55 --- /dev/null +++ b/lib/coreclr/src/inc/clr/fs/dir.h @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header provides general directory-related file system services. + +#ifndef _clr_fs_Dir_h_ +#define _clr_fs_Dir_h_ + +#include "clrtypes.h" +#include "clr/str.h" +#include "strsafe.h" + +#ifndef countof + #define countof(x) (sizeof(x) / sizeof(x[0])) +#endif // !countof + +namespace clr +{ + namespace fs + { + class Dir + { + public: + static inline bool Exists( + LPCWSTR wzDirPath) + { + DWORD attrs = WszGetFileAttributes(wzDirPath); + return (attrs != INVALID_FILE_ATTRIBUTES) && (attrs & FILE_ATTRIBUTE_DIRECTORY); + } + + //----------------------------------------------------------------------------------------- + // Creates new directory indicated by wzDirPath. + // + // Returns: + // S_OK - on success directory creation + // S_FALSE - when directory previously existed + // HR(ERROR_PATH_NOT_FOUND) - when creation of dir fails. + static inline HRESULT Create( + LPCWSTR wzDirPath) + { + HRESULT hr = S_OK; + + if (!WszCreateDirectory(wzDirPath, nullptr)) + { + hr = HRESULT_FROM_GetLastError(); + if (hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) + { + hr = S_FALSE; + } + } + return hr; + } + + //----------------------------------------------------------------------------------------- + // Creates the specified directory and all required subdirectories. wzDirPath will be + // temporarily modified in the process. + // + // Returns: + // S_OK - on success directory creation + // S_FALSE - when directory previously existed + // HR(ERROR_PATH_NOT_FOUND) - when creation of any dir fails. + static inline HRESULT CreateRecursively( + __inout_z LPWSTR wzDirPath, + size_t cchDirPath = 0) + { + HRESULT hr = S_OK; + + if (wzDirPath == nullptr) + { + return E_POINTER; + } + + if (cchDirPath == 0) + { + cchDirPath = wcslen(wzDirPath); + } + + // Try to create the path. If it fails, assume that's because the parent folder does + // not exist. Try to create the parent then re-attempt. + WCHAR chOrig = wzDirPath[cchDirPath]; + hr = Create(wzDirPath); + if (hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)) + { + for (WCHAR* pCurCh = wzDirPath + cchDirPath - 1; pCurCh != wzDirPath; --pCurCh) + { + if (*pCurCh == W('\\') || *pCurCh == W('\0')) + { + WCHAR chOrig = *pCurCh; + *pCurCh = W('\0'); + IfFailRet(CreateRecursively(wzDirPath, pCurCh - wzDirPath)); + *pCurCh = chOrig; + break; + } + } + IfFailRet(Create(wzDirPath)); + } + + return hr; + } + + //----------------------------------------------------------------------------------------- + // Creates the specified directory and all required subdirectories. + static inline HRESULT CreateRecursively( + LPCWSTR wzDirPath) + { + HRESULT hr = S_OK; + + if (wzDirPath == nullptr) + { + return E_POINTER; + } + + // Make a writable copy of wzDirPath + size_t cchDirPath = wcslen(wzDirPath); + CQuickWSTR wzBuffer; + IfFailRet(wzBuffer.ReSizeNoThrow(cchDirPath + 1)); + wcscpy_s(wzBuffer.Ptr(), wzBuffer.Size(), wzDirPath); + IfFailRet(CreateRecursively(wzBuffer.Ptr(), cchDirPath)); + + return hr; + } + }; + } +} + +#endif // _clr_fs_Dir_h_ diff --git a/lib/coreclr/src/inc/clr/fs/file.h b/lib/coreclr/src/inc/clr/fs/file.h new file mode 100644 index 0000000000..70f22a29fa --- /dev/null +++ b/lib/coreclr/src/inc/clr/fs/file.h @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header provides general filename-related file system services. + +#ifndef _clr_fs_File_h_ +#define _clr_fs_File_h_ + +#include "clrtypes.h" +#include "cor.h" // SELECTANY + +namespace clr +{ + namespace fs + { + // This list taken from ndp/clr/src/bcl/system/io/path.cs + SELECTANY WCHAR const g_rgInvalidFileNameChars[] = + { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6, + (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14, + (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22, + (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30, + (WCHAR)31, W(':'), W('*'), W('?'), W('\\'), W('/') }; + + class File + { + public: + static inline bool Exists( + LPCWSTR wzFilePath) + { + DWORD attrs = WszGetFileAttributes(wzFilePath); + return (attrs != INVALID_FILE_ATTRIBUTES) && !(attrs & FILE_ATTRIBUTE_DIRECTORY); + } + }; + } +} + +#endif // _clr_fs_File_h_ diff --git a/lib/coreclr/src/inc/clr/fs/path.h b/lib/coreclr/src/inc/clr/fs/path.h new file mode 100644 index 0000000000..7c1995ecb2 --- /dev/null +++ b/lib/coreclr/src/inc/clr/fs/path.h @@ -0,0 +1,141 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header provides general path-related file system services. + +#ifndef _clr_fs_Path_h_ +#define _clr_fs_Path_h_ + +#include "clrtypes.h" +#include "cor.h" // SELECTANY + +#include "strsafe.h" + +#include "clr/str.h" + +#ifndef LONG_FORMAT_PATH_PREFIX + #define LONG_FORMAT_PATH_PREFIX W("\\\\?\\") +#endif + +namespace clr +{ + namespace fs + { + // This list taken from ndp/clr/src/bcl/system/io/path.cs + SELECTANY WCHAR const g_rgInvalidPathChars[] = + { W('"'), W('<'), W('>'), W('|'), W('\0'), (WCHAR)1, (WCHAR)2, (WCHAR)3, (WCHAR)4, (WCHAR)5, (WCHAR)6, + (WCHAR)7, (WCHAR)8, (WCHAR)9, (WCHAR)10, (WCHAR)11, (WCHAR)12, (WCHAR)13, (WCHAR)14, + (WCHAR)15, (WCHAR)16, (WCHAR)17, (WCHAR)18, (WCHAR)19, (WCHAR)20, (WCHAR)21, (WCHAR)22, + (WCHAR)23, (WCHAR)24, (WCHAR)25, (WCHAR)26, (WCHAR)27, (WCHAR)28, (WCHAR)29, (WCHAR)30, + (WCHAR)31 }; + + class Path + { + public: + //----------------------------------------------------------------------------------------- + static inline bool + Exists( + LPCWSTR wzPath) + { + DWORD attrs = WszGetFileAttributes(wzPath); + return (attrs != INVALID_FILE_ATTRIBUTES); + } + + //----------------------------------------------------------------------------------------- + // Returns true if wzPath represents a long format path (i.e., prefixed with '\\?\'). + static inline bool + HasLongFormatPrefix(LPCWSTR wzPath) + { + _ASSERTE(!clr::str::IsNullOrEmpty(wzPath)); // Must check this first. + return wcscmp(wzPath, LONG_FORMAT_PATH_PREFIX) == 0; + } + + //----------------------------------------------------------------------------------------- + // Returns true if wzPath represents a relative path. + static inline bool + IsRelative(LPCWSTR wzPath) + { + _ASSERTE(wzPath != nullptr); + + // Similar to System.IO.Path.IsRelative() +#if PLATFORM_UNIX + if(wzPath[0] == VOLUME_SEPARATOR_CHAR_W) + { + return false; + } +#else + // Check for a paths like "C:\..." or "\\...". Additional notes: + // - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix + // - "\..." - these paths are relative, as they depend on the current drive + // - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C + if (wzPath[0] != W('\0') && + wzPath[1] == VOLUME_SEPARATOR_CHAR_W && + wzPath[2] == DIRECTORY_SEPARATOR_CHAR_W && + ( + (wzPath[0] >= W('A') && wzPath[0] <= W('Z')) || + (wzPath[0] >= W('a') && wzPath[0] <= W('z')) + )) + { + return false; + } + if (wzPath[0] == DIRECTORY_SEPARATOR_CHAR_W && wzPath[1] == DIRECTORY_SEPARATOR_CHAR_W) + { + return false; + } +#endif + + return true; + } + + //----------------------------------------------------------------------------------------- + // Combines two path parts. wzPathLeft must be a directory path and may be either absolute + // or relative. wzPathRight may be a directory or file path and must be relative. The + // result is placed in wzBuffer and the number of chars written is placed in pcchBuffer on + // success; otherwise an error HRESULT is returned. + static HRESULT + Combine(LPCWSTR wzPathLeft, LPCWSTR wzPathRight, __in DWORD *pcchBuffer, __out_ecount(*pcchBuffer) LPWSTR wzBuffer) + { + STATIC_CONTRACT_NOTHROW; + + HRESULT hr = S_OK; + + if (clr::str::IsNullOrEmpty(wzPathLeft) || clr::str::IsNullOrEmpty(wzPathRight) || pcchBuffer == nullptr) + return E_INVALIDARG; + + LPWSTR wzBuf = wzBuffer; + size_t cchBuf = *pcchBuffer; + + IfFailRet(StringCchCopyExW(wzBuf, cchBuf, wzPathLeft, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); + IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzBuf[-1] == DIRECTORY_SEPARATOR_CHAR_W ? W("") : DIRECTORY_SEPARATOR_STR_W, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); + IfFailRet(StringCchCatExW(wzBuf, cchBuf, wzPathRight, &wzBuf, &cchBuf, STRSAFE_NULL_ON_FAILURE)); + + return S_OK; + } + + //----------------------------------------------------------------------------------------- + // Checks if the path provided is valid within the specified constraints. + // ***NOTE: does not yet check for invalid path characters. + static bool + IsValid(LPCWSTR wzPath, DWORD cchPath, bool fAllowLongFormat) + { + if (clr::str::IsNullOrEmpty(wzPath)) + return false; + + bool fIsLongFormat = HasLongFormatPrefix(wzPath); + + if (fIsLongFormat && !fAllowLongFormat) + return false; + + if (!fIsLongFormat && cchPath > _MAX_PATH) + return false; + + return true; + } + }; + } +} + +#endif // _clr_fs_Path_h_ diff --git a/lib/coreclr/src/inc/clr/stack.h b/lib/coreclr/src/inc/clr/stack.h new file mode 100644 index 0000000000..f9741b274f --- /dev/null +++ b/lib/coreclr/src/inc/clr/stack.h @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header provides a basic stack implementation + +#ifndef _clr_Stack_h_ +#define _clr_Stack_h_ + +namespace clr +{ + //------------------------------------------------------------------------------------------------- + // A basic stack class. + // + template < typename T > + class Stack + { + private: + //--------------------------------------------------------------------------------------------- + struct Link + { + template < typename A1 > + Link(A1 && a1, Link * next = nullptr) + : _value(std::forward(a1)) + , _next(next) + {} + + T _value; + Link * _next; + }; + + public: + //--------------------------------------------------------------------------------------------- + // Empty stack constructor. + Stack() + : _top(nullptr) + , _size(0) + {} + + //--------------------------------------------------------------------------------------------- + // Move constructor. + Stack(Stack && stack) + : _top(nullptr) + , _size(0) + { *this = std::move(stack); } + + //--------------------------------------------------------------------------------------------- + ~Stack() + { + while (!empty()) + { + pop(); + } + } + + //--------------------------------------------------------------------------------------------- + // Move assignment. + Stack& operator=(Stack && stack) + { std::swap(_top, stack._top); std::swap(_size, stack._size); } + + //--------------------------------------------------------------------------------------------- + bool empty() const + { return _top == nullptr; } + + //--------------------------------------------------------------------------------------------- + size_t size() const + { return _size; } + + //--------------------------------------------------------------------------------------------- + T & top() + { return _top->_value; } + + //--------------------------------------------------------------------------------------------- + T const & top() const + { return _top->_value; } + + //--------------------------------------------------------------------------------------------- + template < typename A1 > inline + void push(A1 && value) + { + STATIC_CONTRACT_THROWS; + _top = new Link(std::forward(value), _top); + ++_size; + } + + //--------------------------------------------------------------------------------------------- + void pop() + { Link * del = _top; _top = _top->_next; --_size; delete del; } + + private: + //--------------------------------------------------------------------------------------------- + Link * _top; + size_t _size; + }; +} // namespace clr + +#endif // _clr_Stack_h_ diff --git a/lib/coreclr/src/inc/clr/str.h b/lib/coreclr/src/inc/clr/str.h new file mode 100644 index 0000000000..94c8ed46b5 --- /dev/null +++ b/lib/coreclr/src/inc/clr/str.h @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// This header provides general standard string services. +// + +#ifndef _clr_str_h_ +#define _clr_str_h_ + +namespace clr +{ + namespace str + { + //----------------------------------------------------------------------------------------- + // Returns true if the provided string is a null pointer or the empty string. + static inline bool + IsNullOrEmpty(LPCWSTR wzStr) + { + return wzStr == nullptr || *wzStr == W('\0'); + } + } +} + +#endif // _clr_str_h_ + diff --git a/lib/coreclr/src/inc/clr/win32.h b/lib/coreclr/src/inc/clr/win32.h new file mode 100644 index 0000000000..a0e00c6321 --- /dev/null +++ b/lib/coreclr/src/inc/clr/win32.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// clr/win32.h +// +// Provides Win32-specific utility functionality. +// + +// + +#ifndef clr_win32_h +#define clr_win32_h + +#include "winwrap.h" + +namespace clr +{ + namespace win32 + { + // Prevents an HMODULE from being unloaded until process termination. + inline + HRESULT PreventModuleUnload(HMODULE hMod) + { + if (!WszGetModuleHandleEx( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, + reinterpret_cast(hMod), + &hMod)) + { + return HRESULT_FROM_GetLastError(); + } + + return S_OK; + } + } // namespace win +} // namespace clr + +#endif // clr_win32_h diff --git a/lib/coreclr/src/inc/clr_std/algorithm b/lib/coreclr/src/inc/clr_std/algorithm new file mode 100644 index 0000000000..92b4e8ece6 --- /dev/null +++ b/lib/coreclr/src/inc/clr_std/algorithm @@ -0,0 +1,119 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/algorithm +// +// Copy of some key Standard Template Library functionality + +#ifdef _MSC_VER +#pragma once +#endif + +#ifdef USE_STL +#include +#else +#ifndef __clr_std_algorithm_h__ +#define __clr_std_algorithm_h__ + +namespace std +{ + template + iter find_if ( iter first, iter last, CompareFunc comp ) + { + for ( ; first!=last ; first++ ) + if ( comp(*first) ) + break; + return first; + } + + template + iter find(iter first, iter last, const T& val) + { + for (;first != last; first++) + { + if (*first == val) + break; + } + return first; + } + + template + iter qsort_partition( iter first, iter last, iter pivot, comp compare ) + { + iter lastMinusOne = last - 1; + swap(pivot, lastMinusOne); + + // Pivot is at end + pivot = last - 1; + + iter partitionLoc = first; + + for (iter partitionWalk = first; partitionWalk != pivot; ++partitionWalk) + { + if (compare(*partitionWalk, *pivot)) + { + swap(*partitionWalk, *partitionLoc); + partitionLoc++; + } + } + swap(*pivot, *partitionLoc); + + return partitionLoc; + } + + template + void sort_worker ( iter first, iter last, comp compare ) + { + typename iter::difference_type RangeSize = last - first; + + // When down to a list of size 1, be done + if (RangeSize < 2) + return; + + // Pick pivot + + // Use simple pick middle algorithm + iter pivotLoc = first + (RangeSize / 2); + + // Partition + pivotLoc = qsort_partition(first, last, pivotLoc, compare); + + // Sort first array + sort_worker(first, pivotLoc, compare); + + // Sort second array + sort_worker(pivotLoc + 1, last, compare); + } + + template + void sort ( iter first, iter last, comp compare ) + { + sort_worker(first, last, compare); + if (first != last) + { + for (iter i = first; i < (last - 1); i++) + { + // Assert that the sort function works. + assert(!compare(*(i+1), *i)); + } + } + } + + template + OutIter transform( InIter first, InIter last, OutIter dest, Fn1 func ) + { + for ( ; first!=last ; ++first, ++dest ) + *dest = func(*first); + return dest; + } + +} // namespace std + +#endif /* __clr_std_algorithm_h__ */ + +#endif // !USE_STL + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp diff --git a/lib/coreclr/src/inc/clr_std/string b/lib/coreclr/src/inc/clr_std/string new file mode 100644 index 0000000000..66f219c8a8 --- /dev/null +++ b/lib/coreclr/src/inc/clr_std/string @@ -0,0 +1,426 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/string +// +// Copy of some key Standard Template Library functionality +// +// This was created for use with SuperPMI. It has the minimal functionality needed by SuperPMI. It hasn't +// been tested elsewhere. + +#ifdef _MSC_VER +#pragma once +#endif + +#ifdef USE_STL +#include +#else +#ifndef __clr_std_string_h__ +#define __clr_std_string_h__ + +#include "clr_std/vector" + +namespace std +{ + +template +class basic_string +{ +public: + typedef T value_type; + typedef size_t size_type; + typedef typename vector::iterator iterator; + typedef typename vector::const_iterator const_iterator; + + basic_string() + : m_string(1) // start with a string of length 1 for null terminator + { + m_string[0] = T(); + } + + basic_string(const basic_string& _Right) + { + assign(_Right); + } + + // Initialize a string with _Count characters from the string pointed at by _Ptr. + // If you want to include the trailing null character, _Count needs to include that. + basic_string(const value_type* _Ptr, size_type _Count) + : m_string(_Count + 1) // add 1 for a null terminator + { + copy(_Ptr, _Count); + } + + basic_string(const value_type* _Ptr) : basic_string(_Ptr, c_len(_Ptr)) + { + } + + void reserve(size_t newcapacity) + { + m_string.reserve(newcapacity + 1); // add 1 for the null terminator + } + + // + // Assignment + // + + basic_string& operator=(const basic_string& _Right) + { + if (this != &_Right) + { + assign(_Right); + } + return (*this); + } + + basic_string& assign(const basic_string& _Right) + { + m_string.resize(_Right.size() + 1); // +1 for null terminator + copy(_Right); + return (*this); + } + + // + // Basic data copying + // + + void copy(const basic_string& _Right) + { + assert(size() >= _Right.size()); + size_type i; + for (i = 0; i < _Right.size(); i++) + { + m_string[i] = _Right.m_string[i]; + } + m_string[i] = T(); + } + + void copy(const value_type* _Ptr, size_type _Count) + { + assert(size() >= _Count); + size_type i; + for (i = 0; i < _Count; i++) + { + m_string[i] = _Ptr[i]; + } + m_string[i] = T(); + } + + // + // Appending + // + + // Append a C-style string to the string. + basic_string& operator+=(const value_type* _Ptr) + { + size_type oldsize = size(); // doesn't include null terminator + size_type addsize = c_len(_Ptr); // doesn't include null terminator + size_type newsize = oldsize + addsize + 1; + m_string.resize(newsize); + size_type i; + for (i = oldsize; i < newsize - 1; i++) + { + m_string[i] = *_Ptr++; + } + m_string[i] = T(); + return (*this); + } + + basic_string& operator+=(const basic_string& _Right) + { + size_type oldsize = size(); // doesn't include null terminator + size_type addsize = _Right.size(); // doesn't include null terminator + size_type newsize = oldsize + addsize + 1; + m_string.resize(newsize); + size_type new_index = oldsize, right_index = 0; + while (right_index < addsize) + { + m_string[new_index] = _Right.m_string[right_index]; + ++new_index; + ++right_index; + } + m_string[new_index] = T(); + return (*this); + } + + basic_string& operator+=(value_type _Ch) + { + size_type oldsize = size(); // doesn't include null terminator + m_string[oldsize] = _Ch; // Replace the null terminator with the new symbol. + m_string.push_back(T()); // Return the replaced terminator again. + return (*this); + } + + ~basic_string() + { + // vector destructor does all the work + } + + size_t size() const + { + assert(m_string.size() > 0); + return m_string.size() - 1; // Don't report the null terminator. + } + + size_t length() const + { + return size(); + } + + T& operator[](size_t iIndex) + { + assert(iIndex < size() + 1); // allow looking at the null terminator + return m_string[iIndex]; + } + + const T* c_str() const + { + return m_string.data(); + } + + iterator begin() + { + return m_string.begin(); + } + + iterator end() + { + return m_string.end(); + } + + const_iterator cbegin() const + { + return m_string.cbegin(); + } + + const_iterator cend() const + { + return m_string.cend(); + } + + basic_string substr(size_type _Off = 0, size_type _Count = npos) const + { + size_type cursize = size(); + if (_Off >= cursize) + { + // result will be empty + return basic_string(); + } + else + { + if ((_Count == npos) || // No count specified; take the whole string suffix + (_Off + _Count > cursize)) // Count specified is too many characters; just take the whole suffix + { + _Count = cursize - _Off; + } + return basic_string(m_string.data() + _Off, _Count); + } + } + + size_type find_last_of(value_type _Ch) const + { + for (size_type _Off = size(); _Off != 0; _Off--) + { + if (m_string[_Off - 1] == _Ch) + { + return _Off - 1; + } + } + return npos; + } + + bool empty() const + { + return size() == 0; + } + + int compare(const basic_string& _Str) const + { + size_type i; + size_type compareSize = size(); + if (_Str.size() < compareSize) + { + // This string is longer; compare character-by-character only as many characters as we have. + compareSize = _Str.size(); + } + for (i = 0; i < compareSize; i++) + { + if (m_string[i] != _Str.m_string[i]) + { + if (m_string[i] < _Str.m_string[i]) + { + return -1; + } + else + { + return 1; + } + } + } + + // All the characters we compared were identical, but one string might be longer than the other. + if (size() == _Str.size()) + { + // We compared everything. + return 0; + } + else if (size() < _Str.size()) + { + // _Str has more characters than this. + return -1; + } + else + { + // this has more characters than _Str + return 1; + } + } + + static const size_type npos = size_type(-1); + +private: + + // Compute the length in characters of a null-terminated C-style string, not including the trailing null character. + // _Ptr must not be nullptr. + size_type c_len(const value_type* _Ptr) + { + size_type count; + for (count = 0; *_Ptr != T(); _Ptr++) + { + count++; + } + return count; + } + + vector m_string; // use a vector<> to represent the string, to avoid reimplementing similar functionality + +}; // class basic_string + +// +// String class instantiations +// + +typedef basic_string string; + +// +// Numeric conversions +// + +// convert integer T to string +template inline +string _IntToString(const char *_Fmt, T _Val) +{ + const size_t MaxIntBufSize = 21; /* can hold -2^63 and 2^64 - 1, plus NUL */ + char buf[MaxIntBufSize]; + int len = sprintf_s(buf, MaxIntBufSize, _Fmt, _Val); + return (string(buf, len)); +} + +inline string to_string(int _Val) +{ + return (_IntToString("%d", _Val)); +} + +inline string to_string(unsigned int _Val) +{ + return (_IntToString("%u", _Val)); +} + +inline string to_string(long _Val) +{ + return (_IntToString("%ld", _Val)); +} + +inline string to_string(unsigned long _Val) +{ + return (_IntToString("%lu", _Val)); +} + +inline string to_string(long long _Val) +{ + return (_IntToString("%lld", _Val)); +} + +inline string to_string(unsigned long long _Val) +{ + return (_IntToString("%llu", _Val)); +} + +// +// Comparisons +// + +template inline +bool operator==( + const basic_string& _Left, + const basic_string& _Right) +{ + return (_Left.compare(_Right) == 0); +} + +template inline +bool operator!=( + const basic_string& _Left, + const basic_string& _Right) +{ + return (!(_Left == _Right)); +} + +template inline +bool operator<( + const basic_string& _Left, + const basic_string& _Right) +{ + return (_Left.compare(_Right) < 0); +} + +template inline +bool operator>( + const basic_string& _Left, + const basic_string& _Right) +{ + return (_Right < _Left); +} + +template inline +bool operator<=( + const basic_string& _Left, + const basic_string& _Right) +{ + return (!(_Right < _Left)); +} + +template inline +bool operator>=( + const basic_string& _Left, + const basic_string& _Right) +{ + return (!(_Left < _Right)); +} + +// +// String concatenation and other string operations +// + +template inline +basic_string operator+( + const basic_string& _Left, + const basic_string& _Right) +{ + basic_string ret; + ret.reserve(_Left.size() + _Right.size()); + ret += _Left; + ret += _Right; + return ret; +} + +}; // namespace std + +#endif /* __clr_std_string_h__ */ + +#endif // !USE_STL + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp diff --git a/lib/coreclr/src/inc/clr_std/type_traits b/lib/coreclr/src/inc/clr_std/type_traits new file mode 100644 index 0000000000..090694e320 --- /dev/null +++ b/lib/coreclr/src/inc/clr_std/type_traits @@ -0,0 +1,549 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/utility +// +// Copy of some key Standard Template Library functionality. +// See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation. +// + +#ifdef _MSC_VER +#pragma once +#endif + +#ifndef __clr_std_type_traits_h__ +#define __clr_std_type_traits_h__ + +#ifdef USE_STL + +#include + +#else + +namespace std +{ + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_const + template + struct remove_const + { // remove top level const qualifier + typedef _Ty type; + }; + + template + struct remove_const + { // remove top level const qualifier + typedef _Ty type; + }; + + template + struct remove_const + { // remove top level const qualifier + typedef _Ty type[]; + }; + + template + struct remove_const + { // remove top level const qualifier + typedef _Ty type[_Nx]; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_volatile + template + struct remove_volatile + { // remove top level volatile qualifier + typedef _Ty type; + }; + + template + struct remove_volatile + { // remove top level volatile qualifier + typedef _Ty type; + }; + + template + struct remove_volatile + { // remove top level volatile qualifier + typedef _Ty type[]; + }; + + template + struct remove_volatile + { // remove top level volatile qualifier + typedef _Ty type[_Nx]; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_cv + template + struct remove_cv + { // remove top level const and volatile qualifiers + typedef typename remove_const::type>::type type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE remove_reference + template + struct remove_reference + { // remove reference + typedef T type; + }; + + template + struct remove_reference + { // remove reference + typedef T type; + }; + + template + struct remove_reference + { // remove rvalue reference + typedef T type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE remove_pointer + template + struct remove_pointer + { // remove pointer + typedef T type; + }; + + template + struct remove_pointer + { // remove pointer + typedef T type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE FUNCTION identity + template + struct identity + { // map T to type unchanged + typedef T type; + + inline + const T& operator()(const T& left) const + { // apply identity operator to operand + return (left); + } + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS integral_constant + template + struct integral_constant + { // convenient template for integral constant types + static const _Ty value = _Val; + + typedef _Ty value_type; + typedef integral_constant<_Ty, _Val> type; + }; + + typedef integral_constant true_type; + typedef integral_constant false_type; + + // TEMPLATE CLASS _Cat_base + template + struct _Cat_base + : false_type + { // base class for type predicates + }; + + template<> + struct _Cat_base + : true_type + { // base class for type predicates + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS enable_if + template + struct enable_if + { // type is undefined for assumed !_Test + }; + + template + struct enable_if + { // type is _Type for _Test + typedef _Type type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS conditional + template + struct conditional + { // type is _Ty2 for assumed !_Test + typedef _Ty2 type; + }; + + template + struct conditional + { // type is _Ty1 for _Test + typedef _Ty1 type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_lvalue_reference + template + struct is_lvalue_reference + : false_type + { // determine whether _Ty is an lvalue reference + }; + + template + struct is_lvalue_reference<_Ty&> + : true_type + { // determine whether _Ty is an lvalue reference + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_rvalue_reference + template + struct is_rvalue_reference + : false_type + { // determine whether _Ty is an rvalue reference + }; + + template + struct is_rvalue_reference<_Ty&&> + : true_type + { // determine whether _Ty is an rvalue reference + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_reference + template + struct is_reference + : conditional< + is_lvalue_reference<_Ty>::value || is_rvalue_reference<_Ty>::value, + true_type, + false_type>::type + { // determine whether _Ty is a reference + }; + + // TEMPLATE CLASS is_pointer + template + struct is_pointer + : false_type + { // determine whether _Ty is a pointer + }; + + template + struct is_pointer<_Ty *> + : true_type + { // determine whether _Ty is a pointer + }; + + // TEMPLATE CLASS _Is_integral + template + struct _Is_integral + : false_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + #ifdef _NATIVE_WCHAR_T_DEFINED + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + #endif /* _NATIVE_WCHAR_T_DEFINED */ + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + +// On Unix 'long' is a 64-bit type (same as __int64) and the following two definitions +// conflict with _Is_integral and _Is_integral. +#ifndef PLATFORM_UNIX + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; +#endif /* PLATFORM_UNIX */ + + #if _HAS_CHAR16_T_LANGUAGE_SUPPORT + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + #endif /* _HAS_CHAR16_T_LANGUAGE_SUPPORT */ + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral + : true_type + { // determine whether _Ty is integral + }; + + // TEMPLATE CLASS is_integral + template + struct is_integral + : _Is_integral::type> + { // determine whether _Ty is integral + }; + + // TEMPLATE CLASS _Is_floating_point + template + struct _Is_floating_point + : false_type + { // determine whether _Ty is floating point + }; + + template<> + struct _Is_floating_point + : true_type + { // determine whether _Ty is floating point + }; + + template<> + struct _Is_floating_point + : true_type + { // determine whether _Ty is floating point + }; + +// In PAL, we define long as int and so this becomes int double, +// which is a nonsense +#ifndef FEATURE_PAL + template<> + struct _Is_floating_point + : true_type + { // determine whether _Ty is floating point + }; +#endif + + // TEMPLATE CLASS is_floating_point + template + struct is_floating_point + : _Is_floating_point::type> + { // determine whether _Ty is floating point + }; + + // TEMPLATE CLASS is_arithmetic + template + struct is_arithmetic + : _Cat_base::value + || is_floating_point<_Ty>::value> + { // determine whether _Ty is an arithmetic type + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_signed + template + struct is_signed : conditional< + static_cast::type>(-1) < 0, true_type, false_type>::type {}; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_same + template + struct is_same : false_type { }; + + //----------------------------------------------------------------------------------------- + template + struct is_same : true_type { }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_base_of +#ifdef _MSC_VER + + template + struct is_base_of : + conditional<__is_base_of( TBase, TDerived), true_type, false_type>::type {}; + +#else + namespace detail + { + //------------------------------------------------------------------------------------- + // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) + // + + template + struct conversion_helper + { + typedef char Small; + struct Big { char dummy[2]; }; + static Big Test(...); + static Small Test(U); + static T MakeT(); + }; + + //------------------------------------------------------------------------------------- + // class template conversion + // Figures out the conversion relationships between two types + // Invocations (T and U are types): + // a) conversion::exists + // returns (at compile time) true if there is an implicit conversion from T + // to U (example: Derived to Base) + // b) conversion::exists2Way + // returns (at compile time) true if there are both conversions from T + // to U and from U to T (example: int to char and back) + // c) conversion::sameType + // returns (at compile time) true if T and U represent the same type + // + // NOTE: might not work if T and U are in a private inheritance hierarchy. + // + + template + struct conversion + { + typedef detail::conversion_helper H; + static const bool exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))); + static const bool exists2Way = exists && conversion::exists; + static const bool sameType = false; + }; + + template + struct conversion + { + static const bool exists = true; + static const bool exists2Way = true; + static const bool sameType = true; + }; + + template + struct conversion + { + static const bool exists = false; + static const bool exists2Way = false; + static const bool sameType = false; + }; + + template + struct conversion + { + static const bool exists = false; + static const bool exists2Way = false; + static const bool sameType = false; + }; + + template <> + struct conversion + { + static const bool exists = true; + static const bool exists2Way = true; + static const bool sameType = true; + }; + } // detail + + // Note that we need to compare pointer types here, since conversion of types by-value + // just tells us whether or not an implicit conversion constructor exists. We handle + // type parameters that are already pointers specially; see below. + template + struct is_base_of : + conditional::exists, true_type, false_type>::type {}; + + // Specialization to handle type parameters that are already pointers. + template + struct is_base_of : + conditional::exists, true_type, false_type>::type {}; + + // Specialization to handle invalid mixing of pointer types. + template + struct is_base_of : + false_type {}; + + // Specialization to handle invalid mixing of pointer types. + template + struct is_base_of : + false_type {}; + +#endif + + // Use to determine if a template type parameter is a string. + template + struct is_cstr + : public std::false_type + {}; + + template + struct is_cstr< T* > + : public std::conditional< + std::is_same::type, char>::value || + std::is_same::type, wchar_t>::value, + std::true_type, + std::false_type>::type + + { }; + +} // namespace std + +#endif // !USE_STL + +#define REM_CONST(T) typename std::remove_const< T >::type +#define REM_CV(T) typename std::remove_cv< T >::type +#define REM_REF(T) typename std::remove_reference< T >::type + +#define REF_T(T) REM_REF(T) & +#define REF_CT(T) REM_REF(REM_CONST(T)) const & + +#endif // __clr_std_type_traits_h__ + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp diff --git a/lib/coreclr/src/inc/clr_std/utility b/lib/coreclr/src/inc/clr_std/utility new file mode 100644 index 0000000000..fa2267578e --- /dev/null +++ b/lib/coreclr/src/inc/clr_std/utility @@ -0,0 +1,254 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/utility +// +// Copy of some key Standard Template Library functionality +// See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation. +// + +#ifdef _MSC_VER +#pragma once +#endif + +#ifdef USE_STL +#include +#else +#ifndef __clr_std_utility_h__ +#define __clr_std_utility_h__ + +#include "clr_std/type_traits" + +namespace std +{ + //----------------------------------------------------------------------------------------- + // TEMPLATE FUNCTION move + template inline + typename remove_reference::type&& + move(T&& arg) + { // forward _Arg as movable + return ((typename remove_reference::type&&)arg); + } + + //----------------------------------------------------------------------------------------- + // TEMPLATE FUNCTION swap (from ) + template inline + void swap(T& left, T& right) + { // exchange values stored at left and right + T tmp = std::move(left); + left = std::move(right); + right = std::move(tmp); + } + + //----------------------------------------------------------------------------------------- + // TEMPLATE FUNCTION forward + template inline + T&& + forward(typename identity::type& _Arg) + { // forward _Arg, given explicitly specified type parameter + return ((T&&)_Arg); + } +} + +namespace std +{ + //----------------------------------------------------------------------------------------- + // TEMPLATE STRUCT pair + template + struct pair + { // store a pair of values + typedef pair<_Ty1, _Ty2> _Myt; + typedef _Ty1 first_type; + typedef _Ty2 second_type; + + pair() + : first(_Ty1()), second(_Ty2()) + { // construct from defaults + } + + pair(const _Ty1& _Val1, const _Ty2& _Val2) + : first(_Val1.first), second(_Val2.second) + { // construct from specified values + } + + template + pair(pair<_Other1, _Other2>& _Right) + : first(_Right.first), second(_Right.second) + { // construct from compatible pair + } + + template + pair(const pair<_Other1, _Other2>& _Right) + : first(_Right.first), second(_Right.second) + { // construct from compatible pair + } + + void swap(_Myt& _Right) + { // exchange contents with _Right + if (this != &_Right) + { // different, worth swapping + swap(this->first, _Right.first); + swap(this->second, _Right.second); + } + } + + _Myt& operator=(const _Myt& _Right) + { // assign from copied pair + this->first = _Right.first; + this->second = _Right.second; + return (*this); + } + + typedef typename remove_reference<_Ty1>::type _Ty1x; + typedef typename remove_reference<_Ty2>::type _Ty2x; + + pair(_Ty1x&& _Val1, _Ty2x&& _Val2) + : first(std::move(_Val1)), + second(std::move(_Val2)) + { // construct from specified values + } + + pair(const _Ty1x& _Val1, _Ty2x&& _Val2) + : first(_Val1), + second(std::move(_Val2)) + { // construct from specified values + } + + pair(_Ty1x&& _Val1, const _Ty2x& _Val2) + : first(std::move(_Val1)), + second(_Val2) + { // construct from specified values + } + + template + pair(_Other1&& _Val1, _Other2&& _Val2) + : first(std::move(_Val1)), + second(std::move(_Val2)) + { // construct from moved values + } + + template + pair(pair<_Other1, _Other2>&& _Right) + : first(std::move(_Right.first)), + second(std::move(_Right.second)) + { // construct from moved compatible pair + } + + pair& operator=(pair<_Ty1, _Ty2>&& _Right) + { // assign from moved pair + this->first = std::move(_Right.first); + this->second = std::move(_Right.second); + return (*this); + } + + void swap(_Myt&& _Right) + { // exchange contents with _Right + if (this != &_Right) + { // different, worth swapping + this->first = std::move(_Right.first); + this->second = std::move(_Right.second); + } + } + + _Ty1 first; // the first stored value + _Ty2 second; // the second stored value + }; // struct pair + + //----------------------------------------------------------------------------------------- + // pair TEMPLATE FUNCTIONS + + template inline + void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) + { // swap _Left and _Right pairs + _Left.swap(_Right); + } + + template inline + void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>&& _Right) + { // swap _Left and _Right pairs + typedef pair<_Ty1, _Ty2> _Myt; + _Left.swap(std::forward<_Myt>(_Right)); + } + + template inline + void swap( + pair<_Ty1, _Ty2>&& _Left, + pair<_Ty1, _Ty2>& _Right) + { // swap _Left and _Right pairs + typedef pair<_Ty1, _Ty2> _Myt; + _Right.swap(std::forward<_Myt>(_Left)); + } + + template inline + bool operator==( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test for pair equality + return (_Left.first == _Right.first && _Left.second == _Right.second); + } + + template inline + bool operator!=( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test for pair inequality + return (!(_Left == _Right)); + } + + template inline + bool operator<( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test if _Left < _Right for pairs + return (_Left.first < _Right.first || + (!(_Right.first < _Left.first) && _Left.second < _Right.second)); + } + + template inline + bool operator>( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test if _Left > _Right for pairs + return (_Right < _Left); + } + + template inline + bool operator<=( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test if _Left <= _Right for pairs + return (!(_Right < _Left)); + } + + template inline + bool operator>=( + const pair<_Ty1, _Ty2>& _Left, + const pair<_Ty1, _Ty2>& _Right) + { // test if _Left >= _Right for pairs + return (!(_Left < _Right)); + } + + template inline + _InIt begin( + const pair<_InIt, _InIt>& _Pair) + { // return first element of pair + return (_Pair.first); + } + + template inline + _InIt end( + const pair<_InIt, _InIt>& _Pair) + { // return second element of pair + return (_Pair.second); + } + +} // namespace std + +#endif /* __clr_std_utility_h__ */ + +#endif // !USE_STL + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp diff --git a/lib/coreclr/src/inc/clr_std/vector b/lib/coreclr/src/inc/clr_std/vector new file mode 100644 index 0000000000..c81674617a --- /dev/null +++ b/lib/coreclr/src/inc/clr_std/vector @@ -0,0 +1,431 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/vector +// +// Copy of some key Standard Template Library functionality +// + +#ifdef _MSC_VER +#pragma once +#endif + +#ifdef USE_STL +#include +#else +#ifndef __clr_std_vector_h__ +#define __clr_std_vector_h__ + +// This is defined in the debugmacrosext.h header, but don't take a dependency on that. +#ifndef INDEBUG +#ifdef _DEBUG +#define INDEBUG(x) x +#else +#define INDEBUG(x) +#endif +#endif // !def INDEBUG + +namespace std +{ + template + class vector + { + public: + class const_iterator; + + class iterator + { + friend class std::vector::const_iterator; + public: + typedef T value_type; + typedef ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; + + typedef class vector::iterator _MyIter; + + _MyIter &operator++() + { + m_ptr++; + return *this; + } + + _MyIter operator++(int) + { + // post-increment ++ + _MyIter myiter(m_ptr); + m_ptr++; + return myiter; + } + + _MyIter &operator--() + { + m_ptr--; + return *this; + } + + _MyIter operator--(int) + { + // post-decrement -- + _MyIter myiter(m_ptr); + m_ptr--; + return myiter; + } + + _MyIter operator- (ptrdiff_t n) + { + _MyIter myiter(m_ptr); + myiter.m_ptr -= n; + return myiter; + } + + ptrdiff_t operator- (_MyIter right) + { + _MyIter myiter(m_ptr); + return myiter.m_ptr - right.m_ptr; + } + + _MyIter operator+ (ptrdiff_t n) + { + _MyIter myiter(m_ptr); + myiter.m_ptr += n; + return myiter; + } + + T* operator->() const + { + return m_ptr; + } + + T & operator*() const + { + return *m_ptr; + } + + bool operator==(const _MyIter& _Right) const + { + bool equals = this->m_ptr == _Right.m_ptr; + return equals; + } + + bool operator!=(const _MyIter& _Right) const + { + bool equals = this->m_ptr == _Right.m_ptr; + return !equals; + } + + bool operator<(const _MyIter& _Right) const + { + return this->m_ptr < _Right.m_ptr; + } + + bool operator>(const _MyIter& _Right) const + { + return this->m_ptr > _Right.m_ptr; + } + public: + explicit iterator(T* ptr) + { + m_ptr = ptr; + } + + private: + T* m_ptr; + }; // class iterator + + class const_iterator + { + public: + typedef class vector::const_iterator _MyIter; + typedef class vector::iterator _MyNonConstIter; + + _MyIter &operator++() + { + m_ptr++; + return *this; + } + + _MyIter operator++(int) + { + // post-increment ++ + _MyIter myiter(m_ptr); + m_ptr++; + return myiter; + } + + const T* operator->() const + { + return m_ptr; + } + + const T & operator*() const + { + return *m_ptr; + } + + bool operator==(const _MyIter& _Right) const + { + bool equals = this->m_ptr == _Right.m_ptr; + return equals; + } + + bool operator!=(const _MyIter& _Right) const + { + bool equals = this->m_ptr == _Right.m_ptr; + return !equals; + } + + public: + explicit const_iterator(T* ptr) + { + m_ptr = ptr; + } + const_iterator(const _MyNonConstIter &nonConstIterator) + { + m_ptr = nonConstIterator.m_ptr; + } + + private: + T* m_ptr; + }; // class const iterator + + + public: + explicit vector(size_t n = 0) + { + m_size = 0; + m_capacity = 0; + m_pelements = NULL; + m_isBufferOwner = true; + resize(n); + } + + ~vector() + { + if (m_isBufferOwner) + { + erase(m_pelements, 0, m_size); + delete [] (BYTE*)m_pelements; // cast to BYTE* as we don't want this delete to invoke T's dtor + } + else + { + m_size = 0; + m_capacity = 0; + } + } + + + size_t size() const + { + return m_size; + } + + T & operator[](size_t iIndex) + { + assert(iIndex < m_size); + return m_pelements[iIndex]; + } + + T & operator[](size_t iIndex) const + { + assert(iIndex < m_size); + return m_pelements[iIndex]; + } + + void resize(size_t newsize) + { + assert(m_isBufferOwner); + size_t oldsize = this->size(); + resize_noinit(newsize); + if (newsize > oldsize) + { + fill_uninitialized_with_default_value(m_pelements, oldsize, newsize); + } + } + + void clear() + { + assert(m_isBufferOwner); + resize(0); + } + + void resize(size_t newsize, T c) + { + assert(m_isBufferOwner); + size_t oldsize = this->size(); + resize_noinit(newsize); + if (newsize > oldsize) + { + for (size_t i = oldsize; i < newsize; i++) + { + m_pelements[i] = c; + } + } + } + + void wrap(size_t numElements, T* pElements) + { + m_size = numElements; + m_pelements = pElements; + m_isBufferOwner = false; + } + + void resize_noinit(size_t newsize) + { + assert(m_isBufferOwner); + size_t oldsize = this->size(); + if (newsize < oldsize) + { + // Shrink + erase(m_pelements, newsize, oldsize); + } + else if (newsize > oldsize) + { + // Grow + reserve(newsize); + } + m_size = newsize; + } + + void push_back(const T & val) + { + assert(m_isBufferOwner); + if (m_size + 1 < m_size) + { + assert("push_back: overflow"); + // @todo: how to throw. + } + resize(m_size + 1, val); + } + + void reserve(size_t newcapacity) + { + assert(m_isBufferOwner); + if (newcapacity > m_capacity) + { + // To avoid resizing for every element that gets added to a vector, we + // allocate at least twice the old capacity, or 16 elements, whichever is greater. + newcapacity = max(newcapacity, max(m_capacity * 2, 16)); + + size_t bytesNeeded = newcapacity * sizeof(T); + if (bytesNeeded / sizeof(T) != newcapacity) + { + assert("resize: overflow"); + // @todo: how to throw something here? + } + + + T *pelements = (T*)(new BYTE[bytesNeeded]); // Allocate as BYTE array to avoid automatic construction + INDEBUG(memset(pelements, 0xcc, bytesNeeded)); + for (size_t i = 0; i < m_size; i++) + { + pelements[i] = m_pelements[i]; + } + + erase(m_pelements, 0, m_size); + delete [] (BYTE*)m_pelements; // cast to BYTE* as we don't want this delete to invoke T's dtor + + m_pelements = pelements; + m_capacity = newcapacity; + } + } + + iterator begin() + { + return iterator(m_pelements); + } + + iterator end() + { + return iterator(m_pelements + m_size); + } + + const_iterator cbegin() const + { + return const_iterator(m_pelements); + } + + const_iterator cend() const + { + return const_iterator(m_pelements + m_size); + } + + iterator erase(iterator position) + { + assert(m_isBufferOwner); + assert((position > begin() || position == begin()) && position < end()); + ptrdiff_t index = position - begin(); + erase(m_pelements, index, index + 1); + memcpy(&m_pelements[index], &m_pelements[index + 1], sizeof(T) * (m_size - index - 1)); + --m_size; + return iterator(m_pelements + (position - begin())); + } + + iterator erase(iterator position, iterator positionEnd) + { + assert(m_isBufferOwner); + assert((position > begin() || position == begin()) && position < end()); + ptrdiff_t index = position - begin(); + ptrdiff_t elements = positionEnd - position; + erase(m_pelements, index, index + elements); + memcpy(&m_pelements[index], &m_pelements[index + elements], sizeof(T) * (m_size - index - elements)); + m_size -= elements; + return iterator(m_pelements + (position - begin())); + } + + const T* data() const + { + return m_pelements; + } + + private: + // Transition a subset of the array from uninitialized to initialized with default value for T. + static void fill_uninitialized_with_default_value(T* pelements, size_t startIdx, size_t endIdx) + { + assert(startIdx <= endIdx); + assert(pelements != NULL || startIdx == endIdx); + for (size_t i = startIdx; i < endIdx; i++) + { + INDEBUG(assert(0xcc == *((BYTE*)&pelements[i]))); + pelements[i] = T(); + } + } + + // Transition a subset of the array from a valid value of T to uninitialized. + static void erase(T* pelements, size_t startIdx, size_t endIdx) + { + assert(startIdx <= endIdx); + assert(pelements != NULL || startIdx == endIdx); + for (size_t i = startIdx; i < endIdx; i++) + { + pelements[i].~T(); + } + + INDEBUG(memset(&pelements[startIdx], 0xcc, (endIdx - startIdx) * sizeof(T))); + } + + private: + size_t m_size; //# of elements + size_t m_capacity; //# of elements allocated + T *m_pelements; //actual array + // invariants: + // dimensions == m_capacity + // elements 0 thru m_size-1 always contain constructed T values. + // elements from m_size thru m_capacity - 1 contain memory garbage (0xcc in DEBUG). + bool m_isBufferOwner; // indicate if this vector creates its own buffer, or wraps an existing buffer. + + + + + }; // class vector + +}; // namespace std + +#endif /* __clr_std_vector_h__ */ + +#endif // !USE_STL + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp diff --git a/lib/coreclr/src/inc/clrconfig.h b/lib/coreclr/src/inc/clrconfig.h new file mode 100644 index 0000000000..7e74e65147 --- /dev/null +++ b/lib/coreclr/src/inc/clrconfig.h @@ -0,0 +1,231 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// -------------------------------------------------------------------------------------------------- +// CLRConfig.h +// + +// +// Unified method of accessing configuration values from environment variables, registry and config file(s). +// This class replaces all GetConfigDWORD and GetConfigString methods in EEConfig and REGUTIL. To define a +// flag, add an entry in the table in file:CLRConfigValues.h. +// +// +// +// +// -------------------------------------------------------------------------------------------------- + + +#include "utilcode.h" +#include "holder.h" + +#ifndef __CLRConfig_h__ +#define __CLRConfig_h__ + +class CLRConfig +{ +public: + // + // Types + // + + // Setting each option results in some change to the config value lookup method. Default behavior is (in + // the following order): + // * Look at environment variables (prepending COMPlus to the name) + // * Look at the framework registry keys (HKCU\Software\Microsoft\.NETFramework then + // HKLM\Software\Microsoft\.NETFramework) + // * Look at the available config files (system, application, host and user). For details see TODO: + // Link to BOTR documentation + enum LookupOptions { + // If set, don't look in environment variables. + IgnoreEnv = 0x1, + // If set, do not prepend "COMPlus_" when doing environment variable lookup. + DontPrependCOMPlus_ = 0x2, + // If set, don't look in HKLM in the registry. + IgnoreHKLM = 0x4, + // If set, don't look in HKCU in the registry. + IgnoreHKCU = 0x8, + // If set, don't look in any config files + IgnoreConfigFiles = 0x10, + // If set, look in config file(s) before looking in env/registry. + FavorConfigFile = 0x20, + // If set, look only in the system config file, ignoring other config files. + // (This option does not affect environment variable and registry lookups) + ConfigFile_SystemOnly = 0x40, + // If set, reverse the order of config file lookups (application config file first). + // (This option does not affect environment variable and registry lookups) + ConfigFile_ApplicationFirst = 0x80, + // Remove any whitespace at beginning and end of value. (Only applicable for + // *string* configuration values.) + TrimWhiteSpaceFromStringValue = 0x100, + + // Legacy REGUTIL-style lookup. + REGUTIL_default = IgnoreConfigFiles, + // Legacy EEConfig-style lookup. + EEConfig_default = 0, + }; + + // Function pointer definition used for calling EEConfig::GetConfigValueCallback . + typedef HRESULT (* GetConfigValueFunction) + (__in_z LPCWSTR /*pKey*/, __deref_out_opt LPCWSTR* /*value*/, BOOL /*systemOnly*/, BOOL /*applicationFirst*/); + + // Struct used to store information about where/how to find a Config DWORD. + // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead. + typedef struct ConfigDWORDInfo + { + LPCWSTR name; + DWORD defaultValue; + LookupOptions options; + } ConfigDWORDInfo; + + // Struct used to store information about where/how to find a Config String. + // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead. + typedef struct ConfigStringInfo + { + LPCWSTR name; + LookupOptions options; + } ConfigStringInfo; + + // + // Declaring structs using the macro table in CLRConfigValues.h + // + + // These macros declare ConfigDWORDInfo structs. + #define RETAIL_CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ + static const ConfigDWORDInfo symbol; + #define RETAIL_CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ + static const ConfigDWORDInfo symbol; + + // These macros declare ConfigStringInfo structs. + #define RETAIL_CONFIG_STRING_INFO(symbol, name, description) \ + static const ConfigStringInfo symbol; + #define RETAIL_CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \ + static const ConfigStringInfo symbol; + + // TEMPORARY macros that declare strings. These are used for config value accesses that haven't been + // moved over to CLRConfig yet. Once all accesses have been moved, these macros (and corresponding + // instantiations in file:../utilcode/CLRConfig.cpp) should be removed. + #define RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) \ + static const LPCWSTR symbol; + #define RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \ + static const LPCWSTR symbol; + + // + // Debug versions of the macros + // +#ifdef _DEBUG + #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ + static const ConfigDWORDInfo symbol; + #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ + static const ConfigDWORDInfo symbol; + #define CONFIG_STRING_INFO(symbol, name, description) \ + static const ConfigStringInfo symbol; + #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \ + static const ConfigStringInfo symbol; + #define CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) \ + static const LPCWSTR symbol; + #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) \ + static const LPCWSTR symbol; +#else + #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) + #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) + #define CONFIG_STRING_INFO(symbol, name, description) + #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) + #define CONFIG_DWORD_INFO_DIRECT_ACCESS(symbol, name, description) + #define CONFIG_STRING_INFO_DIRECT_ACCESS(symbol, name, description) +#endif // _DEBUG + // Now that we have defined what what the macros in file:CLRConfigValues.h mean, include it to generate the code. + #include "clrconfigvalues.h" + + #undef RETAIL_CONFIG_DWORD_INFO + #undef RETAIL_CONFIG_STRING_INFO + #undef RETAIL_CONFIG_DWORD_INFO_EX + #undef RETAIL_CONFIG_STRING_INFO_EX + #undef RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS + #undef RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS + #undef CONFIG_DWORD_INFO + #undef CONFIG_STRING_INFO + #undef CONFIG_DWORD_INFO_EX + #undef CONFIG_STRING_INFO_EX + #undef CONFIG_DWORD_INFO_DIRECT_ACCESS + #undef CONFIG_STRING_INFO_DIRECT_ACCESS + + // + // Methods to do config value (DWORD and String) lookups. + // + static BOOL IsConfigEnabled(const ConfigDWORDInfo & info); + + // Look up a DWORD config value. + static DWORD GetConfigValue(const ConfigDWORDInfo & info); + + // Look up a DWORD config value. + static DWORD GetConfigValue(const ConfigDWORDInfo & info, bool acceptExplicitDefaultFromRegutil, /* [Out] */ bool *isDefault); + + // Look up a string config value. + // You own the string that's returned. + static LPWSTR GetConfigValue(const ConfigStringInfo & info); + + // Look up a string config value, passing it out through a pointer reference. Reports out of memory + // errors (HRESULT E_OUTOFMEMORY). + // You own the string that's returned. + static HRESULT GetConfigValue(const ConfigStringInfo & info, __deref_out_z LPWSTR * outVal); + + // + // Check whether an option is specified (e.g. explicitly listed) in any of the CLRConfig + // locations: environment or registry (with or without COMPlus_) or any config file. + // The result is therefore a conservative approximation (some settings do not actually + // take effect everywhere and no setting is valid both with and without COMPlus_) + // + static BOOL IsConfigOptionSpecified(LPCWSTR name); + + // Free a string returned by GetConfigValue + static void FreeConfigString(__in __in_z LPWSTR name); + + // Register EEConfig's GetConfigValueCallback function so CLRConfig can look in config files. + static void RegisterGetConfigValueCallback(GetConfigValueFunction func); + +private: + // Function pointer to EEConfig's GetConfigValueCallback function (can't static bind from utilcode to VM) + static GetConfigValueFunction s_GetConfigValueCallback; + + + // Helper method to translate LookupOptions to REGUTIL::CORConfigLevel + static REGUTIL::CORConfigLevel GetConfigLevel(LookupOptions options); + + // + // Helper methods. + // + + // Helper method to check if a certain option is set in a ConfigDWORDInfo struct. + static inline BOOL CheckLookupOption(const ConfigDWORDInfo & info, LookupOptions option) + { + LIMITED_METHOD_CONTRACT; + return ((info.options & option) == option) ? TRUE : FALSE; + } + + // Helper method to check if a certain option is set in a ConfigStringInfo struct. + static inline BOOL CheckLookupOption(const ConfigStringInfo & info, LookupOptions option) + { + LIMITED_METHOD_CONTRACT; + return ((info.options & option) == option) ? TRUE : FALSE; + } + + // Helper method to check if a certain option is set in an options enum. + static inline BOOL CheckLookupOption(LookupOptions infoOptions, LookupOptions optionToCheck) + { + LIMITED_METHOD_CONTRACT; + return ((infoOptions & optionToCheck) == optionToCheck) ? TRUE : FALSE; + } + + static HRESULT TrimWhiteSpace(LPCWSTR wszOrig, __deref_out_z LPWSTR * pwszTrimmed); +}; + +inline CLRConfig::LookupOptions operator|(CLRConfig::LookupOptions lhs, CLRConfig::LookupOptions rhs) +{ + return static_cast(static_cast(lhs) | static_cast(rhs)); +} + +typedef Wrapper CLRConfigStringHolder; + +#endif //__CLRConfig_h__ diff --git a/lib/coreclr/src/inc/clrconfigvalues.h b/lib/coreclr/src/inc/clrconfigvalues.h new file mode 100644 index 0000000000..c034f4f689 --- /dev/null +++ b/lib/coreclr/src/inc/clrconfigvalues.h @@ -0,0 +1,829 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// CLRConfigValues.h +// + +// +// Unified method of accessing configuration values from environment variables, +// registry and config file. +// +//***************************************************************************** + +// IMPORTANT: Before adding a new config value, please read up on naming conventions (see +// code:#NamingConventions) +// +// ========== +// CONTENTS +// ========== +// * How to define config values (see code:#Define) +// * How to access config values (see code:#Access) +// * Naming conventions (see code:#NamingConventions) +// +// +// ===================================== +// #Define - Use one of the following macros to define config values. (See code:#DWORDs and code:#Strings) +// ===================================== +// +// By default, all macros are DEBUG ONLY. Add the "RETAIL_" prefix to make the config value available in retail builds. +// +// #DWORDs: +// -------------------------------------------------------------------------- +// CONFIG_DWORD_INFO(symbol, name, defaultValue, description) +// -------------------------------------------------------------------------- +// Use this macro to define a basic DWORD value. CLRConfig will look in environment variables (adding +// COMPlus_ to the name), the registry (HKLM and HKCU), and all the config files for this value. To customize +// where CLRConfig looks, use the extended version of the macro below. IMPORTANT: please follow the +// code:#NamingConventions for the symbol and the name! +// +// Example: CONFIG_DWORD_INFO(INTERNAL_AllowCrossModuleInlining, W("AllowCrossModuleInlining"), 0, "") +// +// -------------------------------------------------------------------------- +// CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) +// -------------------------------------------------------------------------- +// To customize where CLRConfig looks to get a DWORD, use the extended (_EX) version of the macro. For a list +// of options and their descriptions, see code:CLRConfig.LookupOptions +// +// Example: CONFIG_DWORD_INFO_EX(INTERNAL_EnableInternetHREFexes, W("EnableInternetHREFexes"), 0, "", +// (CLRConfig::LookupOptions) (CLRConfig::IgnoreEnv | CLRConfig::IgnoreHKCU)) +// +// #Strings: +// -------------------------------------------------------------------------- +// CONFIG_STRING_INFO(symbol, name, description) +// -------------------------------------------------------------------------- +// Defines a string value. Same rules apply as DWORDs. +// +// -------------------------------------------------------------------------- +// CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) +// -------------------------------------------------------------------------- +// Extended version of the String macro. Again, similar to the DWORD extended macro. +// +// +// =============================================================== +// #Access - Use the following overloaded method to access config values. +// =============================================================== +// From anywhere, use CLRConfig::GetConfigValue(CLRConfig::) to access any value defined in this +// file. +// +// +// =============================================================== +// #NamingConventions +// =============================================================== +// ---------------- +// #Symbol - used to access values from the source. (using CLRConfig::) +// ---------------- +// The symbol for each config value is named as such: +// ### __ ### +// +// indicates which of the following buckets the value is in: +// * INTERNAL ? this value is for internal (CLR team) use only +// * UNSUPPORTED ? this value is available to partners/developers, but is not officially supported +// * EXTERNAL ? this value is available for anyone to use and is publicly documented +// +// Examples: +// * INTERNAL_Security_FullAccessChecks +// * UNSUPPORTED_Security_DisableTransparency +// * EXTERNAL_Security_LegacyHMACMode +// +// ---------------- +// #Name - the name of the registry value or environment variable that CLRConfig looks up. +// ---------------- +// The name of each value is the same as the symbol, with one exception. Names of external values do NOT +// contain the EXTERNAL prefix. +// +// For compatibility reasons, current names do not follow the convention. +// +// Examples: +// * W("INTERNAL_Security_FullAccessChecks") +// * W("UNSUPPORTED_Security_DisableTransparency") +// * W("Security_LegacyHMACMode") <---------------------- (No EXTERNAL prefix) + +/// +/// AppDomain +/// +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_AddRejitNops, W("AddRejitNops"), "Control for the profiler rejit feature infrastructure") +CONFIG_DWORD_INFO(INTERNAL_ADDumpSB, W("ADDumpSB"), 0, "Not used") +CONFIG_DWORD_INFO(INTERNAL_ADForceSB, W("ADForceSB"), 0, "Forces sync block creation for all objects") +CONFIG_DWORD_INFO(INTERNAL_ADLogMemory, W("ADLogMemory"), 0, "Superseded by test hooks") +CONFIG_DWORD_INFO(INTERNAL_ADTakeDHSnapShot, W("ADTakeDHSnapShot"), 0, "Superseded by test hooks") +CONFIG_DWORD_INFO(INTERNAL_ADTakeSnapShot, W("ADTakeSnapShot"), 0, "Superseded by test hooks") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_EnableFullDebug, W("EnableFullDebug"), "Heavy-weight checking for AD boundary violations (AD leaks)") + +/// +/// Jit Pitching +/// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchEnabled, W("JitPitchEnabled"), (DWORD)0, "Set it to 1 to enable Jit Pitching") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMemThreshold, W("JitPitchMemThreshold"), (DWORD)0, "Do Jit Pitching when code heap usage is larger than this (in bytes)") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMethodSizeThreshold, W("JitPitchMethodSizeThreshold"), (DWORD)0, "Do Jit Pitching for methods whose native code size larger than this (in bytes)") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchTimeInterval, W("JitPitchTimeInterval"), (DWORD)0, "Time interval between Jit Pitchings in ms") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchPrintStat, W("JitPitchPrintStat"), (DWORD)0, "Print statistics about Jit Pitching") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMinVal, W("JitPitchMinVal"), (DWORD)0, "Do Jit Pitching if the value of the inner counter greater than this value (for debugging purpose only)") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMaxVal, W("JitPitchMaxVal"), (DWORD)0xffffffff, "Do Jit Pitching the value of the inner counter less then this value (for debuggin purpose only)") + +/// +/// Assembly Loader +/// +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DesignerNamespaceResolutionEnabled, W("designerNamespaceResolution"), FALSE, "Set it to 1 to enable DesignerNamespaceResolve event for WinRT types", CLRConfig::IgnoreEnv | CLRConfig::IgnoreHKLM | CLRConfig::IgnoreHKCU | CLRConfig::FavorConfigFile) +CONFIG_DWORD_INFO_EX(INTERNAL_GetAssemblyIfLoadedIgnoreRidMap, W("GetAssemblyIfLoadedIgnoreRidMap"), 0, "Used to force loader to ignore assemblies cached in the rid-map", CLRConfig::REGUTIL_default) + +/// +/// Conditional breakpoints +/// +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnBadExit, W("BreakOnBadExit"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO(INTERNAL_BreakOnClassBuild, W("BreakOnClassBuild"), "Very useful for debugging class layout code.") +CONFIG_STRING_INFO(INTERNAL_BreakOnClassLoad, W("BreakOnClassLoad"), "Very useful for debugging class loading code.") +CONFIG_STRING_INFO(INTERNAL_BreakOnComToClrNativeInfoInit, W("BreakOnComToClrNativeInfoInit"), "Throws an assert when native information about a COM -> CLR call are about to be gathered.") +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDebugBreak, W("BreakOnDebugBreak"), 0, "Allows an assert in debug builds when a user break is hit", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDILoad, W("BreakOnDILoad"), 0, "Allows an assert when the DI is loaded", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff, "Breaks when using internal logging on a particular token value.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnEELoad, W("BreakOnEELoad"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_BreakOnEEShutdown, W("BreakOnEEShutdown"), 0, "") +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnExceptionInGetThrowable, W("BreakOnExceptionInGetThrowable"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_BreakOnFindMethod, W("BreakOnFindMethod"), 0, "Breaks in findMethodInternal when it searches for the specified token.") +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnFirstPass, W("BreakOnFirstPass"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnHR, W("BreakOnHR"), 0, "Debug.cpp, IfFailxxx use this macro to stop if hr matches ", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO(INTERNAL_BreakOnInstantiation, W("BreakOnInstantiation"), "Very useful for debugging generic class instantiation.") +CONFIG_STRING_INFO(INTERNAL_BreakOnInteropStubSetup, W("BreakOnInteropStubSetup"), "Throws an assert when marshaling stub for the given method is about to be built.") +CONFIG_STRING_INFO_EX(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO(INTERNAL_BreakOnMethodName, W("BreakOnMethodName"), "Very useful for debugging method override placement code.") +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnRetailAssert, W("BreakOnRetailAssert"), 0, "Used for debugging \"retail\" asserts (fatal errors)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_BreakOnSO, W("BreakOnSO"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO(INTERNAL_BreakOnStructMarshalSetup, W("BreakOnStructMarshalSetup"), "Throws an assert when field marshalers for the given type with layout are about to be created.") +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUEF, W("BreakOnUEF"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_BreakOnUncaughtException, W("BreakOnUncaughtException"), 0, "", CLRConfig::REGUTIL_default) + +/// + +/// Debugger +/// +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableDiagnostics, W("EnableDiagnostics"), 1, "Allows the debugger and profiler diagnostics to be disabled", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_D__FCE, W("D::FCE"), 0, "Allows an assert when crawling the managed stack for an exception handler", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakIfLocksUnavailable, W("DbgBreakIfLocksUnavailable"), 0, "Allows an assert when the debugger can't take a lock ", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnErr, W("DbgBreakOnErr"), 0, "Allows an assert when we get a failing hresult", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnMapPatchToDJI, W("DbgBreakOnMapPatchToDJI"), 0, "Allows an assert when mapping a patch to an address", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnRawInt3, W("DbgBreakOnRawInt3"), 0, "Allows an assert for test coverage for debug break or other int3 breaks", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSendBreakpoint, W("DbgBreakOnSendBreakpoint"), 0, "Allows an assert when sending a breakpoint to the right side", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgBreakOnSetIP, W("DbgBreakOnSetIP"), 0, "Allows an assert when setting the IP", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgCheckInt3, W("DbgCheckInt3"), 0, "Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgDACAssertOnMismatch, W("DbgDACAssertOnMismatch"), "Allows an assert when the mscordacwks and mscorwks dll versions don't match") +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACEnableAssert, W("DbgDACEnableAssert"), 0, "Enables extra validity checking in DAC - assumes target isn't corrupt", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls"), 0, "Allows disabling the check to ensure mscordacwks and mscorwks dll versions match", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_DbgEnableMixedModeDebugging, W("DbgEnableMixedModeDebuggingInternalOnly"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgExtraThreadsOOB, W("DbgExtraThreadsOOB"), 0, "Allows extra out of band unmanaged threads to run and throw debug events for stress testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgFaultInHandleIPCEvent, W("DbgFaultInHandleIPCEvent"), 0, "Allows testing the unhandled event filter", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgInjectFEE, W("DbgInjectFEE"), 0, "Allows injecting a fatal execution error for testing Watson", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgLeakCheck, W("DbgLeakCheck"), 0, "Allows checking for leaked Cordb objects", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNo2ndChance, W("DbgNo2ndChance"), 0, "Allows breaking on (and catching bogus) 2nd chance exceptions", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoDebugger, W("DbgNoDebugger"), 0, "Allows breaking if we don't want to lazily initialize the debugger", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgNoForceContinue, W("DbgNoForceContinue"), 1, "Used to force a continue on longhorn", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNoOpenMDByFile, W("DbgNoOpenMDByFile"), 0, "Allows opening MD by memory for perf testing", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_DbgOOBinFEEE, W("DbgOOBinFEEE"), 0, "Allows forcing oob breakpoints when a fatal error occurs") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgPackShimPath, W("DbgPackShimPath"), "CoreCLR path to dbgshim.dll - we are trying to figure out if we can remove this") +CONFIG_DWORD_INFO_EX(INTERNAL_DbgPingInterop, W("DbgPingInterop"), 0, "Allows checking for deadlocks in interop debugging", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgRace, W("DbgRace"), 0, "Allows pausing for native debug events to get hijicked", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgRedirect, W("DbgRedirect"), 0, "Allows for redirecting the event pipeline", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectApplication, W("DbgRedirectApplication"), "Specifies the auxiliary debugger application to launch.") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectAttachCmd, W("DbgRedirectAttachCmd"), "Specifies command parameters for attaching the auxiliary debugger.") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectCommonCmd, W("DbgRedirectCommonCmd"), "Specifies a command line format string for the auxiliary debugger.") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(EXTERNAL_DbgRedirectCreateCmd, W("DbgRedirectCreateCmd"), "Specifies command parameters when creating the auxiliary debugger.") +CONFIG_DWORD_INFO_EX(INTERNAL_DbgShortcutCanary, W("DbgShortcutCanary"), 0, "Allows a way to force canary to fail to be able to test failure paths", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipMEOnStep, W("DbgSkipMEOnStep"), 0, "Turns off MethodEnter checks", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgSkipVerCheck, W("DbgSkipVerCheck"), 0, "Allows different RS and LS versions (for servicing work)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTC, W("DbgTC"), 0, "Allows checking boundary compression for offset mappings", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTransportFaultInject, W("DbgTransportFaultInject"), 0, "Allows injecting a fault for testing the debug transport", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgTransportLog, W("DbgTransportLog"), "Turns on logging for the debug transport") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_DbgTransportLogClass, W("DbgTransportLogClass"), "Mask to control what is logged in DbgTransportLog") +RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_DbgTransportProxyAddress, W("DbgTransportProxyAddress"), "Allows specifying the transport proxy address", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgTrapOnSkip, W("DbgTrapOnSkip"), 0, "Allows breaking when we skip a breakpoint", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DbgWaitTimeout, W("DbgWaitTimeout"), 1, "Specifies the timeout value for waits", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgWFDETimeout, W("DbgWFDETimeout"), 25, "Specifies the timeout value for wait when waiting for a debug event", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_RaiseExceptionOnAssert, W("RaiseExceptionOnAssert"), 0, "Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnAssert, W("DebugBreakOnAssert"), 0, "If DACCESS_COMPILE is defined, break on asserts.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0, "Halts the jit on verification failure", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_DebuggerBreakPoint, W("DebuggerBreakPoint"), "Allows counting various debug events", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_DebugVerify, W("DebugVerify"), "Control for tracing in peverify", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_EncApplyChanges, W("EncApplyChanges"), 0, "Allows breaking when ApplyEditAndContinue is called") +CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapComplete, W("EnCBreakOnRemapComplete"), 0, "Allows breaking after N RemapCompletes", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_EnCBreakOnRemapOpportunity, W("EnCBreakOnRemapOpportunity"), 0, "Allows breaking after N RemapOpportunities", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_EncDumpApplyChanges, W("EncDumpApplyChanges"), 0, "Allows dumping edits in delta metadata and il files") +CONFIG_DWORD_INFO(INTERNAL_EncFixupFieldBreak, W("EncFixupFieldBreak"), 0, "Unlikely that this is used anymore.") +CONFIG_DWORD_INFO(INTERNAL_EncJitUpdatedFunction, W("EncJitUpdatedFunction"), 0, "Allows breaking when an updated function is jitted") +CONFIG_DWORD_INFO(INTERNAL_EnCResolveField, W("EnCResolveField"), 0, "Allows breaking when computing the address of an EnC-added field") +CONFIG_DWORD_INFO(INTERNAL_EncResumeInUpdatedFunction, W("EncResumeInUpdatedFunction"), 0, "Allows breaking when execution resumes in a new EnC version of a function") +CONFIG_DWORD_INFO_EX(INTERNAL_DbgAssertOnDebuggeeDebugBreak, W("DbgAssertOnDebuggeeDebugBreak"), 0, "If non-zero causes the managed-only debugger to assert on unhandled breakpoints in the debuggee", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException, W("UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException"), 0, "If non-zero, then don't try to unsuspend threads after continuing a 2nd-chance native exception") +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DbgSkipStackCheck, W("DbgSkipStackCheck"), 0, "Skip the stack pointer check during stackwalking", CLRConfig::REGUTIL_default) +#ifdef DACCESS_COMPILE +CONFIG_DWORD_INFO(INTERNAL_DumpGeneration_IntentionallyCorruptDataFromTarget, W("IntentionallyCorruptDataFromTarget"), 0, "Intentionally fakes bad data retrieved from target to try and break dump generation.") +#endif +// Note that Debugging_RequiredVersion is sometimes an 'INTERNAL' knob and sometimes an 'UNSUPPORTED' knob, but we don't change it's name. +CONFIG_DWORD_INFO(UNSUPPORTED_Debugging_RequiredVersion, W("UNSUPPORTED_Debugging_RequiredVersion"), 0, "The lowest ICorDebug version we should attempt to emulate, or 0 for default policy. Use 2 for CLRv2, 4 for CLRv4, etc.") + +#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +RETAIL_CONFIG_DWORD_INFO(INTERNAL_MiniMdBufferCapacity, W("MiniMdBufferCapacity"), 64 * 1024, "The max size of the buffer to store mini metadata information for triage- and mini-dumps.") +#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS + +CONFIG_DWORD_INFO_EX(INTERNAL_DbgNativeCodeBpBindsAcrossVersions, W("DbgNativeCodeBpBindsAcrossVersions"), 0, "If non-zero causes native breakpoints at offset 0 to bind in all tiered compilation versions of the given method", CLRConfig::REGUTIL_default) + +/// +/// Diagnostics (internal general-purpose) +/// +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ConditionalContracts, W("ConditionalContracts"), "If ENABLE_CONTRACTS_IMPL is defined, sets whether contracts are conditional. (?)") +CONFIG_DWORD_INFO(INTERNAL_ConsistencyCheck, W("ConsistencyCheck"), 0, "") +CONFIG_DWORD_INFO_EX(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set, doesn't break on asserts.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_disableStackOverflowProbing, W("disableStackOverflowProbing"), 0, "", CLRConfig::FavorConfigFile) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_InjectFatalError, W("InjectFatalError"), "") +CONFIG_DWORD_INFO_EX(INTERNAL_InjectFault, W("InjectFault"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SuppressChecks, W("SuppressChecks"), "") +#ifdef WIN64EXCEPTIONS +CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLockViolationsOnReentryFromOS"), 0, "64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations.") +#endif // WIN64EXCEPTIONS + +/// +/// Exception Handling +/// +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), "") +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior", CLRConfig::FavorConfigFile) +CONFIG_DWORD_INFO_EX(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_FailFastOnCorruptedStateException, W("FailFastOnCorruptedStateException"), 0, "Failfast if a CSE is encountered", CLRConfig::FavorConfigFile) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "", CLRConfig::REGUTIL_default) + +/// +/// Garbage collector +/// +CONFIG_DWORD_INFO(INTERNAL_FastGCCheckStack, W("FastGCCheckStack"), 0, "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_FastGCStress, W("FastGCStress"), "Reduce the number of GCs done by enabling GCStress") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCBreakOnOOM, W("GCBreakOnOOM"), "Does a DebugBreak at the soonest time we detect an OOM") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcConcurrent, W("gcConcurrent"), (DWORD)-1, "Enables/Disables concurrent GC") + +#ifdef FEATURE_CONSERVATIVE_GC +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcConservative, W("gcConservative"), 0, "Enables/Disables conservative GC") +#endif +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcServer, W("gcServer"), 0, "Enables server GC") +CONFIG_STRING_INFO(INTERNAL_GcCoverage, W("GcCoverage"), "Specify a method or regular expression of method names to run with GCStress") +CONFIG_STRING_INFO(INTERNAL_SkipGCCoverage, W("SkipGcCoverage"), "Specify a list of assembly names to skip with GC Coverage") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_gcForceCompact, W("gcForceCompact"), "When set to true, always do compacting GC") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCgen0size, W("GCgen0size"), "Specifies the smallest gen0 size") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCGen0MaxBudget, W("GCGen0MaxBudget"), "Specifies the largest gen0 allocation budget") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressMix, W("GCStressMix"), 0, "Specifies whether the GC mix mode is enabled or not") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressStep, W("GCStressStep"), 1, "Specifies how often StressHeap will actually do a GC in GCStressMix mode") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressMaxFGCsPerBGC, W("GCStressMaxFGCsPerBGC"), ~0U, "Specifies how many FGCs will occur during one BGC in GCStressMix mode") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StatsUpdatePeriod, W("StatsUpdatePeriod"), 60, "Specifies the interval, in seconds, at which to update the statistics") +RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_SuspendTimeLog, W("SuspendTimeLog"), "Specifies the name of the log file for suspension statistics") +RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCMixLog, W("GCMixLog"), "Specifies the name of the log file for GC mix statistics") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GCLatencyMode, W("GCLatencyMode"), "Specifies the GC latency mode - batch, interactive or low latency (note that the same thing can be specified via API which is the supported way)") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCLatencyLevel, W("GCLatencyLevel"), 1, "Specifies the GC latency level that you want to optimize for") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCConfigLogEnabled, W("GCConfigLogEnabled"), 0, "Specifies if you want to turn on config logging in GC") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogEnabled, W("GCLogEnabled"), 0, "Specifies if you want to turn on logging in GC") +RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCLogFile, W("GCLogFile"), "Specifies the name of the GC log file") +RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCConfigLogFile, W("GCConfigLogFile"), "Specifies the name of the GC config log file") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogFileSize, W("GCLogFileSize"), 0, "Specifies the GC log file size") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCCompactRatio, W("GCCompactRatio"), 0, "Specifies the ratio compacting GCs vs sweeping ") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCPollType, W("GCPollType"), "") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCRetainVM, W("GCRetainVM"), 0, "When set we put the segments that should be deleted on a standby list (instead of releasing them back to the OS) which will be considered to satisfy new segment requests (note that the same thing can be specified via API which is the supported way)") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCSegmentSize, W("GCSegmentSize"), "Specifies the managed heap segment size") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCLOHThreshold, W("GCLOHThreshold"), 0, "Specifies the size that will make objects go on LOH") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCLOHCompact, W("GCLOHCompact"), "Specifies the LOH compaction mode") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_gcAllowVeryLargeObjects, W("gcAllowVeryLargeObjects"), 1, "Allow allocation of 2GB+ objects on GC heap") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_GCStress, W("GCStress"), 0, "Trigger GCs at regular intervals", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_GcStressOnDirectCalls, W("GcStressOnDirectCalls"), 0, "Whether to trigger a GC on direct calls", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCStressStart, W("GCStressStart"), 0, "Start GCStress after N stress GCs have been attempted") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GCStressStartAtJit, W("GCStressStartAtJit"), 0, "Start GCStress after N items are jitted") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_gcTrimCommitOnLowMemory, W("gcTrimCommitOnLowMemory"), "When set we trim the committed space more aggressively for the ephemeral seg. This is used for running many instances of server processes where they want to keep as little memory committed as possible") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BGCSpinCount, W("BGCSpinCount"), 140, "Specifies the bgc spin count") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BGCSpin, W("BGCSpin"), 2, "Specifies the bgc spin time") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_HeapVerify, W("HeapVerify"), "When set verifies the integrity of the managed heap on entry and exit of each GC") +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_SetupGcCoverage, W("SetupGcCoverage"), "This doesn't appear to be a config flag", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCNumaAware, W("GCNumaAware"), 1, "Specifies if to enable GC NUMA aware") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCCpuGroup, W("GCCpuGroup"), 0, "Specifies if to enable GC to support CPU groups") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCHeapCount, W("GCHeapCount"), 0, "") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCNoAffinitize, W("GCNoAffinitize"), 0, "") +// this config is only in effect if the process is not running in multiple CPU groups. +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapAffinitizeMask, W("GCHeapAffinitizeMask"), "Specifies processor mask for Server GC threads") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCProvModeStress, W("GCProvModeStress"), 0, "Stress the provisional modes") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCHighMemPercent, W("GCHighMemPercent"), 0, "Specifies the percent for GC to consider as high memory") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimit, W("GCHeapHardLimit"), "Specifies the maximum commit size for the GC heap") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCHeapHardLimitPercent, W("GCHeapHardLimitPercent"), "Specifies the GC heap usage as a percentage of the total memory") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCHeapAffinitizeRanges, W("GCHeapAffinitizeRanges"), "Specifies list of processors for Server GC threads. The format is a comma separated list of processor numbers or ranges of processor numbers. Example: 1,3,5,7-9,12") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCLargePages, W("GCLargePages"), "Specifies whether large pages should be used when a heap hard limit is set") + +/// +/// IBC +/// +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_ConvertIbcData, W("ConvertIbcData"), 1, "Converts between v1 and v2 IBC data", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_DisableHotCold, W("DisableHotCold"), "Master hot/cold splitting switch in Jit64") +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_DisableIBC, W("DisableIBC"), 0, "Disables the use of IBC data", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_UseIBCFile, W("UseIBCFile"), 0, "", CLRConfig::REGUTIL_default) + + +/// +/// JIT +/// +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JitAlignLoops, W("JitAlignLoops"), "Aligns loop targets to 8 byte boundaries") +CONFIG_DWORD_INFO_EX(INTERNAL_JitBreakEmit, W("JitBreakEmit"), (DWORD)-1, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_JitDebuggable, W("JitDebuggable"), "") +#if !defined(DEBUG) && !defined(_DEBUG) +#define INTERNAL_JitEnableNoWayAssert_Default 0 +#else +#define INTERNAL_JitEnableNoWayAssert_Default 1 +#endif +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitEnableNoWayAssert, W("JitEnableNoWayAssert"), INTERNAL_JitEnableNoWayAssert_Default, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JitFramed, W("JitFramed"), "Forces EBP frames") +CONFIG_DWORD_INFO_EX(INTERNAL_JitGCStress, W("JitGCStress"), 0, "GC stress mode for jit", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_JitHeartbeat, W("JitHeartbeat"), 0, "") +CONFIG_DWORD_INFO(INTERNAL_JitHelperLogging, W("JitHelperLogging"), 0, "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_JITMinOpts, W("JITMinOpts"), "Forces MinOpts") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_JitName, W("JitName"), "Primary Jit to use") +#if defined(ALLOW_SXS_JIT) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitName, W("AltJitName"), "Alternative Jit to use, will fall back to primary jit.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJit, W("AltJit"), "Enables AltJit and selectively limits it to the specified methods.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.", CLRConfig::REGUTIL_default) +#endif // defined(ALLOW_SXS_JIT) + +#if defined(FEATURE_STACK_SAMPLING) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEnabled, W("StackSamplingEnabled"), 0, "Is stack sampling based tracking of evolving hot methods enabled.") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingAfter, W("StackSamplingAfter"), 0, "When to start sampling (for some sort of app steady state), i.e., initial delay for sampling start in milliseconds.") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEvery, W("StackSamplingEvery"), 100, "How frequent should thread stacks be sampled in milliseconds.") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingNumMethods, W("StackSamplingNumMethods"), 32, "Number of evolving methods to track as hot and JIT them in the background at a given point of execution.") +#endif // defined(FEATURE_JIT_SAMPLING) + +#if defined(ALLOW_SXS_JIT_NGEN) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_AltJitNgen, W("AltJitNgen"), "Enables AltJit for NGEN and selectively limits it to the specified methods.", CLRConfig::REGUTIL_default) +#endif // defined(ALLOW_SXS_JIT_NGEN) + +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitHostMaxSlabCache, W("JitHostMaxSlabCache"), 0x1000000, "Sets jit host max slab cache size, 16MB default") + +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), "") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitPrintInlinedMethods, W("JitPrintInlinedMethods"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitTelemetry, W("JitTelemetry"), 1, "If non-zero, gather JIT telemetry data") +RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogFile, W("JitTimeLogFile"), "If set, gather JIT throughput data and write to this file.") +RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogCsv, W("JitTimeLogCsv"), "If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds.") +RETAIL_CONFIG_STRING_INFO(INTERNAL_JitFuncInfoLogFile, W("JitFuncInfoLogFile"), "If set, gather JIT function info and write to this file.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_JitVerificationDisable, W("JitVerificationDisable"), "") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitLockWrite, W("JitLockWrite"), 0, "Force all volatile writes to be 'locked'") +CONFIG_STRING_INFO_EX(INTERNAL_TailCallMax, W("TailCallMax"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_TailCallOpt, W("TailCallOpt"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TailCallLoopOpt, W("TailCallLoopOpt"), 1, "Convert recursive tail calls to loops") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Jit_NetFx40PInvokeStackResilience, W("NetFx40_PInvokeStackResilience"), (DWORD)-1, "Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty).") + +// AltJitAssertOnNYI should be 0 on targets where JIT is under development or bring up stage, so as to facilitate fallback to main JIT on hitting a NYI. +#if defined(_TARGET_X86_) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 0, "Controls the AltJit behavior of NYI stuff") +#else +RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1, "Controls the AltJit behavior of NYI stuff") +#endif +CONFIG_DWORD_INFO_EX(INTERNAL_JitLargeBranches, W("JitLargeBranches"), 0, "Force using the largest conditional branch format", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control FP enregistration", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitELTHookEnabled, W("JitELTHookEnabled"), 0, "On ARM, setting this will emit Enter/Leave/TailCall callbacks") +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitVNMapSelBudget, W("JitVNMapSelBudget"), 100, "Max # of MapSelect's considered for a particular top-level invocation.") +#if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_) +#define EXTERNAL_FeatureSIMD_Default 1 +#else // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_)) +#define EXTERNAL_FeatureSIMD_Default 0 +#endif // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) || defined(_TARGET_ARM64_)) +#if defined(_TARGET_AMD64_) || defined(_TARGET_X86_) +#define EXTERNAL_JitEnableAVX_Default 1 +#else // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) +#define EXTERNAL_JitEnableAVX_Default 0 +#endif // !(defined(_TARGET_AMD64_) || defined(_TARGET_X86_) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_FeatureSIMD, W("FeatureSIMD"), EXTERNAL_FeatureSIMD_Default, "Enable SIMD intrinsics recognition in System.Numerics.dll and/or System.Numerics.Vectors.dll", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_SIMD16ByteOnly, W("SIMD16ByteOnly"), 0, "Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit)") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_EnableAVX, W("EnableAVX"), EXTERNAL_JitEnableAVX_Default, "Enable AVX instruction set for wide operations as default", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods", CLRConfig::REGUTIL_default) + +#ifdef FEATURE_MULTICOREJIT + +RETAIL_CONFIG_STRING_INFO(INTERNAL_MultiCoreJitProfile, W("MultiCoreJitProfile"), "If set, use the file to store/control multi-core JIT.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_MultiCoreJitProfileWriteDelay, W("MultiCoreJitProfileWriteDelay"), 12, "Set the delay after which the multi-core JIT profile will be written to disk.") + +#endif + +#ifdef FEATURE_INTERPRETER +/// +/// Interpreter +/// +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_Interpret, W("Interpret"), "Selectively uses the interpreter to execute the specified methods", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpretExclude, W("InterpretExclude"), "Excludes the specified methods from the set selected by 'Interpret'", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMin, W("InterpreterMethHashMin"), 0, "Only interpret methods selected by 'Interpret' whose hash is at least this value. or after nth") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMax, W("InterpreterMethHashMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose hash is at most this value") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMin, W("InterpreterStubMin"), 0, "Only interpret methods selected by 'Interpret' whose stub num is at least this value.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMax, W("InterpreterStubMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose stub number is at most this value.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterJITThreshold, W("InterpreterJITThreshold"), 10, "The number of times a method should be interpreted before being JITted") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterDoLoopMethods, W("InterpreterDoLoopMethods"), 0, "If set, don't check for loops, start by interpreting *all* methods") +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterUseCaching, W("InterpreterUseCaching"), 1, "If non-zero, use the caching mechanism.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_InterpreterLooseRules, W("InterpreterLooseRules"), 1, "If non-zero, allow ECMA spec violations required by managed C++.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterPrintPostMortem, W("InterpreterPrintPostMortem"), 0, "Prints summary information about the execution to the console") +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DumpInterpreterStubs, W("DumpInterpreterStubs"), 0, "Prints all interpreter stubs that are created to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterEntries, W("TraceInterpreterEntries"), 0, "Logs entries to interpreted methods to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterIL, W("TraceInterpreterIL"), 0, "Logs individual instructions of interpreted methods to the console") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterOstack, W("TraceInterpreterOstack"), 0, "Logs operand stack after each IL instruction of interpreted methods to the console") +CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterVerbose, W("TraceInterpreterVerbose"), 0, "Logs interpreter progress with detailed messages to the console") +CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterJITTransition, W("TraceInterpreterJITTransition"), 0, "Logs when the interpreter determines a method should be JITted") +#endif +// The JIT queries this ConfigDWORD but it doesn't know if FEATURE_INTERPRETER is enabled +RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterFallback, W("InterpreterFallback"), 0, "Fallback to the interpreter when the JIT compiler fails") + +/// +/// Loader +/// +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_APIThreadStress, W("APIThreadStress"), "Used to test Loader for race conditions") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_ForceLog, W("ForceLog"), "Fusion flag to enforce assembly binding log. Heavily used and documented in MSDN and BLOGS.") +RETAIL_CONFIG_STRING_INFO(INTERNAL_CoreClrBinderLog, W("CoreClrBinderLog"), "Debug flag that enabled detailed log for new binder (similar to stress logging).") +RETAIL_CONFIG_STRING_INFO(INTERNAL_WinMDPath, W("WinMDPath"), "Path for Windows WinMD files") + +/// +/// Loader heap +/// +CONFIG_DWORD_INFO_EX(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, "Loader heap troubleshooting", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 1, "Percentage of code heap to reserve for jump stubs") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_NGenReserveForJumpStubs, W("NGenReserveForJumpStubs"), 0, "Percentage of ngen image size to reserve for jump stubs") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown") + +/// +/// Log +/// +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogEnable, W("LogEnable"), "Turns on the traditional CLR log.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFacility, W("LogFacility"), "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFacility2, W("LogFacility2"), "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_logFatalError, W("logFatalError"), 1, "Specifies whether EventReporter logs fatal errors in the Windows event log.") +CONFIG_STRING_INFO_EX(INTERNAL_LogFile, W("LogFile"), "Specifies a file name for the CLR log.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFileAppend, W("LogFileAppend"), "Specifies whether to append to or replace the CLR log file.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogFlushFile, W("LogFlushFile"), "Specifies whether to flush the CLR log file on each write.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_LogLevel, W("LogLevel"), "4=10 msgs, 9=1000000, 10=everything") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(INTERNAL_LogPath, W("LogPath"), "?Fusion debug log path.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToConsole, W("LogToConsole"), "Writes the CLR log to console.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToDebugger, W("LogToDebugger"), "Writes the CLR log to debugger (OutputDebugStringA).") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogToFile, W("LogToFile"), "Writes the CLR log to a file.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_LogWithPid, W("LogWithPid"), "Appends pid to filename for the CLR log.") + +/// +/// MetaData +/// +CONFIG_DWORD_INFO_EX(INTERNAL_MD_ApplyDeltaBreak, W("MD_ApplyDeltaBreak"), 0, "ASSERT when applying EnC", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AssertOnBadImageFormat, W("AssertOnBadImageFormat"), "ASSERT when invalid MD read") +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_DeltaCheck, W("MD_DeltaCheck"), 1, "Some checks of GUID when applying EnC (?)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_EncDelta, W("MD_EncDelta"), 0, "Forces EnC Delta format in MD (?)", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_MD_ForceNoColDesSharing, W("MD_ForceNoColDesSharing"), 0, "Don't know - the only usage I could find is #if 0 (?)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_KeepKnownCA, W("MD_KeepKnownCA"), 0, "Something with known CAs (?)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_MiniMDBreak, W("MD_MiniMDBreak"), 0, "ASSERT when creating CMiniMdRw class", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_PreSaveBreak, W("MD_PreSaveBreak"), 0, "ASSERT when calling CMiniMdRw::PreSave", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaBreak, W("MD_RegMetaBreak"), 0, "ASSERT when creating RegMeta class", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaDump, W("MD_RegMetaDump"), 0, "Dump MD in 4 functions (?)", CLRConfig::REGUTIL_default) +// MetaData - Desktop-only +CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_Disable, W("MD_WinMD_Disable"), 0, "Never activate the WinMD import adapter", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_MD_WinMD_AssertOnIllegalUsage, W("MD_WinMD_AssertOnIllegalUsage"), 0, "ASSERT if a WinMD import adapter detects a tool incompatibility", CLRConfig::REGUTIL_default) + +// Metadata - mscordbi only - this flag is only intended to mitigate potential issues in bug fix 458597. +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MD_PreserveDebuggerMetadataMemory, W("MD_PreserveDebuggerMetadataMemory"), 0, "Save all versions of metadata memory in the debugger when debuggee metadata is updated", CLRConfig::REGUTIL_default) + +/// +/// Spinning heuristics +/// +// Note that these only take effect once the runtime has been started; prior to that the values hardcoded in g_SpinConstants (vars.cpp) are used +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinInitialDuration, W("SpinInitialDuration"), 0x32, "Hex value specifying the first spin duration", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinBackoffFactor, W("SpinBackoffFactor"), 0x3, "Hex value specifying the growth of each successive spin duration", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinLimitProcCap, W("SpinLimitProcCap"), 0xFFFFFFFF, "Hex value specifying the largest value of NumProcs to use when calculating the maximum spin duration", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinLimitProcFactor, W("SpinLimitProcFactor"), 0x4E20, "Hex value specifying the multiplier on NumProcs to use when calculating the maximum spin duration", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinLimitConstant, W("SpinLimitConstant"), 0x0, "Hex value specifying the constant to add when calculating the maximum spin duration", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_SpinRetryCount, W("SpinRetryCount"), 0xA, "Hex value specifying the number of times the entire spin process is repeated (when applicable)", EEConfig_default) +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_Monitor_SpinCount, W("Monitor_SpinCount"), 0x1e, "Hex value specifying the maximum number of spin iterations Monitor may perform upon contention on acquiring the lock before waiting.", EEConfig_default) + +/// +/// Native Binder +/// + +CONFIG_DWORD_INFO(INTERNAL_NgenBind_ZapForbid, W("NgenBind_ZapForbid"), 0, "Assert if an assembly succeeds in binding to a native image") +CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidExcludeList, W("NgenBind_ZapForbidExcludeList"), "") +CONFIG_STRING_INFO(INTERNAL_NgenBind_ZapForbidList, W("NgenBind_ZapForbidList"), "") + +CONFIG_DWORD_INFO_EX(INTERNAL_SymDiffDump, W("SymDiffDump"), 0, "Used to create the map file while binding the assembly. Used by SemanticDiffer", CLRConfig::REGUTIL_default) + +/// +/// NGEN +/// +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_NGen_JitName, W("NGen_JitName"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_NGenFramed, W("NGenFramed"), (DWORD)-1, "Same as JitFramed, but for ngen", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NGenOnlyOneMethod, W("NGenOnlyOneMethod"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenOrder, W("NgenOrder"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_partialNGenStress, W("partialNGenStress"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_ZapDoNothing, W("ZapDoNothing"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureMask, W("NgenForceFailureMask"), (DWORD)-1, "Bitmask used to control which locations will check and raise the failure (defaults to bits: -1)", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureCount, W("NgenForceFailureCount"), 0, "If set to >0 and we have IBC data we will force a failure after we reference an IBC data item times", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NgenForceFailureKind, W("NgenForceFailureKind"), 1, "If set to 1, We will throw a TypeLoad exception; If set to 2, We will cause an A/V", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_NGenEnableCreatePdb, W("NGenEnableCreatePdb"), 0, "If set to >0 ngen.exe displays help on, recognizes createpdb in the command line") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_NGenSimulateDiskFull, W("NGenSimulateDiskFull"), 0, "If set to 1, ngen will throw a Disk full exception in ZapWriter.cpp:Save()") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_PartialNGen, W("PartialNGen"), (DWORD)-1, "Generate partial NGen images") + +CONFIG_DWORD_INFO(INTERNAL_NoASLRForNgen, W("NoASLRForNgen"), 0, "Turn off IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE bit in generated ngen images. Makes nidump output repeatable from run to run.") + +#ifdef CROSSGEN_COMPILE +RETAIL_CONFIG_DWORD_INFO(INTERNAL_CrossGenAssumeInputSigned, W("CrossGenAssumeInputSigned"), 1, "CrossGen should assume that its input assemblies will be signed before deployment") +#endif + +/// +/// Profiling API / ETW +/// +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_COR_ENABLE_PROFILING, W("COR_ENABLE_PROFILING"), 0, "Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_ | CLRConfig::IgnoreConfigFiles) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER, W("COR_PROFILER"), "Specifies GUID of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH, W("COR_PROFILER_PATH"), "Specifies the path to the DLL of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH_32, W("COR_PROFILER_PATH_32"), "Specifies the path to the DLL of profiler to load into currently running 32 bits process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_COR_PROFILER_PATH_64, W("COR_PROFILER_PATH_64"), "Specifies the path to the DLL of profiler to load into currently running 64 bits process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_PROFILING, W("CORECLR_ENABLE_PROFILING"), 0, "CoreCLR only: Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::DontPrependCOMPlus_ | CLRConfig::IgnoreConfigFiles) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER, W("CORECLR_PROFILER"), "CoreCLR only: Specifies GUID of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH, W("CORECLR_PROFILER_PATH"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_32, W("CORECLR_PROFILER_PATH_32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 32 process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_64, W("CORECLR_PROFILER_PATH_64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process", CLRConfig::DontPrependCOMPlus_) +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::REGUTIL_default | CLRConfig::TrimWhiteSpaceFromStringValue) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMinSleepMs, W("ProfAPI_DetachMinSleepMs"), 0, "The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMaxSleepMs, W("ProfAPI_DetachMaxSleepMs"), 0, "The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_RejitOnAttach, W("ProfApi_RejitOnAttach"), 1, "Enables the ability for profilers to rejit methods on attach.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_InliningTracking, W("ProfApi_InliningTracking"), 1, "Enables the runtime's tracking of inlining for profiler ReJIT.") +CONFIG_DWORD_INFO(INTERNAL_ProfAPI_EnableRejitDiagnostics, W("ProfAPI_EnableRejitDiagnostics"), 0, "Enable extra dumping to stdout of rejit structures") +CONFIG_DWORD_INFO(INTERNAL_ProfAPIFault, W("ProfAPIFault"), 0, "Test-only bitmask to inject various types of faults in the profapi code") +CONFIG_DWORD_INFO(INTERNAL_TestOnlyAllowedEventMask, W("TestOnlyAllowedEventMask"), 0, "Test-only bitmask to allow profiler tests to override CLR enforcement of COR_PRF_ALLOWABLE_AFTER_ATTACH and COR_PRF_MONITOR_IMMUTABLE") +CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableICorProfilerInfo, W("ProfAPI_TestOnlyEnableICorProfilerInfo"), 0, "Test-only flag to allow attaching profiler tests to call ICorProfilerInfo interface, which would otherwise be disallowed for attaching profilers") +CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableObjectAllocatedHook, W("TestOnlyEnableObjectAllocatedHook"), 0, "Test-only flag that forces CLR to initialize on startup as if ObjectAllocated callback were requested, to enable post-attach ObjectAllocated functionality.") +CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableSlowELTHooks, W("TestOnlyEnableSlowELTHooks"), 0, "Test-only flag that forces CLR to initialize on startup as if slow-ELT were requested, to enable post-attach ELT functionality.") + +RETAIL_CONFIG_STRING_INFO_EX(UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec, W("ETW_ObjectAllocationEventsPerTypePerSec"), "Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("ProfAPI_ValidateNGENInstrumentation"), 0, "This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made.") + +#ifdef FEATURE_PERFMAP +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_NativeImagePerfMapFormat, W("NativeImagePerfMapFormat"), "Specifies the format of native image perfmap files generated by crossgen. Valid options are RVA or OFFSET.") +#endif + +RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "") + +/// +/// Stress +/// +CONFIG_DWORD_INFO_EX(INTERNAL_StressCOMCall, W("StressCOMCall"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_StressLog, W("StressLog"), "Turns on the stress log.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_ForceEnc, W("ForceEnc"), "Forces Edit and Continue to be on for all eligible modules.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_StressLogSize, W("StressLogSize"), "Stress log size in bytes per thread.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_StressOn, W("StressOn"), "Enables the STRESS_ASSERT macro that stops runtime quickly (to prevent the clr state from changing significantly before breaking)") +CONFIG_DWORD_INFO_EX(INTERNAL_stressSynchronized, W("stressSynchronized"), 0, "Unknown if or where this is used; unless a test is specifically depending on this, it can be removed.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_StressThreadCount, W("StressThreadCount"), "") + +/// +/// Thread Suspend +/// +CONFIG_DWORD_INFO(INTERNAL_DiagnosticSuspend, W("DiagnosticSuspend"), 0, "") +CONFIG_DWORD_INFO(INTERNAL_SuspendDeadlockTimeout, W("SuspendDeadlockTimeout"), 40000, "") +CONFIG_DWORD_INFO(INTERNAL_SuspendThreadDeadlockTimeoutMs, W("SuspendThreadDeadlockTimeoutMs"), 2000, "") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadSuspendInjection, W("INTERNAL_ThreadSuspendInjection"), 1, "Specifies whether to inject activations for thread suspension on Unix") + +/// +/// Thread (miscellaneous) +/// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DefaultStackSize, W("DefaultStackSize"), 0, "Stack size to use for new VM threads when thread is created with default stack size (dwStackSize == 0).") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadCountThresholdForGCTrigger, W("Thread_DeadThreadCountThresholdForGCTrigger"), 75, "In the heuristics to clean up dead threads, this threshold must be reached before triggering a GC will be considered. Set to 0 to disable triggering a GC based on dead threads.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadGCTriggerPeriodMilliseconds, W("Thread_DeadThreadGCTriggerPeriodMilliseconds"), 1000 * 60 * 30, "In the heuristics to clean up dead threads, this much time must have elapsed since the previous max-generation GC before triggering another GC will be considered") + +/// +/// Threadpool +/// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_ForceMinWorkerThreads, W("ThreadPool_ForceMinWorkerThreads"), 0, "Overrides the MinThreads setting for the ThreadPool worker pool") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_ForceMaxWorkerThreads, W("ThreadPool_ForceMaxWorkerThreads"), 0, "Overrides the MaxThreads setting for the ThreadPool worker pool") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DisableStarvationDetection, W("ThreadPool_DisableStarvationDetection"), 0, "Disables the ThreadPool feature that forces new threads to be added when workitems run for too long") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DebugBreakOnWorkerStarvation, W("ThreadPool_DebugBreakOnWorkerStarvation"), 0, "Breaks into the debugger if the ThreadPool detects work queue starvation") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_EnableWorkerTracking, W("ThreadPool_EnableWorkerTracking"), 0, "Enables extra expensive tracking of how many workers threads are working simultaneously") +#ifdef _TARGET_ARM64_ +// Spinning scheme is currently different on ARM64, see CLRLifoSemaphore::Wait(DWORD, UINT32, UINT32) +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x32, "Maximum number of spins per processor a thread pool worker thread performs before waiting for work") +#else // !_TARGET_ARM64_ +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x46, "Maximum number of spins a thread pool worker thread performs before waiting for work") +#endif // _TARGET_ARM64_ +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_UseAllCpuGroups, W("Thread_UseAllCpuGroups"), 0, "Specifies if to automatically distribute thread across CPU Groups") + +CONFIG_DWORD_INFO(INTERNAL_ThreadpoolTickCountAdjustment, W("ThreadpoolTickCountAdjustment"), 0, "") + +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_Disable, W("HillClimbing_Disable"), 0, "Disables hill climbing for thread adjustments in the thread pool"); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WavePeriod, W("HillClimbing_WavePeriod"), 4, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_TargetSignalToNoiseRatio, W("HillClimbing_TargetSignalToNoiseRatio"), 300, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_ErrorSmoothingFactor, W("HillClimbing_ErrorSmoothingFactor"), 1, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WaveMagnitudeMultiplier, W("HillClimbing_WaveMagnitudeMultiplier"), 100, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxWaveMagnitude, W("HillClimbing_MaxWaveMagnitude"), 20, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WaveHistorySize, W("HillClimbing_WaveHistorySize"), 8, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_Bias, W("HillClimbing_Bias"), 15, "The 'cost' of a thread. 0 means drive for increased throughput regardless of thread count; higher values bias more against higher thread counts."); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxChangePerSecond, W("HillClimbing_MaxChangePerSecond"), 4, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxChangePerSample, W("HillClimbing_MaxChangePerSample"), 20, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxSampleErrorPercent, W("HillClimbing_MaxSampleErrorPercent"), 15, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_SampleIntervalLow, W("HillClimbing_SampleIntervalLow"), 10, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_SampleIntervalHigh, W("HillClimbing_SampleIntervalHigh"), 200, ""); +RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, W("HillClimbing_GainExponent"), 200, "The exponent to apply to the gain, times 100. 100 means to use linear gain, higher values will enhance large moves and damp small ones."); + +/// +/// Tiered Compilation +/// +#ifdef FEATURE_TIERED_COMPILATION +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), 30, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), 100, "A perpetual delay in milliseconds that is applied call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), 10, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers") +#endif + +/// +/// Entry point slot backpatch +/// +#ifndef CROSSGEN_COMPILE +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BackpatchEntryPointSlots, W("BackpatchEntryPointSlots"), 1, "Indicates whether to enable entry point slot backpatching, for instance to avoid making virtual calls through a precode and instead to patch virtual slots for a method when its entry point changes.") +#endif + +/// +/// TypeLoader +/// +CONFIG_DWORD_INFO(INTERNAL_TypeLoader_InjectInterfaceDuplicates, W("INTERNAL_TypeLoader_InjectInterfaceDuplicates"), 0, "Injects duplicates in interface map for all types.") + +/// +/// Virtual call stubs +/// +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideMonoPct, W("VirtualCallStubCollideMonoPct"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubCollideWritePct, W("VirtualCallStubCollideWritePct"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogCounter, W("VirtualCallStubDumpLogCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubDumpLogIncr, W("VirtualCallStubDumpLogIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_VirtualCallStubLogging, W("VirtualCallStubLogging"), 0, "Worth keeping, but should be moved into \"#ifdef STUB_LOGGING\" blocks. This goes for most (or all) of the stub logging infrastructure.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubMissCount, W("VirtualCallStubMissCount"), 100, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheCounter, W("VirtualCallStubResetCacheCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_VirtualCallStubResetCacheIncr, W("VirtualCallStubResetCacheIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.", CLRConfig::REGUTIL_default) + +/// +/// Watson +/// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_DisableWatsonForManagedExceptions, W("DisableWatsonForManagedExceptions"), 0, "Disable Watson and debugger launching for managed exceptions") + +/// +/// Zap +/// +RETAIL_CONFIG_STRING_INFO_EX(INTERNAL_ZapBBInstr, W("ZapBBInstr"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapBBInstrDir, W("ZapBBInstrDir"), "") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ZapDisable, W("ZapDisable"), 0, "") +CONFIG_STRING_INFO_EX(INTERNAL_ZapExclude, W("ZapExclude"), "", CLRConfig::REGUTIL_default) +CONFIG_STRING_INFO_EX(INTERNAL_ZapOnly, W("ZapOnly"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_ZapRequire, W("ZapRequire"), "") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapRequireExcludeList, W("ZapRequireExcludeList"), "") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapRequireList, W("ZapRequireList"), "") +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ZapSet, W("ZapSet"), "", CLRConfig::REGUTIL_default) + +#ifdef FEATURE_LAZY_COW_PAGES +RETAIL_CONFIG_DWORD_INFO(INTERNAL_ZapLazyCOWPagesEnabled, W("ZapLazyCOWPagesEnabled"), 1, ""); +CONFIG_DWORD_INFO(INTERNAL_DebugAssertOnMissedCOWPage, W("DebugAssertOnMissedCOWPage"), 1, ""); +#endif //FEATURE_LAZY_COW_PAGES + +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ReadyToRun, W("ReadyToRun"), 1, "Enable/disable use of ReadyToRun native code") // On by default for CoreCLR +RETAIL_CONFIG_STRING_INFO(EXTERNAL_ReadyToRunExcludeList, W("ReadyToRunExcludeList"), "List of assemblies that cannot use Ready to Run images") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_ReadyToRunLogFile, W("ReadyToRunLogFile"), "Name of file to log success/failure of using Ready to Run images") + +#if defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableEventLog, W("EnableEventLog"), 0, "Enable/disable use of EnableEventLogging mechanism ") // Off by default +RETAIL_CONFIG_STRING_INFO(INTERNAL_EventSourceFilter, W("EventSourceFilter"), "") +RETAIL_CONFIG_STRING_INFO(INTERNAL_EventNameFilter, W("EventNameFilter"), "") +#endif //defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) + +/// +/// Interop +/// +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ExposeExceptionsInCOM, W("ExposeExceptionsInCOM"), "") +RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PInvokeInline, W("PInvokeInline"), "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_InteropValidatePinnedObjects, W("InteropValidatePinnedObjects"), 0, "After returning from a managed-to-unmanaged interop call, validate GC heap around objects pinned by IL stubs.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_InteropLogArguments, W("InteropLogArguments"), 0, "Log all pinned arguments passed to an interop call") +RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_LogCCWRefCountChange, W("LogCCWRefCountChange"), "Outputs debug information and calls LogCCWRefCountChange_BREAKPOINT when AddRef or Release is called on a CCW.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableRCWCleanupOnSTAShutdown, W("EnableRCWCleanupOnSTAShutdown"), 0, "Performs RCW cleanup when STA shutdown is detected using IInitializeSpy in classic processes.") +RETAIL_CONFIG_STRING_INFO(INTERNAL_LocalWinMDPath, W("LocalWinMDPath"), "Additional path to probe for WinMD files in if a WinRT type is not resolved using the standard paths.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_AllowDComReflection, W("AllowDComReflection"), 0, "Allows out of process DCOM clients to marshal blocked reflection types.") + +// +// EventPipe +// +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableEventPipe, W("EnableEventPipe"), 0, "Enable/disable event pipe. Non-zero values enable tracing.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeNetTraceFormat, W("EventPipeNetTraceFormat"), 1, "Enable/disable using the newer nettrace file format.") +RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeOutputPath, W("EventPipeOutputPath"), "The full path excluding file name for the trace file that will be written when COMPlus_EnableEventPipe=1") +RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeConfig, W("EventPipeConfig"), "Configuration for EventPipe.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "Enable/disable eventpipe rundown.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") +RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") + +// +// LTTng +// +RETAIL_CONFIG_STRING_INFO(INTERNAL_LTTngConfig, W("LTTngConfig"), "Configuration for LTTng.") +RETAIL_CONFIG_DWORD_INFO(UNSUPORTED_LTTng, W("LTTng"), 1, "If COMPlus_LTTng is set to 0, this will prevent the LTTng library from being loaded at runtime") + + +#ifdef FEATURE_GDBJIT +/// +/// GDBJIT +/// +CONFIG_STRING_INFO(INTERNAL_GDBJitElfDump, W("GDBJitElfDump"), "Dump ELF for specified method") +#ifdef FEATURE_GDBJIT_FRAME +RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame"), TRUE, "Enable .debug_frame generation") +#endif +#endif + +/// +/// Uncategorized +/// +// +// Unknown +// +//--------------------------------------------------------------------------------------- +// ** +// PLEASE MOVE ANY CONFIG SWITCH YOU OWN OUT OF THIS SECTION INTO A CATEGORY ABOVE +// +// DO NOT ADD ANY MORE CONFIG SWITCHES TO THIS SECTION! +// ** +CONFIG_DWORD_INFO_EX(INTERNAL_ActivatePatchSkip, W("ActivatePatchSkip"), 0, "Allows an assert when ActivatePatchSkip is called", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_AlwaysUseMetadataInterfaceMapLayout, W("AlwaysUseMetadataInterfaceMapLayout"), "Used for debugging generic interface map layout.") +CONFIG_DWORD_INFO(INTERNAL_AssertOnUnneededThis, W("AssertOnUnneededThis"), 0, "While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites.") +CONFIG_DWORD_INFO_EX(INTERNAL_AssertStacktrace, W("AssertStacktrace"), 1, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_clearNativeImageStress, W("clearNativeImageStress"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_CPUFamily, W("CPUFamily"), "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_CPUFeatures, W("CPUFeatures"), "") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_DisableConfigCache, W("DisableConfigCache"), 0, "Used to disable the \"probabilistic\" config cache, which walks through the appropriate config registry keys on init and probabilistically keeps track of which exist.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_DisableStackwalkCache, W("DisableStackwalkCache"), "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_DoubleArrayToLargeObjectHeap, W("DoubleArrayToLargeObjectHeap"), "Controls double[] placement") +CONFIG_DWORD_INFO(INTERNAL_DumpConfiguration, W("DumpConfiguration"), 0, "Dumps runtime properties of xml configuration files to the log.") +CONFIG_STRING_INFO(INTERNAL_DumpOnClassLoad, W("DumpOnClassLoad"), "Dumps information about loaded class to log.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_ExpandAllOnLoad, W("ExpandAllOnLoad"), "") +CONFIG_STRING_INFO_DIRECT_ACCESS(INTERNAL_ForcedRuntime, W("ForcedRuntime"), "Verify version of CLR loaded") +CONFIG_DWORD_INFO_EX(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GenerateLongJumpDispatchStubRatio, W("GenerateLongJumpDispatchStubRatio"), "Useful for testing VSD on AMD64") +CONFIG_DWORD_INFO_EX(INTERNAL_HashStack, W("HashStack"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO(INTERNAL_HostManagerConfig, W("HostManagerConfig"), (DWORD)-1, "") +CONFIG_DWORD_INFO(INTERNAL_HostTestThreadAbort, W("HostTestThreadAbort"), 0, "") +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_IgnoreDllMainReturn, W("IgnoreDllMainReturn"), 0, "Don't check the return value of DllMain if this is set", CLRConfig::ConfigFile_ApplicationFirst) +CONFIG_STRING_INFO(INTERNAL_InvokeHalt, W("InvokeHalt"), "Throws an assert when the given method is invoked through reflection.") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_legacyNullReferenceExceptionPolicy, W("legacyNullReferenceExceptionPolicy"), "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_legacyUnhandledExceptionPolicy, W("legacyUnhandledExceptionPolicy"), "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxStackDepth, W("MaxStackDepth"), "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxStubUnwindInfoSegmentSize, W("MaxStubUnwindInfoSegmentSize"), "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_MaxThreadRecord, W("MaxThreadRecord"), "") +CONFIG_DWORD_INFO(INTERNAL_MessageDebugOut, W("MessageDebugOut"), 0, "") +CONFIG_DWORD_INFO_EX(INTERNAL_MscorsnLogging, W("MscorsnLogging"), 0, "Enables strong name logging", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NativeImageRequire, W("NativeImageRequire"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "", CLRConfig::REGUTIL_default) +#define INTERNAL_NoGuiOnAssert_Default 1 +RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_NoGuiOnAssert, W("NoGuiOnAssert"), INTERNAL_NoGuiOnAssert_Default, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_EX(INTERNAL_NoStringInterning, W("NoStringInterning"), 1, "Disallows string interning. I see no value in it anymore.", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_NotifyBadAppCfg, W("NotifyBadAppCfg"), "Whether to show a message box for bad application config file.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_PauseOnLoad, W("PauseOnLoad"), "Stops in SystemDomain::init. I think it can be removed.") +CONFIG_DWORD_INFO(INTERNAL_PerfAllocsSizeThreshold, W("PerfAllocsSizeThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") +CONFIG_DWORD_INFO(INTERNAL_PerfNumAllocsThreshold, W("PerfNumAllocsThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") +CONFIG_STRING_INFO(INTERNAL_PerfTypesToLog, W("PerfTypesToLog"), "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Prepopulate1, W("Prepopulate1"), 1, "") +CONFIG_STRING_INFO(INTERNAL_PrestubGC, W("PrestubGC"), "") +CONFIG_STRING_INFO(INTERNAL_PrestubHalt, W("PrestubHalt"), "") +RETAIL_CONFIG_STRING_INFO(EXTERNAL_RestrictedGCStressExe, W("RestrictedGCStressExe"), "") +CONFIG_DWORD_INFO_EX(INTERNAL_ReturnSourceTypeForTesting, W("ReturnSourceTypeForTesting"), 0, "Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_RSStressLog, W("RSStressLog"), 0, "Allows turning on logging for RS startup", CLRConfig::REGUTIL_default) +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SaveThreadInfo, W("SaveThreadInfo"), "") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_SaveThreadInfoMask, W("SaveThreadInfoMask"), "") +CONFIG_DWORD_INFO(INTERNAL_SBDumpOnNewIndex, W("SBDumpOnNewIndex"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") +CONFIG_DWORD_INFO(INTERNAL_SBDumpOnResize, W("SBDumpOnResize"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") +CONFIG_DWORD_INFO(INTERNAL_SBDumpStyle, W("SBDumpStyle"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") +RETAIL_CONFIG_STRING_INFO_DIRECT_ACCESS(UNSUPPORTED_ShimDatabaseVersion, W("ShimDatabaseVersion"), "Force using shim database version in registry") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_SleepOnExit, W("SleepOnExit"), 0, "Used for lrak detection. I'd say deprecated by umdh.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_StubLinkerUnwindInfoVerificationOn, W("StubLinkerUnwindInfoVerificationOn"), "") +RETAIL_CONFIG_DWORD_INFO_EX(UNSUPPORTED_SuccessExit, W("SuccessExit"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_SymbolReadingPolicy, W("SymbolReadingPolicy"), "Specifies when PDBs may be read") +RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TestDataConsistency, W("TestDataConsistency"), FALSE, "Allows ensuring the left side is not holding locks (and may thus be in an inconsistent state) when inspection occurs") +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_ThreadGuardPages, W("ThreadGuardPages"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_Timeline, W("Timeline"), 0, "", CLRConfig::REGUTIL_default) +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_TotalStressLogSize, W("TotalStressLogSize"), "Total stress log size in bytes.") + +#ifdef _DEBUG +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_TraceIUnknown, W("TraceIUnknown"), "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_TraceWrap, W("TraceWrap"), "") +#endif + +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_TURNOFFDEBUGINFO, W("TURNOFFDEBUGINFO"), "") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseMethodDataCache, W("UseMethodDataCache"), FALSE, "Used during feature development; may now be removed.") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseParentMethodData, W("UseParentMethodData"), TRUE, "Used during feature development; may now be removed.") +CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_VerifierOff, W("VerifierOff"), "") +RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_VerifyAllOnLoad, W("VerifyAllOnLoad"), "") +// ** +// PLEASE MOVE ANY CONFIG SWITCH YOU OWN OUT OF THIS SECTION INTO A CATEGORY ABOVE +// +// DO NOT ADD ANY MORE CONFIG SWITCHES TO THIS SECTION! +// ** +//--------------------------------------------------------------------------------------- diff --git a/lib/coreclr/src/inc/clrdata.idl b/lib/coreclr/src/inc/clrdata.idl new file mode 100644 index 0000000000..6ef8ddbc6f --- /dev/null +++ b/lib/coreclr/src/inc/clrdata.idl @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** clrdata.idl - Common Language Runtime data access interfaces for ** + ** clients needing to access runtime state from outside ** + ** runtime, such as out-of-process debuggers. ** + ** ** + ** The access interface defines two different types of code running: ** + ** The host is the user of the access interface. ** + ** The target is the target of the access. ** + ** ** + ** The host and target can be have different instruction sets, ** + ** pointer sizes, runtime versions and so on. ** + ** ** + *****************************************************************************/ + +import "unknwn.idl"; + +/* ------------------------------------------------------------------------- * + * Forward declarations. + * ------------------------------------------------------------------------- */ + +interface ICLRDataEnumMemoryRegions; +interface ICLRDataEnumMemoryRegionsCallback; +interface ICLRDataEnumMemoryRegionsCallback2; +interface ICLRDataTarget; +interface ICLRDataTarget2; +interface ICLRMetadataLocator; + +/* + * Addresses in the access interface are always the largest possible. + * If the target uses a smaller address size then addresses are converted + * up by sign extension. + */ +typedef ULONG64 CLRDATA_ADDRESS; + +/* ------------------------------------------------------------------------- * + * Creation function. + * Can create ICLRDataEnumMemoryRegions. + * ------------------------------------------------------------------------- */ + +#pragma midl_echo("STDAPI CLRDataCreateInstance(REFIID iid, ICLRDataTarget* target, void** iface);") +#pragma midl_echo("typedef HRESULT (STDAPICALLTYPE* PFN_CLRDataCreateInstance)(REFIID iid, ICLRDataTarget* target, void** iface);") + +/* + * Interface for providing access to a particular target process. The + * data access services will call functions on this interface to + * access memory and other data in the target process. + * + * The API client must implement this interface as appropriate for the + * particular target (for example, a live process or a memory dump). + * + */ +[ + object, + local, + uuid(3E11CCEE-D08B-43e5-AF01-32717A64DA03), + pointer_default(unique) +] +interface ICLRDataTarget : IUnknown +{ + /* + * Return which kind of instruction set is in use in the + * target. Value is one of the IMAGE_FILE_MACHINE_* constants. + */ + HRESULT GetMachineType([out] ULONG32* machineType); + + /* + * Return the size of a pointer on the target, in bytes. + */ + HRESULT GetPointerSize([out] ULONG32* pointerSize); + + /* + * Find the base address for a given image. + * Image name may or may not have a path. If a path + * is given matching is done with the whole path, otherwise + * matching is done only on the file part. + * In either case, matching should be case-insensitive. + */ + HRESULT GetImageBase([in, string] LPCWSTR imagePath, + [out] CLRDATA_ADDRESS* baseAddress); + + /* + * Virtual memory access. If any bytes can be processed + * the call is considered successful. + */ + HRESULT ReadVirtual([in] CLRDATA_ADDRESS address, + [out, size_is(bytesRequested), length_is(*bytesRead)] BYTE* buffer, + [in] ULONG32 bytesRequested, + [out] ULONG32* bytesRead); + HRESULT WriteVirtual([in] CLRDATA_ADDRESS address, + [in, size_is(bytesRequested)] BYTE* buffer, + [in] ULONG32 bytesRequested, + [out] ULONG32* bytesWritten); + + /* + * TLS data access for the current thread. + */ + HRESULT GetTLSValue([in] ULONG32 threadID, + [in] ULONG32 index, + [out] CLRDATA_ADDRESS* value); + HRESULT SetTLSValue([in] ULONG32 threadID, + [in] ULONG32 index, + [in] CLRDATA_ADDRESS value); + + /* + * System ID for the current thread. + * If there is no "current" thread for the target + * implementation this can fail. + */ + HRESULT GetCurrentThreadID([out] ULONG32* threadID); + + /* + * Thread context. + */ + HRESULT GetThreadContext([in] ULONG32 threadID, + [in] ULONG32 contextFlags, + [in] ULONG32 contextSize, + [out, size_is(contextSize)] BYTE* context); + HRESULT SetThreadContext([in] ULONG32 threadID, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE* context); + + /* + * Generic request facility to allow addition of + * queries and operations without requiring an interface revision. + */ + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); +}; + +/* + * Interface used by the data access services layer to manipulate + * virtual memory regions in the target. The target may not support + * modification. + */ +[ + object, + local, + uuid(6d05fae3-189c-4630-a6dc-1c251e1c01ab), + pointer_default(unique) +] +interface ICLRDataTarget2 : ICLRDataTarget +{ + /* + * Ask the target to allocate memory in its address space. + */ + HRESULT AllocVirtual([in] CLRDATA_ADDRESS addr, + [in] ULONG32 size, + [in] ULONG32 typeFlags, + [in] ULONG32 protectFlags, + [out] CLRDATA_ADDRESS* virt); + + /* + * Ask the target to free a previously allocated memory block. + */ + HRESULT FreeVirtual([in] CLRDATA_ADDRESS addr, + [in] ULONG32 size, + [in] ULONG32 typeFlags); +}; + +/* + * Interface for providing access to exception and context records. + */ +[ + object, + local, + uuid(a5664f95-0af4-4a1b-960e-2f3346b4214c), + pointer_default(unique) +] +interface ICLRDataTarget3 : ICLRDataTarget2 +{ + /* + * Returns an associated exception record, if any. + */ + HRESULT GetExceptionRecord([in] ULONG32 bufferSize, + [out] ULONG32* bufferUsed, + [out, size_is(bufferSize)] BYTE* buffer); + + /* + * Returns a context record associated with the exception, if any. + */ + HRESULT GetExceptionContextRecord([in] ULONG32 bufferSize, + [out] ULONG32* bufferUsed, + [out, size_is(bufferSize)] BYTE* buffer); + + /* + * Returns the ID of the thread raising the exception. + */ + HRESULT GetExceptionThreadID([out] ULONG32* threadID); +}; + +/* + * Interface used by the data access services layer to locate metadata + * of assemblies in a target. + * + * The API client must implement this interface as appropriate for the + * particular target (for example, a live process or a memory dump). + * + * This is an old interface you should not be using. + * see code:ICorDebugMetaDataLocator in cordebug.idl + * + */ +[ + object, + local, + uuid(aa8fa804-bc05-4642-b2c5-c353ed22fc63), + pointer_default(unique) +] +interface ICLRMetadataLocator : IUnknown +{ + /* + * Ask the target to retrieve metadata for an image. + */ + HRESULT GetMetadata([in] LPCWSTR imagePath, + [in] ULONG32 imageTimestamp, + [in] ULONG32 imageSize, + [in] GUID* mvid, + [in] ULONG32 mdRva, + [in] ULONG32 flags, + [in] ULONG32 bufferSize, + [out, size_is(bufferSize), length_is(*dataSize)] + BYTE* buffer, + [out] ULONG32* dataSize); +}; + + +/* + * Callback interface for enumerating memory regions. + */ +[ + object, + local, + uuid(BCDD6908-BA2D-4ec5-96CF-DF4D5CDCB4A4) +] +interface ICLRDataEnumMemoryRegionsCallback : IUnknown +{ + /* + * ICLRDataEnumMemoryRegions::EnumMemoryRegions will call this + * function for every memory region enumerated. Regions reported + * through this callback may be duplicate or overlapping. Failure + * return results will be noted, but will not stop the + * enumeration. + */ + HRESULT EnumMemoryRegion([in] CLRDATA_ADDRESS address, + [in] ULONG32 size); +} + +/* + * Callback interface for writing/poisoning memory regions. + */ +[ + object, + local, + uuid(3721A26F-8B91-4D98-A388-DB17B356FADB) +] +interface ICLRDataEnumMemoryRegionsCallback2 : ICLRDataEnumMemoryRegionsCallback +{ + /* + * ICLRDataEnumMemoryRegions::EnumMemoryRegions will call this function + * for every memory regions it needs to overwrite/poison with the specified + * data buffer passed as input argument. + */ + HRESULT UpdateMemoryRegion( + [in] CLRDATA_ADDRESS address, + [in] ULONG32 bufferSize, + [in, size_is(bufferSize)] BYTE* buffer); +} + +/* + * Flags for controlling which memory regions are enumerated. + */ +typedef enum CLRDataEnumMemoryFlags +{ + CLRDATA_ENUM_MEM_DEFAULT = 0x0, + CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, // generating skinny mini-dump + CLRDATA_ENUM_MEM_HEAP = 0x1, // generating heap dump + CLRDATA_ENUM_MEM_TRIAGE = 0x2, // generating triage mini-dump + + /* More bits to be added here later */ +} CLRDataEnumMemoryFlags; + +/* + * Memory enumeration interface. + * This is one of the top-level interfaces creatable by CLRDataCreateInstance. + */ +[ + object, + local, + uuid(471c35b4-7c2f-4ef0-a945-00f8c38056f1) +] +interface ICLRDataEnumMemoryRegions : IUnknown +{ + /* + * EnumMemoryRegions enumerates regions of interest as specified + * by the flags argument by calling the + * ICLRDataEnumMemoryRegionsCallback::EnumMemoryRegion for every + * region being enumerated. Attempts to enumerate as many regions + * as possible, even if the callback returns failures during + * enumeration. + */ + HRESULT EnumMemoryRegions([in] ICLRDataEnumMemoryRegionsCallback *callback, + [in] ULONG32 miniDumpFlags, + [in] CLRDataEnumMemoryFlags clrFlags); +} + diff --git a/lib/coreclr/src/inc/clrhost.h b/lib/coreclr/src/inc/clrhost.h new file mode 100644 index 0000000000..88a917d59f --- /dev/null +++ b/lib/coreclr/src/inc/clrhost.h @@ -0,0 +1,392 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// + + +#ifndef __CLRHOST_H__ +#define __CLRHOST_H__ + +#include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions +#ifdef CreateSemaphore +#undef CreateSemaphore +#endif +#include "mscoree.h" +#include "clrinternal.h" +#include "switches.h" +#include "holder.h" +#include "new.hpp" +#include "staticcontract.h" +#include "predeftlsslot.h" +#include "safemath.h" +#include "debugreturn.h" +#include "yieldprocessornormalized.h" + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +#define BEGIN_PRESERVE_LAST_ERROR \ + { \ + DWORD __dwLastError = ::GetLastError(); \ + DEBUG_ASSURE_NO_RETURN_BEGIN(PRESERVE_LAST_ERROR); \ + { + +#define END_PRESERVE_LAST_ERROR \ + } \ + DEBUG_ASSURE_NO_RETURN_END(PRESERVE_LAST_ERROR); \ + ::SetLastError(__dwLastError); \ + } + +// +// TRASH_LASTERROR macro sets bogus last error in debug builds to help find places that fail to save it +// +#ifdef _DEBUG + +#define LAST_ERROR_TRASH_VALUE 42424 /* = 0xa5b8 */ + +#define TRASH_LASTERROR \ + SetLastError(LAST_ERROR_TRASH_VALUE) + +#else // _DEBUG + +#define TRASH_LASTERROR + +#endif // _DEBUG + +IExecutionEngine *GetExecutionEngine(); +IEEMemoryManager *GetEEMemoryManager(); + +LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); +BOOL ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); +SIZE_T ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); +BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); +LPVOID ClrDebugAlloc (size_t size, LPCSTR pszFile, int iLineNo); +HANDLE ClrGetProcessHeap(); +HANDLE ClrHeapCreate(DWORD flOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize); +BOOL ClrHeapDestroy(HANDLE hHeap); +LPVOID ClrHeapAlloc(HANDLE hHeap, DWORD dwFlags, S_SIZE_T dwBytes); +BOOL ClrHeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); +BOOL ClrHeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem); +HANDLE ClrGetProcessExecutableHeap(); + + +#ifdef FAILPOINTS_ENABLED +extern int RFS_HashStack(); +#endif + + +void ClrFlsAssociateCallback(DWORD slot, PTLS_CALLBACK_FUNCTION callback); + +typedef LPVOID* (*CLRFLSGETBLOCK)(); +extern CLRFLSGETBLOCK __ClrFlsGetBlock; + +// Combining getter/setter into a single call +inline void ClrFlsIncrementValue(DWORD slot, int increment) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + + _ASSERTE(increment != 0); + + void **block = (*__ClrFlsGetBlock)(); + size_t value; + + if (block != NULL) + { + value = (size_t) block[slot]; + + _ASSERTE((increment > 0) || (value + increment < value)); + block[slot] = (void *) (value + increment); + } + else + { + BEGIN_PRESERVE_LAST_ERROR; + + IExecutionEngine * pEngine = GetExecutionEngine(); + value = (size_t) pEngine->TLS_GetValue(slot); + + _ASSERTE((increment > 0) || (value + increment < value)); + pEngine->TLS_SetValue(slot, (void *) (value + increment)); + + END_PRESERVE_LAST_ERROR; + } +} + + +inline void * ClrFlsGetValue (DWORD slot) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + + void **block = (*__ClrFlsGetBlock)(); + if (block != NULL) + { + return block[slot]; + } + else + { + void * value = GetExecutionEngine()->TLS_GetValue(slot); + return value; + } +} + + +inline BOOL ClrFlsCheckValue(DWORD slot, void ** pValue) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + +#ifdef _DEBUG + *pValue = ULongToPtr(0xcccccccc); +#endif //_DEBUG + void **block = (*__ClrFlsGetBlock)(); + if (block != NULL) + { + *pValue = block[slot]; + return TRUE; + } + else + { + BOOL result = GetExecutionEngine()->TLS_CheckValue(slot, pValue); + return result; + } +} + +inline void ClrFlsSetValue(DWORD slot, void *pData) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + + void **block = (*__ClrFlsGetBlock)(); + if (block != NULL) + { + block[slot] = pData; + } + else + { + BEGIN_PRESERVE_LAST_ERROR; + + GetExecutionEngine()->TLS_SetValue(slot, pData); + + END_PRESERVE_LAST_ERROR; + } +} + +#ifndef SELF_NO_HOST +LPVOID EEHeapAllocInProcessHeap(DWORD dwFlags, SIZE_T dwBytes); +BOOL EEHeapFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem); +#endif + +inline LPVOID ClrAllocInProcessHeap(DWORD dwFlags, S_SIZE_T dwBytes) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; + if (dwBytes.IsOverflow()) + { + return NULL; + } + +#ifndef SELF_NO_HOST + return EEHeapAllocInProcessHeap(dwFlags, dwBytes.Value()); +#else +#undef HeapAlloc +#undef GetProcessHeap + static HANDLE ProcessHeap = NULL; + if (ProcessHeap == NULL) + ProcessHeap = GetProcessHeap(); + return ::HeapAlloc(ProcessHeap,dwFlags,dwBytes.Value()); +#define HeapAlloc(hHeap, dwFlags, dwBytes) Dont_Use_HeapAlloc(hHeap, dwFlags, dwBytes) +#define GetProcessHeap() Dont_Use_GetProcessHeap() +#endif +} + +inline BOOL ClrFreeInProcessHeap(DWORD dwFlags, LPVOID lpMem) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; +#ifndef SELF_NO_HOST + return EEHeapFreeInProcessHeap(dwFlags, lpMem); +#else +#undef HeapFree +#undef GetProcessHeap + static HANDLE ProcessHeap = NULL; + if (ProcessHeap == NULL) + ProcessHeap = GetProcessHeap(); + return (BOOL)(BYTE)::HeapFree(ProcessHeap, dwFlags, lpMem); +#define HeapFree(hHeap, dwFlags, lpMem) Dont_Use_HeapFree(hHeap, dwFlags, lpMem) +#define GetProcessHeap() Dont_Use_GetProcessHeap() +#endif +} + +// Critical section support for CLR DLLs other than the the EE. +// Include the header defining each Crst type and its corresponding level (relative rank). This is +// auto-generated from a tool that takes a high-level description of each Crst type and its dependencies. +#include "crsttypes.h" + +// critical section api +CRITSEC_COOKIE ClrCreateCriticalSection(CrstType type, CrstFlags flags); +HRESULT ClrDeleteCriticalSection(CRITSEC_COOKIE cookie); +void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); +void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); + +// event api +EVENT_COOKIE ClrCreateAutoEvent(BOOL bInitialState); +EVENT_COOKIE ClrCreateManualEvent(BOOL bInitialState); +void ClrCloseEvent(EVENT_COOKIE event); +BOOL ClrSetEvent(EVENT_COOKIE event); +BOOL ClrResetEvent(EVENT_COOKIE event); +DWORD ClrWaitEvent(EVENT_COOKIE event, DWORD dwMilliseconds, BOOL bAlertable); + +// semaphore api +SEMAPHORE_COOKIE ClrCreateSemaphore(DWORD dwInitial, DWORD dwMax); +void ClrCloseSemaphore(SEMAPHORE_COOKIE semaphore); +BOOL ClrReleaseSemaphore(SEMAPHORE_COOKIE semaphore, LONG lReleaseCount, LONG *lpPreviousCount); +DWORD ClrWaitSemaphore(SEMAPHORE_COOKIE semaphore, DWORD dwMilliseconds, BOOL bAlertable); + +// mutex api +MUTEX_COOKIE ClrCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName); +void ClrCloseMutex(MUTEX_COOKIE mutex); +BOOL ClrReleaseMutex(MUTEX_COOKIE mutex); +DWORD ClrWaitForMutex(MUTEX_COOKIE mutex,DWORD dwMilliseconds,BOOL bAlertable); +DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable); + +// Rather than use the above APIs directly, it is recommended that holder classes +// be used. This guarantees that the locks will be vacated when the scope is popped, +// either on exception or on return. + +typedef Holder CRITSEC_Holder; + +// Use this holder to manage CRITSEC_COOKIE allocation to ensure it will be released if anything goes wrong +FORCEINLINE void VoidClrDeleteCriticalSection(CRITSEC_COOKIE cs) { if (cs != NULL) ClrDeleteCriticalSection(cs); } +typedef Wrapper, VoidClrDeleteCriticalSection, NULL> CRITSEC_AllocationHolder; + +class Event { +public: + Event () + : m_event(NULL) + {STATIC_CONTRACT_LEAF;} + ~Event () + { + STATIC_CONTRACT_WRAPPER; + CloseEvent(); + } + + void CreateAutoEvent(BOOL bInitialState) + { + STATIC_CONTRACT_WRAPPER; + m_event = ClrCreateAutoEvent(bInitialState); + } + void CreateManualEvent(BOOL bInitialState) + { + STATIC_CONTRACT_WRAPPER; + m_event = ClrCreateManualEvent(bInitialState); + } + void CloseEvent() + { + STATIC_CONTRACT_WRAPPER; + if (m_event != NULL) + ClrCloseEvent(m_event); + m_event = NULL; + } + + BOOL Set() + { + STATIC_CONTRACT_WRAPPER; + return ClrSetEvent(m_event); + } + BOOL Reset() + { + STATIC_CONTRACT_WRAPPER; + return ClrResetEvent(m_event); + } + DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) + { + STATIC_CONTRACT_WRAPPER; + return ClrWaitEvent(m_event, dwMilliseconds, bAlertable); + } + +private: + EVENT_COOKIE m_event; +}; + +class Semaphore { +public: + Semaphore () + : m_semaphore(NULL) + {STATIC_CONTRACT_LEAF;} + ~Semaphore () + { + STATIC_CONTRACT_WRAPPER; + Close(); + } + + void Create(DWORD dwInitial, DWORD dwMax) + { + STATIC_CONTRACT_WRAPPER; + m_semaphore = ClrCreateSemaphore(dwInitial, dwMax); + } + void Close() + { + STATIC_CONTRACT_WRAPPER; + if (m_semaphore != NULL) + ClrCloseSemaphore(m_semaphore); + m_semaphore = NULL; + } + + BOOL Release(LONG lReleaseCount, LONG* lpPreviousCount) + { + STATIC_CONTRACT_WRAPPER; + return ClrReleaseSemaphore(m_semaphore, lReleaseCount, lpPreviousCount); + } + DWORD Wait(DWORD dwMilliseconds, BOOL bAlertable) + { + STATIC_CONTRACT_WRAPPER; + return ClrWaitSemaphore(m_semaphore, dwMilliseconds, bAlertable); + } + +private: + SEMAPHORE_COOKIE m_semaphore; +}; + +HMODULE GetCLRModule (); + +extern void IncCantAllocCount(); +extern void DecCantAllocCount(); + +class CantAllocHolder +{ +public: + CantAllocHolder () + { + IncCantAllocCount (); + } + ~CantAllocHolder() + { + DecCantAllocCount (); + } +}; + +// At places where want to allocate stress log, we need to first check if we are allowed to do so. +// If ClrTlsInfo doesn't exist for this thread, we take it as can alloc +inline bool IsInCantAllocRegion () +{ + size_t count = 0; + if (ClrFlsCheckValue(TlsIdx_CantAllocCount, (LPVOID *)&count)) + { + _ASSERTE (count >= 0); + return count > 0; + } + return false; +} +// for stress log the rule is more restrict, we have to check the global counter too +extern BOOL IsInCantAllocStressLogRegion(); + +#endif diff --git a/lib/coreclr/src/inc/clrinternal.idl b/lib/coreclr/src/inc/clrinternal.idl new file mode 100644 index 0000000000..0c93f4ae6d --- /dev/null +++ b/lib/coreclr/src/inc/clrinternal.idl @@ -0,0 +1,296 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/************************************************************************************** + ** ** + ** clrinternal.idl - interface definitions for internal usage. ** + ** ** + **************************************************************************************/ + +// +// Interface descriptions +// +import "unknwn.idl"; + +// import mscoree.idl for BucketParameters definition +import "mscoree.idl"; + + + +cpp_quote("#if 0") + +typedef struct _OSVERSIONINFOA { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage +} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA; + +typedef struct _OSVERSIONINFOW { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + WCHAR szCSDVersion[ 128 ]; // Maintenance string for PSS usage +} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW; +#ifdef UNICODE +typedef OSVERSIONINFOW OSVERSIONINFO; +typedef POSVERSIONINFOW POSVERSIONINFO; +typedef LPOSVERSIONINFOW LPOSVERSIONINFO; +#else +typedef OSVERSIONINFOA OSVERSIONINFO; +typedef POSVERSIONINFOA POSVERSIONINFO; +typedef LPOSVERSIONINFOA LPOSVERSIONINFO; +#endif // UNICODE + +cpp_quote("#endif") + +// IID IExecutionEngine : uuid(7AF02DAC-2A33-494b-A09F-25E00A93C6F8) +cpp_quote("EXTERN_GUID(IID_IExecutionEngine, 0x7AF02DAC, 0x2A33, 0x494b, 0xA0, 0x9F, 0x25, 0xE0, 0x0A, 0x93, 0xC6, 0xF8);") + +// IID IEEMemoryManager : uuid{17713B61-B59F-4e13-BAAF-91623DC8ADC0} +cpp_quote("EXTERN_GUID(IID_IEEMemoryManager, 0x17713b61, 0xb59f, 0x4e13, 0xba, 0xaf, 0x91, 0x62, 0x3d, 0xc8, 0xad, 0xc0);") + +// This ID is embedded in the CLRDEBUGINFO resource so that the shim can differentiate dlls which happen to be named +// clr.dll from official Microsoft clr.dll implementations. This is not intended to authenticate a CLR in a strong +// security sense but short of deliberate 3rd party spoofing it should provide a good identity. +// +// Using a different ID allows us to completely hide different CLR SKUs from each other. The recommendation is to keep +// the ID contant between different versions of the same SKU and use mscordbi's logic to determine whether a given +// version is compatible. This allows debuggers to give different errors for 'future version of the CLR I don't +// support' vs. 'No CLR is loaded at all.' +// +// This guid first appears in version 4.0 of CLR on x86 and amd64 - earlier versions had no resource +// GUID CLR_ID_V4_DESKTOP : uuid{267F3989-D786-4b9a-9AF6-D19E42D557EC} +cpp_quote("EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec);") + +// This guid has been set aside for CoreCLR usage - at present CoreCLR doesn't use it though +// GUID CLR_ID_CORECLR : uuid{8CB8E075-0A91-408E-9228-D66E00A3BFF6} +cpp_quote("EXTERN_GUID(CLR_ID_CORECLR, 0x8CB8E075, 0x0A91, 0x408E, 0x92, 0x28, 0xD6, 0x6E, 0x00, 0xA3, 0xBF, 0xF6 );") + +// This guid first appears in the CoreCLR port to Windows Phone 8 - note that it is seperate from the CoreCLR id because it will +// potentially have a different verioning lineage than CoreCLR +// GUID CLR_ID_PHONE_CLR : uuid{E7237E9C-31C0-488C-AD48-324D3E7ED92A} +cpp_quote("EXTERN_GUID(CLR_ID_PHONE_CLR, 0xE7237E9C, 0x31C0, 0x488C, 0xAD, 0x48, 0x32, 0x4D, 0x3E, 0x7E, 0xD9, 0x2A);") + +// This guid first appears 8/19/14 as CoreCLR evolves to OneCore, ProjectK, and versions of Phone after PhoneBlue +// The new guid intentionally creates a breaking change so we can simplify the file naming on mscordaccore.dll and mscordbi.dll +// in xplat hosting scenarios. Old versions of dbgshim.dll will not be able to support this. +// GUID CLR_ID_ONECORE_CLR : uuid{B1EE760D-6C4A-4533-BA41-6F4F661FABAF} +cpp_quote("EXTERN_GUID(CLR_ID_ONECORE_CLR, 0xb1ee760d, 0x6c4a, 0x4533, 0xba, 0x41, 0x6f, 0x4f, 0x66, 0x1f, 0xab, 0xaf);") + + +// IID_IPrivateManagedExceptionReporting : uuid{AD76A023-332D-4298-8001-07AA9350DCA4} +cpp_quote("EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d, 0x4298, 0x80, 0x01, 0x07, 0xaa, 0x93, 0x50, 0xdc, 0xa4);") + + +//***************************************************************************** +// Interface for exposing services from the EE to other DLLs of the CLR. +//***************************************************************************** +typedef void * CRITSEC_COOKIE; +typedef void * EVENT_COOKIE; +typedef void * SEMAPHORE_COOKIE; +typedef void * MUTEX_COOKIE; + +typedef enum { + CRST_DEFAULT = 0x0, + CRST_REENTRANCY = 0x1, // allow same thread to take lock multiple times. + CRST_UNSAFE_SAMELEVEL = 0x2, // AVOID THIS! Can take other locks @ same level in + // any order. + CRST_UNSAFE_COOPGC = 0x4, // AVOID THIS! Lock must be taken in cooperative mode. + CRST_UNSAFE_ANYMODE = 0x8, // AVOID THIS! Lock can be taken in either GC mode. + CRST_DEBUGGER_THREAD = 0x10, // This lock can be taken on the debugger's helper thread. + CRST_HOST_BREAKABLE = 0x20, // This lock is held while running managed code. It can be terminated by a host. + // CRST_UNUSED = 0x40, + CRST_TAKEN_DURING_SHUTDOWN = 0x80, // This lock is taken during the shutdown sequence in EEShutdown(helper) + CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, + // User of this lock cannot trigger GC, while it is locked. + // Note that Enter on this lock can trigger GC if called from COOPERATIVE mode. + // It is useful for locks which can be taken on GC or debugger threads. + CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200, + // Some rare locks should be taken only in ForbidSuspend region (i.e. profiler cannot walk the stack), + // this option will assert it in debug mode. +} CrstFlags; + +// Callback function for cleaning up TLS +typedef VOID (__stdcall *PTLS_CALLBACK_FUNCTION)(PVOID); + + +[ + uuid(7AF02DAC-2A33-494b-A09F-25E00A93C6F8), + helpstring("CLR Coordination Interface"), + pointer_default(unique), + local +] +interface IExecutionEngine : IUnknown +{ + // Thread Local Storage is based on logical threads. The underlying + // implementation could be threads, fibers, or something more exotic. + // Slot numbers are predefined. This is not a general extensibility + // mechanism. + + // Associate a callback function for releasing TLS on thread/fiber death. + // This can be NULL. + void TLS_AssociateCallback([in] DWORD slot, [in] PTLS_CALLBACK_FUNCTION callback); + + // Get the TLS block for fast Get/Set operations + PVOID* TLS_GetDataBlock(); + + // Get the value at a slot + PVOID TLS_GetValue([in] DWORD slot); + + // Get the value at a slot, return FALSE if TLS info block doesn't exist + BOOL TLS_CheckValue([in] DWORD slot, [out] PVOID * pValue); + + // Set the value at a slot + void TLS_SetValue([in] DWORD slot, [in] PVOID pData); + + // Free TLS memory block and make callback + void TLS_ThreadDetaching(); + + // Critical Sections are sometimes exposed to the host and therefore need to be + // reflected from all CLR DLLs to the EE. + // + // In addition, we always monitor interactions between the lock & the GC, based + // on the GC mode in which the lock is acquired and we restrict what operations + // are permitted while holding the lock based on this. + // + // Finally, we we rank all our locks to prevent deadlock across all the DLLs of + // the CLR. This is the level argument to CreateLock. + // + // All usage of these locks must be exception-safe. To achieve this, we suggest + // using Holders (see holder.h & crst.h). In fact, within the EE code cannot + // hold locks except by using exception-safe holders. + + CRITSEC_COOKIE CreateLock([in] LPCSTR szTag, [in] LPCSTR level, [in] CrstFlags flags); + + void DestroyLock([in] CRITSEC_COOKIE lock); + + void AcquireLock([in] CRITSEC_COOKIE lock); + + void ReleaseLock([in] CRITSEC_COOKIE lock); + + EVENT_COOKIE CreateAutoEvent([in] BOOL bInitialState); + EVENT_COOKIE CreateManualEvent([in] BOOL bInitialState); + void CloseEvent([in] EVENT_COOKIE event); + BOOL ClrSetEvent([in] EVENT_COOKIE event); + BOOL ClrResetEvent([in] EVENT_COOKIE event); + DWORD WaitForEvent([in] EVENT_COOKIE event, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); + DWORD WaitForSingleObject([in] HANDLE handle, [in] DWORD dwMilliseconds); + + // OS header file defines CreateSemaphore. + SEMAPHORE_COOKIE ClrCreateSemaphore([in] DWORD dwInitial, [in] DWORD dwMax); + void ClrCloseSemaphore([in] SEMAPHORE_COOKIE semaphore); + DWORD ClrWaitForSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); + BOOL ClrReleaseSemaphore([in] SEMAPHORE_COOKIE semaphore, [in] LONG lReleaseCount, [in] LONG *lpPreviousCount); + + MUTEX_COOKIE ClrCreateMutex([in]LPSECURITY_ATTRIBUTES lpMutexAttributes, [in]BOOL bInitialOwner, [in]LPCTSTR lpName); + DWORD ClrWaitForMutex([in] MUTEX_COOKIE mutex, [in] DWORD dwMilliseconds, [in] BOOL bAlertable); + BOOL ClrReleaseMutex([in] MUTEX_COOKIE mutex); + void ClrCloseMutex([in] MUTEX_COOKIE mutex); + + DWORD ClrSleepEx([in] DWORD dwMilliseconds, [in] BOOL bAlertable); + + BOOL ClrAllocationDisallowed(); + + void GetLastThrownObjectExceptionFromThread([out] void **ppvException); + +}; // interface IExecutionEngine + + +//***************************************************************************** +// Interface for exposing memory services from the EE to other DLLs of the CLR. +//***************************************************************************** + +cpp_quote("#if !defined(_WINNT_) && !defined(_NTMMAPI_)") +typedef void* PMEMORY_BASIC_INFORMATION; +cpp_quote("#endif") + + +[ + uuid(17713B61-B59F-4e13-BAAF-91623DC8ADC0), + helpstring("CLR Memory Manager Interface"), + pointer_default(unique), + local +] +interface IEEMemoryManager : IUnknown +{ + LPVOID ClrVirtualAlloc( + [in] LPVOID lpAddress, // region to reserve or commit + [in] SIZE_T dwSize, // size of region + [in] DWORD flAllocationType, // type of allocation + [in] DWORD flProtect // type of access protection + ); + + BOOL ClrVirtualFree( + [in] LPVOID lpAddress, // address of region + [in] SIZE_T dwSize, // size of region + [in] DWORD dwFreeType // operation type + ); + + SIZE_T ClrVirtualQuery( + [in] const void* lpAddress, // address of region + [in] PMEMORY_BASIC_INFORMATION lpBuffer, // information buffer + [in] SIZE_T dwLength // size of buffer + ); + + BOOL ClrVirtualProtect( + [in] LPVOID lpAddress, // region of committed pages + [in] SIZE_T dwSize, // size of the region + [in] DWORD flNewProtect, // desired access protection + [in] DWORD* lpflOldProtect // old protection + ); + + HANDLE ClrGetProcessHeap(); + + HANDLE ClrHeapCreate( + [in] DWORD flOptions, // heap allocation attributes + [in] SIZE_T dwInitialSize, // initial heap size + [in] SIZE_T dwMaximumSize // maximum heap size + ); + + BOOL ClrHeapDestroy( + [in] HANDLE hHeap // handle to heap + ); + + LPVOID ClrHeapAlloc( + [in] HANDLE hHeap, // handle to private heap block + [in] DWORD dwFlags, // heap allocation control + [in] SIZE_T dwBytes // number of bytes to allocate + ); + + BOOL ClrHeapFree( + [in] HANDLE hHeap, // handle to heap + [in] DWORD dwFlags, // heap free options + [in] LPVOID lpMem // pointer to memory + ); + + BOOL ClrHeapValidate( + [in] HANDLE hHeap, // handle to heap + [in] DWORD dwFlags, // heap access options + [in] const void* lpMem // optional pointer to memory block + ); + + HANDLE ClrGetProcessExecutableHeap(); + +}; // interface IEEMemoryManager + +//******************************************************************************************** +// Interface for exposing GetBucketParametersForCurrentException to Watson testing harness. +//******************************************************************************************** +[ + uuid(AD76A023-332D-4298-8001-07AA9350DCA4), + helpstring("Private Managed Exception Reporting Interface"), + pointer_default(unique), + local +] +interface IPrivateManagedExceptionReporting : IUnknown +{ + HRESULT GetBucketParametersForCurrentException([out]BucketParameters *pParams); +} + + diff --git a/lib/coreclr/src/inc/clrnt.h b/lib/coreclr/src/inc/clrnt.h new file mode 100644 index 0000000000..1356666024 --- /dev/null +++ b/lib/coreclr/src/inc/clrnt.h @@ -0,0 +1,1042 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef CLRNT_H_ +#define CLRNT_H_ + +#include "staticcontract.h" +#include "cfi.h" + +// +// This file is the result of some changes to the SDK header files. +// In particular, nt.h and some of its dependencies are no longer +// available except as "nonship" files. As a result, this file +// was created as a simple cut and past of structures and functions +// from NT that are either not yet documented or have been overlooked +// as being part of the platform SDK. +// + +// +// ALL PLATFORMS +// + +#define STATUS_INVALID_PARAMETER_3 ((NTSTATUS)0xC00000F1L) +#define STATUS_INVALID_PARAMETER_4 ((NTSTATUS)0xC00000F2L) +#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) +#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) + +#ifndef STATUS_UNWIND +#define STATUS_UNWIND ((NTSTATUS)0x80000027L) +#endif + +#ifndef DBG_PRINTEXCEPTION_C +#define DBG_PRINTEXCEPTION_C ((DWORD)0x40010006L) +#endif + +#ifndef STATUS_UNWIND_CONSOLIDATE +#define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS)0x80000029L) +#endif + +#ifndef STATUS_LONGJUMP +#define STATUS_LONGJUMP ((NTSTATUS)0x80000026L) +#endif + +#ifndef LOCALE_NAME_MAX_LENGTH +#define LOCALE_NAME_MAX_LENGTH 85 +#endif // !LOCALE_NAME_MAX_LENGTH + +#ifndef SUBLANG_CUSTOM_DEFAULT +#define SUBLANG_CUSTOM_DEFAULT 0x03 // default custom language/locale +#define SUBLANG_CUSTOM_UNSPECIFIED 0x04 // custom language/locale +#define LOCALE_CUSTOM_DEFAULT \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT), SORT_DEFAULT)) +#define LOCALE_CUSTOM_UNSPECIFIED \ + (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED), SORT_DEFAULT)) +#endif // !SUBLANG_CUSTOM_DEFAULT + +#ifndef __out_xcount_opt +#define __out_xcount_opt(var) __out +#endif + +#ifndef __encoded_pointer +#define __encoded_pointer +#endif + +#ifndef __range +#define __range(min, man) +#endif + +#ifndef __field_bcount +#define __field_bcount(size) +#endif + +#ifndef __field_ecount_opt +#define __field_ecount_opt(nFields) +#endif + +#ifndef __field_ecount +#define __field_ecount(EHCount) +#endif + +#undef _Ret_bytecap_ +#define _Ret_bytecap_(_Size) + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + +#define ARGUMENT_PRESENT(ArgumentPointer) (\ + (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) ) + +#define EXCEPTION_CHAIN_END ((PEXCEPTION_REGISTRATION_RECORD)-1) + +typedef signed char SCHAR; +typedef SCHAR *PSCHAR; +typedef LONG NTSTATUS; + +#ifndef FEATURE_PAL + +#define TLS_MINIMUM_AVAILABLE 64 // winnt +#define TLS_EXPANSION_SLOTS 1024 + +typedef enum _THREADINFOCLASS { + ThreadBasicInformation, + ThreadTimes, + ThreadPriority, + ThreadBasePriority, + ThreadAffinityMask, + ThreadImpersonationToken, + ThreadDescriptorTableEntry, + ThreadEnableAlignmentFaultFixup, + ThreadEventPair_Reusable, + ThreadQuerySetWin32StartAddress, + ThreadZeroTlsCell, + ThreadPerformanceCount, + ThreadAmILastThread, + ThreadIdealProcessor, + ThreadPriorityBoost, + ThreadSetTlsArrayAddress, + ThreadIsIoPending, + ThreadHideFromDebugger, + ThreadBreakOnTermination, + MaxThreadInfoClass + } THREADINFOCLASS; + +typedef enum _SYSTEM_INFORMATION_CLASS { + SystemBasicInformation, + SystemProcessorInformation, // obsolete...delete + SystemPerformanceInformation, + SystemTimeOfDayInformation, + SystemPathInformation, + SystemProcessInformation, + SystemCallCountInformation, + SystemDeviceInformation, + SystemProcessorPerformanceInformation, + SystemFlagsInformation, + SystemCallTimeInformation, + SystemModuleInformation, + SystemLocksInformation, + SystemStackTraceInformation, + SystemPagedPoolInformation, + SystemNonPagedPoolInformation, + SystemHandleInformation, + SystemObjectInformation, + SystemPageFileInformation, + SystemVdmInstemulInformation, + SystemVdmBopInformation, + SystemFileCacheInformation, + SystemPoolTagInformation, + SystemInterruptInformation, + SystemDpcBehaviorInformation, + SystemFullMemoryInformation, + SystemLoadGdiDriverInformation, + SystemUnloadGdiDriverInformation, + SystemTimeAdjustmentInformation, + SystemSummaryMemoryInformation, + SystemMirrorMemoryInformation, + SystemPerformanceTraceInformation, + SystemObsolete0, + SystemExceptionInformation, + SystemCrashDumpStateInformation, + SystemKernelDebuggerInformation, + SystemContextSwitchInformation, + SystemRegistryQuotaInformation, + SystemExtendServiceTableInformation, + SystemPrioritySeperation, + SystemVerifierAddDriverInformation, + SystemVerifierRemoveDriverInformation, + SystemProcessorIdleInformation, + SystemLegacyDriverInformation, + SystemCurrentTimeZoneInformation, + SystemLookasideInformation, + SystemTimeSlipNotification, + SystemSessionCreate, + SystemSessionDetach, + SystemSessionInformation, + SystemRangeStartInformation, + SystemVerifierInformation, + SystemVerifierThunkExtend, + SystemSessionProcessInformation, + SystemLoadGdiDriverInSystemSpace, + SystemNumaProcessorMap, + SystemPrefetcherInformation, + SystemExtendedProcessInformation, + SystemRecommendedSharedDataAlignment, + SystemComPlusPackage, + SystemNumaAvailableMemory, + SystemProcessorPowerInformation, + SystemEmulationBasicInformation, + SystemEmulationProcessorInformation, + SystemExtendedHandleInformation, + SystemLostDelayedWriteInformation +} SYSTEM_INFORMATION_CLASS; + +typedef enum _EVENT_INFORMATION_CLASS { + EventBasicInformation + } EVENT_INFORMATION_CLASS; + +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; // DEVL only + LARGE_INTEGER InterruptTime; // DEVL only + ULONG InterruptCount; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; + +typedef enum _EVENT_TYPE { + NotificationEvent, + SynchronizationEvent + } EVENT_TYPE; + +typedef struct _EVENT_BASIC_INFORMATION { + EVENT_TYPE EventType; + LONG EventState; +} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; + +#define RTL_MEG (1024UL * 1024UL) +#define RTLP_IMAGE_MAX_DOS_HEADER ( 256UL * RTL_MEG) + +typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { + BOOLEAN KernelDebuggerEnabled; + BOOLEAN KernelDebuggerNotPresent; +} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; + +typedef struct _STRING { + USHORT Length; + USHORT MaximumLength; +#ifdef MIDL_PASS + [size_is(MaximumLength), length_is(Length) ] +#endif // MIDL_PASS + PCHAR Buffer; +} STRING; +typedef STRING *PSTRING; + +typedef STRING ANSI_STRING; +typedef PSTRING PANSI_STRING; + +typedef STRING OEM_STRING; +typedef PSTRING POEM_STRING; +typedef CONST STRING* PCOEM_STRING; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; +#ifdef MIDL_PASS + [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer; +#else // MIDL_PASS + PWSTR Buffer; +#endif // MIDL_PASS +} UNICODE_STRING; +typedef UNICODE_STRING *PUNICODE_STRING; +typedef const UNICODE_STRING *PCUNICODE_STRING; +#define UNICODE_NULL ((WCHAR)0) // winnt + +typedef struct _STRING32 { + USHORT Length; + USHORT MaximumLength; + ULONG Buffer; +} STRING32; +typedef STRING32 *PSTRING32; + +typedef STRING32 UNICODE_STRING32; +typedef UNICODE_STRING32 *PUNICODE_STRING32; + +typedef STRING32 ANSI_STRING32; +typedef ANSI_STRING32 *PANSI_STRING32; + + +typedef struct _STRING64 { + USHORT Length; + USHORT MaximumLength; + ULONGLONG Buffer; +} STRING64; +typedef STRING64 *PSTRING64; + +typedef STRING64 UNICODE_STRING64; +typedef UNICODE_STRING64 *PUNICODE_STRING64; + +typedef STRING64 ANSI_STRING64; +typedef ANSI_STRING64 *PANSI_STRING64; + +#define GDI_HANDLE_BUFFER_SIZE32 34 +#define GDI_HANDLE_BUFFER_SIZE64 60 + +#if !defined(_TARGET_AMD64_) +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 +#else +#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 +#endif + +typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; +typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; +typedef ULONG GDI_HANDLE_BUFFER [GDI_HANDLE_BUFFER_SIZE ]; + + +typedef struct _PEB_LDR_DATA { + ULONG Length; + BOOLEAN Initialized; + HANDLE SsHandle; + LIST_ENTRY InLoadOrderModuleList; + LIST_ENTRY InMemoryOrderModuleList; + LIST_ENTRY InInitializationOrderModuleList; + PVOID EntryInProgress; +} PEB_LDR_DATA, *PPEB_LDR_DATA; + +typedef struct _PEB_FREE_BLOCK { + struct _PEB_FREE_BLOCK *Next; + ULONG Size; +} PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; + +typedef PVOID* PPVOID; + +typedef +VOID +(*PPS_POST_PROCESS_INIT_ROUTINE) ( + VOID + ); + +typedef struct _LDR_DATA_TABLE_ENTRY { + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union _foo { + LIST_ENTRY HashLinks; + struct _bar { + PVOID SectionPointer; + ULONG CheckSum; + }; + }; + union _foo2 { + struct _bar2 { + ULONG TimeDateStamp; + }; + struct _bar3 { + PVOID LoadedImports; + }; + }; + PVOID EntryPointActivationContext; +} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; + +#define TYPE3(arg) arg + +typedef struct _PEB { + BOOLEAN InheritedAddressSpace; // These four fields cannot change unless the + BOOLEAN ReadImageFileExecOptions; // + BOOLEAN BeingDebugged; // + BOOLEAN SpareBool; // + HANDLE Mutant; // INITIAL_PEB structure is also updated. + + PVOID ImageBaseAddress; + PPEB_LDR_DATA Ldr; + TYPE3(struct _RTL_USER_PROCESS_PARAMETERS*) ProcessParameters; + PVOID SubSystemData; + PVOID ProcessHeap; + TYPE3(struct _RTL_CRITICAL_SECTION*) FastPebLock; + PVOID FastPebLockRoutine; + PVOID FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PVOID KernelCallbackTable; + ULONG SystemReserved[1]; + + struct _foo { + ULONG ExecuteOptions : 2; + ULONG SpareBits : 30; + }; + + + PPEB_FREE_BLOCK FreeList; + ULONG TlsExpansionCounter; + PVOID TlsBitmap; + ULONG TlsBitmapBits[2]; // TLS_MINIMUM_AVAILABLE bits + PVOID ReadOnlySharedMemoryBase; + PVOID ReadOnlySharedMemoryHeap; + PPVOID ReadOnlyStaticServerData; + PVOID AnsiCodePageData; + PVOID OemCodePageData; + PVOID UnicodeCaseTableData; + + // + // Useful information for LdrpInitialize + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + + // + // Passed up from MmCreatePeb from Session Manager registry key + // + + LARGE_INTEGER CriticalSectionTimeout; + SIZE_T HeapSegmentReserve; + SIZE_T HeapSegmentCommit; + SIZE_T HeapDeCommitTotalFreeThreshold; + SIZE_T HeapDeCommitFreeBlockThreshold; + + // + // Where heap manager keeps track of all heaps created for a process + // Fields initialized by MmCreatePeb. ProcessHeaps is initialized + // to point to the first free byte after the PEB and MaximumNumberOfHeaps + // is computed from the page size used to hold the PEB, less the fixed + // size of this data structure. + // + + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PPVOID ProcessHeaps; + + // + // + PVOID GdiSharedHandleTable; + PVOID ProcessStarterHelper; + ULONG GdiDCAttributeList; + PVOID LoaderLock; + + // + // Following fields filled in by MmCreatePeb from system values and/or + // image header. + // + + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + ULONG_PTR ImageProcessAffinityMask; + GDI_HANDLE_BUFFER GdiHandleBuffer; + PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; + + PVOID TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; // TLS_EXPANSION_SLOTS bits + + // + // Id of the Hydra session in which this process is running + // + ULONG SessionId; + + // + // Filled in by LdrpInstallAppcompatBackend + // + ULARGE_INTEGER AppCompatFlags; + + // + // ntuser appcompat flags + // + ULARGE_INTEGER AppCompatFlagsUser; + + // + // Filled in by LdrpInstallAppcompatBackend + // + PVOID pShimData; + + // + // Filled in by LdrQueryImageFileExecutionOptions + // + PVOID AppCompatInfo; + + // + // Used by GetVersionExW as the szCSDVersion string + // + UNICODE_STRING CSDVersion; + + // + // Fusion stuff + // + PVOID ActivationContextData; + PVOID ProcessAssemblyStorageMap; + PVOID SystemDefaultActivationContextData; + PVOID SystemAssemblyStorageMap; + + // + // Enforced minimum initial commit stack + // + SIZE_T MinimumStackCommit; + +} PEB, *PPEB; + +#define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED (0x00000001) + +typedef struct _ACTIVATION_CONTEXT_STACK { + ULONG Flags; + ULONG NextCookieSequenceNumber; + PVOID ActiveFrame; + LIST_ENTRY FrameListCache; + +#if NT_SXS_PERF_COUNTERS_ENABLED + struct _ACTIVATION_CONTEXT_STACK_PERF_COUNTERS { + ULONGLONG Activations; + ULONGLONG ActivationCycles; + ULONGLONG Deactivations; + ULONGLONG DeactivationCycles; + } Counters; +#endif // NT_SXS_PERF_COUNTERS_ENABLED +} ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; + +typedef const ACTIVATION_CONTEXT_STACK *PCACTIVATION_CONTEXT_STACK; + +#define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001) + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT { + ULONG Flags; + PCSTR FrameName; +} TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; + +typedef const struct _TEB_ACTIVE_FRAME_CONTEXT *PCTEB_ACTIVE_FRAME_CONTEXT; + +typedef struct _TEB_ACTIVE_FRAME_CONTEXT_EX { + TEB_ACTIVE_FRAME_CONTEXT BasicContext; + PCSTR SourceLocation; // e.g. "Z:\foo\bar\baz.c" +} TEB_ACTIVE_FRAME_CONTEXT_EX, *PTEB_ACTIVE_FRAME_CONTEXT_EX; + +typedef const struct _TEB_ACTIVE_FRAME_CONTEXT_EX *PCTEB_ACTIVE_FRAME_CONTEXT_EX; + +#define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001) + +typedef struct _TEB_ACTIVE_FRAME { + ULONG Flags; + TYPE3(struct _TEB_ACTIVE_FRAME*) Previous; + PCTEB_ACTIVE_FRAME_CONTEXT Context; +} TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; + +typedef const struct _TEB_ACTIVE_FRAME *PCTEB_ACTIVE_FRAME; + +typedef struct _TEB_ACTIVE_FRAME_EX { + TEB_ACTIVE_FRAME BasicFrame; + PVOID ExtensionIdentifier; // use address of your DLL Main or something unique to your mapping in the address space +} TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX; + +typedef const struct _TEB_ACTIVE_FRAME_EX *PCTEB_ACTIVE_FRAME_EX; + +typedef struct _CLIENT_ID { + HANDLE UniqueProcess; + HANDLE UniqueThread; +} CLIENT_ID; +typedef CLIENT_ID *PCLIENT_ID; + +#define GDI_BATCH_BUFFER_SIZE 310 + +typedef struct _GDI_TEB_BATCH { + ULONG Offset; + ULONG_PTR HDC; + ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; +} GDI_TEB_BATCH,*PGDI_TEB_BATCH; + +typedef struct _Wx86ThreadState { + PULONG CallBx86Eip; + PVOID DeallocationCpu; + BOOLEAN UseKnownWx86Dll; + char OleStubInvoked; +} WX86THREAD, *PWX86THREAD; + +#define STATIC_UNICODE_BUFFER_LENGTH 261 +#define WIN32_CLIENT_INFO_LENGTH 62 + +typedef struct _PEB* PPEB; + +typedef struct _TEB { + NT_TIB NtTib; + PVOID EnvironmentPointer; + CLIENT_ID ClientId; + PVOID ActiveRpcHandle; + PVOID ThreadLocalStoragePointer; +#if defined(PEBTEB_BITS) + PVOID ProcessEnvironmentBlock; +#else + PPEB ProcessEnvironmentBlock; +#endif + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PVOID CsrClientThread; + PVOID Win32ThreadInfo; // PtiCurrent + ULONG User32Reserved[26]; // user32.dll items + ULONG UserReserved[5]; // Winsrv SwitchStack + PVOID WOW32Reserved; // used by WOW + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; // offset known by outsiders! + PVOID SystemReserved1[54]; // Used by FP emulator + NTSTATUS ExceptionCode; // for RaiseUserException + ACTIVATION_CONTEXT_STACK ActivationContextStack; // Fusion activation stack + // sizeof(PVOID) is a way to express processor-dependence, more generally than #ifdef _WIN64 + UCHAR SpareBytes1[48 - sizeof(PVOID) - sizeof(ACTIVATION_CONTEXT_STACK)]; + GDI_TEB_BATCH GdiTebBatch; // Gdi batching + CLIENT_ID RealClientId; + HANDLE GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PVOID GdiThreadLocalInfo; + ULONG_PTR Win32ClientInfo[WIN32_CLIENT_INFO_LENGTH]; // User32 Client Info + PVOID glDispatchTable[233]; // OpenGL + ULONG_PTR glReserved1[29]; // OpenGL + PVOID glReserved2; // OpenGL + PVOID glSectionInfo; // OpenGL + PVOID glSection; // OpenGL + PVOID glTable; // OpenGL + PVOID glCurrentRC; // OpenGL + PVOID glContext; // OpenGL + ULONG LastStatusValue; + UNICODE_STRING StaticUnicodeString; + WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH]; + PVOID DeallocationStack; + PVOID TlsSlots[TLS_MINIMUM_AVAILABLE]; + LIST_ENTRY TlsLinks; + PVOID Vdm; + PVOID ReservedForNtRpc; + PVOID DbgSsReserved[2]; + ULONG HardErrorsAreDisabled; + PVOID Instrumentation[16]; + PVOID WinSockData; // WinSock + ULONG GdiBatchCount; + BOOLEAN InDbgPrint; + BOOLEAN FreeStackOnTermination; + BOOLEAN HasFiberData; + BOOLEAN IdealProcessor; + ULONG Spare3; + PVOID ReservedForPerf; + PVOID ReservedForOle; + ULONG WaitingOnLoaderLock; + WX86THREAD Wx86Thread; + PPVOID TlsExpansionSlots; + LCID ImpersonationLocale; // Current locale of impersonated user + ULONG IsImpersonating; // Thread impersonation status + PVOID NlsCache; // NLS thread cache + PVOID pShimData; // Per thread data used in the shim + ULONG HeapVirtualAffinity; + HANDLE CurrentTransactionHandle;// reserved for TxF transaction context + PTEB_ACTIVE_FRAME ActiveFrame; +} TEB; +typedef TEB *PTEB; + +typedef struct _CURDIR { + UNICODE_STRING DosPath; + HANDLE Handle; +} CURDIR, *PCURDIR; + +#define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 +#define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 + +typedef struct _RTL_DRIVE_LETTER_CURDIR { + USHORT Flags; + USHORT Length; + ULONG TimeStamp; + STRING DosPath; +} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; + + +#define RTL_MAX_DRIVE_LETTERS 32 +#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 + +typedef struct _RTL_USER_PROCESS_PARAMETERS { + ULONG MaximumLength; + ULONG Length; + + ULONG Flags; + ULONG DebugFlags; + + HANDLE ConsoleHandle; + ULONG ConsoleFlags; + HANDLE StandardInput; + HANDLE StandardOutput; + HANDLE StandardError; + + CURDIR CurrentDirectory; // ProcessParameters + UNICODE_STRING DllPath; // ProcessParameters + UNICODE_STRING ImagePathName; // ProcessParameters + UNICODE_STRING CommandLine; // ProcessParameters + PVOID Environment; // NtAllocateVirtualMemory + + ULONG StartingX; + ULONG StartingY; + ULONG CountX; + ULONG CountY; + ULONG CountCharsX; + ULONG CountCharsY; + ULONG FillAttribute; + + ULONG WindowFlags; + ULONG ShowWindowFlags; + UNICODE_STRING WindowTitle; // ProcessParameters + UNICODE_STRING DesktopInfo; // ProcessParameters + UNICODE_STRING ShellInfo; // ProcessParameters + UNICODE_STRING RuntimeData; // ProcessParameters + RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ RTL_MAX_DRIVE_LETTERS ]; +} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; + + +typedef enum _PROCESSINFOCLASS { + ProcessBasicInformation, + ProcessQuotaLimits, + ProcessIoCounters, + ProcessVmCounters, + ProcessTimes, + ProcessBasePriority, + ProcessRaisePriority, + ProcessDebugPort, + ProcessExceptionPort, + ProcessAccessToken, + ProcessLdtInformation, + ProcessLdtSize, + ProcessDefaultHardErrorMode, + ProcessIoPortHandlers, // Note: this is kernel mode only + ProcessPooledUsageAndLimits, + ProcessWorkingSetWatch, + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, + ProcessPriorityClass, + ProcessWx86Information, + ProcessHandleCount, + ProcessAffinityMask, + ProcessPriorityBoost, + ProcessDeviceMap, + ProcessSessionInformation, + ProcessForegroundInformation, + ProcessWow64Information, + ProcessImageFileName, + ProcessLUIDDeviceMapsEnabled, + ProcessBreakOnTermination, + ProcessDebugObjectHandle, + ProcessDebugFlags, + ProcessHandleTracing, + MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum + } PROCESSINFOCLASS; + + +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; + +#undef TYPE3 + +#endif // !defined(FEATURE_PAL) + +#if !defined(_TARGET_X86_) + +typedef enum _FUNCTION_TABLE_TYPE { + RF_SORTED, + RF_UNSORTED, + RF_CALLBACK +} FUNCTION_TABLE_TYPE; + +typedef struct _DYNAMIC_FUNCTION_TABLE { + LIST_ENTRY Links; + PT_RUNTIME_FUNCTION FunctionTable; + LARGE_INTEGER TimeStamp; + +#ifdef _TARGET_ARM_ + ULONG MinimumAddress; + ULONG MaximumAddress; + ULONG BaseAddress; +#else + ULONG64 MinimumAddress; + ULONG64 MaximumAddress; + ULONG64 BaseAddress; +#endif + + PGET_RUNTIME_FUNCTION_CALLBACK Callback; + PVOID Context; + PWSTR OutOfProcessCallbackDll; + FUNCTION_TABLE_TYPE Type; + ULONG EntryCount; +} DYNAMIC_FUNCTION_TABLE, *PDYNAMIC_FUNCTION_TABLE; + +#endif // !_TARGET_X86_ + +// +// AMD64 +// +#ifdef _TARGET_AMD64_ + +#define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress +#define RUNTIME_FUNCTION__SetBeginAddress(prf,address) ((prf)->BeginAddress = (address)) + +#define RUNTIME_FUNCTION__EndAddress(prf, ImageBase) (prf)->EndAddress + +#define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) +#define OFFSETOF__RUNTIME_FUNCTION__UnwindInfoAddress offsetof(T_RUNTIME_FUNCTION, UnwindData) + +#include "win64unwind.h" + +typedef +PEXCEPTION_ROUTINE +(RtlVirtualUnwindFn) ( + IN ULONG HandlerType, + IN ULONG64 ImageBase, + IN ULONG64 ControlPc, + IN PT_RUNTIME_FUNCTION FunctionEntry, + IN OUT PCONTEXT ContextRecord, + OUT PVOID *HandlerData, + OUT PULONG64 EstablisherFrame, + IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL + ); + +#ifndef FEATURE_PAL +extern RtlVirtualUnwindFn* RtlVirtualUnwind_Unsafe; +#else // !FEATURE_PAL +PEXCEPTION_ROUTINE +RtlVirtualUnwind_Unsafe( + IN ULONG HandlerType, + IN ULONG64 ImageBase, + IN ULONG64 ControlPc, + IN PT_RUNTIME_FUNCTION FunctionEntry, + IN OUT PCONTEXT ContextRecord, + OUT PVOID *HandlerData, + OUT PULONG64 EstablisherFrame, + IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL + ); +#endif // !FEATURE_PAL + +#endif // _TARGET_AMD64_ + +// +// X86 +// + +#ifdef _TARGET_X86_ +#ifndef FEATURE_PAL +// +// x86 ABI does not define RUNTIME_FUNCTION. Define our own to allow unification between x86 and other platforms. +// +typedef struct _RUNTIME_FUNCTION { + DWORD BeginAddress; + DWORD UnwindData; +} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; + +typedef struct _DISPATCHER_CONTEXT { + _EXCEPTION_REGISTRATION_RECORD* RegistrationPointer; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#endif // !FEATURE_PAL + +#define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress +#define RUNTIME_FUNCTION__SetBeginAddress(prf,addr) ((prf)->BeginAddress = (addr)) + +#ifdef WIN64EXCEPTIONS +#include "win64unwind.h" + +FORCEINLINE +DWORD +RtlpGetFunctionEndAddress ( + __in PT_RUNTIME_FUNCTION FunctionEntry, + __in TADDR ImageBase + ) +{ + PTR_UNWIND_INFO pUnwindInfo = (PTR_UNWIND_INFO)(ImageBase + FunctionEntry->UnwindData); + + return FunctionEntry->BeginAddress + pUnwindInfo->FunctionLength; +} + +#define RUNTIME_FUNCTION__EndAddress(prf, ImageBase) RtlpGetFunctionEndAddress(prf, ImageBase) + +#define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf, addr) do { (prf)->UnwindData = (addr); } while(0) + +EXTERN_C +NTSYSAPI +PEXCEPTION_ROUTINE +NTAPI +RtlVirtualUnwind ( + __in DWORD HandlerType, + __in DWORD ImageBase, + __in DWORD ControlPc, + __in PRUNTIME_FUNCTION FunctionEntry, + __inout PT_CONTEXT ContextRecord, + __out PVOID *HandlerData, + __out PDWORD EstablisherFrame, + __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers + ); +#endif // WIN64EXCEPTIONS + +#endif // _TARGET_X86_ + +#ifdef _TARGET_ARM_ +#include "daccess.h" + +// +// Define unwind information flags. +// + +#define UNW_FLAG_NHANDLER 0x0 /* any handler */ +#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ +#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ + +// This function returns the length of a function using the new unwind info on arm. +// Taken from minkernel\ntos\rtl\arm\ntrtlarm.h. +FORCEINLINE +ULONG +RtlpGetFunctionEndAddress ( + __in PT_RUNTIME_FUNCTION FunctionEntry, + __in TADDR ImageBase + ) +{ + ULONG FunctionLength; + + FunctionLength = FunctionEntry->UnwindData; + if ((FunctionLength & 3) != 0) { + FunctionLength = (FunctionLength >> 2) & 0x7ff; + } else { + FunctionLength = *(PTR_ULONG)(ImageBase + FunctionLength) & 0x3ffff; + } + + return FunctionEntry->BeginAddress + 2 * FunctionLength; +} + +#define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ThumbCodeToDataPointer((FunctionEntry)->BeginAddress) +#define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = DataPointerToThumbCode(address)) + +#define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) ThumbCodeToDataPointer(RtlpGetFunctionEndAddress(FunctionEntry, ImageBase)) + +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) + +typedef struct _UNWIND_INFO { + // dummy +} UNWIND_INFO, *PUNWIND_INFO; + +#if defined(FEATURE_PAL) || defined(_X86_) +EXTERN_C +NTSYSAPI +VOID +NTAPI +RtlUnwindEx ( + __in_opt PVOID TargetFrame, + __in_opt PVOID TargetIp, + __in_opt PEXCEPTION_RECORD ExceptionRecord, + __in PVOID ReturnValue, + __in PT_CONTEXT ContextRecord, + __in_opt PUNWIND_HISTORY_TABLE HistoryTable + ); + +EXTERN_C +NTSYSAPI +PEXCEPTION_ROUTINE +NTAPI +RtlVirtualUnwind ( + __in DWORD HandlerType, + __in DWORD ImageBase, + __in DWORD ControlPc, + __in PRUNTIME_FUNCTION FunctionEntry, + __inout PT_CONTEXT ContextRecord, + __out PVOID *HandlerData, + __out PDWORD EstablisherFrame, + __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers + ); +#endif // FEATURE_PAL || _X86_ + +#define UNW_FLAG_NHANDLER 0x0 + +#endif // _TARGET_ARM_ + +#ifdef _TARGET_ARM64_ +#include "daccess.h" + +#define UNW_FLAG_NHANDLER 0x0 /* any handler */ +#define UNW_FLAG_EHANDLER 0x1 /* filter handler */ +#define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ + +// This function returns the RVA of the end of the function (exclusive, so one byte after the actual end) +// using the unwind info on ARM64. (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) +FORCEINLINE +ULONG64 +RtlpGetFunctionEndAddress ( + __in PT_RUNTIME_FUNCTION FunctionEntry, + __in ULONG64 ImageBase + ) +{ + ULONG64 FunctionLength; + + FunctionLength = FunctionEntry->UnwindData; + if ((FunctionLength & 3) != 0) { + FunctionLength = (FunctionLength >> 2) & 0x7ff; + } else { + FunctionLength = *(PTR_ULONG64)(ImageBase + FunctionLength) & 0x3ffff; + } + + return FunctionEntry->BeginAddress + 4 * FunctionLength; +} + +#define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ((FunctionEntry)->BeginAddress) +#define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = (address)) + +#define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) (RtlpGetFunctionEndAddress(FunctionEntry, (ULONG64)(ImageBase))) + +#define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) + +typedef struct _UNWIND_INFO { + // dummy +} UNWIND_INFO, *PUNWIND_INFO; + +EXTERN_C +NTSYSAPI +PEXCEPTION_ROUTINE +NTAPI +RtlVirtualUnwind( + IN ULONG HandlerType, + IN ULONG64 ImageBase, + IN ULONG64 ControlPc, + IN PRUNTIME_FUNCTION FunctionEntry, + IN OUT PCONTEXT ContextRecord, + OUT PVOID *HandlerData, + OUT PULONG64 EstablisherFrame, + IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL + ); + +#ifndef IMAGE_FILE_MACHINE_ARM64 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian +#endif + +#ifndef IMAGE_REL_ARM64_BRANCH26 +#define IMAGE_REL_ARM64_BRANCH26 0x0003 // 26 bit offset << 2 & sign ext. for B & BL +#endif + +#ifndef IMAGE_REL_ARM64_PAGEBASE_REL21 +#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004 // ADRP 21 bit PC-relative page address +#endif + +#ifndef IMAGE_REL_ARM64_PAGEOFFSET_12A +#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006 // ADD 12 bit page offset +#endif + +#endif + +#endif // CLRNT_H_ diff --git a/lib/coreclr/src/inc/clrprivappxhosting.idl b/lib/coreclr/src/inc/clrprivappxhosting.idl new file mode 100644 index 0000000000..04a4cf9407 --- /dev/null +++ b/lib/coreclr/src/inc/clrprivappxhosting.idl @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +import "unknwn.idl"; + +// Forward declarations +interface ICLRPrivAppXDomain; +interface ICLRPrivAppXRuntime; + +/************************************************************************************** + ** ICLRPrivAppXRuntime + **************************************************************************************/ +[ + uuid(6D2DF5A4-FA3A-4481-8BA0-0422FD21720F), + version(1.0), + local +] +interface ICLRPrivAppXRuntime : IUnknown +{ + /********************************************************************************** + ** Use to create and initialize the AppX domain. Should only be called once; all + ** subsequent calls will fail. Thread safe. + ** + ** wzFriendlyName - the domain friendly name. + **********************************************************************************/ + HRESULT InitializeAppXDomain( + [in] LPCWSTR wzFriendlyName); + + /********************************************************************************** + ** Use to retrieve the AppX domain. InitializeAppXDomain must have been + ** successfully called previously. May be called multiple times. Thread safe. + ** + ** riidDomain - the IID of the interface to be returned in ppvDomain. + ** ppIAppXDomain - receives the ICLRPrivAppXDomain interface. + **********************************************************************************/ + HRESULT GetAppXDomain( + [in] REFIID riidDomain, + [out] LPVOID * ppvDomain); +} + +/************************************************************************************** + ** ICLRPrivAppXDomain + **************************************************************************************/ +[ + uuid(6633398E-823D-4361-B30E-824043BD4686), + version(1.0), + local +] +interface ICLRPrivAppXDomain : IUnknown +{ + /********************************************************************************** + ** Use to create a delegate to a static method. + ** + ** wzAssemblyName - the name of the assembly that contains the target type. + ** wzTypeName - the name of the type that contains the target method. + ** wzMethodName - the static method for which to create a delegate. + ** ppvDelegate - receives the native-callable function pointer corresponding to + ** the specified static method. + **********************************************************************************/ + HRESULT CreateDelegate( + [in] LPCWSTR wzAssemblyName, + [in] LPCWSTR wzTypeName, + [in] LPCWSTR wzMethodName, + [out] LPVOID * ppvDelegate); +}; diff --git a/lib/coreclr/src/inc/clrprivbinderutil.h b/lib/coreclr/src/inc/clrprivbinderutil.h new file mode 100644 index 0000000000..023f72c6df --- /dev/null +++ b/lib/coreclr/src/inc/clrprivbinderutil.h @@ -0,0 +1,717 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// Contains helper types for assembly binding host infrastructure. + +#ifndef __CLRPRIVBINDERUTIL_H__ +#define __CLRPRIVBINDERUTIL_H__ + +#include "holder.h" +#include "internalunknownimpl.h" +#include "clrprivbinding.h" +#include "slist.h" +#ifdef FEATURE_COMINTEROP +#include "windowsstring.h" +#endif // FEATURE_COMINTEROP +#include "strongnameholders.h" + +//===================================================================================================================== +#define STANDARD_BIND_CONTRACT \ + CONTRACTL { \ + NOTHROW; \ + GC_TRIGGERS; \ + MODE_PREEMPTIVE; \ + } CONTRACTL_END + +//===================================================================================================================== +// Forward declarations +interface ICLRPrivAssembly; +typedef DPTR(ICLRPrivAssembly) PTR_ICLRPrivAssembly; +typedef DPTR(ICLRPrivBinder) PTR_ICLRPrivBinder; +class PEAssembly; +class AssemblySpec; + +//===================================================================================================================== +#define VALIDATE_CONDITION(condition, fail_op) \ + do { \ + _ASSERTE((condition)); \ + if (!(condition)) \ + fail_op; \ + } while (false) + +#define VALIDATE_PTR_RET(val) VALIDATE_CONDITION(val != nullptr, return E_POINTER) +#define VALIDATE_PTR_THROW(val) VALIDATE_CONDITION(val != nullptr, ThrowHR(E_POINTER)) +#define VALIDATE_ARG_RET(condition) VALIDATE_CONDITION(condition, return E_INVALIDARG) +#define VALIDATE_ARG_THROW(condition) VALIDATE_CONDITION(condition, ThrowHR(E_INVALIDARG)) + +//===================================================================================================================== +namespace CLRPrivBinderUtil +{ + //================================================================================================================= + enum BindFlags + { + BF_BindIL = 1, + BF_BindNI = 2, + BF_Default = BF_BindIL | BF_BindNI, + }; + + //================================================================================================================= + template + inline ItfT * ToInterface( + ObjT * && pObj) + { + STATIC_CONTRACT_THROWS; + + ItfT * pItf = nullptr; + IfFailThrow(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf)); + return pItf; + } + + //================================================================================================================= + template + inline ItfT * ToInterface_NoThrow( + ObjT * && pObj) + { + LIMITED_METHOD_CONTRACT; + + ItfT * pItf = nullptr; + if (FAILED(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf))) + { + return nullptr; + } + return pItf; + } + + //===================================================================================================================== + + //================================================================================================================= + // Used to create an identity-only ICLRPrivAssembly from an ICLRPrivBinder. This is currently used when + // creating dynamic assemblies as these use the parent assembly's ICLRPrivBinder object to provide binding + // functionaltiy. + + class CLRPrivBinderAsAssemblyWrapper : + public IUnknownCommon + { + public: + //----------------------------------------------------------------------------------------------------------------- + CLRPrivBinderAsAssemblyWrapper( + ICLRPrivBinder *pWrapped) + : _pWrapped(clr::SafeAddRef(pWrapped)) + { + STANDARD_VM_CONTRACT; + VALIDATE_ARG_THROW(pWrapped); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(BindAssemblyByName)( + IAssemblyName * pAssemblyName, + ICLRPrivAssembly ** ppAssembly) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->BindAssemblyByName(pAssemblyName, ppAssembly); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(GetBinderID)( + UINT_PTR *pBinderId) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->GetBinderID(pBinderId); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(GetLoaderAllocator)( + LPVOID * pLoaderAllocator) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->GetLoaderAllocator(pLoaderAllocator); + } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(IsShareable)( + BOOL * pbIsShareable) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pbIsShareable); + *pbIsShareable = FALSE; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(GetAvailableImageTypes)( + LPDWORD pdwImageTypes) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pdwImageTypes); + *pdwImageTypes = 0; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(GetImageResource)( + DWORD dwImageType, + DWORD* pdwImageType, + ICLRPrivResource ** ppIResource) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pdwImageType); + *pdwImageType = 0; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + private: + ReleaseHolder _pWrapped; + }; + + //================================================================================================================= + // Provides a struct that can be accessed at the QWORD, DWORD, or WORD level, and is structured + + struct AssemblyVersion + { +#if BIGENDIAN + union + { + UINT64 qwMajorMinorBuildRevision; + struct + { + union + { + DWORD dwMajorMinor; + struct + { + WORD wMajor; + WORD wMinor; + }; + }; + union + { + DWORD dwBuildRevision; + struct + { + WORD wBuild; + WORD wRevision; + }; + }; + }; + }; +#else + union + { + UINT64 qwMajorMinorBuildRevision; + struct + { + union + { + DWORD dwBuildRevision; + struct + { + WORD wRevision; + WORD wBuild; + }; + }; + union + { + DWORD dwMajorMinor; + struct + { + WORD wMinor; + WORD wMajor; + }; + }; + }; + }; +#endif + + // Default value is 0.0.0.0 + AssemblyVersion() + : qwMajorMinorBuildRevision(static_cast(0)) + { LIMITED_METHOD_CONTRACT; } + + // Copy constructor + AssemblyVersion(AssemblyVersion const & other) + : qwMajorMinorBuildRevision(other.qwMajorMinorBuildRevision) + { LIMITED_METHOD_CONTRACT; } + + // Initialize version using an IAssemblyName object. + HRESULT Initialize(IAssemblyName * pName); + + // Initialize version using an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); + + // Relative ordering of versions. + static inline int Compare( + AssemblyVersion const & left, + AssemblyVersion const & right) + { + LIMITED_METHOD_CONTRACT; + + if (left.qwMajorMinorBuildRevision < right.qwMajorMinorBuildRevision) + return -1; + else if (left.qwMajorMinorBuildRevision == right.qwMajorMinorBuildRevision) + return 0; + else + return 1; + } + }; // struct AssemblyVersion + + inline bool operator ==(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision == rhs.qwMajorMinorBuildRevision; } + + inline bool operator !=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision != rhs.qwMajorMinorBuildRevision; } + + inline bool operator <(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision < rhs.qwMajorMinorBuildRevision; } + + inline bool operator <=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision <= rhs.qwMajorMinorBuildRevision; } + + inline bool operator >(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision > rhs.qwMajorMinorBuildRevision; } + + inline bool operator >=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision >= rhs.qwMajorMinorBuildRevision; } + + //================================================================================================================= + // Encapsulates PublicKey value, can be initialized using a variety of data sources. + + struct PublicKey + { + // Defaults to empty value. + PublicKey() + : m_key(nullptr) + , m_key_owned(false) + , m_size((DWORD)-1) + { LIMITED_METHOD_CONTRACT; } + + // Construct directly from existing public key data. + PublicKey(PBYTE pbKey, DWORD cbKey) + : m_key(pbKey) + , m_key_owned(false) + , m_size(cbKey) + { LIMITED_METHOD_CONTRACT; } + + ~PublicKey() + { WRAPPER_NO_CONTRACT; Uninitialize(); } + + // Frees any public key data and resets to default value. + void Uninitialize() + { + LIMITED_METHOD_CONTRACT; + + if (m_key_owned) + { + delete [] m_key; + m_key_owned = false; + } + m_key = nullptr; + m_size = 0; + } + + // Initialize PK data form an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); + + // Returns PK data pointer. + inline BYTE const * GetKey() const + { LIMITED_METHOD_CONTRACT; return m_key; } + + // Returns size in bytes of the PK data. + inline DWORD GetSize() const + { LIMITED_METHOD_CONTRACT; return m_size; } + + private: + PBYTE m_key; + bool m_key_owned; + DWORD m_size; + }; + + //================================================================================================================= + // Encapsulates PublicKeyToken value, can be initialized using a variety of data sources. + // + // Constraints: assumes that non-empty PKT data will always be 8 bytes long. + // + + struct PublicKeyToken + { + PublicKeyToken() + : m_cbKeyToken(0) + { LIMITED_METHOD_CONTRACT; ZeroMemory(&m_rbKeyToken, sizeof(m_rbKeyToken)); } + + PublicKeyToken(PublicKeyToken const & other) + : m_cbKeyToken(other.m_cbKeyToken) + { LIMITED_METHOD_CONTRACT; CopyMemory(m_rbKeyToken, other.m_rbKeyToken, sizeof(m_rbKeyToken)); } + + // Initialize directly from PKT data. + HRESULT Initialize(BYTE * pbKeyToken, DWORD cbKeyToken); + + // Converts PK data to PKT data. + HRESULT Initialize(PublicKey const & pk); + + // Initialize using the PKT value contained by pName; returns S_FALSE if there is no associated PKT. + HRESULT Initialize(IAssemblyName * pName); + + // Initialize using the PK data contained by pInfo; returns S_FALSE if there is no associated PK. + HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); + + // PKT data. + BYTE const * GetToken() const + { LIMITED_METHOD_CONTRACT; return m_rbKeyToken; } + + // Size in bytes of the PKT (should always be 0 or 8). + DWORD GetSize() const + { LIMITED_METHOD_CONTRACT; return m_cbKeyToken; } + + private: + static const DWORD PUBLIC_KEY_TOKEN_LEN1 = 8; + BYTE m_rbKeyToken[PUBLIC_KEY_TOKEN_LEN1]; + DWORD m_cbKeyToken; + }; + + bool operator==(PublicKeyToken const & lhs, PublicKeyToken const & rhs); + + inline bool operator!=(PublicKeyToken const & lhs, PublicKeyToken const & rhs) + { WRAPPER_NO_CONTRACT; return !(lhs == rhs); } + + //================================================================================================================= + // Encapsulates data required for packaged assembly identity: simple name, version, and public key token. + // + // Constraints: assumes that the assembly simple name is no longer than _MAX_PATH + // + + struct AssemblyIdentity + { + AssemblyIdentity() + { LIMITED_METHOD_CONTRACT; Name[0] = W('\0'); } + + AssemblyIdentity(AssemblyIdentity const & other) + : Version(other.Version) + , KeyToken(other.KeyToken) + { LIMITED_METHOD_CONTRACT; CopyMemory(Name, other.Name, sizeof(Name)); } + + // Initialize from assembly simple name; default version and empty PKT values are used. + HRESULT Initialize(LPCWSTR wzName); + + // Initialize from an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); + + // Initialize from an IAssemblyName object. + HRESULT Initialize(IAssemblyName * pAssemblyName); + + // Initialize from an AssemblySpec object. + HRESULT Initialize(AssemblySpec * pSpec); + + // Assembly simple name + WCHAR Name[_MAX_PATH]; + + // Assembly version; defaults to 0.0.0.0. + CLRPrivBinderUtil::AssemblyVersion Version; + + // Assembly public key token; defaults to none. + CLRPrivBinderUtil::PublicKeyToken KeyToken; + }; + + //================================================================================================= + template + struct CLRPrivResourceBase : + public IUnknownCommon + { + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetResourceType)( + IID *pIID) + { + LIMITED_METHOD_CONTRACT; + if (pIID == nullptr) + return E_INVALIDARG; + *pIID = __uuidof(ItfT); + return S_OK; + } + }; + + //================================================================================================================= + class CLRPrivResourcePathImpl : + public IUnknownCommon< ItfBase< CLRPrivResourceBase< ICLRPrivResourcePath > >, + ICLRPrivResourcePath > + { + public: + //--------------------------------------------------------------------------------------------- + CLRPrivResourcePathImpl(LPCWSTR wzPath); + + //--------------------------------------------------------------------------------------------- + LPCWSTR GetPath() + { return m_wzPath; } + + // + // ICLRPrivResourcePath methods + // + + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetPath)( + DWORD cchBuffer, + LPDWORD pcchBuffer, + __inout_ecount_part(cchBuffer, *pcchBuffer) LPWSTR wzBuffer); + + private: + //--------------------------------------------------------------------------------------------- + NewArrayHolder m_wzPath; + }; + + //================================================================================================================= + class CLRPrivResourceStreamImpl : + public IUnknownCommon< ItfBase< CLRPrivResourceBase >, + ICLRPrivResourceStream> + { + public: + //--------------------------------------------------------------------------------------------- + CLRPrivResourceStreamImpl(IStream * pStream); + + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetStream)( + REFIID riid, + LPVOID * ppvStream); + + private: + //--------------------------------------------------------------------------------------------- + ReleaseHolder m_pStream; + }; + + //================================================================================================================= + // Helper to prioritize binder errors. This class will ensure that all other errors have priority over + // CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT. This class should be used just like an HRESULT variable. + class BinderHRESULT + { + public: + BinderHRESULT() + : m_hr(S_OK) + {} + + BinderHRESULT(HRESULT hr) + : m_hr(hr) + {} + + operator HRESULT() const + { return m_hr; } + + BinderHRESULT & operator=(HRESULT hr) + { + // Always record change in success/failure status. + if (FAILED(hr) != FAILED(m_hr)) + m_hr = hr; + + if (FAILED(hr)) + { + if (SUCCEEDED(m_hr)) + m_hr = hr; + else if (m_hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT) + m_hr = hr; + } + else + { + m_hr = hr; + } + return *this; + } + + private: + HRESULT m_hr; + }; // class BinderHRESULT + + //================================================================================================================= + // Types for WStringList (used in WinRT binders) + + typedef SListElem< PTR_WSTR > WStringListElem; + typedef DPTR(WStringListElem) PTR_WStringListElem; + typedef SList< WStringListElem, false /* = fHead default value */, PTR_WStringListElem > WStringList; + typedef DPTR(WStringList) PTR_WStringList; + + // Destroys list of strings (code:WStringList). + void WStringList_Delete(WStringList * pList); + +#ifndef DACCESS_COMPILE + //===================================================================================================================== + // Holder of allocated code:WStringList (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::GetFileNameListForNamespace). + class WStringListHolder + { + public: + WStringListHolder(WStringList * pList = nullptr) + { + LIMITED_METHOD_CONTRACT; + m_pList = pList; + } + ~WStringListHolder() + { + LIMITED_METHOD_CONTRACT; + Destroy(); + } + + void InsertTail(LPCWSTR wszValue) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + NewArrayHolder wszElemValue = DuplicateStringThrowing(wszValue); + NewHolder pElem = new WStringListElem(wszElemValue); + + if (m_pList == nullptr) + { + m_pList = new WStringList(); + } + + m_pList->InsertTail(pElem.Extract()); + // The string is now owned by the list + wszElemValue.SuppressRelease(); + } + + WStringList * GetValue() + { + LIMITED_METHOD_CONTRACT; + return m_pList; + } + + WStringList * Extract() + { + LIMITED_METHOD_CONTRACT; + + WStringList * pList = m_pList; + m_pList = nullptr; + return pList; + } + + private: + void Destroy() + { + LIMITED_METHOD_CONTRACT; + + if (m_pList != nullptr) + { + WStringList_Delete(m_pList); + m_pList = nullptr; + } + } + + private: + WStringList * m_pList; + }; // class WStringListHolder +#endif //!DACCESS_COMPILE + +#ifdef FEATURE_COMINTEROP + //===================================================================================================================== + // Holder of allocated array of HSTRINGs (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::m_rgAltPaths). + class HSTRINGArrayHolder + { + public: + HSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + + m_cValues = 0; + m_rgValues = nullptr; + } +#ifndef DACCESS_COMPILE + ~HSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + Destroy(); + } + + // Destroys current array and allocates a new one with cValues elements. + void Allocate(DWORD cValues) + { + STANDARD_VM_CONTRACT; + + Destroy(); + _ASSERTE(m_cValues == 0); + + if (cValues > 0) + { + m_rgValues = new HSTRING[cValues]; + m_cValues = cValues; + + // Initialize the array values + for (DWORD i = 0; i < cValues; i++) + { + m_rgValues[i] = nullptr; + } + } + } +#endif //!DACCESS_COMPILE + + HSTRING GetAt(DWORD index) const + { + LIMITED_METHOD_CONTRACT; + return m_rgValues[index]; + } + + HSTRING * GetRawArray() + { + LIMITED_METHOD_CONTRACT; + return m_rgValues; + } + + DWORD GetCount() + { + LIMITED_METHOD_CONTRACT; + return m_cValues; + } + + private: +#ifndef DACCESS_COMPILE + void Destroy() + { + LIMITED_METHOD_CONTRACT; + + for (DWORD i = 0; i < m_cValues; i++) + { + if (m_rgValues[i] != nullptr) + { + WindowsDeleteString(m_rgValues[i]); + } + } + m_cValues = 0; + + if (m_rgValues != nullptr) + { + delete [] m_rgValues; + m_rgValues = nullptr; + } + } +#endif //!DACCESS_COMPILE + + private: + DWORD m_cValues; + HSTRING * m_rgValues; + }; // class HSTRINGArrayHolder + +#endif // FEATURE_COMINTEROP + + //////////////////////////////////////////////////////////////////////////////////////////////////// + ///// ----------------------------- Questionable stuff ------------------------------------------- + //////////////////////////////////////////////////////////////////////////////////////////////////// + + /** probably should be exposed on an instance (of something) method rather that magically calling GetAppDomain() **/ + ICLRPrivAssembly* RaiseAssemblyResolveEvent(IAssemblyName *pAssemblyName, ICLRPrivAssembly* pRequestingAssembly); + + /** Ultimately, only the binder can do ref-def matching, and it should be opaque to CLR. + This is not trivial to do, however, since we cannot do data conversion as the function is nofault **/ + BOOL CompareHostBinderSpecs(AssemblySpec* a1, AssemblySpec* a2); + + /** PLACEHOLDER - the same issue as CompareHostBinderSpecs applies to hashing assemblyspecs **/ +} // namespace CLRPrivBinderUtil + +#endif // __CLRPRIVBINDERUTIL_H__ diff --git a/lib/coreclr/src/inc/clrprivbinding.idl b/lib/coreclr/src/inc/clrprivbinding.idl new file mode 100644 index 0000000000..c30ed62d5e --- /dev/null +++ b/lib/coreclr/src/inc/clrprivbinding.idl @@ -0,0 +1,295 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +import "unknwn.idl"; +import "objidl.idl"; +import "fusion.idl"; + +// Forward declarations +interface ICLRPrivBinder; +interface ICLRPrivAssembly; + +interface ICLRPrivResource; +interface ICLRPrivResourcePath; +interface ICLRPrivResourceStream; +interface ICLRPrivResourceHMODULE; + +interface ICLRPrivAssemblyInfo; + +typedef LPCSTR LPCUTF8; + +/************************************************************************************** + ** This IDL file defines the assembly binding host interfaces. Some things to keep + ** in mind: + ** - Equality is determined by pointer equality: two interface instances + ** should be considered equal if and only if their pointer values are equal. + ** - All operations are idempotent: when a method is called more than once with + ** the same input values, it is required to return identical results. The only + ** possible exceptions center around transient errors such as E_OUTOFMEMORY. + **************************************************************************************/ + +/************************************************************************************** + ** ICLRPrivBinder - Use to bind to an assembly by name or by metadata reference. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8542), + version(1.0), + local +] +interface ICLRPrivBinder : IUnknown +{ + /********************************************************************************** + ** BindAssemblyByName -- Binds an assembly by name. + ** NOTE: This method is required to be idempotent. See general comment above. + ** + ** pAssemblyName - name of the assembly for which a bind is being requested. + ** ppAssembly - upon success, receives the bound assembly. + **********************************************************************************/ + HRESULT BindAssemblyByName( + [in] IAssemblyName * pAssemblyName, + [out, retval] ICLRPrivAssembly ** ppAssembly); + + /********************************************************************************** + ** GetBinderID + ** pBinderId, pointer to binder id. The binder id has the following properties + ** It is a pointer that does not change over the lifetime of a binder object + ** It points at an object in memory that will remain allocated for the lifetime of the binder. + ** This value should be the same for a set of binder objects that represent the same binder behavior. + **********************************************************************************/ + HRESULT GetBinderID( + [out, retval] UINT_PTR *pBinderId); + + /********************************************************************************** + ** GetLoaderAllocator + ** Get LoaderAllocator for binders that contain it. For other binders, return + ** E_FAIL + ** + ** pLoaderAllocator - when successful, constains the returned LoaderAllocator + **********************************************************************************/ + HRESULT GetLoaderAllocator( + [out, retval] LPVOID * pLoaderAllocator); +}; + +/************************************************************************************** + ** ASSEMBLY_IMAGE_TYPES - The set of assembly image formats. + **************************************************************************************/ +enum ASSEMBLY_IMAGE_TYPES +{ + // IL image format + ASSEMBLY_IMAGE_TYPE_IL = 0x0001, + // Native image (NGEN) format + ASSEMBLY_IMAGE_TYPE_NATIVE = 0x0002, + // Binder's preferred image type + ASSEMBLY_IMAGE_TYPE_DEFAULT = 0x0003, + // Only supported on CoreCLR + ASSEMBLY_IMAGE_TYPE_ASSEMBLY = 0x0004, +}; + +/************************************************************************************** + ** ICLRPrivAssembly - Represents an assembly bind result. Extends ICLRPrivBinder, which + ** implicitly tracks the parent binder, and enables simple assembly-relative binds. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8543), + version(1.0), + local +] +interface ICLRPrivAssembly : ICLRPrivBinder +{ + /********************************************************************************** + ** IsShareable - Use to determine if the assembly should be shared. + ** NOTE: This method is required to be idempotent. See general comment above. + ** + ** A binder must adhere to the following contract when marking an assembly as + ** shareable: + ** - all assemblies in the full static binding closure must also be shareable. + ** + ** pbIsShareable - set to TRUE if the assembly can be shared; FALSE otherwise. + **********************************************************************************/ + HRESULT IsShareable( + [out, retval] BOOL * pbIsShareable); + + /********************************************************************************** + ** GetAvailableImageTypes - Use to retrieve the set of images available for an + ** assembly. + ** NOTE: This method is required to be idempotent. See general comment above. + ** + ** pdwImageTypes - set to values from ASSEMBLY_IMAGE_TYPES to indicate + ** which image formats are available for the assembly. + **********************************************************************************/ + HRESULT GetAvailableImageTypes( + [out, retval] LPDWORD pdwImageTypes); + + /********************************************************************************** + ** GetImageResource - Returns the resource for the given image type. The returned + ** IUnknown interface is one of the ICLRPrivResource* interfaces defined below. + ** It is the binder's choice as to which resource type is returned. If + ** pdwImageType is non-null, then this will be set to indicate the image type + ** returned. + ** NOTE: This method is required to be idempotent. See general comment above. + **********************************************************************************/ + HRESULT GetImageResource( + [in] DWORD dwImageType, + [out] DWORD* pdwImageType, + [out, retval] ICLRPrivResource ** ppIResource); +}; + +/************************************************************************************** + ** ICLRPrivResource - Generic resource that must be queried for more specific + ** interface. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8547), + version(1.0), + local +] +interface ICLRPrivResource : IUnknown +{ + /********************************************************************************** + ** GetResourceType - use to query the interface IID of the specific resource type. + ** + ** priid - set to the IID corresponding to the resource type. + **********************************************************************************/ + HRESULT GetResourceType( + [out, retval] IID *pIID); +}; + +/************************************************************************************** + ** ICLRPrivResourcePath - Encapsulates a resource identified by path. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8544), + version(1.0), + local +] +interface ICLRPrivResourcePath : IUnknown +{ + /********************************************************************************** + ** GetPath - Use to retrieve the resource's absolute file path. + ** NOTE: This method is required to be idempotent. See general comment above. + ** + ** cchBuffer - the count of unicode characters available in the buffer. + **********************************************************************************/ + HRESULT GetPath( + [in] DWORD cchBuffer, + [out] LPDWORD pcchBuffer, + [out, size_is(cchBuffer), length_is(*pcchBuffer), string, optional] LPWSTR wzBuffer); +}; + +/************************************************************************************** + ** ICLRPrivResourceStream - Encapsulates a resource identified by IStream. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8545), + version(1.0), + local +] +interface ICLRPrivResourceStream : IUnknown +{ + /********************************************************************************** + ** GetStream - Use to retrieve IStream instance corresponding to the resource. + ** NOTE: This method is required to be idempotent. See general comment above. + ** + ** riid - the IID of the interface to return. Typically IID_IStream. + ** ppvStream - contains the returned interface. + **********************************************************************************/ + HRESULT GetStream( + [in] REFIID riid, + [out, iid_is(riid), retval] LPVOID * ppvStream); +}; + +/************************************************************************************** + ** ICLRPrivResourceHMODULE - Encapsulates a resource identified by HMODULE. + **************************************************************************************/ +[ + uuid(2601F621-E462-404C-B299-3E1DE72F8546), + version(1.0), + local +] +interface ICLRPrivResourceHMODULE : IUnknown +{ + /********************************************************************************** + ** GetStream - Use to retrieve the resource's HMODULE value. The HMODULE's + ** reference count is not changed; the ICLRPrivResourceHMODULE instance must be + ** kept until the HMODULE is either reference counted or no longer used. + ** NOTE: This method is required to be idempotent. See general comment above. + **********************************************************************************/ + HRESULT GetHMODULE( + [out, retval] HMODULE * phModule); +}; + +[ + uuid(8d2d3cc9-1249-4ad4-977d-b772bd4e8a94), + version(1.0), + local +] +interface ICLRPrivResourceAssembly : IUnknown +{ + /********************************************************************************** + ** GetAssembly - Use to retrieve the resource's BINDER_SPACE::Assembly value. + ** NOTE: This method is required to be idempotent. See general comment above. + **********************************************************************************/ + HRESULT GetAssembly( + [out, retval] LPVOID * pAssembly); +}; + +/************************************************************************************** + ** ICLRPrivAssemblyInfo - Encapsulates assembly image info. + **************************************************************************************/ +[ + uuid(5653946E-800B-48B7-8B09-B1B879B54F68), + version(1.0), + local +] +interface ICLRPrivAssemblyInfo : IUnknown +{ + HRESULT GetAssemblyName( + [in] DWORD cchBuffer, + [out] LPDWORD pcchBuffer, + [out, string, optional] LPWSTR wzBuffer); + + HRESULT GetAssemblyVersion( + [out] USHORT *pMajor, + [out] USHORT *pMinor, + [out] USHORT *pBuild, + [out] USHORT *pRevision); + + HRESULT GetAssemblyPublicKey( + [in] DWORD cbBuffer, + [out] LPDWORD pcbBuffer, + [out, size_is(cbBuffer), length_is(*pcbBuffer), optional] BYTE *pbBuffer); +}; + +/************************************************************************************** + ** ICLRPrivAssemblyID_WinRT - Provides identification for WinRT assembly - allows dynamic casting inside code:CLRPrivAssemblyWinRT. + **************************************************************************************/ +[ + uuid(4372D277-9906-4FED-BF53-30C0B4010896), + version(1.0), + local +] +interface ICLRPrivAssemblyID_WinRT : IUnknown +{ +}; + +/************************************************************************************** + ** ICLRPrivWinRtTypeBinder - Provides binding to WinRT types that are already loaded. + **************************************************************************************/ +[ + uuid(6DE2A085-EFF4-4078-9F60-B9D366736398), + version(1.0), + local +] +interface ICLRPrivWinRtTypeBinder : IUnknown +{ + /********************************************************************************** + ** FindAssemblyForWinRtTypeIfLoaded + ** Finds Assembly * for type in AppDomain * if it is loaded. + ** Returns NULL if assembly is not loaded or type is not found. + **********************************************************************************/ + void * FindAssemblyForWinRtTypeIfLoaded( + void * pAppDomain, + LPCUTF8 szNamespace, + LPCUTF8 szClassName); +}; diff --git a/lib/coreclr/src/inc/clrprivhosting.idl b/lib/coreclr/src/inc/clrprivhosting.idl new file mode 100644 index 0000000000..b288c286b6 --- /dev/null +++ b/lib/coreclr/src/inc/clrprivhosting.idl @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +import "unknwn.idl"; +import "CLRPrivBinding.idl"; + +//===================================================================================================================== +// Forward declarations +interface ICLRPrivRuntime; + +//===================================================================================================================== +// CLRPrivHosting coclass +//===================================================================================================================== +[ + uuid("EDA73987-E6C0-42BF-A6B7-073F7B24D8C7") +] +library CLRPrivHosting +{ + //================================================================================================================= + // CLRPrivRuntime + //================================================================================================================= + [ + uuid(BC1B53A8-DCBC-43B2-BB17-1E4061447AE8) + ] + coclass CLRPrivRuntime + { + [default] interface ICLRPrivRuntime; + }; +}; + +//===================================================================================================================== +// ICLRPrivRuntime +//===================================================================================================================== +[ + uuid(BC1B53A8-DCBC-43B2-BB17-1E4061447AE9), + version(1.0), + local +] +interface ICLRPrivRuntime : IUnknown +{ + /********************************************************************************** + ** Used for accessing additional hosting functionality. + ** + ** rclsid - the CoClass from which to request the interface. + ** riid - the IID of the interface being requested. + ** ppUnk - receives the interface pointer value. + **********************************************************************************/ + HRESULT GetInterface( + [in] REFCLSID rclsid, + [in] REFIID riid, + [out, iid_is(riid), retval] LPVOID *ppUnk); + + /********************************************************************************** + ** Creates a domain using the provided binder for the root default bind context. + ** + ** pwzFriendlyName - the name to associate with the domain. + ** pBinder - the binder to use for root-level binds in the default context. + ** pdwAppDomainId - receives the ID of the created domain. + **********************************************************************************/ + HRESULT CreateAppDomain( + [in, string] LPCWSTR pwzFriendlyName, + [in] ICLRPrivBinder * pBinder, + [out, retval] LPDWORD pdwAppDomainId); + + /********************************************************************************** + ** Creates a native-callable function pointer to the specified method. + ** + ** appDomainID - the domain in which to create the delegate. + ** wszAssemblyName - the name of the assembly in which the method is defined. + ** wszClassName - the name of the class (including namespace) in which the method + ** is defined. + ** wszMethodName - the name of the method for which to create a delegate. + ** ppvDelegate - receives the delegate pointer value. + **********************************************************************************/ + HRESULT CreateDelegate( + [in] DWORD appDomainID, + [in, string] LPCWSTR wszAssemblyName, + [in, string] LPCWSTR wszClassName, + [in, string] LPCWSTR wszMethodName, + [out, retval] LPVOID * ppvDelegate); + + /********************************************************************************** + ** Creates an AppX appdomain and executes entrypoint method of an executable there + ** + **********************************************************************************/ + HRESULT ExecuteMain( + [in] ICLRPrivBinder * pBinder, + [out, retval] int * pRetVal + ); +}; + diff --git a/lib/coreclr/src/inc/clrprivruntimebinders.idl b/lib/coreclr/src/inc/clrprivruntimebinders.idl new file mode 100644 index 0000000000..0da7e3acd7 --- /dev/null +++ b/lib/coreclr/src/inc/clrprivruntimebinders.idl @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +import "CLRPrivBinding.idl"; + +//===================================================================================================================== +// CLRPrivRuntime +//===================================================================================================================== +[ + uuid("EA6A2170-8F6A-4007-87A9-02429F615958") +] +library CLRPrivRuntimeBinders +{ + //================================================================================================================= + // CLRPrivAppXBinder + //================================================================================================================= + [ + uuid(E990F732-2D0A-48AC-87FC-EF12B618981A), + helpstring("Runtime-provided package-based assembly binder for AppX."), + ] + coclass CLRPrivAppXBinder + { + [default] interface ICLRPrivBinder; + }; + + //================================================================================================================= + // CLRPrivFusionBinder + //================================================================================================================= + [ + uuid(E990F732-2D0A-48AC-87FC-EF12B618981C), + helpstring("Runtime-provided binder for wrapping ICLRPrivBinder-compatible subset of fusion functionality."), + ] + coclass CLRPrivFusionBinder + { + [default] interface ICLRPrivBinder; + }; +}; + diff --git a/lib/coreclr/src/inc/clrtypes.h b/lib/coreclr/src/inc/clrtypes.h new file mode 100644 index 0000000000..15387aa796 --- /dev/null +++ b/lib/coreclr/src/inc/clrtypes.h @@ -0,0 +1,411 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// ================================================================================ +// Standard primitive types for CLR code +// +// This header serves as a platform layer containing all of the primitive types +// which we use across CLR implementation code. +// ================================================================================ + + +#ifndef CLRTYPES_H_ +#define CLRTYPES_H_ + +#if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) && defined(FEATURE_CORESYSTEM) + // Prefer intsafe.h when available, which defines many of the MAX/MIN + // values below (which is why they are in #ifndef blocks). + #include +#endif + +#include "crtwrap.h" +#include "winwrap.h" +#include "staticcontract.h" +#include "static_assert.h" + +#if _WIN64 + #define POINTER_BITS 64 +#else + #define POINTER_BITS 32 +#endif + +// ================================================================================ +// Integral types - use these for all integral types +// These types are in ALL_CAPS. Each type has a _MIN and _MAX defined for it. +// ================================================================================ + +// -------------------------------------------------------------------------------- +// Use these types for fixed size integers: +// INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 +// -------------------------------------------------------------------------------- + +#ifndef INT8_MAX + typedef signed char INT8; + typedef unsigned char UINT8; + typedef short INT16; + typedef unsigned short UINT16; + typedef int INT32; + typedef unsigned int UINT32; + typedef __int64 INT64; + typedef unsigned __int64 UINT64; + + #ifdef _MSC_VER + /* These macros must exactly match those in the Windows SDK's intsafe.h */ + #define INT8_MIN (-127i8 - 1) + #define INT16_MIN (-32767i16 - 1) + #define INT32_MIN (-2147483647i32 - 1) + #define INT64_MIN (-9223372036854775807i64 - 1) + + #define INT8_MAX 127i8 + #define INT16_MAX 32767i16 + #define INT32_MAX 2147483647i32 + #define INT64_MAX 9223372036854775807i64 + + #define UINT8_MAX 0xffui8 + #define UINT16_MAX 0xffffui16 + #define UINT32_MAX 0xffffffffui32 + #define UINT64_MAX 0xffffffffffffffffui64 + #else + #define INT8_MIN ((INT8)0x80) + #define INT16_MIN ((INT16)0x8000) + #define INT32_MIN ((INT32)0x80000000) + #define INT64_MIN ((INT64) I64(0x8000000000000000)) + + #define INT8_MAX ((INT8)0x7f) + #define INT16_MAX ((INT16)0x7fff) + #define INT32_MAX ((INT32)0x7fffffff) + #define INT64_MAX ((INT64) I64(0x7fffffffffffffff)) + + #define UINT8_MAX ((UINT8)0xffU) + #define UINT16_MAX ((UINT16)0xffffU) + #define UINT32_MAX ((UINT32)0xffffffffU) + #define UINT64_MAX ((UINT64) UI64(0xffffffffffffffff)) + #endif +#endif // !INT8_MAX + +// UINTX_MINs aren't defined in standard header files, +// so definition must be separately predicated. +#ifndef UINT8_MIN + #ifdef _MSC_VER + #define UINT8_MIN 0ui8 + #define UINT16_MIN 0ui16 + #define UINT32_MIN 0ui32 + #define UINT64_MIN 0ui64 + #else + #define UINT8_MIN ((UINT8)0U) + #define UINT16_MIN ((UINT16)0U) + #define UINT32_MIN ((UINT32)0U) + #define UINT64_MIN ((UINT64) UI64(0)) + #endif +#endif + + +// -------------------------------------------------------------------------------- +// Use these types for pointer-sized integral types +// SIZE_T SSIZE_T +// +// These types are the ONLY types which can be safely cast back and forth from a +// pointer. +// -------------------------------------------------------------------------------- + +#ifndef SIZE_T_MAX + #if NEED_POINTER_SIZED_TYPEDEFS + typedef size_t SIZE_T; + typedef ptrdiff_t SSIZE_T; + #endif + + #if POINTER_BITS == 64 + #define SIZE_T_MAX UINT64_MAX + #define SIZE_T_MIN UINT64_MIN + + #define SSIZE_T_MAX INT64_MAX + #define SSIZE_T_MIN INT64_MIN + #else + #define SIZE_T_MAX UINT32_MAX + #define SIZE_T_MIN UINT32_MIN + + #define SSIZE_T_MAX INT32_MAX + #define SSIZE_T_MIN INT32_MIN + #endif +#endif + +// -------------------------------------------------------------------------------- +// Non-pointer sized types +// COUNT_T SCOUNT_T +// +// Use these types for "large" counts or indexes which will not exceed 32 bits. They +// may also be used for pointer differences, if you can guarantee that the pointers +// are pointing to the same region of memory. (It can NOT be used for arbitrary +// pointer subtraction.) +// -------------------------------------------------------------------------------- + +#ifndef COUNT_T_MAX + typedef UINT32 COUNT_T; + typedef INT32 SCOUNT_T; + + #define COUNT_T_MAX UINT32_MAX + #define COUNT_T_MIN UINT32_MIN + + #define SCOUNT_T_MAX INT32_MAX + #define SCOUNT_T_MIN INT32_MIN +#endif + +// -------------------------------------------------------------------------------- +// Integral types with additional semantic content +// BOOL BYTE +// -------------------------------------------------------------------------------- + +#ifndef BYTE_MAX + #if NEED_BOOL_TYPEDEF + typedef bool BOOL; + #endif + + #define BOOL_MAX 1 + #define BOOL_MIN 0 + + #define TRUE 1 + #define FALSE 0 + + typedef UINT8 BYTE; + + #define BYTE_MAX UINT8_MAX + #define BYTE_MIN UINT8_MIN +#endif + +// -------------------------------------------------------------------------------- +// Character types +// CHAR SCHAR UCHAR WCHAR +// -------------------------------------------------------------------------------- + +typedef char CHAR; +typedef signed char SCHAR; +typedef unsigned char UCHAR; +typedef wchar_t WCHAR; + +typedef CHAR ASCII; +typedef CHAR ANSI; +typedef CHAR UTF8; + +// Standard C defines: + +// CHAR_MAX +// CHAR_MIN +// SCHAR_MAX +// SCHAR_MIN +// UCHAR_MAX +// UCHAR_MIN +// WCHAR_MAX +// WCHAR_MIN + +#ifndef ASCII_MAX + #define ASCII_MIN ((ASCII)0) + #define ASCII_MAX ((ASCII)127) + + #define ANSI_MIN ((ANSI)0) + #define ANSI_MAX ((ANSI)255) + + #define UTF8_MIN ((UTF8)0) + #define UTF8_MAX ((UTF8)255) +#endif + +// ================================================================================ +// Non-integral types +// These types are in ALL_CAPS. +// ================================================================================ + +// -------------------------------------------------------------------------------- +// Floating point types +// FLOAT DOUBLE +// -------------------------------------------------------------------------------- + +// ================================================================================ +// Runtime type definitions - these are guaranteed to be identical with the +// corresponding managed type +// ================================================================================ + +typedef WCHAR CLR_CHAR; +typedef INT8 CLR_I1; +typedef UINT8 CLR_U1; +typedef INT16 CLR_I2; +typedef UINT16 CLR_U2; +typedef INT32 CLR_I4; +typedef UINT32 CLR_U4; +typedef INT64 CLR_I8; +typedef UINT64 CLR_U8; +typedef FLOAT CLR_R4; +typedef DOUBLE CLR_R8; +typedef SSIZE_T CLR_I; +typedef SIZE_T CLR_U; + +#define CLR_CHAR_MAX WCHAR_MAX +#define CLR_CHAR_MIN WCHAR_MIN + +#define CLR_I1_MAX INT8_MAX +#define CLR_I1_MIN INT8_MIN + +#define CLR_U1_MAX UINT8_MAX +#define CLR_U1_MIN UINT8_MIN + +#define CLR_I2_MAX INT16_MAX +#define CLR_I2_MIN INT16_MIN + +#define CLR_U2_MAX UINT16_MAX +#define CLR_U2_MIN UINT16_MIN + +#define CLR_I4_MAX INT32_MAX +#define CLR_I4_MIN INT32_MIN + +#define CLR_U4_MAX UINT32_MAX +#define CLR_U4_MIN UINT32_MIN + +#define CLR_I8_MAX INT64_MAX +#define CLR_I8_MIN INT64_MIN + +#define CLR_U8_MAX UINT64_MAX +#define CLR_U8_MIN UINT64_MIN + +#define CLR_I_MAX SSIZE_T_MAX +#define CLR_I_MIN SSIZE_T_MIN + +#define CLR_U_MAX SIZE_T_MAX +#define CLR_U_MIN SIZE_T_MIN + + typedef bool CLR_BOOL; + +static_assert_no_msg(sizeof(CLR_BOOL) == 1); + +#define CLR_BOOL_MAX BOOL_MAX +#define CLR_BOOL_MIN BOOL_MIN + +#define CLR_NAN_32 0xFFC00000 +#define CLR_NAN_64 I64(0xFFF8000000000000) + +// ================================================================================ +// Simple utility functions +// ================================================================================ + +// Note that these routines are in terms of UINT, ULONG, and ULONG64, since those are +// the unsigned integral types the compiler overloads based on. + +// -------------------------------------------------------------------------------- +// Min/Max +// -------------------------------------------------------------------------------- + +template +T Min(T v1, T v2) +{ + STATIC_CONTRACT_LEAF; + return v1 < v2 ? v1 : v2; +} + +template +T Max(T v1, T v2) +{ + STATIC_CONTRACT_LEAF; + return v1 > v2 ? v1 : v2; +} + +// -------------------------------------------------------------------------------- +// Alignment bit twiddling macros - "alignment" must be power of 2 +// +// AlignUp - align value to given increment, rounding up +// AlignmentPad - amount adjusted by AlignUp +// AlignUp(value, x) == value + AlignmentPad(value, x) +// +// AlignDown - align value to given increment, rounding down +// AlignmentTrim - amount adjusted by AlignDown +// AlignDown(value, x) == value - AlignmentTrim(value, x) +// -------------------------------------------------------------------------------- + +inline UINT AlignUp(UINT value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value+alignment-1)&~(alignment-1); +} + +#if defined(_MSC_VER) +inline ULONG AlignUp(ULONG value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value+alignment-1)&~(alignment-1); +} +#endif + +inline UINT64 AlignUp(UINT64 value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value+alignment-1)&~(UINT64)(alignment-1); +} + +inline UINT AlignDown(UINT value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value&~(alignment-1)); +} + +#if defined(_MSC_VER) +inline ULONG AlignDown(ULONG value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value&~(ULONG)(alignment-1)); +} +#endif + +inline UINT64 AlignDown(UINT64 value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return (value&~(UINT64)(alignment-1)); +} + +inline UINT AlignmentPad(UINT value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + return AlignUp(value, alignment) - value; +} + +#if defined(_MSC_VER) +inline UINT AlignmentPad(ULONG value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + return AlignUp(value, alignment) - value; +} +#endif + +inline UINT AlignmentPad(UINT64 value, UINT alignment) +{ + STATIC_CONTRACT_WRAPPER; + return (UINT) (AlignUp(value, alignment) - value); +} + +inline UINT AlignmentTrim(UINT value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return value&(alignment-1); +} + +#ifndef PLATFORM_UNIX +// For Unix this and the previous function get the same types. +// So, exclude this one. +inline UINT AlignmentTrim(ULONG value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return value&(alignment-1); +} +#endif // PLATFORM_UNIX + +inline UINT AlignmentTrim(UINT64 value, UINT alignment) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + return ((UINT)value)&(alignment-1); +} + +#endif // CLRTYPES_H_ diff --git a/lib/coreclr/src/inc/complex.h b/lib/coreclr/src/inc/complex.h new file mode 100644 index 0000000000..159c81d04b --- /dev/null +++ b/lib/coreclr/src/inc/complex.h @@ -0,0 +1,80 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// complex.h +// + +// +// Defines a basic complex number data type. We cannot use the standard C++ library's +// complex implementation, because the CLR links to the wrong CRT. +// + +#ifndef _COMPLEX_H_ +#define _COMPLEX_H_ + +#include + +// +// Default compilation mode is /fp:precise, which disables fp intrinsics. This causes us to pull in FP stuff (sqrt,etc.) from +// The CRT, and increases our download size. We don't need the extra precision this gets us, so let's switch to +// the intrinsic versions. +// +#ifdef _MSC_VER +#pragma float_control(precise, off, push) +#endif + + +class Complex +{ +public: + double r; + double i; + + Complex() : r(0), i(0) {} + Complex(double real) : r(real), i(0) {} + Complex(double real, double imag) : r(real), i(imag) {} + Complex(const Complex& other) : r(other.r), i(other.i) {} +}; + +inline Complex operator+(Complex left, Complex right) +{ + LIMITED_METHOD_CONTRACT; + return Complex(left.r + right.r, left.i + right.i); +} + +inline Complex operator-(Complex left, Complex right) +{ + LIMITED_METHOD_CONTRACT; + return Complex(left.r - right.r, left.i - right.i); +} + +inline Complex operator*(Complex left, Complex right) +{ + LIMITED_METHOD_CONTRACT; + return Complex( + left.r * right.r - left.i * right.i, + left.r * right.i + left.i * right.r); +} + +inline Complex operator/(Complex left, Complex right) +{ + LIMITED_METHOD_CONTRACT; + double denom = right.r * right.r + right.i * right.i; + return Complex( + (left.r * right.r + left.i * right.i) / denom, + (-left.r * right.i + left.i * right.r) / denom); +} + +inline double abs(Complex c) +{ + LIMITED_METHOD_CONTRACT; + return sqrt(c.r * c.r + c.i * c.i); +} + +#ifdef _MSC_VER +#pragma float_control(pop) +#endif + + +#endif //_COMPLEX_H_ diff --git a/lib/coreclr/src/inc/configuration.h b/lib/coreclr/src/inc/configuration.h new file mode 100644 index 0000000000..876abf2530 --- /dev/null +++ b/lib/coreclr/src/inc/configuration.h @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// -------------------------------------------------------------------------------------------------- +// configuration.h +// +// +// Access and update configuration values, falling back on legacy CLRConfig methods where necessary. +// +// -------------------------------------------------------------------------------------------------- + +#include "clrconfig.h" + +#ifndef __configuration_h__ +#define __configuration_h__ + +class Configuration +{ +public: + static void InitializeConfigurationKnobs(int numberOfConfigs, LPCWSTR *configNames, LPCWSTR *configValues); + + // Returns (in priority order): + // - The value of the ConfigDWORDInfo if it's set + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcstoul). + // - The default set in the ConfigDWORDInfo + static DWORD GetKnobDWORDValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo); + + // Returns (in priority order): + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcstoul) + // - The default value passed in + static DWORD GetKnobDWORDValue(LPCWSTR name, DWORD defaultValue); + + // Unfortunately our traditional config system insists on interpreting numbers as 32-bit so intepret the config + // in the traditional way separately if you need to. + // + // Returns value for name if found in config. + static ULONGLONG GetKnobULONGLONGValue(LPCWSTR name); + + // Returns (in priority order): + // - The value of the ConfigStringInfo if it's set + // - The value of the ConfigurationKnob (searched by name) if it's set + // - nullptr + static LPCWSTR GetKnobStringValue(LPCWSTR name, const CLRConfig::ConfigStringInfo& stringInfo); + + // Returns (in priority order): + // - The value of the ConfigurationKnob (searched by name) if it's set + // - nullptr + static LPCWSTR GetKnobStringValue(LPCWSTR name); + + // Returns (in priority order): + // - The value of the ConfigDWORDInfo if it's set (1 is true, anything else is false) + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). + // - The default set in the ConfigDWORDInfo (1 is true, anything else is false) + static bool GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo); + + // Returns (in priority order): + // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). + // - The default value passed in + static bool GetKnobBooleanValue(LPCWSTR name, bool defaultValue); +}; + +#endif // __configuration_h__ diff --git a/lib/coreclr/src/inc/contract.h b/lib/coreclr/src/inc/contract.h new file mode 100644 index 0000000000..3913e56b8a --- /dev/null +++ b/lib/coreclr/src/inc/contract.h @@ -0,0 +1,2370 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// Contract.h +// + +// ! I am the owner for issues in the contract *infrastructure*, not for every +// ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine +// ! CONTRACT_VIOLATION, you will become the new owner of this file. +//-------------------------------------------------------------------------------- +// CONTRACTS - User Reference +// +// A CONTRACT is a container for a set of checked declarations about a +// function. Besides giving developers a "laundry list" of checks to +// make checking more complete, contracts compile these checks +// as hidden annotations into the checked executable that our static scanner +// uses to detect violations automatically. +// +// Contracts can be dynamic or static. Dynamic contracts perform runtime checks +// as well as being visible to the static scanner. Static contracts generate no +// runtime code but are still visible to the scanner. Dynamic contracts are +// preferred unless perf or other considerations preclude them. +// +// The following annotations can appear in contracts: +// +// +// THROWS an exception might be thrown out of the function +// -or- NOTHROW an exception will NOT be thrown out of the function +// +// +// +// INJECT_FAULT(statement) function might require its caller to handle an OOM +// -or- FAULT_FORBID function will NOT require its caller to handle an OOM +// +// +// +// GC_TRIGGERS the function can trigger a GC +// -or- GC_NOTRIGGER the function will never trigger a GC provided its +// called in coop mode. +// +// +// MODE_COOPERATIVE the function requires Cooperative GC mode on entry +// -or- MODE_PREEMPTIVE the function requires Preemptive GC mode on entry +// -or- MODE_ANY the function can be entered in either mode +// +// LOADS_TYPE(level) the function promises not to load any types beyond "level" +// +// CAN_TAKE_LOCK the function has a code path that takes a lock +// _or_ (CAN_TAKE_LOCK and CANNOT_RETAKE_LOCK) +// the function has a code path that takes a lock, but never tries to reenter +// locks held at the time this function was called. +// -or- CANNOT_TAKE_LOCK the function will never allow a lock to be taken +// -or- the default is WRAPPER(CAN_TAKE_LOCK). i.e., if any callees take locks, +// then it's ok for this function to as well. If LIMITED_METHOD_CONTRACT is specified, +// however, then CANNOT_TAKE_LOCK is assumed. +// +// EE_THREAD_NOT_REQUIRED the function does not assume an EE Thread object is available in TLS. +// Either GetThread() is never called, or any code path that requires a Thread +// has another code path that deals with the absence of a Thread. Any call to +// to GetThread() must be bracketed with BEGIN_GETTHREAD_ALLOWED / +// END_GETTHREAD_ALLOWED to avoid bogus asserts (the short-form +// GetThreadNULLOk() may be used as well). However, this is only allowed if visual +// inspection of the call site makes it patently obvious that the function deals +// appropriately with the GetThread() == NULL case. +// -or- EE_THREAD_REQUIRED the function requires an EE Thread object in TLS (i.e., GetThread() != NULL) +// If this contract is used, we will ASSERT on entry to the function that +// GetThread() != NULL. +// -or- the default is DISABLED(EE_THREAD_REQUIRED). i.e., we do not assert +// GetThread() != NULL on entry to the function and do not assert on any +// unprotected uses of GetThread(). +// See code:GetThreadGenericFullCheck for info on how these +// contracts are enforced. +// +// SUPPORTS_DAC The function has been written to be callable from out-of-process using DAC. +// In builds where DACCESS_COMPILE is defined, such functions can only call +// other such functions (and a few primitives like new). Functions that support +// DAC must be carefully written to conform to the rules in daccess.h. +// +// SUPPORTS_DAC_HOST_ONLY The function and its call graph has been written to be callable from out of process +// using DAC, but it differs from SUPPORTS_DAC in that these functions won't perform +// any marshalling. Because it does no marshalling, SUPPORTS_DAC_HOST_ONLY functions +// and their call graph won't be checked by DacCop. This should only be used by utility +// functions which will never marshal anything. +// +// PRECONDITION(X) - generic CHECK or BOOL expression which should be true +// on function entry +// +// POSTCONDITION(X) - generic CHECK or BOOL expression which should be true +// on function entry. Note that variable RETVAL will be +// available for use in the expression. +// +// +// INSTANCE_CHECK - equivalent of: +// PRECONDITION(CheckPointer(this)); +// POSTCONDITION(CheckInvariant(this)); +// INSTANCE_CHECK_NULL - equivalent of: +// PRECONDITION(CheckPointer(this, NULL_OK)); +// POSTCONDITION(CheckInvariant(this, NULL_OK)); +// CONSTRUCTOR_CHECK - equivalent of: +// POSTCONDITION(CheckPointer(this)); +// DESTRUCTOR_CHECK - equivalent of: +// PRECONDITION(CheckPointer(this)); +// +// +// +// +// Contracts come in the following flavors: +// +// Dynamic: +// CONTRACTL the standard version used for all dynamic contracts +// except those including postconditions. +// +// CONTRACT(rettype) an uglier version of CONTRACTL that's unfortunately +// needed to support postconditions. You must specify +// the correct return type and it cannot be "void." +// (Use CONTRACT_VOID instead) You must use the +// RETURN macro rather than the "return" keyword. +// +// CONTRACT_VOID you can't supply "void" to a CONTRACT - use this +// instead. +// +// Static: +// LIMITED_METHOD_CONTRACT +// A static contract equivalent to NOTHROW/GC_NOTRIGGER/FORBID_FAULT/MODE_ANY. +// Use only for trivial functions that call only functions with LIMITED_METHOD_CONTRACTs +// (as long as there is no cycle that may introduce infinite recursion). +// +// STATIC_CONTRACT_THROWS +// STATIC_CONTRACT_NOTHROW +// STATIC_CONTRACT_GC_TRIGGERS +// STATIC_CONTRACT_GCNOTRIGGER +// STATIC_CONTRACT_FAULT +// STATIC_CONTRACT_FORBID_FAULT +// use to implement statically checkable contracts +// when runtime contracts cannot be used. +// +// +// WRAPPER(annotation) +// +// When a function does not explicitly caused a condition, use the WRAPPER macro around +// the declaration. This implies that the function is dependent on the functions it calls +// for its behaviour, and guarantees nothing. +// +// +// CONTRACT_VIOLATION(violationmask): +// +// A bandaid used to suppress contract assertions. A contract violation +// is always a bug and you're expected to remove it before shipping. +// If a violation cannot be fixed immediately, however, it's better +// to use this on the offending callsite than to disable a contract entirely. +// +// The violationmask can be one or more of the following OR'd together. +// +// ThrowsViolation +// GCViolation +// ModeViolation +// FaultViolation +// FaultNotFatal +// HostViolation +// LoadsTypeViolation +// TakesLockViolation +// +// The associated assertion will be suppressed until you leave the scope +// containing the CONTRACT_VIOLATION. Note, however, that any called +// function that redeclares the associated annotation reinstates +// the assert for the scope of *its* call. This prevents a CONTRACT_VIOLATION +// placed at the root of a calltree from decimating our entire protection. +// +// +// PERMANENT_CONTRACT_VIOLATION(violationmask, permanentContractViolationReason): +// +// Like a CONTRACT_VIOLATION but also indicates that the violation was a deliberate decision +// and we don't plan on removing the violation in the next release. The reason +// for the violation should be given as the second parameter to the macro. Reasons +// are currently for documentation purposes only and do not have an effect on the binary. +// Valid values are listed below in the definition of PermanentContractViolationReason. +// +// +// CONDITIONAL_CONTRACT_VIOLATION(violationmask, condition): +// +// Similar to CONTRACT_VIOLATION, but only suppresses the contract if the +// condition evaluates to non-zero. The need for this macro should be very +// rare, but it can be useful if a contract should be suppressed based on a +// condition known only at run-time. For example, if a particular test causes +// call sequences never expected by real scenarios, you may want to suppress +// resulting violations, but only when that test is run. +// +// WRAPPER_NO_CONTRACT +// +// A do-nothing contract used by functions that trivially wrap another. +// +// +// "LEGACY" stuff - these features have been mostly superceded by better solutions +// so their use should be discouraged. +// +// +// DISABLED(annotation) +// +// Indicates that a condition is supposed to be checked but is being suppressed +// due to some temporary bug. The more surgical CONTRACT_VIOLATION is +// preferred over DISABLED. +// +// UNCHECKED(annotation) +// +// Indicates that a condition is supposed to be checked but is being suppressed +// due for perf reasons. Use STATIC_CONTRACT over this. +// +// +// Default values: +// If you don't specify certain annotaions, you get defaults. +// - THROWS/NOTHROW defaults to THROWS +// - GCTRIGGERS/GCNOTRIGGER defaults to GCTRIGGERS within the VM directory +// and to no check otherwise +// - INJECT/FORBID_FAULT defaults to no check +// - MODE defaults to MODE_ANY +// +// The problem is that defaults don't work well with static contracts. +// The scanner will always treat a missing annotation as DISABLED. +// New code should not rely on defaults. Explicitly state your invariants. +// +// +//-------------------------------------------------------------------------------- + + + + +#ifndef CONTRACT_H_ +#define CONTRACT_H_ + +#ifdef _MSC_VER +#pragma warning(disable:4189) //local variable is initialized but not referenced +#endif + + +// We only enable contracts in _DEBUG builds +#if defined(_DEBUG) && !defined(DISABLE_CONTRACTS) +#define ENABLE_CONTRACTS_DATA +#endif + +// Also, we won't enable contracts if this is a DAC build. +#if defined(ENABLE_CONTRACTS_DATA) && !defined(DACCESS_COMPILE) && !defined(CROSS_COMPILE) +#define ENABLE_CONTRACTS +#endif + +// Finally, only define the implementaiton parts of contracts if this isn't a DAC build. +#if defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS) +#define ENABLE_CONTRACTS_IMPL +#endif + +#include "specstrings.h" +#include "clrtypes.h" +#include "malloc.h" +#include "check.h" +#include "debugreturn.h" +#include "staticcontract.h" + +#ifdef ENABLE_CONTRACTS_DATA + +#include "eh.h" + +// We chain these onto a stack to give us a stack trace of contract assertions (useful +// when the bug report doesn't contain valid symbols) + +struct ContractStackRecord +{ + ContractStackRecord *m_pNext; + const char *m_szFunction; + const char *m_szFile; + int m_lineNum; + UINT m_testmask; // Bitmask of Contract::TestEnum bitsf + const char *m_construct; // The syntactic construct that pushed this thing +}; + +class CrstBase; + +// The next few enums / structs are used to keep track of all kinds of locks +// currently taken by the current thread (crsts, spinlocks, CLR critical sections). +// Across the VM, there are still multiple counts of locks. The lock counts in these +// contract structs are used to verify consistency of lock take/release in EE code, and +// for contracts. Both user and EE locks are tracked here, but it's EE code consistency +// we're verifying. The Thread object keeps its own counts as well, primarily of user +// locks for implementing thread abort & escalation policy. We tried to have the Thread +// counts also be used for consistency checking, but that doesn't work. Thread counters +// have the following behavior that hurts our internal consistency checks: +// - They only count user locks. +// - Counters are reset & restored as we leave and return to AppDomains + +// An array of these is stored in DbgStateLockData::m_rgTakenLockInfos +// to remember which locks we've taken. If you hit an assert that +// indicates we're exiting locks in the wrong order, or that locks were +// taken when we expected none to be taken, then you can use +// DbgStateLockData::m_rgTakenLockInfos to see the locks we know about. +struct TakenLockInfo +{ + // Generally, this will be a pointer to the lock, but really it's just + // a value that identifies which lock is taken. Ya see, sometimes we don't + // have a lock pointer handy (e.g., if the lock is based on a GC object, + // which has no persistent object pointer we can use). Look at the source + // indicated by m_szFile / m_lineNum to see what was specified as m_pvLock. + // + // A common case is that the lock is just a Crst, so to aid debugging, we + // also include a statically typed version of this pointer (m_pCrstBase) just + // for Crsts. Again, you'll want look at m_szFile / m_lineNum to see how to + // interpret this union. + union + { + void * m_pvLock; + CrstBase * m_pCrstBase; + }; + + // File & line of the *LOCK_TAKEN* macro that added this lock to our list + const char * m_szFile; + int m_lineNum; +}; + +enum DbgStateLockType +{ + // EE locks (used to sync EE structures). These do not include + // CRST_HOST_BREAKABLE Crsts, and are thus not held while managed + // code runs + kDbgStateLockType_EE, + + // CRST_HOST_BREAKABLE Crsts. These can be held while arbitrary + // managed code runs. + kDbgStateLockType_HostBreakableCrst, + + // User locks (e.g., Monitor.Enter, ReaderWriterLock class) + kDbgStateLockType_User, + + // add more lock types here + + kDbgStateLockType_Count +}; + +// This keeps track of how many locks, and which locks, are currently owned +// by the current thread. There is one instance of this structure per +// thread (no EE Thread object required). This is in contrast to the +// ClrDebugState structure, which is instantiated once per function +// on the stack. Reason is that ClrDebugState resets its state on exit +// of function (Contract destructor reinstates previous ClrDebugState), whereas +// we want DbgStateLockData to persist across function enters & exits. +struct DbgStateLockData +{ + // When a lock is taken, we keep track of its pointer and file/line# when it + // was added in a static-size array DbgStateLockData::m_rgTakenLockInfos. This is + // the size of that array, and therefore indicates the maximum number of locks we + // expect one thread to hold at the same time. If we should exceed this limit, + // we'll lose this data for the latter locks that exceed this limit + // (though still maintaining an accurate *count* of locks). + static const int kMaxAllowedSimultaneousLocks = 20; + + // Count of locks taken, separately by type + UINT m_rgcLocksTaken[kDbgStateLockType_Count]; + + // List of the specific locks that have been taken (all DbgStateLockTypes + // intermingled), in the order they were taken. If we exceed the elements + // in the array, we just won't track the latter locks in here (though they are + // included in the counts above) + TakenLockInfo m_rgTakenLockInfos[kMaxAllowedSimultaneousLocks]; + + void SetStartingValues(); + void LockTaken(DbgStateLockType dbgStateLockType, + UINT cEntrances, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, + int lineNum); + void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); + UINT GetLockCount(DbgStateLockType dbgStateLockType); + UINT GetCombinedLockCount(); +}; + +// This struct contains all lock contract information. It is created and destroyed along with +// ClrDebugState. m_pLockData points to a DbgStateLockData object that is allocated per thread +// and persists across function enters and exists. +struct DbgStateLockState +{ +private: + // Count of locks taken at the time the function with CANNOT_RETAKE_LOCK contract + // was called + UINT m_cLocksEnteringCannotRetakeLock; + + DbgStateLockData * m_pLockData; // How many and which locks are currently taken on this thread + +public: + void SetStartingValues(); + void OnEnterCannotRetakeLockFunction(); + BOOL IsLockRetaken(void * pvLock); + BOOL IsSafeToRelease(UINT cReleases); + void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData); + DbgStateLockData * GetDbgStateLockData(); +}; + + +#define CONTRACT_BITMASK_OK_TO_THROW 0x1 << 0 +#define CONTRACT_BITMASK_FAULT_FORBID 0x1 << 1 +#define CONTRACT_BITMASK_HOSTCALLS 0x1 << 2 +#define CONTRACT_BITMASK_SOTOLERANT 0x1 << 3 +#define CONTRACT_BITMASK_DEBUGONLY 0x1 << 4 +#define CONTRACT_BITMASK_SONOTMAINLINE 0x1 << 5 +#define CONTRACT_BITMASK_ALLOWGETTHREAD 0x1 << 6 +#define CONTRACT_BITMASK_OK_TO_LOCK 0x1 << 7 +#define CONTRACT_BITMASK_OK_TO_RETAKE_LOCK 0x1 << 8 + + +#define CONTRACT_BITMASK_IS_SET(whichbit) ((m_flags & (whichbit)) != 0) +#define CONTRACT_BITMASK_SET(whichbit) (m_flags |= (whichbit)) +#define CONTRACT_BITMASK_RESET(whichbit) (m_flags &= ~(whichbit)) +#define CONTRACT_BITMASK_UPDATE(whichbit, value) ((value)?CONTRACT_BITMASK_SET(whichbit):CONTRACT_BITMASK_RESET(whichbit)) + + +// Stored in the FLS under TlsIdx_ClrDebugState. +struct ClrDebugState +{ +private: + UINT_PTR m_flags; + UINT_PTR m_violationmask; // Current CONTRACT_VIOLATIONS in effect + ContractStackRecord *m_pContractStackTrace; + UINT m_GCNoTriggerCount; + UINT m_GCForbidCount; + UINT m_maxLoadTypeLevel; // taken from enum ClassLoadLevel + BOOL m_allowGetThread; // TRUE if GetThread() is ok in this scope + DbgStateLockState m_LockState; + +public: + // Use an explicit Init rather than ctor as we don't want automatic + // construction of the ClrDebugState embedded inside the contract. + void SetStartingValues() + { + m_violationmask = 0; // No violations allowed + + // Default is we're in a THROWS scope. This is not ideal, but there are + // just too many places that I'd have to go clean up right now + // (hundreds) in order to make this FALSE by default. + // Faults not forbidden (an unfortunate default but + // we'd never get this debug infrastructure bootstrapped otherwise.) + // We start out in SO-tolerant mode and must probe before entering SO-intolerant + // any global state updates. + // Initial mode is non-debug until we say otherwise + // Everthing defaults to mainline + // By default, GetThread() is perfectly fine to call + // By default, it's ok to take a lock (or call someone who does) + m_flags = CONTRACT_BITMASK_OK_TO_THROW| + CONTRACT_BITMASK_HOSTCALLS| + CONTRACT_BITMASK_SOTOLERANT| + CONTRACT_BITMASK_ALLOWGETTHREAD| + CONTRACT_BITMASK_OK_TO_LOCK| + CONTRACT_BITMASK_OK_TO_RETAKE_LOCK; + + m_pContractStackTrace = NULL; // At top of stack, no contracts in force + m_GCNoTriggerCount = 0; + m_GCForbidCount = 0; + + m_maxLoadTypeLevel = ((UINT)(-1)); // ideally CLASS_LOAD_LEVEL_FINAL but we don't have access to that #define, so + // the max integer value will do as a substitute. + + m_allowGetThread = TRUE; // By default, GetThread() is perfectly fine to call + + m_LockState.SetStartingValues(); + } + + void CheckOkayToThrow(__in_z const char *szFunction, __in_z const char *szFile, int lineNum); // Asserts if its not okay to throw. + BOOL CheckOkayToThrowNoAssert(); // Returns if OK to throw + + //--// + + UINT_PTR* ViolationMaskPtr() + { + return &m_violationmask; + } + + UINT_PTR ViolationMask() + { + return m_violationmask; + } + + void ViolationMaskSet( UINT_PTR value ) + { + m_violationmask |= value; + } + + void ViolationMaskReset( UINT_PTR value ) + { + m_violationmask &= ~value; + } + + //--// + + BOOL IsOkToThrow() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW); + } + + void SetOkToThrow() + { + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_THROW); + } + + BOOL SetOkToThrow( BOOL value ) + { + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_THROW, value); + return prevState; + } + + void ResetOkToThrow() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_THROW); + } + //--// + + BOOL IsFaultForbid() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID); + } + + + void SetFaultForbid() + { + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_FAULT_FORBID); + } + + BOOL SetFaultForbid(BOOL value) + { + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_FAULT_FORBID, value); + return prevState; + } + + void ResetFaultForbid() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_FAULT_FORBID); + } + + //--// + BOOL IsHostCaller() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS); + } + + void SetHostCaller() + { + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_HOSTCALLS); + } + + + BOOL SetHostCaller(BOOL value) + { + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_HOSTCALLS,value); + return prevState; + } + + void ResetHostCaller() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_HOSTCALLS); + } + + //--// + BOOL IsDebugOnly() + { + STATIC_CONTRACT_WRAPPER; + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY); + } + + void SetDebugOnly() + { + STATIC_CONTRACT_WRAPPER; + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_DEBUGONLY); + } + + BOOL SetDebugOnly(BOOL value) + { + STATIC_CONTRACT_WRAPPER; + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_DEBUGONLY,value); + return prevState; + } + + void ResetDebugOnly() + { + STATIC_CONTRACT_LIMITED_METHOD; + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_DEBUGONLY); + } + + //--// + BOOL IsGetThreadAllowed() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_ALLOWGETTHREAD); + + } + void SetGetThreadAllowed() + { + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_ALLOWGETTHREAD); + } + + + BOOL SetGetThreadAllowed(BOOL value) + { + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_ALLOWGETTHREAD); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_ALLOWGETTHREAD,value); + return prevState; + } + + void ResetGetThreadAllowed() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_ALLOWGETTHREAD); + } + + //--// + BOOL IsOkToLock() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK); + } + + void SetOkToLock() + { + CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_LOCK); + } + + BOOL SetOkToLock( BOOL value ) + { + BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK); + CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_LOCK, value); + return prevState; + } + + void ResetOkToLock() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_LOCK); + } + + //--// + BOOL IsOkToRetakeLock() + { + return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); + } + + void ResetOkToRetakeLock() + { + CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); + } + + + //--// + void LinkContractStackTrace( ContractStackRecord* pContractStackTrace ) + { + pContractStackTrace->m_pNext = m_pContractStackTrace; + + m_pContractStackTrace = pContractStackTrace; + } + + ContractStackRecord* GetContractStackTrace() + { + return m_pContractStackTrace; + } + + void SetContractStackTrace(ContractStackRecord* pContractStackTrace ) + { + m_pContractStackTrace = pContractStackTrace; + } + + //--// + + UINT GetGCNoTriggerCount() + { + return m_GCNoTriggerCount; + } + + void DecrementGCNoTriggerCount() + { + m_GCNoTriggerCount--; + } + + void IncrementGCNoTriggerCount() + { + m_GCNoTriggerCount++; + } + + + UINT GetGCForbidCount() + { + return m_GCForbidCount; + } + + void DecrementGCForbidCount() + { + m_GCForbidCount--; + } + + void IncrementGCForbidCount() + { + m_GCForbidCount++; + } + + UINT GetMaxLoadTypeLevel() + { + return m_maxLoadTypeLevel; + } + + void SetMaxLoadTypeLevel(UINT newLevel) + { + m_maxLoadTypeLevel = newLevel; + } + + //--// + + void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData) + { + m_LockState.SetDbgStateLockData(pDbgStateLockData); + } + + DbgStateLockData * GetDbgStateLockData() + { + return m_LockState.GetDbgStateLockData(); + } + + void OnEnterCannotRetakeLockFunction() + { + m_LockState.OnEnterCannotRetakeLockFunction(); + } + + void CheckOkayToLock(__in_z const char *szFunction, __in_z const char *szFile, int lineNum); // Asserts if its not okay to lock + BOOL CheckOkayToLockNoAssert(); // Returns if OK to lock + void LockTaken(DbgStateLockType dbgStateLockType, + UINT cEntrances, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, + int lineNum); + void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); + UINT GetLockCount(DbgStateLockType dbgStateLockType); + UINT GetCombinedLockCount(); +}; + +#endif // ENABLE_CONTRACTS + +#ifdef ENABLE_CONTRACTS_IMPL +// Create ClrDebugState. +// This routine is not allowed to return NULL. If it can't allocate the memory needed, +// it should return a pointer to a global static ClrDebugState that indicates +// that debug assertions should be skipped. +ClrDebugState *CLRInitDebugState(); +ClrDebugState *GetClrDebugState(BOOL fAlloc = TRUE); + + +// This function returns a ClrDebugState if one has been created, but will not create one itself. +inline ClrDebugState *CheckClrDebugState() +{ + STATIC_CONTRACT_LIMITED_METHOD; + ClrDebugState *ret = (ClrDebugState*)ClrFlsGetValue(TlsIdx_ClrDebugState); + return ret; +} + +void CONTRACT_ASSERT(const char *szElaboration, + UINT whichTest, + UINT whichTestMask, + const char *szFunction, + const char *szFile, + int lineNum + ); + +#endif + +// This needs to be defined up here b/c it is used by ASSERT_CHECK which is used by the contract impl +#ifdef _DEBUG +#ifdef ENTER_DEBUG_ONLY_CODE +#undef ENTER_DEBUG_ONLY_CODE +#endif +#ifdef LEAVE_DEBUG_ONLY_CODE +#undef LEAVE_DEBUG_ONLY_CODE +#endif + +#ifdef ENABLE_CONTRACTS_IMPL +// This can only appear in a debug function so don't define it non-debug +class DebugOnlyCodeHolder +{ +public: + // We use GetClrDebugState on entry, but CheckClrDebugState on Leave + // That way we make sure to create one if we need to set state, but + // we don't recreated one on exit if its been deleted. + DEBUG_NOINLINE void Enter() + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_DEBUG_ONLY; + + m_pClrDebugState = GetClrDebugState(); + if (m_pClrDebugState) + { + m_oldDebugOnlyValue = m_pClrDebugState->IsDebugOnly(); + m_pClrDebugState->SetDebugOnly(); + } + } + + DEBUG_NOINLINE void Leave() + { + SCAN_SCOPE_END; + STATIC_CONTRACT_DEBUG_ONLY; + + m_pClrDebugState = CheckClrDebugState(); + if (m_pClrDebugState) + { + m_pClrDebugState->SetDebugOnly( m_oldDebugOnlyValue ); + } + } + +private: +BOOL m_oldDebugOnlyValue; +ClrDebugState *m_pClrDebugState; +}; + +#define ENTER_DEBUG_ONLY_CODE \ + DebugOnlyCodeHolder __debugOnlyCodeHolder; \ + __debugOnlyCodeHolder.Enter(); + +#define LEAVE_DEBUG_ONLY_CODE \ + __debugOnlyCodeHolder.Leave(); + + +class AutoCleanupDebugOnlyCodeHolder : public DebugOnlyCodeHolder +{ +public: + DEBUG_NOINLINE AutoCleanupDebugOnlyCodeHolder() + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_DEBUG_ONLY; + + Enter(); + }; + + DEBUG_NOINLINE ~AutoCleanupDebugOnlyCodeHolder() + { + SCAN_SCOPE_END; + + Leave(); + }; +}; + +#define DEBUG_ONLY_FUNCTION \ + STATIC_CONTRACT_DEBUG_ONLY; \ + AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; + +#define DEBUG_ONLY_REGION() \ + AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; + + +#define BEGIN_DEBUG_ONLY_CODE \ + { \ + AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; + +#define END_DEBUG_ONLY_CODE \ + } + +#else // ENABLE_CONTRACTS_IMPL +#define DEBUG_ONLY_FUNCTION STATIC_CONTRACT_DEBUG_ONLY +#define DEBUG_ONLY_REGION() +#define BEGIN_DEBUG_ONLY_CODE +#define END_DEBUG_ONLY_CODE +#define ENTER_DEBUG_ONLY_CODE +#define LEAVE_DEBUG_ONLY_CODE +#endif + +#else // _DEBUG +#define DEBUG_ONLY_REGION() +#endif + + +#ifdef ENABLE_CONTRACTS_IMPL + +// These helpers encapsulate our access to our FLS debug state. To improve +// contract perf, we'll soon move these to a private alloced block +// so we can reuse the pointer instead of constantly refetching it. +// Thus, these helpers are just to bridge this transition. +inline LPVOID GetViolationMask() +{ + ClrDebugState *pState = CheckClrDebugState(); + if (pState) + { + return (LPVOID)pState->ViolationMask(); + } + else + { + return 0; + } +} + +// This is the default binding of the MAYBETEMPLATE identifier, +// used in the RETURN macro +template +class ___maybetemplate +{ + public: + FORCEINLINE void *operator new (size_t size) + { + return NULL; + } +}; + +// This is an abstract base class for contracts. The main reason we have this is so that the dtor for many derived class can +// be performant. If this class was not abstract and had a dtor, then the dtor for the derived class adds EH overhead (even if the derived +// class did not anything special in its dtor) +class BaseContract +{ + // Really private, but used by macros + public: + + // We use a single integer to specify all the settings for intrinsic tests + // such as THROWS and GC_TRIGGERS. The compiler should be able to fold all + // these clauses into a single constant. + // + // The value "0" is significant as this is what the entire mask will be initialized to + // in the absence of any clauses. Hence, whichever value is assigned "0" will be the + // default setting for the test. + // + // Also, there must be a "disabled" setting for each category in order to support + // the DISABLED macro. + enum TestEnum + { + THROWS_Mask = 0x00000003, + THROWS_Yes = 0x00000000, // the default + THROWS_No = 0x00000001, + THROWS_Disabled = 0x00000002, + + GC_Mask = 0x0000000C, + GC_Triggers = 0x00000000, // the default + GC_NoTrigger = 0x00000004, + GC_Disabled = 0x00000008, + + FAULT_Mask = 0x00000030, + FAULT_Disabled = 0x00000000, // the default + FAULT_Inject = 0x00000010, + FAULT_Forbid = 0x00000020, + + MODE_Mask = 0x000000C0, + MODE_Disabled = 0x00000000, // the default + MODE_Preempt = 0x00000040, + MODE_Coop = 0x00000080, + + DEBUG_ONLY_Yes = 0x00000400, // code runs under debug only + + SO_MAINLINE_No = 0x00000800, // code is not part of our mainline SO scenario + + // Any place where we can't safely call into the host should have a HOST_NoCalls contract + HOST_Mask = 0x00003000, + HOST_Calls = 0x00002000, + HOST_NoCalls = 0x00001000, + HOST_Disabled = 0x00000000, // the default + + // This enforces the EE_THREAD_NOT_REQUIRED contract by clearing + // ClrDebugState::m_allowGetThread in its scope. That causes raw calls + // to GetThread() to assert, unless inside a temporary "don't worry it's ok" scope + // via BEGIN/END_GETTHREAD_ALLOWED. Useful for enforcing our docs that + // state certain unmanaged API entrypoints (e.g., some from profiling API) + // are callable without an EE Thread in TLS. + EE_THREAD_Mask = 0x0000C000, + EE_THREAD_Disabled = 0x00000000, // the default + EE_THREAD_Required = 0x00004000, + EE_THREAD_Not_Required = 0x00008000, + + // These enforce the CAN_TAKE_LOCK / CANNOT_TAKE_LOCK contracts + CAN_TAKE_LOCK_Mask = 0x00060000, + CAN_TAKE_LOCK_Yes = 0x00020000, + CAN_TAKE_LOCK_No = 0x00040000, + CAN_TAKE_LOCK_Disabled = 0x00000000, // the default + + // These enforce the CANNOT_RETAKE_LOCK contract + CAN_RETAKE_LOCK_No = 0x00080000, + CAN_RETAKE_LOCK_No_Disabled = 0x00000000, // the default + + PRECONDITION_Used = 0x00010000, // a PRECONDITION appeared inside the contract + + // IMPORTANT!!! LOADS_TYPE_Mask and LOADS_TYPE_Shift must be kept in sync. + LOADS_TYPE_Mask = 0x00f00000, // the max loadstype level + 1 ("+1" because 0 is reserved for the default which is "disabled") + LOADS_TYPE_Shift = 20, // # of bits to right-shift to get loadstype bits to rightmost position. + LOADS_TYPE_Disabled = 0x00000000, // the default + + ALL_Disabled = THROWS_Disabled|GC_Disabled|FAULT_Disabled|MODE_Disabled|LOADS_TYPE_Disabled| + HOST_Disabled|EE_THREAD_Disabled|CAN_TAKE_LOCK_Disabled|CAN_RETAKE_LOCK_No_Disabled + + }; + + enum Operation + { + Setup = 0x01, + Preconditions = 0x02, + Postconditions = 0x04, + }; + + + NOTHROW_DECL BaseContract() : m_pClrDebugState(NULL), m_testmask(0) + { + } + NOTHROW_DECL void Restore() + { + // m_pClrDebugState is setup in BaseContract::DoChecks. If an SO happens after the + // BaseContract object is constructed but before DoChecks is invoked, m_pClrDebugState + // will remain NULL (which is what it is set to in the BaseContract ctor). + // + // Thus, we should check for it being NULL before dereferencing it. + if (m_pClrDebugState) + { + // Backout all changes to debug state. + *m_pClrDebugState = m_IncomingClrDebugState; + } + } + + void DoChecks(UINT testmask, __in_z const char *szFunction, __in_z const char *szFile, int lineNum); + void Disable() + { + } + BOOL CheckFaultInjection(); + + protected: + UINT m_testmask; + // Override this function in any derived class to indicate that you have defined a destructor for that class + // and that dtor calls Restore() + virtual void DestructorDefinedThatCallsRestore() = 0; + + + protected: + ClrDebugState *m_pClrDebugState; + ClrDebugState m_IncomingClrDebugState; + + ContractStackRecord m_contractStackRecord; + + public: + // -------------------------------------------------------------------------------- + // These classes and declarations are used to implement our fake return keyword. + // -------------------------------------------------------------------------------- + + // ___box is used to protect the "detected" return value from being combined with other parts + // of the return expression after we have processed it. This can happen if the return + // expression is a non-parenthesized expression with an operator of lower precedence than + // ">". + // + // If you have such a case (and see this class listed in an error message), + // parenthesize your return value expression. + template + class Box__USE_PARENS_WITH_THIS_EXPRESSION + { + const T &value; + + public: + + FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION(const T &value) + : value(value) + { + } + + FORCEINLINE const T& Unbox() + { + return value; + } + }; + + // PseudoTemplate is a class which can be instantated with a template-like syntax, resulting + // in an expression which simply boxes a following value in a Box + + template + class PseudoTemplate + { + public: + FORCEINLINE void *operator new (size_t size) + { + return NULL; + } + + FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION operator>(const T &value) + { + return Box__USE_PARENS_WITH_THIS_EXPRESSION(value); + } + + FORCEINLINE PseudoTemplate operator<(int dummy) + { + return PseudoTemplate(); + } + }; + + // Returner is used to assign the return value to the RETVAL local. Note the use of + // operator , because of its low precedence. + + template + class Returner + { + RETURNTYPE &m_value; + BOOL m_got; + public: + + FORCEINLINE Returner(RETURNTYPE &value) + : m_value(value), + m_got(FALSE) + { + } + + template + FORCEINLINE RETURNTYPE operator,(Box__USE_PARENS_WITH_THIS_EXPRESSION value) + { + m_value = value.Unbox(); + m_got = TRUE; + return m_value; + } + + FORCEINLINE void operator,(___maybetemplate<0> &dummy) + { + m_got = TRUE; + } + + FORCEINLINE BOOL GotReturn() + { + return m_got; + } + }; + + // This type ensures that postconditions were run via RETURN or RETURN_VOID + class RanPostconditions + { + public: + bool ran; + int count; + const char *function; + + FORCEINLINE RanPostconditions(const char *function) + : ran(false), + count(0), + function(function) + { + } + + FORCEINLINE int operator++() + { + return ++count; + } + + FORCEINLINE ~RanPostconditions() + { + // Note: __uncaught_exception() is not a perfect check. It will return TRUE during any exception + // processing. So, if there is a contract called from an exception filter (like our + // COMPlusFrameHandler) then it will return TRUE and the saftey check below will not be performed. + if (!__uncaught_exception()) + ASSERT_CHECK(count == 0 || ran, function, "Didn't run postconditions - be sure to use RETURN at the end of the function"); + } + + }; + + // Set contract enforcement level + static void SetUnconditionalContractEnforcement(BOOL enforceUnconditionally); + + // Check contract enforcement + static BOOL EnforceContract(); + + private: + static BOOL s_alwaysEnforceContracts; +}; + +class Contract: public BaseContract +{ + // Have to override this function in any derived class to indicate that a valid destructor is defined for this class + virtual void DestructorDefinedThatCallsRestore(){} + + public: + NOTHROW_DECL ~Contract() + { + Restore(); + } +}; + +#endif // ENABLE_CONTRACTS_IMPL + + +#ifdef _DEBUG + +// Valid parameters for CONTRACT_VIOLATION macro +enum ContractViolationBits +{ + ThrowsViolation = 0x00000001, // suppress THROW tags in this scope + GCViolation = 0x00000002, // suppress GCTRIGGER tags in this scope + ModeViolation = 0x00000004, // suppress MODE_PREEMP and MODE_COOP tags in this scope + FaultViolation = 0x00000008, // suppress INJECT_FAULT assertions in this scope + FaultNotFatal = 0x00000010, // suppress INJECT_FAULT but not fault injection by harness + LoadsTypeViolation = 0x00000040, // suppress LOADS_TYPE tags in this scope + TakesLockViolation = 0x00000080, // suppress CAN_TAKE_LOCK tags in this scope + HostViolation = 0x00000100, // suppress HOST_CALLS tags in this scope + EEThreadViolation = 0x00000200, // suppress EE_THREAD_REQUIRED tags in this scope + + //These are not violation bits. We steal some bits out of the violation mask to serve as + // general flag bits. + CanFreeMe = 0x00010000, // If this bit is ON, the ClrDebugState was allocated by + // a version of utilcode that registers an Fls Callback to free + // the state. If this bit is OFF, the ClrDebugState was allocated + // by an old version of utilcode that doesn't. (And you can't + // assume that the old utilcode used the same allocator as the new utilcode.) + // (Most likely, this is because you are using an older shim with + // a newer mscorwks.dll) + // + // The Fls callback must only attempt to free debugstates that + // have this bit on. + + BadDebugState = 0x00020000, // If we OOM creating the ClrDebugState, we return a pointer to + // a static ClrDebugState that has this bit turned on. (We don't + // want to slow down contracts with null tests everywhere.) + // Other than this specific bit, all other fields of the DebugState + // must be considered trash. You can stomp on them and you can bit-test them + // but you can't throw up any asserts based on them and you certainly + // can't deref any pointers stored in the bad DebugState. + + AllViolation = 0xFFFFFFFF, +}; + +#endif + +#ifdef ENABLE_CONTRACTS_IMPL + +// Global variables allow PRECONDITION and POSTCONDITION to be used outside contracts +static const BaseContract::Operation ___op = (Contract::Operation) (Contract::Preconditions + |Contract::Postconditions); +enum { + ___disabled = 0 +}; + +static UINT ___testmask; + +// End of global variables + +static int ___ran; + +class __SafeToUsePostCondition { +public: + static int safe_to_use_postcondition() {return 0;}; +}; + +class __YouCannotUseAPostConditionHere { +private: + static int safe_to_use_postcondition() {return 0;}; +}; + +typedef __SafeToUsePostCondition __PostConditionOK; + +// Uncomment the following line to disable runtime contracts completely - PRE/POST conditions will still be present +//#define __FORCE_NORUNTIME_CONTRACTS__ 1 + +#ifndef __FORCE_NORUNTIME_CONTRACTS__ + +#define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \ + _returntype RETVAL; \ + _contracttype ___contract; \ + Contract::Returner<_returntype> ___returner(RETVAL); \ + Contract::RanPostconditions ___ran(__FUNCTION__); \ + Contract::Operation ___op = Contract::Setup; \ + BOOL ___contract_enabled = FALSE; \ + DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ + ___contract_enabled = Contract::EnforceContract(); \ + enum {___disabled = 0}; \ + if (!___contract_enabled) \ + ___contract.Disable(); \ + else \ + { \ + enum { ___CheckMustBeInside_CONTRACT = 1 }; \ + if (0) \ + { \ + /* If you see an "unreferenced label" warning with this name, */\ + /* Be sure that you have a RETURN at the end of your */ \ + /* CONTRACT_VOID function */ \ + ___run_postconditions_DID_YOU_FORGET_A_RETURN: \ + if (___contract_enabled) \ + { \ + ___op = Contract::Postconditions; \ + ___ran.ran = true; \ + } \ + else \ + { \ + DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \ + ___run_return: \ + return _returnexp; \ + DEBUG_OK_TO_RETURN_END(CONTRACT) \ + } \ + } \ + if (0) \ + { \ + ___run_preconditions: \ + ___op = Contract::Preconditions; \ + } \ + UINT ___testmask = 0; \ + +#define CONTRACTL_SETUP(_contracttype) \ + _contracttype ___contract; \ + BOOL ___contract_enabled = Contract::EnforceContract(); \ + enum {___disabled = 0}; \ + if (!___contract_enabled) \ + ___contract.Disable(); \ + else \ + { \ + typedef __YouCannotUseAPostConditionHere __PostConditionOK; \ + enum { ___CheckMustBeInside_CONTRACT = 1 }; \ + Contract::Operation ___op = Contract::Setup; \ + enum {___disabled = 0}; \ + if (0) \ + { \ + ___run_preconditions: \ + ___op = Contract::Preconditions; \ + } \ + if (0) \ + { \ + /* define for CONTRACT_END even though we can't get here */ \ + ___run_return: \ + UNREACHABLE(); \ + } \ + UINT ___testmask = 0; \ + +#else // #ifndef __FORCE_NORUNTIME_CONTRACTS__ + +#define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \ + _returntype RETVAL; \ + Contract::Returner<_returntype> ___returner(RETVAL); \ + Contract::RanPostconditions ___ran(__FUNCTION__); \ + Contract::Operation ___op = Contract::Setup; \ + DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ + BOOL ___contract_enabled = Contract::EnforceContract(); \ + enum {___disabled = 0}; \ + { \ + enum { ___CheckMustBeInside_CONTRACT = 1 }; \ + if (0) \ + { \ + /* If you see an "unreferenced label" warning with this name, */\ + /* Be sure that you have a RETURN at the end of your */ \ + /* CONTRACT_VOID function */ \ + ___run_postconditions_DID_YOU_FORGET_A_RETURN: \ + if (___contract_enabled) \ + { \ + ___op = Contract::Postconditions; \ + ___ran.ran = true; \ + } \ + else \ + { \ + DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \ + ___run_return: \ + return _returnexp; \ + DEBUG_OK_TO_RETURN_END(CONTRACT) \ + } \ + } \ + if (0) \ + { \ + ___run_preconditions: \ + ___op = Contract::Preconditions; \ + } \ + UINT ___testmask = 0; \ + + + + +#define CONTRACTL_SETUP(_contracttype) \ + BOOL ___contract_enabled = Contract::EnforceContract(); \ + enum {___disabled = 0}; \ + { \ + typedef __YouCannotUseAPostConditionHere __PostConditionOK; \ + enum { ___CheckMustBeInside_CONTRACT = 1 }; \ + Contract::Operation ___op = Contract::Setup; \ + enum {___disabled = 0}; \ + if (0) \ + { \ + ___run_preconditions: \ + ___op = Contract::Preconditions; \ + } \ + if (0) \ + { \ + /* define for CONTRACT_END even though we can't get here */ \ + ___run_return: \ + UNREACHABLE(); \ + } \ + UINT ___testmask = 0; \ + +#endif // __FORCE_NORUNTIME_CONTRACTS__ + + +#define CUSTOM_CONTRACT(_contracttype, _returntype) \ + typedef Contract::PseudoTemplate<_returntype> ___maybetemplate; \ + CONTRACT_SETUP(_contracttype, _returntype, RETVAL) + +#define CUSTOM_CONTRACT_VOID(_contracttype) \ + CONTRACT_SETUP(_contracttype, int, ;) + +#define CUSTOM_CONTRACTL(_contracttype) \ + CONTRACTL_SETUP(_contracttype) + +// Although this thing only needs to run in the Setup phase, we'll let it +// run unconditionally. This way, the compiler will see a sequence like this: +// +// THROWS; GC_TRIGGERS; FORBID_FAULT ==> +// +// ___testmask |= constant +// ___testmask |= constant +// ___testmask |= constant +// +// and be able to fold all these into a single constant at runtime. +// +#define REQUEST_TEST(thetest, todisable) (___testmask |= (___CheckMustBeInside_CONTRACT, (___disabled ? (todisable) : (thetest)))) + + +#define INJECT_FAULT(_statement) \ + do \ + { \ + STATIC_CONTRACT_FAULT; \ + REQUEST_TEST(Contract::FAULT_Inject, Contract::FAULT_Disabled); \ + if (0) \ + { \ + _statement; \ + } \ + } \ + while(0) \ + + +#define FORBID_FAULT do { STATIC_CONTRACT_FORBID_FAULT; REQUEST_TEST(Contract::FAULT_Forbid, Contract::FAULT_Disabled); } while(0) + +#define THROWS do { STATIC_CONTRACT_THROWS; REQUEST_TEST(Contract::THROWS_Yes, Contract::THROWS_Disabled); } while(0) + +#define NOTHROW do { STATIC_CONTRACT_NOTHROW; REQUEST_TEST(Contract::THROWS_No, Contract::THROWS_Disabled); } while(0) \ + +#define ENTRY_POINT STATIC_CONTRACT_ENTRY_POINT + +#define LOADS_TYPE(maxlevel) do { REQUEST_TEST( ((maxlevel) + 1) << Contract::LOADS_TYPE_Shift, Contract::LOADS_TYPE_Disabled ); } while(0) + +#define CAN_TAKE_LOCK do { STATIC_CONTRACT_CAN_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_Yes, Contract::CAN_TAKE_LOCK_Disabled); } while(0) + +#define CANNOT_TAKE_LOCK do { STATIC_CONTRACT_CANNOT_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_No, Contract::CAN_TAKE_LOCK_Disabled); } while(0) + +#define CANNOT_RETAKE_LOCK do { REQUEST_TEST(Contract::CAN_RETAKE_LOCK_No, Contract::CAN_RETAKE_LOCK_No_Disabled); } while(0) + +#define DEBUG_ONLY do { STATIC_CONTRACT_DEBUG_ONLY; REQUEST_TEST(Contract::DEBUG_ONLY_Yes, 0); } while (0) + +#ifndef __DISABLE_PREPOST_CONDITIONS__ +#define PRECONDITION_MSG(_expression, _message) \ + do \ + { \ + enum { ___CheckMustBeInside_CONTRACT = 1 }; \ + REQUEST_TEST(Contract::PRECONDITION_Used, 0); \ + if ((___op&Contract::Preconditions) && !___disabled) \ + ASSERT_CHECK(_expression, _message, "Precondition failure"); \ + } \ + while(0) + + +#define PRECONDITION(_expression) \ + PRECONDITION_MSG(_expression, NULL) + +#define POSTCONDITION_MSG(_expression, _message) \ + ++___ran; \ + if ((!(0 && __PostConditionOK::safe_to_use_postcondition())) && \ + (___op&Contract::Postconditions) && \ + !___disabled) \ + { \ + ASSERT_CHECK(_expression, _message, "Postcondition failure"); \ + } + +#define POSTCONDITION(_expression) \ + POSTCONDITION_MSG(_expression, NULL) + +#define INSTANCE_CHECK \ + ___CheckMustBeInside_CONTRACT; \ + if ((___op&Contract::Preconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure"); \ + ++___ran; \ + if ((___op&Contract::Postconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure"); + +#define INSTANCE_CHECK_NULL \ + ___CheckMustBeInside_CONTRACT; \ + if ((___op&Contract::Preconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance precheck failure"); \ + ++___ran; \ + if ((___op&Contract::Postconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance postcheck failure"); + +#define CONSTRUCTOR_CHECK \ + ___CheckMustBeInside_CONTRACT; \ + ++___ran; \ + if ((___op&Contract::Postconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure"); + +#define DESTRUCTOR_CHECK \ + ___CheckMustBeInside_CONTRACT; \ + NOTHROW; \ + if ((___op&Contract::Preconditions) && !___disabled) \ + ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure"); +#else // __DISABLE_PREPOST_CONDITIONS__ + + +#define PRECONDITION_MSG(_expression, _message) do { } while(0) +#define PRECONDITION(_expression) do { } while(0) +#define POSTCONDITION_MSG(_expression, _message) do { } while(0) +#define POSTCONDITION(_expression) do { } while(0) +#define INSTANCE_CHECK +#define INSTANCE_CHECK_NULL +#define CONSTRUCTOR_CHECK +#define DESTRUCTOR_CHECK + +#endif // __DISABLE_PREPOST_CONDITIONS__ + +#define UNCHECKED(thecheck) \ + do { \ + ANNOTATION_UNCHECKED(thecheck); \ + enum {___disabled = 1 }; \ + thecheck; \ + } while(0) + +#define DISABLED(thecheck) UNCHECKED(thecheck) + +#define WRAPPER(thecheck) UNCHECKED(thecheck) + +// This keyword is redundant but it's handy for reducing the nuisance editing you +// have to when repeatedly enabling and disabling contract items while debugging. +// You shouldn't check in code that explicitly uses ENABLED. +#define ENABLED(_check) _check + + +#ifndef __FORCE_NORUNTIME_CONTRACTS__ +#define CONTRACTL_END \ + if (___op & Contract::Setup) \ + { \ + ___contract.DoChecks(___testmask, __FUNCTION__, __FILE__, __LINE__); \ + if (___testmask & Contract::PRECONDITION_Used) \ + { \ + goto ___run_preconditions; \ + } \ + } \ + else if (___op & Contract::Postconditions) \ + { \ + goto ___run_return; \ + } \ + ___CheckMustBeInside_CONTRACT; \ + } + +#else + +#define CONTRACTL_END \ + if (___op & Contract::Setup) \ + { \ + if (___testmask & Contract::PRECONDITION_Used) \ + { \ + goto ___run_preconditions; \ + } \ + } \ + else if (___op & Contract::Postconditions) \ + { \ + goto ___run_return; \ + } \ + ___CheckMustBeInside_CONTRACT; \ + } \ + +#endif // __FORCE_NORUNTIME_CONTRACTS__ + +#define CONTRACT_END CONTRACTL_END \ + DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \ + + +// The final expression in the RETURN macro deserves special explanation (or something.) +// The expression is constructed so as to be syntactically ambiguous, depending on whether +// __maybetemplate is a template or not. If it is a template, the expression is syntactically +// correct as-is. If it is not, the angle brackets are interpreted as +// less than & greater than, and the expression is incomplete. This is the point - we can +// choose whether we need an expression or not based on the context in which the macro is used. +// This allows the same RETURN macro to be used both in value-returning and void-returning +// contracts. +// +// The "__returner ," portion of the expression is used instead of "RETVAL =", since "," +// has lower precedence than "=". (Ain't overloaded operators fun.) +// +// Also note that the < and > operators on the non-template version of __maybetemplate +// are overridden to "box" the return value in a special type and pass it +// through to the __returner's "," operator. This is so we can detect a case where an +// operator with lower precedence than ">" is in the return expression - in such a case we +// will get a type error message, which instructs that parens be placed around the return +// value expression. + +#define RETURN_BODY \ + if (___returner.GotReturn()) \ + goto ___run_postconditions_DID_YOU_FORGET_A_RETURN; \ + else \ + ___returner, * new ___maybetemplate < 0 > + + +// We have two versions of the RETURN macro. CONTRACT_RETURN is for use inside the CONTRACT +// scope where it is OK to return this way, even though the CONTRACT macro itself does not +// allow a return. RETURN is for use inside the function body where it might not be OK +// to return and we need to ensure that we don't allow a return where one should not happen +// +#define RETURN \ + while (DEBUG_ASSURE_SAFE_TO_RETURN, TRUE) \ + RETURN_BODY \ + +#define RETURN_VOID \ + RETURN + +#define CONTRACT_RETURN \ + while (___CheckMustBeInside_CONTRACT, TRUE) \ + RETURN_BODY \ + +#define CONTRACT_RETURN_VOID \ + CONTRACT_RETURN \ + +#if 0 +#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ + { \ + _contracttype ___contract; \ + STATIC_CONTRACT_LEAF; \ + ___contract.DoChecks(Contract::THROWS_No|Contract::GC_NoTrigger|Contract::MODE_Disabled|Contract::FAULT_Disabled); \ + /* Should add some assertion mechanism to ensure no other contracts are called */ \ + } +#else +#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ + { \ + STATIC_CONTRACT_LEAF; \ + } +#endif + +#define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \ + { \ + /* Should add some assertion mechanism to ensure one other contract is called */ \ + STATIC_CONTRACT_WRAPPER; \ + } + +#define CONTRACT_THROWS() \ + { \ + ::GetClrDebugState()->CheckOkayToThrow(__FUNCTION__, __FILE__, __LINE__); \ + } + +#define CONTRACT_THROWSEX(__func, __file, __line) \ + { \ + ::GetClrDebugState()->CheckOkayToThrow(__func, __file, __line); \ + } + +#else // ENABLE_CONTRACTS_IMPL +#define CUSTOM_CONTRACT(_contracttype, _returntype) if (0) { struct YouCannotUseThisHere { int x; }; // This temporary typedef allows retail use of +#define CUSTOM_CONTRACT_VOID(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // FORBIDGC_LOADER_USE_ENABLED +#define CUSTOM_CONTRACTL(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // inside contracts and asserts but nowhere else. + +#define INJECT_FAULT(_statement) +#define FORBID_FAULT +#define THROWS +#define NOTHROW +#define CAN_TAKE_LOCK +#define CANNOT_TAKE_LOCK +#define CANNOT_RETAKE_LOCK +#define LOADS_TYPE(maxlevel) +#define ENTRY_POINT + +#ifdef _DEBUG +// This can only appear in a debug function so don't define it non-debug +#define DEBUG_ONLY STATIC_CONTRACT_DEBUG_ONLY +#else +#define DEBUG_ONLY +#endif + +#define PRECONDITION_MSG(_expression, _message) do { } while(0) +#define PRECONDITION(_expression) do { } while(0) +#define POSTCONDITION_MSG(_expression, _message) do { } while(0) +#define POSTCONDITION(_expression) do { } while(0) +#define INSTANCE_CHECK +#define INSTANCE_CHECK_NULL +#define CONSTRUCTOR_CHECK +#define DESTRUCTOR_CHECK +#define UNCHECKED(thecheck) +#define DISABLED(thecheck) +#define WRAPPER(thecheck) +#define ENABLED(_check) +#define CONTRACT_END } +#define CONTRACTL_END } + +#define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ + { \ + /* Should add some assertion mechanism to ensure one other contract is called */ \ + STATIC_CONTRACT_LEAF; \ + } +#define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \ + { \ + /* Should add some assertion mechanism to ensure one other contract is called */ \ + STATIC_CONTRACT_WRAPPER; \ + } + + +#define RETURN return +#define RETURN_VOID RETURN + +#define CONTRACT_THROWS() +#define CONTRACT_THROWSEX(__func, __file, __line) + +#endif // ENABLE_CONTRACTS_IMPL + + +#define CONTRACT(_returntype) CUSTOM_CONTRACT(Contract, _returntype) +#define CONTRACT_VOID CUSTOM_CONTRACT_VOID(Contract) +#define CONTRACTL CUSTOM_CONTRACTL(Contract) + +// See description near the top of the file +#define LIMITED_METHOD_CONTRACT CUSTOM_LIMITED_METHOD_CONTRACT(Contract) + +#define WRAPPER_NO_CONTRACT CUSTOM_WRAPPER_NO_CONTRACT(Contract) + +// GC_NOTRIGGER allowed but not currently enforced at runtime +#define GC_NOTRIGGER STATIC_CONTRACT_GC_NOTRIGGER +#define GC_TRIGGERS static_assert(false, "TriggersGC not supported in utilcode contracts") + +#ifdef ENABLE_CONTRACTS_IMPL +template +class ContractViolationHolder +{ +public: + ContractViolationHolder() + { + m_pviolationmask = NULL; + m_oldviolationmask = 0; + } + + DEBUG_NOINLINE void Enter(); + + DEBUG_NOINLINE void Leave() + { + SCAN_SCOPE_END; + LeaveInternal(); + }; + +protected: + // We require that violationMask is passed as a parameter here to hopefully defeat the + // compiler's desire to fold all the Enter and Ctor implementations together. + FORCEINLINE void EnterInternal(UINT_PTR violationMask) + { + _ASSERTE(0 == (violationMask & ~(ThrowsViolation | GCViolation | ModeViolation | FaultViolation | + FaultNotFatal | HostViolation | + TakesLockViolation | LoadsTypeViolation)) || + violationMask == AllViolation); + + m_pviolationmask = GetClrDebugState()->ViolationMaskPtr(); + m_oldviolationmask = *m_pviolationmask; + *m_pviolationmask = (m_oldviolationmask | violationMask); + }; + + FORCEINLINE void LeaveInternal() + { + // This can be used in places where our debug state has been destroyed, so check for it first. + if (CheckClrDebugState()) + { + _ASSERTE(m_pviolationmask != NULL); + *m_pviolationmask = m_oldviolationmask; + } + }; + + UINT_PTR *m_pviolationmask; + UINT_PTR m_oldviolationmask; +}; + +template +class AutoCleanupContractViolationHolder : ContractViolationHolder +{ +public: + DEBUG_NOINLINE AutoCleanupContractViolationHolder(BOOL fEnterViolation = TRUE); + + DEBUG_NOINLINE ~AutoCleanupContractViolationHolder() + { + SCAN_SCOPE_END; + this->LeaveInternal(); + }; +}; + +#endif // ENABLE_CONTRACTS_IMPL + +#ifdef ENABLE_CONTRACTS_IMPL +#define BEGIN_CONTRACT_VIOLATION(violationmask) \ + { \ + ContractViolationHolder __violationHolder_onlyOneAllowedPerScope; \ + __violationHolder_onlyOneAllowedPerScope.Enter(); \ + DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ + +// Use this to jump out prematurely from a violation. Used for EH +// when the function might not return +#define RESET_CONTRACT_VIOLATION() \ + __violationHolder_onlyOneAllowedPerScope.Leave(); \ + +#define END_CONTRACT_VIOLATION \ + DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \ + __violationHolder_onlyOneAllowedPerScope.Leave(); \ + } \ + +// See description near the top of the file +#define CONTRACT_VIOLATION(violationMask) \ + AutoCleanupContractViolationHolder __violationHolder_onlyOneAllowedPerScope; + + +// Reasons for having the violation. Use one of these values as an additional parameter to +// E.g. PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonContractInfrastructure) +// New values and explanations can be added when needed. +enum PermanentContractViolationReason +{ + ReasonContractInfrastructure, // This violation is there for contract test or infrastructure purposes. + ReasonDebugOnly, // Code path doesn't occur on retail builds + ReasonNonShippingCode, // Code runs in undocumented non-shipping feature + ReasonIBC, // Code runs in IBC scenarios only and the violation is safe. + ReasonNGEN, // Code runs in NGEN scenarios only and the violation is safe. + ReasonProfilerCallout, // Profiler implementers are guaranteed not to throw. + ReasonUnsupportedForSQLF1Profiling, // This code path violates HOST_NOCALLS, but that's ok b/c SQL will never + // invoke it, and thus SQL/F1 profiling (the primary reason to enforce + // HOST_NOCALLS) is not in danger. + ReasonRuntimeReentrancy, // e.g. SafeQueryInterface + ReasonShutdownOnly, // Code path only runs as part of Shutdown and the violation is safe. + ReasonSOTolerance, // We would like to redesign SO contracts anyways + ReasonStartupOnly, // Code path only runs as part of Startup and the violation is safe. + ReasonWorkaroundForScanBug, // Violation is needed because of a bug in SCAN + ReasonProfilerAsyncCannotRetakeLock, // Profiler may call this from redirected thread, causing a CANNOT_TAKE_LOCK + // violation, but the scope is still protected with CANNOT_RETAKE_LOCK + ReasonILStubWillNotThrow, // Specially-crafted reverse COM IL stubs will not throw +}; + +// See the discussion near the top of the file on the use of PERMANENT_CONTRACT_VIOLATION +// The reasonEnum is currently only used for documentation and searchability. Here +// we have the compiler check for a typo. +#define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum) \ + if (0) \ + PermanentContractViolationReason reason = reasonEnum; \ + CONTRACT_VIOLATION(violationMask) + +#define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition) \ + AutoCleanupContractViolationHolder __violationHolder_onlyOneAllowedPerScope((condition)); + +#else +#define BEGIN_CONTRACT_VIOLATION(violationmask) +#define RESET_CONTRACT_VIOLATION() +#define END_CONTRACT_VIOLATION +#define CONTRACT_VIOLATION(violationmask) +#define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition) +#define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum) +#endif + + + +#ifdef ENABLE_CONTRACTS_IMPL +// Holder for setting up a faultforbid region +class FaultForbidHolder +{ + public: + DEBUG_NOINLINE FaultForbidHolder(BOOL fConditional, BOOL fAlloc, const char *szFunction, const char *szFile, int lineNum) + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_FORBID_FAULT; + + m_fConditional = fConditional; + if (m_fConditional) + { + m_pClrDebugState = GetClrDebugState(fAlloc); + + // + // If we fail to get a debug state, then we must not be allocating and + // we simply no-op this holder. + // + if (m_pClrDebugState == NULL) + { + _ASSERTE(!fAlloc); + m_fConditional = FALSE; + return; + } + + m_oldClrDebugState = *m_pClrDebugState; + + m_pClrDebugState->ViolationMaskReset( FaultViolation|FaultNotFatal ); + m_pClrDebugState->SetFaultForbid(); + + m_ContractStackRecord.m_szFunction = szFunction; + m_ContractStackRecord.m_szFile = szFile; + m_ContractStackRecord.m_lineNum = lineNum; + m_ContractStackRecord.m_testmask = (Contract::ALL_Disabled & ~((UINT)(Contract::FAULT_Mask))) | Contract::FAULT_Forbid; + m_ContractStackRecord.m_construct = "FAULT_FORBID"; + m_pClrDebugState->LinkContractStackTrace( &m_ContractStackRecord ); + } + } + + DEBUG_NOINLINE ~FaultForbidHolder() + { + SCAN_SCOPE_END; + + if (m_fConditional) + { + *m_pClrDebugState = m_oldClrDebugState; + } + } + + private: + ClrDebugState *m_pClrDebugState; + ClrDebugState m_oldClrDebugState; + BOOL m_fConditional; + ContractStackRecord m_ContractStackRecord; + +}; +#endif // ENABLE_CONTRACTS_IMPL + + +#ifdef ENABLE_CONTRACTS_IMPL + +#define FAULT_FORBID() FaultForbidHolder _ffh(TRUE, TRUE, __FUNCTION__, __FILE__, __LINE__); +#define FAULT_FORBID_NO_ALLOC() FaultForbidHolder _ffh(TRUE, FALSE, __FUNCTION__, __FILE__, __LINE__); +#define MAYBE_FAULT_FORBID(cond) FaultForbidHolder _ffh(cond, TRUE, __FUNCTION__, __FILE__, __LINE__); +#define MAYBE_FAULT_FORBID_NO_ALLOC(cond) FaultForbidHolder _ffh(cond, FALSE, __FUNCTION__, __FILE__, __LINE__); + +#else // ENABLE_CONTRACTS_IMPL + +#define FAULT_FORBID() ; +#define FAULT_FORBID_NO_ALLOC() ; +#define MAYBE_FAULT_FORBID(cond) ; +#define MAYBE_FAULT_FORBID_NO_ALLOC(cond) ; + +#endif // ENABLE_CONTRACTS_IMPL + + +#ifdef ENABLE_CONTRACTS_IMPL + +inline BOOL AreFaultsForbiddenHelper() +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + + ClrDebugState *pClrDebugState = CheckClrDebugState(); + if (!pClrDebugState) + { + // By default, faults are not forbidden. Not the most desirable default + // but we'd never get this debug infrastructure bootstrapped otherwise. + return FALSE; + } + else + { + return pClrDebugState->IsFaultForbid() && (!(pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState))); + } +} + +#define ARE_FAULTS_FORBIDDEN() AreFaultsForbiddenHelper() +#else + +// If you got an error about ARE_FAULTS_FORBIDDEN being undefined, it's because you tried +// to use this predicate in a free build outside of a CONTRACT or ASSERT. +// +#define ARE_FAULTS_FORBIDDEN() (sizeof(YouCannotUseThisHere) != 0) +#endif + + +// This allows a fault-forbid region to invoke a non-mandatory allocation, such as for the +// purpose of growing a lookaside cache (if the allocation fails, the code can abandon the +// cache growing operation without negative effect.) +// +// Although it's implemented using CONTRACT_VIOLATION(), it's not a bug to have this in the code. +// +// It *is* a bug to use this to hide a situation where an OOM is genuinely fatal but not handled. +#define FAULT_NOT_FATAL() CONTRACT_VIOLATION(FaultNotFatal) + + + +#ifdef ENABLE_CONTRACTS_IMPL + +//------------------------------------------------------------------------------------ +// Underlying class support for TRIGGERS_TYPE_LOAD and OVERRIDE_TYPE_LOAD_LEVEL_LIMIT. +// Don't reference this class directly. Use the macros. +//------------------------------------------------------------------------------------ +class LoadsTypeHolder +{ + public: + LoadsTypeHolder(BOOL fConditional, + UINT newLevel, + BOOL fEnforceLevelChangeDirection, + const char *szFunction, + const char *szFile, + int lineNum + ); + + ~LoadsTypeHolder(); + + private: + ClrDebugState *m_pClrDebugState; + ClrDebugState m_oldClrDebugState; + BOOL m_fConditional; + ContractStackRecord m_contractStackRecord; + +}; + +#endif // ENABLE_CONTRACTS_IMPL + + +//------------------------------------------------------------------------------------ +// TRIGGERS_TYPE_LOAD(newLevel) +// Works just LOADS_TYPE in contracts but lets you protect individual scopes +// +// OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) +// Sets a new limit just like TRIGGERS_TYPE_LOAD but does not restrict you +// to decreasing the limit. Only the loader should use this and only when it +// can prove structurally that no recursion will occur as a result. +//------------------------------------------------------------------------------------ +#ifdef ENABLE_CONTRACTS_IMPL + +#define TRIGGERS_TYPE_LOAD(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__); +#define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__); +#define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__); +#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__); + +#else // ENABLE_CONTRACTS_IMPL + +#define TRIGGERS_TYPE_LOAD(newLevel) +#define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) +#define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) +#define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) + +#endif // ENABLE_CONTRACTS_IMPL + + + +#ifdef ENABLE_CONTRACTS_IMPL +class PAL_TryMarker +{ +public: + DEBUG_NOINLINE void Enter(); + DEBUG_NOINLINE void Leave(); +}; + +#define PAL_ENTER_THROWS_REGION \ + PAL_TryMarker __throwsHolder_onlyOneAllowedPerScope; \ + __throwsHolder_onlyOneAllowedPerScope.Enter(); + +#define PAL_LEAVE_THROWS_REGION \ + __throwsHolder_onlyOneAllowedPerScope.Leave(); + +// This sets up a marker that says its okay to throw on this thread. This is not a public macro, and should only be +// used from within the implementation of various try/catch macros. +class ClrTryMarkerHolder +{ +public: + DEBUG_NOINLINE ClrTryMarkerHolder() + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_THROWS; + + m_pClrDebugState = GetClrDebugState(); + m_oldOkayToThrowValue = m_pClrDebugState->IsOkToThrow(); + m_pClrDebugState->SetOkToThrow(); + } + + DEBUG_NOINLINE ~ClrTryMarkerHolder() + { + SCAN_SCOPE_END; + + m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue ); + } + +private: + BOOL m_oldOkayToThrowValue; + ClrDebugState *m_pClrDebugState; +}; + +#define CLR_TRY_MARKER() ClrTryMarkerHolder ___tryMarkerHolder; + +#else // ENABLE_CONTRACTS_IMPL + +#define CLR_TRY_MARKER() +#define PAL_ENTER_THROWS_REGION +#define PAL_LEAVE_THROWS_REGION + +#endif + +#ifdef ENABLE_CONTRACTS_IMPL +// Note: This routine will create a ClrDebugState if called for the first time. +// It cannot return NULL (see comment for InitClrDebugState). +inline ClrDebugState *GetClrDebugState(BOOL fAlloc) +{ + STATIC_CONTRACT_LIMITED_METHOD; + + ClrDebugState *pState = CheckClrDebugState(); + + if (pState) + { + return pState; + } + + if (fAlloc) + { + return CLRInitDebugState(); + } + + return NULL; +} +#endif // ENABLE_CONTRACTS_IMPL + +#ifdef ENABLE_CONTRACTS_IMPL + +class HostNoCallHolder +{ + public: + DEBUG_NOINLINE HostNoCallHolder() + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_HOST_NOCALLS; + + m_clrDebugState = GetClrDebugState(); + m_previousState = m_clrDebugState->SetHostCaller(FALSE); + } + + DEBUG_NOINLINE ~HostNoCallHolder() + { + SCAN_SCOPE_END; + + m_clrDebugState->SetHostCaller(m_previousState); + } + + private: + BOOL m_previousState; + ClrDebugState* m_clrDebugState; + +}; + +#define BEGIN_HOST_NOCALL_CODE \ + { \ + HostNoCallHolder __hostNoCallHolder; \ + CantAllocHolder __cantAlloc; + +#define END_HOST_NOCALL_CODE \ + } + +#else // ENABLE_CONTRACTS_IMPL +#define BEGIN_HOST_NOCALL_CODE \ + { \ + CantAllocHolder __cantAlloc; \ + +#define END_HOST_NOCALL_CODE \ + } +#endif + +#ifdef ENABLE_CONTRACTS_IMPL + +class GetThreadAllowedHolder +{ + public: + GetThreadAllowedHolder(BOOL newState) + { + m_clrDebugState = ::GetClrDebugState(); + m_previousState = m_clrDebugState->SetGetThreadAllowed(newState); + } + + ~GetThreadAllowedHolder() + { + m_clrDebugState->SetGetThreadAllowed(m_previousState); + } + +private: + BOOL m_previousState; + ClrDebugState* m_clrDebugState; +}; + +// When in an EE_THREAD_NOT_REQUIRED contracted scope, it's expected that the +// function does not assume an EE Thread object is available in TLS. Either +// GetThread() is never called, or any code path that requires a Thread +// has another code path that deals with the absence of a Thread. Any call to +// to GetThread() must be bracketed with BEGIN_GETTHREAD_ALLOWED / +// END_GETTHREAD_ALLOWED to avoid bogus asserts (the short-form +// GetThreadNULLOk() may be used as well). However, this is only allowed if visual +// inspection of the call site makes it patently obvious that the function deals +// appropriately with the GetThread() == NULL case (or that case has already been +// dealt with and control has exited before the BEGIN_GETTHREAD_ALLOWED / +// END_GETTHREAD_ALLOWED block. +// +// These use holder objects, which causes the compiler to generate EH code and prevent +// inlining. So try to avoid these in small, downstream functions (like inline +// EE Thread member functions). Use the _IN_NO_THROW_REGION variants below instead. + +#define BEGIN_GETTHREAD_ALLOWED \ + { \ + GetThreadAllowedHolder __getThreadAllowedHolder(TRUE); \ + +#define END_GETTHREAD_ALLOWED \ + } + +// These are lighter-weight versions of BEGIN_GETTHREAD_ALLOWED / +// END_GETTHREAD_ALLOWED. These don't use holders, so be sure only to +// use these to bracket code that won't throw exceptions +#define BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION \ + { \ + ClrDebugState * __clrDebugState = ::GetClrDebugState(); \ + BOOL __previousState = __clrDebugState->SetGetThreadAllowed(TRUE); \ + +#define END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION \ + __clrDebugState->SetGetThreadAllowed(__previousState); \ + } + +#else // ENABLE_CONTRACTS_IMPL +#define BEGIN_GETTHREAD_ALLOWED +#define END_GETTHREAD_ALLOWED +#define BEGIN_GETTHREAD_ALLOWED_IN_NO_THROW_REGION +#define END_GETTHREAD_ALLOWED_IN_NO_THROW_REGION +#endif + +#if defined(ENABLE_CONTRACTS_IMPL) + +// Macros to indicate we're taking or releasing locks + +// Most general macros, not used directly +#define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) \ + ::GetClrDebugState()->LockTaken((dbgStateLockType), (cEntrances), (void*) (pvLock), __FUNCTION__, __FILE__, __LINE__) +#define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) \ + ::GetClrDebugState()->LockReleased((dbgStateLockType), (cExits), (void*) (pvLock)) + +// Use these only if you need to force multiple entrances or exits in a single +// line (e.g., to restore the lock to a previous state). CRWLock in vm\rwlock.cpp does this +#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, cEntrances, pvLock) +#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, cExits, pvLock) +#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cEntrances, pvLock) +#define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cExits, pvLock) +#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, cEntrances, pvLock) +#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, cExits, pvLock) + +// These are most typically used +#define EE_LOCK_TAKEN(pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, 1, pvLock) +#define EE_LOCK_RELEASED(pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, 1, pvLock) +#define HOST_BREAKABLE_CRST_TAKEN(pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock) +#define HOST_BREAKABLE_CRST_RELEASED(pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock) +#define USER_LOCK_TAKEN(pvLock) \ + LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, 1, pvLock) +#define USER_LOCK_RELEASED(pvLock) \ + LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, 1, pvLock) + +#else // defined(ENABLE_CONTRACTS_IMPL) + +#define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) +#define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) +#define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) +#define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) +#define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) +#define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) +#define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) +#define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) +#define EE_LOCK_TAKEN(pvLock) +#define EE_LOCK_RELEASED(pvLock) +#define HOST_BREAKABLE_CRST_TAKEN(pvLock) +#define HOST_BREAKABLE_CRST_RELEASED(pvLock) +#define USER_LOCK_TAKEN(pvLock) +#define USER_LOCK_RELEASED(pvLock) + +#endif // defined(ENABLE_CONTRACTS_IMPL) + +#if defined(ENABLE_CONTRACTS_IMPL) + +// Abbreviation for an assert that is only considered if there is a valid +// ClrDebugState available. Useful if you want to assert based on the value +// of GetDbgStateLockCount(), where a return of 0 (the default if there is no +// valid ClrDebugState available) would cause your assert to fire. The variable +// __pClrDebugState is set to the current ClrDebugState, and may be used within +// your assert expression +#define ASSERT_UNLESS_NO_DEBUG_STATE(e) \ + { \ + ClrDebugState * __pClrDebugState = GetClrDebugState(); \ + _ASSERTE(((__pClrDebugState->ViolationMask() & BadDebugState) != 0) || (e)); \ + } + +#else // defined(ENABLE_CONTRACTS_IMPL) + +#define ASSERT_UNLESS_NO_DEBUG_STATE(e) + +#endif // defined(ENABLE_CONTRACTS_IMPL) + + +//----------------------------------------------------------------------------- +// Debug support to ensure that nobody calls New on the helper thread. +// This is for interop debugging. +// They should be using the InteropSafe heap. +// Having this in the meantime allows us to +// assert that the helper thread never calls new, and maintain a finite list of +// exceptions (bugs). +// Eventually, all those bugs should be fixed this holder can be completely removed. +// +// It is also the case that we disallow allocations when any thread is OS suspended +// This happens for a short time when we are suspending the EE. We supress both +// of these. +// +// @todo- ideally this would be rolled into the ContractViolation. +// also, we'd have contract bit for whether APIs can be called on the helper thread. +// @todo - if we really wanted to be strict, we should make this per-thread. +//----------------------------------------------------------------------------- +#ifdef ENABLE_CONTRACTS_IMPL +extern Volatile g_DbgSuppressAllocationAsserts; +#define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE CounterHolder _AllowNewOnHelperHolder(&g_DbgSuppressAllocationAsserts); +#else +// Nothing in retail since this holder just disabled an assert. +#define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE +#endif + + +//----------------------------------------------------------------------------- +// Support for contracts in DAC builds +// +// At the moment, most of the contract system is disabled in DAC builds. +// We do however want some simple static contracts in order to support static +// analysis tools that run on mscordacwks.dll like DacCop. +// Note that we want these static contracts in both DEBUG and retail builds. +// We also already get simple static contracts like WRAPPER and LEAF. +// +//----------------------------------------------------------------------------- +#if defined(DACCESS_COMPILE) + +// SUPPORTS_DAC is an annotation that says the function is designed to be used in DAC builds. +// This enables full DacCop analysis on the function, including verifying that all functions that are +// called also support DAC. +#define SUPPORTS_DAC do { STATIC_CONTRACT_SUPPORTS_DAC; } while(0) + +// Normally a function can be annotated just with WRAPPER_NO_CONTRACT, which (in addition to the normal +// contract meaning) indicates to DacCop that the function should be considered to support DAC when +// it is called from a supports-dac function. This is to avoid having to add a DAC-specific contract +// to all the trivial one-line wrapper functions we have. +// However, we occasionally want these semantics even for functions which are not appropriate to label +// as WRAPPER_NO_CONTRACT. For example, a template function may support DAC for certain template arguments, +// but not others (due to the functions it calls). We want to ensure that when such a function is called +// in a DAC code path, analysis is enabled on that particular instantiation including checking all of the +// call targets specific to this template instantiation. But we don't want to require that the call targets +// for ALL instantiations support dac, since we may not even be using them in DAC code paths. Ideally we'd +// remove any such code from the DAC build, but this will take time. +#define SUPPORTS_DAC_WRAPPER do { STATIC_CONTRACT_WRAPPER; } while(0) + +// SUPPORTS_DAC_HOST_ONLY indicates that a function is allowed to be called in DAC builds, but rather +// than being a normal DAC function which operates on marshalled data, it is a host-only utility function +// that knows nothing about DAC and operates solely on the host. For example, DbgAssertDialog is a utility +// function for popping assert dialogs - there is nothing DAC-specific about this. Ideally such utility +// functions would be confined to their own library which had no access to DAC functionality, and which +// is not analyzed by DacCop. At the moment splitting utilcode into two variations like this is too +// painful, but we hope to do it in the future (primarily to support functions which can be used in either +// DAC or host-only mode). +// WARNING: This contract disables DacCop analysis on the function and any functions it calls, so it +// should be used very carefully. +#define SUPPORTS_DAC_HOST_ONLY do { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; } while(0) + +#else +#define SUPPORTS_DAC +#define SUPPORTS_DAC_HOST_ONLY +#define SUPPORTS_DAC_WRAPPER +#endif // DACCESS_COMPILE + +// LIMITED_METHOD_DAC_CONTRACT is a shortcut for LIMITED_METHOD_CONTRACT and SUPPORTS_DAC. Usefull for one-line inline functions. +#define LIMITED_METHOD_DAC_CONTRACT LIMITED_METHOD_CONTRACT; SUPPORTS_DAC + +// +// The default contract is the recommended contract for ordinary code. +// The ordinary code can throw or trigger GC any time, does not operate +// on raw object refs, etc. +// + +#define STANDARD_VM_CHECK \ + THROWS; + +#define STANDARD_VM_CONTRACT \ + CONTRACTL \ + { \ + STANDARD_VM_CHECK; \ + } \ + CONTRACTL_END; \ + +#define STATIC_STANDARD_VM_CONTRACT \ + STATIC_CONTRACT_THROWS; \ + STATIC_CONTRACT_GC_TRIGGERS; \ + STATIC_CONTRACT_MODE_PREEMPTIVE; + +#define AFTER_CONTRACTS +#include "volatile.h" + +#endif // CONTRACT_H_ diff --git a/lib/coreclr/src/inc/contract.inl b/lib/coreclr/src/inc/contract.inl new file mode 100644 index 0000000000..3c794948a9 --- /dev/null +++ b/lib/coreclr/src/inc/contract.inl @@ -0,0 +1,640 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// Contract.inl +// + +// ! I am the owner for issues in the contract *infrastructure*, not for every +// ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine +// ! CONTRACT_VIOLATION, you will become the new owner of this file. +// --------------------------------------------------------------------------- + +#ifndef CONTRACT_INL_ +#define CONTRACT_INL_ + +#include "contract.h" +#include + +#ifndef _countof +#define _countof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifdef ENABLE_CONTRACTS_IMPL + +inline void BaseContract::DoChecks(UINT testmask, __in_z const char *szFunction, __in_z const char *szFile, int lineNum) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + // Cache the pointer to our ClrDebugState if it's not already cached. + // Derived types could set up this ptr before calling BaseContract::DoChecks if they have access to the Thread ptr + if (m_pClrDebugState == NULL) + { + m_pClrDebugState = GetClrDebugState(); + } + + // Save the incoming contents for restoration in the destructor + m_IncomingClrDebugState = *m_pClrDebugState; + + m_testmask = testmask; // Save the testmask for destructor + + // Setup the new stack record. + m_contractStackRecord.m_szFunction = szFunction; + m_contractStackRecord.m_szFile = szFile; + m_contractStackRecord.m_lineNum = lineNum; + m_contractStackRecord.m_testmask = testmask; + m_contractStackRecord.m_construct = "CONTRACT"; + + // Link the new ContractStackRecord into the chain for this thread. + m_pClrDebugState->LinkContractStackTrace( &m_contractStackRecord ); + + if (testmask & DEBUG_ONLY_Yes) + { + m_pClrDebugState->SetDebugOnly(); + } + + switch (testmask & FAULT_Mask) + { + case FAULT_Forbid: + m_pClrDebugState->ViolationMaskReset( FaultViolation|FaultNotFatal ); + m_pClrDebugState->SetFaultForbid(); + break; + + case FAULT_Inject: + if (m_pClrDebugState->IsFaultForbid() && + !(m_pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState))) + { + CONTRACT_ASSERT("INJECT_FAULT called in a FAULTFORBID region.", + BaseContract::FAULT_Forbid, + BaseContract::FAULT_Mask, + m_contractStackRecord.m_szFunction, + m_contractStackRecord.m_szFile, + m_contractStackRecord.m_lineNum); + } + break; + + case FAULT_Disabled: + // Nothing + break; + + default: + UNREACHABLE(); + } + + switch (testmask & THROWS_Mask) + { + case THROWS_Yes: + m_pClrDebugState->CheckOkayToThrow(m_contractStackRecord.m_szFunction, + m_contractStackRecord.m_szFile, + m_contractStackRecord.m_lineNum); + break; + + case THROWS_No: + m_pClrDebugState->ViolationMaskReset( ThrowsViolation ); + m_pClrDebugState->ResetOkToThrow(); + break; + + case THROWS_Disabled: + // Nothing + break; + + default: + UNREACHABLE(); + } + + // LOADS_TYPE check + switch (testmask & LOADS_TYPE_Mask) + { + case LOADS_TYPE_Disabled: + // Nothing + break; + + default: + { + UINT newTypeLoadLevel = ((testmask & LOADS_TYPE_Mask) >> LOADS_TYPE_Shift) - 1; + if (newTypeLoadLevel > m_pClrDebugState->GetMaxLoadTypeLevel()) + { + if (!((LoadsTypeViolation|BadDebugState) & m_pClrDebugState->ViolationMask())) + { + CONTRACT_ASSERT("A function tried to load a type past the current level limit.", + (m_pClrDebugState->GetMaxLoadTypeLevel() + 1) << LOADS_TYPE_Shift, + Contract::LOADS_TYPE_Mask, + m_contractStackRecord.m_szFunction, + m_contractStackRecord.m_szFile, + m_contractStackRecord.m_lineNum + ); + } + } + m_pClrDebugState->SetMaxLoadTypeLevel(newTypeLoadLevel); + m_pClrDebugState->ViolationMaskReset(LoadsTypeViolation); + + } + break; + } + + if (testmask & CAN_RETAKE_LOCK_No) + { + m_pClrDebugState->OnEnterCannotRetakeLockFunction(); + m_pClrDebugState->ResetOkToRetakeLock(); + } + + switch (testmask & CAN_TAKE_LOCK_Mask) + { + case CAN_TAKE_LOCK_Yes: + m_pClrDebugState->CheckOkayToLock(m_contractStackRecord.m_szFunction, + m_contractStackRecord.m_szFile, + m_contractStackRecord.m_lineNum); + break; + + case CAN_TAKE_LOCK_No: + m_pClrDebugState->ViolationMaskReset(TakesLockViolation); + m_pClrDebugState->ResetOkToLock(); + break; + + case CAN_TAKE_LOCK_Disabled: + // Nothing + break; + + default: + UNREACHABLE(); + } + +} + +FORCEINLINE BOOL BaseContract::CheckFaultInjection() +{ + // ??? use m_tag to see if we should trigger an injection + return FALSE; +} + +inline BOOL ClrDebugState::CheckOkayToThrowNoAssert() +{ + if (!IsOkToThrow() && !(m_violationmask & (ThrowsViolation|BadDebugState))) + { + return FALSE; + } + return TRUE; +} + +inline void ClrDebugState::CheckOkayToThrow(__in_z const char *szFunction, __in_z const char *szFile, int lineNum) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (!CheckOkayToThrowNoAssert()) + { + CONTRACT_ASSERT("THROWS called in a NOTHROW region.", + BaseContract::THROWS_No, + BaseContract::THROWS_Mask, + szFunction, + szFile, + lineNum); + } +} + +inline BOOL ClrDebugState::CheckOkayToLockNoAssert() +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (!IsOkToLock() && !(m_violationmask & (TakesLockViolation|BadDebugState))) + { + return FALSE; + } + return TRUE; +} + +inline void ClrDebugState::CheckOkayToLock(__in_z const char *szFunction, __in_z const char *szFile, int lineNum) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (!CheckOkayToLockNoAssert()) + { + + CONTRACT_ASSERT("CAN_TAKE_LOCK called in a CANNOT_TAKE_LOCK region.", + BaseContract::CAN_TAKE_LOCK_No, + BaseContract::CAN_TAKE_LOCK_Mask, + szFunction, + szFile, + lineNum); + + } +} + + +inline void ClrDebugState::LockTaken(DbgStateLockType dbgStateLockType, + UINT cTakes, + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, + int lineNum) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if ((m_violationmask & BadDebugState) != 0) + { + return; + } + + // Assert if we're taking a lock in a CANNOT_TAKE_LOCK scope. Even if this asserts, we'll + // continue to the following lines to track the lock + CheckOkayToLock(szFunction, szFile, lineNum); + + _ASSERTE(GetDbgStateLockData() != NULL); + + if (!IsOkToRetakeLock()) + { + if (m_LockState.IsLockRetaken(pvLock)) + { + CONTRACT_ASSERT("You cannot take a lock which is already being held in a CANNOT_RETAKE_LOCK scope.", + BaseContract::CAN_RETAKE_LOCK_No, + BaseContract::CAN_RETAKE_LOCK_No, + szFunction, + szFile, + lineNum); + } + } + + GetDbgStateLockData()->LockTaken(dbgStateLockType, cTakes, pvLock, szFunction, szFile, lineNum); +} + +inline void ClrDebugState::LockReleased(DbgStateLockType dbgStateLockType, UINT cReleases, void * pvLock) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if ((m_violationmask & BadDebugState) != 0) + { + return; + } + + _ASSERTE(GetDbgStateLockData() != NULL); + + if (!IsOkToRetakeLock()) + { + // It is very suspicious to release any locks being hold at the time this function was + // called in a CANNOT_RETAKE_LOCK scope + _ASSERTE(m_LockState.IsSafeToRelease(cReleases)); + } + + GetDbgStateLockData()->LockReleased(dbgStateLockType, cReleases, pvLock); +} + +inline UINT ClrDebugState::GetLockCount(DbgStateLockType dbgStateLockType) +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if ((m_violationmask & BadDebugState) != 0) + { + return 0; + } + + _ASSERTE(GetDbgStateLockData() != NULL); + return GetDbgStateLockData()->GetLockCount(dbgStateLockType); +} + +inline UINT ClrDebugState::GetCombinedLockCount() +{ + STATIC_CONTRACT_DEBUG_ONLY; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if ((m_violationmask & BadDebugState) != 0) + { + return 0; + } + + _ASSERTE(GetDbgStateLockData() != NULL); + return GetDbgStateLockData()->GetCombinedLockCount(); +} + +inline void DbgStateLockData::LockTaken(DbgStateLockType dbgStateLockType, + UINT cTakes, // # times we're taking this lock (usually 1) + void * pvLock, + __in_z const char * szFunction, + __in_z const char * szFile, + int lineNum) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + // Technically the lock's already been taken before we're called, but it's + // handy to have this contract here at the leaf end of the call chain, as it + // ensures SCAN will enforce that no use of the LOCK_TAKEN macros occurs + // in a CANNOT_TAKE_LOCK scope (as LOCK_TAKEN macros just call this function). + STATIC_CONTRACT_CAN_TAKE_LOCK; + + // Valid enum? + _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); + + UINT cCombinedLocks = GetCombinedLockCount(); + + // Are we exceeding the threshold for what we can store in m_rgTakenLockInfos? + // If so, assert a warning, but we'll deal with it. + if ((cCombinedLocks <= _countof(m_rgTakenLockInfos)) && + (cCombinedLocks + cTakes > _countof(m_rgTakenLockInfos))) + { + // Actually, for now we are NOT asserting until I can dedicate more time + // to this. Some class loader code paths legally hold many simultaneous + // locks (>10). Need to do further analysis on reasonable value to set + // for kMaxAllowedSimultaneousLocks. Since lock order checking is turned + // off for the moment anyway, exceeding kMaxAllowedSimultaneousLocks + // has no consequences for now anyway. + } + + m_rgcLocksTaken[dbgStateLockType] += cTakes; + + // Remember as many of these new entrances in m_rgTakenLockInfos as we can + for (UINT i = cCombinedLocks; + i < min (_countof(m_rgTakenLockInfos), cCombinedLocks + cTakes); + i++) + { + m_rgTakenLockInfos[i].m_pvLock = pvLock; + m_rgTakenLockInfos[i].m_szFile = szFile; + m_rgTakenLockInfos[i].m_lineNum = lineNum; + } +} + +inline void DbgStateLockData::LockReleased(DbgStateLockType dbgStateLockType, UINT cReleases, void * pvLock) +{ + // Valid enum? + _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); + + if (cReleases > m_rgcLocksTaken[dbgStateLockType]) + { + _ASSERTE(!"Releasing lock(s) that were never taken"); + cReleases = m_rgcLocksTaken[dbgStateLockType]; + } + + UINT cCombinedLocks = GetCombinedLockCount(); + + // If lock count is within range of our m_rgTakenLockInfos buffer size, then + // make sure we're releasing locks in reverse order of how we took them + for (UINT i = cCombinedLocks - cReleases; + i < min (_countof(m_rgTakenLockInfos), cCombinedLocks); + i++) + { + if (m_rgTakenLockInfos[i].m_pvLock != pvLock) + { + // Ok, I lied. We're not really checking that we're releasing locks in reverse + // order, because sometimes we legally release them out of order. (The loader + // does this intentionally in a few places.) We should consider whether those + // places can be changed, or whether we can add some kind of macro to declare + // that we're releasing out of order, and that it's ok & intentional. At that + // point, we can place a nice ASSERTE right here. Until then, do nothing. + } + + // We may be clearing out the wrong entry in m_rgTakenLockInfos here, if the locks + // were released out of order. However, it will eventually correct itself once all + // the out-of-order locks have been released. And our count + // (i.e., m_rgcLocksTaken[dbgStateLockType]) will always be accurate + memset(&(m_rgTakenLockInfos[i]), + 0, + sizeof(m_rgTakenLockInfos[i])); + } + + m_rgcLocksTaken[dbgStateLockType] -= cReleases; +} + +inline void DbgStateLockData::SetStartingValues() +{ + memset(this, 0, sizeof(*this)); +} + +inline UINT DbgStateLockData::GetLockCount(DbgStateLockType dbgStateLockType) +{ + _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); + return m_rgcLocksTaken[dbgStateLockType]; +} + +inline UINT DbgStateLockData::GetCombinedLockCount() +{ + // If this fires, the set of lock types must have changed. You'll need to + // fix the sum below to include all lock types + _ASSERTE(kDbgStateLockType_Count == 3); + + return m_rgcLocksTaken[0] + m_rgcLocksTaken[1] + m_rgcLocksTaken[2]; +} + +inline void DbgStateLockState::SetStartingValues() +{ + m_cLocksEnteringCannotRetakeLock = 0; + m_pLockData = NULL; // Will get filled in by CLRInitDebugState() +} + +// We set a marker to record the number of locks that have been taken when +// CANNOT_RETAKE_LOCK contract is constructed. +inline void DbgStateLockState::OnEnterCannotRetakeLockFunction() +{ + m_cLocksEnteringCannotRetakeLock = m_pLockData->GetCombinedLockCount(); +} + +inline BOOL DbgStateLockState::IsLockRetaken(void * pvLock) +{ + // m_cLocksEnteringCannotRetakeLock must be in valid range + _ASSERTE(m_cLocksEnteringCannotRetakeLock <= m_pLockData->GetCombinedLockCount()); + + // m_cLocksEnteringCannotRetakeLock records the number of locks that were taken + // when CANNOT_RETAKE_LOCK contract was constructed. + for (UINT i = 0; + i < min(_countof(m_pLockData->m_rgTakenLockInfos), m_cLocksEnteringCannotRetakeLock); + ++i) + { + if (m_pLockData->m_rgTakenLockInfos[i].m_pvLock == pvLock) + { + return TRUE; + } + } + return FALSE; +} + +inline BOOL DbgStateLockState::IsSafeToRelease(UINT cReleases) +{ + return m_cLocksEnteringCannotRetakeLock <= (m_pLockData->GetCombinedLockCount() - cReleases); +} + +inline void DbgStateLockState::SetDbgStateLockData(DbgStateLockData * pDbgStateLockData) +{ + m_pLockData = pDbgStateLockData; +} + +inline DbgStateLockData * DbgStateLockState::GetDbgStateLockData() +{ + return m_pLockData; +} + +inline +void CONTRACT_ASSERT(const char *szElaboration, + UINT whichTest, + UINT whichTestMask, + const char *szFunction, + const char *szFile, + int lineNum) +{ + if (CheckClrDebugState() && ( CheckClrDebugState()->ViolationMask() & BadDebugState)) + { + _ASSERTE(!"Someone tried to assert a contract violation although the contracts were disabled in this thread due to" + " an OOM or a shim/mscorwks mismatch. You can probably safely ignore this assert - however, whoever" + " called CONTRACT_ASSERT was supposed to checked if the current violationmask had the BadDebugState set." + " Look up the stack, see who called CONTRACT_ASSERT and file a bug against the owner."); + return; + } + + // prevent recursion - we use the same mechanism as CHECK, so this will + // also prevent mutual recursion involving ASSERT_CHECKs + CHECK _check; + if (_check.EnterAssert()) + { + char Buf[512*20 + 2048 + 1024]; + + sprintf_s(Buf,_countof(Buf), "CONTRACT VIOLATION by %s at \"%s\" @ %d\n\n%s\n", szFunction, szFile, lineNum, szElaboration); + + int count = 20; + ContractStackRecord *pRec = CheckClrDebugState() ? CheckClrDebugState()->GetContractStackTrace() : NULL; + BOOL foundconflict = FALSE; + BOOL exceptionBuildingStack = FALSE; + + PAL_TRY_NAKED + { + while (pRec != NULL) + { + char tmpbuf[512]; + BOOL fshowconflict = FALSE; + + if (!foundconflict) + { + if (whichTest == (pRec->m_testmask & whichTestMask)) + { + foundconflict = TRUE; + fshowconflict = TRUE; + } + } + + if (count != 0 || fshowconflict) + { + if (count != 0) + { + count--; + } + else + { + // Show that some lines have been skipped + strcat_s(Buf, _countof(Buf), "\n ..."); + + } + + sprintf_s(tmpbuf,_countof(tmpbuf), + "\n%s %s in %s at \"%s\" @ %d", + fshowconflict ? "VIOLATED-->" : " ", + pRec->m_construct, + pRec->m_szFunction, + pRec->m_szFile, + pRec->m_lineNum + ); + + strcat_s(Buf, _countof(Buf), tmpbuf); + } + + pRec = pRec->m_pNext; + } + } + PAL_EXCEPT_NAKED(EXCEPTION_EXECUTE_HANDLER) + { + // We're done trying to walk the stack of contracts. We faulted trying to form the contract stack trace, + // and that usually means that its corrupted. A common cause of this is having CONTRACTs in functions that + // never return, but instead do a non-local goto. + count = 0; + exceptionBuildingStack = TRUE; + } + PAL_ENDTRY_NAKED; + + if (count == 0) + { + strcat_s(Buf,_countof(Buf), "\n ..."); + } + + if (exceptionBuildingStack) + { + strcat_s(Buf,_countof(Buf), + "\n" + "\nError forming contract stack. Any contract stack displayed above is correct," + "\nbut it's most probably truncated. This is probably due to a CONTRACT in a" + "\nfunction that does a non-local goto. There are two bugs here:" + "\n" + "\n 1) the CONTRACT violation, and" + "\n 2) the CONTRACT in the function with the non-local goto." + "\n" + "\nPlease fix both bugs!" + "\n" + ); + } + + strcat_s(Buf,_countof(Buf), "\n\n"); + + if (!foundconflict && count != 0) + { + if (whichTest == BaseContract::THROWS_No) + { + strcat_s(Buf,_countof(Buf), "You can't throw here because there is no handler on the stack.\n"); + } + else + { + strcat_s(Buf,_countof(Buf), "We can't find the violated contract. Look for an old-style non-holder-based contract.\n"); + } + } + + DbgAssertDialog((char *)szFile, lineNum, Buf); + _check.LeaveAssert(); + } +} + + +FORCEINLINE BOOL BaseContract::EnforceContract() +{ + if (s_alwaysEnforceContracts) + return TRUE; + else + return CHECK::EnforceAssert(); +} + +inline void BaseContract::SetUnconditionalContractEnforcement(BOOL value) +{ + s_alwaysEnforceContracts = value; +} + +inline UINT GetDbgStateCombinedLockCount() +{ + return GetClrDebugState()->GetCombinedLockCount(); +} +inline UINT GetDbgStateLockCount(DbgStateLockType dbgStateLockType) +{ + return GetClrDebugState()->GetLockCount(dbgStateLockType); +} + +#define ASSERT_NO_USER_LOCKS_HELD() \ + _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_User) == 0) +#define ASSERT_NO_HOST_BREAKABLE_CRSTS_HELD() \ + _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_HostBreakableCrst) == 0) +#define ASSERT_NO_EE_LOCKS_HELD() \ + _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_EE) == 0) + +#else // ENABLE_CONTRACTS_IMPL + +#define ASSERT_NO_USER_LOCKS_HELD() +#define ASSERT_NO_HOST_BREAKABLE_CRSTS_HELD() +#define ASSERT_NO_EE_LOCKS_HELD() + +#endif // ENABLE_CONTRACTS_IMPL + +#endif // CONTRACT_INL_ diff --git a/lib/coreclr/src/inc/contxt.h b/lib/coreclr/src/inc/contxt.h new file mode 100644 index 0000000000..98240b3331 --- /dev/null +++ b/lib/coreclr/src/inc/contxt.h @@ -0,0 +1,3472 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + +/* File created by MIDL compiler version 5.01.0164 */ +/* at Mon May 01 14:39:38 2000 + */ +/* Compiler settings for contxt.idl: + Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext + error checks: allocation ref bounds_check enum stub_data +*/ +//@@MIDL_FILE_HEADING( ) + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __contxt_h__ +#define __contxt_h__ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Forward Declarations */ + +#ifndef __IEnumContextProps_FWD_DEFINED__ +#define __IEnumContextProps_FWD_DEFINED__ +typedef interface IEnumContextProps IEnumContextProps; +#endif /* __IEnumContextProps_FWD_DEFINED__ */ + + +#ifndef __IContext_FWD_DEFINED__ +#define __IContext_FWD_DEFINED__ +typedef interface IContext IContext; +#endif /* __IContext_FWD_DEFINED__ */ + + +#ifndef __IContextMarshaler_FWD_DEFINED__ +#define __IContextMarshaler_FWD_DEFINED__ +typedef interface IContextMarshaler IContextMarshaler; +#endif /* __IContextMarshaler_FWD_DEFINED__ */ + + +#ifndef __IObjContext_FWD_DEFINED__ +#define __IObjContext_FWD_DEFINED__ +typedef interface IObjContext IObjContext; +#endif /* __IObjContext_FWD_DEFINED__ */ + + +#ifndef __IGetContextId_FWD_DEFINED__ +#define __IGetContextId_FWD_DEFINED__ +typedef interface IGetContextId IGetContextId; +#endif /* __IGetContextId_FWD_DEFINED__ */ + + +#ifndef __IAggregator_FWD_DEFINED__ +#define __IAggregator_FWD_DEFINED__ +typedef interface IAggregator IAggregator; +#endif /* __IAggregator_FWD_DEFINED__ */ + + +#ifndef __ICall_FWD_DEFINED__ +#define __ICall_FWD_DEFINED__ +typedef interface ICall ICall; +#endif /* __ICall_FWD_DEFINED__ */ + + +#ifndef __IRpcCall_FWD_DEFINED__ +#define __IRpcCall_FWD_DEFINED__ +typedef interface IRpcCall IRpcCall; +#endif /* __IRpcCall_FWD_DEFINED__ */ + + +#ifndef __ICallInfo_FWD_DEFINED__ +#define __ICallInfo_FWD_DEFINED__ +typedef interface ICallInfo ICallInfo; +#endif /* __ICallInfo_FWD_DEFINED__ */ + + +#ifndef __IPolicy_FWD_DEFINED__ +#define __IPolicy_FWD_DEFINED__ +typedef interface IPolicy IPolicy; +#endif /* __IPolicy_FWD_DEFINED__ */ + + +#ifndef __IPolicyAsync_FWD_DEFINED__ +#define __IPolicyAsync_FWD_DEFINED__ +typedef interface IPolicyAsync IPolicyAsync; +#endif /* __IPolicyAsync_FWD_DEFINED__ */ + + +#ifndef __IPolicySet_FWD_DEFINED__ +#define __IPolicySet_FWD_DEFINED__ +typedef interface IPolicySet IPolicySet; +#endif /* __IPolicySet_FWD_DEFINED__ */ + + +#ifndef __IComObjIdentity_FWD_DEFINED__ +#define __IComObjIdentity_FWD_DEFINED__ +typedef interface IComObjIdentity IComObjIdentity; +#endif /* __IComObjIdentity_FWD_DEFINED__ */ + + +#ifndef __IPolicyMaker_FWD_DEFINED__ +#define __IPolicyMaker_FWD_DEFINED__ +typedef interface IPolicyMaker IPolicyMaker; +#endif /* __IPolicyMaker_FWD_DEFINED__ */ + + +#ifndef __IExceptionNotification_FWD_DEFINED__ +#define __IExceptionNotification_FWD_DEFINED__ +typedef interface IExceptionNotification IExceptionNotification; +#endif /* __IExceptionNotification_FWD_DEFINED__ */ + + +#ifndef __IMarshalEnvoy_FWD_DEFINED__ +#define __IMarshalEnvoy_FWD_DEFINED__ +typedef interface IMarshalEnvoy IMarshalEnvoy; +#endif /* __IMarshalEnvoy_FWD_DEFINED__ */ + + +#ifndef __IWrapperInfo_FWD_DEFINED__ +#define __IWrapperInfo_FWD_DEFINED__ +typedef interface IWrapperInfo IWrapperInfo; +#endif /* __IWrapperInfo_FWD_DEFINED__ */ + + +#ifndef __IComThreadingInfo_FWD_DEFINED__ +#define __IComThreadingInfo_FWD_DEFINED__ +typedef interface IComThreadingInfo IComThreadingInfo; +#endif /* __IComThreadingInfo_FWD_DEFINED__ */ + + +#ifndef __IComDispatchInfo_FWD_DEFINED__ +#define __IComDispatchInfo_FWD_DEFINED__ +typedef interface IComDispatchInfo IComDispatchInfo; +#endif /* __IComDispatchInfo_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "wtypes.h" +#include "objidl.h" + +void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void __RPC_FAR * ); + +/* interface __MIDL_itf_contxt_0000 */ +/* [local] */ + +enum tagCONTEXTEVENT + { CONTEXTEVENT_NONE = 0, + CONTEXTEVENT_CALL = 0x1, + CONTEXTEVENT_ENTER = 0x2, + CONTEXTEVENT_LEAVE = 0x4, + CONTEXTEVENT_RETURN = 0x8, + CONTEXTEVENT_CALLFILLBUFFER = 0x10, + CONTEXTEVENT_ENTERWITHBUFFER = 0x20, + CONTEXTEVENT_LEAVEFILLBUFFER = 0x40, + CONTEXTEVENT_RETURNWITHBUFFER = 0x80, + CONTEXTEVENT_BEGINCALL = 0x100, + CONTEXTEVENT_BEGINENTER = 0x200, + CONTEXTEVENT_BEGINLEAVE = 0x400, + CONTEXTEVENT_BEGINRETURN = 0x800, + CONTEXTEVENT_FINISHCALL = 0x1000, + CONTEXTEVENT_FINISHENTER = 0x2000, + CONTEXTEVENT_FINISHLEAVE = 0x4000, + CONTEXTEVENT_FINISHRETURN = 0x8000, + CONTEXTEVENT_BEGINCALLFILLBUFFER = 0x10000, + CONTEXTEVENT_BEGINENTERWITHBUFFER = 0x20000, + CONTEXTEVENT_FINISHLEAVEFILLBUFFER = 0x40000, + CONTEXTEVENT_FINISHRETURNWITHBUFFER = 0x80000, + CONTEXTEVENT_LEAVEEXCEPTION = 0x100000, + CONTEXTEVENT_LEAVEEXCEPTIONFILLBUFFER = 0x200000, + CONTEXTEVENT_RETURNEXCEPTION = 0x400000, + CONTEXTEVENT_RETURNEXCEPTIONWITHBUFFER = 0x800000, + CONTEXTEVENT_ADDREFPOLICY = 0x10000000, + CONTEXTEVENT_RELEASEPOLICY = 0x20000000 + }; +typedef DWORD ContextEvent; + + +enum tagCPFLAGS + { CPFLAG_NONE = 0, + CPFLAG_PROPAGATE = 0x1, + CPFLAG_EXPOSE = 0x2, + CPFLAG_ENVOY = 0x4, + CPFLAG_MONITORSTUB = 0x8, + CPFLAG_MONITORPROXY = 0x10, + CPFLAG_DONTCOMPARE = 0x20 + }; +typedef DWORD CPFLAGS; + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0000_v0_0_s_ifspec; + +#ifndef __IEnumContextProps_INTERFACE_DEFINED__ +#define __IEnumContextProps_INTERFACE_DEFINED__ + +/* interface IEnumContextProps */ +/* [unique][uuid][object] */ + +typedef /* [unique] */ IEnumContextProps __RPC_FAR *LPENUMCONTEXTPROPS; + + +EXTERN_C const IID IID_IEnumContextProps; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c1-0000-0000-C000-000000000046") + IEnumContextProps : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; + + virtual HRESULT STDMETHODCALLTYPE Count( + /* [out] */ ULONG __RPC_FAR *pcelt) = 0; + + }; + +#else /* C style interface */ + + typedef struct IEnumContextPropsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IEnumContextProps __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IEnumContextProps __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( + IEnumContextProps __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( + IEnumContextProps __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Count )( + IEnumContextProps __RPC_FAR * This, + /* [out] */ ULONG __RPC_FAR *pcelt); + + END_INTERFACE + } IEnumContextPropsVtbl; + + interface IEnumContextProps + { + CONST_VTBL struct IEnumContextPropsVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IEnumContextProps_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IEnumContextProps_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IEnumContextProps_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IEnumContextProps_Next(This,celt,pContextProperties,pceltFetched) \ + (This)->lpVtbl -> Next(This,celt,pContextProperties,pceltFetched) + +#define IEnumContextProps_Skip(This,celt) \ + (This)->lpVtbl -> Skip(This,celt) + +#define IEnumContextProps_Reset(This) \ + (This)->lpVtbl -> Reset(This) + +#define IEnumContextProps_Clone(This,ppEnumContextProps) \ + (This)->lpVtbl -> Clone(This,ppEnumContextProps) + +#define IEnumContextProps_Count(This,pcelt) \ + (This)->lpVtbl -> Count(This,pcelt) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Next_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched); + + +void __RPC_STUB IEnumContextProps_Next_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Skip_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt); + + +void __RPC_STUB IEnumContextProps_Skip_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Reset_Proxy( + IEnumContextProps __RPC_FAR * This); + + +void __RPC_STUB IEnumContextProps_Reset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Clone_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + +void __RPC_STUB IEnumContextProps_Clone_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Count_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [out] */ ULONG __RPC_FAR *pcelt); + + +void __RPC_STUB IEnumContextProps_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IEnumContextProps_INTERFACE_DEFINED__ */ + + +#ifndef __IContext_INTERFACE_DEFINED__ +#define __IContext_INTERFACE_DEFINED__ + +/* interface IContext */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c0-0000-0000-C000-000000000046") + IContext : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProperty( + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemoveProperty( + /* [in] */ REFGUID rPolicyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProperty( + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumContextProps( + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; + + }; + +#else /* C style interface */ + + typedef struct IContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IContext __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IContext __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + IContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + END_INTERFACE + } IContextVtbl; + + interface IContext + { + CONST_VTBL struct IContextVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IContext_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IContext_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IContext_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IContext_SetProperty(This,rpolicyId,flags,pUnk) \ + (This)->lpVtbl -> SetProperty(This,rpolicyId,flags,pUnk) + +#define IContext_RemoveProperty(This,rPolicyId) \ + (This)->lpVtbl -> RemoveProperty(This,rPolicyId) + +#define IContext_GetProperty(This,rGuid,pFlags,ppUnk) \ + (This)->lpVtbl -> GetProperty(This,rGuid,pFlags,ppUnk) + +#define IContext_EnumContextProps(This,ppEnumContextProps) \ + (This)->lpVtbl -> EnumContextProps(This,ppEnumContextProps) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IContext_SetProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + +void __RPC_STUB IContext_SetProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_RemoveProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + +void __RPC_STUB IContext_RemoveProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_GetProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + +void __RPC_STUB IContext_GetProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_EnumContextProps_Proxy( + IContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + +void __RPC_STUB IContext_EnumContextProps_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IContext_INTERFACE_DEFINED__ */ + + +#ifndef __IContextMarshaler_INTERFACE_DEFINED__ +#define __IContextMarshaler_INTERFACE_DEFINED__ + +/* interface IContextMarshaler */ +/* [uuid][object][local] */ + +typedef /* [unique] */ IContextMarshaler __RPC_FAR *LPCTXMARSHALER; + + +EXTERN_C const IID IID_IContextMarshaler; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001D8-0000-0000-C000-000000000046") + IContextMarshaler : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax( + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE MarshalInterface( + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags) = 0; + + }; + +#else /* C style interface */ + + typedef struct IContextMarshalerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IContextMarshaler __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IContextMarshaler __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetMarshalSizeMax )( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalInterface )( + IContextMarshaler __RPC_FAR * This, + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags); + + END_INTERFACE + } IContextMarshalerVtbl; + + interface IContextMarshaler + { + CONST_VTBL struct IContextMarshalerVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IContextMarshaler_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IContextMarshaler_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IContextMarshaler_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IContextMarshaler_GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize) \ + (This)->lpVtbl -> GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize) + +#define IContextMarshaler_MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags) \ + (This)->lpVtbl -> MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IContextMarshaler_GetMarshalSizeMax_Proxy( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize); + + +void __RPC_STUB IContextMarshaler_GetMarshalSizeMax_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContextMarshaler_MarshalInterface_Proxy( + IContextMarshaler __RPC_FAR * This, + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags); + + +void __RPC_STUB IContextMarshaler_MarshalInterface_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IContextMarshaler_INTERFACE_DEFINED__ */ + + +// Placing the following definition here rather than with the IObjContext stuff +// below is a temporary workaround to get around build problems where the system +// objidl.h now has a IObjContext section but has not made much public (all the +// interface methods are marked as reserved and the following typedef does not +// exist). Once the system objidl.h is updated again we can remove the entire +// section. +#ifndef __PFNCTXCALLBACK_HACK +#define __PFNCTXCALLBACK_HACK +typedef /* [ref] */ HRESULT ( __stdcall __RPC_FAR *PFNCTXCALLBACK )( + void __RPC_FAR *pParam); +#endif + +#ifndef __IObjContext_INTERFACE_DEFINED__ +#define __IObjContext_INTERFACE_DEFINED__ + +/* interface IObjContext */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IObjContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c6-0000-0000-C000-000000000046") + IObjContext : public IContext + { + public: + virtual HRESULT STDMETHODCALLTYPE Freeze( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE DoCallback( + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContextMarshaler( + /* [in] */ IContextMarshaler __RPC_FAR *pICM) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContextMarshaler( + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContextFlags( + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearContextFlags( + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContextFlags( + /* [out] */ DWORD __RPC_FAR *pdwFlags) = 0; + + }; + +#else /* C style interface */ + + typedef struct IObjContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IObjContext __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IObjContext __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IObjContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + IObjContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + IObjContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DoCallback )( + IObjContext __RPC_FAR * This, + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextMarshaler )( + IObjContext __RPC_FAR * This, + /* [in] */ IContextMarshaler __RPC_FAR *pICM); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextMarshaler )( + IObjContext __RPC_FAR * This, + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextFlags )( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ClearContextFlags )( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextFlags )( + IObjContext __RPC_FAR * This, + /* [out] */ DWORD __RPC_FAR *pdwFlags); + + END_INTERFACE + } IObjContextVtbl; + + interface IObjContext + { + CONST_VTBL struct IObjContextVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IObjContext_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IObjContext_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IObjContext_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IObjContext_SetProperty(This,rpolicyId,flags,pUnk) \ + (This)->lpVtbl -> SetProperty(This,rpolicyId,flags,pUnk) + +#define IObjContext_RemoveProperty(This,rPolicyId) \ + (This)->lpVtbl -> RemoveProperty(This,rPolicyId) + +#define IObjContext_GetProperty(This,rGuid,pFlags,ppUnk) \ + (This)->lpVtbl -> GetProperty(This,rGuid,pFlags,ppUnk) + +#define IObjContext_EnumContextProps(This,ppEnumContextProps) \ + (This)->lpVtbl -> EnumContextProps(This,ppEnumContextProps) + + +#define IObjContext_Freeze(This) \ + (This)->lpVtbl -> Freeze(This) + +#define IObjContext_DoCallback(This,pfnCallback,pParam,riid,iMethod) \ + (This)->lpVtbl -> DoCallback(This,pfnCallback,pParam,riid,iMethod) + +#define IObjContext_SetContextMarshaler(This,pICM) \ + (This)->lpVtbl -> SetContextMarshaler(This,pICM) + +#define IObjContext_GetContextMarshaler(This,pICM) \ + (This)->lpVtbl -> GetContextMarshaler(This,pICM) + +#define IObjContext_SetContextFlags(This,dwFlags) \ + (This)->lpVtbl -> SetContextFlags(This,dwFlags) + +#define IObjContext_ClearContextFlags(This,dwFlags) \ + (This)->lpVtbl -> ClearContextFlags(This,dwFlags) + +#define IObjContext_GetContextFlags(This,pdwFlags) \ + (This)->lpVtbl -> GetContextFlags(This,pdwFlags) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IObjContext_Freeze_Proxy( + IObjContext __RPC_FAR * This); + + +void __RPC_STUB IObjContext_Freeze_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_DoCallback_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod); + + +void __RPC_STUB IObjContext_DoCallback_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_SetContextMarshaler_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ IContextMarshaler __RPC_FAR *pICM); + + +void __RPC_STUB IObjContext_SetContextMarshaler_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_GetContextMarshaler_Proxy( + IObjContext __RPC_FAR * This, + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); + + +void __RPC_STUB IObjContext_GetContextMarshaler_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_SetContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + +void __RPC_STUB IObjContext_SetContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_ClearContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + +void __RPC_STUB IObjContext_ClearContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_GetContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [out] */ DWORD __RPC_FAR *pdwFlags); + + +void __RPC_STUB IObjContext_GetContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IObjContext_INTERFACE_DEFINED__ */ + + +#ifndef __IGetContextId_INTERFACE_DEFINED__ +#define __IGetContextId_INTERFACE_DEFINED__ + +/* interface IGetContextId */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IGetContextId; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001dd-0000-0000-C000-000000000046") + IGetContextId : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContextId( + /* [out] */ GUID __RPC_FAR *pguidCtxtId) = 0; + + }; + +#else /* C style interface */ + + typedef struct IGetContextIdVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IGetContextId __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IGetContextId __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IGetContextId __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextId )( + IGetContextId __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidCtxtId); + + END_INTERFACE + } IGetContextIdVtbl; + + interface IGetContextId + { + CONST_VTBL struct IGetContextIdVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IGetContextId_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IGetContextId_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IGetContextId_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IGetContextId_GetContextId(This,pguidCtxtId) \ + (This)->lpVtbl -> GetContextId(This,pguidCtxtId) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IGetContextId_GetContextId_Proxy( + IGetContextId __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidCtxtId); + + +void __RPC_STUB IGetContextId_GetContextId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IGetContextId_INTERFACE_DEFINED__ */ + + +#ifndef __IAggregator_INTERFACE_DEFINED__ +#define __IAggregator_INTERFACE_DEFINED__ + +/* interface IAggregator */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ IAggregator __RPC_FAR *IAGGREGATOR; + + +EXTERN_C const IID IID_IAggregator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d8-0000-0000-C000-000000000046") + IAggregator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Aggregate( + /* [in] */ IUnknown __RPC_FAR *pInnerUnk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAggregatorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IAggregator __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IAggregator __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IAggregator __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Aggregate )( + IAggregator __RPC_FAR * This, + /* [in] */ IUnknown __RPC_FAR *pInnerUnk); + + END_INTERFACE + } IAggregatorVtbl; + + interface IAggregator + { + CONST_VTBL struct IAggregatorVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAggregator_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAggregator_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAggregator_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAggregator_Aggregate(This,pInnerUnk) \ + (This)->lpVtbl -> Aggregate(This,pInnerUnk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAggregator_Aggregate_Proxy( + IAggregator __RPC_FAR * This, + /* [in] */ IUnknown __RPC_FAR *pInnerUnk); + + +void __RPC_STUB IAggregator_Aggregate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAggregator_INTERFACE_DEFINED__ */ + + +#ifndef __ICall_INTERFACE_DEFINED__ +#define __ICall_INTERFACE_DEFINED__ + +/* interface ICall */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ ICall __RPC_FAR *LPCALL; + + +EXTERN_C const IID IID_ICall; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d6-0000-0000-C000-000000000046") + ICall : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCallInfo( + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr) = 0; + + virtual HRESULT STDMETHODCALLTYPE Nullify( + /* [in] */ HRESULT hr) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetServerHR( + /* [out] */ HRESULT __RPC_FAR *phr) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICallVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + ICall __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + ICall __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + ICall __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallInfo )( + ICall __RPC_FAR * This, + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Nullify )( + ICall __RPC_FAR * This, + /* [in] */ HRESULT hr); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetServerHR )( + ICall __RPC_FAR * This, + /* [out] */ HRESULT __RPC_FAR *phr); + + END_INTERFACE + } ICallVtbl; + + interface ICall + { + CONST_VTBL struct ICallVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICall_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICall_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICall_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICall_GetCallInfo(This,ppIdentity,piid,pdwMethod,phr) \ + (This)->lpVtbl -> GetCallInfo(This,ppIdentity,piid,pdwMethod,phr) + +#define ICall_Nullify(This,hr) \ + (This)->lpVtbl -> Nullify(This,hr) + +#define ICall_GetServerHR(This,phr) \ + (This)->lpVtbl -> GetServerHR(This,phr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICall_GetCallInfo_Proxy( + ICall __RPC_FAR * This, + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr); + + +void __RPC_STUB ICall_GetCallInfo_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICall_Nullify_Proxy( + ICall __RPC_FAR * This, + /* [in] */ HRESULT hr); + + +void __RPC_STUB ICall_Nullify_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICall_GetServerHR_Proxy( + ICall __RPC_FAR * This, + /* [out] */ HRESULT __RPC_FAR *phr); + + +void __RPC_STUB ICall_GetServerHR_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICall_INTERFACE_DEFINED__ */ + + +#ifndef __IRpcCall_INTERFACE_DEFINED__ +#define __IRpcCall_INTERFACE_DEFINED__ + +/* interface IRpcCall */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ IRpcCall __RPC_FAR *LPRPCCALL; + + +EXTERN_C const IID IID_IRpcCall; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c5-0000-0000-C000-000000000046") + IRpcCall : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRpcOleMessage( + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRpcCallVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IRpcCall __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IRpcCall __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IRpcCall __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRpcOleMessage )( + IRpcCall __RPC_FAR * This, + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); + + END_INTERFACE + } IRpcCallVtbl; + + interface IRpcCall + { + CONST_VTBL struct IRpcCallVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRpcCall_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IRpcCall_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IRpcCall_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IRpcCall_GetRpcOleMessage(This,ppMessage) \ + (This)->lpVtbl -> GetRpcOleMessage(This,ppMessage) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IRpcCall_GetRpcOleMessage_Proxy( + IRpcCall __RPC_FAR * This, + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); + + +void __RPC_STUB IRpcCall_GetRpcOleMessage_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IRpcCall_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0083 */ +/* [local] */ + +typedef +enum _CALLSOURCE + { CALLSOURCE_CROSSAPT = 0, + CALLSOURCE_CROSSCTX = 1 + } CALLSOURCE; + + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0083_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0083_v0_0_s_ifspec; + +#ifndef __ICallInfo_INTERFACE_DEFINED__ +#define __ICallInfo_INTERFACE_DEFINED__ + +/* interface ICallInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_ICallInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001dc-0000-0000-C000-000000000046") + ICallInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCallSource( + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICallInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + ICallInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + ICallInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + ICallInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallSource )( + ICallInfo __RPC_FAR * This, + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); + + END_INTERFACE + } ICallInfoVtbl; + + interface ICallInfo + { + CONST_VTBL struct ICallInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICallInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICallInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICallInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICallInfo_GetCallSource(This,pCallSource) \ + (This)->lpVtbl -> GetCallSource(This,pCallSource) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICallInfo_GetCallSource_Proxy( + ICallInfo __RPC_FAR * This, + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); + + +void __RPC_STUB ICallInfo_GetCallSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICallInfo_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicy_INTERFACE_DEFINED__ +#define __IPolicy_INTERFACE_DEFINED__ + +/* interface IPolicy */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c2-0000-0000-C000-000000000046") + IPolicy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Call( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Enter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Leave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Return( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE CallGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE CallFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnterWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE LeaveGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE LeaveFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReturnWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual ULONG STDMETHODCALLTYPE AddRefPolicy( void) = 0; + + virtual ULONG STDMETHODCALLTYPE ReleasePolicy( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicy __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicy __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Call )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Enter )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Leave )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Return )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallGetSize )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallFillBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnterWithBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveGetSize )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveFillBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReturnWithBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRefPolicy )( + IPolicy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *ReleasePolicy )( + IPolicy __RPC_FAR * This); + + END_INTERFACE + } IPolicyVtbl; + + interface IPolicy + { + CONST_VTBL struct IPolicyVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicy_Call(This,pCall) \ + (This)->lpVtbl -> Call(This,pCall) + +#define IPolicy_Enter(This,pCall) \ + (This)->lpVtbl -> Enter(This,pCall) + +#define IPolicy_Leave(This,pCall) \ + (This)->lpVtbl -> Leave(This,pCall) + +#define IPolicy_Return(This,pCall) \ + (This)->lpVtbl -> Return(This,pCall) + +#define IPolicy_CallGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> CallGetSize(This,pCall,pcb) + +#define IPolicy_CallFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> CallFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicy_EnterWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> EnterWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicy_LeaveGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> LeaveGetSize(This,pCall,pcb) + +#define IPolicy_LeaveFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> LeaveFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicy_ReturnWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> ReturnWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicy_AddRefPolicy(This) \ + (This)->lpVtbl -> AddRefPolicy(This) + +#define IPolicy_ReleasePolicy(This) \ + (This)->lpVtbl -> ReleasePolicy(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicy_Call_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Call_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Enter_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Enter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Leave_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Leave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Return_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Return_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_CallGetSize_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_CallGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_CallFillBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_CallFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_EnterWithBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicy_EnterWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_LeaveGetSize_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_LeaveGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_LeaveFillBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_LeaveFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_ReturnWithBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicy_ReturnWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +ULONG STDMETHODCALLTYPE IPolicy_AddRefPolicy_Proxy( + IPolicy __RPC_FAR * This); + + +void __RPC_STUB IPolicy_AddRefPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +ULONG STDMETHODCALLTYPE IPolicy_ReleasePolicy_Proxy( + IPolicy __RPC_FAR * This); + + +void __RPC_STUB IPolicy_ReleasePolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicy_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicyAsync_INTERFACE_DEFINED__ +#define __IPolicyAsync_INTERFACE_DEFINED__ + +/* interface IPolicyAsync */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicyAsync; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001cd-0000-0000-C000-000000000046") + IPolicyAsync : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BeginCallGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginCall( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginCallFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginEnter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginEnterWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginLeave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginReturn( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishCall( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishEnter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishReturn( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishReturnWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyAsyncVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicyAsync __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicyAsync __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallGetSize )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCall )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallFillBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnter )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnterWithBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginLeave )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginReturn )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishCall )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishEnter )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveGetSize )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeave )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveFillBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturn )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturnWithBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + END_INTERFACE + } IPolicyAsyncVtbl; + + interface IPolicyAsync + { + CONST_VTBL struct IPolicyAsyncVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicyAsync_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicyAsync_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicyAsync_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicyAsync_BeginCallGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> BeginCallGetSize(This,pCall,pcb) + +#define IPolicyAsync_BeginCall(This,pCall) \ + (This)->lpVtbl -> BeginCall(This,pCall) + +#define IPolicyAsync_BeginCallFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> BeginCallFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicyAsync_BeginEnter(This,pCall) \ + (This)->lpVtbl -> BeginEnter(This,pCall) + +#define IPolicyAsync_BeginEnterWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> BeginEnterWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicyAsync_BeginLeave(This,pCall) \ + (This)->lpVtbl -> BeginLeave(This,pCall) + +#define IPolicyAsync_BeginReturn(This,pCall) \ + (This)->lpVtbl -> BeginReturn(This,pCall) + +#define IPolicyAsync_FinishCall(This,pCall) \ + (This)->lpVtbl -> FinishCall(This,pCall) + +#define IPolicyAsync_FinishEnter(This,pCall) \ + (This)->lpVtbl -> FinishEnter(This,pCall) + +#define IPolicyAsync_FinishLeaveGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> FinishLeaveGetSize(This,pCall,pcb) + +#define IPolicyAsync_FinishLeave(This,pCall) \ + (This)->lpVtbl -> FinishLeave(This,pCall) + +#define IPolicyAsync_FinishLeaveFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> FinishLeaveFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicyAsync_FinishReturn(This,pCall) \ + (This)->lpVtbl -> FinishReturn(This,pCall) + +#define IPolicyAsync_FinishReturnWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> FinishReturnWithBuffer(This,pCall,pvBuf,cb) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallGetSize_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_BeginCallGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCall_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginCall_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallFillBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_BeginCallFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnter_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginEnter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnterWithBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicyAsync_BeginEnterWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginLeave_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginLeave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginReturn_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginReturn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishCall_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishCall_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishEnter_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishEnter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveGetSize_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_FinishLeaveGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeave_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishLeave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveFillBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_FinishLeaveFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturn_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishReturn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturnWithBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicyAsync_FinishReturnWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicyAsync_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicySet_INTERFACE_DEFINED__ +#define __IPolicySet_INTERFACE_DEFINED__ + +/* interface IPolicySet */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicySet; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c3-0000-0000-C000-000000000046") + IPolicySet : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddPolicy( + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicySetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicySet __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicySet __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicySet __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddPolicy )( + IPolicySet __RPC_FAR * This, + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy); + + END_INTERFACE + } IPolicySetVtbl; + + interface IPolicySet + { + CONST_VTBL struct IPolicySetVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicySet_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicySet_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicySet_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicySet_AddPolicy(This,ctxEvent,rguid,pPolicy) \ + (This)->lpVtbl -> AddPolicy(This,ctxEvent,rguid,pPolicy) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicySet_AddPolicy_Proxy( + IPolicySet __RPC_FAR * This, + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy); + + +void __RPC_STUB IPolicySet_AddPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicySet_INTERFACE_DEFINED__ */ + + +#ifndef __IComObjIdentity_INTERFACE_DEFINED__ +#define __IComObjIdentity_INTERFACE_DEFINED__ + +/* interface IComObjIdentity */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComObjIdentity; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d7-0000-0000-C000-000000000046") + IComObjIdentity : public IUnknown + { + public: + virtual BOOL STDMETHODCALLTYPE IsServer( void) = 0; + + virtual BOOL STDMETHODCALLTYPE IsDeactivated( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetIdentity( + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComObjIdentityVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComObjIdentity __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComObjIdentity __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComObjIdentity __RPC_FAR * This); + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsServer )( + IComObjIdentity __RPC_FAR * This); + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsDeactivated )( + IComObjIdentity __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIdentity )( + IComObjIdentity __RPC_FAR * This, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + END_INTERFACE + } IComObjIdentityVtbl; + + interface IComObjIdentity + { + CONST_VTBL struct IComObjIdentityVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComObjIdentity_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComObjIdentity_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComObjIdentity_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComObjIdentity_IsServer(This) \ + (This)->lpVtbl -> IsServer(This) + +#define IComObjIdentity_IsDeactivated(This) \ + (This)->lpVtbl -> IsDeactivated(This) + +#define IComObjIdentity_GetIdentity(This,ppUnk) \ + (This)->lpVtbl -> GetIdentity(This,ppUnk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +BOOL STDMETHODCALLTYPE IComObjIdentity_IsServer_Proxy( + IComObjIdentity __RPC_FAR * This); + + +void __RPC_STUB IComObjIdentity_IsServer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +BOOL STDMETHODCALLTYPE IComObjIdentity_IsDeactivated_Proxy( + IComObjIdentity __RPC_FAR * This); + + +void __RPC_STUB IComObjIdentity_IsDeactivated_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComObjIdentity_GetIdentity_Proxy( + IComObjIdentity __RPC_FAR * This, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + +void __RPC_STUB IComObjIdentity_GetIdentity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComObjIdentity_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicyMaker_INTERFACE_DEFINED__ +#define __IPolicyMaker_INTERFACE_DEFINED__ + +/* interface IPolicyMaker */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicyMaker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c4-0000-0000-C000-000000000046") + IPolicyMaker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddClientPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddEnvoyPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddServerPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE Freeze( + /* [in] */ IObjContext __RPC_FAR *pObjContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStub( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyStub( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateProxy( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyProxy( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyMakerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicyMaker __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicyMaker __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddClientPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddEnvoyPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddServerPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IObjContext __RPC_FAR *pObjContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateStub )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyStub )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateProxy )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyProxy )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + END_INTERFACE + } IPolicyMakerVtbl; + + interface IPolicyMaker + { + CONST_VTBL struct IPolicyMakerVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicyMaker_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicyMaker_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicyMaker_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicyMaker_AddClientPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddClientPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_AddEnvoyPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddEnvoyPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_AddServerPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddServerPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_Freeze(This,pObjContext) \ + (This)->lpVtbl -> Freeze(This,pObjContext) + +#define IPolicyMaker_CreateStub(This,pID) \ + (This)->lpVtbl -> CreateStub(This,pID) + +#define IPolicyMaker_DestroyStub(This,pID) \ + (This)->lpVtbl -> DestroyStub(This,pID) + +#define IPolicyMaker_CreateProxy(This,pID) \ + (This)->lpVtbl -> CreateProxy(This,pID) + +#define IPolicyMaker_DestroyProxy(This,pID) \ + (This)->lpVtbl -> DestroyProxy(This,pID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddClientPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddClientPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddEnvoyPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddEnvoyPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddServerPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddServerPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_Freeze_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IObjContext __RPC_FAR *pObjContext); + + +void __RPC_STUB IPolicyMaker_Freeze_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateStub_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_CreateStub_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyStub_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_DestroyStub_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateProxy_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_CreateProxy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyProxy_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_DestroyProxy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicyMaker_INTERFACE_DEFINED__ */ + + +#ifndef __IExceptionNotification_INTERFACE_DEFINED__ +#define __IExceptionNotification_INTERFACE_DEFINED__ + +/* interface IExceptionNotification */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IExceptionNotification; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001db-0000-0000-C000-000000000046") + IExceptionNotification : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE ServerException( + /* [in] */ void __RPC_FAR *pExcepPtrs) = 0; + + }; + +#else /* C style interface */ + + typedef struct IExceptionNotificationVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IExceptionNotification __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IExceptionNotification __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IExceptionNotification __RPC_FAR * This); + + void ( STDMETHODCALLTYPE __RPC_FAR *ServerException )( + IExceptionNotification __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pExcepPtrs); + + END_INTERFACE + } IExceptionNotificationVtbl; + + interface IExceptionNotification + { + CONST_VTBL struct IExceptionNotificationVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IExceptionNotification_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IExceptionNotification_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IExceptionNotification_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IExceptionNotification_ServerException(This,pExcepPtrs) \ + (This)->lpVtbl -> ServerException(This,pExcepPtrs) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +void STDMETHODCALLTYPE IExceptionNotification_ServerException_Proxy( + IExceptionNotification __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pExcepPtrs); + + +void __RPC_STUB IExceptionNotification_ServerException_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IExceptionNotification_INTERFACE_DEFINED__ */ + + +#ifndef __IMarshalEnvoy_INTERFACE_DEFINED__ +#define __IMarshalEnvoy_INTERFACE_DEFINED__ + +/* interface IMarshalEnvoy */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IMarshalEnvoy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c8-0000-0000-C000-000000000046") + IMarshalEnvoy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEnvoyUnmarshalClass( + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEnvoySizeMax( + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE MarshalEnvoy( + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnmarshalEnvoy( + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IMarshalEnvoyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IMarshalEnvoy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IMarshalEnvoy __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoyUnmarshalClass )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoySizeMax )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalEnvoy )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UnmarshalEnvoy )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk); + + END_INTERFACE + } IMarshalEnvoyVtbl; + + interface IMarshalEnvoy + { + CONST_VTBL struct IMarshalEnvoyVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IMarshalEnvoy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IMarshalEnvoy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IMarshalEnvoy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IMarshalEnvoy_GetEnvoyUnmarshalClass(This,dwDestContext,pClsid) \ + (This)->lpVtbl -> GetEnvoyUnmarshalClass(This,dwDestContext,pClsid) + +#define IMarshalEnvoy_GetEnvoySizeMax(This,dwDestContext,pcb) \ + (This)->lpVtbl -> GetEnvoySizeMax(This,dwDestContext,pcb) + +#define IMarshalEnvoy_MarshalEnvoy(This,pStream,dwDestContext) \ + (This)->lpVtbl -> MarshalEnvoy(This,pStream,dwDestContext) + +#define IMarshalEnvoy_UnmarshalEnvoy(This,pStream,riid,ppunk) \ + (This)->lpVtbl -> UnmarshalEnvoy(This,pStream,riid,ppunk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoyUnmarshalClass_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid); + + +void __RPC_STUB IMarshalEnvoy_GetEnvoyUnmarshalClass_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoySizeMax_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb); + + +void __RPC_STUB IMarshalEnvoy_GetEnvoySizeMax_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_MarshalEnvoy_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext); + + +void __RPC_STUB IMarshalEnvoy_MarshalEnvoy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_UnmarshalEnvoy_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk); + + +void __RPC_STUB IMarshalEnvoy_UnmarshalEnvoy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IMarshalEnvoy_INTERFACE_DEFINED__ */ + + +#ifndef __IWrapperInfo_INTERFACE_DEFINED__ +#define __IWrapperInfo_INTERFACE_DEFINED__ + +/* interface IWrapperInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IWrapperInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5052f924-7ab8-11d3-b93f-00c04f990176") + IWrapperInfo : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE SetMapping( + void __RPC_FAR *pv) = 0; + + virtual void __RPC_FAR *STDMETHODCALLTYPE GetMapping( void) = 0; + + virtual IObjContext __RPC_FAR *STDMETHODCALLTYPE GetServerObjectContext( void) = 0; + + virtual IUnknown __RPC_FAR *STDMETHODCALLTYPE GetServerObject( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IWrapperInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IWrapperInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IWrapperInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IWrapperInfo __RPC_FAR * This); + + void ( STDMETHODCALLTYPE __RPC_FAR *SetMapping )( + IWrapperInfo __RPC_FAR * This, + void __RPC_FAR *pv); + + void __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetMapping )( + IWrapperInfo __RPC_FAR * This); + + IObjContext __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObjectContext )( + IWrapperInfo __RPC_FAR * This); + + IUnknown __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObject )( + IWrapperInfo __RPC_FAR * This); + + END_INTERFACE + } IWrapperInfoVtbl; + + interface IWrapperInfo + { + CONST_VTBL struct IWrapperInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IWrapperInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IWrapperInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IWrapperInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IWrapperInfo_SetMapping(This,pv) \ + (This)->lpVtbl -> SetMapping(This,pv) + +#define IWrapperInfo_GetMapping(This) \ + (This)->lpVtbl -> GetMapping(This) + +#define IWrapperInfo_GetServerObjectContext(This) \ + (This)->lpVtbl -> GetServerObjectContext(This) + +#define IWrapperInfo_GetServerObject(This) \ + (This)->lpVtbl -> GetServerObject(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +void STDMETHODCALLTYPE IWrapperInfo_SetMapping_Proxy( + IWrapperInfo __RPC_FAR * This, + void __RPC_FAR *pv); + + +void __RPC_STUB IWrapperInfo_SetMapping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +void __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetMapping_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetMapping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +IObjContext __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObjectContext_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetServerObjectContext_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +IUnknown __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObject_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetServerObject_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IWrapperInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0092 */ +/* [local] */ + + +typedef DWORD APARTMENTID; + + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0092_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0092_v0_0_s_ifspec; + +#ifndef __IComThreadingInfo_INTERFACE_DEFINED__ +#define __IComThreadingInfo_INTERFACE_DEFINED__ + +/* interface IComThreadingInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComThreadingInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001ce-0000-0000-C000-000000000046") + IComThreadingInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCurrentApartmentType( + /* [out] */ APTTYPE __RPC_FAR *pAptType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadType( + /* [out] */ THDTYPE __RPC_FAR *pThreadType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentLogicalThreadId( + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCurrentLogicalThreadId( + /* [in] */ REFGUID rguid) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComThreadingInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComThreadingInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComThreadingInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentApartmentType )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ APTTYPE __RPC_FAR *pAptType); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentThreadType )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ THDTYPE __RPC_FAR *pThreadType); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentLogicalThreadId )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetCurrentLogicalThreadId )( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFGUID rguid); + + END_INTERFACE + } IComThreadingInfoVtbl; + + interface IComThreadingInfo + { + CONST_VTBL struct IComThreadingInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComThreadingInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComThreadingInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComThreadingInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComThreadingInfo_GetCurrentApartmentType(This,pAptType) \ + (This)->lpVtbl -> GetCurrentApartmentType(This,pAptType) + +#define IComThreadingInfo_GetCurrentThreadType(This,pThreadType) \ + (This)->lpVtbl -> GetCurrentThreadType(This,pThreadType) + +#define IComThreadingInfo_GetCurrentLogicalThreadId(This,pguidLogicalThreadId) \ + (This)->lpVtbl -> GetCurrentLogicalThreadId(This,pguidLogicalThreadId) + +#define IComThreadingInfo_SetCurrentLogicalThreadId(This,rguid) \ + (This)->lpVtbl -> SetCurrentLogicalThreadId(This,rguid) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentApartmentType_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ APTTYPE __RPC_FAR *pAptType); + + +void __RPC_STUB IComThreadingInfo_GetCurrentApartmentType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentThreadType_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ THDTYPE __RPC_FAR *pThreadType); + + +void __RPC_STUB IComThreadingInfo_GetCurrentThreadType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentLogicalThreadId_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); + + +void __RPC_STUB IComThreadingInfo_GetCurrentLogicalThreadId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_SetCurrentLogicalThreadId_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFGUID rguid); + + +void __RPC_STUB IComThreadingInfo_SetCurrentLogicalThreadId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComThreadingInfo_INTERFACE_DEFINED__ */ + + +#ifndef __IComDispatchInfo_INTERFACE_DEFINED__ +#define __IComDispatchInfo_INTERFACE_DEFINED__ + +/* interface IComDispatchInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComDispatchInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d9-0000-0000-C000-000000000046") + IComDispatchInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnableComInits( + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE DisableComInits( + /* [in] */ void __RPC_FAR *pvCookie) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComDispatchInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComDispatchInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComDispatchInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnableComInits )( + IComDispatchInfo __RPC_FAR * This, + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DisableComInits )( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pvCookie); + + END_INTERFACE + } IComDispatchInfoVtbl; + + interface IComDispatchInfo + { + CONST_VTBL struct IComDispatchInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComDispatchInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComDispatchInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComDispatchInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComDispatchInfo_EnableComInits(This,ppvCookie) \ + (This)->lpVtbl -> EnableComInits(This,ppvCookie) + +#define IComDispatchInfo_DisableComInits(This,pvCookie) \ + (This)->lpVtbl -> DisableComInits(This,pvCookie) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IComDispatchInfo_EnableComInits_Proxy( + IComDispatchInfo __RPC_FAR * This, + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); + + +void __RPC_STUB IComDispatchInfo_EnableComInits_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComDispatchInfo_DisableComInits_Proxy( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pvCookie); + + +void __RPC_STUB IComDispatchInfo_DisableComInits_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComDispatchInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0094 */ +/* [local] */ + +typedef DWORD HActivator; + +STDAPI CoCreateObjectInContext(IUnknown *pUnk, IObjContext *pObjectCtx, REFIID riid, void **ppv); +STDAPI CoGetApartmentID(APTTYPE dAptType, HActivator* pAptID); +STDAPI CoDeactivateObject(IUnknown *pUnk, IUnknown **ppCookie); +STDAPI CoReactivateObject(IUnknown *pUnk, IUnknown *pCookie); +#define MSHLFLAGS_NO_IEC 0x8 // don't use IExternalConnextion +#define MSHLFLAGS_NO_IMARSHAL 0x10 // don't use IMarshal +#define CONTEXTFLAGS_FROZEN 0x01 // Frozen context +#define CONTEXTFLAGS_ALLOWUNAUTH 0x02 // Allow unauthenticated calls +#define CONTEXTFLAGS_ENVOYCONTEXT 0x04 // Envoy context +#define CONTEXTFLAGS_DEFAULTCONTEXT 0x08 // Default context +#define CONTEXTFLAGS_STATICCONTEXT 0x10 // Static context +#define CONTEXTFLAGS_INPROPTABLE 0x20 // Is in property table +#define CONTEXTFLAGS_INDESTRUCTOR 0x40 // Is in destructor +#define CONTEXTFLAGS_URTPROPPRESENT 0x80 // CLR property added + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0094_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0094_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/coreclr/src/inc/cor.h b/lib/coreclr/src/inc/cor.h new file mode 100644 index 0000000000..034801b05f --- /dev/null +++ b/lib/coreclr/src/inc/cor.h @@ -0,0 +1,2430 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** Cor.h - general header for the Runtime. ** + ** ** + *****************************************************************************/ + + +#ifndef _COR_H_ +#define _COR_H_ + +//***************************************************************************** +// Required includes +#include // Definitions of OLE types. +#include +#include "corerror.h" + +//***************************************************************************** + +#ifdef __cplusplus +extern "C" { +#endif + +// {BED7F4EA-1A96-11d2-8F08-00A0C9A6186D} +EXTERN_GUID(LIBID_ComPlusRuntime, 0xbed7f4ea, 0x1a96, 0x11d2, 0x8f, 0x8, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); + +// {90883F05-3D28-11D2-8F17-00A0C9A6186D} +EXTERN_GUID(GUID_ExportedFromComPlus, 0x90883f05, 0x3d28, 0x11d2, 0x8f, 0x17, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); + +// {0F21F359-AB84-41e8-9A78-36D110E6D2F9} +EXTERN_GUID(GUID_ManagedName, 0xf21f359, 0xab84, 0x41e8, 0x9a, 0x78, 0x36, 0xd1, 0x10, 0xe6, 0xd2, 0xf9); + +// {54FC8F55-38DE-4703-9C4E-250351302B1C} +EXTERN_GUID(GUID_Function2Getter, 0x54fc8f55, 0x38de, 0x4703, 0x9c, 0x4e, 0x25, 0x3, 0x51, 0x30, 0x2b, 0x1c); + +// CLSID_CorMetaDataDispenserRuntime: {1EC2DE53-75CC-11d2-9775-00A0C9B4D50C} +// Dispenser coclass for version 1.5 and 2.0 meta data. To get the "latest" bind +// to CLSID_MetaDataDispenser. +EXTERN_GUID(CLSID_CorMetaDataDispenserRuntime, 0x1ec2de53, 0x75cc, 0x11d2, 0x97, 0x75, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + +// {CD2BC5C9-F452-4326-B714-F9C539D4DA58} +EXTERN_GUID(GUID_DispIdOverride, 0xcd2bc5c9, 0xf452, 0x4326, 0xb7, 0x14, 0xf9, 0xc5, 0x39, 0xd4, 0xda, 0x58); + +// {B64784EB-D8D4-4d9b-9ACD-0E30806426F7} +EXTERN_GUID(GUID_ForceIEnumerable, 0xb64784eb, 0xd8d4, 0x4d9b, 0x9a, 0xcd, 0x0e, 0x30, 0x80, 0x64, 0x26, 0xf7); + +// {2941FF83-88D8-4F73-B6A9-BDF8712D000D} +EXTERN_GUID(GUID_PropGetCA, 0x2941ff83, 0x88d8, 0x4f73, 0xb6, 0xa9, 0xbd, 0xf8, 0x71, 0x2d, 0x00, 0x0d); + +// {29533527-3683-4364-ABC0-DB1ADD822FA2} +EXTERN_GUID(GUID_PropPutCA, 0x29533527, 0x3683, 0x4364, 0xab, 0xc0, 0xdb, 0x1a, 0xdd, 0x82, 0x2f, 0xa2); + +// CLSID_CLR_v1_MetaData: {005023CA-72B1-11D3-9FC4-00C04F79A0A3} +// Used to generate v1 metadata (for v1.0 and v1.1 CLR compatibility). +EXTERN_GUID(CLSID_CLR_v1_MetaData, 0x005023ca, 0x72b1, 0x11d3, 0x9f, 0xc4, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// CLSID_CLR_v2_MetaData: {EFEA471A-44FD-4862-9292-0C58D46E1F3A} +EXTERN_GUID(CLSID_CLR_v2_MetaData, 0xefea471a, 0x44fd, 0x4862, 0x92, 0x92, 0xc, 0x58, 0xd4, 0x6e, 0x1f, 0x3a); + + +// CLSID_CorMetaDataRuntime: +// This will can always be used to generate the "latest" metadata available. +#define CLSID_CorMetaDataRuntime CLSID_CLR_v2_MetaData + + +// {30FE7BE8-D7D9-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataCheckDuplicatesFor, 0x30fe7be8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {DE3856F8-D7D9-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataRefToDefCheck, 0xde3856f8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {E5D71A4C-D7DA-11D2-9F80-00C04F79A0A3} +EXTERN_GUID(MetaDataNotificationForTokenMovement, 0xe5d71a4c, 0xd7da, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +// {2eee315c-d7db-11d2-9f80-00c04f79a0a3} +EXTERN_GUID(MetaDataSetUpdate, 0x2eee315c, 0xd7db, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); +#define MetaDataSetENC MetaDataSetUpdate + +// Use this guid in SetOption to indicate if the import enumerator should skip over +// delete items or not. The default is yes. +// +// {79700F36-4AAC-11d3-84C3-009027868CB1} +EXTERN_GUID(MetaDataImportOption, 0x79700f36, 0x4aac, 0x11d3, 0x84, 0xc3, 0x0, 0x90, 0x27, 0x86, 0x8c, 0xb1); + +// Use this guid in the SetOption if compiler wants to have MetaData API to take reader/writer lock +// +// {F7559806-F266-42ea-8C63-0ADB45E8B234} +EXTERN_GUID(MetaDataThreadSafetyOptions, 0xf7559806, 0xf266, 0x42ea, 0x8c, 0x63, 0xa, 0xdb, 0x45, 0xe8, 0xb2, 0x34); + +// Use this guid in the SetOption if compiler wants error when some tokens are emitted out of order +// {1547872D-DC03-11d2-9420-0000F8083460} +EXTERN_GUID(MetaDataErrorIfEmitOutOfOrder, 0x1547872d, 0xdc03, 0x11d2, 0x94, 0x20, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); + +// Use this guid in the SetOption to indicate if the tlbimporter should generate the +// TCE adapters for COM connection point containers. +// {DCC9DE90-4151-11d3-88D6-00902754C43A} +EXTERN_GUID(MetaDataGenerateTCEAdapters, 0xdcc9de90, 0x4151, 0x11d3, 0x88, 0xd6, 0x0, 0x90, 0x27, 0x54, 0xc4, 0x3a); + +// Use this guid in the SetOption to specifiy a non-default namespace for typelib import. +// {F17FF889-5A63-11d3-9FF2-00C04FF7431A} +EXTERN_GUID(MetaDataTypeLibImportNamespace, 0xf17ff889, 0x5a63, 0x11d3, 0x9f, 0xf2, 0x0, 0xc0, 0x4f, 0xf7, 0x43, 0x1a); + +// Use this guid in the SetOption to specify the behavior of UnmarkAll. See CorLinkerOptions. +// {47E099B6-AE7C-4797-8317-B48AA645B8F9} +EXTERN_GUID(MetaDataLinkerOptions, 0x47e099b6, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); + +// Use this guid in the SetOption to specify the runtime version stored in the CLR metadata. +// {47E099B7-AE7C-4797-8317-B48AA645B8F9} +EXTERN_GUID(MetaDataRuntimeVersion, 0x47e099b7, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); + +// Use this guid in the SetOption to specify the behavior of the merger. +// {132D3A6E-B35D-464e-951A-42EFB9FB6601} +EXTERN_GUID(MetaDataMergerOptions, 0x132d3a6e, 0xb35d, 0x464e, 0x95, 0x1a, 0x42, 0xef, 0xb9, 0xfb, 0x66, 0x1); + +// Use this guid in SetOption to disable optimizing module-local refs to defs +// {a55c0354-e91b-468b-8648-7cc31035d533} +EXTERN_GUID(MetaDataPreserveLocalRefs, 0xa55c0354, 0xe91b, 0x468b, 0x86, 0x48, 0x7c, 0xc3, 0x10, 0x35, 0xd5, 0x33); + +interface IMetaDataImport; +interface IMetaDataAssemblyEmit; +interface IMetaDataAssemblyImport; +interface IMetaDataEmit; +interface ICeeGen; + + +typedef UNALIGNED void const *UVCP_CONSTANT; + + +// Constant for connection id and task id +#define INVALID_CONNECTION_ID 0x0 +#define INVALID_TASK_ID 0x0 +#define MAX_CONNECTION_NAME MAX_PATH + + +#define MAIN_CLR_MODULE_NAME_W W("coreclr") +#define MAIN_CLR_MODULE_NAME_A "coreclr" + +#define MAIN_CLR_DLL_NAME_W MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W) +#define MAIN_CLR_DLL_NAME_A MAKEDLLNAME_A(MAIN_CLR_MODULE_NAME_A) + + +#define MSCOREE_SHIM_W MAIN_CLR_DLL_NAME_W +#define MSCOREE_SHIM_A MAIN_CLR_DLL_NAME_A + +#define SWITCHOUT_HANDLE_VALUE ((HANDLE)(LONG_PTR)-2) + +// +// CoInitializeEE flags. +// +typedef enum tagCOINITEE +{ + COINITEE_DEFAULT = 0x0, // Default initialization mode. + COINITEE_DLL = 0x1, // Initialization mode for loading DLL. + COINITEE_MAIN = 0x2 // Initialize prior to entering the main routine +} COINITIEE; + +//***************************************************************************** +//***************************************************************************** +// +// I L & F I L E F O R M A T D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + + +// +#ifndef _WINDOWS_UPDATES_ +#include +#endif // updates + +//***************************************************************************** +//***************************************************************************** + +// CLSID_Cor: {bee00000-ee77-11d0-a015-00c04fbbb884} +EXTERN_GUID(CLSID_Cor, 0xbee00010, 0xee77, 0x11d0, 0xa0, 0x15, 0x00, 0xc0, 0x4f, 0xbb, 0xb8, 0x84); + +// CLSID_CorMetaDataDispenser: {E5CB7A31-7512-11d2-89CE-0080C792E5D8} +// This is the "Master Dispenser", always guaranteed to be the most recent +// dispenser on the machine. +EXTERN_GUID(CLSID_CorMetaDataDispenser, 0xe5cb7a31, 0x7512, 0x11d2, 0x89, 0xce, 0x0, 0x80, 0xc7, 0x92, 0xe5, 0xd8); + + +// CLSID_CorMetaDataDispenserReg: {435755FF-7397-11d2-9771-00A0C9B4D50C} +// Dispenser coclass for version 1.0 meta data. To get the "latest" bind +// to CLSID_CorMetaDataDispenser. +EXTERN_GUID(CLSID_CorMetaDataDispenserReg, 0x435755ff, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + + +// CLSID_CorMetaDataReg: {87F3A1F5-7397-11d2-9771-00A0C9B4D50C} +// For COM+ Meta Data, Data Driven Registration +EXTERN_GUID(CLSID_CorMetaDataReg, 0x87f3a1f5, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); + + +interface IMetaDataDispenser; + +//------------------------------------- +//--- IMetaDataError +//------------------------------------- +// {B81FF171-20F3-11d2-8DCC-00A0C9B09C19} +EXTERN_GUID(IID_IMetaDataError, 0xb81ff171, 0x20f3, 0x11d2, 0x8d, 0xcc, 0x0, 0xa0, 0xc9, 0xb0, 0x9c, 0x19); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataError +DECLARE_INTERFACE_(IMetaDataError, IUnknown) +{ + STDMETHOD(OnError)(HRESULT hrError, mdToken token) PURE; +}; + +//------------------------------------- +//--- IMapToken +//------------------------------------- +// IID_IMapToken: {06A3EA8B-0225-11d1-BF72-00C04FC31E12} +EXTERN_GUID(IID_IMapToken, 0x6a3ea8b, 0x225, 0x11d1, 0xbf, 0x72, 0x0, 0xc0, 0x4f, 0xc3, 0x1e, 0x12); + +//--- +#undef INTERFACE +#define INTERFACE IMapToken +DECLARE_INTERFACE_(IMapToken, IUnknown) +{ + STDMETHOD(Map)(mdToken tkImp, mdToken tkEmit) PURE; +}; + +//------------------------------------- +//--- IMetaDataDispenser +//------------------------------------- +// {809C652E-7396-11D2-9771-00A0C9B4D50C} +EXTERN_GUID(IID_IMetaDataDispenser, 0x809c652e, 0x7396, 0x11d2, 0x97, 0x71, 0x00, 0xa0, 0xc9, 0xb4, 0xd5, 0x0c); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataDispenser +DECLARE_INTERFACE_(IMetaDataDispenser, IUnknown) +{ + STDMETHOD(DefineScope)( // Return code. + REFCLSID rclsid, // [in] What version to create. + DWORD dwCreateFlags, // [in] Flags on the create. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(OpenScope)( // Return code. + LPCWSTR szScope, // [in] The scope to open. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(OpenScopeOnMemory)( // Return code. + LPCVOID pData, // [in] Location of scope data. + ULONG cbData, // [in] Size of the data pointed to by pData. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. +}; + +//------------------------------------- +//--- IMetaDataEmit +//------------------------------------- +// {BA3FEE4C-ECB9-4e41-83B7-183FA41CD859} +EXTERN_GUID(IID_IMetaDataEmit, 0xba3fee4c, 0xecb9, 0x4e41, 0x83, 0xb7, 0x18, 0x3f, 0xa4, 0x1c, 0xd8, 0x59); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataEmit +DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) +{ + STDMETHOD(SetModuleProps)( // S_OK or error. + LPCWSTR szName) PURE; // [IN] If not NULL, the name of the module to set. + + STDMETHOD(Save)( // S_OK or error. + LPCWSTR szFile, // [IN] The filename to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveToStream)( // S_OK or error. + IStream *pIStream, // [IN] A writable stream to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(GetSaveSize)( // S_OK or error. + CorSaveSize fSave, // [IN] cssAccurate or cssQuick. + DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. + + STDMETHOD(DefineTypeDef)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of TypeDef + DWORD dwTypeDefFlags, // [IN] CustomAttribute flags + mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken rtkImplements[], // [IN] Implements interfaces + mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here + + STDMETHOD(DefineNestedType)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of TypeDef + DWORD dwTypeDefFlags, // [IN] CustomAttribute flags + mdToken tkExtends, // [IN] extends this TypeDef or typeref + mdToken rtkImplements[], // [IN] Implements interfaces + mdTypeDef tdEncloser, // [IN] TypeDef token of the enclosing type. + mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here + + STDMETHOD(SetHandler)( // S_OK. + IUnknown *pUnk) PURE; // [IN] The new error handler. + + STDMETHOD(DefineMethod)( // S_OK or error. + mdTypeDef td, // Parent TypeDef + LPCWSTR szName, // Name of member + DWORD dwMethodFlags, // Member attributes + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + ULONG ulCodeRVA, + DWORD dwImplFlags, + mdMethodDef *pmd) PURE; // Put member token here + + STDMETHOD(DefineMethodImpl)( // S_OK or error. + mdTypeDef td, // [IN] The class implementing the method + mdToken tkBody, // [IN] Method body - MethodDef or MethodRef + mdToken tkDecl) PURE; // [IN] Method declaration - MethodDef or MethodRef + + STDMETHOD(DefineTypeRefByName)( // S_OK or error. + mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. + LPCWSTR szName, // [IN] Name of the TypeRef. + mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. + + STDMETHOD(DefineImportType)( // S_OK or error. + IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the TypeDef. + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *pImport, // [IN] Scope containing the TypeDef. + mdTypeDef tdImport, // [IN] The imported TypeDef. + IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the TypeDef is imported. + mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. + + STDMETHOD(DefineMemberRef)( // S_OK or error + mdToken tkImport, // [IN] ClassRef or ClassDef importing a member. + LPCWSTR szName, // [IN] member's name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMemberRef *pmr) PURE; // [OUT] memberref token + + STDMETHOD(DefineImportMember)( // S_OK or error. + IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the Member. + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *pImport, // [IN] Import scope, with member. + mdToken mbMember, // [IN] Member in import scope. + IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the Member is imported. + mdToken tkParent, // [IN] Classref or classdef in emit scope. + mdMemberRef *pmr) PURE; // [OUT] Put member ref here. + + STDMETHOD(DefineEvent) ( + mdTypeDef td, // [IN] the class/interface on which the event is being defined + LPCWSTR szEvent, // [IN] Name of the event + DWORD dwEventFlags, // [IN] CorEventAttr + mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class + mdMethodDef mdAddOn, // [IN] required add method + mdMethodDef mdRemoveOn, // [IN] required remove method + mdMethodDef mdFire, // [IN] optional fire method + mdMethodDef rmdOtherMethods[], // [IN] optional array of other methods associate with the event + mdEvent *pmdEvent) PURE; // [OUT] output event token + + STDMETHOD(SetClassLayout) ( + mdTypeDef td, // [IN] typedef + DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16 + COR_FIELD_OFFSET rFieldOffsets[], // [IN] array of layout specification + ULONG ulClassSize) PURE; // [IN] size of the class + + STDMETHOD(DeleteClassLayout) ( + mdTypeDef td) PURE; // [IN] typedef whose layout is to be deleted. + + STDMETHOD(SetFieldMarshal) ( + mdToken tk, // [IN] given a fieldDef or paramDef token + PCCOR_SIGNATURE pvNativeType, // [IN] native type specification + ULONG cbNativeType) PURE; // [IN] count of bytes of pvNativeType + + STDMETHOD(DeleteFieldMarshal) ( + mdToken tk) PURE; // [IN] given a fieldDef or paramDef token + + STDMETHOD(DefinePermissionSet) ( + mdToken tk, // [IN] the object to be decorated. + DWORD dwAction, // [IN] CorDeclSecurity. + void const *pvPermission, // [IN] permission blob. + ULONG cbPermission, // [IN] count of bytes of pvPermission. + mdPermission *ppm) PURE; // [OUT] returned permission token. + + STDMETHOD(SetRVA)( // S_OK or error. + mdMethodDef md, // [IN] Method for which to set offset + ULONG ulRVA) PURE; // [IN] The offset + + STDMETHOD(GetTokenFromSig)( // S_OK or error. + PCCOR_SIGNATURE pvSig, // [IN] Signature to define. + ULONG cbSig, // [IN] Size of signature data. + mdSignature *pmsig) PURE; // [OUT] returned signature token. + + STDMETHOD(DefineModuleRef)( // S_OK or error. + LPCWSTR szName, // [IN] DLL name + mdModuleRef *pmur) PURE; // [OUT] returned + + // @FUTURE: This should go away once everyone starts using SetMemberRefProps. + STDMETHOD(SetParent)( // S_OK or error. + mdMemberRef mr, // [IN] Token for the ref to be fixed up. + mdToken tk) PURE; // [IN] The ref parent. + + STDMETHOD(GetTokenFromTypeSpec)( // S_OK or error. + PCCOR_SIGNATURE pvSig, // [IN] TypeSpec Signature to define. + ULONG cbSig, // [IN] Size of signature data. + mdTypeSpec *ptypespec) PURE; // [OUT] returned TypeSpec token. + + STDMETHOD(SaveToMemory)( // S_OK or error. + void *pbData, // [OUT] Location to write data. + ULONG cbData) PURE; // [IN] Max size of data buffer. + + STDMETHOD(DefineUserString)( // Return code. + LPCWSTR szString, // [IN] User literal string. + ULONG cchString, // [IN] Length of string. + mdString *pstk) PURE; // [OUT] String token. + + STDMETHOD(DeleteToken)( // Return code. + mdToken tkObj) PURE; // [IN] The token to be deleted + + STDMETHOD(SetMethodProps)( // S_OK or error. + mdMethodDef md, // [IN] The MethodDef. + DWORD dwMethodFlags, // [IN] Method attributes. + ULONG ulCodeRVA, // [IN] Code RVA. + DWORD dwImplFlags) PURE; // [IN] Impl flags. + + STDMETHOD(SetTypeDefProps)( // S_OK or error. + mdTypeDef td, // [IN] The TypeDef. + DWORD dwTypeDefFlags, // [IN] TypeDef flags. + mdToken tkExtends, // [IN] Base TypeDef or TypeRef. + mdToken rtkImplements[]) PURE; // [IN] Implemented interfaces. + + STDMETHOD(SetEventProps)( // S_OK or error. + mdEvent ev, // [IN] The event token. + DWORD dwEventFlags, // [IN] CorEventAttr. + mdToken tkEventType, // [IN] A reference (mdTypeRef or mdTypeRef) to the Event class. + mdMethodDef mdAddOn, // [IN] Add method. + mdMethodDef mdRemoveOn, // [IN] Remove method. + mdMethodDef mdFire, // [IN] Fire method. + mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods associate with the event. + + STDMETHOD(SetPermissionSetProps)( // S_OK or error. + mdToken tk, // [IN] The object to be decorated. + DWORD dwAction, // [IN] CorDeclSecurity. + void const *pvPermission, // [IN] Permission blob. + ULONG cbPermission, // [IN] Count of bytes of pvPermission. + mdPermission *ppm) PURE; // [OUT] Permission token. + + STDMETHOD(DefinePinvokeMap)( // Return code. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD dwMappingFlags, // [IN] Flags used for mapping. + LPCWSTR szImportName, // [IN] Import name. + mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. + + STDMETHOD(SetPinvokeMap)( // Return code. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD dwMappingFlags, // [IN] Flags used for mapping. + LPCWSTR szImportName, // [IN] Import name. + mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. + + STDMETHOD(DeletePinvokeMap)( // Return code. + mdToken tk) PURE; // [IN] FieldDef or MethodDef. + + // New CustomAttribute functions. + STDMETHOD(DefineCustomAttribute)( // Return code. + mdToken tkOwner, // [IN] The object to put the value on. + mdToken tkCtor, // [IN] Constructor of the CustomAttribute type (MemberRef/MethodDef). + void const *pCustomAttribute, // [IN] The custom value data. + ULONG cbCustomAttribute, // [IN] The custom value data length. + mdCustomAttribute *pcv) PURE; // [OUT] The custom value token value on return. + + STDMETHOD(SetCustomAttributeValue)( // Return code. + mdCustomAttribute pcv, // [IN] The custom value token whose value to replace. + void const *pCustomAttribute, // [IN] The custom value data. + ULONG cbCustomAttribute) PURE;// [IN] The custom value data length. + + STDMETHOD(DefineField)( // S_OK or error. + mdTypeDef td, // Parent TypeDef + LPCWSTR szName, // Name of member + DWORD dwFieldFlags, // Member attributes + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdFieldDef *pmd) PURE; // [OUT] Put member token here + + STDMETHOD(DefineProperty)( + mdTypeDef td, // [IN] the class/interface on which the property is being defined + LPCWSTR szProperty, // [IN] Name of the property + DWORD dwPropFlags, // [IN] CorPropertyAttr + PCCOR_SIGNATURE pvSig, // [IN] the required type signature + ULONG cbSig, // [IN] the size of the type signature blob + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdMethodDef mdSetter, // [IN] optional setter of the property + mdMethodDef mdGetter, // [IN] optional getter of the property + mdMethodDef rmdOtherMethods[], // [IN] an optional array of other methods + mdProperty *pmdProp) PURE; // [OUT] output property token + + STDMETHOD(DefineParam)( + mdMethodDef md, // [IN] Owning method + ULONG ulParamSeq, // [IN] Which param + LPCWSTR szName, // [IN] Optional param name + DWORD dwParamFlags, // [IN] Optional param flags + DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* + void const *pValue, // [IN] constant value + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdParamDef *ppd) PURE; // [OUT] Put param token here + + STDMETHOD(SetFieldProps)( // S_OK or error. + mdFieldDef fd, // [IN] The FieldDef. + DWORD dwFieldFlags, // [IN] Field attributes. + DWORD dwCPlusTypeFlag, // [IN] Flag for the value type, selected ELEMENT_TYPE_* + void const *pValue, // [IN] Constant value. + ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). + + STDMETHOD(SetPropertyProps)( // S_OK or error. + mdProperty pr, // [IN] Property token. + DWORD dwPropFlags, // [IN] CorPropertyAttr. + DWORD dwCPlusTypeFlag, // [IN] Flag for value type, selected ELEMENT_TYPE_* + void const *pValue, // [IN] Constant value. + ULONG cchValue, // [IN] size of constant value (string, in wide chars). + mdMethodDef mdSetter, // [IN] Setter of the property. + mdMethodDef mdGetter, // [IN] Getter of the property. + mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods. + + STDMETHOD(SetParamProps)( // Return code. + mdParamDef pd, // [IN] Param token. + LPCWSTR szName, // [IN] Param name. + DWORD dwParamFlags, // [IN] Param flags. + DWORD dwCPlusTypeFlag, // [IN] Flag for value type. selected ELEMENT_TYPE_*. + void const *pValue, // [OUT] Constant value. + ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). + + // Specialized Custom Attributes for security. + STDMETHOD(DefineSecurityAttributeSet)( // Return code. + mdToken tkObj, // [IN] Class or method requiring security attributes. + COR_SECATTR rSecAttrs[], // [IN] Array of security attribute descriptions. + ULONG cSecAttrs, // [IN] Count of elements in above array. + ULONG *pulErrorAttr) PURE; // [OUT] On error, index of attribute causing problem. + + STDMETHOD(ApplyEditAndContinue)( // S_OK or error. + IUnknown *pImport) PURE; // [IN] Metadata from the delta PE. + + STDMETHOD(TranslateSigWithScope)( + IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *import, // [IN] importing interface + PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope + ULONG cbSigBlob, // [IN] count of bytes of signature + IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface + IMetaDataEmit *emit, // [IN] emit interface + PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature + ULONG cbTranslatedSigMax, + ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature + + STDMETHOD(SetMethodImplFlags)( // [IN] S_OK or error. + mdMethodDef md, // [IN] Method for which to set ImplFlags + DWORD dwImplFlags) PURE; + + STDMETHOD(SetFieldRVA)( // [IN] S_OK or error. + mdFieldDef fd, // [IN] Field for which to set offset + ULONG ulRVA) PURE; // [IN] The offset + + STDMETHOD(Merge)( // S_OK or error. + IMetaDataImport *pImport, // [IN] The scope to be merged. + IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification + IUnknown *pHandler) PURE; // [IN] An object to receive to receive error notification. + + STDMETHOD(MergeEnd)() PURE; // S_OK or error. + + // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. + +}; // IMetaDataEmit + +//------------------------------------- +//--- IMetaDataEmit2 +//------------------------------------- +// {F5DD9950-F693-42e6-830E-7B833E8146A9} +EXTERN_GUID(IID_IMetaDataEmit2, 0xf5dd9950, 0xf693, 0x42e6, 0x83, 0xe, 0x7b, 0x83, 0x3e, 0x81, 0x46, 0xa9); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataEmit2 +DECLARE_INTERFACE_(IMetaDataEmit2, IMetaDataEmit) +{ + STDMETHOD(DefineMethodSpec)( + mdToken tkParent, // [IN] MethodDef or MemberRef + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMethodSpec *pmi) PURE; // [OUT] method instantiation token + + STDMETHOD(GetDeltaSaveSize)( // S_OK or error. + CorSaveSize fSave, // [IN] cssAccurate or cssQuick. + DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. + + STDMETHOD(SaveDelta)( // S_OK or error. + LPCWSTR szFile, // [IN] The filename to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveDeltaToStream)( // S_OK or error. + IStream *pIStream, // [IN] A writable stream to save to. + DWORD dwSaveFlags) PURE; // [IN] Flags for the save. + + STDMETHOD(SaveDeltaToMemory)( // S_OK or error. + void *pbData, // [OUT] Location to write data. + ULONG cbData) PURE; // [IN] Max size of data buffer. + + STDMETHOD(DefineGenericParam)( // S_OK or error. + mdToken tk, // [IN] TypeDef or MethodDef + ULONG ulParamSeq, // [IN] Index of the type parameter + DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) + LPCWSTR szname, // [IN] Name + DWORD reserved, // [IN] For future use (e.g. non-type parameters) + mdToken rtkConstraints[], // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) + mdGenericParam *pgp) PURE; // [OUT] Put GenericParam token here + + STDMETHOD(SetGenericParamProps)( // S_OK or error. + mdGenericParam gp, // [IN] GenericParam + DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) + LPCWSTR szName, // [IN] Optional name + DWORD reserved, // [IN] For future use (e.g. non-type parameters) + mdToken rtkConstraints[]) PURE;// [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) + + STDMETHOD(ResetENCLog)() PURE; // S_OK or error. + +}; + +//------------------------------------- +//--- IMetaDataImport +//------------------------------------- +// {7DAC8207-D3AE-4c75-9B67-92801A497D44} +EXTERN_GUID(IID_IMetaDataImport, 0x7dac8207, 0xd3ae, 0x4c75, 0x9b, 0x67, 0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataImport +DECLARE_INTERFACE_(IMetaDataImport, IUnknown) +{ + STDMETHOD_(void, CloseEnum)(HCORENUM hEnum) PURE; + STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG *pulCount) PURE; + STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) PURE; + STDMETHOD(EnumTypeDefs)(HCORENUM *phEnum, mdTypeDef rTypeDefs[], + ULONG cMax, ULONG *pcTypeDefs) PURE; + STDMETHOD(EnumInterfaceImpls)(HCORENUM *phEnum, mdTypeDef td, + mdInterfaceImpl rImpls[], ULONG cMax, + ULONG* pcImpls) PURE; + STDMETHOD(EnumTypeRefs)(HCORENUM *phEnum, mdTypeRef rTypeRefs[], + ULONG cMax, ULONG* pcTypeRefs) PURE; + + STDMETHOD(FindTypeDefByName)( // S_OK or error. + LPCWSTR szTypeDef, // [IN] Name of the Type. + mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class. + mdTypeDef *ptd) PURE; // [OUT] Put the TypeDef token here. + + STDMETHOD(GetScopeProps)( // S_OK or error. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Put the name here. + ULONG cchName, // [IN] Size of name buffer in wide chars. + ULONG *pchName, // [OUT] Put size of name (wide chars) here. + GUID *pmvid) PURE; // [OUT, OPTIONAL] Put MVID here. + + STDMETHOD(GetModuleFromScope)( // S_OK. + mdModule *pmd) PURE; // [OUT] Put mdModule token here. + + STDMETHOD(GetTypeDefProps)( // S_OK or error. + mdTypeDef td, // [IN] TypeDef token for inquiry. + _Out_writes_to_opt_(cchTypeDef, *pchTypeDef) + LPWSTR szTypeDef, // [OUT] Put name here. + ULONG cchTypeDef, // [IN] size of name buffer in wide chars. + ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here. + DWORD *pdwTypeDefFlags, // [OUT] Put flags here. + mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here. + + STDMETHOD(GetInterfaceImplProps)( // S_OK or error. + mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. + mdTypeDef *pClass, // [OUT] Put implementing class token here. + mdToken *ptkIface) PURE; // [OUT] Put implemented interface token here. + + STDMETHOD(GetTypeRefProps)( // S_OK or error. + mdTypeRef tr, // [IN] TypeRef token. + mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Name of the TypeRef. + ULONG cchName, // [IN] Size of buffer. + ULONG *pchName) PURE; // [OUT] Size of Name. + + STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) PURE; + + STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdToken rMembers[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMembersWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdToken rMembers[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdMethodDef rMethods[], // [OUT] Put MethodDefs here. + ULONG cMax, // [IN] Max MethodDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethodsWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdMethodDef rMethods[], // [OU] Put MethodDefs here. + ULONG cMax, // [IN] Max MethodDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFields)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + mdFieldDef rFields[], // [OUT] Put FieldDefs here. + ULONG cMax, // [IN] Max FieldDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFieldsWithName)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef cl, // [IN] TypeDef to scope the enumeration. + LPCWSTR szName, // [IN] Limit results to those with this name. + mdFieldDef rFields[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + + STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdParamDef rParams[], // [OUT] Put ParamDefs here. + ULONG cMax, // [IN] Max ParamDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tkParent, // [IN] Parent token to scope the enumeration. + mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. + ULONG cMax, // [IN] Max MemberRefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumMethodImpls)( // S_OK, S_FALSE, or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdToken rMethodBody[], // [OUT] Put Method Body tokens here. + mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here. + ULONG cMax, // [IN] Max tokens to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] if !NIL, token to scope the enumeration. + DWORD dwActions, // [IN] if !0, return only these actions. + mdPermission rPermission[], // [OUT] Put Permissions here. + ULONG cMax, // [IN] Max Permissions to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(FindMember)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdToken *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindMethod)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMethodDef *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindField)( + mdTypeDef td, // [IN] given typedef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdFieldDef *pmb) PURE; // [OUT] matching memberdef + + STDMETHOD(FindMemberRef)( + mdTypeRef td, // [IN] given typeRef + LPCWSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMemberRef *pmr) PURE; // [OUT] matching memberref + + STDMETHOD (GetMethodProps)( + mdMethodDef mb, // The method for which to get props. + mdTypeDef *pClass, // Put method's class here. + _Out_writes_to_opt_(cchMethod, *pchMethod) + LPWSTR szMethod, // Put method's name here. + ULONG cchMethod, // Size of szMethod buffer in wide chars. + ULONG *pchMethod, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + ULONG *pulCodeRVA, // [OUT] codeRVA + DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags + + STDMETHOD(GetMemberRefProps)( // S_OK or error. + mdMemberRef mr, // [IN] given memberref + mdToken *ptk, // [OUT] Put classref or classdef here. + _Out_writes_to_opt_(cchMember, *pchMember) + LPWSTR szMember, // [OUT] buffer to fill for member's name + ULONG cchMember, // [IN] the count of char of szMember + ULONG *pchMember, // [OUT] actual count of char in member name + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value + ULONG *pbSig) PURE; // [OUT] actual size of signature blob + + STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdProperty rProperties[], // [OUT] Put Properties here. + ULONG cMax, // [IN] Max properties to put. + ULONG *pcProperties) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdTypeDef td, // [IN] TypeDef to scope the enumeration. + mdEvent rEvents[], // [OUT] Put events here. + ULONG cMax, // [IN] Max events to put. + ULONG *pcEvents) PURE; // [OUT] Put # put here. + + STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. + mdEvent ev, // [IN] event token + mdTypeDef *pClass, // [OUT] typedef containing the event declarion. + LPCWSTR szEvent, // [OUT] Event name + ULONG cchEvent, // [IN] the count of wchar of szEvent + ULONG *pchEvent, // [OUT] actual count of wchar for event's name + DWORD *pdwEventFlags, // [OUT] Event flags. + mdToken *ptkEventType, // [OUT] EventType class + mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event + mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event + mdMethodDef *pmdFire, // [OUT] Fire method of the event + mdMethodDef rmdOtherMethod[], // [OUT] other method of the event + ULONG cMax, // [IN] size of rmdOtherMethod + ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this event + + STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdMethodDef mb, // [IN] MethodDef to scope the enumeration. + mdToken rEventProp[], // [OUT] Put Event/Property here. + ULONG cMax, // [IN] Max properties to put. + ULONG *pcEventProp) PURE; // [OUT] Put # put here. + + STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. + mdMethodDef mb, // [IN] method token + mdToken tkEventProp, // [IN] event/property token. + DWORD *pdwSemanticsFlags) PURE; // [OUT] the role flags for the method/propevent pair + + STDMETHOD(GetClassLayout) ( + mdTypeDef td, // [IN] give typedef + DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 + COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array + ULONG cMax, // [IN] size of the array + ULONG *pcFieldOffset, // [OUT] needed array size + ULONG *pulClassSize) PURE; // [OUT] the size of the class + + STDMETHOD(GetFieldMarshal) ( + mdToken tk, // [IN] given a field's memberdef + PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field + ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType + + STDMETHOD(GetRVA)( // S_OK or error. + mdToken tk, // Member for which to set offset + ULONG *pulCodeRVA, // The offset + DWORD *pdwImplFlags) PURE; // the implementation flags + + STDMETHOD(GetPermissionSetProps) ( + mdPermission pm, // [IN] the permission token. + DWORD *pdwAction, // [OUT] CorDeclSecurity. + void const **ppvPermission, // [OUT] permission blob. + ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. + + STDMETHOD(GetSigFromToken)( // S_OK or error. + mdSignature mdSig, // [IN] Signature token. + PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. + ULONG *pcbSig) PURE; // [OUT] return size of signature. + + STDMETHOD(GetModuleRefProps)( // S_OK or error. + mdModuleRef mur, // [IN] moduleref token. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] buffer to fill with the moduleref name. + ULONG cchName, // [IN] size of szName in wide characters. + ULONG *pchName) PURE; // [OUT] actual count of characters in the name. + + STDMETHOD(EnumModuleRefs)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdModuleRef rModuleRefs[], // [OUT] put modulerefs here. + ULONG cmax, // [IN] max memberrefs to put. + ULONG *pcModuleRefs) PURE; // [OUT] put # put here. + + STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. + mdTypeSpec typespec, // [IN] TypeSpec token. + PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature + ULONG *pcbSig) PURE; // [OUT] return size of signature. + + STDMETHOD(GetNameFromToken)( // Not Recommended! May be removed! + mdToken tk, // [IN] Token to get name from. Must have a name. + MDUTF8CSTR *pszUtf8NamePtr) PURE; // [OUT] Return pointer to UTF8 name in heap. + + STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken rMethods[], // [OUT] Put MemberDefs here. + ULONG cMax, // [IN] Max MemberDefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(GetUserString)( // S_OK or error. + mdString stk, // [IN] String token. + _Out_writes_to_opt_(cchString, *pchString) + LPWSTR szString, // [OUT] Copy of string. + ULONG cchString, // [IN] Max chars of room in szString. + ULONG *pchString) PURE; // [OUT] How many chars in actual string. + + STDMETHOD(GetPinvokeMap)( // S_OK or error. + mdToken tk, // [IN] FieldDef or MethodDef. + DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. + _Out_writes_to_opt_(cchImportName, *pchImportName) + LPWSTR szImportName, // [OUT] Import name. + ULONG cchImportName, // [IN] Size of the name buffer. + ULONG *pchImportName, // [OUT] Actual number of characters stored. + mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. + + STDMETHOD(EnumSignatures)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdSignature rSignatures[], // [OUT] put signatures here. + ULONG cmax, // [IN] max signatures to put. + ULONG *pcSignatures) PURE; // [OUT] put # put here. + + STDMETHOD(EnumTypeSpecs)( // S_OK or error. + HCORENUM *phEnum, // [IN|OUT] pointer to the enum. + mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here. + ULONG cmax, // [IN] max TypeSpecs to put. + ULONG *pcTypeSpecs) PURE; // [OUT] put # put here. + + STDMETHOD(EnumUserStrings)( // S_OK or error. + HCORENUM *phEnum, // [IN/OUT] pointer to the enum. + mdString rStrings[], // [OUT] put Strings here. + ULONG cmax, // [IN] max Strings to put. + ULONG *pcStrings) PURE; // [OUT] put # put here. + + STDMETHOD(GetParamForMethodIndex)( // S_OK or error. + mdMethodDef md, // [IN] Method token. + ULONG ulParamSeq, // [IN] Parameter sequence. + mdParamDef *ppd) PURE; // [IN] Put Param token here. + + STDMETHOD(EnumCustomAttributes)( // S_OK or error. + HCORENUM *phEnum, // [IN, OUT] COR enumerator. + mdToken tk, // [IN] Token to scope the enumeration, 0 for all. + mdToken tkType, // [IN] Type of interest, 0 for all. + mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here. + ULONG cMax, // [IN] Size of rCustomAttributes. + ULONG *pcCustomAttributes) PURE; // [OUT, OPTIONAL] Put count of token values here. + + STDMETHOD(GetCustomAttributeProps)( // S_OK or error. + mdCustomAttribute cv, // [IN] CustomAttribute token. + mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. + mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here. + void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. + ULONG *pcbSize) PURE; // [OUT, OPTIONAL] Put size of date here. + + STDMETHOD(FindTypeRef)( + mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. + LPCWSTR szName, // [IN] TypeRef Name. + mdTypeRef *ptr) PURE; // [OUT] matching TypeRef. + + STDMETHOD(GetMemberProps)( + mdToken mb, // The member for which to get props. + mdTypeDef *pClass, // Put member's class here. + _Out_writes_to_opt_(cchMember, *pchMember) + LPWSTR szMember, // Put member's name here. + ULONG cchMember, // Size of szMember buffer in wide chars. + ULONG *pchMember, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + ULONG *pulCodeRVA, // [OUT] codeRVA + DWORD *pdwImplFlags, // [OUT] Impl. Flags + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppValue, // [OUT] constant value + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetFieldProps)( + mdFieldDef mb, // The field for which to get props. + mdTypeDef *pClass, // Put field's class here. + _Out_writes_to_opt_(cchField, *pchField) + LPWSTR szField, // Put field's name here. + ULONG cchField, // Size of szField buffer in wide chars. + ULONG *pchField, // Put actual size here + DWORD *pdwAttr, // Put flags here. + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob, // [OUT] actual size of signature blob + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppValue, // [OUT] constant value + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. + mdProperty prop, // [IN] property token + mdTypeDef *pClass, // [OUT] typedef containing the property declarion. + LPCWSTR szProperty, // [OUT] Property name + ULONG cchProperty, // [IN] the count of wchar of szProperty + ULONG *pchProperty, // [OUT] actual count of wchar for property name + DWORD *pdwPropFlags, // [OUT] property flags. + PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob + ULONG *pbSig, // [OUT] count of bytes in *ppvSig + DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* + UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value + ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. + mdMethodDef *pmdSetter, // [OUT] setter method of the property + mdMethodDef *pmdGetter, // [OUT] getter method of the property + mdMethodDef rmdOtherMethod[], // [OUT] other method of the property + ULONG cMax, // [IN] size of rmdOtherMethod + ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this property + + STDMETHOD(GetParamProps)( // S_OK or error. + mdParamDef tk, // [IN]The Parameter. + mdMethodDef *pmd, // [OUT] Parent Method token. + ULONG *pulSequence, // [OUT] Parameter sequence. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Put name here. + ULONG cchName, // [OUT] Size of name buffer. + ULONG *pchName, // [OUT] Put actual size of name here. + DWORD *pdwAttr, // [OUT] Put flags here. + DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*. + UVCP_CONSTANT *ppValue, // [OUT] Constant value. + ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. + + STDMETHOD(GetCustomAttributeByName)( // S_OK or error. + mdToken tkObj, // [IN] Object with Custom Attribute. + LPCWSTR szName, // [IN] Name of desired Custom Attribute. + const void **ppData, // [OUT] Put pointer to data here. + ULONG *pcbData) PURE; // [OUT] Put size of data here. + + STDMETHOD_(BOOL, IsValidToken)( // True or False. + mdToken tk) PURE; // [IN] Given token. + + STDMETHOD(GetNestedClassProps)( // S_OK or error. + mdTypeDef tdNestedClass, // [IN] NestedClass token. + mdTypeDef *ptdEnclosingClass) PURE; // [OUT] EnclosingClass token. + + STDMETHOD(GetNativeCallConvFromSig)( // S_OK or error. + void const *pvSig, // [IN] Pointer to signature. + ULONG cbSig, // [IN] Count of signature bytes. + ULONG *pCallConv) PURE; // [OUT] Put calling conv here (see CorPinvokemap). + + STDMETHOD(IsGlobal)( // S_OK or error. + mdToken pd, // [IN] Type, Field, or Method token. + int *pbGlobal) PURE; // [OUT] Put 1 if global, 0 otherwise. + + // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. + +}; // IMetaDataImport + +//------------------------------------- +//--- IMetaDataImport2 +//------------------------------------- +// {FCE5EFA0-8BBA-4f8e-A036-8F2022B08466} +EXTERN_GUID(IID_IMetaDataImport2, 0xfce5efa0, 0x8bba, 0x4f8e, 0xa0, 0x36, 0x8f, 0x20, 0x22, 0xb0, 0x84, 0x66); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataImport2 +DECLARE_INTERFACE_(IMetaDataImport2, IMetaDataImport) +{ + STDMETHOD(EnumGenericParams)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested + mdGenericParam rGenericParams[], // [OUT] Put GenericParams here. + ULONG cMax, // [IN] Max GenericParams to put. + ULONG *pcGenericParams) PURE; // [OUT] Put # put here. + + STDMETHOD(GetGenericParamProps)( // S_OK or error. + mdGenericParam gp, // [IN] GenericParam + ULONG *pulParamSeq, // [OUT] Index of the type parameter + DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance) + mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef) + DWORD *reserved, // [OUT] For future use (e.g. non-type parameters) + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR wzname, // [OUT] Put name here + ULONG cchName, // [IN] Size of buffer + ULONG *pchName) PURE; // [OUT] Put size of name (wide chars) here. + + STDMETHOD(GetMethodSpecProps)( + mdMethodSpec mi, // [IN] The method instantiation + mdToken *tkParent, // [OUT] MethodDef or MemberRef + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob + + STDMETHOD(EnumGenericParamConstraints)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdGenericParam tk, // [IN] GenericParam whose constraints are requested + mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here. + ULONG cMax, // [IN] Max GenericParamConstraints to put. + ULONG *pcGenericParamConstraints) PURE; // [OUT] Put # put here. + + STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. + mdGenericParamConstraint gpc, // [IN] GenericParamConstraint + mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained + mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint + + STDMETHOD(GetPEKind)( // S_OK or error. + DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE) + DWORD* pdwMAchine) PURE; // [OUT] Machine as defined in NT header + + STDMETHOD(GetVersionString)( // S_OK or error. + _Out_writes_to_opt_(ccBufSize, *pccBufSize) + LPWSTR pwzBuf, // [OUT] Put version string here. + DWORD ccBufSize, // [IN] size of the buffer, in wide chars + DWORD *pccBufSize) PURE; // [OUT] Size of the version string, wide chars, including terminating nul. + + STDMETHOD(EnumMethodSpecs)( + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested + mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here. + ULONG cMax, // [IN] Max tokens to put. + ULONG *pcMethodSpecs) PURE; // [OUT] Put actual count here. + +}; // IMetaDataImport2 + +//------------------------------------- +//--- IMetaDataFilter +//------------------------------------- +// {D0E80DD1-12D4-11d3-B39D-00C04FF81795} +EXTERN_GUID(IID_IMetaDataFilter, 0xd0e80dd1, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataFilter +DECLARE_INTERFACE_(IMetaDataFilter, IUnknown) +{ + STDMETHOD(UnmarkAll)() PURE; + STDMETHOD(MarkToken)(mdToken tk) PURE; + STDMETHOD(IsTokenMarked)(mdToken tk, BOOL *pIsMarked) PURE; +}; + + +//------------------------------------- +//--- IHostFilter +//------------------------------------- +// {D0E80DD3-12D4-11d3-B39D-00C04FF81795} +EXTERN_GUID(IID_IHostFilter, 0xd0e80dd3, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); + +//--- +#undef INTERFACE +#define INTERFACE IHostFilter +DECLARE_INTERFACE_(IHostFilter, IUnknown) +{ + STDMETHOD(MarkToken)(mdToken tk) PURE; +}; + + +//***************************************************************************** +// Assembly Declarations +//***************************************************************************** + +typedef struct +{ + DWORD dwOSPlatformId; // Operating system platform. + DWORD dwOSMajorVersion; // OS Major version. + DWORD dwOSMinorVersion; // OS Minor version. +} OSINFO; + + +typedef struct +{ + USHORT usMajorVersion; // Major Version. + USHORT usMinorVersion; // Minor Version. + USHORT usBuildNumber; // Build Number. + USHORT usRevisionNumber; // Revision Number. + LPWSTR szLocale; // Locale. + ULONG cbLocale; // [IN/OUT] Size of the buffer in wide chars/Actual size. + DWORD *rProcessor; // Processor ID array. + ULONG ulProcessor; // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in. + OSINFO *rOS; // OSINFO array. + ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. +} ASSEMBLYMETADATA; + + +// {211EF15B-5317-4438-B196-DEC87B887693} +EXTERN_GUID(IID_IMetaDataAssemblyEmit, 0x211ef15b, 0x5317, 0x4438, 0xb1, 0x96, 0xde, 0xc8, 0x7b, 0x88, 0x76, 0x93); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataAssemblyEmit +DECLARE_INTERFACE_(IMetaDataAssemblyEmit, IUnknown) +{ + STDMETHOD(DefineAssembly)( // S_OK or error. + const void *pbPublicKey, // [IN] Public key of the assembly. + ULONG cbPublicKey, // [IN] Count of bytes in the public key. + ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. + LPCWSTR szName, // [IN] Name of the assembly. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + DWORD dwAssemblyFlags, // [IN] Flags. + mdAssembly *pma) PURE; // [OUT] Returned Assembly token. + + STDMETHOD(DefineAssemblyRef)( // S_OK or error. + const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. + LPCWSTR szName, // [IN] Name of the assembly being referenced. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwAssemblyRefFlags, // [IN] Flags. + mdAssemblyRef *pmdar) PURE; // [OUT] Returned AssemblyRef token. + + STDMETHOD(DefineFile)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the file. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwFileFlags, // [IN] Flags. + mdFile *pmdf) PURE; // [OUT] Returned File token. + + STDMETHOD(DefineExportedType)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the Com Type. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType + mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. + DWORD dwExportedTypeFlags, // [IN] Flags. + mdExportedType *pmdct) PURE; // [OUT] Returned ExportedType token. + + STDMETHOD(DefineManifestResource)( // S_OK or error. + LPCWSTR szName, // [IN] Name of the resource. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. + DWORD dwResourceFlags, // [IN] Flags. + mdManifestResource *pmdmr) PURE; // [OUT] Returned ManifestResource token. + + STDMETHOD(SetAssemblyProps)( // S_OK or error. + mdAssembly pma, // [IN] Assembly token. + const void *pbPublicKey, // [IN] Public key of the assembly. + ULONG cbPublicKey, // [IN] Count of bytes in the public key. + ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. + LPCWSTR szName, // [IN] Name of the assembly. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + DWORD dwAssemblyFlags) PURE; // [IN] Flags. + + STDMETHOD(SetAssemblyRefProps)( // S_OK or error. + mdAssemblyRef ar, // [IN] AssemblyRefToken. + const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. + ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. + LPCWSTR szName, // [IN] Name of the assembly being referenced. + const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwAssemblyRefFlags) PURE; // [IN] Token for Execution Location. + + STDMETHOD(SetFileProps)( // S_OK or error. + mdFile file, // [IN] File token. + const void *pbHashValue, // [IN] Hash Blob. + ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. + DWORD dwFileFlags) PURE; // [IN] Flags. + + STDMETHOD(SetExportedTypeProps)( // S_OK or error. + mdExportedType ct, // [IN] ExportedType token. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType. + mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. + DWORD dwExportedTypeFlags) PURE; // [IN] Flags. + + STDMETHOD(SetManifestResourceProps)( // S_OK or error. + mdManifestResource mr, // [IN] ManifestResource token. + mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. + DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. + DWORD dwResourceFlags) PURE; // [IN] Flags. + +}; // IMetaDataAssemblyEmit + + +// {EE62470B-E94B-424e-9B7C-2F00C9249F93} +EXTERN_GUID(IID_IMetaDataAssemblyImport, 0xee62470b, 0xe94b, 0x424e, 0x9b, 0x7c, 0x2f, 0x0, 0xc9, 0x24, 0x9f, 0x93); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataAssemblyImport +DECLARE_INTERFACE_(IMetaDataAssemblyImport, IUnknown) +{ + STDMETHOD(GetAssemblyProps)( // S_OK or error. + mdAssembly mda, // [IN] The Assembly for which to get the properties. + const void **ppbPublicKey, // [OUT] Pointer to the public key. + ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. + ULONG *pulHashAlgId, // [OUT] Hash Algorithm. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with assembly's simply name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. + DWORD *pdwAssemblyFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetAssemblyRefProps)( // S_OK or error. + mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. + const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. + ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. + _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. + const void **ppbHashValue, // [OUT] Hash blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. + DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetFileProps)( // S_OK or error. + mdFile mdf, // [IN] The File for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. + DWORD *pdwFileFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetExportedTypeProps)( // S_OK or error. + mdExportedType mdct, // [IN] The ExportedType for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType. + mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. + DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. + + STDMETHOD(GetManifestResourceProps)( // S_OK or error. + mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. + _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. + ULONG cchName, // [IN] Size of buffer in wide chars. + ULONG *pchName, // [OUT] Actual # of wide chars in name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource. + DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. + DWORD *pdwResourceFlags) PURE;// [OUT] Flags. + + STDMETHOD(EnumAssemblyRefs)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. + ULONG cMax, // [IN] Max AssemblyRefs to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumFiles)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdFile rFiles[], // [OUT] Put Files here. + ULONG cMax, // [IN] Max Files to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumExportedTypes)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. + ULONG cMax, // [IN] Max ExportedTypes to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(EnumManifestResources)( // S_OK or error + HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. + mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. + ULONG cMax, // [IN] Max Resources to put. + ULONG *pcTokens) PURE; // [OUT] Put # put here. + + STDMETHOD(GetAssemblyFromScope)( // S_OK or error + mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. + + STDMETHOD(FindExportedTypeByName)( // S_OK or error + LPCWSTR szName, // [IN] Name of the ExportedType. + mdToken mdtExportedType, // [IN] ExportedType for the enclosing class. + mdExportedType *ptkExportedType) PURE; // [OUT] Put the ExportedType token here. + + STDMETHOD(FindManifestResourceByName)( // S_OK or error + LPCWSTR szName, // [IN] Name of the ManifestResource. + mdManifestResource *ptkManifestResource) PURE; // [OUT] Put the ManifestResource token here. + + STDMETHOD_(void, CloseEnum)( + HCORENUM hEnum) PURE; // Enum to be closed. + + STDMETHOD(FindAssembliesByName)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here + ULONG cMax, // [IN] The max number to put + ULONG *pcAssemblies) PURE; // [OUT] The number of assemblies returned. +}; // IMetaDataAssemblyImport + + +//***************************************************************************** +// End Assembly Declarations +//***************************************************************************** + +//***************************************************************************** +// MetaData Validator Declarations +//***************************************************************************** + +// Specifies the type of the module, PE file vs. .obj file. +typedef enum +{ + ValidatorModuleTypeInvalid = 0x0, + ValidatorModuleTypeMin = 0x00000001, + ValidatorModuleTypePE = 0x00000001, + ValidatorModuleTypeObj = 0x00000002, + ValidatorModuleTypeEnc = 0x00000003, + ValidatorModuleTypeIncr = 0x00000004, + ValidatorModuleTypeMax = 0x00000004, +} CorValidatorModuleType; + + +// {4709C9C6-81FF-11D3-9FC7-00C04F79A0A3} +EXTERN_GUID(IID_IMetaDataValidate, 0x4709c9c6, 0x81ff, 0x11d3, 0x9f, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataValidate +DECLARE_INTERFACE_(IMetaDataValidate, IUnknown) +{ + STDMETHOD(ValidatorInit)( // S_OK or error. + DWORD dwModuleType, // [IN] Specifies the type of the module. + IUnknown *pUnk) PURE; // [IN] Validation error handler. + + STDMETHOD(ValidateMetaData)( // S_OK or error. + ) PURE; +}; // IMetaDataValidate + +//***************************************************************************** +// End MetaData Validator Declarations +//***************************************************************************** + +//***************************************************************************** +// IMetaDataDispenserEx declarations. +//***************************************************************************** + +// {31BCFCE2-DAFB-11D2-9F81-00C04F79A0A3} +EXTERN_GUID(IID_IMetaDataDispenserEx, 0x31bcfce2, 0xdafb, 0x11d2, 0x9f, 0x81, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); + +#undef INTERFACE +#define INTERFACE IMetaDataDispenserEx +DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) +{ + STDMETHOD(SetOption)( // Return code. + REFGUID optionid, // [in] GUID for the option to be set. + const VARIANT *value) PURE; // [in] Value to which the option is to be set. + + STDMETHOD(GetOption)( // Return code. + REFGUID optionid, // [in] GUID for the option to be set. + VARIANT *pvalue) PURE; // [out] Value to which the option is currently set. + + STDMETHOD(OpenScopeOnITypeInfo)( // Return code. + ITypeInfo *pITI, // [in] ITypeInfo to open. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + + STDMETHOD(GetCORSystemDirectory)( // Return code. + _Out_writes_to_opt_(cchBuffer, *pchBuffer) + LPWSTR szBuffer, // [out] Buffer for the directory name + DWORD cchBuffer, // [in] Size of the buffer + DWORD* pchBuffer) PURE; // [OUT] Number of characters returned + + STDMETHOD(FindAssembly)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szGlobalBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + LPCWSTR szName, // [OUT] buffer - to hold name + ULONG cchName, // [IN] the name buffer's size + ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer + + STDMETHOD(FindAssemblyModule)( // S_OK or error + LPCWSTR szAppBase, // [IN] optional - can be NULL + LPCWSTR szPrivateBin, // [IN] optional - can be NULL + LPCWSTR szGlobalBin, // [IN] optional - can be NULL + LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting + LPCWSTR szModuleName, // [IN] required - the name of the module + _Out_writes_to_opt_(cchName, *pcName) + LPWSTR szName, // [OUT] buffer - to hold name + ULONG cchName, // [IN] the name buffer's size + ULONG *pcName) PURE; // [OUT] the number of characters returend in the buffer + +}; + +//***************************************************************************** +//***************************************************************************** +// +// Registration declarations. Will be replace by Services' Registration +// implementation. +// +//***************************************************************************** +//***************************************************************************** +// Various flags for use in installing a module or a composite +typedef enum +{ + regNoCopy = 0x00000001, // Don't copy files into destination + regConfig = 0x00000002, // Is a configuration + regHasRefs = 0x00000004 // Has class references +} CorRegFlags; + +typedef GUID CVID; + +typedef struct { + short Major; + short Minor; + short Sub; + short Build; +} CVStruct; + + +//***************************************************************************** +//***************************************************************************** +// +// CeeGen interfaces for generating in-memory Common Language Runtime files +// +//***************************************************************************** +//***************************************************************************** + +typedef void *HCEESECTION; + +typedef enum { + sdNone = 0, + sdReadOnly = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA, + sdReadWrite = sdReadOnly | IMAGE_SCN_MEM_WRITE, + sdExecute = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE +} CeeSectionAttr; + +// +// Relocation types. +// + +typedef enum { + // generate only a section-relative reloc, nothing into .reloc section + srRelocAbsolute, + + // generate a .reloc for a pointer sized location, + // This is transformed into BASED_HIGHLOW or BASED_DIR64 based on the platform + srRelocHighLow = 3, + + // generate a .reloc for the top 16-bits of a 32 bit number, where the + // bottom 16 bits are included in the next word in the .reloc table + srRelocHighAdj, // Never Used + + // generate a token map relocation, nothing into .reloc section + srRelocMapToken, + + // relative address fixup + srRelocRelative, + + // Generate only a section-relative reloc, nothing into .reloc + // section. This reloc is relative to the file position of the + // section, not the section's virtual address. + srRelocFilePos, + + // code relative address fixup + srRelocCodeRelative, + + // generate a .reloc for a 64 bit address in an ia64 movl instruction + srRelocIA64Imm64, + + // generate a .reloc for a 64 bit address + srRelocDir64, + + // generate a .reloc for a 25-bit PC relative address in an ia64 br.call instruction + srRelocIA64PcRel25, + + // generate a .reloc for a 64-bit PC relative address in an ia64 brl.call instruction + srRelocIA64PcRel64, + + // generate a 30-bit section-relative reloc, used for tagged pointer values + srRelocAbsoluteTagged, + + + // A sentinel value to help ensure any additions to this enum are reflected + // in PEWriter.cpp's RelocName array. + srRelocSentinel, + + // Flags that can be used with the above reloc types + + // do not emit base reloc + srNoBaseReloc = 0x4000, + + // pre-fixup contents of memory are ptr rather than a section offset + srRelocPtr = 0x8000, + + // legal enums which include the Ptr flag + srRelocAbsolutePtr = srRelocPtr + srRelocAbsolute, + srRelocHighLowPtr = srRelocPtr + srRelocHighLow, + srRelocRelativePtr = srRelocPtr + srRelocRelative, + srRelocIA64Imm64Ptr = srRelocPtr + srRelocIA64Imm64, + srRelocDir64Ptr = srRelocPtr + srRelocDir64, + +} CeeSectionRelocType; + +typedef union { + USHORT highAdj; +} CeeSectionRelocExtra; + +//------------------------------------- +//--- ICeeGen +//------------------------------------- +// {7ED1BDFF-8E36-11d2-9C56-00A0C9B7CC45} +EXTERN_GUID(IID_ICeeGen, 0x7ed1bdff, 0x8e36, 0x11d2, 0x9c, 0x56, 0x0, 0xa0, 0xc9, 0xb7, 0xcc, 0x45); + +DECLARE_INTERFACE_(ICeeGen, IUnknown) +{ + STDMETHOD (EmitString) ( + _In_ + LPWSTR lpString, // [IN] String to emit + ULONG *RVA) PURE; // [OUT] RVA for string emitted string + + STDMETHOD (GetString) ( + ULONG RVA, // [IN] RVA for string to return + _Out_opt_ + LPWSTR *lpString) PURE; // [OUT] Returned string + + STDMETHOD (AllocateMethodBuffer) ( + ULONG cchBuffer, // [IN] Length of buffer to create + UCHAR **lpBuffer, // [OUT] Returned buffer + ULONG *RVA) PURE; // [OUT] RVA for method + + STDMETHOD (GetMethodBuffer) ( + ULONG RVA, // [IN] RVA for method to return + UCHAR **lpBuffer) PURE; // [OUT] Returned buffer + + STDMETHOD (GetIMapTokenIface) ( + IUnknown **pIMapToken) PURE; + + STDMETHOD (GenerateCeeFile) () PURE; + + STDMETHOD (GetIlSection) ( + HCEESECTION *section) PURE; + + STDMETHOD (GetStringSection) ( + HCEESECTION *section) PURE; + + STDMETHOD (AddSectionReloc) ( + HCEESECTION section, + ULONG offset, + HCEESECTION relativeTo, + CeeSectionRelocType relocType) PURE; + + // use these only if you have special section requirements not handled + // by other APIs + STDMETHOD (GetSectionCreate) ( + const char *name, + DWORD flags, + HCEESECTION *section) PURE; + + STDMETHOD (GetSectionDataLen) ( + HCEESECTION section, + ULONG *dataLen) PURE; + + STDMETHOD (GetSectionBlock) ( + HCEESECTION section, + ULONG len, + ULONG align=1, + void **ppBytes=0) PURE; + + STDMETHOD (TruncateSection) ( + HCEESECTION section, + ULONG len) PURE; + + STDMETHOD (GenerateCeeMemoryImage) ( + void **ppImage) PURE; + + STDMETHOD (ComputePointer) ( + HCEESECTION section, + ULONG RVA, // [IN] RVA for method to return + UCHAR **lpBuffer) PURE; // [OUT] Returned buffer + +}; + +//***************************************************************************** +//***************************************************************************** +// +// End of CeeGen declarations. +// +//***************************************************************************** + +//********************************************************************** +//********************************************************************** +//--- IMetaDataTables +//------------------------------------- +// This API isn't big endian friendly since it indexes directly into the memory that +// is stored in little endian format. +// {D8F579AB-402D-4b8e-82D9-5D63B1065C68} +EXTERN_GUID(IID_IMetaDataTables, 0xd8f579ab, 0x402d, 0x4b8e, 0x82, 0xd9, 0x5d, 0x63, 0xb1, 0x6, 0x5c, 0x68); + +DECLARE_INTERFACE_(IMetaDataTables, IUnknown) +{ + STDMETHOD (GetStringHeapSize) ( + ULONG *pcbStrings) PURE; // [OUT] Size of the string heap. + + STDMETHOD (GetBlobHeapSize) ( + ULONG *pcbBlobs) PURE; // [OUT] Size of the Blob heap. + + STDMETHOD (GetGuidHeapSize) ( + ULONG *pcbGuids) PURE; // [OUT] Size of the Guid heap. + + STDMETHOD (GetUserStringHeapSize) ( + ULONG *pcbBlobs) PURE; // [OUT] Size of the User String heap. + + STDMETHOD (GetNumTables) ( + ULONG *pcTables) PURE; // [OUT] Count of tables. + + STDMETHOD (GetTableIndex) ( + ULONG token, // [IN] Token for which to get table index. + ULONG *pixTbl) PURE; // [OUT] Put table index here. + + STDMETHOD (GetTableInfo) ( + ULONG ixTbl, // [IN] Which table. + ULONG *pcbRow, // [OUT] Size of a row, bytes. + ULONG *pcRows, // [OUT] Number of rows. + ULONG *pcCols, // [OUT] Number of columns in each row. + ULONG *piKey, // [OUT] Key column, or -1 if none. + const char **ppName) PURE; // [OUT] Name of the table. + + STDMETHOD (GetColumnInfo) ( + ULONG ixTbl, // [IN] Which Table + ULONG ixCol, // [IN] Which Column in the table + ULONG *poCol, // [OUT] Offset of the column in the row. + ULONG *pcbCol, // [OUT] Size of a column, bytes. + ULONG *pType, // [OUT] Type of the column. + const char **ppName) PURE; // [OUT] Name of the Column. + + STDMETHOD (GetCodedTokenInfo) ( + ULONG ixCdTkn, // [IN] Which kind of coded token. + ULONG *pcTokens, // [OUT] Count of tokens. + ULONG **ppTokens, // [OUT] List of tokens. + const char **ppName) PURE; // [OUT] Name of the CodedToken. + + STDMETHOD (GetRow) ( + ULONG ixTbl, // [IN] Which table. + ULONG rid, // [IN] Which row. + void **ppRow) PURE; // [OUT] Put pointer to row here. + + STDMETHOD (GetColumn) ( + ULONG ixTbl, // [IN] Which table. + ULONG ixCol, // [IN] Which column. + ULONG rid, // [IN] Which row. + ULONG *pVal) PURE; // [OUT] Put the column contents here. + + STDMETHOD (GetString) ( + ULONG ixString, // [IN] Value from a string column. + const char **ppString) PURE; // [OUT] Put a pointer to the string here. + + STDMETHOD (GetBlob) ( + ULONG ixBlob, // [IN] Value from a blob column. + ULONG *pcbData, // [OUT] Put size of the blob here. + const void **ppData) PURE; // [OUT] Put a pointer to the blob here. + + STDMETHOD (GetGuid) ( + ULONG ixGuid, // [IN] Value from a guid column. + const GUID **ppGUID) PURE; // [OUT] Put a pointer to the GUID here. + + STDMETHOD (GetUserString) ( + ULONG ixUserString, // [IN] Value from a UserString column. + ULONG *pcbData, // [OUT] Put size of the UserString here. + const void **ppData) PURE; // [OUT] Put a pointer to the UserString here. + + STDMETHOD (GetNextString) ( + ULONG ixString, // [IN] Value from a string column. + ULONG *pNext) PURE; // [OUT] Put the index of the next string here. + + STDMETHOD (GetNextBlob) ( + ULONG ixBlob, // [IN] Value from a blob column. + ULONG *pNext) PURE; // [OUT] Put the index of the netxt blob here. + + STDMETHOD (GetNextGuid) ( + ULONG ixGuid, // [IN] Value from a guid column. + ULONG *pNext) PURE; // [OUT] Put the index of the next guid here. + + STDMETHOD (GetNextUserString) ( + ULONG ixUserString, // [IN] Value from a UserString column. + ULONG *pNext) PURE; // [OUT] Put the index of the next user string here. + + // Interface is sealed. + +}; +// This API isn't big endian friendly since it indexes directly into the memory that +// is stored in little endian format. +// {BADB5F70-58DA-43a9-A1C6-D74819F19B15} +EXTERN_GUID(IID_IMetaDataTables2, 0xbadb5f70, 0x58da, 0x43a9, 0xa1, 0xc6, 0xd7, 0x48, 0x19, 0xf1, 0x9b, 0x15); + +DECLARE_INTERFACE_(IMetaDataTables2, IMetaDataTables) +{ + STDMETHOD (GetMetaDataStorage) ( //@todo: name? + const void **ppvMd, // [OUT] put pointer to MD section here (aka, 'BSJB'). + ULONG *pcbMd) PURE; // [OUT] put size of the stream here. + + STDMETHOD (GetMetaDataStreamInfo) ( // Get info about the MD stream. + ULONG ix, // [IN] Stream ordinal desired. + const char **ppchName, // [OUT] put pointer to stream name here. + const void **ppv, // [OUT] put pointer to MD stream here. + ULONG *pcb) PURE; // [OUT] put size of the stream here. + +}; // IMetaDataTables2 + +#ifdef _DEFINE_META_DATA_META_CONSTANTS +#ifndef _META_DATA_META_CONSTANTS_DEFINED +#define _META_DATA_META_CONSTANTS_DEFINED +const unsigned int iRidMax = 63; +const unsigned int iCodedToken = 64; // base of coded tokens. +const unsigned int iCodedTokenMax = 95; +const unsigned int iSHORT = 96; // fixed types. +const unsigned int iUSHORT = 97; +const unsigned int iLONG = 98; +const unsigned int iULONG = 99; +const unsigned int iBYTE = 100; +const unsigned int iSTRING = 101; // pool types. +const unsigned int iGUID = 102; +const unsigned int iBLOB = 103; + +inline int IsRidType(ULONG ix) { return ix <= iRidMax; } +inline int IsCodedTokenType(ULONG ix) { return (ix >= iCodedToken) && (ix <= iCodedTokenMax); } +inline int IsRidOrToken(ULONG ix) { return ix <= iCodedTokenMax; } +inline int IsHeapType(ULONG ix) { return ix >= iSTRING; } +inline int IsFixedType(ULONG ix) { return (ix < iSTRING) && (ix > iCodedTokenMax); } +#endif +#endif + +//********************************************************************** +// End of IMetaDataTables. +//********************************************************************** + +//------------------------------------- +//--- IMetaDataInfo +//------------------------------------- +// {7998EA64-7F95-48B8-86FC-17CAF48BF5CB} +EXTERN_GUID(IID_IMetaDataInfo, 0x7998EA64, 0x7F95, 0x48B8, 0x86, 0xFC, 0x17, 0xCA, 0xF4, 0x8B, 0xF5, 0xCB); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataInfo +DECLARE_INTERFACE_(IMetaDataInfo, IUnknown) +{ + // Return Values: + // S_OK - All parameters are filled. + // COR_E_NOTSUPPORTED - The API is not supported for this particular scope (e.g. .obj files, scope + // opened without whole file via code:IMetaDataDispenser::OpenScopeOnMemory, etc.). + // E_INVALIDARG - If NULL is passed as parameter. + STDMETHOD(GetFileMapping)( + const void ** ppvData, // [out] Pointer to the start of the mapped file. + ULONGLONG * pcbData, // [out] Size of the mapped memory region. + DWORD * pdwMappingType) PURE; // [out] Type of file mapping (code:CorFileMapping). +}; // class IMetaDataInfo + + +//------------------------------------- +//--- IMetaDataWinMDImport +//------------------------------------- +// {969EA0C5-964E-411B-A807-B0F3C2DFCBD4} +EXTERN_GUID(IID_IMetaDataWinMDImport, 0x969ea0c5, 0x964e, 0x411b, 0xa8, 0x7, 0xb0, 0xf3, 0xc2, 0xdf, 0xcb, 0xd4); + +//--- +#undef INTERFACE +#define INTERFACE IMetaDataWinMDImport +DECLARE_INTERFACE_(IMetaDataWinMDImport, IUnknown) +{ + STDMETHOD(GetUntransformedTypeRefProps)( // S_OK or error. + mdTypeRef tr, // [IN] TypeRef token. + mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. + _Out_writes_to_opt_(cchName, *pchName) + LPWSTR szName, // [OUT] Name of the TypeRef. + ULONG cchName, // [IN] Size of buffer. + ULONG *pchName) PURE; // [OUT] Size of Name. +}; // class IMetaDataWinMDImport + +//********************************************************************** +// +// Predefined CustomAttribute and structures for these custom value +// +//********************************************************************** + +// +// Native Link method custom value definitions. This is for N-direct support. +// + +#define COR_NATIVE_LINK_CUSTOM_VALUE L"COMPLUS_NativeLink" +#define COR_NATIVE_LINK_CUSTOM_VALUE_ANSI "COMPLUS_NativeLink" + +// count of chars for COR_NATIVE_LINK_CUSTOM_VALUE(_ANSI) +#define COR_NATIVE_LINK_CUSTOM_VALUE_CC 18 + +#include +typedef struct +{ + BYTE m_linkType; // see CorNativeLinkType below + BYTE m_flags; // see CorNativeLinkFlags below + mdMemberRef m_entryPoint; // member ref token giving entry point, format is lib:entrypoint +} COR_NATIVE_LINK; +#include + +typedef enum +{ + nltNone = 1, // none of the keywords are specified + nltAnsi = 2, // ansi keyword specified + nltUnicode = 3, // unicode keyword specified + nltAuto = 4, // auto keyword specified + nltMaxValue = 7, // used so we can assert how many bits are required for this enum +} CorNativeLinkType; + +typedef enum +{ + nlfNone = 0x00, // no flags + nlfLastError = 0x01, // setLastError keyword specified + nlfNoMangle = 0x02, // nomangle keyword specified + nlfMaxValue = 0x03, // used so we can assert how many bits are required for this enum +} CorNativeLinkFlags; + +// +// Base class for security custom attributes. +// + +#define COR_BASE_SECURITY_ATTRIBUTE_CLASS L"System.Security.Permissions.SecurityAttribute" +#define COR_BASE_SECURITY_ATTRIBUTE_CLASS_ANSI "System.Security.Permissions.SecurityAttribute" + +// +// Name of custom attribute used to indicate that per-call security checks should +// be disabled for P/Invoke calls. +// + +#define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE L"System.Security.SuppressUnmanagedCodeSecurityAttribute" +#define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI "System.Security.SuppressUnmanagedCodeSecurityAttribute" + +// +// Name of custom attribute tagged on module to indicate it contains +// unverifiable code. +// + +#define COR_UNVER_CODE_ATTRIBUTE L"System.Security.UnverifiableCodeAttribute" +#define COR_UNVER_CODE_ATTRIBUTE_ANSI "System.Security.UnverifiableCodeAttribute" + +// +// Name of custom attribute indicating that a method requires a security object +// slot on the caller's stack. +// + +#define COR_REQUIRES_SECOBJ_ATTRIBUTE W("System.Security.DynamicSecurityMethodAttribute") +#define COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI "System.Security.DynamicSecurityMethodAttribute" + +#define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE L"System.Runtime.CompilerServices.DiscardableAttribute" +#define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE_ASNI "System.Runtime.CompilerServices.DiscardableAttribute" + + +#ifdef __cplusplus +} + +//***************************************************************************** +//***************************************************************************** +// +// C O M + s i g n a t u r e s u p p o r t +// +//***************************************************************************** +//***************************************************************************** + +#ifndef FORCEINLINE + #if _MSC_VER < 1200 + #define FORCEINLINE inline + #else + #define FORCEINLINE __forceinline + #endif +#endif + + +// We need a version that is FORCEINLINE on retail and NOINLINE on debug + +#ifndef DEBUG_NOINLINE +#if defined(_DEBUG) +#define DEBUG_NOINLINE NOINLINE +#else +#define DEBUG_NOINLINE +#endif +#endif + +#ifndef NOINLINE +#ifdef _MSC_VER +#define NOINLINE __declspec(noinline) +#elif defined __GNUC__ +#define NOINLINE __attribute__ ((noinline)) +#else +#define NOINLINE +#endif +#endif // !NOINLINE + +// return true if it is a primitive type, i.e. only need to store CorElementType +FORCEINLINE int CorIsPrimitiveType(CorElementType elementtype) +{ + return (elementtype < ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_I || elementtype == ELEMENT_TYPE_U); +} + + +// Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are +// turned on. For now, it is checking for ELEMENT_TYPE_PTR and ELEMENT_TYPE_BYREF +// as well. This will be removed when we turn on ELEMENT_TYPE_MODIFIER bits for +// these two enum members. +// +FORCEINLINE int CorIsModifierElementType(CorElementType elementtype) +{ + if (elementtype == ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_BYREF) + return 1; + return (elementtype & ELEMENT_TYPE_MODIFIER); +} + +// Given a compress byte (*pData), return the size of the uncompressed data. +inline ULONG CorSigUncompressedDataSize( + PCCOR_SIGNATURE pData) +{ + if ((*pData & 0x80) == 0) + return 1; + else if ((*pData & 0xC0) == 0x80) + return 2; + else + return 4; +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// Given a compressed integer(*pData), expand the compressed int to *pDataOut. +// Return value is the number of bytes that the integer occupies in the compressed format +// It is caller's responsibility to ensure pDataOut has at least 4 bytes to be written to. +// +// This function returns -1 if pass in with an incorrectly compressed data, such as +// (*pBytes & 0xE0) == 0XE0. +///////////////////////////////////////////////////////////////////////////////////////////// +inline ULONG CorSigUncompressBigData( + PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data +{ + ULONG res; + + // 1 byte data is handled in CorSigUncompressData + // _ASSERTE(*pData & 0x80); + + // Medium. + if ((*pData & 0xC0) == 0x80) // 10?? ???? + { + res = (ULONG)((*pData++ & 0x3f) << 8); + res |= *pData++; + } + else // 110? ???? + { + res = (*pData++ & 0x1f) << 24; + res |= *pData++ << 16; + res |= *pData++ << 8; + res |= *pData++; + } + return res; +} +FORCEINLINE ULONG CorSigUncompressData( + PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data +{ + // Handle smallest data inline. + if ((*pData & 0x80) == 0x00) // 0??? ???? + return *pData++; + return CorSigUncompressBigData(pData); +} + +inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the signature is bad + PCCOR_SIGNATURE pData, // [IN] compressed data + DWORD len, // [IN] length of the signature + ULONG * pDataOut, // [OUT] the expanded *pData + ULONG * pDataLen) // [OUT] length of the expanded *pData +{ + HRESULT hr = S_OK; + BYTE const *pBytes = reinterpret_cast(pData); + + // Smallest. + if ((*pBytes & 0x80) == 0x00) // 0??? ???? + { + if (len < 1) + { + *pDataOut = 0; + *pDataLen = 0; + hr = META_E_BAD_SIGNATURE; + } + else + { + *pDataOut = *pBytes; + *pDataLen = 1; + } + } + // Medium. + else if ((*pBytes & 0xC0) == 0x80) // 10?? ???? + { + if (len < 2) + { + *pDataOut = 0; + *pDataLen = 0; + hr = META_E_BAD_SIGNATURE; + } + else + { + *pDataOut = (ULONG)(((*pBytes & 0x3f) << 8 | *(pBytes+1))); + *pDataLen = 2; + } + } + else if ((*pBytes & 0xE0) == 0xC0) // 110? ???? + { + if (len < 4) + { + *pDataOut = 0; + *pDataLen = 0; + hr = META_E_BAD_SIGNATURE; + } + else + { + *pDataOut = (ULONG)(((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3))); + *pDataLen = 4; + } + } + else // We don't recognize this encoding + { + *pDataOut = 0; + *pDataLen = 0; + hr = META_E_BAD_SIGNATURE; + } + + return hr; +} + +inline ULONG CorSigUncompressData( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + ULONG *pDataOut) // [OUT] the expanded *pData +{ + ULONG dwSizeOfData = 0; + + // We don't know how big the signature is, so we'll just say that it's big enough + if (FAILED(CorSigUncompressData(pData, 0xff, pDataOut, &dwSizeOfData))) + { + *pDataOut = 0; + return (ULONG)-1; + } + + return dwSizeOfData; +} + + +#if !defined(SELECTANY) +#if defined(__GNUC__) + #define SELECTANY extern __attribute__((weak)) +#else + #define SELECTANY extern __declspec(selectany) +#endif +#endif + +SELECTANY const mdToken g_tkCorEncodeToken[4] ={mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType}; + +// uncompress a token +inline mdToken CorSigUncompressToken( // return the token. + PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data +{ + mdToken tk; + mdToken tkType; + + tk = CorSigUncompressData(pData); + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + return tk; +} + + +inline ULONG CorSigUncompressToken( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + mdToken * pToken) // [OUT] the expanded *pData +{ + ULONG cb; + mdToken tk; + mdToken tkType; + + cb = CorSigUncompressData(pData, (ULONG *)&tk); + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + *pToken = tk; + return cb; +} + +inline HRESULT CorSigUncompressToken( + PCCOR_SIGNATURE pData, // [IN] compressed data + DWORD dwLen, // [IN] Remaining length of sigature + mdToken * pToken, // [OUT] the expanded *pData + DWORD * dwTokenLength) // [OUT] The length of the token in the sigature +{ + mdToken tk; + mdToken tkType; + + HRESULT hr = CorSigUncompressData(pData, dwLen, (ULONG *)&tk, dwTokenLength); + + if (SUCCEEDED(hr)) + { + tkType = g_tkCorEncodeToken[tk & 0x3]; + tk = TokenFromRid(tk >> 2, tkType); + *pToken = tk; + } + else + { + *pToken = mdTokenNil; + } + return hr; +} + + + +FORCEINLINE ULONG CorSigUncompressCallingConv( + PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data +{ + return *pData++; +} + +FORCEINLINE HRESULT CorSigUncompressCallingConv( + PCCOR_SIGNATURE pData, // [IN] Signature + DWORD dwLen, // [IN] Length of signature + ULONG * data) // [OUT] Compressed data +{ + if (dwLen > 0) + { + *data = *pData; + return S_OK; + } + else + { + *data = 0; + return META_E_BAD_SIGNATURE; + } +} + + +enum { + SIGN_MASK_ONEBYTE = 0xffffffc0, // Mask the same size as the missing bits. + SIGN_MASK_TWOBYTE = 0xffffe000, // Mask the same size as the missing bits. + SIGN_MASK_FOURBYTE = 0xf0000000, // Mask the same size as the missing bits. +}; + +// uncompress a signed integer +inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] compressed data + int * pInt) // [OUT] the expanded *pInt +{ + ULONG cb; + ULONG ulSigned; + ULONG iData; + + cb = CorSigUncompressData(pData, &iData); + if (cb == (ULONG) -1) return cb; + ulSigned = iData & 0x1; + iData = iData >> 1; + if (ulSigned) + { + if (cb == 1) + { + iData |= SIGN_MASK_ONEBYTE; + } + else if (cb == 2) + { + iData |= SIGN_MASK_TWOBYTE; + } + else + { + iData |= SIGN_MASK_FOURBYTE; + } + } + *pInt = (int)iData; + return cb; +} + + +// uncompress encoded element type +FORCEINLINE CorElementType CorSigUncompressElementType( // Element type + PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data +{ + return (CorElementType)*pData++; +} + +inline ULONG CorSigUncompressElementType( // Return number of bytes of that compressed data occupied in pData + PCCOR_SIGNATURE pData, // [IN] Compressed data + CorElementType * pElementType) // [OUT] The expanded *pData +{ + *pElementType = (CorElementType)(*pData & 0x7f); + return 1; +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +// +// Given an uncompressed unsigned integer (iLen), Store it to pDataOut in a compressed format. +// Return value is the number of bytes that the integer occupies in the compressed format. +// It is caller's responsibilityt to ensure *pDataOut has at least 4 bytes to write to. +// +// Note that this function returns -1 if iLen is too big to be compressed. We currently can +// only represent to 0x1FFFFFFF. +// +///////////////////////////////////////////////////////////////////////////////////////////// +inline ULONG CorSigCompressData( // return number of bytes that compressed form of iLen will take + ULONG iLen, // [IN] given uncompressed data + void * pDataOut) // [OUT] buffer where iLen will be compressed and stored. +{ + BYTE *pBytes = reinterpret_cast(pDataOut); + + if (iLen <= 0x7F) + { + *pBytes = BYTE(iLen); + return 1; + } + + if (iLen <= 0x3FFF) + { + *pBytes = BYTE((iLen >> 8) | 0x80); + *(pBytes+1) = BYTE(iLen & 0xff); + return 2; + } + + if (iLen <= 0x1FFFFFFF) + { + *pBytes = BYTE((iLen >> 24) | 0xC0); + *(pBytes+1) = BYTE((iLen >> 16) & 0xff); + *(pBytes+2) = BYTE((iLen >> 8) & 0xff); + *(pBytes+3) = BYTE(iLen & 0xff); + return 4; + } + return (ULONG) -1; +} + +// compress a token +// The least significant bit of the first compress byte will indicate the token type. +// +inline ULONG CorSigCompressToken( // return number of bytes that compressed form of the token will take + mdToken tk, // [IN] given token + void * pDataOut) // [OUT] buffer where the token will be compressed and stored. +{ + RID rid = RidFromToken(tk); + ULONG32 ulTyp = TypeFromToken(tk); + + if (rid > 0x3FFFFFF) + // token is too big to be compressed + return (ULONG) -1; + + rid = (rid << 2); + + // TypeDef is encoded with low bits 00 + // TypeRef is encoded with low bits 01 + // TypeSpec is encoded with low bits 10 + // BaseType is encoded with low bit 11 + // + if (ulTyp == g_tkCorEncodeToken[1]) + { + // make the last two bits 01 + rid |= 0x1; + } + else if (ulTyp == g_tkCorEncodeToken[2]) + { + // make last two bits 0 + rid |= 0x2; + } + else if (ulTyp == g_tkCorEncodeToken[3]) + { + rid |= 0x3; + } + return CorSigCompressData((ULONG)rid, pDataOut); +} + +// compress a signed integer +// The least significant bit of the first compress byte will be the signed bit. +// +inline ULONG CorSigCompressSignedInt( // return number of bytes that compressed form of iData will take + int iData, // [IN] given integer + void * pDataOut) // [OUT] buffer where iLen will be compressed and stored. +{ + ULONG isSigned = 0; + BYTE *pBytes = reinterpret_cast(pDataOut); + + if (iData < 0) + isSigned = 0x1; + + // Note that we cannot use code:CorSigCompressData to pack the iData value, because of negative values + // like: 0xffffe000 (-8192) which has to be encoded as 1 in 2 bytes, i.e. 0x81 0x00 + // However CorSigCompressedData would store value 1 as 1 byte: 0x01 + if ((iData & SIGN_MASK_ONEBYTE) == 0 || (iData & SIGN_MASK_ONEBYTE) == SIGN_MASK_ONEBYTE) + { + iData = (int)((iData & ~SIGN_MASK_ONEBYTE) << 1 | isSigned); + //_ASSERTE(iData <= 0x7f); + *pBytes = BYTE(iData); + return 1; + } + else if ((iData & SIGN_MASK_TWOBYTE) == 0 || (iData & SIGN_MASK_TWOBYTE) == SIGN_MASK_TWOBYTE) + { + iData = (int)((iData & ~SIGN_MASK_TWOBYTE) << 1 | isSigned); + //_ASSERTE(iData <= 0x3fff); + *pBytes = BYTE((iData >> 8) | 0x80); + *(pBytes + 1) = BYTE(iData & 0xff); + return 2; + } + else if ((iData & SIGN_MASK_FOURBYTE) == 0 || (iData & SIGN_MASK_FOURBYTE) == SIGN_MASK_FOURBYTE) + { + iData = (int)((iData & ~SIGN_MASK_FOURBYTE) << 1 | isSigned); + //_ASSERTE(iData <= 0x1FFFFFFF); + *pBytes = BYTE((iData >> 24) | 0xC0); + *(pBytes + 1) = BYTE((iData >> 16) & 0xff); + *(pBytes + 2) = BYTE((iData >> 8) & 0xff); + *(pBytes + 3) = BYTE(iData & 0xff); + return 4; + } + // Out of compressable range + return (ULONG)-1; +} // CorSigCompressSignedInt + + +// uncompress encoded element type +inline ULONG CorSigCompressElementType( // return number of bytes of that compressed data occupied in pData + CorElementType et, // [OUT] the expanded *pData + void * pData) // [IN] compressed data +{ + BYTE *pBytes = (BYTE *)(pData); + + *pBytes = BYTE(et); + return 1; +} + +// Compress a pointer (used for internal element types only, never for persisted +// signatures). +inline ULONG CorSigCompressPointer( // return number of bytes of that compressed data occupied + void * pvPointer, // [IN] given uncompressed data + void * pData) // [OUT] buffer where iLen will be compressed and stored. +{ + *((void * UNALIGNED *)pData) = pvPointer; + return sizeof(void *); +} + +// Uncompress a pointer (see above for comments). +inline ULONG CorSigUncompressPointer( // return number of bytes of that compressed data occupied + PCCOR_SIGNATURE pData, // [IN] compressed data + void ** ppvPointer) // [OUT] the expanded *pData +{ + *ppvPointer = *(void * const UNALIGNED *)pData; + return sizeof(void *); +} + +#endif // __cplusplus + +#endif // _COR_H_ +// EOF ======================================================================= diff --git a/lib/coreclr/src/inc/corbbtprof.h b/lib/coreclr/src/inc/corbbtprof.h new file mode 100644 index 0000000000..f7258c1e5b --- /dev/null +++ b/lib/coreclr/src/inc/corbbtprof.h @@ -0,0 +1,592 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*****************************************************************************\ +* * +* CorBBTProf.h - File format for profile data * +* * +* Version 1.0 * +******************************************************************************* +* * +* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +* PURPOSE. * +* * +\*****************************************************************************/ + +#ifndef _COR_BBTPROF_H_ +#define _COR_BBTPROF_H_ + +#include +#include + +const CorTokenType ibcExternalNamespace = CorTokenType(0x61000000); +const CorTokenType ibcExternalType = CorTokenType(0x62000000); +const CorTokenType ibcExternalSignature = CorTokenType(0x63000000); +const CorTokenType ibcExternalMethod = CorTokenType(0x64000000); +const CorTokenType ibcTypeSpec = CorTokenType(0x68000000); +const CorTokenType ibcMethodSpec = CorTokenType(0x69000000); + +typedef mdToken idExternalNamespace; // External Namespace token in the IBC data +typedef mdToken idExternalType; // External Type token in the IBC data +typedef mdToken idExternalSignature; // External Signature token in the IBC data +typedef mdToken idExternalMethod; // External Method token in the IBC data +typedef mdToken idTypeSpec; // TypeSpec token in the IBC data +typedef mdToken idMethodSpec; // MethodSpec token in the IBC data + +#define idExternalNamespaceNil ((idExternalNamespace) ibcExternalNamespace) +#define idExternalTypeNil ((idExternalType) ibcExternalType) +#define idExternalSignatureNil ((idExternalSignature) ibcExternalSignature) +#define idExternalMethodNil ((idExternalMethod) ibcExternalMethod) +#define idTypeSpecNil ((idTypeSpec) ibcTypeSpec) +#define idMethodSpecNil ((idMethodSpec) ibcMethodSpec) + +// +// File format: +// +// CORBBTPROF_FILE_HEADER +// CORBBTPROF_SECTION_TABLE_HEADER +// CORBBTPROF_SECTION_TABLE_ENTRY +// ... (can be multiple entries) +// +// Method block counts section: +// CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER +// CORBBTPROF_METHOD_HEADER +// CORBBTPROF_BLOCK_DATA +// ... (can be multiple method header/block data entries) +// +// Method load order section: +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// +// Type token usage information +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// MethodDef token usage information +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// RIDs to not use slim headers section +// CORBBTPROF_TOKEN_LIST_SECTION_HEADER +// ... (list of tokens) +// + +// Metadata hints to re-order some tables +// Instantiated TypeSPecs to re-order EEClasses +// +// The header for the profile data file. +// ... (list of CORBBTPROF_BLOB_ENTRY) +// terminated by null + +struct CORBBTPROF_FILE_HEADER +{ + DWORD HeaderSize; + DWORD Magic; + DWORD Version; + GUID MVID; +}; + +// Optional in V1 and V2. Usually present in V2. Must be present in V3. +struct CORBBTPROF_FILE_OPTIONAL_HEADER +{ + DWORD Size; // Including the size field + DWORD MinorVersion; + DWORD FileFlags; // Only in V3 or later + // future fields +}; + +enum CORBBTPROF_FILE_FLAGS +{ + CORBBTPROF_FILE_FLAG_MINIFIED = 1, + CORBBTPROF_FILE_FLAG_PARTIAL_NGEN = 2 +}; + +enum +{ + CORBBTPROF_V0_VERSION = 0, + CORBBTPROF_V1_VERSION = 1, + CORBBTPROF_V2_VERSION = 2, + CORBBTPROF_V3_VERSION = 3, + CORBBTPROF_CURRENT_VERSION = CORBBTPROF_V2_VERSION, // V3 is opt-in + CORBBTPROF_MAGIC = 0xb1d0f11e, + CORBBTPROF_END_TOKEN = 0xb4356f98 +}; + +// +// The profile data can be mapped anywhere in memory. So instead of using pointers, +// to denote sections, we will instead use offsets from the beginning of the file. +// + +struct Section +{ + DWORD Offset; + DWORD Size; +}; + +// +// Section types, where various sections contains different types of profile data. +// + +#define CORBBTPROF_TOKEN_MAX_NUM_FLAGS 32 + +enum TypeProfilingDataFlags +{ + // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these + ReadMethodTable = 0, // 0x00001 + ReadEEClass = 1, // 0x00002 + WriteEEClass = 2, // 0x00004 +// ReadStoredEnumData = 3, // 0x00008 // obsolete + ReadFieldDescs = 4, // 0x00010 + ReadCCtorInfo = 5, // 0x00020 + ReadClassHashTable = 6, // 0x00040 + ReadDispatchMap = 7, // 0x00080 + ReadDispatchTable = 8, // 0x00100 + ReadMethodTableWriteableData = 9, // 0x00200 + ReadFieldMarshalers = 10, // 0x00400 +// WriteDispatchTable = 11, // 0x00800 // obsolete +// WriteMethodTable = 12, // 0x01000 // obsolete + WriteMethodTableWriteableData = 13, // 0x02000 + ReadTypeDesc = 14, // 0x04000 + WriteTypeDesc = 15, // 0x08000 + ReadTypeHashTable = 16, // 0x10000 +// WriteTypeHashTable = 17, // 0x20000 // obsolete +// ReadDictionary = 18, // 0x40000 // obsolete +// WriteDictionary = 19, // 0x80000 // obsolete + ReadNonVirtualSlots = 20, // 0x100000 +}; + +enum MethodProfilingDataFlags +{ + // Important: update toolbox\ibcmerge\ibcmerge.cs if you change these + ReadMethodCode = 0, // 0x00001 // Also means the method was executed + ReadMethodDesc = 1, // 0x00002 + RunOnceMethod = 2, // 0x00004 + RunNeverMethod = 3, // 0x00008 +// MethodStoredDataAccess = 4, // 0x00010 // obsolete + WriteMethodDesc = 5, // 0x00020 +// ReadFCallHash = 6, // 0x00040 // obsolete + ReadGCInfo = 7, // 0x00080 + CommonReadGCInfo = 8, // 0x00100 +// ReadMethodDefRidMap = 9, // 0x00200 // obsolete + ReadCerMethodList = 10, // 0x00400 + ReadMethodPrecode = 11, // 0x00800 + WriteMethodPrecode = 12, // 0x01000 + ExcludeHotMethodCode = 13, // 0x02000 // Hot method should be excluded from the ReadyToRun image + ExcludeColdMethodCode = 14, // 0x04000 // Cold method should be excluded from the ReadyToRun image + DisableInlining = 15, // 0x08000 // Disable inlining of this method in optimized AOT native code +}; + +enum GeneralProfilingDataFlags +{ + // Important: update ibcmerge.cs if you change these + // ZapImage.h depends on 0xFFFFFFFF being an invalid flag value. If this + // changes, update ReadFlagWithMemory in that file. + // Important: make sure these don't collide with TypeProfilingDataFlags or MethodProfilingDataFlags + // These grow downward from CORBBTPROF_TOKEN_MAX_NUM_FLAGS-1 to minimize the chance of collision + ProfilingFlags_MetaData = 31, // 0x800... + CommonMetaData = 30, // 0x400... + RidMap = 29, // 0x200... + RVAFieldData = 28, // 0x100... + ProfilingFlags_MetaDataSearch = 27, // 0x080... +}; + +enum BlobType +{ + /* IMPORTANT: Keep the first four enums together in the same order and at + the very begining of this enum. See MetaModelPub.h for the order */ + MetadataStringPool = 0, + MetadataGuidPool = 1, + MetadataBlobPool = 2, + MetadataUserStringPool = 3, + + FirstMetadataPool = 0, + LastMetadataPool = 3, + + // SectionFormat only supports tokens, which have to already exist in the module. + // For instantiated paramterized types, there may be no corresponding token + // in the module, if a dependent module caused the type to be instantiated. + // For such instantiated types, we save a blob/signature to identify the type. + // + ParamTypeSpec = 4, // Instantiated Type Signature + ParamMethodSpec = 5, // Instantiated Method Signature + ExternalNamespaceDef = 6, // External Namespace Token Definition + ExternalTypeDef = 7, // External Type Token Definition + ExternalSignatureDef = 8, // External Signature Definition + ExternalMethodDef = 9, // External Method Token Definition + + IllegalBlob = 10, // Failed to allocate the blob + + EndOfBlobStream = -1 +}; + +enum SectionFormat +{ + // Important: update ibcmerge.cs if you change these + ScenarioInfo = 0, + MethodBlockCounts = 1, // Basic-block counts. Cold blocks will be placed in the cold-code section + BlobStream = 2, // metadata access, inst-type-spec and inst-method-spec blobs + + FirstTokenFlagSection = 3, + + ModuleProfilingData = FirstTokenFlagSection + (mdtModule >> 24), + TypeRefProfilingData = FirstTokenFlagSection + (mdtTypeRef >> 24), + TypeProfilingData = FirstTokenFlagSection + (mdtTypeDef >> 24), + FieldDefProfilingData = FirstTokenFlagSection + (mdtFieldDef >> 24), + MethodProfilingData = FirstTokenFlagSection + (mdtMethodDef >> 24), + ParamDefProfilingData = FirstTokenFlagSection + (mdtParamDef >> 24), + InterfaceImplProfilingData = FirstTokenFlagSection + (mdtInterfaceImpl >> 24), + MemberRefProfilingData = FirstTokenFlagSection + (mdtMemberRef >> 24), + CustomAttributeProfilingData = FirstTokenFlagSection + (mdtCustomAttribute >> 24), + PermissionProfilingData = FirstTokenFlagSection + (mdtPermission >> 24), + SignatureProfilingData = FirstTokenFlagSection + (mdtSignature >> 24), + EventProfilingData = FirstTokenFlagSection + (mdtEvent >> 24), + PropertyProfilingData = FirstTokenFlagSection + (mdtProperty >> 24), + ModuleRefProfilingData = FirstTokenFlagSection + (mdtModuleRef >> 24), + TypeSpecProfilingData = FirstTokenFlagSection + (mdtTypeSpec >> 24), + AssemblyProfilingData = FirstTokenFlagSection + (mdtAssembly >> 24), + AssemblyRefProfilingData = FirstTokenFlagSection + (mdtAssemblyRef >> 24), + FileProfilingData = FirstTokenFlagSection + (mdtFile >> 24), + ExportedTypeProfilingData = FirstTokenFlagSection + (mdtExportedType >> 24), + ManifestResourceProfilingData = FirstTokenFlagSection + (mdtManifestResource >> 24), + GenericParamProfilingData = FirstTokenFlagSection + (mdtGenericParam >> 24), + MethodSpecProfilingData = FirstTokenFlagSection + (mdtMethodSpec >> 24), + GenericParamConstraintProfilingData = FirstTokenFlagSection + (mdtGenericParamConstraint >> 24), + + StringPoolProfilingData, + GuidPoolProfilingData, + BlobPoolProfilingData, + UserStringPoolProfilingData, + + FirstMetadataPoolSection = StringPoolProfilingData, + LastMetadataPoolSection = UserStringPoolProfilingData, + LastTokenFlagSection = LastMetadataPoolSection, + + IbcTypeSpecSection, + IbcMethodSpecSection, + + GenericTypeProfilingData = 63, // Deprecated with V2 IBC data + SectionFormatCount = 64, // 0x40 + + SectionFormatInvalid = -1 +}; + +struct CORBBTPROF_SECTION_TABLE_ENTRY +{ + SectionFormat FormatID; + Section Data; +}; + +struct CORBBTPROF_SECTION_TABLE_HEADER +{ + DWORD NumEntries; + CORBBTPROF_SECTION_TABLE_ENTRY Entries[0]; +}; + +// +// ScenarioInfo section +// + +struct CORBBTPROF_SCENARIO_RUN +{ + FILETIME runTime; // the FILETIME when the scenario was cnt + GUID mvid; // The GUID of this assembly when the scenario was run (useful for incremental ibcdata) + DWORD cCmdLine; // the count of WCHAR's in the cmdLine for this run of the scenario + DWORD cSystemInfo; // the count of WCHAR's in the systemInfo string for this run of the scenario + WCHAR cmdLine[0]; // the command line used, the array is 'cName' in length +// WCHAR systemInfo[]; // the system information, the array is 'cSystemInfo' in length + + DWORD sizeofCmdLine() + { + return (cCmdLine * (DWORD)sizeof(WCHAR)); + } + + DWORD sizeofSystemInfo() + { + return (cSystemInfo * (DWORD)sizeof(WCHAR)); + } + + DWORD Size() + { + return (DWORD)sizeof(CORBBTPROF_SCENARIO_RUN) + sizeofCmdLine() + sizeofSystemInfo(); + } + + CORBBTPROF_SCENARIO_RUN* GetNextRun() + { + return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >( + reinterpret_cast< PBYTE >( this + 1 ) + Size() ); + } +}; + +struct CORBBTPROF_SCENARIO_INFO +{ + DWORD ordinal; // the id number for this scenario + DWORD mask; // the one-bit mask use to identify this scenario + DWORD priority; // the priority of this scenario + DWORD numRuns; // the number of times this scenario was run + DWORD cName; // the count of WCHAR's in name[] + WCHAR name[0]; // the name of this scenario, the array is 'cName' in length +// CORBBTPROF_SCENARIO_RUN run[]; // the array is 'numRuns' in length + + DWORD sizeofName() + { + return (DWORD) (cName * sizeof(WCHAR)); + } + + DWORD Size() + { + return (DWORD) sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName() + sizeofRuns(); + } + + CORBBTPROF_SCENARIO_RUN* GetScenarioRun() + { + return reinterpret_cast< CORBBTPROF_SCENARIO_RUN* >( + reinterpret_cast< PBYTE >( this ) + (DWORD)sizeof(CORBBTPROF_SCENARIO_INFO) + sizeofName()); + } + + DWORD sizeofRuns() + { + DWORD sum = 0; + if (numRuns > 0) + { + DWORD cnt = 1; + CORBBTPROF_SCENARIO_RUN* pRun = GetScenarioRun(); + do + { + sum += pRun->Size(); + if (cnt == numRuns) + break; + cnt++; + pRun = pRun->GetNextRun(); + } + while (true); + } + return sum; + } +}; + +struct CORBBTPROF_SCENARIO_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_SCENARIO_HEADER + CORBBTPROF_SCENARIO_INFO scenario; + + DWORD Size() + { + return (DWORD) sizeof(CORBBTPROF_SCENARIO_HEADER) + scenario.sizeofName() + scenario.sizeofRuns(); + } +}; + +struct CORBBTPROF_SCENARIO_INFO_SECTION_HEADER +{ + DWORD TotalNumRuns; + DWORD NumScenarios; +// CORBBTPROF_SCENARIO_HEADER scenario[0]; // array is 'NumScenarios' in length +}; + +// +// MethodBlockCounts section +// + +struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 +{ + DWORD NumMethods; + DWORD NumRuns; +}; + +struct CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER +{ + DWORD NumMethods; +}; + +struct CORBBTPROF_BLOCK_DATA // This struct is also defined by: ICorJitInfo.BlockCounts +{ + UINT32 ILOffset; + UINT32 ExecutionCount; +}; + +struct CORBBTPROF_METHOD_DETAIL_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_DETAIL_HEADER at this level + DWORD kind; // Identifier that specifies what kind this CORBBTPROF_METHOD_DETAIL_HEADER actually represents + + size_t Size() + { + return size; + } +}; + +// +// This struct records the basic block execution counts for a method +// +struct CORBBTPROF_METHOD_INFO +{ + DWORD token; // token for this method + DWORD ILSize; // IL size for this method + DWORD cBlock; // count for block[] + CORBBTPROF_BLOCK_DATA block[0]; // actually 'cBlock' in length + + size_t Size() + { + return sizeof(CORBBTPROF_METHOD_INFO) + sizeofBlock(); + } + + size_t sizeofBlock() + { + return cBlock * sizeof(CORBBTPROF_BLOCK_DATA); + } +}; + +struct CORBBTPROF_METHOD_HEADER_V1 +{ + DWORD HeaderSize; + mdToken MethodToken; + DWORD Size; +}; + +struct CORBBTPROF_METHOD_HEADER +{ + DWORD size; // Size to skip to get to the next CORBBTPROF_METHOD_HEADER + DWORD cDetail; // the count of CORBBTPROF_METHOD_DETAIL_HEADER records that folow this record + CORBBTPROF_METHOD_INFO method; // Basic block execution counts for a method + // ... followed by 'cDetail' occurances of CORBBTPROF_METHOD_DETAIL_HEADER + + size_t Size() + { + return sizeof(CORBBTPROF_METHOD_HEADER) + method.sizeofBlock(); + } +}; + + +struct CORBBTPROF_TOKEN_LIST_SECTION_HEADER +{ + DWORD NumTokens; +}; + +struct CORBBTPROF_TOKEN_LIST_ENTRY_V1 +{ + mdToken token; + DWORD flags; +}; + +struct CORBBTPROF_TOKEN_INFO // Was CORBBTPROF_TOKEN_LIST_ENTRY +{ + mdToken token; + DWORD flags; + DWORD scenarios; // Could use UINT64 instead + + CORBBTPROF_TOKEN_INFO() + : token(0) + , flags(0) + , scenarios(0) + {} + + CORBBTPROF_TOKEN_INFO( mdToken t, DWORD f = 0, DWORD s = 0) + : token(t) + , flags(f) + , scenarios(s) + {} + + CORBBTPROF_TOKEN_INFO( CORBBTPROF_TOKEN_INFO const & right ) + : token(right.token) + , flags(right.flags) + , scenarios(right.scenarios) + {} + + CORBBTPROF_TOKEN_INFO operator=( CORBBTPROF_TOKEN_INFO const & right ) + { + token = right.token; + flags = right.flags; + scenarios = right.scenarios; + return *this; + } + + bool operator<( CORBBTPROF_TOKEN_INFO const & right ) const + { + return token < right.token; + } +}; + +struct CORBBTPROF_BLOB_ENTRY_V1 +{ + BlobType blobType; + DWORD flags; + DWORD cBuffer; + BYTE pBuffer[0]; // actually 'cBuffer' in length + + CORBBTPROF_BLOB_ENTRY_V1 * GetNextEntry() + { + return reinterpret_cast< CORBBTPROF_BLOB_ENTRY_V1* >( + reinterpret_cast< PBYTE >( this + 1 ) + cBuffer ); + } +}; + +struct CORBBTPROF_BLOB_ENTRY +{ + DWORD size; + BlobType type; + mdToken token; // The code:CORBBTPROF_BLOB_ENTRY.token field is not a real meta-data token + // but a look-alike that IBCMerge makes to represent blob entry + + bool TypeIsValid() + { + return (type >= MetadataStringPool) && (type < IllegalBlob); + } + + CORBBTPROF_BLOB_ENTRY * GetNextEntry() + { + return reinterpret_cast< CORBBTPROF_BLOB_ENTRY* >( + reinterpret_cast< PBYTE >( this ) + size); + } +}; + +struct CORBBTPROF_BLOB_PARAM_SIG_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cSig; + COR_SIGNATURE sig[0]; // actually 'cSig' in length +}; + +struct CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_TYPE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + mdToken assemblyRefToken; + mdToken nestedClassToken; + mdToken nameSpaceToken; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cSig; + COR_SIGNATURE sig[0]; // actually 'cSig' in length +}; + +struct CORBBTPROF_BLOB_METHOD_DEF_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + mdToken nestedClassToken; + mdToken signatureToken; + DWORD cName; + CHAR name[0]; // actually cName in length +}; + +struct CORBBTPROF_BLOB_POOL_ENTRY +{ + CORBBTPROF_BLOB_ENTRY blob; + DWORD cBuffer; + BYTE buffer[0]; // actually 'cBuffer' in length +}; +#endif /* COR_BBTPROF_H_ */ diff --git a/lib/coreclr/src/inc/corcompile.h b/lib/coreclr/src/inc/corcompile.h new file mode 100644 index 0000000000..755c846f51 --- /dev/null +++ b/lib/coreclr/src/inc/corcompile.h @@ -0,0 +1,1827 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*****************************************************************************\ +* * +* CorCompile.h - EE / Compiler interface * +* * +* Version 1.0 * +******************************************************************************* +* * +* * +* * +\*****************************************************************************/ +// See code:CorProfileData for information on Hot Cold splitting using profile data. + + +#ifndef _COR_COMPILE_H_ +#define _COR_COMPILE_H_ + +#if !defined(_TARGET_X86_) || defined(FEATURE_PAL) +#ifndef WIN64EXCEPTIONS +#define WIN64EXCEPTIONS +#endif +#endif // !_TARGET_X86_ || FEATURE_PAL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef DPTR(struct CORCOMPILE_CODE_MANAGER_ENTRY) + PTR_CORCOMPILE_CODE_MANAGER_ENTRY; +typedef DPTR(struct CORCOMPILE_EE_INFO_TABLE) + PTR_CORCOMPILE_EE_INFO_TABLE; +typedef DPTR(struct CORCOMPILE_HEADER) + PTR_CORCOMPILE_HEADER; +typedef DPTR(struct CORCOMPILE_COLD_METHOD_ENTRY) + PTR_CORCOMPILE_COLD_METHOD_ENTRY; +typedef DPTR(struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE) + PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE; +typedef DPTR(struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY) + PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY; +typedef DPTR(struct CORCOMPILE_EXCEPTION_CLAUSE) + PTR_CORCOMPILE_EXCEPTION_CLAUSE; +typedef DPTR(struct CORCOMPILE_VIRTUAL_IMPORT_THUNK) + PTR_CORCOMPILE_VIRTUAL_IMPORT_THUNK; +typedef DPTR(struct CORCOMPILE_EXTERNAL_METHOD_THUNK) + PTR_CORCOMPILE_EXTERNAL_METHOD_THUNK; +typedef DPTR(struct CORCOMPILE_EXTERNAL_METHOD_DATA_ENTRY) + PTR_CORCOMPILE_EXTERNAL_METHOD_DATA_ENTRY; +typedef DPTR(struct CORCOMPILE_VIRTUAL_SECTION_INFO) + PTR_CORCOMPILE_VIRTUAL_SECTION_INFO; +typedef DPTR(struct CORCOMPILE_IMPORT_SECTION) + PTR_CORCOMPILE_IMPORT_SECTION; + +#ifdef _TARGET_X86_ + +typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; + + +// Chained unwind info. Used for cold methods. +#define RUNTIME_FUNCTION_INDIRECT 0x80000000 + +#endif // _TARGET_X86_ + +// The stride is choosen as maximum value that still gives good page locality of RUNTIME_FUNCTION table touches (only one page of +// RUNTIME_FUNCTION table is going to be touched during most IP2MD lookups). +// +// Smaller stride values also improve speed of IP2MD lookups, but this improvement is not significant (5% when going +// from 8192 to 1024), so the working set / page locality was used as the metric to choose the optimum value. +// +#define RUNTIME_FUNCTION_LOOKUP_STRIDE 8192 + + +typedef DPTR(struct CORCOMPILE_METHOD_PROFILE_LIST) + PTR_CORCOMPILE_METHOD_PROFILE_LIST; +typedef DPTR(struct CORCOMPILE_RUNTIME_DLL_INFO) + PTR_CORCOMPILE_RUNTIME_DLL_INFO; +typedef DPTR(struct CORCOMPILE_VERSION_INFO) PTR_CORCOMPILE_VERSION_INFO; +typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD; + +// This can be used to specify a dll that should be used as the compiler during ngen. +// If this is not specified, the default compiler dll will be used. +// If this is specified, it needs to be specified for all the assemblies that are ngenned. +#define NGEN_COMPILER_OVERRIDE_KEY W("NGen_JitName") + +// +// CORCOMPILE_IMPORT_SECTION describes image range with references to other assemblies or runtime data structures +// +// There is number of different types of these ranges: eagerly initialized at image load vs. lazily initialized at method entry +// vs. lazily initialized on first use; hot vs. cold, handles vs. code pointers, etc. +// +struct CORCOMPILE_IMPORT_SECTION +{ + IMAGE_DATA_DIRECTORY Section; // Section containing values to be fixed up + USHORT Flags; // One or more of CorCompileImportFlags + BYTE Type; // One of CorCompileImportType + BYTE EntrySize; + DWORD Signatures; // RVA of optional signature descriptors + DWORD AuxiliaryData; // RVA of optional auxiliary data (typically GC info) +}; + +enum CorCompileImportType +{ + CORCOMPILE_IMPORT_TYPE_UNKNOWN = 0, + CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD = 1, + CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH = 2, + CORCOMPILE_IMPORT_TYPE_STRING_HANDLE = 3, + CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE = 4, + CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE = 5, + CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD = 6, +}; + +enum CorCompileImportFlags +{ + CORCOMPILE_IMPORT_FLAGS_EAGER = 0x0001, // Section at module load time. + CORCOMPILE_IMPORT_FLAGS_CODE = 0x0002, // Section contains code. + CORCOMPILE_IMPORT_FLAGS_PCODE = 0x0004, // Section contains pointers to code. +}; + +// ================================================================================ +// Portable tagged union of a pointer field with a 30 bit scalar value +// ================================================================================ + +// The lowest bit of the tag will be set for tagged pointers. We also set the highest bit for convenience. +// It makes dereferences of tagged pointers to crash under normal circumstances. +// The highest bit of the tag will be set for tagged indexes (e.g. classid). + +#define CORCOMPILE_TOKEN_TAG 0x80000001 + +// These two macros are mostly used just for debug-only checks to ensure that we have either tagged pointer (lowest bit is set) +// or tagged index (highest bit is set). +#define CORCOMPILE_IS_POINTER_TAGGED(token) ((((SIZE_T)(token)) & 0x00000001) != 0) +#define CORCOMPILE_IS_INDEX_TAGGED(token) ((((SIZE_T)(token)) & 0x80000000) != 0) + +// The token (RVA of the fixup in most cases) is stored in the mid 30 bits of DWORD +#define CORCOMPILE_TAG_TOKEN(token) ((SIZE_T)(((token)<<1)|CORCOMPILE_TOKEN_TAG)) +#define CORCOMPILE_UNTAG_TOKEN(token) ((((SIZE_T)(token))&~CORCOMPILE_TOKEN_TAG)>>1) + +#ifdef _TARGET_ARM_ +// Tagging of code pointers on ARM uses inverse logic because of the thumb bit. +#define CORCOMPILE_IS_PCODE_TAGGED(token) ((((SIZE_T)(token)) & 0x00000001) == 0x00000000) +#define CORCOMPILE_TAG_PCODE(token) ((SIZE_T)(((token)<<1)|0x80000000)) +#else +#define CORCOMPILE_IS_PCODE_TAGGED(token) CORCOMPILE_IS_POINTER_TAGGED(token) +#define CORCOMPILE_TAG_PCODE(token) CORCOMPILE_TAG_TOKEN(token) +#endif + +inline BOOL CORCOMPILE_IS_FIXUP_TAGGED(SIZE_T fixup, PTR_CORCOMPILE_IMPORT_SECTION pSection) +{ +#ifdef _TARGET_ARM_ + // Tagging of code pointers on ARM has to use inverse logic because of the thumb bit + if (pSection->Flags & CORCOMPILE_IMPORT_FLAGS_PCODE) + { + return CORCOMPILE_IS_PCODE_TAGGED(fixup); + } +#endif + + return ((((SIZE_T)(fixup)) & CORCOMPILE_TOKEN_TAG) == CORCOMPILE_TOKEN_TAG); +} + +enum CorCompileBuild +{ + CORCOMPILE_BUILD_CHECKED, + CORCOMPILE_BUILD_FREE +}; + +enum CorCompileCodegen +{ + CORCOMPILE_CODEGEN_DEBUGGING = 0x0001, // suports debugging (unoptimized code with symbol info) + + CORCOMPILE_CODEGEN_PROFILING = 0x0004, // supports profiling + CORCOMPILE_CODEGEN_PROF_INSTRUMENTING = 0x0008, // code is instrumented to collect profile count info + +}; + + +// Used for INativeImageInstallInfo::GetConfigMask() +// A bind will ask for the particular bits it needs set; if all bits are set, it is a match. Additional +// bits are ignored. + +enum CorCompileConfigFlags +{ + CORCOMPILE_CONFIG_DEBUG_NONE = 0x01, // Assembly has Optimized code + CORCOMPILE_CONFIG_DEBUG = 0x02, // Assembly has non-Optimized debuggable code + CORCOMPILE_CONFIG_DEBUG_DEFAULT = 0x08, // Additional flag set if this particular setting is the + // one indicated by the assembly debug custom attribute. + + CORCOMPILE_CONFIG_PROFILING_NONE = 0x100, // Assembly code has profiling hooks + CORCOMPILE_CONFIG_PROFILING = 0x200, // Assembly code has profiling hooks + + CORCOMPILE_CONFIG_INSTRUMENTATION_NONE = 0x1000, // Assembly code has no instrumentation + CORCOMPILE_CONFIG_INSTRUMENTATION = 0x2000, // Assembly code has basic block instrumentation +}; + +// Values for Flags field of CORCOMPILE_HEADER. +enum CorCompileHeaderFlags +{ + CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY = 0x00000001, // Original image had a security directory + // Note it is useless to cache the actual directory contents + // since it must be verified as part of the original image + CORCOMPILE_HEADER_IS_IBC_OPTIMIZED = 0x00000002, + + CORCOMPILE_HEADER_IS_READY_TO_RUN = 0x00000004, +}; + +// +// !!! INCREMENT THE MAJOR VERSION ANY TIME THERE IS CHANGE IN CORCOMPILE_HEADER STRUCTURE !!! +// +#define CORCOMPILE_SIGNATURE 0x0045474E // 'NGEN' +#define CORCOMPILE_MAJOR_VERSION 0x0001 +#define CORCOMPILE_MINOR_VERSION 0x0000 + +// This structure is pointed to by the code:IMAGE_COR20_HEADER (see file:corcompile.h#ManagedHeader) +// See the file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for more +struct CORCOMPILE_HEADER +{ + // For backward compatibility reasons, VersionInfo field must be at offset 40, ManifestMetaData + // must be at 88, PEKind must be at 112/116 bytes, Machine must be at 120/124 bytes, and + // size of CORCOMPILE_HEADER must be 164/168 bytes. Be careful when you modify this struct. + // See code:PEDecoder::GetMetaDataHelper. + DWORD Signature; + USHORT MajorVersion; + USHORT MinorVersion; + + IMAGE_DATA_DIRECTORY HelperTable; // Table of function pointers to JIT helpers indexed by helper number + IMAGE_DATA_DIRECTORY ImportSections; // points to array of code:CORCOMPILE_IMPORT_SECTION + IMAGE_DATA_DIRECTORY Dummy0; + IMAGE_DATA_DIRECTORY StubsData; // contains the value to register with the stub manager for the delegate stubs & AMD64 tail call stubs + IMAGE_DATA_DIRECTORY VersionInfo; // points to a code:CORCOMPILE_VERSION_INFO + IMAGE_DATA_DIRECTORY Dependencies; // points to an array of code:CORCOMPILE_DEPENDENCY + IMAGE_DATA_DIRECTORY DebugMap; // points to an array of code:CORCOMPILE_DEBUG_RID_ENTRY hashed by method RID + IMAGE_DATA_DIRECTORY ModuleImage; // points to the freeze dried Module structure + IMAGE_DATA_DIRECTORY CodeManagerTable; // points to a code:CORCOMPILE_CODE_MANAGER_ENTRY + IMAGE_DATA_DIRECTORY ProfileDataList;// points to the list of code:CORCOMPILE_METHOD_PROFILE_LIST + IMAGE_DATA_DIRECTORY ManifestMetaData; // points to the native manifest metadata + IMAGE_DATA_DIRECTORY VirtualSectionsTable;// List of CORCOMPILE_VIRTUAL_SECTION_INFO. Contains a list of Section + // ranges for debugging purposes. There is one entry in this table per + // ZapVirtualSection in the NGEN image. This data is used to fire ETW + // events that describe the various VirtualSection in the NGEN image. These + // events are used for diagnostics and performance purposes. Some of the + // questions these events help answer are like : how effective is IBC + // training data. They can also be used to have better nidump support for + // decoding virtual section information ( start - end ranges for each + // virtual section ) + + TADDR ImageBase; // Actual image base address (ASLR fakes the image base in PE header while applying relocations in kernel) + DWORD Flags; // Flags, see CorCompileHeaderFlags above + + DWORD PEKind; // CorPEKind of the original IL image + + ULONG COR20Flags; // Cached value of code:IMAGE_COR20_HEADER.Flags from original IL image + WORD Machine; // Cached value of _IMAGE_FILE_HEADER.Machine from original IL image + WORD Characteristics;// Cached value of _IMAGE_FILE_HEADER.Characteristics from original IL image + + IMAGE_DATA_DIRECTORY EEInfoTable; // points to a code:CORCOMPILE_EE_INFO_TABLE + + // For backward compatibility (see above) + IMAGE_DATA_DIRECTORY Dummy1; + IMAGE_DATA_DIRECTORY Dummy2; + IMAGE_DATA_DIRECTORY Dummy3; + IMAGE_DATA_DIRECTORY Dummy4; +}; + +// CORCOMPILE_VIRTUAL_SECTION_INFO describes virtual section ranges. This data is used by nidump +// and to fire ETW that are used for diagnostics and performance purposes. Some of the questions +// these events help answer are like : how effective is IBC training data. +struct CORCOMPILE_VIRTUAL_SECTION_INFO +{ + ULONG VirtualAddress; + ULONG Size; + DWORD SectionType; +}; + +#define CORCOMPILE_SECTION_TYPES() \ + CORCOMPILE_SECTION_TYPE(Module) \ + CORCOMPILE_SECTION_TYPE(EETable) \ + CORCOMPILE_SECTION_TYPE(WriteData) \ + CORCOMPILE_SECTION_TYPE(WriteableData) \ + CORCOMPILE_SECTION_TYPE(Data) \ + CORCOMPILE_SECTION_TYPE(RVAStatics) \ + CORCOMPILE_SECTION_TYPE(EEData) \ + CORCOMPILE_SECTION_TYPE(DelayLoadInfoTableEager) \ + CORCOMPILE_SECTION_TYPE(DelayLoadInfoTable) \ + CORCOMPILE_SECTION_TYPE(EEReadonlyData) \ + CORCOMPILE_SECTION_TYPE(ReadonlyData) \ + CORCOMPILE_SECTION_TYPE(Class) \ + CORCOMPILE_SECTION_TYPE(CrossDomainInfo) \ + CORCOMPILE_SECTION_TYPE(MethodDesc) \ + CORCOMPILE_SECTION_TYPE(MethodDescWriteable) \ + CORCOMPILE_SECTION_TYPE(Exception) \ + CORCOMPILE_SECTION_TYPE(Instrument) \ + CORCOMPILE_SECTION_TYPE(VirtualImportThunk) \ + CORCOMPILE_SECTION_TYPE(ExternalMethodThunk) \ + CORCOMPILE_SECTION_TYPE(HelperTable) \ + CORCOMPILE_SECTION_TYPE(MethodPrecodeWriteable) \ + CORCOMPILE_SECTION_TYPE(MethodPrecodeWrite) \ + CORCOMPILE_SECTION_TYPE(MethodPrecode) \ + CORCOMPILE_SECTION_TYPE(Win32Resources) \ + CORCOMPILE_SECTION_TYPE(Header) \ + CORCOMPILE_SECTION_TYPE(Metadata) \ + CORCOMPILE_SECTION_TYPE(DelayLoadInfo) \ + CORCOMPILE_SECTION_TYPE(ImportTable) \ + CORCOMPILE_SECTION_TYPE(Code) \ + CORCOMPILE_SECTION_TYPE(CodeHeader) \ + CORCOMPILE_SECTION_TYPE(CodeManager) \ + CORCOMPILE_SECTION_TYPE(UnwindData) \ + CORCOMPILE_SECTION_TYPE(RuntimeFunction) \ + CORCOMPILE_SECTION_TYPE(Stubs) \ + CORCOMPILE_SECTION_TYPE(StubDispatchData) \ + CORCOMPILE_SECTION_TYPE(ExternalMethodData) \ + CORCOMPILE_SECTION_TYPE(DelayLoadInfoDelayList) \ + CORCOMPILE_SECTION_TYPE(ReadonlyShared) \ + CORCOMPILE_SECTION_TYPE(Readonly) \ + CORCOMPILE_SECTION_TYPE(IL) \ + CORCOMPILE_SECTION_TYPE(GCInfo) \ + CORCOMPILE_SECTION_TYPE(ILMetadata) \ + CORCOMPILE_SECTION_TYPE(Resources) \ + CORCOMPILE_SECTION_TYPE(CompressedMaps) \ + CORCOMPILE_SECTION_TYPE(Debug) \ + CORCOMPILE_SECTION_TYPE(BaseRelocs) \ + +// Hot: Items are frequently accessed ( Indicated by either IBC data, or +// statically known ) + +// Warm : Items are less frequently accessed, or frequently accessed +// but were not touched during IBC profiling. + +// Cold : Least frequently accessed /shouldn't not be accessed +// when running a scenario that was used during IBC +// training ( training scenario ) + +// HotColdSorted : Sections marked with this category means they contain both +// Hot items and Cold items. The hot items are placed before +// the cold items (Sorted) + +#define CORCOMPILE_SECTION_RANGE_TYPES() \ + CORCOMPILE_SECTION_RANGE_TYPE(Hot, 0x00010000) \ + CORCOMPILE_SECTION_RANGE_TYPE(Warm, 0x00020000) \ + CORCOMPILE_SECTION_RANGE_TYPE(Cold, 0x00040000) \ + CORCOMPILE_SECTION_RANGE_TYPE(HotColdSorted, 0x00080000) \ + + +// IBCUnProfiled: Items in this VirtualSection are statically determined to be cold. +// (IBC Profiling wouldn't have helped put these item in a hot section). +// Items that currently doesn't have IBC probs, or are always put in a specific section +// regardless of IBC data should fall in this category. + +// IBCProfiled: IBC profiling placed items in this section, or +// items are NOT placed into a hot section they didn't have IBC profiling data +// ( IBC profiling would have helped put these items in a hot section ) + +#define CORCOMPILE_SECTION_IBCTYPES() \ + CORCOMPILE_SECTION_IBCTYPE(IBCUnProfiled, 0x01000000) \ + CORCOMPILE_SECTION_IBCTYPE(IBCProfiled, 0x02000000) \ + + +// Support for VirtualSection Metadata/Categories +// Please update the VirtualSetionType ETW map in ClrEtwAll.man if you changed this enum. +// ZapVirtualSectionType is used to describe metadata about VirtualSections. +// The metadata consists of 3 sub-metadata parts. +// --------------------------------------------------- +// 1 byte 1 byte 2 bytes -- +// -- +// --------------------------------------------------- +// +// +// VirtualSections are a CLR concept to aggregate data +// items that share common properties together (Hot/Cold/Warm, Writeable/ +// Readonly ...etc.). VirtualSections are tagged with some categories when they +// are created (code:NewVirtualSection) +// The VirtualSection categorize are described more in VirtualSectionType enum. +// The categories describe 2 important aspects for each VirtualSection +// +// *********************************************** +// IBCProfiled v.s NonIBCProfiled Categories. +// ********************************************** +// +// IBCProfiled: Distinguish between sections that IBC profiling data has been used +// to decide the layout of the data items in this section. +// NonIBCProfiled: We don't have IBC data for all our datastructures. +// The access pattern/frequency for some data structures +// are statically determined. Sections that contain these data items +// are marked as NonIBCProfiled. +// +//*************************************************** +// Access Frequency categories +// ************************************************** +// Hot: Data is frequently accessed +// Warm: Less frequently accessed than Hot +// Cold: Should be rarely accessed. +// +// The combination of these 2 sub-categories gives us the following valid categories +// 1-IBCProfiled | Hot: Hot based on IBC profiling data. +// 2-IBCProfiled | Cold: IBC profiling could have helped make this section hot. +// 3-NonIBCProfiled | Hot: Statically determined hot. +// 4-NonIBCProfiled | Warm: Staticaly determined warm. +// 5-NonIBCProfiled | Cold: Statically determined cold. +// +// We should try to place data items into the correct section based on +// the above categorization, this could mean that we might split +// a virtual section into 2 sections if it contains multiple heterogeneous items. + +enum ZapVirtualSectionType +{ + // + IBCTypeReservedFlag = 0xFF000000, +#define CORCOMPILE_SECTION_IBCTYPE(ibcType, flag) ibcType##Section = flag, + CORCOMPILE_SECTION_IBCTYPES() +#undef CORCOMPILE_SECTION_IBCTYPE + + // + RangeTypeReservedFlag = 0x00FF0000, +#define CORCOMPILE_SECTION_RANGE_TYPE(rangeType, flag) rangeType##Range = flag, + CORCOMPILE_SECTION_RANGE_TYPES() +#undef CORCOMPILE_SECTION_RANGE_TYPE + + // + VirtualSectionTypeReservedFlag = 0x0000FFFF, + VirtualSectionTypeStartSection = 0x0, // reserved so the first section start at 0x1 +#define CORCOMPILE_SECTION_TYPE(virtualSectionType) virtualSectionType##Section, + CORCOMPILE_SECTION_TYPES() +#undef CORCOMPILE_SECTION_TYPE + + CORCOMPILE_SECTION_TYPE_COUNT +}; + +class VirtualSectionData +{ + +public : + static UINT8 IBCType(DWORD sectionType) { return (UINT8) ((sectionType & IBCTypeReservedFlag) >> 24); } + static UINT8 RangeType(DWORD sectionType) { return (UINT8) ((sectionType & RangeTypeReservedFlag) >> 16); } + static UINT16 VirtualSectionType(DWORD sectionType) { return (UINT16) ((sectionType & VirtualSectionTypeReservedFlag)); } + static BOOL IsIBCProfiledColdSection(DWORD sectionType) + { + return ((sectionType & ColdRange) == ColdRange) && ((sectionType & IBCProfiledSection) == IBCProfiledSection); + } +}; + +struct CORCOMPILE_EE_INFO_TABLE +{ + TADDR inlinedCallFrameVptr; + PTR_LONG addrOfCaptureThreadGlobal; + PTR_DWORD addrOfJMCFlag; + SIZE_T gsCookie; + CORINFO_Object ** emptyString; + + DWORD threadTlsIndex; + + DWORD rvaStaticTlsIndex; +}; + +/*********************************************************************************/ + +// This is the offset to the compressed blob of debug information + +typedef ULONG CORCOMPILE_DEBUG_ENTRY; + +// A single generic method may be get compiled into multiple copies of code for +// different instantiations, and can have multiple entries for the same RID. + +struct CORCOMPILE_DEBUG_LABELLED_ENTRY +{ + DWORD nativeCodeRVA; // the ngen code RVA distinguishes this entry from others with the same RID. + CORCOMPILE_DEBUG_ENTRY debugInfoOffset; // offset to the debug information for this native code +}; + +// Debug information is accessed using a table of RVAs indexed by the RID token for +// the method. + +typedef CORCOMPILE_DEBUG_ENTRY CORCOMPILE_DEBUG_RID_ENTRY; + +// If this bit is not set, the CORCOMPILE_DEBUG_RID_ENTRY RVA points to a compressed +// debug information blob. +// If this bit is set, the RVA points to CORCOMPILE_DEBUG_LABELLED_ENTRY. +// If this bit is set in CORCOMPILE_DEBUG_LABELLED_ENTRY, there is another entry following it. + +const CORCOMPILE_DEBUG_RID_ENTRY CORCOMPILE_DEBUG_MULTIPLE_ENTRIES = 0x80000000; + +inline bool IsMultipleLabelledEntries(CORCOMPILE_DEBUG_RID_ENTRY rva) +{ + SUPPORTS_DAC; + + return (rva & CORCOMPILE_DEBUG_MULTIPLE_ENTRIES) != 0; +} + +inline unsigned GetDebugRidEntryHash(mdToken token) +{ + SUPPORTS_DAC; + + unsigned hashCode = token; + + // mix it + hashCode -= hashCode >> 17; + hashCode -= hashCode >> 11; + hashCode -= hashCode >> 5; + + return hashCode; +} + +typedef DPTR(CORCOMPILE_DEBUG_ENTRY) PTR_CORCOMPILE_DEBUG_ENTRY; +typedef DPTR(struct CORCOMPILE_DEBUG_LABELLED_ENTRY) PTR_CORCOMPILE_DEBUG_LABELLED_ENTRY; +typedef DPTR(CORCOMPILE_DEBUG_RID_ENTRY) PTR_CORCOMPILE_DEBUG_RID_ENTRY; + +/*********************************************************************************/ + +struct CORCOMPILE_CODE_MANAGER_ENTRY +{ + IMAGE_DATA_DIRECTORY HotCode; + IMAGE_DATA_DIRECTORY Code; + IMAGE_DATA_DIRECTORY ColdCode; + + IMAGE_DATA_DIRECTORY ROData; + + //Layout is + //HOT COMMON + //HOT IBC + //HOT GENERICS + //Hot due to procedure splitting + ULONG HotIBCMethodOffset; + ULONG HotGenericsMethodOffset; + + //Layout is + //COLD IBC + //Cold due to procedure splitting. + ULONG ColdUntrainedMethodOffset; +}; + +#if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + +#define _PRECODE_EXTERNAL_METHOD_THUNK 0x41 +#define _PRECODE_VIRTUAL_IMPORT_THUNK 0x42 + + struct CORCOMPILE_VIRTUAL_IMPORT_THUNK + { + BYTE callJmp[5]; // Call/Jmp Pc-Rel32 + BYTE precodeType; // 0x42 _PRECODE_VIRTUAL_IMPORT_THUNK + WORD slotNum; + }; + + struct CORCOMPILE_EXTERNAL_METHOD_THUNK + { + BYTE callJmp[5]; // Call/Jmp Pc-Rel32 + BYTE precodeType; // 0x41 _PRECODE_EXTERNAL_METHOD_THUNK + WORD padding; + }; + +#elif defined(_TARGET_ARM_) + + struct CORCOMPILE_VIRTUAL_IMPORT_THUNK + { + // Array of words to do the following: + // + // mov r12, pc ; Save the current address relative to which we will get slot ID and address to patch. + // ldr pc, [pc, #4] ; Load the target address. Initially it will point to the helper stub that will patch it + // ; to point to the actual target on the first run. + WORD m_rgCode[3]; + + // WORD to store the slot ID + WORD slotNum; + + // The target address - initially, this will point to VirtualMethodFixupStub. + // Post patchup by the stub, it will point to the actual method body. + PCODE m_pTarget; + }; + + struct CORCOMPILE_EXTERNAL_METHOD_THUNK + { + // Array of words to do the following: + // + // mov r12, pc ; Save the current address relative to which we will get GCRef bitmap and address to patch. + // ldr pc, [pc, #4] ; Load the target address. Initially it will point to the helper stub that will patch it + // ; to point to the actual target on the first run. + WORD m_rgCode[3]; + + WORD m_padding; + + // The target address - initially, this will point to ExternalMethodFixupStub. + // Post patchup by the stub, it will point to the actual method body. + PCODE m_pTarget; + }; + +#elif defined(_TARGET_ARM64_) + struct CORCOMPILE_VIRTUAL_IMPORT_THUNK + { + // Array of words to do the following: + // + // adr x12, #0 ; Save the current address relative to which we will get slot ID and address to patch. + // ldr x10, [x12, #16] ; Load the target address. + // br x10 ; Jump to the target + DWORD m_rgCode[3]; + + // WORD to store the slot ID + WORD slotNum; + + // The target address - initially, this will point to VirtualMethodFixupStub. + // Post patchup by the stub, it will point to the actual method body. + PCODE m_pTarget; + }; + + struct CORCOMPILE_EXTERNAL_METHOD_THUNK + { + // Array of words to do the following: + // adr x12, #0 ; Save the current address relative to which we will get slot ID and address to patch. + // ldr x10, [x12, #16] ; Load the target address. + // br x10 ; Jump to the target + DWORD m_rgCode[3]; + + DWORD m_padding; //aligning stack to 16 bytes + + // The target address - initially, this will point to ExternalMethodFixupStub. + // Post patchup by the stub, it will point to the actual method body. + PCODE m_pTarget; + }; + +#endif + +// +// GCRefMap blob starts with DWORDs lookup index of relative offsets into the blob. This lookup index is used to limit amount +// of linear scanning required to find entry in the GCRefMap. The size of this lookup index is +// / GCREFMAP_LOOKUP_STRIDE. +// +#define GCREFMAP_LOOKUP_STRIDE 1024 + +enum CORCOMPILE_GCREFMAP_TOKENS +{ + GCREFMAP_SKIP = 0, + GCREFMAP_REF = 1, + GCREFMAP_INTERIOR = 2, + GCREFMAP_METHOD_PARAM = 3, + GCREFMAP_TYPE_PARAM = 4, + GCREFMAP_VASIG_COOKIE = 5, +}; + +// Tags for fixup blobs +enum CORCOMPILE_FIXUP_BLOB_KIND +{ + ENCODE_NONE = 0, + + ENCODE_MODULE_OVERRIDE = 0x80, /* When the high bit is set, override of the module immediately follows */ + + ENCODE_DICTIONARY_LOOKUP_THISOBJ = 0x07, + ENCODE_DICTIONARY_LOOKUP_TYPE = 0x08, + ENCODE_DICTIONARY_LOOKUP_METHOD = 0x09, + + ENCODE_TYPE_HANDLE = 0x10, /* Type handle */ + ENCODE_METHOD_HANDLE, /* Method handle */ + ENCODE_FIELD_HANDLE, /* Field handle */ + + ENCODE_METHOD_ENTRY, /* For calling a method entry point */ + ENCODE_METHOD_ENTRY_DEF_TOKEN, /* Smaller version of ENCODE_METHOD_ENTRY - method is def token */ + ENCODE_METHOD_ENTRY_REF_TOKEN, /* Smaller version of ENCODE_METHOD_ENTRY - method is ref token */ + + ENCODE_VIRTUAL_ENTRY, /* For invoking a virtual method */ + ENCODE_VIRTUAL_ENTRY_DEF_TOKEN, /* Smaller version of ENCODE_VIRTUAL_ENTRY - method is def token */ + ENCODE_VIRTUAL_ENTRY_REF_TOKEN, /* Smaller version of ENCODE_VIRTUAL_ENTRY - method is ref token */ + ENCODE_VIRTUAL_ENTRY_SLOT, /* Smaller version of ENCODE_VIRTUAL_ENTRY - type & slot */ + + ENCODE_READYTORUN_HELPER, /* ReadyToRun helper */ + ENCODE_STRING_HANDLE, /* String token */ + + ENCODE_NEW_HELPER, /* Dynamically created new helpers */ + ENCODE_NEW_ARRAY_HELPER, + + ENCODE_ISINSTANCEOF_HELPER, /* Dynamically created casting helper */ + ENCODE_CHKCAST_HELPER, + + ENCODE_FIELD_ADDRESS, /* For accessing a cross-module static fields */ + ENCODE_CCTOR_TRIGGER, /* Static constructor trigger */ + + ENCODE_STATIC_BASE_NONGC_HELPER, /* Dynamically created static base helpers */ + ENCODE_STATIC_BASE_GC_HELPER, + ENCODE_THREAD_STATIC_BASE_NONGC_HELPER, + ENCODE_THREAD_STATIC_BASE_GC_HELPER, + + ENCODE_FIELD_BASE_OFFSET, /* Field base */ + ENCODE_FIELD_OFFSET, + + ENCODE_TYPE_DICTIONARY, + ENCODE_METHOD_DICTIONARY, + + ENCODE_CHECK_TYPE_LAYOUT, + ENCODE_CHECK_FIELD_OFFSET, + + ENCODE_DELEGATE_CTOR, + + ENCODE_DECLARINGTYPE_HANDLE, + + ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr */ + + ENCODE_MODULE_HANDLE = 0x50, /* Module token */ + ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */ + ENCODE_MODULE_ID_FOR_STATICS, /* For accessing static fields */ + ENCODE_MODULE_ID_FOR_GENERIC_STATICS, /* For accessing static fields */ + ENCODE_CLASS_ID_FOR_STATICS, /* For accessing static fields */ + ENCODE_SYNC_LOCK, /* For synchronizing access to a type */ + ENCODE_PROFILING_HANDLE, /* For the method's profiling counter */ + ENCODE_VARARGS_METHODDEF, /* For calling a varargs method */ + ENCODE_VARARGS_METHODREF, + ENCODE_VARARGS_SIG, + ENCODE_ACTIVE_DEPENDENCY, /* Conditional active dependency */ + ENCODE_METHOD_NATIVE_ENTRY, /* NativeCallable method token */ +}; + +enum EncodeMethodSigFlags +{ + ENCODE_METHOD_SIG_UnboxingStub = 0x01, + ENCODE_METHOD_SIG_InstantiatingStub = 0x02, + ENCODE_METHOD_SIG_MethodInstantiation = 0x04, + ENCODE_METHOD_SIG_SlotInsteadOfToken = 0x08, + ENCODE_METHOD_SIG_MemberRefToken = 0x10, + ENCODE_METHOD_SIG_Constrained = 0x20, + ENCODE_METHOD_SIG_OwnerType = 0x40, +}; + +enum EncodeFieldSigFlags +{ + ENCODE_FIELD_SIG_IndexInsteadOfToken = 0x08, + ENCODE_FIELD_SIG_MemberRefToken = 0x10, + ENCODE_FIELD_SIG_OwnerType = 0x40, +}; + +class SBuffer; +class SigBuilder; +class PEDecoder; +class GCRefMapBuilder; + +//REVIEW: include for ee exception info +#include "eexcp.h" + +struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY +{ + DWORD MethodStartRVA; + DWORD ExceptionInfoRVA; +}; + +struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE +{ + // pointer to the first element of m_numLookupEntries elements + CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY m_Entries[1]; + + CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY* ExceptionLookupEntry(unsigned i) + { + SUPPORTS_DAC_WRAPPER; + return &(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY(PTR_HOST_MEMBER_TADDR(CORCOMPILE_EXCEPTION_LOOKUP_TABLE,this,m_Entries))[i]); + } +}; + +struct CORCOMPILE_EXCEPTION_CLAUSE +{ + CorExceptionFlag Flags; + DWORD TryStartPC; + DWORD TryEndPC; + DWORD HandlerStartPC; + DWORD HandlerEndPC; + union { + mdToken ClassToken; + DWORD FilterOffset; + }; +}; + +//lower order bit (HAS_EXCEPTION_INFO_MASK) used to determine if the method has any exception handling +#define HAS_EXCEPTION_INFO_MASK 1 + +struct CORCOMPILE_COLD_METHOD_ENTRY +{ +#ifdef WIN64EXCEPTIONS + DWORD mainFunctionEntryRVA; +#endif + // TODO: hotCodeSize should be encoded in GC info + ULONG hotCodeSize; +}; + +// MVID used by the metadata of all ngen images +// {70E9452F-5F0A-4f0e-8E02-203992F4221C} +EXTERN_GUID(NGEN_IMAGE_MVID, 0x70e9452f, 0x5f0a, 0x4f0e, 0x8e, 0x2, 0x20, 0x39, 0x92, 0xf4, 0x22, 0x1c); + +typedef GUID CORCOMPILE_NGEN_SIGNATURE; + +// To indicate that the dependency is not hardbound +// {DB15CD8C-1378-4963-9DF3-14D97E95D1A1} +EXTERN_GUID(INVALID_NGEN_SIGNATURE, 0xdb15cd8c, 0x1378, 0x4963, 0x9d, 0xf3, 0x14, 0xd9, 0x7e, 0x95, 0xd1, 0xa1); + +struct CORCOMPILE_ASSEMBLY_SIGNATURE +{ + // Metadata MVID. + GUID mvid; + + // timestamp and IL image size for the source IL assembly. + // This is used for mini-dump to find matching metadata. + DWORD timeStamp; + DWORD ilImageSize; +}; + +typedef enum +{ + CORECLR_INFO, + CROSSGEN_COMPILER_INFO, + NUM_RUNTIME_DLLS +} CorCompileRuntimeDlls; + +extern LPCWSTR CorCompileGetRuntimeDllName(CorCompileRuntimeDlls id); + +// Will always return a valid HMODULE for CLR_INFO, but will return NULL for NGEN_COMPILER_INFO +// if the DLL has not yet been loaded (it does not try to cause a load). +extern HMODULE CorCompileGetRuntimeDll(CorCompileRuntimeDlls id); + +struct CORCOMPILE_RUNTIME_DLL_INFO +{ + // This structure can only contain information not updated by authenticode signing. It is required + // for crossgen to work in buildlab. It particular, it cannot contain PE checksum because of it is + // update by authenticode signing. + DWORD timeStamp; + DWORD virtualSize; +}; + + + +struct CORCOMPILE_VERSION_INFO +{ + // OS + WORD wOSPlatformID; + WORD wOSMajorVersion; + + // For backward compatibility reasons, the following four fields must start at offset 4, + // be consequtive, and be 2 bytes each. See code:PEDecoder::GetMetaDataHelper. + // EE Version + WORD wVersionMajor; + WORD wVersionMinor; + WORD wVersionBuildNumber; + WORD wVersionPrivateBuildNumber; + + // Codegen flags + WORD wCodegenFlags; + WORD wConfigFlags; + WORD wBuild; + + // Processor + WORD wMachine; + CORINFO_CPU cpuInfo; + + // Signature of source assembly + CORCOMPILE_ASSEMBLY_SIGNATURE sourceAssembly; + + // Signature which identifies this ngen image + CORCOMPILE_NGEN_SIGNATURE signature; + + // Timestamp info for runtime dlls + CORCOMPILE_RUNTIME_DLL_INFO runtimeDllInfo[NUM_RUNTIME_DLLS]; +}; + + + + +struct CORCOMPILE_DEPENDENCY +{ + // Pre-bind Ref + mdAssemblyRef dwAssemblyRef; + + // Post-bind Def + mdAssemblyRef dwAssemblyDef; + CORCOMPILE_ASSEMBLY_SIGNATURE signAssemblyDef; + + CORCOMPILE_NGEN_SIGNATURE signNativeImage; // INVALID_NGEN_SIGNATURE if this a soft-bound dependency + + +}; + +/*********************************************************************************/ +// Flags used to encode HelperTable +#if defined(_TARGET_ARM64_) +#define HELPER_TABLE_ENTRY_LEN 16 +#else +#define HELPER_TABLE_ENTRY_LEN 8 +#endif //defined(_TARGET_ARM64_) + +#define HELPER_TABLE_ALIGN 8 +#define CORCOMPILE_HELPER_PTR 0x80000000 // The entry is pointer to the helper (jump thunk otherwise) + +// The layout of this struct is required to be +// a 'next' pointer followed by a CORBBTPROF_METHOD_HEADER +// +struct CORCOMPILE_METHOD_PROFILE_LIST +{ + CORCOMPILE_METHOD_PROFILE_LIST * next; +// CORBBTPROF_METHOD_HEADER info; + + CORBBTPROF_METHOD_HEADER * GetInfo() + { return (CORBBTPROF_METHOD_HEADER *) (this+1); } +}; + +// see code:CorProfileData.GetHotTokens for how we determine what is in hot meta-data. +class CorProfileData +{ +public: + CorProfileData(void * rawProfileData); // really of type ZapImage::ProfileDataSection* + + struct CORBBTPROF_TOKEN_INFO * GetTokenFlagsData(SectionFormat section) + { + if (this == NULL) + return NULL; + return this->profilingTokenFlagsData[section].data; + } + + DWORD GetTokenFlagsCount(SectionFormat section) + { + if (this == NULL) + return 0; + return this->profilingTokenFlagsData[section].count; + } + + CORBBTPROF_BLOB_ENTRY * GetBlobStream() + { + if (this == NULL) + return NULL; + return this->blobStream; + } + + + // see code:MetaData::HotMetaDataHeader for details on reading hot meta-data + // + // for detail on where we use the API to store the hot meta data + // * code:CMiniMdRW.SaveFullTablesToStream#WritingHotMetaData + // * code:CMiniMdRW.SaveHotPoolsToStream + // * code:CMiniMdRW.SaveHotPoolToStream#CallToGetHotTokens + // + ULONG GetHotTokens(int table, DWORD mask, DWORD hotValue, mdToken *tokenBuffer, ULONG maxCount) + { + ULONG count = 0; + SectionFormat format = (SectionFormat)(FirstTokenFlagSection + table); + + CORBBTPROF_TOKEN_INFO *profilingData = profilingTokenFlagsData[format].data; + DWORD cProfilingData = profilingTokenFlagsData[format].count; + + if (profilingData != NULL) + { + for (DWORD i = 0; i < cProfilingData; i++) + { + if ((profilingData[i].flags & mask) == hotValue) + { + if (tokenBuffer != NULL && count < maxCount) + tokenBuffer[count] = profilingData[i].token; + count++; + } + } + } + return count; + } + + // + // Token lookup methods + // + ULONG GetTypeProfilingFlagsOfToken(mdToken token) + { + _ASSERTE(TypeFromToken(token) == mdtTypeDef); + return GetProfilingFlagsOfToken(token); + } + + CORBBTPROF_BLOB_PARAM_SIG_ENTRY *GetBlobSigEntry(mdToken token) + { + _ASSERTE((TypeFromToken(token) == ibcTypeSpec) || (TypeFromToken(token) == ibcMethodSpec)); + + CORBBTPROF_BLOB_ENTRY * pBlobEntry = GetBlobEntry(token); + if (pBlobEntry == NULL) + return NULL; + + _ASSERTE(pBlobEntry->token == token); + _ASSERTE((pBlobEntry->type == ParamTypeSpec) || (pBlobEntry->type == ParamMethodSpec)); + + return (CORBBTPROF_BLOB_PARAM_SIG_ENTRY *) pBlobEntry; + } + + CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *GetBlobExternalNamespaceDef(mdToken token) + { + _ASSERTE(TypeFromToken(token) == ibcExternalNamespace); + + CORBBTPROF_BLOB_ENTRY * pBlobEntry = GetBlobEntry(token); + if (pBlobEntry == NULL) + return NULL; + + _ASSERTE(pBlobEntry->token == token); + _ASSERTE(pBlobEntry->type == ExternalNamespaceDef); + + return (CORBBTPROF_BLOB_NAMESPACE_DEF_ENTRY *) pBlobEntry; + } + + CORBBTPROF_BLOB_TYPE_DEF_ENTRY *GetBlobExternalTypeDef(mdToken token) + { + _ASSERTE(TypeFromToken(token) == ibcExternalType); + + CORBBTPROF_BLOB_ENTRY * pBlobEntry = GetBlobEntry(token); + if (pBlobEntry == NULL) + return NULL; + + _ASSERTE(pBlobEntry->token == token); + _ASSERTE(pBlobEntry->type == ExternalTypeDef); + + return (CORBBTPROF_BLOB_TYPE_DEF_ENTRY *) pBlobEntry; + } + + CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *GetBlobExternalSignatureDef(mdToken token) + { + _ASSERTE(TypeFromToken(token) == ibcExternalSignature); + + CORBBTPROF_BLOB_ENTRY * pBlobEntry = GetBlobEntry(token); + if (pBlobEntry == NULL) + return NULL; + + _ASSERTE(pBlobEntry->token == token); + _ASSERTE(pBlobEntry->type == ExternalSignatureDef); + + return (CORBBTPROF_BLOB_SIGNATURE_DEF_ENTRY *) pBlobEntry; + } + + CORBBTPROF_BLOB_METHOD_DEF_ENTRY *GetBlobExternalMethodDef(mdToken token) + { + _ASSERTE(TypeFromToken(token) == ibcExternalMethod); + + CORBBTPROF_BLOB_ENTRY * pBlobEntry = GetBlobEntry(token); + if (pBlobEntry == NULL) + return NULL; + + _ASSERTE(pBlobEntry->token == token); + _ASSERTE(pBlobEntry->type == ExternalMethodDef); + + return (CORBBTPROF_BLOB_METHOD_DEF_ENTRY *) pBlobEntry; + } + +private: + ULONG GetProfilingFlagsOfToken(mdToken token) + { + SectionFormat section = (SectionFormat)((TypeFromToken(token) >> 24) + FirstTokenFlagSection); + + CORBBTPROF_TOKEN_INFO *profilingData = this->profilingTokenFlagsData[section].data; + DWORD cProfilingData = this->profilingTokenFlagsData[section].count; + + if (profilingData != NULL) + { + for (DWORD i = 0; i < cProfilingData; i++) + { + if (profilingData[i].token == token) + return profilingData[i].flags; + } + } + return 0; + } + + CORBBTPROF_BLOB_ENTRY *GetBlobEntry(idTypeSpec token) + { + CORBBTPROF_BLOB_ENTRY * pBlobEntry = this->GetBlobStream(); + if (pBlobEntry == NULL) + return NULL; + + while (pBlobEntry->TypeIsValid()) + { + if (pBlobEntry->token == token) + { + return pBlobEntry; + } + pBlobEntry = pBlobEntry->GetNextEntry(); + } + + return NULL; + } + +private: + struct + { + struct CORBBTPROF_TOKEN_INFO *data; + DWORD count; + } + profilingTokenFlagsData[SectionFormatCount]; + + CORBBTPROF_BLOB_ENTRY* blobStream; +}; + +/*********************************************************************************/ +// IL region is used to group frequently used IL method bodies together + +enum CorCompileILRegion +{ + CORCOMPILE_ILREGION_INLINEABLE, // Public inlineable methods + CORCOMPILE_ILREGION_WARM, // Other inlineable methods and methods that failed to NGen + CORCOMPILE_ILREGION_GENERICS, // Generic methods (may be needed to compile non-NGened instantiations) + CORCOMPILE_ILREGION_COLD, // Everything else (should be touched in rare scenarios like reflection or profiling only) + CORCOMPILE_ILREGION_COUNT, +}; + +/********************************************************************************* + * ICorCompilePreloader is used to query preloaded EE data structures + *********************************************************************************/ + +class ICorCompilePreloader +{ + public: + typedef void (__stdcall *CORCOMPILE_CompileStubCallback)(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags); + + // + // Map methods are available after Serialize() is called + // (which will cause it to allocate its data.) Note that returned + // results are RVAs into the image. + // + // If compiling after serializing the preloaded image, these methods can + // be used to avoid making entries in the various info tables. + // Else, use ICorCompileInfo::CanEmbedXXX() + // + + virtual DWORD MapMethodEntryPoint( + CORINFO_METHOD_HANDLE handle + ) = 0; + + virtual DWORD MapClassHandle( + CORINFO_CLASS_HANDLE handle + ) = 0; + + virtual DWORD MapMethodHandle( + CORINFO_METHOD_HANDLE handle + ) = 0; + + virtual DWORD MapFieldHandle( + CORINFO_FIELD_HANDLE handle + ) = 0; + + virtual DWORD MapAddressOfPInvokeFixup( + CORINFO_METHOD_HANDLE handle + ) = 0; + + virtual DWORD MapGenericHandle( + CORINFO_GENERIC_HANDLE handle + ) = 0; + + virtual DWORD MapModuleIDHandle( + CORINFO_MODULE_HANDLE handle + ) = 0; + + // Load a method for the specified method def + // If the class or method is generic, instantiate all parameters with + virtual CORINFO_METHOD_HANDLE LookupMethodDef(mdMethodDef token) = 0; + + // For the given ftnHnd fill in the methInfo structure and return true if successful. + virtual bool GetMethodInfo(mdMethodDef token, CORINFO_METHOD_HANDLE ftnHnd, CORINFO_METHOD_INFO * methInfo) = 0; + + // Returns region that the IL should be emitted in + virtual CorCompileILRegion GetILRegion(mdMethodDef token) = 0; + + // Find the (parameterized) method for the given blob from the profile data + virtual CORINFO_METHOD_HANDLE FindMethodForProfileEntry(CORBBTPROF_BLOB_PARAM_SIG_ENTRY * profileBlobEntry) = 0; + + virtual void ReportInlining(CORINFO_METHOD_HANDLE inliner, CORINFO_METHOD_HANDLE inlinee) = 0; + + // + // Call Link when you want all the fixups + // to be applied. You may call this e.g. after + // compiling all the code for the module. + // Return some stats about the types in the ngen image + // + virtual void Link() = 0; + + virtual void FixupRVAs() = 0; + + virtual void SetRVAsForFields(IMetaDataEmit * pEmit) = 0; + + virtual void GetRVAFieldData(mdFieldDef fd, PVOID * ppData, DWORD * pcbSize, DWORD * pcbAlignment) = 0; + + // The preloader also maintains a set of uncompiled generic + // methods or methods in generic classes. A single method can be + // registered or all the methods in a class can be registered. + // The method is added to the set only if it should be compiled + // into this ngen image + // + // The zapper registers methods and classes that are resolved by + // findClass and findMethod during compilation + virtual void AddMethodToTransitiveClosureOfInstantiations(CORINFO_METHOD_HANDLE handle) = 0; + virtual void AddTypeToTransitiveClosureOfInstantiations(CORINFO_CLASS_HANDLE handle) = 0; + + // Report reference to the given method from compiled code + virtual void MethodReferencedByCompiledCode(CORINFO_METHOD_HANDLE handle) = 0; + + virtual BOOL IsUncompiledMethod(CORINFO_METHOD_HANDLE handle) = 0; + + // Return a method handle that was previously registered and + // hasn't been compiled already, and remove it from the set + // of uncompiled methods. + // Return NULL if the set is empty + virtual CORINFO_METHOD_HANDLE NextUncompiledMethod() = 0; + + // Prepare a method and its statically determinable call graph if + // a hint attribute has been applied. This is called to save + // additional preparation information into the ngen image that + // wouldn't normally be there (since we can't automatically + // determine it's needed). + virtual void PrePrepareMethodIfNecessary(CORINFO_METHOD_HANDLE hMethod) = 0; + + // If a method requires stubs, this will call back passing method + // handles for those stubs. + virtual void GenerateMethodStubs( + CORINFO_METHOD_HANDLE hMethod, + bool fNgenProfileImage, + CORCOMPILE_CompileStubCallback pfnCallback, + LPVOID pCallbackContext) = 0; + + // Determines whether or not a method is a dynamic method. This is used + // to prevent operations that may require metadata knowledge at times other + // than compile time. + virtual bool IsDynamicMethod(CORINFO_METHOD_HANDLE hMethod) = 0; + + // Set method profiling flags for layout of EE datastructures + virtual void SetMethodProfilingFlags(CORINFO_METHOD_HANDLE hMethod, DWORD flags) = 0; + + // Returns false if precompiled code must ensure that + // the EE's DoPrestub function gets run before the + // code for the method is used, i.e. if it returns false + // then an indirect call must be made. + // + // Returning true does not guaratee that a direct call can be made: + // there can be other reasons why the entry point cannot be embedded. + // + virtual bool CanSkipMethodPreparation ( + CORINFO_METHOD_HANDLE callerHnd, /* IN */ + CORINFO_METHOD_HANDLE calleeHnd, /* IN */ + CorInfoIndirectCallReason *pReason = NULL, + CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY) = 0; + + virtual BOOL CanEmbedModuleHandle( + CORINFO_MODULE_HANDLE moduleHandle) = 0; + + // These check if we can hardbind to a handle. They guarantee either that + // the structure referred to by the handle is in a referenced zapped image + // or will be saved into the module currently being zapped. That is the + // corresponding GetLoaderModuleForEmeddableXYZ call will return + // either the module currently being zapped or a referenced zapped module. + virtual BOOL CanEmbedClassID(CORINFO_CLASS_HANDLE typeHandle) = 0; + virtual BOOL CanEmbedModuleID(CORINFO_MODULE_HANDLE moduleHandle) = 0; + virtual BOOL CanEmbedClassHandle(CORINFO_CLASS_HANDLE typeHandle) = 0; + virtual BOOL CanEmbedMethodHandle(CORINFO_METHOD_HANDLE methodHandle, CORINFO_METHOD_HANDLE contextHandle = NULL) = 0; + virtual BOOL CanEmbedFieldHandle(CORINFO_FIELD_HANDLE fieldHandle) = 0; + + // Return true if we can both embed a direct hardbind to the handle _and_ + // no "restore" action is needed on the handle. Equivalent to "CanEmbed + Prerestored". + // + // Typically a handle needs runtime restore it has embedded cross-module references + // or other data that cannot be persisted directly. + virtual BOOL CanPrerestoreEmbedClassHandle( + CORINFO_CLASS_HANDLE classHnd) = 0; + + // Return true if a method needs runtime restore + // This is only the case if it is instantiated and any of its type arguments need restoring. + virtual BOOL CanPrerestoreEmbedMethodHandle( + CORINFO_METHOD_HANDLE methodHnd) = 0; + + // Can a method entry point be embedded? + virtual BOOL CanEmbedFunctionEntryPoint( + CORINFO_METHOD_HANDLE methodHandle, + CORINFO_METHOD_HANDLE contextHandle = NULL, + CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY + ) = 0; + + // Prestub is not able to handle method restore in all cases for generics. + // If it is the case the method has to be restored explicitly upfront. + // See the comment inside the implemenation method for more details. + virtual BOOL DoesMethodNeedRestoringBeforePrestubIsRun( + CORINFO_METHOD_HANDLE methodHandle + ) = 0; + + // Returns true if the given activation fixup is not necessary + virtual BOOL CanSkipDependencyActivation( + CORINFO_METHOD_HANDLE context, + CORINFO_MODULE_HANDLE moduleFrom, + CORINFO_MODULE_HANDLE moduleTo) = 0; + + virtual CORINFO_MODULE_HANDLE GetPreferredZapModuleForClassHandle( + CORINFO_CLASS_HANDLE classHnd + ) = 0; + + virtual void NoteDeduplicatedCode( + CORINFO_METHOD_HANDLE method, + CORINFO_METHOD_HANDLE duplicateMethod) = 0; + +#ifdef FEATURE_READYTORUN_COMPILER + // Returns a compressed encoding of the inline tracking map + // for this compilation + virtual void GetSerializedInlineTrackingMap( + IN OUT SBuffer * pSerializedInlineTrackingMap + ) = 0; +#endif + + // + // Release frees the preloader + // + + virtual ULONG Release() = 0; +}; + +// +// The DataImage provides several "sections", which can be used +// to sort data into different sets for locality control. The Arrange +// phase is responsible for placing items into sections. +// + +#define CORCOMPILE_SECTIONS() \ + CORCOMPILE_SECTION(MODULE) \ + CORCOMPILE_SECTION(WRITE) \ + CORCOMPILE_SECTION(METHOD_PRECODE_WRITE) \ + CORCOMPILE_SECTION(HOT_WRITEABLE) \ + CORCOMPILE_SECTION(WRITEABLE) \ + CORCOMPILE_SECTION(HOT) \ + CORCOMPILE_SECTION(METHOD_PRECODE_HOT) \ + CORCOMPILE_SECTION(RVA_STATICS_HOT) \ + CORCOMPILE_SECTION(RVA_STATICS_COLD) \ + CORCOMPILE_SECTION(WARM) \ + CORCOMPILE_SECTION(READONLY_SHARED_HOT) \ + CORCOMPILE_SECTION(READONLY_HOT) \ + CORCOMPILE_SECTION(READONLY_WARM) \ + CORCOMPILE_SECTION(READONLY_COLD) \ + CORCOMPILE_SECTION(READONLY_VCHUNKS) \ + CORCOMPILE_SECTION(READONLY_DICTIONARY) \ + CORCOMPILE_SECTION(CLASS_COLD) \ + CORCOMPILE_SECTION(CROSS_DOMAIN_INFO) \ + CORCOMPILE_SECTION(METHOD_PRECODE_COLD) \ + CORCOMPILE_SECTION(METHOD_PRECODE_COLD_WRITEABLE) \ + CORCOMPILE_SECTION(METHOD_DESC_COLD) \ + CORCOMPILE_SECTION(METHOD_DESC_COLD_WRITEABLE) \ + CORCOMPILE_SECTION(MODULE_COLD) \ + CORCOMPILE_SECTION(DEBUG_COLD) \ + CORCOMPILE_SECTION(COMPRESSED_MAPS) \ + +enum CorCompileSection +{ +#define CORCOMPILE_SECTION(section) CORCOMPILE_SECTION_##section, + CORCOMPILE_SECTIONS() +#undef CORCOMPILE_SECTION + + CORCOMPILE_SECTION_COUNT +}; + +enum VerboseLevel +{ + CORCOMPILE_NO_LOG, + CORCOMPILE_STATS, + CORCOMPILE_VERBOSE +}; + +class ZapImage; + +// When NGEN install /Profile is run, the ZapProfilingHandleImport fixup table contains +// these 5 values per MethodDesc +enum +{ + kZapProfilingHandleImportValueIndexFixup = 0, + kZapProfilingHandleImportValueIndexEnterAddr = 1, + kZapProfilingHandleImportValueIndexLeaveAddr = 2, + kZapProfilingHandleImportValueIndexTailcallAddr = 3, + kZapProfilingHandleImportValueIndexClientData = 4, + + kZapProfilingHandleImportValueIndexCount +}; + +class ICorCompileDataStore +{ + public: + // Returns ZapImage + virtual ZapImage * GetZapImage() = 0; + + // Report an error during preloading: + // 'token' is the metadata token that triggered the error + // hr is the HRESULT from the thrown Exception, or S_OK if we don't have an thrown exception + // resID is the resourceID with additional information from the thrown Exception, or 0 + // + virtual void Error(mdToken token, HRESULT hr, UINT _resID, LPCWSTR description) = 0; +}; + + +class ICorCompilationDomain +{ + public: + + // Sets the application context for fusion + // to use when binding, using a shell exe file path + virtual HRESULT SetContextInfo( + LPCWSTR path, + BOOL isExe + ) = 0; + + // Retrieves the dependencies of the code which + // has been compiled + virtual HRESULT GetDependencies( + CORCOMPILE_DEPENDENCY **ppDependencies, + DWORD *cDependencies + ) = 0; + + +#ifdef CROSSGEN_COMPILE + virtual HRESULT SetPlatformWinmdPaths( + LPCWSTR pwzPlatformWinmdPaths + ) = 0; +#endif +}; + +/********************************************************************************* + * ICorCompileInfo is the interface for a compiler + *********************************************************************************/ +// Define function pointer ENCODEMODULE_CALLBACK +typedef DWORD (*ENCODEMODULE_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle); + +// Define function pointer DEFINETOKEN_CALLBACK +typedef void (*DEFINETOKEN_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle, DWORD index, mdTypeRef* token); + +class ICorCompileInfo +{ + public: + + + // + // Currently no other instance of the EE may be running inside + // a process that is used as an NGEN compilation process. + // + // So, the host must call StartupAsCompilationProcess before compiling + // any code, and Shutdown after finishing. + // + // The arguments control which native image of mscorlib to use. + // This matters for hardbinding. + // + + virtual HRESULT Startup( + BOOL fForceDebug, + BOOL fForceProfiling, + BOOL fForceInstrument) = 0; + + // Creates a new compilation domain + // The BOOL arguments control what kind of a native image is + // to be generated. Other factors affect what kind of a native image + // will actually be generated. GetAssemblyVersionInfo() ultimately reflects + // the kind of native image that will be generated + // + // pEmitter - sets this as the emitter to use when generating tokens for + // the dependency list. If this is NULL, dependencies won't be computed. + + virtual HRESULT CreateDomain( + ICorCompilationDomain **ppDomain, // [OUT] + IMetaDataAssemblyEmit *pEmitter, + BOOL fForceDebug, + BOOL fForceProfiling, + BOOL fForceInstrument + ) = 0; + + // Destroys a compilation domain + virtual HRESULT DestroyDomain( + ICorCompilationDomain *pDomain + ) = 0; + + // Loads an assembly manifest module into the EE + // and returns a handle to it. + virtual HRESULT LoadAssemblyByPath( + LPCWSTR wzPath, + BOOL fExplicitBindToNativeImage, + CORINFO_ASSEMBLY_HANDLE *pHandle + ) = 0; + + +#ifdef FEATURE_COMINTEROP + // Loads a WinRT typeref into the EE and returns + // a handle to it. We have to load all typerefs + // during dependency computation since assemblyrefs + // are meaningless to WinRT. + virtual HRESULT LoadTypeRefWinRT( + IMDInternalImport *pAssemblyImport, + mdTypeRef ref, + CORINFO_ASSEMBLY_HANDLE *pHandle + ) = 0; +#endif + + virtual BOOL IsInCurrentVersionBubble(CORINFO_MODULE_HANDLE hModule) = 0; + + // Loads a module from an assembly into the EE + // and returns a handle to it. + virtual HRESULT LoadAssemblyModule( + CORINFO_ASSEMBLY_HANDLE assembly, + mdFile file, + CORINFO_MODULE_HANDLE *pHandle + ) = 0; + + + // Checks to see if an up to date zap exists for the + // assembly + virtual BOOL CheckAssemblyZap( + CORINFO_ASSEMBLY_HANDLE assembly, + __out_ecount_opt(*cAssemblyManifestModulePath) + LPWSTR assemblyManifestModulePath, + LPDWORD cAssemblyManifestModulePath + ) = 0; + + // Sets up the compilation target in the EE + virtual HRESULT SetCompilationTarget( + CORINFO_ASSEMBLY_HANDLE assembly, + CORINFO_MODULE_HANDLE module + ) = 0; + + + // Returns the dependency load setting for an assembly ref + virtual HRESULT GetLoadHint( + CORINFO_ASSEMBLY_HANDLE hAssembly, + CORINFO_ASSEMBLY_HANDLE hAssemblyDependency, + LoadHintEnum *loadHint, + LoadHintEnum *defaultLoadHint = NULL + ) = 0; + + // Returns information on how the assembly has been loaded + virtual HRESULT GetAssemblyVersionInfo( + CORINFO_ASSEMBLY_HANDLE hAssembly, + CORCOMPILE_VERSION_INFO *pInfo + ) = 0; + + // Returns the manifest metadata for an assembly + // Use the internal IMDInternalImport for performance. + // Creation of the public IMetaDataImport * triggers + // conversion to R/W metadata that slows down all subsequent accesses. + virtual IMDInternalImport * GetAssemblyMetaDataImport( + CORINFO_ASSEMBLY_HANDLE assembly + ) = 0; + + // Returns an interface to query the metadata for a loaded module + // Use the internal IMDInternalImport for performance. + // Creation of the public IMetaDataAssemblyImport * triggers + // conversion to R/W metadata that slows down all subsequent accesses. + virtual IMDInternalImport * GetModuleMetaDataImport( + CORINFO_MODULE_HANDLE module + ) = 0; + + // Returns the module of the assembly which contains the manifest, + // or NULL if the manifest is standalone. + virtual CORINFO_MODULE_HANDLE GetAssemblyModule( + CORINFO_ASSEMBLY_HANDLE assembly + ) = 0; + + // Returns the assembly of a loaded module + virtual CORINFO_ASSEMBLY_HANDLE GetModuleAssembly( + CORINFO_MODULE_HANDLE module + ) = 0; + + // Returns the current PEDecoder of a loaded module. + virtual PEDecoder * GetModuleDecoder( + CORINFO_MODULE_HANDLE module + ) = 0; + + // Gets the full file name, including path, of a loaded module + virtual void GetModuleFileName( + CORINFO_MODULE_HANDLE module, + SString &result + ) = 0; + + // Get a class def token + virtual HRESULT GetTypeDef( + CORINFO_CLASS_HANDLE classHandle, + mdTypeDef *token + ) = 0; + + // Get a method def token + virtual HRESULT GetMethodDef( + CORINFO_METHOD_HANDLE methodHandle, + mdMethodDef *token + ) = 0; + + // Get a field def token + virtual HRESULT GetFieldDef( + CORINFO_FIELD_HANDLE fieldHandle, + mdFieldDef *token + ) = 0; + + // Get the loader module for mscorlib + virtual CORINFO_MODULE_HANDLE GetLoaderModuleForMscorlib() = 0; + + // Get the loader module for a type (where the type is regarded as + // living for the purposes of loading, unloading, and ngen). + // + // classHandle must have passed CanEmbedClassHandle, since the zapper + // should only care about the module where a type + // prefers to be saved if it knows that that module is either + // an zapped module or is the module currently being compiled. + // See vm\ceeload.h for more information + virtual CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableType( + CORINFO_CLASS_HANDLE classHandle + ) = 0; + + // Get the loader module for a method (where the method is regarded as + // living for the purposes of loading, unloading, and ngen) + // + // methodHandle must have passed CanEmbedMethodHandle, since the zapper + // should only care about the module where a type + // prefers to be saved if it knows that that module is either + // an zapped module or is the module currently being compiled. + // See vm\ceeload.h for more information + virtual CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableMethod( + CORINFO_METHOD_HANDLE methodHandle + ) = 0; + + // Get the loader module for a method (where the method is regarded as + // living for the purposes of loading, unloading, and ngen) + // See vm\ceeload.h for more information + virtual CORINFO_MODULE_HANDLE GetLoaderModuleForEmbeddableField( + CORINFO_FIELD_HANDLE fieldHandle + ) = 0; + + // Set the list of assemblies we can hard bind to + virtual void SetAssemblyHardBindList( + __in_ecount(cHardBindList) + LPWSTR * pHardBindList, + DWORD cHardBindList + ) = 0; + + // Encode a module for the imports table + virtual void EncodeModuleAsIndex( + CORINFO_MODULE_HANDLE fromHandle, + CORINFO_MODULE_HANDLE handle, + DWORD *pIndex, + IMetaDataAssemblyEmit *pAssemblyEmit) = 0; + + + // Encode a class into the given SigBuilder. + virtual void EncodeClass( + CORINFO_MODULE_HANDLE referencingModule, + CORINFO_CLASS_HANDLE classHandle, + SigBuilder * pSigBuilder, + LPVOID encodeContext, + ENCODEMODULE_CALLBACK pfnEncodeModule) = 0; + + // Encode a method into the given SigBuilder. + virtual void EncodeMethod( + CORINFO_MODULE_HANDLE referencingModule, + CORINFO_METHOD_HANDLE handle, + SigBuilder * pSigBuilder, + LPVOID encodeContext, + ENCODEMODULE_CALLBACK pfnEncodeModule, + CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, + CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL, + BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE) = 0; + + // Returns non-null methoddef or memberref token if it is sufficient to encode the method (no generic instantiations, etc.) + virtual mdToken TryEncodeMethodAsToken( + CORINFO_METHOD_HANDLE handle, + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_MODULE_HANDLE * referencingModule) = 0; + + // Returns method slot (for encoding virtual stub dispatch) + virtual DWORD TryEncodeMethodSlot( + CORINFO_METHOD_HANDLE handle) = 0; + + // Encode a field into the given SigBuilder. + virtual void EncodeField( + CORINFO_MODULE_HANDLE referencingModule, + CORINFO_FIELD_HANDLE handle, + SigBuilder * pSigBuilder, + LPVOID encodeContext, + ENCODEMODULE_CALLBACK pfnEncodeModule, + CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, + BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE) = 0; + + + // Encode generic dictionary signature + virtual void EncodeGenericSignature( + LPVOID signature, + BOOL fMethod, + SigBuilder * pSigBuilder, + LPVOID encodeContext, + ENCODEMODULE_CALLBACK pfnEncodeModule) = 0; + + + virtual BOOL IsEmptyString( + mdString token, + CORINFO_MODULE_HANDLE module) = 0; + + + // Preload a modules' EE data structures + // directly into an executable image + + virtual ICorCompilePreloader * PreloadModule( + CORINFO_MODULE_HANDLE moduleHandle, + ICorCompileDataStore *pData, + CorProfileData *profileData + ) = 0; + + // Gets the codebase URL for the assembly + virtual void GetAssemblyCodeBase( + CORINFO_ASSEMBLY_HANDLE hAssembly, + SString &result) = 0; + + // Returns the GC-information for a method. This is the simple representation + // and can be used when a code that can trigger a GC does not have access + // to the CORINFO_METHOD_HANDLE (which is normally used to access the GC information) + // + // Returns S_FALSE if there is no simple representation for the method's GC info + // + virtual void GetCallRefMap( + CORINFO_METHOD_HANDLE hMethod, + GCRefMapBuilder * pBuilder, + bool isDispatchCell) = 0; + + // Returns a compressed block of debug information + // + // Uncompressed debug maps are passed in. + // Writes to outgoing SBuffer. + // Throws on failure. + virtual void CompressDebugInfo( + IN ICorDebugInfo::OffsetMapping * pOffsetMapping, + IN ULONG iOffsetMapping, + IN ICorDebugInfo::NativeVarInfo * pNativeVarInfo, + IN ULONG iNativeVarInfo, + IN OUT SBuffer * pDebugInfoBuffer + ) = 0; + + + + // Allows to set verbose level for log messages, enabled in retail build too for stats + virtual HRESULT SetVerboseLevel( + IN VerboseLevel level) = 0; + + // Get the compilation flags that are shared between JIT and NGen + virtual HRESULT GetBaseJitFlags( + IN CORINFO_METHOD_HANDLE hMethod, + OUT CORJIT_FLAGS *pFlags) = 0; + + virtual ICorJitHost* GetJitHost() = 0; + + // needed for stubs to obtain the number of bytes to copy into the native image + // return the beginning of the stub and the size to copy (in bytes) + virtual void* GetStubSize(void *pStubAddress, DWORD *pSizeToCopy) = 0; + + // Takes a stub and blits it into the buffer, resetting the reference count + // to 1 on the clone. The buffer has to be large enough to hold the stub object and the code + virtual HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize) = 0; + + // true if the method has [NativeCallableAttribute] + virtual BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle) = 0; + + virtual BOOL GetIsGeneratingNgenPDB() = 0; + virtual void SetIsGeneratingNgenPDB(BOOL fGeneratingNgenPDB) = 0; + +#ifdef FEATURE_READYTORUN_COMPILER + virtual CORCOMPILE_FIXUP_BLOB_KIND GetFieldBaseOffset( + CORINFO_CLASS_HANDLE classHnd, + DWORD * pBaseOffset + ) = 0; + + virtual BOOL NeedsTypeLayoutCheck(CORINFO_CLASS_HANDLE classHnd) = 0; + virtual void EncodeTypeLayout(CORINFO_CLASS_HANDLE classHandle, SigBuilder * pSigBuilder) = 0; + + virtual BOOL AreAllClassesFullyLoaded(CORINFO_MODULE_HANDLE moduleHandle) = 0; + + virtual int GetVersionResilientTypeHashCode(CORINFO_MODULE_HANDLE moduleHandle, mdToken token) = 0; + + virtual int GetVersionResilientMethodHashCode(CORINFO_METHOD_HANDLE methodHandle) = 0; + + virtual BOOL EnumMethodsForStub(CORINFO_METHOD_HANDLE hMethod, void** enumerator) = 0; + virtual BOOL EnumNextMethodForStub(void * enumerator, CORINFO_METHOD_HANDLE *hMethod) = 0; + virtual void EnumCloseForStubEnumerator(void *enumerator) = 0; + +#endif + + virtual BOOL HasCustomAttribute(CORINFO_METHOD_HANDLE method, LPCSTR customAttributeName) = 0; +}; + +/*****************************************************************************/ +// This function determines the compile flags to use for a generic intatiation +// since only the open instantiation can be verified. +// See the comment associated with CORJIT_FLAG_SKIP_VERIFICATION for details. +// +// On return: +// if *raiseVerificationException=TRUE, the caller should raise a VerificationException. +// if *unverifiableGenericCode=TRUE, the method is a generic instantiation with +// unverifiable code + +CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation( + CORINFO_METHOD_HANDLE method, + CORJIT_FLAGS compileFlags, + ICorJitInfo * pCorJitInfo, + BOOL * raiseVerificationException, + BOOL * unverifiableGenericCode); + +// Returns the global instance of JIT->EE interface for NGen + +extern "C" ICorDynamicInfo * __stdcall GetZapJitInfo(); + +// Returns the global instance of Zapper->EE interface + +extern "C" ICorCompileInfo * __stdcall GetCompileInfo(); + +// Stress mode to leave some methods/types uncompiled in the ngen image. +// Those methods will be JIT-compiled at runtime as needed. + +extern "C" unsigned __stdcall PartialNGenStressPercentage(); + +// create a PDB dumping all functions in hAssembly into pdbPath +extern "C" HRESULT __stdcall CreatePdb(CORINFO_ASSEMBLY_HANDLE hAssembly, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath, LPCWSTR pDiasymreaderPath); + +extern bool g_fNGenMissingDependenciesOk; + +extern bool g_fNGenWinMDResilient; + +#ifdef FEATURE_READYTORUN_COMPILER +extern bool g_fReadyToRunCompilation; +extern bool g_fLargeVersionBubble; +#endif + +inline bool IsReadyToRunCompilation() +{ +#ifdef FEATURE_READYTORUN_COMPILER + return g_fReadyToRunCompilation; +#else + return false; +#endif +} + +#ifdef FEATURE_READYTORUN_COMPILER +inline bool IsLargeVersionBubbleEnabled() +{ + return g_fLargeVersionBubble; +} +#endif + +#endif /* COR_COMPILE_H_ */ diff --git a/lib/coreclr/src/inc/cordbpriv.h b/lib/coreclr/src/inc/cordbpriv.h new file mode 100644 index 0000000000..30231d3788 --- /dev/null +++ b/lib/coreclr/src/inc/cordbpriv.h @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* ------------------------------------------------------------------------- * + * cordbpriv.h -- header file for private Debugger data shared by various + * Runtime components. + * ------------------------------------------------------------------------- */ + +#ifndef _cordbpriv_h_ +#define _cordbpriv_h_ + +#include "corhdr.h" +#include + +// +// Initial value for EnC versions +// +#define CorDB_DEFAULT_ENC_FUNCTION_VERSION 1 +#define CorDB_UNKNOWN_ENC_FUNCTION_VERSION ((SIZE_T)(-1)) + +enum DebuggerLaunchSetting +{ + DLS_ASK_USER = 0, + DLS_ATTACH_DEBUGGER = 1 +}; + + +// +// Flags used to control the Runtime's debugging modes. These indicate to +// the Runtime that it needs to load the Runtime Controller, track data +// during JIT's, etc. +// +enum DebuggerControlFlag +{ + DBCF_NORMAL_OPERATION = 0x0000, + + DBCF_USER_MASK = 0x00FF, + DBCF_GENERATE_DEBUG_CODE = 0x0001, + DBCF_ALLOW_JIT_OPT = 0x0008, + DBCF_PROFILER_ENABLED = 0x0020, +// DBCF_ACTIVATE_REMOTE_DEBUGGING = 0x0040, Deprecated. DO NOT USE + + DBCF_INTERNAL_MASK = 0xFF00, + DBCF_PENDING_ATTACH = 0x0100, + DBCF_ATTACHED = 0x0200, + DBCF_FIBERMODE = 0x0400 +}; + +// +// Flags used to control the debuggable state of modules and +// assemblies. +// +enum DebuggerAssemblyControlFlags +{ + DACF_NONE = 0x00, + DACF_USER_OVERRIDE = 0x01, + DACF_ALLOW_JIT_OPTS = 0x02, + DACF_OBSOLETE_TRACK_JIT_INFO = 0x04, // obsolete in V2.0, we're always tracking. + DACF_ENC_ENABLED = 0x08, + DACF_IGNORE_PDBS = 0x20, + DACF_CONTROL_FLAGS_MASK = 0x2F, + + DACF_PDBS_COPIED = 0x10, + DACF_MISC_FLAGS_MASK = 0x10, +}; + +#endif /* _cordbpriv_h_ */ diff --git a/lib/coreclr/src/inc/cordebug.idl b/lib/coreclr/src/inc/cordebug.idl new file mode 100644 index 0000000000..c0dcb7670b --- /dev/null +++ b/lib/coreclr/src/inc/cordebug.idl @@ -0,0 +1,7574 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** Cordebug.idl - Common Language Runtime Debugging interfaces. ** + ** ** + *****************************************************************************/ + + +/* ------------------------------------------------------------------------- * + * Imported types + * ------------------------------------------------------------------------- */ + +#if !DEFINITIONS_FROM_NON_IMPORTABLE_PLACES + +cpp_quote("#if 0") + +import "unknwn.idl"; +import "objidl.idl"; + +typedef UINT32 mdToken; +typedef mdToken mdModule; +typedef SIZE_T mdScope; +typedef mdToken mdTypeDef; +typedef mdToken mdSourceFile; +typedef mdToken mdMemberRef; +typedef mdToken mdMethodDef; +typedef mdToken mdFieldDef; +typedef mdToken mdSignature; +typedef ULONG CorElementType; +typedef SIZE_T PCCOR_SIGNATURE; + +typedef SIZE_T LPDEBUG_EVENT; + +typedef SIZE_T LPSTARTUPINFOW; +typedef SIZE_T LPPROCESS_INFORMATION; + +typedef const void far *LPCVOID; + +cpp_quote("#endif") + +typedef [wire_marshal(unsigned long)] void *HPROCESS; +typedef [wire_marshal(unsigned long)] void *HTHREAD; + +typedef UINT64 TASKID; +typedef DWORD CONNID; + + + + +#endif + +cpp_quote("#ifndef _COR_IL_MAP") +cpp_quote("#define _COR_IL_MAP") + +// Note that this structure is also defined in CorProf.idl - PROPOGATE CHANGES +// BOTH WAYS, or this'll become a really insidious bug some day. +typedef struct _COR_IL_MAP +{ + ULONG32 oldOffset; // Old IL offset relative to beginning of function + ULONG32 newOffset; // New IL offset relative to beginning of function + BOOL fAccurate; // TRUE if mapping is known to be good, FALSE otherwise +} COR_IL_MAP; + +cpp_quote("#endif //_COR_IL_MAP") + +cpp_quote("#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_") +cpp_quote("#define _COR_DEBUG_IL_TO_NATIVE_MAP_") + +/* ICorDebugCode:: GetILToNativeMapping returns an array of + * COR_DEBUG_IL_TO_NATIVE_MAP structures. In order to convey that certain + * ranges of native instructions correspond to special regions of code (for + * example, the prolog), an entry in the array may have it's ilOffset field set + * to one of these values. + */ +typedef enum CorDebugIlToNativeMappingTypes +{ + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3 +} CorDebugIlToNativeMappingTypes; + +typedef struct COR_DEBUG_IL_TO_NATIVE_MAP +{ + ULONG32 ilOffset; + ULONG32 nativeStartOffset; + ULONG32 nativeEndOffset; +} COR_DEBUG_IL_TO_NATIVE_MAP; + +cpp_quote("#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_") + +cpp_quote("#define REMOTE_DEBUGGING_DLL_ENTRY L\"Software\\\\Microsoft\\\\.NETFramework\\\\Debugger\\\\ActivateRemoteDebugging\"") + + +typedef enum CorDebugJITCompilerFlags +{ + CORDEBUG_JIT_DEFAULT = 0x1, // Track info, enable optimizations + CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3, // Includes track info, disable opts, + CORDEBUG_JIT_ENABLE_ENC = 0x7 // Includes track & disable opt & Edit and Continue. +} CorDebugJITCompilerFlags; + +typedef enum CorDebugJITCompilerFlagsDecprecated +{ + CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1, // Use CORDEBUG_JIT_DEFAULT instead +} CorDebugJITCompilerFlagsDeprecated; + +typedef enum CorDebugNGENPolicy +{ + DISABLE_LOCAL_NIC = 1 // indicates that the native image cache for a modern application should be ignored +} CorDebugNGENPolicy; + +/* ------------------------------------------------------------------------- * + * Forward declarations + * ------------------------------------------------------------------------- */ +#pragma warning(push) +#pragma warning(disable:28718) //Unable to annotate as this is not a local interface + +interface ICorDebug; + +interface ICorDebugController; +interface ICorDebugProcess; +interface ICorDebugProcess2; +interface ICorDebugAppDomain; +interface ICorDebugAssembly; +interface ICorDebugAssembly2; +interface ICorDebugBreakpoint; +interface ICorDebugFunctionBreakpoint; +interface ICorDebugModuleBreakpoint; +interface ICorDebugValueBreakpoint; +interface ICorDebugStepper; +interface ICorDebugEval; +interface ICorDebugEval2; +interface ICorDebugThread; +interface ICorDebugThread2; +interface ICorDebugThread3; +interface ICorDebugThread4; +interface ICorDebugStackWalk; +interface ICorDebugChain; +interface ICorDebugFrame; +interface ICorDebugILFrame; +interface ICorDebugInternalFrame; +interface ICorDebugInternalFrame2; +interface ICorDebugNativeFrame; +interface ICorDebugNativeFrame2; +interface ICorDebugRuntimeUnwindableFrame; +interface ICorDebugContext; +interface ICorDebugModule; +interface ICorDebugFunction; +interface ICorDebugFunction2; +interface ICorDebugCode; +interface ICorDebugILCode; +interface ICorDebugClass; +interface ICorDebugType; + +interface ICorDebugValue; +interface ICorDebugGenericValue; +interface ICorDebugReferenceValue; +interface ICorDebugHeapValue; +interface ICorDebugHeapValue2; +interface ICorDebugHeapValue3; +interface ICorDebugHandleValue; +interface ICorDebugObjectValue; +interface ICorDebugStringValue; +interface ICorDebugArrayValue; + +interface ICorDebugEnum; +interface ICorDebugObjectEnum; +interface ICorDebugProcessEnum; +interface ICorDebugBreakpointEnum; +interface ICorDebugStepperEnum; +interface ICorDebugModuleEnum; +interface ICorDebugThreadEnum; +interface ICorDebugChainEnum; +interface ICorDebugTypeEnum; +interface ICorDebugCodeEnum; +interface ICorDebugFrameEnum; +interface ICorDebugValueEnum; +interface ICorDebugVariableHomeEnum; +interface ICorDebugAppDomainEnum; +interface ICorDebugAssemblyEnum; +interface ICorDebugBlockingObjectEnum; + +interface ICorDebugErrorInfoEnum; +interface ICorDebugMDA; + +/* DEPRECATED */ +interface ICorDebugEditAndContinueSnapshot; +/* DEPRECATED */ +interface ICorDebugEditAndContinueErrorInfo; + +#pragma warning(pop) + +// All target addresses in ICorDebug are represented as 0-extended 64-bit integer values. +typedef ULONG64 CORDB_ADDRESS; + +typedef ULONG64 CORDB_REGISTER; +typedef DWORD CORDB_CONTINUE_STATUS; +typedef enum CorDebugBlockingReason { + BLOCKING_NONE = 0x0, + BLOCKING_MONITOR_CRITICAL_SECTION = 0x1, + BLOCKING_MONITOR_EVENT = 0x2 +} CorDebugBlockingReason; + +typedef struct CorDebugBlockingObject { + ICorDebugValue *pBlockingObject; + DWORD dwTimeout; + CorDebugBlockingReason blockingReason; +} CorDebugBlockingObject; + +typedef struct CorDebugExceptionObjectStackFrame +{ + ICorDebugModule* pModule; + CORDB_ADDRESS ip; + mdMethodDef methodDef; + BOOL isLastForeignExceptionFrame; +} CorDebugExceptionObjectStackFrame; + +typedef struct CorDebugGuidToTypeMapping +{ + GUID iid; + ICorDebugType * pType; +} CorDebugGuidToTypeMapping; + +/* + * Callback interface for providing access to a particular target process. The + * debugging services will call functions on this interface to access memory + * and other data in the target process. The debugger client must implement + * this interface as appropriate for the particular target (for example, a live + * process or a memory dump). The DataTarget will only be invoked from within + * the implementation of other ICorDebug APIs (i.e. the debugger client has + * control over which thread it is invoked on, and when) + * + * Error HRESULTS returned by DataTarget APIs will propagate up and be returned + * by the active ICorDebug API call. + * + * The DataTarget implementation must always return up-to-date information + * about the target. The target process should be stopped (not changing + * in any way) while ICorDebug APIs (and hence DataTarget APIs) are being + * called. If the target is a live process and it's state changes, + * OpenVirtualProcess needs to be called again to provide a replacement + * ICorDebugProcess instance. + */ +[ + object, + local, + uuid(FE06DC28-49FB-4636-A4A3-E80DB4AE116C), + pointer_default(unique) +] +interface ICorDebugDataTarget : IUnknown +{ + /* + * GetPlatform returns the processor architecture and operating system on + * which the target process is (or was) running. + * + * This is used by ICorDebug to determine details of the target process + * such as its pointer size, address space layout, register set, + * instruction format, context layout, and calling conventions, etc. + * This platforms in this list are the only ones supported by this version + * of ICorDebug, but more may be added in future versions. + * + * Note that this may actually indicate the platform which is being + * emulated for the target, not the actual hardware in use. For example, + * a process running in the WOW on Windows x64 should use + * CORDB_PLATFORM_WINDOWS_X86. + * + * Implementations should be sure to describe what the platform of the + * target actually is, not just what the host expects it to be. + * + * This function must succeed. If it fails, the DataTarget is unusable. + */ + typedef enum CorDebugPlatform + { + CORDB_PLATFORM_WINDOWS_X86, // Windows on Intel x86 + CORDB_PLATFORM_WINDOWS_AMD64, // Windows x64 (Amd64, Intel EM64T) + CORDB_PLATFORM_WINDOWS_IA64, // Windows on Intel IA-64 + CORDB_PLATFORM_MAC_PPC, // Mac OS on PowerPC (Deprecated) + CORDB_PLATFORM_MAC_X86, // Mac OS on Intel x86 (Deprecated, use CORDB_PLATFORM_POSIX_X86) + CORDB_PLATFORM_WINDOWS_ARM, // Windows on ARM + CORDB_PLATFORM_MAC_AMD64, // Mac OS on Intel x64 (Deprecated, use CORDB_PLATFORM_POSIX_AMD64) + CORDB_PLATFORM_WINDOWS_ARM64, // Windows on ARM64 + + CORDB_PLATFORM_POSIX_AMD64, // Posix supporting OS on Intel x64 + CORDB_PLATFORM_POSIX_X86, // Posix supporting OS on Intel x86 + CORDB_PLATFORM_POSIX_ARM, // Posix supporting OS on ARM32 + CORDB_PLATFORM_POSIX_ARM64 // Posix supporting OS on ARM64 + } CorDebugPlatform; + + HRESULT GetPlatform([out] CorDebugPlatform * pTargetPlatform); + + /* + * ReadVirtual - Read virtual memory from the target process. + * + * Requests contiguous memory starting at the specified target address to + * be read from the target process into the supplied buffer. If at least + * the first byte (at the specified start address) can be read, the call + * should return success (to support efficient reading of data structures + * with self-describing length, like null-terminated strings). + * + * On success, the actual number of bytes read must be stored into + * pBytesRead. + */ + HRESULT ReadVirtual([in] CORDB_ADDRESS address, + [out, size_is(bytesRequested), length_is(*pBytesRead)] BYTE * pBuffer, + [in] ULONG32 bytesRequested, + [out] ULONG32 * pBytesRead); + + /* + * GetThreadContext - Get the thread context (register values) for a thread. + * + * Requests the current thread context for the specified (operating-system + * defined) thread identifier. The size and format of the context record + * is platform dependant, and is determined by the result of the call to + * GetPlatform. + * + * The context flags specify, in a platform-dependent manor, which portions + * of the context should be read. contextSize specifies the size of the + * supplied buffer, but the function is free to not fill the whole buffer + * if it is possible to determine the actual size from the context. + * + * On Windows platforms, the buffer must be a CONTEXT structure appropriate + * for the machine type specified by GetPlatform. contextFlags has the + * same values as the ContextFlags field of CONTEXT. + */ + HRESULT GetThreadContext([in] DWORD dwThreadID, + [in] ULONG32 contextFlags, + [in] ULONG32 contextSize, + [out, size_is(contextSize)] BYTE * pContext); +}; + +/* + * Used to retrieve the debug-symbol information for a static field. + */ +[ + object, + local, + uuid(CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B), + pointer_default(unique) +] +interface ICorDebugStaticFieldSymbol : IUnknown +{ + /* + * GetName - gives the name of the static field + */ + HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + /* + * GetSize - gives the size of the static field + */ + HRESULT GetSize([out] ULONG32 *pcbSize); + + /* + * GetAddress - gives the RVA of the static field + */ + HRESULT GetAddress([out] CORDB_ADDRESS *pRVA); +} + +/* + * Used to retrieve the debug-symbol information for an instance field. + */ +[ + object, + local, + uuid(A074096B-3ADC-4485-81DA-68C7A4EA52DB), + pointer_default(unique) +] +interface ICorDebugInstanceFieldSymbol : IUnknown +{ + /* + * GetName - gives the name of the instance field + */ + HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + /* + * GetSize - gives the size of the instance field + */ + HRESULT GetSize([out] ULONG32 *pcbSize); + + /* + * GetOffset - gives the offset of the instance field in its parent class + */ + HRESULT GetOffset([out] ULONG32 *pcbOffset); +} + +/* + * Used to retrieve the debug-symbol information for a variable. + */ +[ + object, + local, + uuid(707E8932-1163-48D9-8A93-F5B1F480FBB7), + pointer_default(unique) +] +interface ICorDebugVariableSymbol : IUnknown +{ + /* + * GetName - gives the name of the variable + */ + HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + /* + * GetSize - gives the size of a variable + */ + HRESULT GetSize([out] ULONG32 *pcbValue); + + /* + * GetValue - Used to get the value of a variable as a byte array. + * + * offset: read the value starting at this offset in variable, this is used when reading member fields in an object + * context: thread context used to read the value + * cbContext: size of thread context + * + * cbValue: size of pValue buffer + * pcbValue: size of pValue buffer filled with value + * pValue: buffer used to hold the read value + */ + HRESULT GetValue([in] ULONG32 offset, + [in] ULONG32 cbContext, + [in, size_is(cbContext)] BYTE context[], + [in] ULONG32 cbValue, + [out] ULONG32 *pcbValue, + [out, size_is(cbValue), length_is(*pcbValue)] BYTE pValue[]); + + /* + * SetValue - Given a byte array, sets it as the value of the variable. + * + * offset: set the value starting at this offset in variable, this is used when writing member fields in an object + * threadID: thread id used to indentify the thread whose context must be updated to reflect the new value + * context: thread context used to write the value + * cbContext: size of thread context + * + * cbValue: size of pValue buffer + * pValue: buffer to hold the value to set + */ + HRESULT SetValue([in] ULONG32 offset, + [in] DWORD threadID, + [in] ULONG32 cbContext, + [in, size_is(cbContext)] BYTE context[], + [in] ULONG32 cbValue, + [in, size_is(cbValue)] BYTE pValue[]); + + /* + * GetSlotIndex - Gives the managed slot-index of a local variable. + * This slot-index can be used to retrieve the metadata information for this local. + * + * Returns E_FAIL if the variable is a function argument. + */ + HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex); +} + + +/* + * Represents an in-memory buffer. + */ +[ + object, + uuid(677888B3-D160-4B8C-A73B-D79E6AAA1D13), + local, + pointer_default(unique) +] +interface ICorDebugMemoryBuffer : IUnknown +{ + /* + * GetStartAddress - Gives the address where buffer starts. + */ + HRESULT GetStartAddress([out] LPCVOID *address); + + /* + * GetStartAddress - Gives the size of memory buffer. + */ + HRESULT GetSize([out] ULONG32 *pcbBufferLength); +} + +/* + * Used to get information about a merged assembly. + */ +[ + object, + uuid(FAA8637B-3BBE-4671-8E26-3B59875B922A), + local, + pointer_default(unique) +] +interface ICorDebugMergedAssemblyRecord : IUnknown +{ + /* + * GetSimpleName - Gives the simple name of the assembly (for example "System.Collections") + * These names do not include qualifiers such as file extensions, culture, version, or public key token + */ + HRESULT GetSimpleName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + /* + * GetVersion - Gives the assembly version information + */ + HRESULT GetVersion([out] USHORT *pMajor, [out] USHORT *pMinor, [out] USHORT *pBuild, [out] USHORT *pRevision); + + /* + * GetCulture - Gives culture string for the assembly (for example "neutral" or "en-US") + */ + HRESULT GetCulture([in] ULONG32 cchCulture, [out] ULONG32 *pcchCulture, [out, size_is(cchCulture), length_is(*pcchCulture)] WCHAR szCulture[]); + + /* + * GetPublicKey - Gives the assembly public key + */ + HRESULT GetPublicKey([in] ULONG32 cbPublicKey, [out] ULONG32 *pcbPublicKey, [out, size_is(cbPublicKey), length_is(*pcbPublicKey)] BYTE pbPublicKey[]); + + /* + * GetPublicKeyToken - Gives the assembly public key token (the last 8 bytes of a SHA1 hash of the public key) + */ + HRESULT GetPublicKeyToken([in] ULONG32 cbPublicKeyToken, [out] ULONG32 *pcbPublicKeyToken, + [out, size_is(cbPublicKeyToken), length_is(*pcbPublicKeyToken)] BYTE pbPublicKeyToken[]); + + /* + * GetIndex - Gives prefix index used to prevent name collisions in the merged metadata type names + */ + HRESULT GetIndex([out] ULONG32 *pIndex); +} + +/* + * Used to retrieve debug symbol information. + */ +[ + object, + uuid(3948A999-FD8A-4C38-A708-8A71E9B04DBB), + local, + pointer_default(unique) +] +interface ICorDebugSymbolProvider : IUnknown +{ + /* + * GetStaticFieldSymbols - given a typespec signature, gives back its static field symbols + */ + HRESULT GetStaticFieldSymbols([in] ULONG32 cbSignature, + [in, size_is(cbSignature)] BYTE typeSig[], + [in] ULONG32 cRequestedSymbols, + [out] ULONG32 *pcFetchedSymbols, + [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugStaticFieldSymbol *pSymbols[]); + + /* + * GetInstanceFieldSymbols - given a typespec signature, gives back its instance field symbols + */ + HRESULT GetInstanceFieldSymbols([in] ULONG32 cbSignature, + [in, size_is(cbSignature)] BYTE typeSig[], + [in] ULONG32 cRequestedSymbols, + [out] ULONG32 *pcFetchedSymbols, + [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugInstanceFieldSymbol *pSymbols[]); + + /* + * GetMethodLocalSymbols - given rva in a method, gives back its local symbols + */ + HRESULT GetMethodLocalSymbols([in] ULONG32 nativeRVA, + [in] ULONG32 cRequestedSymbols, + [out] ULONG32 *pcFetchedSymbols, + [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugVariableSymbol *pSymbols[]); + + /* + * GetMethodParameterSymbols - given rva in a method, gives back its parameter symbols + */ + HRESULT GetMethodParameterSymbols([in] ULONG32 nativeRVA, + [in] ULONG32 cRequestedSymbols, + [out] ULONG32 *pcFetchedSymbols, + [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugVariableSymbol *pSymbols[]); + + /* + * GetMergedAssemblyRecords - gets symbol records for all the merged assemblies + */ + HRESULT GetMergedAssemblyRecords([in] ULONG32 cRequestedRecords, + [out] ULONG32 *pcFetchedRecords, + [out, size_is(cRequestedRecords), length_is(*pcFetchedRecords)] ICorDebugMergedAssemblyRecord *pRecords[]); + + /* + * GetMethodProps - given an rva in a method, gives back the + * pMethodToken - method's token + * pcGenericParams - number of generic parameters associated with this method + * cbSignature - size of signature array, set to 0 and pass signature as NULL to get the actual size in pcbSignature + * pcbSignature - returned size of signature + * signature - buffer to hold the type-spec signatures of all generic parameters + */ + HRESULT GetMethodProps([in] ULONG32 codeRva, + [out] mdToken *pMethodToken, + [out] ULONG32 *pcGenericParams, + [in] ULONG32 cbSignature, + [out] ULONG32 *pcbSignature, + [out, size_is(cbSignature), length_is(*pcbSignature)] BYTE signature[]); + + /* + * GetTypeProps - given a vtable rva, gives back the + * cbSignature - size of signature array, set to 0 and pass signature as NULL to get the actual size in pcbSignature + * pcbSignature - returned size of signature + * signature - buffer to hold the signature of type corresponding to input vtableRva + */ + HRESULT GetTypeProps([in] ULONG32 vtableRva, + [in] ULONG32 cbSignature, + [out] ULONG32 *pcbSignature, + [out, size_is(cbSignature), length_is(*pcbSignature)] BYTE signature[]); + + /* + * GetCodeRange - given rva in a method, gives back the method start address and size. + */ + HRESULT GetCodeRange([in] ULONG32 codeRva, [out] ULONG32* pCodeStartAddress, ULONG32* pCodeSize); + + /* + * GetAssemblyImageBytes - given an RVA in the merged assembly and size, reads data from the merged assembly and gives it back as an ICorDebugMemoryBuffer + */ + HRESULT GetAssemblyImageBytes([in] CORDB_ADDRESS rva, [in] ULONG32 length, [out] ICorDebugMemoryBuffer** ppMemoryBuffer); + + /* + * GetObjectSize - given a typespec signature, gives back its object size + */ + HRESULT GetObjectSize([in] ULONG32 cbSignature, + [in, size_is(cbSignature)] BYTE typeSig[], + [out] ULONG32 *pObjectSize); + + /* + * GetAssemblyImageMetadata - gives back the merged assembly metadata as an ICorDebugMemoryBuffer + */ + HRESULT GetAssemblyImageMetadata([out] ICorDebugMemoryBuffer** ppMemoryBuffer); +} + +/* + * Used to retrieve debug symbol information. + */ +[ + object, + uuid(F9801807-4764-4330-9E67-4F685094165E), + local, + pointer_default(unique) +] +interface ICorDebugSymbolProvider2 : IUnknown +{ + /* + * Gives back the generic dictionary map as an ICorDebugMemoryBuffer + * + * At the highest level, the map consists of two sections. + * The first section contains a "directory" of all dictionaries (RVA) covered by this map, the second section + * is a byte aligned heap with instantiation information starting right after the last directory entry. + * Each entry in the "directory" refers to an offset inside the "heap" (relative to the start of the heap). + * Please note that it is possible that multiple directory entries point to the same offset into the heap. + * + * Contents of the map: + * + * - First 4 bytes: number of RVA/dictionary entries (N) + * If the high bit is set, the following N entries are sorted by RVA in ascending order. + * + * - N 8 byte wide entries, each entry consisting of 2 4-byte entries: + * 1st 4 byte entry - RVA: the dictionary's RVA + * 2nd 4 byte entry - Offset: an offset relative to the start of the heap. + * + * - Heap + * + * The heap's size can be computed be a stream reader by subtracting the directory size + 4. + * + * The format for each instantiation info in heap is as follows: + * - Length of this instantiation info (in bytes, not including this length information) in compressed ECMA metadata format. + * - Number of instantatiation types (T, in compressed ECMA metadata format) + * - T types, each expressed in ECMA type signature format + * + * The inclusion of the length for each heap element enables simple sorting of the directory section without affecting the heap. + */ + HRESULT GetGenericDictionaryInfo([out] ICorDebugMemoryBuffer** ppMemoryBuffer); + + /* + * GetFrameProps: + * For a given code-rva, gives the method start rva (pCodeStartRva) and parent + * frame's start rva (pParentFrameStartRva). + * If there is no parent frame, then pParentFrameStartRva is set to 0 + */ + HRESULT GetFrameProps([in] ULONG32 codeRva, + [out] ULONG32 *pCodeStartRva, + [out] ULONG32 *pParentFrameStartRva); +} + +/* + * Implemented by the debugger and helps in stack unwinding. + */ +[ + object, + uuid(F69126B7-C787-4F6B-AE96-A569786FC670), + local, + pointer_default(unique) +] +interface ICorDebugVirtualUnwinder : IUnknown +{ + /* + * Get the current context of this unwinder. + * + * contextBuf is passed in by ICorDebugStackWalk. As unwinding may only restore a subset of the + * registers, such as only non-volatile registers, the context may not exactly match the register + * state at the time of the actual call. + * + * Any failing HRESULT received by mscordbi is considered fatal and will cause ICorDebug + * APIs to return CORDBG_E_DATA_TARGET_ERROR. + */ + HRESULT GetContext([in] ULONG32 contextFlags, + [in] ULONG32 cbContextBuf, + [out] ULONG32* contextSize, + [out, size_is(cbContextBuf)] BYTE contextBuf[]); + + /* + * Advances to the callers context. + * + * If a failing HRESULT is returned ICorDebug APIs will return CORDBG_E_DATA_TARGET_ERROR. + * If the unwind can not be completed because there are no more frames the unwinder should + * return CORDBG_S_AT_END_OF_STACK. + * If the unwind occurred successfully return S_OK. + * + * The stackwalker should ensure forward progress is being made, so that eventually a call + * to Next() will return a failing HRESULT or CORDBG_S_AT_END_OF_STACK. Returning S_OK + * indefinitely may cause an infinite loop. + */ + HRESULT Next(); +} + + +[ + object, + uuid(2eb364da-605b-4e8d-b333-3394c4828d41), + local, + pointer_default(unique) +] +interface ICorDebugDataTarget2 : IUnknown +{ + /* + * GetImageFromPointer: + * Given address in a module, gives back the module base address and size. + */ + HRESULT GetImageFromPointer([in] CORDB_ADDRESS addr, [out] CORDB_ADDRESS *pImageBase, [out] ULONG32 *pSize); + + /* + * GetImageLocation: + * Given module base address, gives back the module's path. + */ + HRESULT GetImageLocation([in] CORDB_ADDRESS baseAddress, + [in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + /* + * GetImageLocation: + * Given address in a module, gives back a symbol-provider for the module. + */ + HRESULT GetSymbolProviderForImage([in] CORDB_ADDRESS imageBaseAddress, [out] ICorDebugSymbolProvider **ppSymProvider); + + /* + * EnumerateThreadIDs: + * Gives back the list of active thread ids. + */ + HRESULT EnumerateThreadIDs([in] ULONG32 cThreadIds, [out] ULONG32 *pcThreadIds, [out, size_is(cThreadIds), length_is(*pcThreadIds)] ULONG32 pThreadIds[]); + + /* + * CreateVirtualUnwinder: + * Create a new stack unwinder that starts unwinding from initialContext (which isn't + * necessarily the leaf of a thread). + * Any failing HRESULT received by mscordbi is considered fatal and will cause ICorDebug + * APIs to return CORDBG_E_DATA_TARGET_ERROR. + */ + HRESULT CreateVirtualUnwinder([in] DWORD nativeThreadID, + [in] ULONG32 contextFlags, + [in] ULONG32 cbContext, + [in, size_is(cbContext)] BYTE initialContext[], + [out] ICorDebugVirtualUnwinder ** ppUnwinder); +}; + + +/* + * Provides the information about a loaded module. + * Note that this interface is implemented by debugger and is used by DBI to get + * the loaded module information from debugger. + */ +[ + object, + uuid(817F343A-6630-4578-96C5-D11BC0EC5EE2), + local, + pointer_default(unique) +] +interface ICorDebugLoadedModule : IUnknown +{ + /* + * gives the base address + */ + HRESULT GetBaseAddress([out] CORDB_ADDRESS *pAddress); + + /* + * gives the module name + */ + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * gives the module size + */ + HRESULT GetSize([out] ULONG32 *pcBytes); +}; + +[ + object, + uuid(D05E60C3-848C-4E7D-894E-623320FF6AFA), + local, + pointer_default(unique) +] +interface ICorDebugDataTarget3 : IUnknown +{ + /* + * gives back the list of modules loaded so far. + */ + HRESULT GetLoadedModules([in] ULONG32 cRequestedModules, + [out] ULONG32 *pcFetchedModules, + [out, size_is(cRequestedModules), + length_is(*pcFetchedModules)] ICorDebugLoadedModule *pLoadedModules[]); +}; + +/* + * Data target that knows how to obtain debugee's process id. + * Debugee is not necessarily a living process at that time or on the same machine. + */ +[ + object, + uuid(E799DC06-E099-4713-BDD9-906D3CC02CF2), + local, + pointer_default(unique) +] +interface ICorDebugDataTarget4 : IUnknown +{ + /* + * Unwinds one native stack frame in the target process/thread + */ + HRESULT VirtualUnwind([in] DWORD threadId, + [in] ULONG32 contextSize, + [in, out, size_is(contextSize)] BYTE *context); +}; + +/* + * Mutable extension to the data target. This version of ICorDebugDataTarget + * can be implemented by targets that wish to support modification of the target + * process (such as for live invasive debugging). + * + * All of these APIs are optional in the sense that no core inspection-based + * debugging functionality will be lost by not implementing this interface or + * by the failure of these methods. Any failure HRESULT from these APIs will + * propagate out as the HRESULT from the ICorDebug API call. + * + * Note that a single ICorDebug API call may result in multiple mutations, + * and there is no mechanism for ensuring related mutations are applied + * transactionally (all-or-none). This means that if a mutation fails after + * others (for the same ICorDebug call) have succeeded, the target process may + * be left in an inconsistent state and debugging may become unreliable. + */ +[ + object, + uuid(A1B8A756-3CB6-4CCB-979F-3DF999673A59), + local, + pointer_default(unique) +] +interface ICorDebugMutableDataTarget : ICorDebugDataTarget +{ + /* + * WriteVirtual - write memory into the target process address space + * + * Write the specified buffer into the target process at the specified + * address. If any bytes cannot be written, the call should fail without + * changing any bytes in the target (otherwise the target may be in an + * inconsistent state which makes further debugging unreliable). + */ + HRESULT WriteVirtual([in] CORDB_ADDRESS address, + [in, size_is(bytesRequested)] const BYTE * pBuffer, + [in] ULONG32 bytesRequested); + + /* + * SetThreadContext - set the context (register values) for a thread. + * + * Updates the current context for the thread specified by the (OS-defined) + * dwThreadID. The format of the context record is determined by the platform + * indicated by GetPlatform. On Windows, this is a CONTEXT structure. + * contextSize specifies the size of the buffer being passed. + */ + HRESULT SetThreadContext([in] DWORD dwThreadID, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] const BYTE * pContext); + + /* + * Invoke to change the continue-status for the outstanding debug-event on + * the specified thread. + * + * Arguments: + * dwThreadId - OS Thread Id of the debug event + * continueStatus - New continue status being requested. See the + * definition of CORDB_CONTINUE_STATUS for details. + * + * This API is used when the Debugger makes an ICorDebug API request + * which requires the current debug event to be handled in a way that is + * potentially different from which it would be otherwise. For example, + * if there is an outstanding exception, and the debugger requests an + * operation that would cancel the exception (such as SetIp or FuncEval), + * than this API is used to request the exception be cancelled. + */ + HRESULT ContinueStatusChanged([in] DWORD dwThreadId, + [in] CORDB_CONTINUE_STATUS continueStatus); + +}; + + +/* + * Interface used by the data access services layer to locate metadata + * of assemblies in a target. + * + * The API client must implement this interface as appropriate for the + * particular target (for example, a live process or a memory dump). + * + */ +[ + object, + local, + uuid(7cef8ba9-2ef7-42bf-973f-4171474f87d9), + pointer_default(unique) +] +interface ICorDebugMetaDataLocator : IUnknown +{ + /* + * Ask the debugger to return the full path to a module whose metadata is + * needed to complete an operation the debugger requested. + * + * Arguments: + * wszImagePath - This buffer will always contain a NULL-terminated string + * representing the full path to the file when available, and the + * FileName.extension otherwise. + * dwImageTimeStamp - The TimeStamp from the image's PE headers; can + * potentially be used for a symsrv lookup. + * dwImageSize - Size of the image from PE headers; potentially used for + * a symsrv lookup. + * cchPathBuffer - The count of WCHARs pointed to by wszPathBuffer. + * pcchPathBuffer - When the callee returns E_NOT_SUFFICIENT_BUFFER, contains + * the count of WCHARs needed to store the path. + * For all other return values, pcchPathBuffer contains the count of + * WCHARs written to wszPathBuffer. + * wszPathBuffer - Pointer to a buffer into which the debugger will copy + * the full path to the file containing the requested metadata. + * CorOpenFlags.ofReadOnly access to the metadata in this file will + * be requested. + * + * Assumptions: + * The returned file represents a Windows module containing the metadata + * needed to complete a request made by the debugger. + * + * Return Value: + * S_OK on success. wszPathBuffer contains the full path to the file and + * is NULL-terminated. + * + * E_NOT_SUFFICIENT_BUFFER if the current size of wszPathBuffer is not + * sufficient to hold the full path. pcchPathBuffer will contain the + * needed count of WCHARs, including the terminating NULL. + * In this case GetMetaData will be called a second time with the + * requested buffer size. + * + * All other failure HRESULTs are interpreted to mean that the file + * is not retrievable. + * + * Notes: + * If wszImagePath contains a full path for a module from a dump, that + * path will be the path from the machine where the dump was collected. + * The file may not exist at this location, or an incorrect file with the + * same name may be stored on the path. + */ + HRESULT GetMetaData( [in] LPCWSTR wszImagePath, + [in] DWORD dwImageTimeStamp, + [in] DWORD dwImageSize, + [in] ULONG32 cchPathBuffer, + [out, annotation("_Out_")] ULONG32 * pcchPathBuffer, + [out, size_is(cchPathBuffer), length_is(*pcchPathBuffer), annotation("_Out_writes_to_(cchPathBuffer, *pcchPathBuffer) ")] WCHAR wszPathBuffer[]); +}; + + +/* ------------------------------------------------------------------------- * + * User Callback interface + * ------------------------------------------------------------------------- */ + + +#pragma warning(push) +#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugManagedCallback */ +/* + * ICorDebugManagedCallback is implemented by the user of the + * ICorDebug interfaces in order to respond to events in managed code + * in the debuggee process. + * This interface handles manage debug events from v1.0/v1.1 + */ + +[ + object, + local, + uuid(3d6f5f60-7538-11d3-8d5b-00104b35e7ef), + pointer_default(unique) +] +interface ICorDebugManagedCallback : IUnknown +{ + /* + * All callbacks are called with the process in the synchronized state + * All callbacks are serialized, and are called in in the same thread. + * Each callback implementor must call Continue in a callback to + * resume execution. + * If Continue is not called before returning, the process will + * remain stopped. Continue must later be called before any more + * event callbacks will happen. + * + */ + + /* + * Breakpoint is called when a breakpoint is hit. + */ + + HRESULT Breakpoint([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugBreakpoint *pBreakpoint); + + /* + * StepComplete is called when a step has completed. The stepper + * may be used to continue stepping if desired (except for TERMINATE + * reasons.) + * + * STEP_NORMAL means that stepping completed normally, in the same + * function. + * + * STEP_RETURN means that stepping continued normally, after the function + * returned. + * + * STEP_CALL means that stepping continued normally, at the start of + * a newly called function. + * + * STEP_EXCEPTION_FILTER means that control passed to an exception filter + * after an exception was thrown. + * + * STEP_EXCEPTION_HANDLER means that control passed to an exception handler + * after an exception was thrown. + * + * STEP_INTERCEPT means that control passed to an interceptor. + * + * STEP_EXIT means that the thread exited before the step completed. + * No more stepping can be performed with the stepper. + */ + + typedef enum CorDebugStepReason + { + STEP_NORMAL, + STEP_RETURN, + STEP_CALL, + STEP_EXCEPTION_FILTER, + STEP_EXCEPTION_HANDLER, + STEP_INTERCEPT, + STEP_EXIT + } CorDebugStepReason; + + HRESULT StepComplete([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugStepper *pStepper, + [in] CorDebugStepReason reason); + + /* + * Break is called when a break opcode in the code stream is + * executed. + */ + + HRESULT Break([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *thread); + + /* + * Exception is called when an exception is thrown from managed + * code, The specific exception can be retrieved from the thread object. + * + * If unhandled is FALSE, this is a "first chance" exception that + * hasn't had a chance to be processed by the application. If + * unhandled is TRUE, this is an unhandled exception which will + * terminate the process. + */ + + HRESULT Exception([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] BOOL unhandled); + + /* + * EvalComplete is called when an evaluation is completed. + */ + + HRESULT EvalComplete([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugEval *pEval); + + /* + * EvalException is called when an evaluation terminates with + * an unhandled exception. + */ + + HRESULT EvalException([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugEval *pEval); + + /* + * CreateProcess is called when a process is first attached to or + * started. + * + * This entry point won't be called until the EE is initialized. + * Most of the ICorDebug API will return CORDBG_E_NOTREADY prior + * to the CreateProcess callback. + */ + + HRESULT CreateProcess([in] ICorDebugProcess *pProcess); + + /* + * ExitProcess is called when a process exits. + * + * Note: you don't Continue from an ExitProcess event, and this + * event may fire asynchronously to other events, while the + * process appears to be stopped. This can occur if the process + * dies while stopped, usually due to some external force. + * + * If the CLR is already dispatching a managed callback, this event + * will be delayed until after that callback has returned. + * + * This is the only exit/unload event that is guaranteed to get called + * on shutdown. + */ + + HRESULT ExitProcess([in] ICorDebugProcess *pProcess); + + /* + * CreateThread is called when a thread first begins executing managed + * code. The thread will be positioned immediately at the first + * managed code to be executed. + */ + + HRESULT CreateThread([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *thread); + + /* + * ExitThread is called when a thread which has run managed code exits. + * Once this callback is fired, the thread no longer will appear in thread enumerations. + */ + + HRESULT ExitThread([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *thread); + + /* + * LoadModule is called when a Common Language Runtime module is successfully + * loaded. This is an appropriate time to examine metadata for the + * module, set JIT compiler flags, or enable or disable + * class loading callbacks for the module. + */ + + HRESULT LoadModule([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugModule *pModule); + + /* + * UnloadModule is called when a Common Language Runtime module (DLL) is unloaded. The module + * should not be used after this point. + */ + + HRESULT UnloadModule([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugModule *pModule); + + /* + * LoadClass is called when a class finishes loading. This callback only + * occurs if ClassLoading has been enabled for the class's module. + * + * ClassLoading is always enabled for dynamic modules. This is a good time + * to update symbols (ICorDebugModule3::CreateReaderForInMemorySymbols) and + * bind breakpoints to newly generated classes in dynamic modules. + */ + + HRESULT LoadClass([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugClass *c); + + /* + * UnloadClass is called immediately before a class is unloaded. The class + * should not be referenced after this point. This callback only occurs if + * ClassLoading has been enabled for the class's module. + */ + + HRESULT UnloadClass([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugClass *c); + + /* + * DebuggerError is called when an error occurs while attempting to + * handle an event from the Common Language Runtime. It is very strongly + * advised that debuggers log this message to the end user because + * this callback indicates the debugging services have been disabled due to + * an error. + * + * ICorDebugProcess::GetID() will be safe to call, but all other APIs should + * not be called and will fail if they are. + * This includes ICorDebugProcess::Terminate and ICorDebug Process::Detach. The + * debugger should use OS facilities for terminating processes to shut down the process. + */ + HRESULT DebuggerError([in] ICorDebugProcess *pProcess, + [in] HRESULT errorHR, + [in] DWORD errorCode); + + + /* + * Enum defining log message LoggingLevels + */ + typedef enum LoggingLevelEnum + { + LTraceLevel0 = 0, + LTraceLevel1, + LTraceLevel2, + LTraceLevel3, + LTraceLevel4, + LStatusLevel0 = 20, + LStatusLevel1, + LStatusLevel2, + LStatusLevel3, + LStatusLevel4, + LWarningLevel = 40, + LErrorLevel = 50, + LPanicLevel = 100 + } LoggingLevelEnum; + + + typedef enum LogSwitchCallReason + { + SWITCH_CREATE, + SWITCH_MODIFY, + SWITCH_DELETE + } LogSwitchCallReason; + + + /* + * LogMessage is called when a Common Language Runtime managed thread calls the Log + * class in the System.Diagnostics package to log an event. + */ + HRESULT LogMessage([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] LONG lLevel, + [in] WCHAR *pLogSwitchName, + [in] WCHAR *pMessage); + + /* + * LogSwitch is called when a Common Language Runtime managed thread calls the LogSwitch + * class in the System.Diagnostics package to create/modify a LogSwitch. + */ + HRESULT LogSwitch([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] LONG lLevel, + [in] ULONG ulReason, + [in] WCHAR *pLogSwitchName, + [in] WCHAR *pParentName); + + /* + * CreateAppDomain is called when an app domain is created. + */ + HRESULT CreateAppDomain([in] ICorDebugProcess *pProcess, + [in] ICorDebugAppDomain *pAppDomain); + + /* + * ExitAppDomain is called when an app domain exits. + */ + HRESULT ExitAppDomain([in] ICorDebugProcess *pProcess, + [in] ICorDebugAppDomain *pAppDomain); + + + /* + * LoadAssembly is called when a Common Language Runtime assembly is successfully + * loaded. + */ + HRESULT LoadAssembly([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugAssembly *pAssembly); + + /* + * UnloadAssembly is called when a Common Language Runtime assembly is unloaded. The assembly + * should not be used after this point. + */ + HRESULT UnloadAssembly([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugAssembly *pAssembly); + + /* + * ControlCTrap is called if a CTRL-C is trapped in the process being + * debugged. All appdomains within the process are stopped for + * this callback. + * Return values: + * S_OK : Debugger will handle the ControlC Trap + * S_FALSE : Debugger won't handle the ControlC Trap + */ + HRESULT ControlCTrap([in] ICorDebugProcess *pProcess); + + /* + * NameChange() is called if either an AppDomain's or + * Thread's name changes. + */ + HRESULT NameChange([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread); + + /* + * UpdateModuleSymbols is called when PDB debug symbols are available for an + * in-memory module. This is a debugger's chance to load the symbols + * (using ISymUnmanagedBinder::GetReaderForStream), and bind source-level + * breakpoints for the module. + * + * This callback is no longer dispatched for dynamic modules. Instead, + * debuggers should call ICorDebugModule3::CreateReaderForInMemorySymbols + * to obtain a symbol reader for a dynamic module. + */ + HRESULT UpdateModuleSymbols([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugModule *pModule, + [in] IStream *pSymbolStream); + + + /* + * DEPRECATED + */ + HRESULT EditAndContinueRemap([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugFunction *pFunction, + [in] BOOL fAccurate); + + /* + * BreakpointSetError is called if the CLR was unable to accuratley bind a breakpoint that + * was set before a function was JIT compiled. The given breakpoint will never be hit. The + * debugger should deactivate it and rebind it appropiatley. + */ + HRESULT BreakpointSetError([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugBreakpoint *pBreakpoint, + [in] DWORD dwError); +}; +#pragma warning(pop) + +#pragma warning(push) + +[ + object, + local, + uuid(264EA0FC-2591-49AA-868E-835E6515323F), + pointer_default(unique) +] + +interface ICorDebugManagedCallback3 : IUnknown +{ + /* Callback indicating an enabled custom debugger notification has been + * raised. pThread points to the thread that issued the notification. + * A subsequent call to GetCurrentCustomDebuggerNotification will retrieve the object that was passed to + * System.Diagnostics.Debugger.CustomNotification, whose type will be one + * that has been enabled via SetEnableCustomNotification. + * Note that this will return non-null if and only if we are currently inside a CustomNotification + * callback. + * The debugger can read type-specific parameters from fields of the data + * object, and store responses into fields. + * ICorDebug imposes no policy on the types of notifications or their + * contents, and their semantics are strictly a contract between + * debuggers and applications/frameworks. + */ + HRESULT CustomNotification([in] ICorDebugThread * pThread, [in] ICorDebugAppDomain * pAppDomain); +} + +[ + object, + local, + uuid(322911AE-16A5-49BA-84A3-ED69678138A3), + pointer_default(unique) +] + +interface ICorDebugManagedCallback4 : IUnknown +{ + // + // Callback indicating a garbage collection is about to start. + // + // Parameters + // pProcess - the process that is going to perform garbage collection. + // + // Returns + // S_OK - on success + // + HRESULT BeforeGarbageCollection([in] ICorDebugProcess* pProcess); + + // + // Callback indicating a garbage collection is about to complete. + // + // Parameters + // pProcess - the process that is going to complete garbage collection. + // + // Returns + // S_OK - on success + // + HRESULT AfterGarbageCollection([in] ICorDebugProcess* pProcess); + + // + // Callback indicating a data breakpoint is hit + // + // Parameters + // pProcess - the process that hits the data breakpoint + // pThread - the thread that hits the data breakpoint + // pContext - a pointer to the CONTEXT structure + // contextSize - the size of the CONTEXT structure + // + // Returns + // S_OK - on success + // + HRESULT DataBreakpoint([in] ICorDebugProcess* pProcess, [in] ICorDebugThread* pThread, [in] BYTE* pContext, [in] ULONG32 contextSize); +} + +#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugManagedCallback2 */ + +/* + * ICorDebugManagedCallback2 is a logical extension to ICorDebugManagedCallback. + * This handles new debug events introduced in V2.0. A debugger's callback object + * to ICorDebug::SetManagedHandler must implement this interface if it is debugging v2.0 apps. + */ +[ + object, + local, + uuid(250E5EEA-DB5C-4C76-B6F3-8C46F12E3203), + pointer_default(unique) +] +interface ICorDebugManagedCallback2 : IUnknown +{ + + /* + * FunctionRemapOpportunity is fired whenever execution reaches a sequence point in an older version + * of an edited function. This event gives the debugger an opportunity to remap the IP to its proper + * place in the new version by calling ICorDebugILFrame2::RemapFunction. If the debugger does not call + * RemapFunction before calling Continue, the runtime will continue executing the old code and will + * fire another FunctionRemapOpportunity callback at the next sequence point + */ + HRESULT FunctionRemapOpportunity([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugFunction *pOldFunction, + [in] ICorDebugFunction *pNewFunction, + [in] ULONG32 oldILOffset); + + /* + * CreateConnection is called when a new connection is created. + */ + HRESULT CreateConnection([in] ICorDebugProcess *pProcess, + [in] CONNID dwConnectionId, + [in] WCHAR *pConnName); + + /* + * ChangeConnection is called when a connection's set of tasks changes. + */ + HRESULT ChangeConnection([in] ICorDebugProcess *pProcess, + [in] CONNID dwConnectionId ); + + /* + * DestroyConnection is called when a connection is ended. + */ + HRESULT DestroyConnection([in] ICorDebugProcess *pProcess, + [in] CONNID dwConnectionId ); + + + + + + + typedef enum CorDebugExceptionCallbackType + { + DEBUG_EXCEPTION_FIRST_CHANCE = 1, /* Fired when exception thrown */ + DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2, /* Fired when search reaches first user code */ + DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3, /* Fired if & when search finds a handler */ + DEBUG_EXCEPTION_UNHANDLED = 4 /* Fired if search doesnt find a handler */ + } CorDebugExceptionCallbackType; + + + typedef enum CorDebugExceptionFlags + { + DEBUG_EXCEPTION_NONE = 0, + DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x0001 /* Indicates interceptable exception */ + } CorDebugExceptionFlags; + + + /* + * Exception is called at various points during the search phase of the + * exception-handling process. The exception being processed can be + * retrieved from the ICorDebugThread. + */ + HRESULT Exception( [in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugFrame *pFrame, + [in] ULONG32 nOffset, + [in] CorDebugExceptionCallbackType dwEventType, + [in] DWORD dwFlags ); + + + typedef enum CorDebugExceptionUnwindCallbackType + { + DEBUG_EXCEPTION_UNWIND_BEGIN = 1, /* Fired at the beginning of the unwind */ + DEBUG_EXCEPTION_INTERCEPTED = 2 /* Fired after an exception has been intercepted */ + } CorDebugExceptionUnwindCallbackType; + + + + /* + * For non-intercepted exceptions, ExceptionUnwind is called at the beginning of the second pass + * when we start to unwind the stack. For intercepted exceptions, ExceptionUnwind is called when + * the interception is complete, conceptually at the end of the second pass. + * + * dwFlags is not currently used. + */ + HRESULT ExceptionUnwind( [in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] CorDebugExceptionUnwindCallbackType dwEventType, + [in] DWORD dwFlags ); + + /* + * FunctionRemapComplete is fired whenever execution has completed switching over to a + * new version of an edited function (as requested by a call to ICorDebugILFrame2::RemapFunction). + * At this point (and no sooner) steppers can be added to that new version of the function. + */ + HRESULT FunctionRemapComplete([in] ICorDebugAppDomain *pAppDomain, + [in] ICorDebugThread *pThread, + [in] ICorDebugFunction *pFunction); + + // Notification that an Managed Debug Assistant (MDA) was hit in the debuggee process. + // - MDAs are heuristic warnings and do not require any explicit debugger action (other than continue, of course) for proper functionality. + // - The CLR can change what MDAs are fired (and what data is in any given MDA) at any point. + // - Therefore, debuggers should not build any specific functionality requiring specific MDAs patterns. + // - MDAs may be queued and fired "after the fact". This could happen if the runtime needs to slip from when an + // MDA occurs to get to a safe point for firing it. It also means the runtime reserves the right to fire a bunch of MDAs + // in a single set of callback queue (similar for what we do w/ attach events). + // + // See the MDA documentation for how to enable / disable notifications. + // + // Parameters: + // - pController is the controller object (process or appdomain) that the MDA occurred in. + // Clients should not make any assumption about whether the controller is a process or appdomain (though they can + // always QI to find out). + // Call continue on this to resume the debuggee. + // - pThread - managed thread on which the debug event occurred. If the MDA occurred on an unmanaged thread then + // this will be null. Get the OS thread ID from the MDA object itself. + // - pMDA is an object containing MDA information. + // Suggested usage is that the client does not keep a reference to the MDA object after returning from this callback + // because that lets the CLR quickly recycle the MDA's memory. This could be a performance win if there are + // lots of MDAs firing. + HRESULT MDANotification( + [in] ICorDebugController * pController, + [in] ICorDebugThread *pThread, + [in] ICorDebugMDA * pMDA + ); + +}; +#pragma warning(pop) + +[ + object, + local, + uuid(5263E909-8CB5-11d3-BD2F-0000F80849BD), + pointer_default(unique) +] +interface ICorDebugUnmanagedCallback : IUnknown +{ + /* + * DebugEvent is called when a DEBUG_EVENT is received which is + * not directly related to the Common Language Runtime. + * + * DO NOT USE any parts of the debugging API from the Win32 Event + * Thread. Only ICorDebugController::Continue() can be called on + * the Win32 Event Thread, and only when continuing from an out-of-band + * event. + * + * This callback is an exception to the rules about callbacks. + * When this callback is called, the process will be in the "raw" + * OS debug stopped state. The process will not be synchronized. + * The process will automatically enter the synchronized state when + * necessary to satisfy certain requests for information about + * managed code. (Note that this may result in other nested + * DebugEvent callbacks.) + * + * Call ClearCurrentException on the process to ignore an + * exception event before continuing the process. (Causes + * DBG_CONTINUE to be sent on continue rather than + * DBG_EXCEPTION_NOT_HANDLED) + * Out-of-band Breakpoint and single-step exceptions are automatically cleared. + * + * fOutOfBand will be FALSE if the debugging services support + * interaction with the process's managed state while the process + * is stopped due to this event. fOutOfBand will be TRUE if + * interaction with the process's managed state is impossible until + * the unmanaged event is continued from. + * + * Out-Of-Band events can come at anytime; even when there debuggee appears stopped + * and even when there's already an outstanding inband event. + * + * In v2.0, it is strongly recommended that the debugger just immediately + * continues OOB breakpoint events. The debugger should be using the ICorDebugProcess2 + * SetUnmanagedBreakpoint and ClearUnmanagedBreakpoint APIs to add/remove breakpoints. + * Those APIs will already skip over any OOB breakpoints automatically. Thus the only + * oob breakpoints that get dispatched should be raw breakpoints already in the + * instruction stream (eg, like a call to kernel32!DebugBreak). In these cases, + * just continuing past the breakpoint is the correct thing to do. Do not try to use + * any other portion of the API like ClearCurrentException or Get/SetThreadContext. + * + */ + + HRESULT DebugEvent([in] LPDEBUG_EVENT pDebugEvent, + [in] BOOL fOutOfBand); +}; + +/* ------------------------------------------------------------------------- * + * Debugger interface + * ------------------------------------------------------------------------- */ + + +typedef enum CorDebugCreateProcessFlags +{ + DEBUG_NO_SPECIAL_OPTIONS = 0x0000 +} CorDebugCreateProcessFlags; + + +/* ICorDebugHeapValue::CreateHandle takes a handle flavor. + * A strong handle will keep an object alive while a weak track resurrection + * will not. + */ +typedef enum CorDebugHandleType +{ + HANDLE_STRONG = 1, + HANDLE_WEAK_TRACK_RESURRECTION = 2 +} CorDebugHandleType; + +#pragma warning(push) +#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebug */ +/* + * ICorDebug represents an event processing loop for a debugger process. + * + * The debugger must wait for the ExitProcess callback from all + * processes being debugged before releasing this interface. + * + * The ICorDebug object is the initial object to control all further managed debugging. + * In v1.0 + v1.1, this object was a CoClass created from COM. + * In v2.0, this object is no longer a CoClass and must be created from the function: + * CreateDebuggingInterfaceFromVersion( + * int iDebuggerVersion, // <--- CorDebugVersion_2_0 if Debugger is V2.0 + * LPCWSTR szDebuggeeVersion, // <--- version string of debuggee. Eg, "v1.1.4322" + * IUnknown ** ppCordb + * ) + * declared in mscoree.idl. + * This new creation function is more version-aware. It allows clients to get a + * specific implementation (as specified by szDebuggeeVersion) of ICorDebug, which + * also emulates a specific version of the debugging API (as specified by iDebuggerVersion). + */ +[ + object, + local, + uuid(3d6f5f61-7538-11d3-8d5b-00104b35e7ef), + pointer_default(unique) +] +interface ICorDebug : IUnknown +{ + /* + * The debugger calls this method at creation time to initialize the debugging + * services, and must be called at creation time before any other method on + * ICorDebug is called. + */ + + HRESULT Initialize(); + + /* + * Terminate must be called when the ICorDebug is no longer needed. + * + * NOTE: Terminate should not be called until an ExitProcess callback has + * been received for all processes being debugged. + * + */ + + HRESULT Terminate(); + + /* + * SetManagedHandler should be called at creation time to specify the + * event handler object for managed events. + * + * Returns: + * S_OK on success. + * E_NOINTERFACE - if pCallback does not implement sufficient interfaces + * to receive debug events for the version of the API it requested. + * Eg, if debugging a V2.0 app, pCallback must implement ICorDebugManagedCallback2. + * + */ + + HRESULT SetManagedHandler([in] ICorDebugManagedCallback *pCallback); + + /* + * SetUnmanagedHandler should be called at creation time to specify the + * event handler object for unmanaged events. + * + * This should be set after Initialize and before any calls to CreateProcess or DebugActiveProcess. + * + * However, for legacy purposes, it is not absolutely required to set this until + * before the first native debug event is fired. Specifically, if CreateProcess has the + * CREATE_SUSPENDED flag, native debug events will not be dispatched until the main thread + * is resumed. + * DebugActiveProcess will dispatch native debug events immediately, and so the unmanaged callback + * must be set before DebugActiveProcess is called. + * + * Returns: + * S_OK if callback pointer is successfully updated. + * failure on any failure. + * + */ + + HRESULT SetUnmanagedHandler([in] ICorDebugUnmanagedCallback *pCallback); + + /* + * CreateProcess launches a process under the control of the debugger + * All parameters are the same as the win32 CreateProcess call. + * + * To enable unmanaged (mixed-mode) debugging, pass + * DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS to dwCreationFlags. DEBUG_PROCESS + * alone is not supported. If only managed debugging is desired, do not set + * these flags. + * + * The debugger and debuggee share a single console, then it's possible for + * the debuggee to hold "console locks" and then get stopped at a debug event. + * The debugger will then block trying to use the console. This is only an issue + * when interop debugging and if debugger + debuggee share the console. + * It is recommended to use the CREATE_NEW_CONSOLE flag to avoid this problem. + * + */ + + HRESULT CreateProcess([in] LPCWSTR lpApplicationName, + [in] LPWSTR lpCommandLine, + [in] LPSECURITY_ATTRIBUTES lpProcessAttributes, + [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, + [in] BOOL bInheritHandles, + [in] DWORD dwCreationFlags, + [in] PVOID lpEnvironment, + [in] LPCWSTR lpCurrentDirectory, + [in] LPSTARTUPINFOW lpStartupInfo, + [in] LPPROCESS_INFORMATION lpProcessInformation, + [in] CorDebugCreateProcessFlags debuggingFlags, + [out] ICorDebugProcess **ppProcess); + + /* + * DebugActiveProcess is used to attach to an existing process. + * + * If win32Attach is TRUE, then the debugger becomes the Win32 + * debugger for the process and will begin dispatching the + * unmanaged callbacks. + * + */ + + HRESULT DebugActiveProcess([in] DWORD id, + [in] BOOL win32Attach, + [out] ICorDebugProcess **ppProcess); + + /* + * EnumerateProcesses returns an enum of processes being debugged. + * + */ + + HRESULT EnumerateProcesses([out] ICorDebugProcessEnum **ppProcess); + + /* + * GetProcess returns the ICorDebugProcess with the given OS Id. + */ + + HRESULT GetProcess([in] DWORD dwProcessId, + [out] ICorDebugProcess **ppProcess); + + /* + * CanLaunchOrAttach returns S_OK if the debugging services believe that + * launching a new process or attaching to the given process is possible + * given what it knows about the current machine and runtime configuration. + * + * If you plan to launch with win32 debugging enabled, or to attach with + * win32 debugging enabled then pass in TRUE for win32DebuggineEnabled. + * The answer may be different if this option will be used. + * + * Note: the rest of the API will not stop you from launching or attaching + * to a process anyway. This function is purely informational. + * + * Possible HRESULTs: S_OK, CORDBG_E_DEBUGGING_NOT_POSSIBLE, + * CORDBG_E_KERNEL_DEBUGGER_PRESENT, CORDBG_E_KERNEL_DEBUGGER_ENABLED + * + */ + + HRESULT CanLaunchOrAttach([in] DWORD dwProcessId, + [in] BOOL win32DebuggingEnabled); +}; +#pragma warning(pop) + +/* + * A debugger can implement this interface and pass it to ICorDebugRemote to specify the host name of the + * target machine in Mac remote debugging scenarios. This is only supported on Silverlight. + */ +[ + object, + local, + uuid(C3ED8383-5A49-4cf5-B4B7-01864D9E582D), + pointer_default(unique) +] +interface ICorDebugRemoteTarget : IUnknown +{ + /* + * Return the host name of the target machine. The host name can either be a fully qualified domain name or + * an IPv4 address. If cchHostName is 0 and szHostName is NULL, this function just returns the number of + * characters including the NULL character in the host name. + * + * cchHostName is the number of characters in the buffer szHostName. If this is 0, then szHostName must + * be NULL. If it is not 0, then szHostName must be non-NULL. + * + * pcchHostName returns the number of characters including the NULL character in the host name. This can + * be NULL. + * + * szHostName is the buffer for returning the host name. + */ + + HRESULT GetHostName([in] ULONG32 cchHostName, + [out, annotation("_Out_")] ULONG32 * pcchHostName, + [out, size_is(cchHostName), length_is(*pcchHostName), annotation("_Out_writes_to_opt_(cchHostName, *pcchHostName)")] + WCHAR szHostName[]); +} + +/* + * A debugger can QI for this interface from an ICorDebug interface in order to specify a target machine in + * Mac remote debugging scenarios. This is only supported on Silverlight. + */ +[ + object, + local, + uuid(D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64), + pointer_default(unique) +] +interface ICorDebugRemote : IUnknown +{ + HRESULT CreateProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget, + [in] LPCWSTR lpApplicationName, + [in, annotation("_In_")] LPWSTR lpCommandLine, + [in] LPSECURITY_ATTRIBUTES lpProcessAttributes, + [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, + [in] BOOL bInheritHandles, + [in] DWORD dwCreationFlags, + [in] PVOID lpEnvironment, + [in] LPCWSTR lpCurrentDirectory, + [in] LPSTARTUPINFOW lpStartupInfo, + [in] LPPROCESS_INFORMATION lpProcessInformation, + [in] CorDebugCreateProcessFlags debuggingFlags, + [out] ICorDebugProcess ** ppProcess); + + + HRESULT DebugActiveProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget, + [in] DWORD dwProcessId, + [in] BOOL fWin32Attach, + [out] ICorDebugProcess ** ppProcess); +} + +typedef struct _COR_VERSION +{ + DWORD dwMajor; + DWORD dwMinor; + DWORD dwBuild; + DWORD dwSubBuild; +} COR_VERSION; + + +[ + object, + local, + uuid(ECCCCF2E-B286-4b3e-A983-860A8793D105), + pointer_default(unique) +] +/* + * Sets the maximum version of the runtime supported by the debugger using this + * object. + */ +interface ICorDebug2 : IUnknown +{ + typedef enum CorDebugInterfaceVersion + { + CorDebugInvalidVersion = 0, + CorDebugVersion_1_0 = CorDebugInvalidVersion + 1, + ver_ICorDebugManagedCallback = CorDebugVersion_1_0, + ver_ICorDebugUnmanagedCallback = CorDebugVersion_1_0, + ver_ICorDebug = CorDebugVersion_1_0, + ver_ICorDebugController = CorDebugVersion_1_0, + ver_ICorDebugAppDomain = CorDebugVersion_1_0, + ver_ICorDebugAssembly = CorDebugVersion_1_0, + ver_ICorDebugProcess = CorDebugVersion_1_0, + ver_ICorDebugBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugFunctionBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugModuleBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugValueBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugStepper = CorDebugVersion_1_0, + ver_ICorDebugRegisterSet = CorDebugVersion_1_0, + ver_ICorDebugThread = CorDebugVersion_1_0, + ver_ICorDebugChain = CorDebugVersion_1_0, + ver_ICorDebugFrame = CorDebugVersion_1_0, + ver_ICorDebugILFrame = CorDebugVersion_1_0, + ver_ICorDebugNativeFrame = CorDebugVersion_1_0, + ver_ICorDebugModule = CorDebugVersion_1_0, + ver_ICorDebugFunction = CorDebugVersion_1_0, + ver_ICorDebugCode = CorDebugVersion_1_0, + ver_ICorDebugClass = CorDebugVersion_1_0, + ver_ICorDebugEval = CorDebugVersion_1_0, + ver_ICorDebugValue = CorDebugVersion_1_0, + ver_ICorDebugGenericValue = CorDebugVersion_1_0, + ver_ICorDebugReferenceValue = CorDebugVersion_1_0, + ver_ICorDebugHeapValue = CorDebugVersion_1_0, + ver_ICorDebugObjectValue = CorDebugVersion_1_0, + ver_ICorDebugBoxValue = CorDebugVersion_1_0, + ver_ICorDebugStringValue = CorDebugVersion_1_0, + ver_ICorDebugArrayValue = CorDebugVersion_1_0, + ver_ICorDebugContext = CorDebugVersion_1_0, + ver_ICorDebugEnum = CorDebugVersion_1_0, + ver_ICorDebugObjectEnum = CorDebugVersion_1_0, + ver_ICorDebugBreakpointEnum = CorDebugVersion_1_0, + ver_ICorDebugStepperEnum = CorDebugVersion_1_0, + ver_ICorDebugProcessEnum = CorDebugVersion_1_0, + ver_ICorDebugThreadEnum = CorDebugVersion_1_0, + ver_ICorDebugFrameEnum = CorDebugVersion_1_0, + ver_ICorDebugChainEnum = CorDebugVersion_1_0, + ver_ICorDebugModuleEnum = CorDebugVersion_1_0, + ver_ICorDebugValueEnum = CorDebugVersion_1_0, + ver_ICorDebugCodeEnum = CorDebugVersion_1_0, + ver_ICorDebugTypeEnum = CorDebugVersion_1_0, + ver_ICorDebugErrorInfoEnum = CorDebugVersion_1_0, + ver_ICorDebugAppDomainEnum = CorDebugVersion_1_0, + ver_ICorDebugAssemblyEnum = CorDebugVersion_1_0, + ver_ICorDebugEditAndContinueErrorInfo = CorDebugVersion_1_0, + ver_ICorDebugEditAndContinueSnapshot = CorDebugVersion_1_0, + + CorDebugVersion_1_1 = CorDebugVersion_1_0 + 1, + // no interface definitions in v1.1 + + CorDebugVersion_2_0 = CorDebugVersion_1_1 + 1, + + ver_ICorDebugManagedCallback2 = CorDebugVersion_2_0, + ver_ICorDebugAppDomain2 = CorDebugVersion_2_0, + ver_ICorDebugAssembly2 = CorDebugVersion_2_0, + ver_ICorDebugProcess2 = CorDebugVersion_2_0, + ver_ICorDebugStepper2 = CorDebugVersion_2_0, + ver_ICorDebugRegisterSet2 = CorDebugVersion_2_0, + ver_ICorDebugThread2 = CorDebugVersion_2_0, + ver_ICorDebugILFrame2 = CorDebugVersion_2_0, + ver_ICorDebugInternalFrame = CorDebugVersion_2_0, + ver_ICorDebugModule2 = CorDebugVersion_2_0, + ver_ICorDebugFunction2 = CorDebugVersion_2_0, + ver_ICorDebugCode2 = CorDebugVersion_2_0, + ver_ICorDebugClass2 = CorDebugVersion_2_0, + ver_ICorDebugValue2 = CorDebugVersion_2_0, + ver_ICorDebugEval2 = CorDebugVersion_2_0, + ver_ICorDebugObjectValue2 = CorDebugVersion_2_0, + + // CLR v4 - next major CLR version after CLR v2 + // Includes Silverlight 4 + CorDebugVersion_4_0 = CorDebugVersion_2_0 + 1, + + ver_ICorDebugThread3 = CorDebugVersion_4_0, + ver_ICorDebugThread4 = CorDebugVersion_4_0, + ver_ICorDebugStackWalk = CorDebugVersion_4_0, + ver_ICorDebugNativeFrame2 = CorDebugVersion_4_0, + ver_ICorDebugInternalFrame2 = CorDebugVersion_4_0, + ver_ICorDebugRuntimeUnwindableFrame = CorDebugVersion_4_0, + ver_ICorDebugHeapValue3 = CorDebugVersion_4_0, + ver_ICorDebugBlockingObjectEnum = CorDebugVersion_4_0, + ver_ICorDebugValue3 = CorDebugVersion_4_0, + + CorDebugVersion_4_5 = CorDebugVersion_4_0 + 1, + + ver_ICorDebugComObjectValue = CorDebugVersion_4_5, + ver_ICorDebugAppDomain3 = CorDebugVersion_4_5, + ver_ICorDebugCode3 = CorDebugVersion_4_5, + ver_ICorDebugILFrame3 = CorDebugVersion_4_5, + + CorDebugLatestVersion = CorDebugVersion_4_5 + + } CorDebugInterfaceVersion; + +}; + +/* ------------------------------------------------------------------------- * + * Controller interface + * ------------------------------------------------------------------------- */ + + +/* + * A thread's DebugState determines whether the debugger lets a thread + * run or not. Possible states are: + * + * THREAD_RUN - thread runs freely, unless a debug event occurs + * THREAD_SUSPEND - thread cannot run. + * + * NOTE: We allow for message pumping via a callback provided to the Hosting + * API, thus we don't need an 'interrupted' state here. + */ + +typedef enum CorDebugThreadState +{ + THREAD_RUN, + THREAD_SUSPEND +} CorDebugThreadState; + + +/* + * ICorDebugController represents a scope at which program execution context + * can be controlled. It represents either a process or an app domain. + * + * If this is the controller of a process, this controller affects all + * threads in the process. Otherwise it just affects the threads of + * a particular app domain + */ + +[ + object, + local, + uuid(3d6f5f62-7538-11d3-8d5b-00104b35e7ef), + pointer_default(unique) +] + +interface ICorDebugController : IUnknown +{ + /* + * Stop performs a cooperative stop on all threads running managed + * code in the process. When managed-only debugging, unmanaged threads may continue + * to run (but will be blocked when trying to call managed code). When-interop debugging, + * unmanaged threads will also be stopped. + * The timeout value is currently ignored and treated as INFINTE (-1). + * If the cooperative stop fails due to a deadlock, all threads are suspended (and E_TIMEOUT is returned) + * + * NOTE: This function is the one function in the debugging API + * that is synchronous. When Stop returns with S_OK, the process + * is stopped. (No callback will be given to notify of the stop.) + * The debugger must call Continue when it wishes to allow + * the process to resume running. + * + * The debugger maintains a "stop-counter". When the counter goes to zero, the + * Controller is resumed. Each call to Stop() or each dispatched callback will increment + * the counter. Each call to continue will decrement the counter. + */ + + HRESULT Stop([in] DWORD dwTimeoutIgnored); + + /* + * Continue continues the process after a call to Stop. + * + * Continue continues the process. fIsOutOfBand is set to TRUE + * if continuing from an unmanaged event that was sent with the + * fOutOfBand flag in the unmanaged callback and it is set to + * FALSE if continuing from a managed event or a normal + * unmanaged event. + * + * When doing mixed-mode debugging, Continue cannot be called on + * the Win32 Event Thread unless it is continuing from an + * out-of-band event. + */ + + HRESULT Continue([in] BOOL fIsOutOfBand); + + /* + * IsRunning returns TRUE if the threads in the process are running freely. + * + */ + + HRESULT IsRunning([out] BOOL *pbRunning); + + /* + * HasQueuedCallbacks returns TRUE if there are currently managed + * callbacks which are queued up for the given thread. These + * callbacks will be dispatched one at a time, each time Continue + * is called. + * + * The debugger can check this flag if it wishes to report multiple + * debugging events which occur simultaneously. + * + * If NULL is given for the pThread parameter, HasQueuedCallbacks + * will return TRUE if there are currently managed callbacks + * queued for any thread. + * + * Note that once debug events have been queued, they've already occurred, + * and so the debugger must drain the entire queue to be sure of the state + * of the debuggee. For example, if the queue contains 2 debug events on thread X, + * and the debugger suspends thread X after the 1st debug event and then calls continue, + * the 2nd debug event for thread X will still be dispatched even though the thread + * is suspended. + * + */ + + HRESULT HasQueuedCallbacks([in] ICorDebugThread *pThread, + [out] BOOL *pbQueued); + + /* + * EnumerateThreads returns an enum of all managed threads active in the process. + * A thread is considered Managed threads after the CreateThread callback has been + * dispatched and before the ExitThread callback has been dispatched. + * A managed thread may not necessarily have any managed frames on its stack. + * + * Threads can be enumerated even before the CreateProcess callback. The enumeration + * will naturally be empty. + */ + + HRESULT EnumerateThreads([out] ICorDebugThreadEnum **ppThreads); + + /* + * SetAllThreadsDebugState sets the current debug state of each thread. + * See ICorDebugThread::SetDebugState for details. + * + * The pExceptThisThread parameter allows you to specify one + * thread which is exempted from the debug state change. Pass NULL + * if you want to affect all threads. + * + * This may affect threads not visible via EnumerateThreads, so threads suspended + * via this API will need to be resumed via this API too. + * + */ + + HRESULT SetAllThreadsDebugState([in] CorDebugThreadState state, + [in] ICorDebugThread *pExceptThisThread); + + /* + * Detach detaches the debugger from the process. The process + * continues execution normally. The ICorDebugProcess object is + * no longer valid and no further callbacks will occur. This is + * not implemented for AppDomains (detaching is process-wide). + * + * Note that currently if unmanaged debugging is enabled this call will + * fail due to OS limitations. + * + * Returns S_OK on success. + * + */ + + HRESULT Detach(); + + /* + * Terminate terminates the process (with extreme prejudice, I might add). + * + * NOTE: If the process or appdomain is stopped when Terminate is called, + * the process or appdomain should be continued using Continue so that the + * ExitProcess or ExitAppDomain callback is received. + * + * NOTE: This method is not implemented by an appdomain. + */ + + HRESULT Terminate([in] UINT exitCode); + + /* + * DEPRECATED + */ + + HRESULT CanCommitChanges([in] ULONG cSnapshots, + [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[], + [out] ICorDebugErrorInfoEnum **pError); + + + /* + * DEPRECATED + */ + + HRESULT CommitChanges([in] ULONG cSnapshots, + [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[], + [out] ICorDebugErrorInfoEnum **pError); + +}; + + + +#pragma warning(push) +#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugAppDomain */ +/* ------------------------------------------------------------------------- * + * + * AppDomain interface + * + * ------------------------------------------------------------------------- */ + + +[ + object, + local, + uuid(3d6f5f63-7538-11d3-8d5b-00104b35e7ef), + pointer_default(unique) +] +interface ICorDebugAppDomain : ICorDebugController +{ + /* + * GetProcess returns the process containing the app domain + */ + + HRESULT GetProcess([out] ICorDebugProcess **ppProcess); + + /* + * EnumerateAssemblies enumerates all assemblies in the app domain + * + */ + + HRESULT EnumerateAssemblies([out] ICorDebugAssemblyEnum **ppAssemblies); + + /* + * GetModuleFromMetaDataInterface returns the ICorDebugModule with + * the given metadata interface. + */ + + HRESULT GetModuleFromMetaDataInterface([in] IUnknown *pIMetaData, + [out] ICorDebugModule **ppModule); + + /* + * EnumerateBreakpoints returns an enum (ICorDebugBreakpointEnum) of all active + * breakpoints in the app domain. This includes all types of breakpoints : + * function breakpoints, data breakpoints, etc. + */ + + HRESULT EnumerateBreakpoints([out] ICorDebugBreakpointEnum **ppBreakpoints); + + /* + * EnumerateSteppers returns an enum of all active steppers in the app domain. + * + */ + + HRESULT EnumerateSteppers([out] ICorDebugStepperEnum **ppSteppers); + + /* + * DEPRECATED. Always returns TRUE in V3 (attaching is process-wide). + */ + + HRESULT IsAttached([out] BOOL *pbAttached); + + + /* + * GetName returns the name of the app domain. + * + * Usage pattern: + * *pcchName is always set to the length of pInputString (including NULL) in characters. This lets + * callers know the full size of buffer they'd need to allocate to get the full string. + * + * if (cchName == 0) then we're in "query" mode: + * This fails if szName is non-null or pcchName is null + * Else this function will set pcchName to let the caller know how large of a buffer to allocate + * and return S_OK. + * + * if (cchName != 0) then + * This fails if szName is null. + * Else this copies as much as can fit into szName (it will always null terminate szName) and returns S_OK. + * pcchName can be null. If it's non-null, we set it. + * + * The expected usage pattern is that a client will call once to get the size of a buffer needed for the name, + * allocate the buffer, and then call a 2nd time to fill in the buffer. + * + * The rest of the GetName() functions have the same semantics for the parameters unless otherwise noted. + */ + + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * GetObject returns a reference to the System.AppDomain object which represents this AppDomain + * from within the runtime. + * + * Note: this object is lazily initialized within the runtime and may return NULL if the object + * does not yet exist. This case will return S_FALSE and is not considered a failure. + * + */ + + HRESULT GetObject([out] ICorDebugValue **ppObject); + + /* + * DEPRECATED. This does nothing in V3. Attaching is process-wide. + */ + + HRESULT Attach(); + + /* + * Get the ID of this app domain. The ID will be unique within the + * containing process. + */ + + HRESULT GetID([out] ULONG32 *pId); +}; +#pragma warning(pop) + +[ + object, + local, + uuid(096E81D5-ECDA-4202-83F5-C65980A9EF75), + pointer_default(unique) +] +interface ICorDebugAppDomain2 : IUnknown +{ + /* + * GetArrayOrPointerType returns an array, pointer, byref or function pointer type. + * elementType indicated the kind of type to be created and + * must be one of ELEMENT_TYPE_PTR, ELEMENT_TYPE_BYREF, + * ELEMENT_TYPE_ARRAY or ELEMENT_TYPE_SZARRAY. If used with + * ELEMENT_TYPE_PTR or ELEMENT_TYPE_BYREF then nRank must be zero. + */ + + HRESULT GetArrayOrPointerType([in] CorElementType elementType, + [in] ULONG32 nRank, + [in] ICorDebugType *pTypeArg, + [out] ICorDebugType **ppType); + + /* + * GetFunctionPointerType returns a function pointer type. + * This corresponds to ELEMENT_TYPE_FNPTR. The first type in the type arguments + * must be the return type and the remainder the argument types. + */ + + HRESULT GetFunctionPointerType( [in] ULONG32 nTypeArgs, + [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], + [out] ICorDebugType **ppType); +}; + +[ + object, + local, + uuid(6164D242-1015-4BD6-8CBE-D0DBD4B8275A), + pointer_default(unique) +] +interface ICorDebugGuidToTypeEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of IID / Type pairs from the app domain cache. + * The actual number of frames retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of pairs retrieved is smaller + * than the number of pairs requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + CorDebugGuidToTypeMapping values[], + [out] ULONG* pceltFetched); +}; + +[ + object, + local, + uuid(8CB96A16-B588-42E2-B71C-DD849FC2ECCC), + pointer_default(unique) +] +interface ICorDebugAppDomain3 : IUnknown +{ + /* + * Returns an enumeration of types corresponding to the IIDs passed in + * guidsToResolve. The enumeration will have the same cReqTypes elements + * with NULL values corresponding to unknown IIDs. + */ + HRESULT GetCachedWinRTTypesForIIDs( + [in] ULONG32 cReqTypes, + [in, size_is(cReqTypes)] GUID * iidsToResolve, + [out] ICorDebugTypeEnum ** ppTypesEnum); + + /* + * Returns an enumeration of IID / Type pairs. This is the exhaustive + * list of pairs as they were cached in the current app domain. + */ + HRESULT GetCachedWinRTTypes( + [out] ICorDebugGuidToTypeEnum ** ppGuidToTypeEnum); +}; + +[ + object, + local, + uuid(FB99CC40-83BE-4724-AB3B-768E796EBAC2), + pointer_default(unique) +] +interface ICorDebugAppDomain4 : IUnknown +{ + /* + * gives back the managed object for a given CCW pointer + */ + HRESULT GetObjectForCCW([in]CORDB_ADDRESS ccwPointer, [out]ICorDebugValue **ppManagedObject); +}; + +#pragma warning(push) +#pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugAssembly */ + +/* ------------------------------------------------------------------------- * + * Assembly interface + * An ICorDebugAssembly instance corresponds to a a managed assembly loaded + * into a specific AppDomain in the CLR. For assemblies shared between multiple + * AppDomains (eg. mscorlib), there will be a separate ICorDebugAssembly instance + * per AppDomain in which it is used. + * ------------------------------------------------------------------------- */ +[ + object, + local, + uuid(df59507c-d47a-459e-bce2-6427eac8fd06), + pointer_default(unique) +] + +interface ICorDebugAssembly : IUnknown +{ + /* + * GetProcess returns the process containing the assembly + */ + + HRESULT GetProcess([out] ICorDebugProcess **ppProcess); + + /* + * GetAppDomain returns the app domain containing the assembly. + */ + + HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain); + + /* + * EnumerateModules enumerates all modules in the assembly + * + */ + + HRESULT EnumerateModules([out] ICorDebugModuleEnum **ppModules); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetCodeBase([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * GetName returns the full path and filename of the assembly. + * If the assembly has no filename (i.e. it is in-memory only), + * S_FALSE is returned, and a fabricated string is stored into szName. + */ + + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); +}; +#pragma warning(pop) + +[ + object, + local, + uuid(426d1f9e-6dd4-44c8-aec7-26cdbaf4e398), + pointer_default(unique) +] +interface ICorDebugAssembly2 : IUnknown +{ + /* + * IsFullyTrusted sets a flag indicating whether the assembly has + * been granted full trust by the runtime security system. + * This may return CORDBG_E_NOTREADY if the security policy for + * the assembly has not yet been resolved (eg. no code in the + * assembly has been run yet). + */ + HRESULT IsFullyTrusted([out] BOOL *pbFullyTrusted); +}; + +[ + object, + local, + uuid(76361AB2-8C86-4FE9-96F2-F73D8843570A), + pointer_default(unique) +] +interface ICorDebugAssembly3 : IUnknown +{ + /* + * If this assembly has been merged with others inside a single container assembly, + * this gives back the container. Otherwise *ppAssembly = NULL and the result is S_FALSE. + */ + HRESULT GetContainerAssembly(ICorDebugAssembly **ppAssembly); + + /* + * Gets an enumeration for all the assemblies contained within this assembly + * If the assembly isn't a container, the result is S_FALSE and the enumeration + * will be empty. Symbols are needed to compute this result; if they aren't + * present an error will be returned and no enumeration provided. + */ + HRESULT EnumerateContainedAssemblies(ICorDebugAssemblyEnum **ppAssemblies); +}; + + +/* ------------------------------------------------------------------------- * + * Heap enumeration interface + * ------------------------------------------------------------------------- */ + +cpp_quote("#ifndef _DEF_COR_TYPEID_") +cpp_quote("#define _DEF_COR_TYPEID_") +typedef struct COR_TYPEID +{ + UINT64 token1; + UINT64 token2; +} COR_TYPEID; +cpp_quote("#endif // _DEF_COR_TYPEID_") + +typedef struct _COR_HEAPOBJECT +{ + CORDB_ADDRESS address; // The address (in memory) of the object. + ULONG64 size; // The total size of the object. + COR_TYPEID type; // The fully instantiated type of the object. +} COR_HEAPOBJECT; + +[ + object, + local, + uuid(76D7DAB8-D044-11DF-9A15-7E29DFD72085), + pointer_default(unique) +] +interface ICorDebugHeapEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of objects in the enumeration. + * The actual number of objects retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of objects retrieved is smaller + * than the number of objects requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] COR_HEAPOBJECT objects[], + [out] ULONG *pceltFetched); +}; + + +/* ------------------------------------------------------------------------- * + * Segment enumeration interface + * ------------------------------------------------------------------------- */ + +typedef enum CorDebugGenerationTypes +{ + CorDebug_Gen0 = 0, + CorDebug_Gen1 = 1, + CorDebug_Gen2 = 2, + CorDebug_LOH = 3, +} CorDebugGenerationTypes; + +typedef struct _COR_SEGMENT +{ + CORDB_ADDRESS start; // The start address of the segment. + CORDB_ADDRESS end; // The end address of the segment. + CorDebugGenerationTypes type; // The generation of the segment. + ULONG heap; // The heap the segment resides in. +} COR_SEGMENT; + + +typedef enum CorDebugGCType +{ + CorDebugWorkstationGC, + CorDebugServerGC +} CorDebugGCType; + +typedef struct _COR_HEAPINFO +{ + BOOL areGCStructuresValid; // TRUE if it's ok to walk the heap, FALSE otherwise. + DWORD pointerSize; // The size of pointers on the target architecture in bytes. + DWORD numHeaps; // The number of logical GC heaps in the process. + BOOL concurrent; // Is the GC concurrent? + CorDebugGCType gcType; // Workstation or Server? +} COR_HEAPINFO; + +[ + object, + local, + uuid(A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085), + pointer_default(unique) +] +interface ICorDebugHeapSegmentEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of objects in the enumeration. + * The actual number of objects retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of objects retrieved is smaller + * than the number of objects requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] COR_SEGMENT segments[], + [out] ULONG *pceltFetched); +}; + + +/* ------------------------------------------------------------------------- * + * Reference enumeration interface + * ------------------------------------------------------------------------- */ +typedef enum CorGCReferenceType +{ + CorHandleStrong = 1<<0, + CorHandleStrongPinning = 1<<1, + CorHandleWeakShort = 1<<2, + CorHandleWeakLong = 1<<3, + CorHandleWeakRefCount = 1<<4, + CorHandleStrongRefCount = 1<<5, + CorHandleStrongDependent = 1<<6, + CorHandleStrongAsyncPinned = 1<<7, + CorHandleStrongSizedByref = 1<<8, + CorHandleWeakWinRT = 1<<9, + + CorReferenceStack = 0x80000001, + CorReferenceFinalizer = 80000002, + + // Used for EnumHandles + CorHandleStrongOnly = 0x1E3, + CorHandleWeakOnly = 0x21C, + CorHandleAll = 0x7FFFFFFF +} CorGCReferenceType; + + +cpp_quote("#ifndef _DEF_COR_GC_REFERENCE_") +cpp_quote("#define _DEF_COR_GC_REFERENCE_") +typedef struct COR_GC_REFERENCE +{ + ICorDebugAppDomain *Domain; // The AppDomain of the handle/object, may be null. + ICorDebugValue *Location; // A reference to the object + CorGCReferenceType Type; // Where the root came from. + + /* + DependentSource - for HandleDependent + RefCount - for HandleStrongRefCount + Size - for HandleSizedByref + */ + UINT64 ExtraData; +} COR_GC_REFERENCE; + +cpp_quote("#endif // _DEF_COR_GC_REFERENCE_") + +[ + object, + local, + uuid(7F3C24D3-7E1D-4245-AC3A-F72F8859C80C), + pointer_default(unique) +] +interface ICorDebugGCReferenceEnum : ICorDebugEnum +{ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] COR_GC_REFERENCE roots[], + [out] ULONG *pceltFetched); +} + +cpp_quote("#ifndef _DEF_COR_ARRAY_LAYOUT_") +cpp_quote("#define _DEF_COR_ARRAY_LAYOUT_") +typedef struct COR_ARRAY_LAYOUT +{ + COR_TYPEID componentID; // The type of objects the array contains + + CorElementType componentType; // Whether the component itself is a GC reference, value class, or primitive + + ULONG32 firstElementOffset; // The offset to the first element + ULONG32 elementSize; // The size of each element + ULONG32 countOffset; // The offset to the number of elements in the array. + + // For multidimensional arrays (works with normal arrays too). + ULONG32 rankSize; // The size of the rank + ULONG32 numRanks; // The number of ranks in the array (1 for array, N for multidimensional array) + ULONG32 rankOffset; // The offset at which the ranks start +} COR_ARRAY_LAYOUT; + +cpp_quote("#endif // _DEF_COR_ARRAY_LAYOUT_") + + +cpp_quote("#ifndef _DEF_COR_TYPE_LAYOUT_") +cpp_quote("#define _DEF_COR_TYPE_LAYOUT_") +typedef struct COR_TYPE_LAYOUT +{ + COR_TYPEID parentID; + ULONG32 objectSize; + ULONG32 numFields; + ULONG32 boxOffset; + CorElementType type; +} COR_TYPE_LAYOUT; +cpp_quote("#endif // _DEF_COR_TYPE_LAYOUT_") + +cpp_quote("#ifndef _DEF_COR_FIELD_") +cpp_quote("#define _DEF_COR_FIELD_") +typedef struct COR_FIELD +{ + mdFieldDef token; // FieldDef token to get the field info + ULONG32 offset; // Offset in object of data. + COR_TYPEID id; // TYPEID of the field + + CorElementType fieldType; +} COR_FIELD; +cpp_quote("#endif // _DEF_COR_FIELD_") + + + + +/* ------------------------------------------------------------------------- * + * Process interface + * ------------------------------------------------------------------------- */ + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugProcess */ + +/* + * ICorDebugProcess represents a process running some managed code. + */ + +[ + object, + local, + uuid(3d6f5f64-7538-11d3-8d5b-00104b35e7ef), + pointer_default(unique) +] +interface ICorDebugProcess : ICorDebugController +{ + /* + * GetID returns the OS ID of the process. + */ + + HRESULT GetID([out] DWORD *pdwProcessId); + + /* + * GetHandle returns a handle to the process. This handle is owned + * by the debugging API; the debugger should duplicate it before + * using it. + */ + + HRESULT GetHandle([out] HPROCESS *phProcessHandle); + + /* + * GetThread returns the ICorDebugThread with the given OS Id. + * + * Note that eventually there will not be a one to one correspondence + * between OS threads and runtime threads, so this entry point will + * go away. + */ + + HRESULT GetThread([in] DWORD dwThreadId, [out] ICorDebugThread **ppThread); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT EnumerateObjects([out] ICorDebugObjectEnum **ppObjects); + + /* + * IsTransitionStub tests whether an address is inside of a transition stub + * which will cause a transition to managed code. This can be used by + * unmanaged stepping code to decide when to return stepping control to + * the managed stepper. + * + * Note that, tentatively, these stubs may also be able to be identified + * ahead of time by looking at information in the PE file. + * + */ + + HRESULT IsTransitionStub([in] CORDB_ADDRESS address, + [out] BOOL *pbTransitionStub); + + + /* + * IsOSSuspended returns whether or not the thread has been + * suspended as part of the debugger logic of stopping the process. + * (that is, it has had its Win32 suspend count incremented by + * one.) The debugger UI may want to take this into account if + * it shows the user the OS suspend count of the thread. + * + * This function only makes sense in the context of + * unmanaged debugging - during managed debugging threads are not + * OS suspended. (They are cooperatively suspended.) + */ + + HRESULT IsOSSuspended([in] DWORD threadID, [out] BOOL *pbSuspended); + + /* + * GetThreadContext returns the context for the given thread. The + * debugger should call this function rather than the Win32 + * GetThreadContext, because the thread may actually be in a "hijacked" + * state where its context has been temporarily changed. + * + * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet + * for threads in managed code. + * + * The data returned is a CONTEXT structure for the current platform. + * (CONTEXT is typically declared in winnt.h) Just as with a call + * to Win32's GetThreadContext, the caller should initialize the + * CONTEXT struct before calling. + * + */ + + HRESULT GetThreadContext([in] DWORD threadID, + [in] ULONG32 contextSize, + [in, out, length_is(contextSize), + size_is(contextSize)] BYTE context[]); + + /* + * SetThreadContext sets the context for the given thread. The + * debugger should call this function rather than the Win32 + * SetThreadContext, because the thread may actually be in a "hijacked" + * state where its context has been temporarily changed. + * + * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet + * for threads in managed code. + * + * This should never be needed to modify the context of a thread during an oob-debug + * event. + * + * The data passed should be a CONTEXT structure for the current platform. + * (CONTEXT is typically declared in winnt.h) + * + * This is a dangerous call which can corrupt the runtime if used + * improperly. + * + */ + + HRESULT SetThreadContext([in] DWORD threadID, + [in] ULONG32 contextSize, + [in, length_is(contextSize), + size_is(contextSize)] BYTE context[]); + + /* + * ReadMemory reads memory from the process. + * This is primarily intended to be used by interop-debugging to inspect memory + * regions used by the unmanaged portion of the debuggee. + * + * This can also be used to read IL and native jitted code. + * Any managed breakpoints will be automatically stripped from the returned buffer. + * No adjustments will be made for Native breakpoints set by ICorDebugProcess2::SetUnmanagedBreakpoint + * + * No caching of process memory is peformed. + * These parameters have the same semantics as kernel32!ReadProcessMemory. + * The entire range must be read for the function to return success. + */ + + HRESULT ReadMemory([in] CORDB_ADDRESS address, [in] DWORD size, + [out, size_is(size), length_is(size)] BYTE buffer[], + [out] SIZE_T *read); + + /* + * WriteMemory writes memory in the process. + * In v2.0, Native debuggers should *not* use this to inject breakpoints + * into the instruction stream. Use ICorDebugProcess2::SetUnamangedBreakpoint + * instead. + * + * This is a dangerous call which can corrupt the runtime if used + * improperly. It is highly recommended that this is only used outside + * of managed code. + * + * These parameters have the same semantics as kernel32!WriteProcessMemory. + */ + + HRESULT WriteMemory([in] CORDB_ADDRESS address, [in] DWORD size, + [in, size_is(size)] BYTE buffer[], + [out]SIZE_T *written); + + + /* + * ClearCurrentException clears the current unmanaged exception on + * the given thread. Call this before calling Continue when a + * thread has reported an unmanaged exception that should be + * ignored by the debuggee. + * + * This will clear both the outstanding IB and OOB events on the given thread. + * Out-of-band Breakpoint and single-step exceptions are automatically cleared. + * + * See ICorDebugThread2::InterceptCurrentException for continuing managed exceptions. + * + */ + + HRESULT ClearCurrentException([in] DWORD threadID); + + /* + * EnableLogMessages enables/disables sending of log messages to the + * debugger for logging. + * This is only valid after the CreateProcess callback. + * + */ + + HRESULT EnableLogMessages([in]BOOL fOnOff); + + /* + * ModifyLogSwitch modifies the specified switch's severity level. + * This is only valid after the CreateProcess callback. + * + */ + HRESULT ModifyLogSwitch([in, annotation("_In_")] WCHAR *pLogSwitchName, + [in]LONG lLevel); + + /* + * EnumerateAppDomains enumerates all app domains in the process. + * This can be used before the CreateProcess callback. + * + */ + + HRESULT EnumerateAppDomains([out] ICorDebugAppDomainEnum **ppAppDomains); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetObject([out] ICorDebugValue **ppObject); + + /* + * DEPRECATED + */ + + HRESULT ThreadForFiberCookie([in] DWORD fiberCookie, + [out] ICorDebugThread **ppThread); + + /* + * Returns the OS thread id of the debugger's internal helper thread. + * During managed/unmanaged debugging, it is the debugger's + * responsibility to ensure that the thread with this ID remains running + * if it hits a breakpoint placed by the debugger. A debugger may also + * wish to hide this thread from the user. + * + * If there is no helper thread in the process yet, then this method + * will return zero as the thread id. + * + * Note: you cannot cache this value. The ID of the helper thread may + * change over time, so this value must be re-queried at every stopping + * event. + * + * Note: this value will be correct on every unmanaged CreateThread event. + * This will allow a debugger to determine the TID of the helper thread + * and hide it from the user. A thread identified as a helper thread during + * an unmanaged CreateThread event will never run managed user code. + */ + + HRESULT GetHelperThreadID([out] DWORD *pThreadID); +}; +#pragma warning(pop) + +[ + object, + local, + uuid(AD1B3588-0EF0-4744-A496-AA09A9F80371), + pointer_default(unique) +] +interface ICorDebugProcess2 : IUnknown +{ + + /* + * Return a ICorDebugThread2 interface given a TASKID + * Host can set TASKID using ICLRTask::SetTaskIdentifier + */ + HRESULT GetThreadForTaskID( + [in] TASKID taskid, + [out] ICorDebugThread2 **ppThread); + + + /* + * Returns the version of the runtime the debugee process is running. + */ + HRESULT GetVersion([out] COR_VERSION* version); + + /* + * Set an unmanaged breakpoint at the given native address. If the address is within + * the runtime, the breakpoint will be ignored. + * This allows the CLR to avoid dispatching out-of-band breakpoints for breakpoints + * set by the debugger. + * buffer[] returns the opcode at the address that is replaced by the breakpoint. + */ + + HRESULT SetUnmanagedBreakpoint([in] CORDB_ADDRESS address, + [in] ULONG32 bufsize, + [out, size_is(bufsize), length_is(*bufLen)] BYTE buffer[], + [out] ULONG32 * bufLen); + + /* + * Remove a breakpoint set by SetUnmanagedBreakpoint. + */ + HRESULT ClearUnmanagedBreakpoint([in] CORDB_ADDRESS address); + + + /* + * SetDesiredNGENCompilerFlags specifies the set of flags that must be set in a pre-JITted + * image in order for the runtime to load that image into this app domain. If no such image exists, + * the runtime will load the IL and JIT instead. The flags set by this function are just used to select the + * correct pre-JITted image; if no suitable image is found the debugger will still need to use + * ICorDebugModule2::SetJITCompilerFlags to set the flags as desired for JIT. + * + * This function must be called during the CreateProcess callback. + * Attempts to call it after this callback has been delivered will fail. + */ + HRESULT SetDesiredNGENCompilerFlags( [in] DWORD pdwFlags ); + + /* + * GetDesiredNGENCompilerFlags gets the set of flags that must be set in a pre-JITted image in order + * for the runtime to load that image into this process. + */ + HRESULT GetDesiredNGENCompilerFlags( [out] DWORD *pdwFlags ); + + + /* + * Gets an ICorDebugReferenceValue object from a raw GC handle value. + * + * handle is the IntPtr within a GCHandle. Do not confuse + * this with a GC reference value. This is a potentially dangerous API and may + * corrupt both the debugger and debuggee if a bogus handle is passed in. + * This API does not necessarily validate that the handle is valid. + * + * The ICorDebugReferenceValue will behave much like a normal reference. It will + * be neutered on the next continue; the lifetime of the target object will + * not be affected by the existence of the ReferenceValue. + */ + HRESULT GetReferenceValueFromGCHandle( [in] UINT_PTR handle, + [out] ICorDebugReferenceValue **pOutValue); + +}; + + +[ + object, + local, + uuid(2EE06488-C0D4-42B1-B26D-F3795EF606FB), + pointer_default(unique) +] + +interface ICorDebugProcess3 : IUnknown +{ + /* Enables (or disables) custom debugger notifications of a specified + * type (which implements ICustomDebuggerNotification). + * When this has been enabled, calls to + * System.Diagnostics.Debugger.CustomNotification with a data argument + * of the specified class will trigger a CustomNotification callback. + * Notifications are disabled by default and the debugger must opt-into + * any notification types it knows of and wishes to handle. + * Since ICorDebugClass is scoped by appdomains, the debugger needs to + * call this API for every appdomain in the process if it's interested in + * receiving the notification across the entire process. + */ + + HRESULT SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable); +} + +[ + object, + local, + uuid(21e9d9c0-fcb8-11df-8cff-0800200c9a66), + pointer_default(unique) +] +interface ICorDebugProcess5 : IUnknown +{ + HRESULT GetGCHeapInformation([out] COR_HEAPINFO *pHeapInfo); + HRESULT EnumerateHeap([out] ICorDebugHeapEnum **ppObjects); + HRESULT EnumerateHeapRegions([out] ICorDebugHeapSegmentEnum **ppRegions); + HRESULT GetObject([in] CORDB_ADDRESS addr, [out] ICorDebugObjectValue **pObject); + HRESULT EnumerateGCReferences([in] BOOL enumerateWeakReferences, [out] ICorDebugGCReferenceEnum **ppEnum); + HRESULT EnumerateHandles([in] CorGCReferenceType types, [out] ICorDebugGCReferenceEnum **ppEnum); + + HRESULT GetTypeID([in] CORDB_ADDRESS obj, [out] COR_TYPEID *pId); + HRESULT GetTypeForTypeID([in] COR_TYPEID id, [out] ICorDebugType **ppType); + + HRESULT GetArrayLayout([in] COR_TYPEID id, [out] COR_ARRAY_LAYOUT *pLayout); + HRESULT GetTypeLayout([in] COR_TYPEID id, [out] COR_TYPE_LAYOUT *pLayout); + HRESULT GetTypeFields([in] COR_TYPEID id, ULONG32 celt, COR_FIELD fields[], ULONG32 *pceltNeeded); + + /* + * Enables the specified policy. + */ + HRESULT EnableNGENPolicy([in] CorDebugNGENPolicy ePolicy); +} + + +// Describes formats of pRecord byte blob in DecodeEvent. +// This is dependent on the target architecture. +typedef enum CorDebugRecordFormat +{ + FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, + FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2, +} CorDebugRecordFormat; + +// dwFlags in DecodeEvent is dependent on the target architecture. +// Definition of DecodeEvent flags on Windows. +typedef enum CorDebugDecodeEventFlagsWindows +{ + IS_FIRST_CHANCE = 1, +} CorDebugDecodeEventFlagsWindows; + +// Possible events which can be decoded in DecodeEvent +typedef enum CorDebugDebugEventKind +{ + DEBUG_EVENT_KIND_MODULE_LOADED = 1, + DEBUG_EVENT_KIND_MODULE_UNLOADED = 2, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_FIRST_CHANCE = 3, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_USER_FIRST_CHANCE = 4, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_CATCH_HANDLER_FOUND = 5, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 +} CorDebugDebugEventKind; + +// Describes what amount of cached data must be discarded based on changes to the +// process +typedef enum CorDebugStateChange +{ + PROCESS_RUNNING = 0x0000001, // The process reached a new memory state via + // forward execution. + FLUSH_ALL = 0x0000002, // The process' memory might be arbitrarily + // different than it was before. +} CorDebugStateChange; + +// Base interface from which all ICorDebug debug events derive +[ + object, + local, + uuid(41BD395D-DE99-48F1-BF7A-CC0F44A6D281), + pointer_default(unique) +] +interface ICorDebugDebugEvent : IUnknown +{ + /* + * Quickly determines what kind of event this is. Based on the answer you + * you can QI to get a more precise debug event interface with additional data + * available. + */ + HRESULT GetEventKind([out]CorDebugDebugEventKind *pDebugEventKind); + + /* + * Gets the thread on which the event occurred + */ + HRESULT GetThread([out]ICorDebugThread **ppThread); +} + +typedef enum CorDebugCodeInvokeKind +{ + CODE_INVOKE_KIND_NONE, // if there is any managed code invoked by this method, it will have + // have to be located by explicit events/breakpoints later + // OR we may just miss some of the managed code this method calls + // because there is no easy way to stop on it + // OR the method may never invoke managed code + CODE_INVOKE_KIND_RETURN, // This method will invoke managed code via a return instruction, + // Stepping out should arrive at the next managed code + CODE_INVOKE_KIND_TAILCALL, // This method will invoke managed code via a tail-call. Single-stepping + // + stepping over any call instructions should arrive at managed code +} CorDebugCodeInvokeKind; + +typedef enum CorDebugCodeInvokePurpose +{ + CODE_INVOKE_PURPOSE_NONE, + CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION, // The managed code will run any managed entrypoint + // such as a reverse p-invoke. Any more detailed purpose + // is unknown by the runtime. + CODE_INVOKE_PURPOSE_CLASS_INIT, // The managed code will run a static constructor + CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH, // The managed code will run the implementation for + // some interface method that was called +} CorDebugCodeInvokePurpose; + +[ + object, + local, + uuid(11588775-7205-4CEB-A41A-93753C3153E9), + pointer_default(unique) +] +interface ICorDebugProcess6 : IUnknown +{ + //Decodes managed debug events which have been encapsulated in the payload of + //specially crafted native exception debug events + HRESULT DecodeEvent( + [in, length_is(countBytes), size_is(countBytes)] const BYTE pRecord[], + [in] DWORD countBytes, + [in] CorDebugRecordFormat format, + [in] DWORD dwFlags, + [in] DWORD dwThreadId, + [out] ICorDebugDebugEvent **ppEvent); + + // Debugger calls this to notify ICorDebug that the process is running. + // + // Notes: + // ProcessStateChanged(PROCESS_RUNNING) has similar semantics to + // ICorDebugProcess::Continue(); + HRESULT ProcessStateChanged([in] CorDebugStateChange change); + + // Get information about managed code at codeAddress + HRESULT GetCode([in] CORDB_ADDRESS codeAddress, [out] ICorDebugCode **ppCode); + + // Virtual module splitting causes ICorDebug to recognize modules that were + // merged together during the build process and present them as a group of separate + // modules rather than a single large module. Doing this changes the behavior of + // various ICorDebug APIs described below. + // + // Terminology + // The aggregate modules are called containers, the modules inside are called + // sub-modules or virtual modules. Both container modules and sub-modules are + // represented with the ICorDebugModule interface, however the behavior of the + // interface is slightly different in each case, as described below. + // In addition there may still be modules loaded that weren't merged during build. + // These modules, called regular modules, are neither container modules nor + // sub-modules. + // + // Modules and assemblies + // Multi-module assemblies are not supported for assembly merging scenarios + // so module and assembly are exactly 1:1. Each ICorDebugModule, regardless of + // whether it represents a container module or a sub-module, has a corresponding + // ICorDebugAssembly. ICorDebugModule.GetAssembly() converts from the module to the + // assembly. To map the other direction, ICorDebugAssembly.EnumerateModules() will + // enumerate only 1 module. Because assembly and module form a tightly coupled pair + // in this case, the terms assembly and module become largely interchangeable. + // + // Differences in behavior for container modules vs. sub-modules + // Container modules: + // -have metadata for all of the constituent sub-modules merged together + // -type names may be mangled + // -ICorDebugModule.GetName() will return the path to an on-disk module + // -ICorDebugModule.GetSize() returns the size of that image. + // -ICorDebugAssembly3.EnumerateContainedAssemblies will list the sub-modules + // -ICorDebugAssembly3.GetContainerAssembly returns S_FALSE + // Sub-modules: + // -have a reduced set of metadata that corresponds only to the original + // assembly that was merged in. + // -The metadata names have no mangling. + // -Metadata tokens are unlikely to match with the tokens in the original + // assembly before it was merged in the build process + // -ICorDebugModule.GetName() returns the assembly name (not a file path) + // -ICorDebug.GetSize() returns the original unmerged image size. + // -ICorDebugModule3.EnumerateContainedAssemblies will return S_FALSE + // -ICorDebugAssembly3.GetContainerAssembly will return the containing module + // + // Interfaces retrieved from modules + // There are a variety of interfaces that can be created from modules, such as + // ICorDebugModule.GetClassFromToken() -> ICorDebugClass + // These objects are always cached by ICorDebug, and they will have the same pointer + // identity regardless of whether they were created/queried from the container module + // or a sub-module. The sub-module serves as a filtered view of these cached + // objects, not a separate cache with its own copies. + // + // Enabling Virtual Module Splitting has the following effects elsewhere in the API: + // ICorDebugFunction.GetModule + // Disabled - Returns the container module this function was merged into + // Enabled - Returns the sub-module this function was originally defined in + // ICorDebugClass.GetModule + // Disabled - Returns the container module this class was merged into + // Enabled - Returns the sub-module this class was originally defined in + // ICorDebugModuleDebugEvent.GetModule + // Enabled OR Disabled - Returns the container module that was loaded. + // Sub-modules are not given load events regardless of this + // setting. + // ICorDebugAppDomain.EnumerateAssemblies + // Disabled - Returns a list of container assemblies + regular assemblies + // (no sub-assemblies are shown) + // Enabled - Returns the list of sub-assemblies + regular assemblies + // (no container assemblies are shown). + // Note: If any container assembly is missing symbols, none of its + // sub-assemblies will be enumerated. If any regular assembly is + // missing symbols it may or may not be enumerated. + // ICorDebugCode.GetCode (when refering to IL code only) + // Disabled - Returns the IL in the post-merge assembly image. + // Enabled - Returns IL that would be valid in a pre-merge assembly image. Specifically + // any inline metadata tokens will correctly be TypeRef or MemberRef tokens + // when the types being refered to are not defined in the virtual module + // containing the IL. These TypeRefs/MemberRefs can be looked up in the + // IMetaDataImport for the corresponding virtual ICorDebugModule. + // + // This setting can be changed at any time. It does not incur any stateful functional + // changes in ICorDebug, beyond altering the behavior of the above APIs at the time they are + // called. Using virtual modules does incur a performance penalty for all the above + // APIs. Additionally the virtualized metadata may do significant in-memory caching required + // to correctly implement the IMetaDataImport APIs, and these caches may be retained + // even after virtual module splitting has been turned off. + HRESULT EnableVirtualModuleSplitting(BOOL enableSplitting); + + // Changes internal state of the debuggee so that the System.Debugger.IsAttached API in the BCL + // returns true. + // + // Returns + // S_OK - debuggee is succesfully updated + // CORDBG_E_MODULE_NOT_LOADED - assembly containing System.Debugger.IsAttached API is not loaded + // or some other error is preventing it from being recognized such as missing metadata. This error + // is common and benign - it is recommended to try the call again when future assemblies load. + // + // other misc failing HRESULTs are possible, but likely indicate misbehaving debugger or compiler + // components + HRESULT MarkDebuggerAttached(BOOL fIsAttached); + + // Provides information on runtime exported functions to help step to managed code + // + // Parameters + // pszExportName - The name of a runtime export function as written in the PE export table + // invokeKind - [out] A description of how the exported function will invoke managed code + // invokePurpose - [out] A description of why the exported function will call managed code + // + // Returns + // S_OK - on success + // E_POINTER - pInvokeKind or pInvokePurpose is NULL + // Other failing HRESULTs as appropriate + // + HRESULT GetExportStepInfo([in]LPCWSTR pszExportName, [out]CorDebugCodeInvokeKind* pInvokeKind, [out]CorDebugCodeInvokePurpose* pInvokePurpose); +} + +typedef enum WriteableMetadataUpdateMode +{ + LegacyCompatPolicy, + AlwaysShowUpdates +} WriteableMetadataUpdateMode; + + +[ + object, + local, + uuid(9B2C54E4-119F-4D6F-B402-527603266D69), + pointer_default(unique) +] +interface ICorDebugProcess7 : IUnknown +{ + // Configures how the debugger handles metadata that has been updated in-memory + // within the target process. These updates could come from EnC, a profiler, + // or Reflection.Emit + HRESULT SetWriteableMetadataUpdateMode(WriteableMetadataUpdateMode flags); +} + +[ + object, + local, + uuid(2E6F28C1-85EB-4141-80AD-0A90944B9639), + pointer_default(unique) +] +interface ICorDebugProcess8 : IUnknown +{ + /* + * EnableExceptionCallbacksOutsideOfMyCode enables/disables certain types of exception callback to ICorDebugManagedCallback2. + * If the flag is FALSE: + * 1) DEBUG_EXCEPTION_FIRST_CHANCE callbacks won't called in the debugger. + * 2) DEBUG_EXCEPTION_CATCH_HANDLER_FOUND callbacks won't be called if an exception never escapes into user code. + * (i.e. a path from an exception origin to an exception handler has no methods marked as JMC) + * + * Default value of this flag is TRUE. + */ + HRESULT EnableExceptionCallbacksOutsideOfMyCode([in] BOOL enableExceptionsOutsideOfJMC); +} + +[ + object, + local, + uuid(8F378F6F-1017-4461-9890-ECF64C54079F), + pointer_default(unique) +] +interface ICorDebugProcess10 : IUnknown +{ + // + // Enable or disable the GC notification events. The GC notification events are turned off by default + // They will be delivered through ICorDebugManagedCallback4 + // + // Parameters + // fEnable - true to enable the events, false to disable + // + // Returns + // S_OK - on success + // + HRESULT EnableGCNotificationEvents(BOOL fEnable); +} + +// Event types MODULE_LOADED and MODULE_UNLOADED implement this interface +[ + object, + local, + uuid(51A15E8D-9FFF-4864-9B87-F4FBDEA747A2), + pointer_default(unique) +] +interface ICorDebugModuleDebugEvent : ICorDebugDebugEvent +{ + /* + * Gets the merged module that was just loaded or unloaded. Use + * ICorDebugDebugEvent.GetEventType() to determine whether it was load/unload. + */ + HRESULT GetModule([out]ICorDebugModule **ppModule); +} + +// This interface is implemented by events types: +// MANAGED_EXCEPTION_FIRST_CHANCE, +// MANAGED_EXCEPTION_USER_FIRST_CHANCE, +// MANAGED_EXCEPTION_CATCH_HANDLER_FOUND, +// MANAGED_EXCEPTION_UNHANDLED, +[ + object, + local, + uuid(AF79EC94-4752-419C-A626-5FB1CC1A5AB7), + pointer_default(unique) +] +interface ICorDebugExceptionDebugEvent : ICorDebugDebugEvent +{ + // The meaning of this stack pointer varies based on event type (available from + // ICorDebugDebugEvent.GetEventType()) + // + // MANAGED_EXCEPTION_FIRST_CHANCE -> The stack pointer for the frame that threw the exception + // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> The stack pointer for the user-code frame closest to the point of + // the thrown exception + // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> The stack pointer for the frame that contains the catch handler + // MANAGED_EXCEPTION_UNHANDLED -> *pStackPointer will be NULL + HRESULT GetStackPointer([out]CORDB_ADDRESS *pStackPointer); + + // The meaning of the IP varies based on event type (available from + // ICorDebugDebugEvent.GetEventType()) + // + // MANAGED_EXCEPTION_FIRST_CHANCE -> The address of the faulting instruction + // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> Within the frame indicated by GetStackPointer(), + // this is the code address where execution would resume if no exception had been + // raised. The exception may or may not cause different code to be executed in this + // frame such as a catch of finally clause. + // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> Within the frame indicated by GetStackPointer(), + // this is the code address where catch handler execution will start + // MANAGED_EXCEPTION_UNHANDLED -> *pIP will be 0 + HRESULT GetNativeIP([out]CORDB_ADDRESS *pIP); + + + // Gets a flag that indicates if the exception is interceptable. + HRESULT GetFlags([out]CorDebugExceptionFlags *pdwFlags); +} + +/* ------------------------------------------------------------------------- * + * Breakpoint interface + * ------------------------------------------------------------------------- */ + +/* + * ICorDebugBreakpoint represents a breakpoint; either a breakpoint + * set in a function, or a watchpoint set on a value. + * + * Note that breakpoints have no direct support for condition + * expressions. The debugger must implement this functionality on top of + * this interface if desired. + * + */ + +[ + object, + local, + uuid(CC7BCAE8-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugBreakpoint : IUnknown +{ + /* + * Sets the active state of the breakpoint + */ + HRESULT Activate([in] BOOL bActive); + + /* + * Returns whether the breakpoint is active. + */ + HRESULT IsActive([out] BOOL *pbActive); +}; + +[ + object, + local, + uuid(CC7BCAE9-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugFunctionBreakpoint : ICorDebugBreakpoint +{ + /* + * Returns the function on which this breakpoint is set + */ + HRESULT GetFunction([out] ICorDebugFunction **ppFunction); + + /* + * Returns the offset of this breakpoint within the function + */ + HRESULT GetOffset([out] ULONG32 *pnOffset); +}; + +[ + object, + local, + uuid(CC7BCAEA-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugModuleBreakpoint : ICorDebugBreakpoint +{ + /* + * Returns the module on which this breakpoint is set. + */ + HRESULT GetModule([out] ICorDebugModule **ppModule); +}; + +[ + object, + local, + uuid(CC7BCAEB-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugValueBreakpoint : ICorDebugBreakpoint +{ + /* + * Gets the value on which this breakpoint is set. + */ + HRESULT GetValue([out] ICorDebugValue **ppValue); +}; + +/* ------------------------------------------------------------------------- * + * Stepper interface + * ------------------------------------------------------------------------- */ + +/* + * A Stepper object represents a stepping operation being performed by + * the debugger. Note that there can be more than one stepper per + * thread; for instance a breakpoint may be hit in the midst of a + * stepping over a function, and the user may wish to start a new + * stepping operation inside that function. (Note that it is up to the + * debugger how to handle this; it may want to cancel the original + * stepping operation, or nest them. This API allows either behavior.) + * + * Also, a stepper may migrate between threads if a cross-thread + * marshalled call is made by the EE. + * + * This object serves several purposes. Its serves as an identifer between a + * step command issued and the completion of that command. It also + * provides a central interface to encapsulate all of the stepping + * that can be performed. Finally it provides a way to prematurely + * cancel a stepping operation. + * + */ + +[ + object, + local, + uuid(CC7BCAEC-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugStepper : IUnknown +{ + /* + * IsActive returns whether or not the stepper is active, that is, whether + * it is currently stepping. + * + * Any step action remains active until StepComplete is called. Note that + * this automatically deactivates the stepper. + * + * A stepper may also be deactivated prematurely by calling + * Deactivate before a callback condition is reached. + */ + + HRESULT IsActive([out] BOOL *pbActive); + + /* + * Deactivate causes a stepper to cancel the last stepping command it + * received. A new stepping command may then be issued. + */ + + HRESULT Deactivate(); + + /* + * SetInterceptMask controls which intercept code will be stepped + * into by the stepper. If the bit for an interceptor is set, the + * stepper will complete with reason STEPPER_INTERCEPT when the + * given type of intercept occurs. If the bit is cleared, the + * intercepting code will be skipped. + * + * Note that SetInterceptMask may have unforeseen interactions + * with SetUnmappedStopMask (from the user's point of view). For + * example, if the only visible (ie, non internal) portion of class + * init code lacks mapping info (STOP_NO_MAPPING_INFO) and + * STOP_NO_MAPPING_INFO isn't set, then we'll step over the class init. + * + * By default, only INTERCEPT_NONE will be used. + */ + + typedef enum CorDebugIntercept + { + INTERCEPT_NONE = 0x0 , + INTERCEPT_CLASS_INIT = 0x01, + INTERCEPT_EXCEPTION_FILTER = 0x02, + INTERCEPT_SECURITY = 0x04, + INTERCEPT_CONTEXT_POLICY = 0x08, + INTERCEPT_INTERCEPTION = 0x10, + INTERCEPT_ALL = 0xffff + } CorDebugIntercept; + + HRESULT SetInterceptMask([in] CorDebugIntercept mask); + + /* + * SetUnmappedStopMask controls whether the stepper + * will stop in jitted code which is not mapped to IL. + * + * If the given flag is set, then that type of unmapped code + * will be stopped in. Otherwise stepping transparently continues. + * + * It should be noted that if one doesn't use a stepper to enter a + * method (for example, the main() method of C++), then one + * won't neccessarily step over prologs,etc. + * + * By default, STOP_OTHER_UNMAPPED will be used. + * + * STOP_UNMANAGED is only valid w/ interop debugging. + */ + + typedef enum CorDebugUnmappedStop + { + STOP_NONE = 0x0, + STOP_PROLOG = 0x01, + STOP_EPILOG = 0x02, + STOP_NO_MAPPING_INFO = 0x04, + STOP_OTHER_UNMAPPED = 0x08, + STOP_UNMANAGED = 0x10, + + STOP_ALL = 0xffff, + + } CorDebugUnmappedStop; + + HRESULT SetUnmappedStopMask([in] CorDebugUnmappedStop mask); + + /* + * Step is called when a thread is to be single stepped. The step + * will complete at the next managed instruction executed by the + * EE in the stepper's frame. + * + * If bStepIn is TRUE, any function calls made during the step + * will be stepped into. Otherwise they will be skipped. + * + * If Step is called on a stepper which is not in managed code, + * the step will complete when the next managed code is executed + * by the thread. (if bStepIn is FALSE, it will only complete + * when managed code is returned to, not when it is stepped into.) + */ + + HRESULT Step([in] BOOL bStepIn); + + /* + * StepRange works just like Step, except it will not complete + * until code outside the given range is reached. This can be + * more efficient than stepping one instruction at a time. + * + * Ranges are specified as a list of offset pairs [start, end) + * (note that end is exclusive) from the start of the stepper's + * frame's code. + * + * Ranges are in relative to the IL code of a method. Call + * SetRangeIL(FALSE) to specify ranges relative to the native code + * of a method. + */ + + typedef struct COR_DEBUG_STEP_RANGE + { + ULONG32 startOffset, endOffset; + } COR_DEBUG_STEP_RANGE; + + HRESULT StepRange([in] BOOL bStepIn, + [in,size_is(cRangeCount)] COR_DEBUG_STEP_RANGE ranges[], + [in] ULONG32 cRangeCount); + + /* + * A StepOut operation will complete after the current frame is + * returned from normally and the previous frame is reactivated. + * + * If this is called when in unmanaged code, the step will complete + * when the calling managed code is returned to. + * + * In v2.0, we explicitly forbid StepOut with the STOP_UNMANAGED mask + * and will fail that. Interop debuggers must do step-out-to-native + * themselves. + */ + + HRESULT StepOut(); + + /* + * SetRangeIL is used to set whether the ranges passed StepRange are + * relative to the IL code or the native code for the method being + * stepped in. + * + * By default the range is in IL. + */ + + HRESULT SetRangeIL([in] BOOL bIL); +}; + +/* + * ICorDebugStepper2 exposes JMC functionality. + */ +[ + object, + local, + uuid(C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7), + pointer_default(unique) +] +interface ICorDebugStepper2 : IUnknown +{ + HRESULT SetJMC([in] BOOL fIsJMCStepper); +} + +/* ------------------------------------------------------------------------- * + * Program state object interfaces + * ------------------------------------------------------------------------- */ + +/* + * ICorDebugRegisterSet + */ + +[ + object, + local, + uuid(CC7BCB0B-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugRegisterSet : IUnknown +{ + typedef enum CorDebugRegister + { + // registers (potentially) available on all architectures + // Note that these overlap with the architecture-specific + // registers + // + // NOTE: On IA64, REGISTER_FRAME_POINTER represents the BSP register. + + REGISTER_INSTRUCTION_POINTER = 0, + REGISTER_STACK_POINTER, + REGISTER_FRAME_POINTER, + + + // X86 registers + + REGISTER_X86_EIP = 0, + REGISTER_X86_ESP, + REGISTER_X86_EBP, + + REGISTER_X86_EAX, + REGISTER_X86_ECX, + REGISTER_X86_EDX, + REGISTER_X86_EBX, + + REGISTER_X86_ESI, + REGISTER_X86_EDI, + + REGISTER_X86_FPSTACK_0, + REGISTER_X86_FPSTACK_1, + REGISTER_X86_FPSTACK_2, + REGISTER_X86_FPSTACK_3, + REGISTER_X86_FPSTACK_4, + REGISTER_X86_FPSTACK_5, + REGISTER_X86_FPSTACK_6, + REGISTER_X86_FPSTACK_7, + + + // AMD64 registers + + REGISTER_AMD64_RIP = 0, + REGISTER_AMD64_RSP, + REGISTER_AMD64_RBP, + + REGISTER_AMD64_RAX, + REGISTER_AMD64_RCX, + REGISTER_AMD64_RDX, + REGISTER_AMD64_RBX, + + REGISTER_AMD64_RSI, + REGISTER_AMD64_RDI, + + REGISTER_AMD64_R8, + REGISTER_AMD64_R9, + REGISTER_AMD64_R10, + REGISTER_AMD64_R11, + REGISTER_AMD64_R12, + REGISTER_AMD64_R13, + REGISTER_AMD64_R14, + REGISTER_AMD64_R15, + + // Xmm FP + + REGISTER_AMD64_XMM0, + REGISTER_AMD64_XMM1, + REGISTER_AMD64_XMM2, + REGISTER_AMD64_XMM3, + REGISTER_AMD64_XMM4, + REGISTER_AMD64_XMM5, + REGISTER_AMD64_XMM6, + REGISTER_AMD64_XMM7, + REGISTER_AMD64_XMM8, + REGISTER_AMD64_XMM9, + REGISTER_AMD64_XMM10, + REGISTER_AMD64_XMM11, + REGISTER_AMD64_XMM12, + REGISTER_AMD64_XMM13, + REGISTER_AMD64_XMM14, + REGISTER_AMD64_XMM15, + + + // IA64 registers + + REGISTER_IA64_BSP = REGISTER_FRAME_POINTER, + + // To get a particular general register, add the register number + // to REGISTER_IA64_R0. The same also goes for floating point + // registers. + // + // For example, if you need REGISTER_IA64_R83, + // use REGISTER_IA64_R0 + 83. + REGISTER_IA64_R0 = REGISTER_IA64_BSP + 1, + REGISTER_IA64_F0 = REGISTER_IA64_R0 + 128, + + + // ARM registers (@ARMTODO: FP?) + + REGISTER_ARM_PC = 0, + REGISTER_ARM_SP, + REGISTER_ARM_R0, + REGISTER_ARM_R1, + REGISTER_ARM_R2, + REGISTER_ARM_R3, + REGISTER_ARM_R4, + REGISTER_ARM_R5, + REGISTER_ARM_R6, + REGISTER_ARM_R7, + REGISTER_ARM_R8, + REGISTER_ARM_R9, + REGISTER_ARM_R10, + REGISTER_ARM_R11, + REGISTER_ARM_R12, + REGISTER_ARM_LR, + REGISTER_ARM_D0, + REGISTER_ARM_D1, + REGISTER_ARM_D2, + REGISTER_ARM_D3, + REGISTER_ARM_D4, + REGISTER_ARM_D5, + REGISTER_ARM_D6, + REGISTER_ARM_D7, + REGISTER_ARM_D8, + REGISTER_ARM_D9, + REGISTER_ARM_D10, + REGISTER_ARM_D11, + REGISTER_ARM_D12, + REGISTER_ARM_D13, + REGISTER_ARM_D14, + REGISTER_ARM_D15, + REGISTER_ARM_D16, + REGISTER_ARM_D17, + REGISTER_ARM_D18, + REGISTER_ARM_D19, + REGISTER_ARM_D20, + REGISTER_ARM_D21, + REGISTER_ARM_D22, + REGISTER_ARM_D23, + REGISTER_ARM_D24, + REGISTER_ARM_D25, + REGISTER_ARM_D26, + REGISTER_ARM_D27, + REGISTER_ARM_D28, + REGISTER_ARM_D29, + REGISTER_ARM_D30, + REGISTER_ARM_D31, + + + // ARM64 registers + + REGISTER_ARM64_PC = 0, + REGISTER_ARM64_SP, + REGISTER_ARM64_FP, + REGISTER_ARM64_X0, + REGISTER_ARM64_X1, + REGISTER_ARM64_X2, + REGISTER_ARM64_X3, + REGISTER_ARM64_X4, + REGISTER_ARM64_X5, + REGISTER_ARM64_X6, + REGISTER_ARM64_X7, + REGISTER_ARM64_X8, + REGISTER_ARM64_X9, + REGISTER_ARM64_X10, + REGISTER_ARM64_X11, + REGISTER_ARM64_X12, + REGISTER_ARM64_X13, + REGISTER_ARM64_X14, + REGISTER_ARM64_X15, + REGISTER_ARM64_X16, + REGISTER_ARM64_X17, + REGISTER_ARM64_X18, + REGISTER_ARM64_X19, + REGISTER_ARM64_X20, + REGISTER_ARM64_X21, + REGISTER_ARM64_X22, + REGISTER_ARM64_X23, + REGISTER_ARM64_X24, + REGISTER_ARM64_X25, + REGISTER_ARM64_X26, + REGISTER_ARM64_X27, + REGISTER_ARM64_X28, + REGISTER_ARM64_LR, + + REGISTER_ARM64_V0, + REGISTER_ARM64_V1, + REGISTER_ARM64_V2, + REGISTER_ARM64_V3, + REGISTER_ARM64_V4, + REGISTER_ARM64_V5, + REGISTER_ARM64_V6, + REGISTER_ARM64_V7, + REGISTER_ARM64_V8, + REGISTER_ARM64_V9, + REGISTER_ARM64_V10, + REGISTER_ARM64_V11, + REGISTER_ARM64_V12, + REGISTER_ARM64_V13, + REGISTER_ARM64_V14, + REGISTER_ARM64_V15, + REGISTER_ARM64_V16, + REGISTER_ARM64_V17, + REGISTER_ARM64_V18, + REGISTER_ARM64_V19, + REGISTER_ARM64_V20, + REGISTER_ARM64_V21, + REGISTER_ARM64_V22, + REGISTER_ARM64_V23, + REGISTER_ARM64_V24, + REGISTER_ARM64_V25, + REGISTER_ARM64_V26, + REGISTER_ARM64_V27, + REGISTER_ARM64_V28, + REGISTER_ARM64_V29, + REGISTER_ARM64_V30, + REGISTER_ARM64_V31, + + // other architectures here + + } CorDebugRegister; + + /* + * GetRegistersAvailable returns a mask indicating which registers + * are available in the given register set. Registers may be unavailable + * if their value is undeterminable for the given situation. The returned + * word contains a bit for each register (1 << register index), which will + * be 1 if the register is available or 0 if it is not. + */ + + HRESULT GetRegistersAvailable([out] ULONG64 *pAvailable); + + /* + * GetRegisters returns an array of register values corresponding + * to the given mask. The registers which have their bit set in + * the mask will be packed into the resulting array. (No room is + * assigned in the array for registers whose mask bit is not set.) + * Thus, the size of the array should be equal to the number of + * 1's in the mask. + * + * If an unavailable register is indicated by the mask, an indeterminate + * value will be returned for the corresponding register. + * + * registerBufferCount should indicate number of elements in the + * buffer to receive the register values. If it is too small for + * the number of registers indicated by the mask, the higher + * numbered registers will be truncated from the set. Or, if it + * is too large, the unused registerBuffer elements will be + * unmodified. */ + + HRESULT GetRegisters([in] ULONG64 mask, [in] ULONG32 regCount, + [out, size_is(regCount), length_is(regCount)] + CORDB_REGISTER regBuffer[]); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT SetRegisters([in] ULONG64 mask, + [in] ULONG32 regCount, + [in, size_is(regCount)] CORDB_REGISTER regBuffer[]); + + /* + * GetThreadContext returns the context for the given thread. The + * debugger should call this function rather than the Win32 + * GetThreadContext, because the thread may actually be in a "hijacked" + * state where its context has been temporarily changed. + * + * The data returned is a CONTEXT structure for the current platform. + * + * For non-leaf frames, clients should check which registers are valid by + * using GetRegistersAvailable. + * + */ + + HRESULT GetThreadContext([in] ULONG32 contextSize, + [in, out, length_is(contextSize), + size_is(contextSize)] BYTE context[]); + + /* + * Not implemented in v2.0. It is too dangerous to manipulate the context of + * threads in Managed code. Use other high level operations (like SetIp, + * ICorDebugValue::SetValue) instead. + * + */ + + HRESULT SetThreadContext([in] ULONG32 contextSize, + [in, length_is(contextSize), + size_is(contextSize)] BYTE context[]); +} + +/* + * ICorDebugRegisterSet2 is an extension for hardward platforms with more + * than 64 registers, since ICorDebugRegisterSet::GetRegisters() only + * recognizes a 64-bit mask. + */ + +[ + object, + local, + uuid(6DC7BA3F-89BA-4459-9EC1-9D60937B468D), + pointer_default(unique) +] +interface ICorDebugRegisterSet2 : IUnknown +{ + /* + * Given a CorDebugRegister value, its position in the mask is determined as + * follows: + * + * 1) (value >> 3) is used to index the array of BYTEs, and + * 2) (value & 7) (the least significant three bits) represents the bit position + * within the indexed BYTE, where bit 0 is the least significant bit. + * + * Or, in code: + * + * #define REGISTER_IA64_MAX REGISTER_IA64_F0 + 128 + * #define MAX_MASK_COUNT ((REGISTER_IA64_MAX + 7) >> 3) + * #define SET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] |= (1 << ((_reg) & 7)) + * #define RESET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] &= ~(1 << ((_reg) & 7)) + * #define IS_SET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] & (1 << ((_reg) & 7)) + * + * CorDebugRegister value = ; + * BYTE pAvailable[MAX_MASK_COUNT]; + * + * GetRegistersAvailable(MAX_MASK_COUNT, pAvailable); + * ASSERT(value < REGISTER_IA64_MAX); + * IS_SET_BIT_MASK(pAvailable, value); + */ + + HRESULT GetRegistersAvailable([in] ULONG32 numChunks, + [out, size_is(numChunks)] BYTE availableRegChunks[]); + + HRESULT GetRegisters([in] ULONG32 maskCount, + [in, size_is(maskCount)] BYTE mask[], + [in] ULONG32 regCount, + [out, size_is(regCount)] CORDB_REGISTER regBuffer[]); + + HRESULT SetRegisters([in] ULONG32 maskCount, + [in, size_is(maskCount)] BYTE mask[], + [in] ULONG32 regCount, + [in, size_is(regCount)] CORDB_REGISTER regBuffer[]); +} + +/* + * ICorDebugThread represents a thread in the process. The lifetime of a + * thread object is equal to the lifetime of the thread it represents. + */ + +[ + object, + local, + uuid(938c6d66-7fb6-4f69-b389-425b8987329b), + pointer_default(unique) +] +interface ICorDebugThread : IUnknown +{ + /* + * GetProcess returns the process of which this thread is a part. + */ + + HRESULT GetProcess([out] ICorDebugProcess **ppProcess); + + /* + * GetID returns the current OS ID of the active part of the thread. + * Note that this may theoretically change as the process executes, + * and even be different for different parts of the thread. + */ + + HRESULT GetID([out] DWORD *pdwThreadId); + + /* + * GetHandle returns the current Handle of the active part of the thread. + * Note that this may theoretically change as the process executes, + * and even be different for different parts of the thread. + * + * This handle is owned by the debugging API. The debugger should duplicate + * it before using it. + */ + + HRESULT GetHandle([out] HTHREAD *phThreadHandle); + + /* + * GetAppDomain returns the app domain which the thread is currently + * executing in. + */ + + HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain); + + /* + * SetDebugState sets the current debug state of the thread. + * (The "current debug state" + * represents the debug state if the process were to be continued, + * not the actual current state.) + * + * The normal value for this is THREAD_RUNNING. Only the debugger + * can affect the debug state of a thread. Debug states do + * last across continues, so if you want to keep a thread + * THREAD_SUSPENDed over mulitple continues, you can set it once + * and thereafter not have to worry about it. + * + * Suspending threads and resuming the process can cause deadlocks, though it's + * usually unlikely. This is an intrinisc quality of threads and processes and is by-design. + * A debugger can async break and resume the threads to break the deadlock. + * + * If the thread's user state includes USER_UNSAFE_POINT, then the thread may block a GC. + * This means the suspended thread has a mcuh higher chance of causing a deadlock. + * + * This may not affect debug events already queued. Thus a debugger should drain the entire + * event queue (via calling HasQueuedCallbacks) before suspending or resuming threads. Else it + * may get events on a thread that it believes it has already suspended. + * + */ + + HRESULT SetDebugState([in] CorDebugThreadState state); + + /* + * GetDebugState returns the current debug state of the thread. + * (If the process is currently stopped, the "current debug state" + * represents the debug state if the process were to be continued, + * not the actual current state.) + */ + + HRESULT GetDebugState([out] CorDebugThreadState *pState); + + /* + * GetUserState returns the user state of the thread, that is, the state + * which it has when the program being debugged examines it. + * A thread may have multiple state bits set. + */ + + typedef enum CorDebugUserState + { + USER_STOP_REQUESTED = 0x01, + USER_SUSPEND_REQUESTED = 0x02, + USER_BACKGROUND = 0x04, + USER_UNSTARTED = 0x08, + USER_STOPPED = 0x10, + USER_WAIT_SLEEP_JOIN = 0x20, + USER_SUSPENDED = 0x40, + + // An "unsafe point" is a place where the thread may block a Garbage Collection (GC). + // Debug events may be dispatched from unsafe points, but suspending a thread at + // an unsafe spot will very likely cause a deadlock (until the thread is resumed). + // This is a function of the thread's IP and the available GC info. The exact details + // of what is safe and unsafe is unspecified and highly determined by jit/gc implementation details. + USER_UNSAFE_POINT = 0x80, + + // indicates that this thread is a threadpool thread + USER_THREADPOOL = 0x100, + } CorDebugUserState; + + HRESULT GetUserState([out] CorDebugUserState *pState); + + /* + * GetCurrentException returns the exception object which is + * currently being thrown by the thread. This will exist from the time the exception + * is thrown until the end of the catch block. That range will include filters + * and finallys. + * + * FuncEval will clear out the exception object on setup and restore it on completion. + * + * Exceptions can be nested (eg, if an exception is thrown in filter or a func-eval), + * so there may be multiple outstanding exceptions on a single thread. + * This returns the most current exception. + * + * The exception object and type may change throughout the life of the exception. For example, an + * exception of type X may be thrown, but then the CLR may run out of memory and promote + * that to an OutOfMemory exception. + */ + + HRESULT GetCurrentException([out] ICorDebugValue **ppExceptionObject); + + /* + * This is not implemented. + */ + + HRESULT ClearCurrentException(); + + /* + * CreateStepper creates a stepper object which operates relative + * to the active frame in the given thread. (Note that this may be + * unmanaged code.) The Stepper API must then be used to perform + * actual stepping. + * + */ + + HRESULT CreateStepper([out] ICorDebugStepper **ppStepper); + + /* + * EnumerateChains returns an enum which will return all the stack + * chains in the thread, starting at the active (most recent) one. + * These chains represent the physical call stack for the thread. + * + * Chain boundaries occur for several reasons: + * managed <-> unmanaged transitions + * context switches + * debugger hijacking of user threads + * + * Note that in the simple case for a thread running purely + * managed code in a single context there will be a one to one + * correspondence between threads & chains. + * + * A debugger may want to rearrange the physical call + * stacks of all threads into logical call stacks. This would involve + * sorting all the threads' chains by their caller/callee + * relationships & regrouping them. + * + */ + + HRESULT EnumerateChains([out] ICorDebugChainEnum **ppChains); + + /* + * GetActiveChain is a convenience routine to return the + * active (most recent) chain on the thread, if any. + * + */ + + HRESULT GetActiveChain([out] ICorDebugChain **ppChain); + + /* + * GetActiveFrame is a convenience routine to return the + * active (most recent) frame on the thread, if any. + * If there are no frames on the stack, ppFrame will point to NULL + * and the function still returns S_OK. + */ + + HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame); + + /* + * GetRegisterSet returns the register set for the active part + * of the thread. + * + */ + + HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); + + /* + * CreateEval creates an evaluation object which operates on the + * given thread. The Eval will push a new chain on the thread before + * doing its computation. + * + * Note that this interrupts the computation currently + * being performed on the thread until the eval completes. + * + */ + + HRESULT CreateEval([out] ICorDebugEval **ppEval); + + /* + * Returns the runtime thread object. + */ + + HRESULT GetObject([out] ICorDebugValue **ppObject); + +}; + +/* + * ICorDebugThread2 is a logical extension to ICorDebugThread. + */ +[ + object, + local, + uuid(2BD956D9-7B07-4bef-8A98-12AA862417C5), + pointer_default(unique) +] +interface ICorDebugThread2 : IUnknown +{ + + typedef struct _COR_ACTIVE_FUNCTION + { + ICorDebugAppDomain *pAppDomain; // Pointer to the owning AppDomain of the below IL Offset. + ICorDebugModule *pModule; // Pointer to the owning Module of the below IL Offset. + ICorDebugFunction2 *pFunction; // Pointer to the owning Function of the below IL Offset. + ULONG32 ilOffset; // IL Offset of the frame. + ULONG32 flags; // Bit mask of flags, currently unused. Reserved. + } COR_ACTIVE_FUNCTION; + + /* + * Retrieves the active functions for the given threads' frames. This + * includes AppDomain ID, Module ID, Funtion ID and IL offset for + * each active statement on the stack. A flags field is also included + * for future information about the frame that might need to be conveyed. + * + * If pFunctions is NULL, returns only the number of functions that + * is on the stack in pcFunctions. + */ + + HRESULT GetActiveFunctions([in] ULONG32 cFunctions, + [out] ULONG32 *pcFunctions, + [in, out, size_is(cFunctions), length_is(*pcFunctions)] + COR_ACTIVE_FUNCTION pFunctions[] + ); + /* + * Returns 0 if not part of a connection + * Maps to a SPID in SQL Server + */ + HRESULT GetConnectionID( + [out] CONNID *pdwConnectionId); + + /* + * Return the TASKID of this thread. + */ + HRESULT GetTaskID( + [out] TASKID *pTaskId); + + /* + * Return the OS Thread ID + */ + HRESULT GetVolatileOSThreadID( + [out] DWORD *pdwTid); + + /* + * Allow the debugger to intercept the current exception on a thread. It can be + * called between an Exception callback and the associated call to ICorDebugProcess::Continue. + * + * pFrame specifies where we should intercept the exception. It must be a valid ICDFrame pointer, + * which can be obtained from a stackwalk. However, you must not call Continue() between + * doing the stackwalk and calling this function. + */ + HRESULT InterceptCurrentException( + [in] ICorDebugFrame *pFrame); +} + + + +/* + * ICorDebugThread3 is a logical extension to ICorDebugThread. + */ +[ + object, + local, + uuid(F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5), + pointer_default(unique) +] +interface ICorDebugThread3 : IUnknown +{ + HRESULT CreateStackWalk([out] ICorDebugStackWalk **ppStackWalk); + + HRESULT GetActiveInternalFrames([in] ULONG32 cInternalFrames, + [out] ULONG32 *pcInternalFrames, + [in, out, size_is(cInternalFrames), length_is(*pcInternalFrames)] + ICorDebugInternalFrame2 * ppInternalFrames[] + ); +}; + +/* + * ICorDebugThread4 is a logical extension to ICorDebugThread. + */ +[ + object, + local, + uuid(1A1F204B-1C66-4637-823F-3EE6C744A69C), + pointer_default(unique) +] +interface ICorDebugThread4 : IUnknown +{ + /* + * Returns S_OK if ICorDebugThread::GetCurrentException() is non-NULL and the exception + * it refers to has completed the first pass of exception handling without locating + * a catch clause. + * Returns S_FALSE if there is no exception, it hasn't completed first pass handling, + * or a catch handler was located + * Returns an appropriate error HRESULT when the answer can not be determined + */ + HRESULT HasUnhandledException(); + + HRESULT GetBlockingObjects([out] ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); + /* + * Gets the current CustomNotification object on the current thread. This could be NULL if no + * current notification object exists. If we aren't currently inside a CustomNotification callback, + * this will always return NULL. + * A debugger can examine this object to determine how to handle the notification. + * See ICorDebugManagedCallback3::CustomNotification for more information about + * custom notifications. + */ + HRESULT GetCurrentCustomDebuggerNotification([out] ICorDebugValue ** ppNotificationObject); +}; + +/* + * The new V3.0 stackwalking API. + */ +[ + object, + local, + uuid(A0647DE9-55DE-4816-929C-385271C64CF7), + pointer_default(unique) +] +interface ICorDebugStackWalk : IUnknown +{ + typedef enum CorDebugSetContextFlag + { + SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, + SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2, + } CorDebugSetContextFlag; + + /* + * Get the current context of this stack frame. + * + * The CONTEXT is retrieved from the ICorDebugStackWalk. As unwinding may only restore a subset of the + * registers, such as only non-volatile registers, the context may not exactly match the register state at + * the time of the actual call. + */ + HRESULT GetContext([in] ULONG32 contextFlags, + [in] ULONG32 contextBufSize, + [out] ULONG32* contextSize, + [out, size_is(contextBufSize)] BYTE contextBuf[]); + + /* + * Change the current context of this stack walk, allowing the + * debugger to move it to an arbitrary context. Does not actually + * alter the current context of the thread whose stack is being walked. + * + * The CONTEXT has to be a valid CONTEXT of a stack frame on the thread. + * If the CONTEXT is outside of the current thread's stack range, we'll + * return a failure HRESULT. Otherwise, in the case of an invalid CONTEXT, + * the result is undefined. + */ + HRESULT SetContext([in] CorDebugSetContextFlag flag, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE context[]); + + /* + * Attempt to advance the stackwalk to the next frame. + * If the current frame type is a native stack frame, Next() will not advance to the caller frame. + * Instead, Next() will advance to the next managed stack frame or the next internal frame marker. + * + * If a debugger wants to unwind unmanaged stack frames, it needs to start from the + * native stack frame itself. It can seed the unwind by calling GetContext(). + * + * This function will return CORDBG_S_AT_END_OF_STACK when there are no more frames. + */ + HRESULT Next(); + + /* + * Return the current frame. If the stackwalker is stopped at a native stack frame, we will return S_FALSE + * and set pFrame to NULL. + */ + HRESULT GetFrame([out] ICorDebugFrame ** pFrame); +}; + + +/* + * ICorDebugChain represents a segment of a physical or logical call + * stack. All frames in a chain occupy contiguous stack space, and + * they share the same thread & context. A chain may represent either + * managed or unmanaged code. Chains may be empty. Unmanaged chains are + * always empty. + */ + +[ + object, + local, + uuid(CC7BCAEE-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugChain : IUnknown +{ + /* + * GetThread returns the physical thread which this call chain is + * part of. + */ + + HRESULT GetThread([out] ICorDebugThread **ppThread); + + /* + * GetStackRange returns the address range of the stack segment for the + * call chain. Note that you cannot make any assumptions about + * what is actually stored on the stack - the numeric range is to compare + * stack frame locations only. + * The start of a stack range is the leafmost boundary of the chain, and + * the end of a stack range is the rootmost boundary of the chain. + */ + + HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetContext([out] ICorDebugContext **ppContext); + + /* + * GetCaller returns a pointer to the chain which called this + * chain. Note that this may be a chain on another thread in the + * case of cross-thread-marshalled calls. The caller will be NULL + * for spontaneously called chains (e.g. the ThreadProc, a + * debugger initiated call, etc.) + */ + + HRESULT GetCaller([out] ICorDebugChain **ppChain); + + /* + * GetCallee returns a pointer to the chain which this chain is + * waiting on before it resumes. Note that this may be a chain on + * another thread in the case of cross-thread-marshalled + * calls. The callee will be NULL if the chain is currently + * actively running. + */ + + HRESULT GetCallee([out] ICorDebugChain **ppChain); + + /* + * GetPrevious returns a pointer to the chain which was on this + * thread before the current one was pushed, if there is one. + */ + + HRESULT GetPrevious([out] ICorDebugChain **ppChain); + + /* + * GetNext returns a pointer to the chain which was pushed on this + * thread after the current one, if there is one. + */ + + HRESULT GetNext([out] ICorDebugChain **ppChain); + + /* + * IsManaged returns whether or not the chain is running managed + * code. + */ + + HRESULT IsManaged([out] BOOL *pManaged); + + /* + * These chains represent the physical call stack for the thread. + * EnumerateFrames returns an iterator which will list all the stack + * frames in the chain, starting at the active (most recent) one. This + * should be called only for managed chains. + * + * NOTE: The debugging API does not provide methods for obtaining + * frames contained in unmanaged chains. The debugger needs to use + * other means to obtain this information. + */ + + HRESULT EnumerateFrames([out] ICorDebugFrameEnum **ppFrames); + + /* + * GetActiveFrame is a convenience routine to return the + * active (most recent) frame on the chain, if any. + * + * If the active frame is not available, the call will succeed + * and *ppFrame will be NULL. Active frames will not be available + * for all CHAIN_ENTER_UNMANAGED chains, and for some + * CHAIN_CLASS_INIT chains. + */ + + HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame); + + /* + * GetRegisterSet returns the register set for the beginnning (the leafmost end) + * of the chain. + */ + + HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); + + /* + * GetReason returns the reason for the genesis of this calling chain. + */ + + typedef enum CorDebugChainReason + { + // Note that the first five line up with CorDebugIntercept + CHAIN_NONE = 0x000, + CHAIN_CLASS_INIT = 0x001, + CHAIN_EXCEPTION_FILTER = 0x002, + CHAIN_SECURITY = 0x004, + CHAIN_CONTEXT_POLICY = 0x008, + CHAIN_INTERCEPTION = 0x010, + CHAIN_PROCESS_START = 0x020, + CHAIN_THREAD_START = 0x040, + CHAIN_ENTER_MANAGED = 0x080, + CHAIN_ENTER_UNMANAGED = 0x100, + CHAIN_DEBUGGER_EVAL = 0x200, + CHAIN_CONTEXT_SWITCH = 0x400, + CHAIN_FUNC_EVAL = 0x800, + } CorDebugChainReason; + + HRESULT GetReason([out] CorDebugChainReason *pReason); +}; + + +[ + object, + local, + uuid(CC7BCAEF-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugFrame : IUnknown +{ + /* + * GetChain returns the chain of which this stack frame is a part. + */ + + HRESULT GetChain([out] ICorDebugChain **ppChain); + + /* + * GetCode returns the code which this stack frame is running if any. + */ + + HRESULT GetCode([out] ICorDebugCode **ppCode); + + /* + * GetFunction returns the function for the code which this stack + * frame is running. + * For ICorDebugInternalFrames, this may point to a method the + * frame is associated with (which may be in a different AppDomain + * from the frame itself), or may fail if the frame doesn't relate to any + * particular function. + */ + + HRESULT GetFunction([out] ICorDebugFunction **ppFunction); + + /* + * GetFunctionToken is a convenience routine to return the token for the + * function for the code which this stack frame is running. + * The scope to resolve the token can be gotten from the ICorDebugFunction + * associated with this frame. + */ + + HRESULT GetFunctionToken([out] mdMethodDef *pToken); + + /* + * GetStackRange returns the absolute address range of the stack + * frame. (This is useful for piecing together interleaved stack + * traces gathered from multiple debugging engines.) Note that you + * cannot make any assumptions about what is actually stored on + * the stack - the numeric range is to compare stack frame + * locations only. + * The start of a stack range is the leafmost boundary of the frame, and + * the end of a stack range is the rootmost boundary of the frame. + */ + + HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd); + + /* + * GetCaller returns a pointer to the frame in the current chain + * which called this frame, or NULL if this is the rootmost frame + * in the chain. + */ + + HRESULT GetCaller([out] ICorDebugFrame **ppFrame); + + /* + * GetCallee returns a pointer to the frame in the current chain + * which this frame called, or NULL if this is the leafmost frame + * in the chain. + */ + + HRESULT GetCallee([out] ICorDebugFrame **ppFrame); + + /* + * CreateStepper creates a stepper object which operates relative to the + * frame. The Stepper API must then be used to perform actual stepping. + * + * Note that if this frame is not active, the frame will typically have to + * be returned to before the step is completed. + * + */ + + HRESULT CreateStepper([out] ICorDebugStepper **ppStepper); +}; + +[ + object, + local, + uuid(B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4), + pointer_default(unique) +] +interface ICorDebugInternalFrame : ICorDebugFrame +{ + + typedef enum CorDebugInternalFrameType + { + // This is a 'null' value for GetFrameType and is included for completeness sake. + // ICorDebugInternalFrame::GetFrameType() should never actually return this. + STUBFRAME_NONE = 0x00000000, + + // This frame is a M2U stub-frame. This could include both PInvoke + // and COM-interop calls. + STUBFRAME_M2U = 0x0000001, + + // This is a U2M stub frame. + STUBFRAME_U2M = 0x0000002, + + // AppDomain transition. + STUBFRAME_APPDOMAIN_TRANSITION = 0x00000003, + + // LightWeight method calls. + STUBFRAME_LIGHTWEIGHT_FUNCTION = 0x00000004, + + // Start of Func-eval. This is included for CHF callbacks. + // Funcevals also have a chain CHAIN_FUNC_EVAL (legacy from v1.0) + STUBFRAME_FUNC_EVAL = 0x00000005, + + // Start of an internal call into the CLR. + STUBFRAME_INTERNALCALL = 0x00000006, + + // start of a class initialization; corresponds to CHAIN_CLASS_INIT + STUBFRAME_CLASS_INIT = 0x00000007, + + // an exception is thrown; corresponds to CHAIN_EXCEPTION_FILTER + STUBFRAME_EXCEPTION = 0x00000008, + + // a frame used for code-access security purposes; corresponds to CHAIN_SECURITY + STUBFRAME_SECURITY = 0x00000009, + + // a frame used to mark that the runtime is jitting a managed method + STUBFRAME_JIT_COMPILATION = 0x0000000a, + } CorDebugInternalFrameType; + + // Get the type of internal frame. This will never be STUBFRAME_NONE. + // Debuggers should gracefully ignore unrecognized internal frame types. + HRESULT GetFrameType([out] CorDebugInternalFrameType * pType); + +}; + +[ + object, + local, + uuid(C0815BDC-CFAB-447e-A779-C116B454EB5B), + pointer_default(unique) +] +interface ICorDebugInternalFrame2 : IUnknown +{ + /* + * Returns the stack address of the internal frame marker. + */ + HRESULT GetAddress([out] CORDB_ADDRESS *pAddress); + +/* + * Check if an internal frame is closer to the leaf than pFrameToCompare. + */ + HRESULT IsCloserToLeaf([in] ICorDebugFrame * pFrameToCompare, + [out] BOOL * pIsCloser); +}; + +/* + * ICorDebugILFrame is a specialized interface of ICorDebugFrame for IL frames or jitted frames. + * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.) + */ + +[ + object, + local, + uuid(03E26311-4F76-11d3-88C6-006097945418), + pointer_default(unique) +] +interface ICorDebugILFrame : ICorDebugFrame +{ + /* + * GetIP returns the stack frame's offset into the function's IL code. + * If this stack frame is active, this address is the next + * instruction to execute. If this stack frame is not active, this is the + * next instruction to execute when the stack frame is reactivated. + * + * Note that if this a jitted frame, the IP will be determined by + * mapping backwards from the actual native IP, so the value may + * be only approximately correct. + * + * If pMappingResult is not NULL, A mapping result is returned which + * indicates the details of how the IP was obtained. The following values + * can be returned: + * + * MAPPING_EXACT - the IP is correct; either the frame is + * interpreted or there is an exact IL map for the function. + * + * MAPPING_APPROXIMATE - the IP was successfully mapped, but may + * be only approximately correct + * + * MAPPING_UNMAPPED_ADDRESS - although there is mapping info for + * the function, the current address is not mappable to IL. An + * IP of 0 is returned. + * + * MAPPING_PROLOG - the native code is in the prolog, so an IP of + * 0 is returned + * + * MAPPING_EPILOG - the native code is in an epilog, so the last + * IP of the method is returned + * + * MAPPING_NO_INFO - no mapping info is available for the method, + * so an IP of 0 is returned + * + */ + + typedef enum CorDebugMappingResult + { + MAPPING_PROLOG = 0x1, + MAPPING_EPILOG = 0x2, + MAPPING_NO_INFO = 0x4, + MAPPING_UNMAPPED_ADDRESS = 0x8, + MAPPING_EXACT = 0x10, + MAPPING_APPROXIMATE = 0x20, + } CorDebugMappingResult; + + HRESULT GetIP([out] ULONG32 *pnOffset, [out] CorDebugMappingResult *pMappingResult); + + /* + * SetIP sets the instruction pointer to the IL at the given offset. + * The debugger will do its best to fix up the state of the executing code + * so that it is consistent with the new IP as far as the EE is concerned, + * while preserving as much of the state of the user program as possible. + * + * Calling SetIP immediately invalidates all frames and chains for the + * current thread; the debugger must perform a new stack trace if it + * requires frame information after calling SetIP. + * + */ + + HRESULT SetIP([in] ULONG32 nOffset); + + /* + * EnumerateLocalVariables returns a list of the local variables + * available in the frame. Note that this may not include all of + * the locals in the running function, as some of them may not be + * active. + */ + + HRESULT EnumerateLocalVariables([out] ICorDebugValueEnum **ppValueEnum); + + /* + * GetLocalVariable gets the value for a local variable + * in an IL frame. This can be used either in an IL + * frame or a jitted frame. + */ + + HRESULT GetLocalVariable([in] DWORD dwIndex, + [out] ICorDebugValue **ppValue); + + /* + * EnumerateArguments returns a list of the arguments available in the + * frame. Note that this will include varargs arguments as well as + * arguments declared by the function signature (inlucding the implicit + * "this" argument if any). + */ + + HRESULT EnumerateArguments([out] ICorDebugValueEnum **ppValueEnum); + + /* + * GetArgument gets the value for an argument + * in an IL frame. This can be used either in an IL + * frame or a jitted frame. + * For instance (non-static) methods, argument index 0 is the "this" object, + * and the normal explicit arguments start with index 1. + */ + + HRESULT GetArgument([in] DWORD dwIndex, + [out] ICorDebugValue **ppValue); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetStackDepth([out] ULONG32 *pDepth); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetStackValue([in] DWORD dwIndex, + [out] ICorDebugValue **ppValue); + + /* + * CanSetIP attempts to determine if it's safe to set the instruction pointer + * to the IL at the given offset. If this returns S_OK, then executing + * SetIP (see above) will result in a safe, correct, continued execution. + * If CanSetIP returns anything else, SetIP can still be invoked, but + * continued, correct execution of the debuggee cannot be guaranteed. + * + */ + + HRESULT CanSetIP([in] ULONG32 nOffset); +}; + + +/* + * ICorDebugILFrame2 is a logical extension to ICorDebugILFrame. + */ +[ + object, + local, + uuid(5D88A994-6C30-479b-890F-BCEF88B129A5), + pointer_default(unique) +] +interface ICorDebugILFrame2 : IUnknown +{ + /* + * Performs an on-stack replacement for an outstanding function remap opportunity. + * This is used to update execution of an edited function to the latest version, + * preserving the current frame state (such as the values of all locals). + * This can only be called when a FunctionRemapOpportunity callback has been delivered + * for this leaf frame, and the callback has not yet been continued. newILOffset + * is the offset into the new function at which execution should continue. + * When the remap has completed, a FunctionRemapComplete callback will be delivered. + */ + HRESULT RemapFunction([in] ULONG32 newILOffset); + + /* + * EnumerateTypeParameters returns the type parameters active on a frame. + * This will include both the class type parameters (if any) followed by the method type + * parameters (if any). + * Use the metadata API IMetaDataImport2::EnumGenericParams to determine how many + * Class type parameters vs. Method Type parameters there are in this list. + * The type parameters will not always be available. + */ + + HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum); + +}; + +[ + object, + local, + uuid(9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24), + pointer_default(unique) +] +interface ICorDebugILFrame3 : IUnknown +{ + /* + * For the specified IL offset, obtains an ICorDebugValue object that encapsulates + * the return value of a function. The provided IL offset should be at a function + * call site and the debuggee should be stopped at a breakpoint set at the native + * offset returned by ICorDebugCode3::GetNativeOffsetForReturnValueBreakpoint for + * the same IL offset. + * If the debuggee is not stopped at the correct location for the specified IL offset + * the API will fail. + * If the function call doesn't return a value the API will fail. + */ + HRESULT GetReturnValueForILOffset(ULONG32 ILoffset, [out] ICorDebugValue** ppReturnValue); +}; + +typedef enum ILCodeKind +{ + ILCODE_ORIGINAL_IL = 0x1, + ILCODE_REJIT_IL = 0x2, +} ILCodeKind; + +[ + object, + local, + uuid(AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45), + pointer_default(unique) +] +interface ICorDebugILFrame4 : IUnknown +{ + /* + * EnumerateLocalVariablesEx returns a list of the local variables + * available in the frame. Note that this may not include all of + * the locals in the running function, as some of them may not be + * active. The Ex version of this function optionally accesses + * variables added in profiler ReJIT instrumentation. + * + * flags: + * ILCODE_ORIGINAL_IL preserves the same behavior as calling + * EnermateLocalVariables in ICorDebugILFrame. + * If the method is instrumented with additional locals, those locals + * will not be viewable. + * ILCODE_REJIT_IL allows viewing the locals defined + * in the profiler's updated local var signature included with the + * instrumented IL. If the IL is not instrumented the enumeration will + * be empty and S_OK is returned. + */ + + HRESULT EnumerateLocalVariablesEx([in] ILCodeKind flags, [out] ICorDebugValueEnum **ppValueEnum); + + /* + * GetLocalVariableEx gets the value for a local variable + * in an IL frame. The Ex version of this function optionally accesses + * variables added in profiler ReJIT instrumentation. + * + * flags: + * ILCODE_ORIGINAL_IL preserves the same behavior as calling + * GetLocalVariable in ICorDebugILFrame. + * If the method is instrumented with additional locals, those locals + * will not be addressable or viewable. + * ILCODE_REJIT_IL allows viewing the locals defined + * in the profiler's updated local var signature included with the + * instrumented IL. If the IL is not instrumented the method will + * return E_INVALIDARG. + */ + HRESULT GetLocalVariableEx([in] ILCodeKind flags, [in] DWORD dwIndex, [out] ICorDebugValue **ppValue); + + + /* + * GetCode returns the code which this stack frame is running if any. + * + * flags: + * ILCODE_ORIGINAL_IL preserves the same behavior as calling + * GetCode in ICorDebugFrame. + * If the method is instrumented that IL will not be visible. + * ILCODE_REJIT_IL allows viewing the IL defined by the profiler's + * rejit request. If the IL is not instrumented *ppCode will be + * set to NULL and S_OK is returned. + */ + HRESULT GetCodeEx([in] ILCodeKind flags, [out] ICorDebugCode **ppCode); + +}; + +/* + * ICorDebugNativeFrame is a specialized interface of ICorDebugFrame for jitted frames, i.e. + * native frames for managed methods. + * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.) + */ + +[ + object, + local, + uuid(03E26314-4F76-11d3-88C6-006097945418), + pointer_default(unique) +] +interface ICorDebugNativeFrame : ICorDebugFrame +{ + /* + * GetIP returns the stack frame's offset into the function's + * native code. If this stack frame is active, this address is + * the next instruction to execute. If this stack frame is not + * active, this is the next instruction to execute when the stack + * frame is reactivated. + */ + + HRESULT GetIP([out] ULONG32 *pnOffset); + + /* + * SetIP sets the instruction pointer to the given native + * offset. CorDebug will attempt to keep the stack frame in a + * coherent state. (Note that even if the frame is in a valid + * state as far as the runtime is concerned, there still may be + * problems - e.g. uninitialized local variables, etc. The caller + * (or perhaps the user) is responsible for insuring coherency of + * the running program.) + * + * Calling SetIP immediately invalidates all frames and chains for the + * current thread; the debugger must perform a new stack trace if it + * requires frame information after calling SetIP. + */ + + HRESULT SetIP([in] ULONG32 nOffset); + + /* + * GetRegisterSet returns the register set for the given frame. + * + */ + + HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); + + /* + * GetLocalRegisterValue gets the value for a local variable or + * argument stored in a register of a native frame. This can be + * used either in a native frame or a jitted frame. + */ + + HRESULT GetLocalRegisterValue([in] CorDebugRegister reg, + [in] ULONG cbSigBlob, + [in] PCCOR_SIGNATURE pvSigBlob, + [out] ICorDebugValue **ppValue); + + /* + * GetLocalDoubleRegisterValue gets the value for a local variable + * or argument stored in 2 registers of a native frame. This can + * be used either in a native frame or a jitted frame. + */ + + HRESULT GetLocalDoubleRegisterValue([in] CorDebugRegister highWordReg, + [in] CorDebugRegister lowWordReg, + [in] ULONG cbSigBlob, + [in] PCCOR_SIGNATURE pvSigBlob, + [out] ICorDebugValue **ppValue); + + /* + * GetLocalMemoryValue gets the value for a local variable stored + * at the given address. + */ + + HRESULT GetLocalMemoryValue([in] CORDB_ADDRESS address, + [in] ULONG cbSigBlob, + [in] PCCOR_SIGNATURE pvSigBlob, + [out] ICorDebugValue **ppValue); + + /* + * GetLocalRegisterMemoryValue gets the value for a local which + * is stored half in a register and half in memory. + */ + + HRESULT GetLocalRegisterMemoryValue([in] CorDebugRegister highWordReg, + [in] CORDB_ADDRESS lowWordAddress, + [in] ULONG cbSigBlob, + [in] PCCOR_SIGNATURE pvSigBlob, + [out] ICorDebugValue **ppValue); + + /* + * GetLocalMemoryRegisterValue gets the value for a local which + * is stored half in a register and half in memory. + */ + + HRESULT GetLocalMemoryRegisterValue([in] CORDB_ADDRESS highWordAddress, + [in] CorDebugRegister lowWordRegister, + [in] ULONG cbSigBlob, + [in] PCCOR_SIGNATURE pvSigBlob, + [out] ICorDebugValue **ppValue); + /* + * CanSetIP attempts to determine if it's safe to set the instruction pointer + * to the given native offset. If this returns S_OK, then executing + * SetIP (see above) will result in a safe, correct, continued execution. + * If CanSetIP returns anything else, SetIP can still be invoked, but + * continued, correct execution of the debuggee cannot be guaranteed. + * + */ + + HRESULT CanSetIP([in] ULONG32 nOffset); +}; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugModule */ +[ + object, + local, + uuid(35389FF1-3684-4c55-A2EE-210F26C60E5E), + pointer_default(unique) +] +interface ICorDebugNativeFrame2 : IUnknown +{ + /* + * Returns true if the current frame is a child frame. + */ + HRESULT IsChild([out] BOOL *pIsChild); + + /* + * Return true if the specified frame is the parent frame of the current frame. + */ + HRESULT IsMatchingParentFrame([in] ICorDebugNativeFrame2 *pPotentialParentFrame, + [out] BOOL *pIsParent); + + /* + * Return the stack parameter size on x86. On other platforms, we return S_FALSE and set pSize to 0. + * This is because other platforms don't need this information for unwinding. + */ + HRESULT GetStackParameterSize([out] ULONG32 * pSize); +}; + +/* + * ICorDebugModule3 is a logical extension to ICorDebugModule. + */ +[ + object, + local, + uuid(86F012BF-FF15-4372-BD30-B6F11CAAE1DD), + pointer_default(unique) +] +interface ICorDebugModule3 : IUnknown +{ + /* + * CreateReaderForInMemorySymbols creates a debug symbol reader object (eg. + * ISymUnmanagedReader) for a dynamic module. This symbol reader becomes stale + * and is usually discarded whenever a LoadClass callback is delivered for the + * module. + * + * Arguments: + * riid - The IID of the COM interface to return (typically IID_ISymUnmanagedReader) + * ppObj - Where to store the reader interface. + * + * Return Value: + * S_OK on success + * Error hresults otherwise, including: + * CORDBG_E_MODULE_LOADED_FROM_DISK if this isn't an in-memory or dynamic module + * CORDBG_E_SYMBOLS_NOT_AVAILABLE if symbols weren't supplied by the application or aren't + * yet available. + * + * Notes: + * This API can also be used to create a symbol reader object for in-memory + * (non-dynamic) modules, but only after the symbols are first available + * (indicated by the UpdateModuleSymbols callback). + * + * This API returns a new reader instance every time it is called (like CoCreateInstance) + * and so the debugger should cache the result and only request a new one when + * the underlying data may have changed (i.e. a LoadClass event). + * + * Dynamic modules do not have any symbols available until the first type has been + * loaded into them (as indicated by the LoadClass callback). + */ + HRESULT CreateReaderForInMemorySymbols([in] REFIID riid, + [out][iid_is(riid)] void **ppObj); +} + +/* + * ICorDebugRuntimeUnwindableFrame is a specialized interface of ICorDebugFrame for unmanaged methods + * which requires special knowledge to unwind. They are not jitted code. When the debugger sees this type + * of frames, it should use ICorDebugStackWalk::Next() to unwind, but it should do inspection itself. + * The debugger can call ICorDebugStackWalk::GetContext() to retrieve the CONTEXT of the frame when it gets + * an ICorDebugRuntimeUnwindableFrame. + */ + +[ + object, + local, + uuid(879CAC0A-4A53-4668-B8E3-CB8473CB187F), + pointer_default(unique) +] +interface ICorDebugRuntimeUnwindableFrame : ICorDebugFrame +{ +} + +/* + * ICorDebugModule represents a Common Language Runtime module that is loaded into a + * specific AppDomain. Normally this is an executable or a DLL, but it may also be + * some other file of a multi-module assembly. There is an ICorDebugModule instance + * for each AppDomain a module is loaded into, even in the case of shared modules like + * mscorlib. + */ + +[ + object, + local, + uuid(dba2d8c1-e5c5-4069-8c13-10a7c6abf43d), + pointer_default(unique) +] +interface ICorDebugModule : IUnknown +{ + /* + * GetProcess returns the process of which this module is a part. + */ + + HRESULT GetProcess([out] ICorDebugProcess **ppProcess); + + /* + * GetBaseAddress returns the base address of the module. + * + * For modules loaded from NGEN images, the base address will be 0. + */ + + HRESULT GetBaseAddress([out] CORDB_ADDRESS *pAddress); + + /* + * GetAssembly returns the assembly of which this module is a part. + */ + + HRESULT GetAssembly([out] ICorDebugAssembly **ppAssembly); + + /* + * GetName returns a name identifying the module. + * + * For on-disk modules this is a full path. For dynamic modules this + * is just the filename if one was provided. Otherwise, and for other + * in-memory modules, this is just the simple name stored in the module's + * metadata. + */ + + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * EnableJITDebugging controls whether the jitter preserves + * debugging information for methods within this module. + * If bTrackJITInfo is true, then the jitter preserves + * mapping information between the IL version of a function and + * the jitted version for functions in the module. If bAllowJitOpts + * is true, then the jitter will generate code with certain (JIT-specific) + * optimizations. + * + * JITDebug is enabled by default for all modules loaded when the + * debugger is active. Programmatically enabling/disabling these + * settings will override global settings. + * + */ + HRESULT EnableJITDebugging([in] BOOL bTrackJITInfo, + [in] BOOL bAllowJitOpts); + + /* + * EnableClassLoadCallbacks controls whether on not LoadClass and + * UnloadClass callbacks are called for the particular module. + * For non-dynamic modules, they are off by default. + * For dynamic modules, they are on by default and can not be disabled. + */ + + HRESULT EnableClassLoadCallbacks([in] BOOL bClassLoadCallbacks); + + /* + * GetFunctionFromToken returns the ICorDebugFunction from + * metadata information. Returns CORDBG_E_FUNCTION_NOT_IL if + * called with a methodDef that does not refer to an IL method. + * In the EnC case, this will return the most recent version of the function. + */ + + HRESULT GetFunctionFromToken([in] mdMethodDef methodDef, + [out] ICorDebugFunction **ppFunction); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetFunctionFromRVA([in] CORDB_ADDRESS rva, + [out] ICorDebugFunction **ppFunction); + + /* + * GetClassFromToken returns the ICorDebugClass from metadata information. + */ + + HRESULT GetClassFromToken([in] mdTypeDef typeDef, + [out] ICorDebugClass **ppClass); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT CreateBreakpoint([out] ICorDebugModuleBreakpoint **ppBreakpoint); + + /* + * DEPRECATED + */ + + HRESULT GetEditAndContinueSnapshot([out] ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); + + /* + * Return a metadata interface pointer that can be used to examine the + * metadata for this module. + */ + HRESULT GetMetaDataInterface([in] REFIID riid, [out] IUnknown **ppObj); + + + /* + * Return the token for the Module table entry for this object. The token + * may then be passed to the meta data import api's. + */ + HRESULT GetToken([out] mdModule *pToken); + + /* + * If this is a dynamic module, IsDynamic sets *pDynamic to true, otherwise + * sets *pDynamic to false. + * Dynamic modules can continue to grow new classes (receive LoadClass callbacks) even after + * the module is loaded. + */ + HRESULT IsDynamic([out] BOOL *pDynamic); + + /* + * GetGlobalVariableValue returns a value object for the given global + * variable. + */ + HRESULT GetGlobalVariableValue([in] mdFieldDef fieldDef, + [out] ICorDebugValue **ppValue); + + /* + * GetSize returns the size, in bytes, of the module. + * + * For modules loaded from NGEN images, the size will be 0. + */ + HRESULT GetSize([out] ULONG32 *pcBytes); + + /* + * If this is a module that exists only in the debuggee's memory, + * then pInMemory will be set to TRUE. The Runtime supports + * loading assemblies from raw streams of bytes. Such modules are + * called "in memory" modules and they have no on-disk + * representation. + */ + HRESULT IsInMemory([out] BOOL *pInMemory); +}; +#pragma warning(pop) + +/* + * ICorDebugModule2 is a logical extension to ICorDebugModule. + */ +[ + object, + local, + uuid(7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7), + pointer_default(unique) +] +interface ICorDebugModule2 : IUnknown +{ + /* + * SetUserCode sets the user-code status of all the functions on all the classes in + * the module to bIsJustMyCode, except for the functions or classes in the tokens array, + * which it sets to !bIsJustMyCode. + * These settings erase all previous JMC settings in this module. + * JMC status can be refined by calls to SetJMCStatus on the Class and Function. + * Returns S_OK if all functions were set successfully, + * CORDBG_E_FUNCTION_NOT_DEBUGGABLE if some function to be marked TRUE was not + * debuggable. + */ + HRESULT SetJMCStatus([in] BOOL bIsJustMyCode, + [in] ULONG32 cTokens, + [in, size_is(cTokens)] mdToken pTokens[]); + + /* + * ApplyChanges is called to apply an Edit and Continue delta to the running process. + * An EnC delta consists of a delta metadata blob (created by IMetadataEmit2::SaveDelta) + * and a delta IL blob (a method body stream just like the one in an on disk assembly). + * If this operation fails, the debug session is considered to be in an invalid state + * and must be restarted. + */ + HRESULT ApplyChanges([in] ULONG cbMetadata, + [in, size_is(cbMetadata)] BYTE pbMetadata[], + [in] ULONG cbIL, + [in, size_is(cbIL)] BYTE pbIL[]); + + /* + * SetJITCompilerFlags sets the flags that control the JIT compiler. If the set of flags is invalid, + * the function will fail. This function can only be called from within the true LoadModule callback + * for the given module. Attempts to call it after this callback has been delivered or in a "faked" + * LoadModule callback for debugger attach will fail. + */ + + HRESULT SetJITCompilerFlags( [in] DWORD dwFlags ); + + /* + * GetJITCompilerFlags gets the set of flags that control the JIT compiler for this module. + */ + + HRESULT GetJITCompilerFlags( [out] DWORD *pdwFlags ); + + /* + * Resolve an assembly given an AssemblyRef token. Note that + * this will not trigger the loading of assembly. If assembly is not yet loaded, + * this will return an CORDBG_E_CANNOT_RESOLVE_ASSEMBLY error + * + */ + HRESULT ResolveAssembly([in] mdToken tkAssemblyRef, + [out] ICorDebugAssembly **ppAssembly); + +}; + + +/* + ICorDebugFunction represents a managed function. + In the non-EnC case, it is 1:1 with a methoddef metadata token. + For EnC, each version of a function has its own ICorDebugFunction instance. + EnCed functions keep the same metadata tokens, but will get new ICorDebugCode instances. + + ICorDebugFunction does not represent generic typeparameters. That means that there's + an ICDFunction for Func, but not for Func or Func. Get the generic + parameters from ICorDebugIlFrame::EnumerateTypeParameters. +*/ +[ + object, + local, + uuid(CC7BCAF3-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugFunction : IUnknown +{ + /* + * GetModule returns the module for the function. + */ + + HRESULT GetModule([out] ICorDebugModule **ppModule); + + /* + * GetClass returns the class for the function. Returns null if + * the function is not a member. + */ + + HRESULT GetClass([out] ICorDebugClass **ppClass); + + /* + * GetToken returns the metadata methodDef token for the function. + */ + + HRESULT GetToken([out] mdMethodDef *pMethodDef); + + /* + * GetILCode returns the IL code for the function. Returns null + * if there is no IL code for the function. Note that this will + * get the IL code corresponding to this function's EnC version of + * the code in the runtime, if this function has been EnC'd. + */ + + HRESULT GetILCode([out] ICorDebugCode **ppCode); + + /* + * GetNativeCode returns the native code for the function. + * Returns null if there is no native code for the function + * (i.e. it is an IL function which has not been jitted) + * If this function has been jitted multiple times (Eg, generics) this + * will return a random Native Code object. + */ + + HRESULT GetNativeCode([out] ICorDebugCode **ppCode); + + /* + * CreateBreakpoint creates a breakpoint at the start of the function. + * + */ + + HRESULT CreateBreakpoint([out] ICorDebugFunctionBreakpoint **ppBreakpoint); + + /* + * Returns the token for the local variable signature for this function. + * If there is no signature (ie, the function doesn't have any local + * variables), then mdSignatureNil will be returned. + */ + + HRESULT GetLocalVarSigToken([out] mdSignature *pmdSig); + + + /* + * Obtains the latest (largest) EnC version number for this function. + * If this function has never been edited with EnC, this will return + * the same value as ICorDebugFunction2::GetVersionNumber. + */ + HRESULT GetCurrentVersionNumber([out] ULONG32 *pnCurrentVersion); +}; + +/* + ICorDebugFunction2 is a logical extension to ICorDebugFunction. +*/ +[ + object, + local, + uuid(EF0C490B-94C3-4e4d-B629-DDC134C532D8), + pointer_default(unique) +] +interface ICorDebugFunction2 : IUnknown +{ + /* + * Sets the User-code status (for JMC stepping) for this function. + * A JMC stepper will skip non-user code. + * User code must be a subset of debuggable code. + * Returns S_OK if successful, CORDBG_E_FUNCTION_NOT_DEBUGGABLE + * if bIsJustMyCode is TRUE and the function is not debuggable. + */ + HRESULT SetJMCStatus([in] BOOL bIsJustMyCode); + + /* + * IsUserCode outputs whether the function is marked as user code. + * Always outputs FALSE for non-debuggable functions. + * Returns S_OK if successful. + */ + HRESULT GetJMCStatus([out] BOOL * pbIsJustMyCode); + + /* + * Not yet implemented. + */ + + HRESULT EnumerateNativeCode([out] ICorDebugCodeEnum **ppCodeEnum); + + /* + * Obtains the EnC version number of the function represented by this ICorDebugFunction2. + * When a function is edited with EnC, the new function has a larger version number than + * that of any previous version (not necessarily exactly 1 greater). + * This function's version number will be less than or equal to the value returned by + * ICorDebugFunction::GetCurrentVersionNumber. + */ + + HRESULT GetVersionNumber([out] ULONG32 *pnVersion); +}; + + +/* +ICorDebugFunction3 is a logical extension to ICorDebugFunction. +*/ +[ + object, + local, + uuid(09B70F28-E465-482D-99E0-81A165EB0532), + pointer_default(unique) +] +interface ICorDebugFunction3 : IUnknown +{ + /* + * If this function has an active rejit request it will be returned in + * pRejitedILCode. + * If there is no active request (a common case) then *ppRejitedILCode = NULL + * + * A rejit request becomes active just after execution returns from the call + * ICorProfilerCallback4::GetReJITParameters(). It may not yet be jitted + * and threads may still be executing in the original version of the code. + * + * A rejit request becomes inactive during the profiler's call to + * ICorProfInfo::RequestRevert. Even after being reverted a thread can still + * be executing in the rejited code. + */ + HRESULT GetActiveReJitRequestILCode(ICorDebugILCode **ppReJitedILCode); +}; + +/* +ICorDebugFunction4 is a logical extension to ICorDebugFunction. +*/ +[ + object, + local, + uuid(72965963-34fd-46e9-9434-b817fe6e7f43), + pointer_default(unique) +] +interface ICorDebugFunction4 : IUnknown +{ + /* + * Sets a breakpoint at offset 0 of any current or future jitted methods. + */ + HRESULT CreateNativeBreakpoint(ICorDebugFunctionBreakpoint **ppBreakpoint); +}; + +/* + ICorDebugCode represents an IL or native code blob. + + For methods that take offsets, the units are the same as the units on the CordbCode object. + (eg, IL offsets for an IL code object, and native offsets for a native code object) + + V2 allows multiple code-regions. CordbCode presents an abstraction where these + are merged together in a single linear, continuous space. So if the code is split + with 0x5 bytes at address 0x1000, and 0x10 bytes at address 0x2000, + then: + - GetAddress() yields a start address of 0x1000. + - GetSize() is the size of the merged regions = 0x5+ 0x10 = 0x15 bytes. + - The (Offset --> Address) mapping is: + 0x0 --> 0x1000 + 0x1 --> 0x1001 + 0x4 --> 0x1004 + 0x5 --> 0x2000 + 0x6 --> 0x2001 + 0x15 --> 0x2010 + + A caller can get the specific code regions via ICorDebugCode2. +*/ +[ + object, + local, + uuid(CC7BCAF4-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugCode : IUnknown +{ + /* + * IsIL returns whether the code is IL (as opposed to native.) + */ + + HRESULT IsIL([out] BOOL *pbIL); + + /* + * GetFunction returns the function for the code. + */ + + HRESULT GetFunction([out] ICorDebugFunction **ppFunction); + + /* + * GetAddress returns the address of the code. + */ + + HRESULT GetAddress([out] CORDB_ADDRESS *pStart); + + /* + * GetSize returns the size in bytes of the code. + */ + + HRESULT GetSize([out] ULONG32 *pcBytes); + + /* + * CreateBreakpoint creates a breakpoint in the function at the + * given offset. + * + * If this code is IL code, and there is a jitted native version + * of the code, the breakpoint will be applied in the jitted code + * as well. (The same is true if the code is later jitted.) + * + */ + + HRESULT CreateBreakpoint([in] ULONG32 offset, + [out] ICorDebugFunctionBreakpoint **ppBreakpoint); + + /* + * GetCode returns the code of the method, suitable for disassembly. Note + * that instruction boundaries aren't checked. + * This glues together multiple code-regions into a single binary stream. + * Caller must use ICorDebugCode2::GetCodeChunks to get (start,size) for + * code chunks to be able to properly resolve addresses embedded in the instructions. + */ + + HRESULT GetCode([in] ULONG32 startOffset, [in] ULONG32 endOffset, + [in] ULONG32 cBufferAlloc, + [out, size_is(cBufferAlloc), + length_is(*pcBufferSize)] BYTE buffer[], + [out] ULONG32 *pcBufferSize); + + /* + * GetVersionNumber returns the 1 based number identifying the + * version of the code that this ICorDebugCode corresponds to. The + * version number is incremented each time the function is Edit-And- + * Continue'd. + */ + + HRESULT GetVersionNumber([out] ULONG32 *nVersion); + + /* + * GetILToNativeMapping returns a map from IL offsets to native + * offsets for this code. An array of COR_DEBUG_IL_TO_NATIVE_MAP + * structs will be returned, and some of the ilOffsets in this array + * map be the values specified in CorDebugIlToNativeMappingTypes. + * + * Note: this method is only valid for ICorDebugCodes representing + * native code that was jitted from IL code. + * Note: There is no ordering to the array of elements returned, nor + * should you assume that there is or will be. + */ + HRESULT GetILToNativeMapping([in] ULONG32 cMap, + [out] ULONG32 *pcMap, + [out, size_is(cMap), length_is(*pcMap)] + COR_DEBUG_IL_TO_NATIVE_MAP map[]); + + /* + * Not implemented. + */ + HRESULT GetEnCRemapSequencePoints([in] ULONG32 cMap, + [out] ULONG32 *pcMap, + [out, size_is(cMap), length_is(*pcMap)] + ULONG32 offsets[]); +}; + +[ + object, + local, + uuid(5F696509-452F-4436-A3FE-4D11FE7E2347), + pointer_default(unique) +] +interface ICorDebugCode2 : IUnknown +{ + typedef struct _CodeChunkInfo + { + CORDB_ADDRESS startAddr; + ULONG32 length; + } CodeChunkInfo; + + // The native code for a code object may be split up into multiple regions. + // + HRESULT GetCodeChunks( + [in] ULONG32 cbufSize, + [out] ULONG32 * pcnumChunks, + [out, size_is(cbufSize), length_is(*pcnumChunks)] CodeChunkInfo chunks[]); + + + // GetCompilerFlags returns the flags under which this piece of code was JITted or NGENed. + + HRESULT GetCompilerFlags( [out] DWORD *pdwFlags ); +}; + +[ + object, + local, + uuid(D13D3E88-E1F2-4020-AA1D-3D162DCBE966), + pointer_default(unique) +] +interface ICorDebugCode3 : IUnknown +{ + /* + * For the specified IL offset, obtains the native offset where a breakpoint should + * be placed so that the debugger can obtain the return value from a function. + * The provided IL offset should be at a function call site, if not the API will fail. + * If the function call doesn't return a value the API will fail. + * + * Returns: + * S_OK - on success. + * CORDBG_E_INVALID_OPCODE - If the given IL offset site was not a call instruction + * or if the function returns "void". + * CORDBG_E_UNSUPPORTED - If the given IL offset is a proper call, but the return + * type is unsupported for getting return value. + */ + HRESULT GetReturnValueLiveOffset([in] ULONG32 ILoffset, + [in] ULONG32 bufferSize, + [out] ULONG32 *pFetched, + [out, size_is(bufferSize), length_is(*pFetched)] ULONG32 pOffsets[]); +}; + +[ + object, + local, + uuid(18221fa4-20cb-40fa-b19d-9f91c4fa8c14), + pointer_default(unique) +] +interface ICorDebugCode4 : IUnknown +{ + /* + * EnumerateVariableHomes - gives an enum for local variables and arguments + * in the function. + * This may include multiple ICorDebugVariableHomes for the same slot or + * argument index if they have different homes at different points in the + * function. + */ + HRESULT EnumerateVariableHomes([out] ICorDebugVariableHomeEnum **ppEnum); +} + +[ + object, + local, + uuid(598D46C2-C877-42A7-89D2-3D0C7F1C1264), + pointer_default(unique) +] +interface ICorDebugILCode : IUnknown +{ + /* + * Represents an exception clause for a given piece of IL. These fields should be interpretted + * the same was as an EH clause in encoded IL in the ECMA CLI specification. + */ + typedef struct _CorDebugEHClause + { + ULONG32 Flags; + ULONG32 TryOffset; + ULONG32 TryLength; + ULONG32 HandlerOffset; + ULONG32 HandlerLength; + ULONG32 ClassToken; + ULONG32 FilterOffset; + } CorDebugEHClause; + + /* + * Returns a list of EH clauses that were defined for this IL. The EH clause information + * is defined by the CLI specification. + * If cClauses is 0 and pcClauses is non-NULL, *pcClauses will be set to the number of + * available EH clauses. + * If cClauses is non-zero it represents the storage capacity of the clauses array, which + * be filled with at most cClauses entries. *pcClauses will be set to the number of clauses + * actually written into clauses array. + */ + HRESULT GetEHClauses( + [in] ULONG32 cClauses, + [out] ULONG32 * pcClauses, + [out, size_is(cClauses), length_is(*pcClauses)] CorDebugEHClause clauses[]); +} + +[ + object, + local, + uuid(46586093-D3F5-4DB6-ACDB-955BCE228C15), + pointer_default(unique) +] +interface ICorDebugILCode2 : IUnknown +{ + /* + * Returns the token for the local variable signature for this function. + * If there is no signature (ie, the function doesn't have any local + * variables), then mdSignatureNil will be returned. + */ + HRESULT GetLocalVarSigToken([out] mdSignature *pmdSig); + + /* + * GetInstrumentedILMap returns a map from profiler instrumentated IL + * offsets to original method IL offsets. + * + * If the IL hasn't been instrumentated or the mapping wasn't provided + * by a profiler then this function returns S_OK and pcMap = 0. + */ + HRESULT GetInstrumentedILMap([in] ULONG32 cMap, + [out] ULONG32 *pcMap, + [out, size_is(cMap), length_is(*pcMap)] COR_IL_MAP map[]); +} + +/* + ICorDebugClass represents a Class (mdTypeDef) in the IL image. + For generic types, it represents the generic type definition (eg. List) not any of + the specific instantiations (eg. List). + + Use ICorDebugClass2::GetParameterizedType to build an ICorDebugType from an + ICorDebugClass and type parameters. + + Classes live in a module and are uniquely identified by a mdTypeDef. + In other words, you can round-trip a class like so: + ICorDebugClass * pClass1 = ...; // some initial class + + ICorDebugModule * pModule = NULL; + pClass1->GetModule(&pModule); + + mdTypeDef token; + pClass1->GetToken(&token); + + ICorDebugClass * pClass2; + pModule->GetClassFromToken(token, &pClass2); + // Now: pClass1 == pClass2 + +*/ +[ + object, + local, + uuid(CC7BCAF5-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugClass : IUnknown +{ + /* + * GetModule returns the module for the class. + */ + + HRESULT GetModule([out] ICorDebugModule **pModule); + + /* + * GetTypeDefToken returns the metadata typedef token for the class. + */ + + HRESULT GetToken([out] mdTypeDef *pTypeDef); + + /* + * GetStaticFieldValue returns a value object (ICorDebugValue) for the given static field + * variable. If the static field could possibly be relative to either + * a thread, context, or appdomain, then pFrame will help the debugger + * determine the proper value. + * + * Note that if the class accepts type parameters, then you should + * use GetStaticField on an appropriate ICorDebugType rather than on the + * ICorDebugClass. + * + * Returns: + * S_OK on success. + * CORDBG_E_FIELD_NOT_STATIC if the field is not static. + * CORDBG_E_STATIC_VAR_NOT_AVAILABLE if field is not yet available (storage for statics + * may be lazily allocated). + * CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL if the field is actually a metadata literal. In this + * case, the debugger should get the value from the metadata. + * error on other errors. + */ + + HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef, + [in] ICorDebugFrame *pFrame, + [out] ICorDebugValue **ppValue); +}; + +[ + object, + local, + uuid(B008EA8D-7AB1-43f7-BB20-FBB5A04038AE), + pointer_default(unique) +] +interface ICorDebugClass2 : IUnknown +{ + /* + * GetParameterizedType returns a type that corresponds to this class. + * + * If the class is non-generic, i.e. has no type parameters, then + * this simply gets the type object corresponding to the class. + * elementType should be set to the correct element type for the + * class, i.e. ELEMENT_TYPE_VALUETYPE if the class is a value type + * otherwise ELEMENT_TYPE_CLASS. + * + * If the class accepts type parameters, e.g. ArrayList, then + * this function can be used to construct a type object for an + * instantiated type such as ArrayList. + */ + HRESULT GetParameterizedType([in] CorElementType elementType, + [in] ULONG32 nTypeArgs, + [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], + [out] ICorDebugType **ppType); + + /* + * Sets the User-code status (for JMC stepping) for all methods + * in this class. This is functionally equivalent to setting the + * JMCStatus onall methods in this class. + * A JMC stepper will skip non-user code. + * User code must be a subset of debuggable code. + * + * Returns S_OK if all methods are set succesfully. + * Return failure if any are not set. + * On failure, some may still be set. + */ + HRESULT SetJMCStatus([in] BOOL bIsJustMyCode); + +}; + +/* ------------------------------------------------------------------------- * + * Function call interfaces + * ------------------------------------------------------------------------- */ + +/* + * ICorDebugEval collects functionality which requires running code + * inside the debuggee. Note that the operations do not complete until + * ICorDebugProcess::Continue is called, and the EvalComplete callback + * is called. + * + * An ICorDebugEval object is created in the context of a specific + * thread, which will be used to perform the evaluations. + * + * If you need to use this functionality without allowing other threads + * to run, set the DebugState of the program's threads to STOP + * before calling Continue. + * + * Note that since user code is running when the evaluation is in + * progress, any debug events can occur, including class loads, + * breakpoints, etc. Callbacks will be called normally in such a + * case. The state of the Eval will be seen as part of the normal + * program state inspection, the stack chain will be a CHAIN_FUNC_EVAL chain; + * the full debugger API continues to operate as normal. Evals can even be nested. + * + * Also, the user code may never complete due to deadlock or infinite + * looping. In this case you will need to Abort the Eval before + * resuming the program. + * + * All objects and types used in a given func-eval must all reside within the + * same app domain. That app-domain need not be the same as the current + * app domain of the thread. + * + */ + +[ + object, + local, + uuid(CC7BCAF6-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugEval : IUnknown +{ + /* + * CallFunction sets up a function call. Note that if the function + * is virtual, this will perform virtual dispatch. If the function is + * not static, then the first argument must be the "this" object. + * If the function is in an a different AppDomain, a transition will + * occur (but all arguments must also be in the target AppDomain) + */ + + HRESULT CallFunction([in] ICorDebugFunction *pFunction, + [in] ULONG32 nArgs, + [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); + + /* + * NewObject allocates and calls the constructor for an object. + */ + + HRESULT NewObject([in] ICorDebugFunction *pConstructor, + [in] ULONG32 nArgs, + [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); + + /* + * NewObjectNoConstructor allocates a new object without + * attempting to call any constructor on the object. + */ + + HRESULT NewObjectNoConstructor([in] ICorDebugClass *pClass); + + /* + * NewString allocates a string object with the given contents. + * The string is always created in the AppDomain the thread is currently in. + */ + + HRESULT NewString([in] LPCWSTR string); + + /* + * NewArray allocates a new array with the given element type and + * dimensions. If the elementType is a primitive, pElementClass + * may be NULL. Otherwise, pElementClass should be the class of + * the elements of the array. Note: lowBounds is optional. If + * omitted, a zero lower bound for each dimension is assumed. + * The array is always created in the AppDomain the thread is currently in. + * + * NOTE: In the current release, rank must be 1. + */ + + HRESULT NewArray([in] CorElementType elementType, + [in] ICorDebugClass *pElementClass, + [in] ULONG32 rank, + [in, size_is(rank)] ULONG32 dims[], + [in, size_is(rank)] ULONG32 lowBounds[]); + + /* + * IsActive returns whether the func-eval is currently executing. + */ + + HRESULT IsActive([out] BOOL *pbActive); + + /* + * Abort aborts the current computation. Note that in the case of nested + * Evals, this may fail unless it is the most recent Eval. + */ + + HRESULT Abort(); + + /* + * GetResult returns the result of the evaluation. This is only + * valid after the evaluation is completed. + * + * If the evaluation completes normally, the result will be the + * return value. If it terminates with an exception, the result + * is the exception thrown. If the evaluation was for a new object, + * the return value is the reference to the object. + */ + + HRESULT GetResult([out] ICorDebugValue **ppResult); + + /* + * GetThread returns the thread on which this eval will run or is running. + */ + + HRESULT GetThread([out] ICorDebugThread **ppThread); + + /* + * CreateValue creates an ICorDebugValue of the given type for the + * sole purpose of using it in a function evaluation. These can be + * used to pass user constants as parameters. The value has a zero + * or NULL initial value. Use ICorDebugValue::SetValue to + * set the value. + * + * pElementClass is only required for value classes. Pass NULL + * otherwise. + * + * If elementType == ELEMENT_TYPE_CLASS, then you get an + * ICorDebugReferenceValue representing the NULL object reference. + * You can use this to pass NULL to evals that have object reference + * parameters. You cannot set the ICorDebugReferenceValue to + * anything... it always remains NULL. + */ + + HRESULT CreateValue([in] CorElementType elementType, + [in] ICorDebugClass *pElementClass, + [out] ICorDebugValue **ppValue); +}; + +[ + object, + local, + uuid(FB0D9CE7-BE66-4683-9D32-A42A04E2FD91), + pointer_default(unique) +] +interface ICorDebugEval2 : IUnknown +{ + /* + * CallParameterizedFunction is like CallFunction except the function + * may be inside a class with type parameters, or may itself take type + * parameters, or both. The type arguments should be given for the + * class first, then the function. + * + * If the function is in an a different AppDomain, a transition will occur. + * However, all type and value arguments must be in the target AppDomain. + * + * Func-eval can only be performed in limited scenarios. If Call*Function + * fails, then the HR makes a best effort at describing the most general + * possible reason for failure. + */ + + HRESULT CallParameterizedFunction([in] ICorDebugFunction *pFunction, + [in] ULONG32 nTypeArgs, + [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], + [in] ULONG32 nArgs, + [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); + + /* + * CreateValueForType generalizes CreateValue by allowing you to specify an + * arbitrary object type including constructed types such as List. + * Once again the sole purpose is to generate a value to pass for a function evaluation. + * + * The element type of the type must be ELEMENT_TYPE_CLASS or + * ELEMENT_TYPE_VALUE, or one of the simple types. You cannot use this + * to create array values or string values. + */ + + HRESULT CreateValueForType([in] ICorDebugType *pType, + [out] ICorDebugValue **ppValue); + + /* + * NewParameterizedObject allocates and calls the constructor for an object. + * The object may be in a class that includes type parameters. + */ + + HRESULT NewParameterizedObject([in] ICorDebugFunction *pConstructor, + [in] ULONG32 nTypeArgs, + [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], + [in] ULONG32 nArgs, + [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); + + /* + * NewParameterizedObjectNoConstructor allocates a new object without + * attempting to call any constructor on the object. + * The object may be in a class that includes type parameters. + */ + + HRESULT NewParameterizedObjectNoConstructor([in] ICorDebugClass *pClass, + [in] ULONG32 nTypeArgs, + [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[]); + + /* + * NewParamaterizedArray allocates a new array whose elements may be instances + * of a generic type. The array is always created in the AppDomain the thread is + * currently in. + */ + HRESULT NewParameterizedArray([in] ICorDebugType *pElementType, + [in] ULONG32 rank, + [in, size_is(rank)] ULONG32 dims[], + [in, size_is(rank)] ULONG32 lowBounds[]); + + /* + * NewStringWithLength allocates a string object with the given contents. + * The length is specified in uiLength. This is used for user to pass in null + * embedded string. If the string's tailing null is expected to be in + * the managed string, client has to ensure the length including the tailing null. + * + * The string is always created in the AppDomain the thread is currently in. + */ + + HRESULT NewStringWithLength([in] LPCWSTR string, + [in] UINT uiLength); + + /* + * RudeAbort aborts the current computation. Any locks the aborted + * eval was holding are not released, and thus the debugging session + * is in an unsafe state. + */ + + HRESULT RudeAbort(void); + +}; + + +/* ------------------------------------------------------------------------- * + * Runtime value interfaces + * ------------------------------------------------------------------------- */ + +/* + * ICorDebugValue represents a value in the remote process. Note that + * the values can be both Get and Set; they are "lvalues". + * + * In general, ownership of a value object is passed when it is returned. The + * recipient is responsible for removing a reference from the object when + * finished with it. + * + * Depending on where the value was retrieved from, the value may not remain + * valid after the process is resumed, + * so in general they shouldn't be held across continues. + */ + +[ + object, + local, + uuid(CC7BCAF7-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugValue : IUnknown +{ + /* + * GetType returns the simple type of the value. If the object + * has a more complex runtime type, that type may be examined through the + * appropriate subclasses (e.g. ICorDebugObjectValue can get the class of + * an object.) + */ + + HRESULT GetType([out] CorElementType *pType); + + /* + * GetSize returns the size of the value in bytes. Note that for reference + * types this will be the size of the pointer rather than the size of + * the object. + */ + + HRESULT GetSize([out] ULONG32 *pSize); + + /* + * GetAddress returns the address of the value in the debugee + * process. This might be useful information for the debugger to + * show. + * + * If the value is unavailable, 0 is returned. This could happen if + * it is at least partly in registers or stored in a GC Handle. + */ + + HRESULT GetAddress([out] CORDB_ADDRESS *pAddress); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT CreateBreakpoint([out] ICorDebugValueBreakpoint **ppBreakpoint); + +}; + +[ + object, + local, + uuid(5E0B54E7-D88A-4626-9420-A691E0A78B49), + pointer_default(unique) +] +interface ICorDebugValue2 : IUnknown +{ + /* + * GetExactType returns the runtime type of the object in the value. + */ + + HRESULT GetExactType([out] ICorDebugType **ppType); + +}; + +[ + object, + local, + uuid(565005FC-0F8A-4F3E-9EDB-83102B156595), + pointer_default(unique) +] +interface ICorDebugValue3 : IUnknown +{ + /* + * GetSize returns the size of the value in bytes. It has the same + * semantics as ICorDebugValue::GetSize except that it works + * for arrays >4GB. + */ + + HRESULT GetSize64([out] ULONG64 *pSize); + +}; + +/* + * ICorDebugGenericValue is a subclass of ICorDebugValue which applies to + * all values, and can be used to get & set the value. It is a + * separate subinterface because it is non-remotable. + * + * Note that for reference types, the value is the reference rather than + * the contents. + */ + +[ + object, + local, + uuid(CC7BCAF8-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugGenericValue : ICorDebugValue +{ + /* + * GetValue copies the value into the specified buffer. The buffer should + * be the appropriate size for the simple type. + */ + + HRESULT GetValue([out] void *pTo); + + /* + * SetValue copies a new value from the specified buffer. The buffer should + * be the approprirate size for the simple type. + * + */ + + HRESULT SetValue([in] void *pFrom); +}; + +/* ISSUE: an remotable interface for each simple type + * + * It might be nice to have a subclass with a typesafe Get/Set for each simple + * type. + */ + +/* + * ICorDebugReferenceValue is a subclass of ICorDebugValue which applies to + * a reference type. + * The runtime may Garbage Collect objects once the debuggee is continued. The GC may + * move objects around in memory. + * + * An ICorDebugReference will either cooperate with GCs such that its information is updated + * after the GC, or it will be implicitly neutered before the GC. + * + * The ICorDebugReferenceValue inteface may be implicitly neutered after the debuggee + * has been continued. The derived ICorDebugHandleValue is not neutered until explicitly + * released or exposed. + * + */ + +[ + object, + local, + uuid(CC7BCAF9-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugReferenceValue : ICorDebugValue +{ + /* + * IsNull tests whether the reference is null. + */ + + HRESULT IsNull([out] BOOL *pbNull); + + /* + * GetValue returns the current address of the object referred to by this + * reference. + */ + + HRESULT GetValue([out] CORDB_ADDRESS *pValue); + + /* + * SetValue sets this reference to refer to a different address. + */ + + HRESULT SetValue([in] CORDB_ADDRESS value); + + /* + * Dereference returns a ICorDebugValue representing the value + * referenced. This is only valid while the interface has not yet been neutered. + */ + + HRESULT Dereference([out] ICorDebugValue **ppValue); + + /* + * DEPRECATED + */ + + HRESULT DereferenceStrong([out] ICorDebugValue **ppValue); +}; + +/* + * ICorDebugHeapValue is a subclass of ICorDebugValue which represents + * a garbage collected object + */ + +[ + object, + local, + uuid(CC7BCAFA-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugHeapValue : ICorDebugValue +{ + /* + * DEPRECATED. + * All objects are only valid until Continue is called, at which time they are neutered. + */ + + HRESULT IsValid([out] BOOL *pbValid); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT CreateRelocBreakpoint([out] + ICorDebugValueBreakpoint **ppBreakpoint); + +}; + +/* + * ICorDebugHeapValue2 + */ + +[ + object, + local, + uuid(E3AC4D6C-9CB7-43e6-96CC-B21540E5083C), + pointer_default(unique) +] +interface ICorDebugHeapValue2 : IUnknown +{ + + /* + * Creates a handle of the given type for this heap value. + * + */ + HRESULT CreateHandle([in] CorDebugHandleType type, [out] ICorDebugHandleValue ** ppHandle); + +}; + +/* + * ICorDebugHeapValue3 - exposes the monitor lock properties of objects + */ + +[ + object, + local, + uuid(A69ACAD8-2374-46e9-9FF8-B1F14120D296), + pointer_default(unique) +] +interface ICorDebugHeapValue3 : IUnknown +{ + + /* + * Gets the owning thread for a monitor lock + */ + HRESULT GetThreadOwningMonitorLock([out] ICorDebugThread **ppThread, [out] DWORD *pAcquisitionCount); + + /* + * Gets the list of threads waiting on a monitor event + */ + HRESULT GetMonitorEventWaitList([out] ICorDebugThreadEnum **ppThreadEnum); +}; + +/* + * ICorDebugObjectValue is a subclass of ICorDebugValue which applies to + * values which contain an object. + * An ICorDebugObjectValue becomes invalid after the debuggee is continued. + */ + +[ + object, + local, + uuid(18AD3D6E-B7D2-11d2-BD04-0000F80849BD), + pointer_default(unique) +] +interface ICorDebugObjectValue : ICorDebugValue +{ + /* + * GetClass returns the runtime class of the object in the value. + */ + + HRESULT GetClass([out] ICorDebugClass **ppClass); + + /* + * GetFieldValue returns a value for the given field in the given + * class. The class must be on the class hierarchy of the object's + * class, and the field must be a field of that class. + */ + + HRESULT GetFieldValue([in] ICorDebugClass *pClass, + [in] mdFieldDef fieldDef, + [out] ICorDebugValue **ppValue); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetVirtualMethod([in] mdMemberRef memberRef, + [out] ICorDebugFunction **ppFunction); + + /* + * NOT YET IMPLEMENTED + */ + + HRESULT GetContext([out] ICorDebugContext **ppContext); + + /* + * IsValueClass returns true if the the class of this object is + * a value class. + */ + + HRESULT IsValueClass([out] BOOL *pbIsValueClass); + + /* + * DEPRECATED + */ + + HRESULT GetManagedCopy([out] IUnknown **ppObject); + + /* + * DEPRECATED + */ + + HRESULT SetFromManagedCopy([in] IUnknown *pObject); +}; + +[ + object, + local, + uuid(49E4A320-4A9B-4eca-B105-229FB7D5009F), + pointer_default(unique) +] +interface ICorDebugObjectValue2 : IUnknown +{ + /* + * GetVirtualMethodForType returns the most derived function + * for the given ref on this object. + * + * Note: not yet implemented. + */ + + HRESULT GetVirtualMethodAndType([in] mdMemberRef memberRef, + [out] ICorDebugFunction **ppFunction, + [out] ICorDebugType **ppType); +}; + +[ + object, + local, + uuid(3AF70CC7-6047-47F6-A5C5-090A1A622638), + pointer_default(unique) +] +interface ICorDebugDelegateObjectValue : IUnknown +{ + /* + * GetTarget retrieves the object on which the delegate calls the function. + * Returns: + * - S_OK: + * - The ICorDebugReferenceValue object targeted by the function. + * - NULL if the delegate function is a static function or an open delegate + * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. + * In this case, the value of ppObject should not be used. Some of these + * include: Secure wrappers, Open Virual delegates. + */ + HRESULT GetTarget([out] ICorDebugReferenceValue **ppObject); + + /* + * GetFunction returns the function that gets run by the delegate. + * - S_OK: + * - The ICorDebugFunction function for the function the delegate would invoke. + * - There are a few cases where the ICorDebugFunction can be different from what's expected, + * such as generic methods, which won't contain the instantiation. + * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. + * In this case, the value of ppObject should not be used. Some of these + * include: Secure wrappers, Open Virual delegates. + */ + HRESULT GetFunction([out] ICorDebugFunction **ppFunction); +} + + +/* + * ICorDebugBoxValue is a subclass of ICorDebugValue which + * represents a boxed value class object. + */ + +[ + object, + local, + uuid(CC7BCAFC-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugBoxValue : ICorDebugHeapValue +{ + /* + * GetObject returns the value object which is in the box. + */ + + HRESULT GetObject([out] ICorDebugObjectValue **ppObject); +}; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugStringValue */ +/* + * ICorDebugStringValue is a subclass of ICorDebugValue which + * applies to values which contain a string. This interface + * provides an easy way to get the string contents. + */ + +[ + object, + local, + uuid(CC7BCAFD-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugStringValue : ICorDebugHeapValue +{ + /* + * GetLength returns the number of characters in the string. + */ + + HRESULT GetLength([out] ULONG32 *pcchString); + + /* + * GetString returns the contents of the string. + */ + + HRESULT GetString([in] ULONG32 cchString, + [out] ULONG32 *pcchString, + [out, size_is(cchString), + length_is(*pcchString)] WCHAR szString[]); +}; +#pragma warning(pop) + +/* + * ICorDebugArrayValue is a subclass of ICorDebugValue which applies + * to values which contain an array. This interface supports both + * single and multidimension arrays. + */ + +[ + object, + local, + uuid(0405B0DF-A660-11d2-BD02-0000F80849BD), + pointer_default(unique) +] +interface ICorDebugArrayValue : ICorDebugHeapValue +{ + /* + * GetElementType returns the simple type of the elements in the + * array. + */ + + HRESULT GetElementType([out] CorElementType *pType); + + /* + * GetRank returns the number of dimensions in the array. + */ + + HRESULT GetRank([out] ULONG32 *pnRank); + + /* + * GetCount returns the total number of elements in the array. + */ + + HRESULT GetCount([out] ULONG32 *pnCount); + + /* + * GetDimensions returns the dimensions of the array. + */ + + HRESULT GetDimensions([in] ULONG32 cdim, + [out, size_is(cdim), + length_is(cdim)] ULONG32 dims[]); + + /* + * HasBaseIndicies returns whether or not the array has base indicies. + * If the answer is no, then all dimensions have a base index of 0. + */ + + HRESULT HasBaseIndicies([out] BOOL *pbHasBaseIndicies); + + /* + * GetBaseIndicies returns the base index of each dimension in + * the array + */ + + HRESULT GetBaseIndicies([in] ULONG32 cdim, + [out, size_is(cdim), + length_is(cdim)] ULONG32 indicies[]); + + /* + * GetElement returns a value representing the given element in the array. + * The indices array must not be null. + */ + + HRESULT GetElement([in] ULONG32 cdim, + [in, size_is(cdim), + length_is(cdim)] ULONG32 indices[], + [out] ICorDebugValue **ppValue); + /* + * GetElementAtPosition returns the element at the given position, + * treating the array as a zero-based, single-dimensional array. + * + * Multidimensional array layout follows the C++ style of array layout. + */ + + HRESULT GetElementAtPosition([in] ULONG32 nPosition, + [out] ICorDebugValue **ppValue); +}; + +[ + object, + local, + uuid(50847b8d-f43f-41b0-924c-6383a5f2278b), + pointer_default(unique) +] +interface ICorDebugVariableHome : IUnknown +{ + /* + * GetCode - gives the ICorDebugCode instance containing this + * ICorDebugVariableHome. + */ + HRESULT GetCode([out] ICorDebugCode **ppCode); + /* + * GetSlotIndex - gives the managed slot-index of a local variable. + * The slot-index can be used to retrieve the metadata for this local. + * Returns E_FAIL if the variable is a function argument. + */ + HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex); + + /* + * GetArgumentIndex - gives the argument index of a function argument. + * The argument index can be used to retrieve the metadata for this + * argument. + * Returns E_FAIL if the variable is a local variable. + */ + HRESULT GetArgumentIndex([out] ULONG32* pArgumentIndex); + + /* + * GetLiveRange - gives the native range over which this variable is live. + * pStartOffset is the logical offset at which the variable is first live. + * pEndOffset is the logical offset immediately after that at which the + * variable is last live. + */ + HRESULT GetLiveRange([out] ULONG32* pStartOffset, + [out] ULONG32 *pEndOffset); + + typedef enum VariableLocationType + { + VLT_REGISTER, // variable is in a register + VLT_REGISTER_RELATIVE, // variable is in a register-relative memory + // location + VLT_INVALID + } VariableLocationType; + + /* + * GetLocationType - gives the type of native location. See + * VariableLocationType. + * Returns VLT_INVALID if the variable is not stored in a register or in a + * register-relative memory location. + */ + HRESULT GetLocationType([out] VariableLocationType *pLocationType); + + /* + * GetRegister - gives the register containing the variables with location + * type VLT_REGISTER, and the base register for variables with location + * type VLT_REGISTER_RELATIVE. + * Returns E_FAIL if the variable is not in a register or in a + * register-relative location. + */ + HRESULT GetRegister([out] CorDebugRegister *pRegister); + + /* + * GetOffset - gives the offset from the base register for a variable. + * Returns E_FAIL if the variable is not in a register-relative memory + * location. + */ + HRESULT GetOffset([out] LONG *pOffset); +} + + + +/* + * ICorDebugHandleValue represents a reference value that the debugger has + * explicitly created a GC handle to. It does not represent GC Handles in the debuggee process, + + * A normal ICorDebugReference becomes neutered after the debuggee has been + * continued. A ICorDebugHandleValue will survive across continues and can be + * dereferenced until the client explcitly disposes the handle. + * + * + * ICorDebugHeapValu2::CreateHandle will create ICorDebugHandleValue + */ +[ + object, + local, + uuid(029596E8-276B-46a1-9821-732E96BBB00B), + pointer_default(unique) +] +interface ICorDebugHandleValue : ICorDebugReferenceValue +{ + /* + * returns the type of this handle. + * + */ + HRESULT GetHandleType([out] CorDebugHandleType *pType); + + + /* + * The final release of the interface will also dispose of the handle. This + * API provides the ability for client to early dispose the handle. + * + */ + HRESULT Dispose(); + +}; + + +/* + * ICorDebugContext represents a context object. + * + * Interface TBD. + */ + +[ + object, + local, + uuid(CC7BCB00-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugContext : ICorDebugObjectValue +{ +}; + + +/* + * ICorDebugComObjectValue applies to values which contain a COM object. + * An ICorDebugComObjectValue becomes invalid after the debuggee is continued. + */ + +[ + object, + local, + uuid(5F69C5E5-3E12-42DF-B371-F9D761D6EE24), + pointer_default(unique) +] +interface ICorDebugComObjectValue : IUnknown +{ + /* + * GetCachedInterfaceTypes returns an enum of the types of all interfaces + * that are cached by the COM object. + */ + HRESULT GetCachedInterfaceTypes( + [in] BOOL bIInspectableOnly, + [out] ICorDebugTypeEnum **ppInterfacesEnum); + + /* + * GetCachedInterfacePointers returns at most celt values of the + * interface pointer values cached by the COM object. It fills + * pcEltFetched with the actual number of fetched elements. + * When called with NULL for ptrs, and 0 for celt, it simply returns + * the number of elements it needs. + */ + HRESULT GetCachedInterfacePointers( + [in] BOOL bIInspectableOnly, + [in] ULONG32 celt, + [out] ULONG32 *pcEltFetched, + [out, size_is(celt), length_is(*pcEltFetched)] CORDB_ADDRESS * ptrs); +}; + +/* ------------------------------------------------------------------------- * + * Enum interfaces + * ------------------------------------------------------------------------- */ + +/* + * ICorDebugEnum is an abstract enumerator. + */ + +[ + object, + local, + uuid(CC7BCB01-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugEnum : IUnknown +{ + /* + * Moves the current position forward the given number of + * elements. + */ + HRESULT Skip([in] ULONG celt); + + /* + * Sets the position of the enumerator to the beginning of the + * enumeration. + */ + HRESULT Reset(); + + /* + * Creates another enumerator with the same current position + * as this one. + */ + HRESULT Clone([out] ICorDebugEnum **ppEnum); + + /* + * Gets the number of elements in the enumeration + */ + HRESULT GetCount([out] ULONG *pcelt); +}; + +[ + object, + local, + uuid(CC7BCB02-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugObjectEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of objects in the enumeration. + * The actual number of objects retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of objects retrieved is smaller + * than the number of objects requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), + length_is(*pceltFetched)] CORDB_ADDRESS objects[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB03-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] + +interface ICorDebugBreakpointEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of breakpoints in the enumeration. + * The actual number of breakpoints retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of breakpoints retrieved is smaller + * than the number of breakpoints requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugBreakpoint *breakpoints[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB04-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] + +interface ICorDebugStepperEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of steppers in the enumeration. + * The actual number of steppers retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of steppers retrieved is smaller + * than the number of steppers requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugStepper *steppers[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB05-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugProcessEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of processes in the enumeration. + * The actual number of processes retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of processes retrieved is smaller + * than the number of processes requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugProcess *processes[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB06-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugThreadEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of threads in the enumeration. + * The actual number of threads retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of threads retrieved is smaller + * than the number of threads requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugThread *threads[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB07-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugFrameEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of frames in the enumeration. + * The actual number of frames retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of frames retrieved is smaller + * than the number of frames requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugFrame *frames[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB08-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugChainEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of chains in the enumeration. + * The actual number of chains retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of chains retrieved is smaller + * than the number of chains requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugChain *chains[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB09-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugModuleEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of modules in the enumeration. + * The actual number of modules retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of modules retrieved is smaller + * than the number of modules requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugModule *modules[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(CC7BCB0A-8A68-11d2-983C-0000F808342D), + pointer_default(unique) +] +interface ICorDebugValueEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of values in the enumeration. + * The actual number of values retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of values retrieved is smaller + * than the number of values requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugValue *values[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(e76b7a57-4f7a-4309-85a7-5d918c3deaf7), + pointer_default(unique) +] +interface ICorDebugVariableHomeEnum : ICorDebugEnum +{ + /* + * Next - gives the specified number of ICorDebugVariableHome instances from + * the enumeration, starting at the current position. + * celt is the number of requested instances. + * pceltFetched is the number of instances retrieved. + * returns S_FALSE if the actual number of instances retrieved is smaller + * than the number of instances requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugVariableHome *homes[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(55E96461-9645-45e4-A2FF-0367877ABCDE), + pointer_default(unique) +] +interface ICorDebugCodeEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of code objects in the enumeration. + * The actual number of code objects retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of code objects retrieved is smaller + * than the number of code objects requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugCode *values[], + [out] ULONG *pceltFetched); +}; + +[ + object, + local, + uuid(10F27499-9DF2-43ce-8333-A321D7C99CB4), + pointer_default(unique) +] +interface ICorDebugTypeEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of types in the enumeration. + * The actual number of types retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of types retrieved is smaller + * than the number of types requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugType *values[], + [out] ULONG *pceltFetched); +}; + + + +/* + * ICorDebugType represents an instantiated type in the debugggee. + * Unlike ICorDebugClass, it can store type-parameter information and thus can + * represent instantiated generic types (Eg, List) + * Use the metadata interfaces to get static (Compile-time) information about the type. + * + * A type (and all of its type parameters) lives in an single AppDomain and becomes + * invalid once the containing ICorDebugAppDomain is unloaded. + * + * Types may be lazily loaded, so if the debugger queries for a type that hasn't been + * loaded yet, it may be unavailable. + */ +[ + object, + local, + uuid(D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5), + pointer_default(unique) +] +interface ICorDebugType : IUnknown +{ + /* + * GetType gets the basic type of the generic parameter. This can be used to + * determine if it is necessary to call GetClass to find the full information for the + * generic type parameter. + */ + HRESULT GetType([out] CorElementType *ty); + + /* + * GetClass is used if the CorElementType returned by GetType is ELEMENT_TYPE_CLASS, + * ELEMENT_TYPE_VALUETYPE. If the type is a constructed type, e.g. List, + * then this will return the ICorDebugClass for the type constructor, i.e. "List". + * + * GetClass should not be used if the element type is anything other than these two element + * types. In particular, it may not be used if the element type is ELEMENT_TYPE_STRING. + */ + HRESULT GetClass([out] ICorDebugClass **ppClass); + + /* + * EnumerateTypeParameters may be used if the CorElementType + * returned by GetType is one of ELEMENT_TYPE_CLASS, + * ELEMENT_TYPE_VALUETYPE, ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY, + * ELEMENT_TYPE_BYREF, ELEMENT_TYPE_PTR or ELEMENT_TYPE_FNPTR. + * It returns the parameters specifying further information about + * the type. For example, if the type is "class Dict" + * then EnumerateTypeParameters will return "String" and "int32" + * in sequence. + * + */ + HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum); + + /* + * GetFirstTypeParameter can be used in those cases where the further + * information about the type involves at most one type + * parameter. You can determine this from the element type returned by + * GetType. In particular it may be used with + * ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY, ELEMENT_TYPE_BYREF + * or ELEMENT_TYPE_PTR. + * This can only be called if the type does indeed have a type-parameter. + */ + HRESULT GetFirstTypeParameter([out] ICorDebugType **value); + + /* + * GetBase returns the ICorDebugType object for the base type of this type, if it + * has one, i.e. if the type is a class type. + * For example, if + * class MyStringDict : Dict + * then the base type of "MyStringDict" will be "Dict". + * + * This is a helper function - you could compute this from EnumerateTypeParemeters, + * GetClass and the relevant metadata, but it is relatively painful: you would + * have to lookup the class, then the metadata of that class + * to find the "generic" base type, then instantiate this generic base type by + * looking up the type paramaters to the initial type, + * and then perform the appropriate instantiation in the case where the class + * happens to be either a generic class or a normal class with a constructed type + * as its parent. Looking up the base types is useful to implement common + * debugger functionality, e.g. printing out all the fields of an object, including its + * superclasses. + * + */ + + HRESULT GetBase([out] ICorDebugType **pBase); + + /* + * GetStaticFieldValue returns a value object (ICorDebugValue) + * for the given static field variable. For non-parameterized + * types, this is identical to calling GetStaticFieldValue on the + * ICorDebugClass object returned by ICorDebugType::GetClass. + * For parameterized types a static field value will be relative to a + * particular instantiation. If in addition the static field could + * possibly be relative to either a thread, context, or appdomain, then pFrame + * will help the debugger determine the proper value. + * + * This may only be used when ICorDebugType::GetType returns + * ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE. + */ + HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef, + [in] ICorDebugFrame *pFrame, + [out] ICorDebugValue **ppValue); + + + /* + * GetRank returns the number of dimensions in an array type + */ + + HRESULT GetRank([out] ULONG32 *pnRank); + +}; + + +[ + object, + local, + uuid(e6e91d79-693d-48bc-b417-8284b4f10fb5), + pointer_default(unique) +] +interface ICorDebugType2 : IUnknown +{ + /* + * GetTypeID - gives a COR_TYPEID for the ICorDebugType. This + * provides a mapping from the ICorDebugType, which represents a + * type that may or may not have been loaded into the runtime, to + * a COR_TYPEID, which serves as an opaque handle identifying a + * type loaded into the runtime. When the type that the + * ICorDebugType represents has not yet been loaded, this returns + * CORDBG_E_CLASS_NOT_LOADED. Returns CORDBG_E_UNSUPPORTED for + * unsupported types. + */ + HRESULT GetTypeID([out] COR_TYPEID *id); +}; + + +/* ------------------------------------------------------------------------- * + * DEPRECATED + * + * ICorDebugErrorInfoEnum interface + * + * ------------------------------------------------------------------------- */ +[ + object, + local, + uuid(F0E18809-72B5-11d2-976F-00A0C9B4D50C), + pointer_default(unique) +] +interface ICorDebugErrorInfoEnum : ICorDebugEnum +{ + /* + * DEPRECATED + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugEditAndContinueErrorInfo *errors[], + [out] ULONG *pceltFetched); +}; + +/* ------------------------------------------------------------------------- * + * AppDomainEnum interface + * ------------------------------------------------------------------------- */ + +[ + object, + local, + uuid(63ca1b24-4359-4883-bd57-13f815f58744), + pointer_default(unique) +] + +interface ICorDebugAppDomainEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" app domains in the enumeration + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugAppDomain *values[], + [out] ULONG *pceltFetched); + +}; + + +/* ------------------------------------------------------------------------- * + * AssemblyEnum interface + * ------------------------------------------------------------------------- */ + +[ + object, + local, + uuid(4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83), + pointer_default(unique) +] + +interface ICorDebugAssemblyEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" assemblies in the enumeration + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ICorDebugAssembly *values[], + [out] ULONG *pceltFetched); + +}; + +/* ------------------------------------------------------------------------- * + * BlockingObjectEnum interface + * ------------------------------------------------------------------------- */ + +[ + object, + local, + uuid(976A6278-134A-4a81-81A3-8F277943F4C3), + pointer_default(unique) +] + +interface ICorDebugBlockingObjectEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" blocking objects in the enumeration + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + CorDebugBlockingObject values[], + [out] ULONG *pceltFetched); + +}; + + +#pragma warning(push) +#pragma warning(disable:28718) +// Represent data for an Managed Debugging Assistant (MDA) notification. See the MDA documentation for MDA-specific information like: +// - enabling / disabling MDAs +// - MDA naming conventions +// - What the contents of an MDA look like, schemas, etc. +[ + object, + local, + uuid(CC726F2F-1DB7-459b-B0EC-05F01D841B42), + pointer_default(unique) +] +interface ICorDebugMDA : IUnknown +{ + // Get the string for the type of the MDA. Never empty. + // This is a convenient performant alternative to getting the XML stream and extracting + // the type from that based off the schema. + HRESULT GetName( + [in] ULONG32 cchName, + [out] ULONG32 * pcchName, + [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + // Get a string description of the MDA. This may be empty (0-length). + HRESULT GetDescription( + [in] ULONG32 cchName, + [out] ULONG32 * pcchName, + [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + // Get the full associated XML for the MDA. This may be empty. + // This could be a potentially expensive operation if the xml stream is large. + // See the MDA documentation for the schema for this XML stream. + HRESULT GetXML( + [in] ULONG32 cchName, + [out] ULONG32 * pcchName, + [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); + + // Get the flags associated w/ the MDA. New flags may be added in future versions. + typedef enum CorDebugMDAFlags + { + // If this flag is high, then the thread may have slipped since the MDA was fired. + MDA_FLAG_SLIP = 0x2 + } CorDebugMDAFlags; + HRESULT GetFlags([in] CorDebugMDAFlags * pFlags); + + // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a + // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread + // object for it yet) + HRESULT GetOSThreadId([out] DWORD * pOsTid); +}; +#pragma warning(pop) + +/* ------------------------------------------------------------------------- * + * Edit and Continue interfaces + * DEPRECATED + * ------------------------------------------------------------------------- */ +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugEditAndContinueErrorInfo */ +/* + * DEPRECATED + * + * ICorDebugEditAndContinueErrorInfo + * + */ +[ + object, + local, + uuid(8D600D41-F4F6-4cb3-B7EC-7BD164944036), + pointer_default(unique) +] +interface ICorDebugEditAndContinueErrorInfo : IUnknown +{ + /* + * DEPRECATED + */ + HRESULT GetModule([out] ICorDebugModule **ppModule); + + /* + * DEPRECATED + */ + HRESULT GetToken([out]mdToken *pToken); + + /* + * DEPRECATED + */ + HRESULT GetErrorCode([out]HRESULT *pHr); + + /* + * DEPRECATED + */ + HRESULT GetString([in] ULONG32 cchString, + [out] ULONG32 *pcchString, + [out, size_is(cchString), + length_is(*pcchString)] WCHAR szString[]); +} +#pragma warning(pop) + +/* + * DEPRECATED + * + * ICorDebugEditAndContinueSnapshot + */ + +[ + object, + local, + uuid(6DC3FA01-D7CB-11d2-8A95-0080C792E5D8), + pointer_default(unique) +] +interface ICorDebugEditAndContinueSnapshot : IUnknown +{ + /* + * DEPRECATED + */ + HRESULT CopyMetaData([in] IStream *pIStream, [out] GUID *pMvid); + + /* + * DEPRECATED + */ + HRESULT GetMvid([out] GUID *pMvid); + + /* + * DEPRECATED + */ + HRESULT GetRoDataRVA([out] ULONG32 *pRoDataRVA); + + /* + * DEPRECATED + */ + HRESULT GetRwDataRVA([out] ULONG32 *pRwDataRVA); + + + /* + * DEPRECATED + */ + HRESULT SetPEBytes([in] IStream *pIStream); + + /* + * DEPRECATED + */ + HRESULT SetILMap([in] mdToken mdFunction, [in] ULONG cMapSize, + [in, size_is(cMapSize)] COR_IL_MAP map[]); + + /* + * DEPRECATED + */ + HRESULT SetPESymbolBytes([in] IStream *pIStream); +}; + +[ + object, + local, + uuid(ED775530-4DC4-41F7-86D0-9E2DEF7DFC66), + pointer_default(unique) +] +interface ICorDebugExceptionObjectCallStackEnum : ICorDebugEnum +{ + /* + * Gets the next "celt" number of frames in the enumeration. + * The actual number of frames retrieved is returned in "pceltFetched". + * Returns S_FALSE if the actual number of frames retrieved is smaller + * than the number of frames requested. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + CorDebugExceptionObjectStackFrame values[], + [out] ULONG* pceltFetched); +}; + +[ + object, + local, + uuid(AE4CA65D-59DD-42A2-83A5-57E8A08D8719), + pointer_default(unique) +] +interface ICorDebugExceptionObjectValue : IUnknown +{ + HRESULT EnumerateExceptionCallStack([out] ICorDebugExceptionObjectCallStackEnum** ppCallStackEnum); +}; + +/* ------------------------------------------------------------------------- * + * Library definition + * ------------------------------------------------------------------------- */ + +[ + uuid(53D13620-F417-11d1-9762-A63826A4F255), + version(1.0), + helpstring("Common Language Runtime Debugging 1.0 Type Library") +] +library CORDBLib +{ + importlib("stdole32.tlb"); + + // There should be no co-class for V2.0 CorDebug at all. + // Clients should create the ICorDebug object using the shim API + // CreateDebuggerInterfaceFromVersion defined in mscoree.idl. + // This guid here is the same as the v1.1 guid for setup / breaking-change purposes. + [ + uuid(6fef44d0-39e7-4c77-be8e-c9f8cf988630) + ] + coclass CorDebug + { + [default] interface ICorDebug; + }; + + [ + uuid(211f1254-bc7e-4af5-b9aa-067308d83dd1) + ] + coclass EmbeddedCLRCorDebug + { + [default] interface ICorDebug; + }; + + interface ICorDebugReferenceValue; + interface ICorDebugStringValue; + interface ICorDebugGenericValue; + interface ICorDebugBoxValue; + interface ICorDebugArrayValue; + interface ICorDebugILFrame; + interface ICorDebugInternalFrame; + interface ICorDebugInternalFrame2; + interface ICorDebugNativeFrame; + interface ICorDebugNativeFrame2; + interface ICorDebugRuntimeUnwindableFrame; + + interface ICorDebugManagedCallback2; + interface ICorDebugAppDomain2; + interface ICorDebugAppDomain3; + interface ICorDebugAssembly2; + interface ICorDebugProcess2 ; + interface ICorDebugStepper2 ; + interface ICorDebugThread2 ; + interface ICorDebugThread3 ; + interface ICorDebugILFrame2; + interface ICorDebugModule2 ; + interface ICorDebugFunction2; + interface ICorDebugClass2 ; + interface ICorDebugEval2 ; + interface ICorDebugValue2; + interface ICorDebugObjectValue2; + interface ICorDebugHandleValue; + interface ICorDebugHeapValue2; + interface ICorDebugComObjectValue; + + interface ICorDebugModule3; +}; diff --git a/lib/coreclr/src/inc/cordebuginfo.h b/lib/coreclr/src/inc/cordebuginfo.h new file mode 100644 index 0000000000..bbe4de8739 --- /dev/null +++ b/lib/coreclr/src/inc/cordebuginfo.h @@ -0,0 +1,337 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Keep in sync with https://github.com/dotnet/corert/blob/master/src/Native/ObjWriter/cordebuginfo.h +// + +/**********************************************************************************/ +// DebugInfo types shared by JIT-EE interface and EE-Debugger interface + +class ICorDebugInfo +{ +public: + /*----------------------------- Boundary-info ---------------------------*/ + + enum MappingTypes + { + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3, + MAX_MAPPING_VALUE = -3 // Sentinal value. This should be set to the largest magnitude value in the enum + // so that the compression routines know the enum's range. + }; + + enum BoundaryTypes + { + NO_BOUNDARIES = 0x00, // No implicit boundaries + STACK_EMPTY_BOUNDARIES = 0x01, // Boundary whenever the IL evaluation stack is empty + NOP_BOUNDARIES = 0x02, // Before every CEE_NOP instruction + CALL_SITE_BOUNDARIES = 0x04, // Before every CEE_CALL, CEE_CALLVIRT, etc instruction + + // Set of boundaries that debugger should always reasonably ask the JIT for. + DEFAULT_BOUNDARIES = STACK_EMPTY_BOUNDARIES | NOP_BOUNDARIES | CALL_SITE_BOUNDARIES + }; + + // Note that SourceTypes can be OR'd together - it's possible that + // a sequence point will also be a stack_empty point, and/or a call site. + // The debugger will check to see if a boundary offset's source field & + // SEQUENCE_POINT is true to determine if the boundary is a sequence point. + + enum SourceTypes + { + SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies + SEQUENCE_POINT = 0x01, // The debugger asked for it. + STACK_EMPTY = 0x02, // The stack is empty here + CALL_SITE = 0x04, // This is a call site. + NATIVE_END_OFFSET_UNKNOWN = 0x08, // Indicates a epilog endpoint + CALL_INSTRUCTION = 0x10 // The actual instruction of a call. + + }; + + struct OffsetMapping + { + DWORD nativeOffset; + DWORD ilOffset; + SourceTypes source; // The debugger needs this so that + // we don't put Edit and Continue breakpoints where + // the stack isn't empty. We can put regular breakpoints + // there, though, so we need a way to discriminate + // between offsets. + }; + + /*------------------------------ Var-info -------------------------------*/ + + // Note: The debugger needs to target register numbers on platforms other than which the debugger itself + // is running. To this end it maintains its own values for REGNUM_SP and REGNUM_AMBIENT_SP across multiple + // platforms. So any change here that may effect these values should be reflected in the definitions + // contained in debug/inc/DbgIPCEvents.h. + enum RegNum + { +#ifdef _TARGET_X86_ + REGNUM_EAX, + REGNUM_ECX, + REGNUM_EDX, + REGNUM_EBX, + REGNUM_ESP, + REGNUM_EBP, + REGNUM_ESI, + REGNUM_EDI, +#elif _TARGET_ARM_ + REGNUM_R0, + REGNUM_R1, + REGNUM_R2, + REGNUM_R3, + REGNUM_R4, + REGNUM_R5, + REGNUM_R6, + REGNUM_R7, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_SP, + REGNUM_LR, + REGNUM_PC, +#elif _TARGET_ARM64_ + REGNUM_X0, + REGNUM_X1, + REGNUM_X2, + REGNUM_X3, + REGNUM_X4, + REGNUM_X5, + REGNUM_X6, + REGNUM_X7, + REGNUM_X8, + REGNUM_X9, + REGNUM_X10, + REGNUM_X11, + REGNUM_X12, + REGNUM_X13, + REGNUM_X14, + REGNUM_X15, + REGNUM_X16, + REGNUM_X17, + REGNUM_X18, + REGNUM_X19, + REGNUM_X20, + REGNUM_X21, + REGNUM_X22, + REGNUM_X23, + REGNUM_X24, + REGNUM_X25, + REGNUM_X26, + REGNUM_X27, + REGNUM_X28, + REGNUM_FP, + REGNUM_LR, + REGNUM_SP, + REGNUM_PC, +#elif _TARGET_AMD64_ + REGNUM_RAX, + REGNUM_RCX, + REGNUM_RDX, + REGNUM_RBX, + REGNUM_RSP, + REGNUM_RBP, + REGNUM_RSI, + REGNUM_RDI, + REGNUM_R8, + REGNUM_R9, + REGNUM_R10, + REGNUM_R11, + REGNUM_R12, + REGNUM_R13, + REGNUM_R14, + REGNUM_R15, +#else + PORTABILITY_WARNING("Register numbers not defined on this platform") +#endif + REGNUM_COUNT, + REGNUM_AMBIENT_SP, // ambient SP support. Ambient SP is the original SP in the non-BP based frame. + // Ambient SP should not change even if there are push/pop operations in the method. + +#ifdef _TARGET_X86_ + REGNUM_FP = REGNUM_EBP, + REGNUM_SP = REGNUM_ESP, +#elif _TARGET_AMD64_ + REGNUM_SP = REGNUM_RSP, +#elif _TARGET_ARM_ +#ifdef REDHAWK + REGNUM_FP = REGNUM_R7, +#else + REGNUM_FP = REGNUM_R11, +#endif //REDHAWK +#elif _TARGET_ARM64_ + //Nothing to do here. FP is already alloted. +#else + // RegNum values should be properly defined for this platform + REGNUM_FP = 0, + REGNUM_SP = 1, +#endif + + }; + + // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF + // are only used for value types on X64. + + enum VarLocType + { + VLT_REG, // variable is in a register + VLT_REG_BYREF, // address of the variable is in a register + VLT_REG_FP, // variable is in an fp register + VLT_STK, // variable is on the stack (memory addressed relative to the frame-pointer) + VLT_STK_BYREF, // address of the variable is on the stack (memory addressed relative to the frame-pointer) + VLT_REG_REG, // variable lives in two registers + VLT_REG_STK, // variable lives partly in a register and partly on the stack + VLT_STK_REG, // reverse of VLT_REG_STK + VLT_STK2, // variable lives in two slots on the stack + VLT_FPSTK, // variable lives on the floating-point stack + VLT_FIXED_VA, // variable is a fixed argument in a varargs function (relative to VARARGS_HANDLE) + + VLT_COUNT, + VLT_INVALID, + }; + + // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) + // eg. EAX + // VLT_REG_BYREF -- the specified register contains the address of the variable + // eg. [EAX] + + struct vlReg + { + RegNum vlrReg; + }; + + // VLT_STK -- Any 32 bit value which is on the stack + // eg. [ESP+0x20], or [EBP-0x28] + // VLT_STK_BYREF -- the specified stack location contains the address of the variable + // eg. mov EAX, [ESP+0x20]; [EAX] + + struct vlStk + { + RegNum vlsBaseReg; + signed vlsOffset; + }; + + // VLT_REG_REG -- TYP_LONG with both DWords enregistred + // eg. RBM_EAXEDX + + struct vlRegReg + { + RegNum vlrrReg1; + RegNum vlrrReg2; + }; + + // VLT_REG_STK -- Partly enregistered TYP_LONG + // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } + + struct vlRegStk + { + RegNum vlrsReg; + struct + { + RegNum vlrssBaseReg; + signed vlrssOffset; + } vlrsStk; + }; + + // VLT_STK_REG -- Partly enregistered TYP_LONG + // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } + + struct vlStkReg + { + struct + { + RegNum vlsrsBaseReg; + signed vlsrsOffset; + } vlsrStk; + RegNum vlsrReg; + }; + + // VLT_STK2 -- Any 64 bit value which is on the stack, + // in 2 successsive DWords. + // eg 2 DWords at [ESP+0x10] + + struct vlStk2 + { + RegNum vls2BaseReg; + signed vls2Offset; + }; + + // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) + // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk") + + struct vlFPstk + { + unsigned vlfReg; + }; + + // VLT_FIXED_VA -- fixed argument of a varargs function. + // The argument location depends on the size of the variable + // arguments (...). Inspecting the VARARGS_HANDLE indicates the + // location of the first arg. This argument can then be accessed + // relative to the position of the first arg + + struct vlFixedVarArg + { + unsigned vlfvOffset; + }; + + // VLT_MEMORY + + struct vlMemory + { + void *rpValue; // pointer to the in-process + // location of the value. + }; + + struct VarLoc + { + VarLocType vlType; + + union + { + ICorDebugInfo::vlReg vlReg; + ICorDebugInfo::vlStk vlStk; + ICorDebugInfo::vlRegReg vlRegReg; + ICorDebugInfo::vlRegStk vlRegStk; + ICorDebugInfo::vlStkReg vlStkReg; + ICorDebugInfo::vlStk2 vlStk2; + ICorDebugInfo::vlFPstk vlFPstk; + ICorDebugInfo::vlFixedVarArg vlFixedVarArg; + ICorDebugInfo::vlMemory vlMemory; + }; + }; + + // This is used to report implicit/hidden arguments + + enum + { + VARARGS_HND_ILNUM = -1, // Value for the CORINFO_VARARGS_HANDLE varNumber + RETBUF_ILNUM = -2, // Pointer to the return-buffer + TYPECTXT_ILNUM = -3, // ParamTypeArg for CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG + + UNKNOWN_ILNUM = -4, // Unknown variable + + MAX_ILNUM = -4 // Sentinal value. This should be set to the largest magnitude value in th enum + // so that the compression routines know the enum's range. + }; + + struct ILVarInfo + { + DWORD startOffset; + DWORD endOffset; + DWORD varNumber; + }; + + struct NativeVarInfo + { + DWORD startOffset; + DWORD endOffset; + DWORD varNumber; + VarLoc loc; + }; +}; diff --git a/lib/coreclr/src/inc/coredistools.h b/lib/coreclr/src/inc/coredistools.h new file mode 100644 index 0000000000..54146058e8 --- /dev/null +++ b/lib/coreclr/src/inc/coredistools.h @@ -0,0 +1,149 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//===--------- coredistools.h - Dissassembly tools for CoreClr ------------===// +// +// Core Disassembly Tools API Version 1.0.1-prerelease +// Disassembly tools required by CoreCLR for utilities like +// GCStress and SuperPMI +//===----------------------------------------------------------------------===// + +#if !defined(_COREDISTOOLS_H_) +#define _COREDISTOOLS_H_ + +#include + +#if defined(__cplusplus) +#define EXTERN_C extern "C" +#else +#define EXTERN_C +#endif // defined(__cplusplus) + +#if defined(_MSC_VER) +#if defined(DllInterfaceExporter) +#define DllIface EXTERN_C __declspec(dllexport) +#else +#define DllIface EXTERN_C __declspec(dllimport) +#endif // defined(DllInterfaceExporter) +#else +#if !defined(__cdecl) +#if defined(__i386__) +#define __cdecl __attribute__((cdecl)) +#else +#define __cdecl +#endif +#endif +#define DllIface EXTERN_C +#endif // defined(_MSC_VER) + +enum TargetArch { + Target_Host, // Target is the same as host architecture + Target_X86, + Target_X64, + Target_Thumb, + Target_Arm64 +}; + +struct CorDisasm; +struct CorAsmDiff; + +// The custom print functionality to be provide by the +// users of this Library +typedef void(__cdecl *Printer)(const char *msg, ...); +struct PrintControl { + const Printer Error; + const Printer Warning; + const Printer Log; + const Printer Dump; +}; + +// The type of a custom function provided by the user to determine +// if two offsets are considered equivalent wrt diffing code blocks. +// Offset1 and Offset2 are the two offsets to be compared. +// BlockOffset is the offest of the instructions (that contain Offset1 +// and Offset2) from the beginning of their respective code blocks. +// InstructionLength is the length of the current instruction being +// compared for equivalency. +typedef bool(__cdecl *OffsetComparator)(const void *UserData, size_t BlockOffset, + size_t InstructionLength, uint64_t Offset1, + uint64_t Offset2); + +// The Export/Import definitions for CoreDistools library are defined below. +// A typedef for each interface function's type is defined in order to aid +// the importer. + +// Initialize the disassembler, using default print controls +typedef CorDisasm * __cdecl InitDisasm_t(enum TargetArch Target); +DllIface InitDisasm_t InitDisasm; + +// Initialize the disassembler using custom print controls +typedef CorDisasm * __cdecl NewDisasm_t(enum TargetArch Target, + const PrintControl *PControl); +DllIface NewDisasm_t NewDisasm; + +// Delete the disassembler +typedef void __cdecl FinishDisasm_t(const CorDisasm *Disasm); +DllIface FinishDisasm_t FinishDisasm; + +// DisasmInstruction -- Disassemble one instruction +// Arguments: +// Disasm -- The Disassembler +// Address -- The address at which the bytes of the instruction +// are intended to execute +// Bytes -- Pointer to the actual bytes which need to be disassembled +// MaxLength -- Number of bytes available in Bytes buffer +// Returns: +// -- The Size of the disassembled instruction +// -- Zero on failure +typedef size_t __cdecl DisasmInstruction_t(const CorDisasm *Disasm, + const uint8_t *Address, + const uint8_t *Bytes, size_t Maxlength); +DllIface DisasmInstruction_t DisasmInstruction; + +// Initialize the Code Differ +typedef CorAsmDiff * __cdecl NewDiffer_t(enum TargetArch Target, + const PrintControl *PControl, + const OffsetComparator Comparator); +DllIface NewDiffer_t NewDiffer; + +// Delete the Code Differ +typedef void __cdecl FinishDiff_t(const CorAsmDiff *AsmDiff); +DllIface FinishDiff_t FinishDiff; + +// NearDiffCodeBlocks -- Compare two code blocks for semantic +// equivalence +// Arguments: +// AsmDiff -- The Asm-differ +// UserData -- Any data the user wishes to pass through into +// the OffsetComparator +// Address1 -- Address at which first block will execute +// Bytes1 -- Pointer to the actual bytes of the first block +// Size1 -- The size of the first block +// Address2 -- Address at which second block will execute +// Bytes2 -- Pointer to the actual bytes of the second block +// Size2 -- The size of the second block +// Returns: +// -- true if the two blocks are equivalent, false if not. +typedef bool __cdecl NearDiffCodeBlocks_t(const CorAsmDiff *AsmDiff, + const void *UserData, + const uint8_t *Address1, + const uint8_t *Bytes1, size_t Size1, + const uint8_t *Address2, + const uint8_t *Bytes2, size_t Size2); +DllIface NearDiffCodeBlocks_t NearDiffCodeBlocks; + +// Print a code block according to the Disassembler's Print Controls +typedef void __cdecl DumpCodeBlock_t(const CorDisasm *Disasm, const uint8_t *Address, + const uint8_t *Bytes, size_t Size); +DllIface DumpCodeBlock_t DumpCodeBlock; + +// Print the two code blocks being diffed, according to +// AsmDiff's PrintControls. +typedef void __cdecl DumpDiffBlocks_t(const CorAsmDiff *AsmDiff, + const uint8_t *Address1, const uint8_t *Bytes1, + size_t Size1, const uint8_t *Address2, + const uint8_t *Bytes2, size_t Size2); +DllIface DumpDiffBlocks_t DumpDiffBlocks; + +#endif // !defined(_COREDISTOOLS_H_) diff --git a/lib/coreclr/src/inc/coregen.h b/lib/coreclr/src/inc/coregen.h new file mode 100644 index 0000000000..a286c27174 --- /dev/null +++ b/lib/coreclr/src/inc/coregen.h @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// ngencommon.h - cross-compilation enablement structures. +// + + + +#ifndef _NGENCOMMON_H_ +#define _NGENCOMMON_H_ + +#define NGENWORKER_FLAGS_TUNING 0x0001 + +#define NGENWORKER_FLAGS_MISSINGDEPENDENCIESOK 0x0004 +#define NGENWORKER_FLAGS_LARGEVERSIONBUBBLE 0x0008 + +#define NGENWORKER_FLAGS_WINMD_RESILIENT 0x1000 +#define NGENWORKER_FLAGS_READYTORUN 0x2000 +#define NGENWORKER_FLAGS_NO_METADATA 0x4000 +#define NGENWORKER_FLAGS_SILENT 0x8000 +#define NGENWORKER_FLAGS_VERBOSE 0x10000 +#define NGENWORKER_FLAGS_SUPPRESS_WARNINGS 0x20000 + +#endif // _NGENCOMMON_H_ diff --git a/lib/coreclr/src/inc/corerror.xml b/lib/coreclr/src/inc/corerror.xml new file mode 100644 index 0000000000..38efe0d6de --- /dev/null +++ b/lib/coreclr/src/inc/corerror.xml @@ -0,0 +1,2369 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CLDB_S_TRUNCATION + STATUS: Data value was truncated. + + + + META_S_DUPLICATE + Attempt to define an object that already exists in valid scenerios. + + + + CORDBG_S_BAD_START_SEQUENCE_POINT + Attempt to SetIP not at a sequence point sequence point. + + + + CORDBG_S_BAD_END_SEQUENCE_POINT + Attempt to SetIP when not going to a sequence point. If both this and CORDBG_E_BAD_START_SEQUENCE_POINT are true, only CORDBG_E_BAD_START_SEQUENCE_POINT will be reported. + + + + CORDBG_S_FUNC_EVAL_HAS_NO_RESULT + Some Func evals will lack a return value, + + + + CORDBG_S_VALUE_POINTS_TO_VOID + The Debugging API doesn't support dereferencing void pointers. + + + + CORDBG_S_FUNC_EVAL_ABORTED + The func eval completed, but was aborted. + + + + CORDBG_S_AT_END_OF_STACK + "The stack walk has reached the end of the stack. There are no more frames to walk." + The stack walk has reached the end of the stack. There are no more frames to walk. + + + + CORDBG_S_NOT_ALL_BITS_SET + Not all bits specified were successfully applied + + + + CEE_E_CVTRES_NOT_FOUND + "cvtres.exe not found." + cannot find cvtres.exe + + + + COR_E_TYPEUNLOADED + "Type has been unloaded." + The type had been unloaded. + + + + COR_E_APPDOMAINUNLOADED + "Attempted to access an unloaded appdomain." + access unloaded appdomain + + + + COR_E_CANNOTUNLOADAPPDOMAIN + "Error while unloading appdomain." + Error while unloading an appdomain + + + + MSEE_E_ASSEMBLYLOADINPROGRESS + "Assembly is still being loaded." + Assembly is being currently being loaded + + + + COR_E_ASSEMBLYEXPECTED + "The module was expected to contain an assembly manifest." + The module was expected to contain an assembly manifest. + + + + COR_E_FIXUPSINEXE + "Attempt to load an unverifiable executable with fixups (IAT with more than 2 sections or a TLS section.)" + Attempt to load an unverifiable exe with fixups (IAT with more than 2 sections or a TLS section) + + + + COR_E_NEWER_RUNTIME + "This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded." + The assembly is built by a runtime newer than the currently loaded runtime, and cannot be loaded. + + + + COR_E_MULTIMODULEASSEMBLIESDIALLOWED + "The module cannot be loaded because only single file assemblies are supported." + The module cannot be loaded because only single file assemblies are supported. + + + + HOST_E_DEADLOCK + "Host detected a deadlock on a blocking operation." + Host detects deadlock on a blocking operation + + + + HOST_E_INVALIDOPERATION + "Invalid operation." + The operation is invalid + + + + HOST_E_CLRNOTAVAILABLE + "CLR has been disabled due to unrecoverable error." + CLR has been disabled due to unrecoverable error + + + + HOST_E_EXITPROCESS_THREADABORT + "Process exited due to ThreadAbort escalation." + ExitProcess due to ThreadAbort escalation + + + + HOST_E_EXITPROCESS_ADUNLOAD + "Process exited due to AD Unload escalation." + ExitProcess due to AD Unload escalation + + + + HOST_E_EXITPROCESS_TIMEOUT + "Process exited due to Timeout escalation." + ExitProcess due to Timeout escalation + + + + HOST_E_EXITPROCESS_OUTOFMEMORY + "Process exited due to OutOfMemory escalation." + ExitProcess due to OutOfMemory escalation + + + + COR_E_MODULE_HASH_CHECK_FAILED + "The check of the module's hash failed." + The check of the module's hash failed. + + + + FUSION_E_REF_DEF_MISMATCH + "The located assembly's manifest definition does not match the assembly reference." + The located assembly's manifest definition does not match the assembly reference. + + + + FUSION_E_INVALID_PRIVATE_ASM_LOCATION + "The private assembly was located outside the appbase directory." + The private assembly was located outside the appbase directory. + + + + FUSION_E_ASM_MODULE_MISSING + "A module specified in the manifest was not found." + A module specified in the manifest was not found. + + + + FUSION_E_PRIVATE_ASM_DISALLOWED + "A strongly-named assembly is required." + A strongly-named assembly is required. + + + + FUSION_E_SIGNATURE_CHECK_FAILED + "Strong name signature could not be verified. The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key." + The check of the signature failed. + + + + FUSION_E_INVALID_NAME + "The given assembly name or codebase was invalid." + The given assembly name or codebase was invalid. + + + + FUSION_E_CODE_DOWNLOAD_DISABLED + "HTTP download of assemblies has been disabled for this appdomain." + HTTP download of assemblies has been disabled for this appdomain. + + + + FUSION_E_HOST_GAC_ASM_MISMATCH + "Assembly in host store has a different signature than assembly in GAC." + Assembly in host store has a different signature than assembly in GAC + + + + FUSION_E_LOADFROM_BLOCKED + "LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host." + Hosted environment doesn't permit loading by location + + + + FUSION_E_CACHEFILE_FAILED + "Failed to add file to AppDomain cache." + Failed to add file to AppDomain cache + + + + FUSION_E_APP_DOMAIN_LOCKED + "The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest." + The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest + + + + FUSION_E_CONFIGURATION_ERROR + "The requested assembly name was neither found in the GAC nor in the manifest or the manifest's specified location is wrong." + The requested assembly name was neither found in the GAC nor in the manifest or the manifest's specified location is wrong + + + + FUSION_E_MANIFEST_PARSE_ERROR + "Unexpected error while parsing the specified manifest." + Unexpected error while parsing the specified manifest + + + + COR_E_LOADING_REFERENCE_ASSEMBLY + "Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context." + Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context. + + + + COR_E_NI_AND_RUNTIME_VERSION_MISMATCH + "The native image could not be loaded, because it was generated for use by a different version of the runtime." + The native image could not be loaded, because it was generated for use by a different version of the runtime. + + + + COR_E_LOADING_WINMD_REFERENCE_ASSEMBLY + "Contract Windows Runtime assemblies cannot be loaded for execution. Make sure your application only contains non-contract Windows Runtime assemblies." + Contract Windows Runtime assemblies cannot be loaded for execution. Make sure your application only contains non-contract Windows Runtime assemblies + + + + COR_E_AMBIGUOUSIMPLEMENTATION + "Ambiguous implementation found." + Ambiguous implementation found + + + + CLDB_E_FILE_BADREAD + "Error occurred during a read." + Error occurred during a read. + + + + CLDB_E_FILE_BADWRITE + "Error occurred during a write." + Error occurred during a write. + + + + CLDB_E_FILE_OLDVER + "Old version error." + Old version error. + + + + CLDB_E_SMDUPLICATE + "Create of shared memory failed. A memory mapping of the same name already exists." + Create of shared memory failed. A memory mapping of the same name already exists. + + + + CLDB_E_NO_DATA + "No .CLB data in the memory or stream." + There isn't .CLB data in the memory or stream. + + + + CLDB_E_INCOMPATIBLE + "Importing scope is not compatible with the emitting scope." + The importing scope is not comptabile with the emitting scope + + + + CLDB_E_FILE_CORRUPT + "File is corrupt." + File is corrupt. + + + + CLDB_E_BADUPDATEMODE + "Cannot open a incrementally build scope for full update." + cannot open a incrementally build scope for full update + + + + CLDB_E_INDEX_NOTFOUND + "Index not found." + Index %s not found. + + + + CLDB_E_RECORD_NOTFOUND + "Record not found on lookup." + Record wasn't found on lookup. + + + + CLDB_E_RECORD_OUTOFORDER + "Record is emitted out of order." + Record is emitted out of order. + + + + CLDB_E_TOO_BIG + "A blob or string was too big." + A blob or string was too big. + + + + META_E_INVALID_TOKEN_TYPE + "A token of the wrong type passed to a metadata function." + A token of the wrong type passed to a metadata function. + + + + TLBX_E_LIBNOTREGISTERED + "Typelib export: Type library is not registered." + Typelib export: type library is not registered. + + + + META_E_BADMETADATA + "Merge: Inconsistency in meta data import scope." + Merge: Inconsistency in meta data import scope + + + + META_E_BAD_SIGNATURE + "Bad binary signature." + Bad binary signature + + + + META_E_BAD_INPUT_PARAMETER + "Bad input parameters." + Bad input parameters + + + + META_E_CANNOTRESOLVETYPEREF + "Cannot resolve typeref." + Cannot resolve typeref + + + + META_E_STRINGSPACE_FULL + "No logical space left to create more user strings." + No logical space left to create more user strings. + + + + META_E_HAS_UNMARKALL + "Unmark all has been called already." + Unmark all has been called already + + + + META_E_MUST_CALL_UNMARKALL + "Must call UnmarkAll first before marking." + Must call UnmarkAll first before marking. + + + + META_E_CA_INVALID_TARGET + "Known custom attribute on invalid target." + Known custom attribute on invalid target. + + + + META_E_CA_INVALID_VALUE + "Known custom attribute had invalid value." + Known custom attribute had invalid value. + + + + META_E_CA_INVALID_BLOB + "Known custom attribute blob has bad format." + Known custom attribute blob is bad format. + + + + META_E_CA_REPEATED_ARG + "Known custom attribute blob has repeated named argument." + Known custom attribute blob has repeated named argument. + + + + META_E_CA_UNKNOWN_ARGUMENT + "Known custom attribute named argument not recognized." + Known custom attrubte named arg not recognized. + + + + META_E_CA_UNEXPECTED_TYPE + "Known attribute parser found unexpected type." + Known attribute parser found unexpected type. + + + + META_E_CA_INVALID_ARGTYPE + "Known attribute parser only handles fields, not properties." + Known attribute parser only handles fields -- no properties. + + + + META_E_CA_INVALID_ARG_FOR_TYPE + "Known attribute parser found an argument that is invalid for the object it is applied to." + Known attribute parser found an argument that is invalid for the object it is applied to. + + + + META_E_CA_INVALID_UUID + "The format of the UUID was invalid." + The format of the UUID was invalid. + + + + META_E_CA_INVALID_MARSHALAS_FIELDS + "The MarshalAs attribute has fields set that are not valid for the specified unmanaged type." + The MarshalAs attribute has fields set that are not valid for the specified unmanaged type. + + + + META_E_CA_NT_FIELDONLY + "The specified unmanaged type is only valid on fields." + The specified unmanaged type is only valid on fields. + + + + META_E_CA_NEGATIVE_PARAMINDEX + "The parameter index cannot be negative." + The parameter index cannot be negative. + + + + META_E_CA_NEGATIVE_CONSTSIZE + "The constant size cannot be negative." + The constant size cannot be negative. + + + + META_E_CA_FIXEDSTR_SIZE_REQUIRED + "A fixed string requires a size." + A fixed string requires a size. + + + + META_E_CA_CUSTMARSH_TYPE_REQUIRED + "A custom marshaler requires the custom marshaler type." + A custom marshaler requires the custom marshaler type. + + + + META_E_NOT_IN_ENC_MODE + "SaveDelta was called without being in EnC mode." + SaveDelta was called without being in EnC mode + + + + META_E_CA_BAD_FRIENDS_ARGS + "InternalsVisibleTo can't have a version, culture, or processor architecture." + InternalsVisibleTo can't have a version, culture, or processor architecture. + + + + META_E_CA_FRIENDS_SN_REQUIRED + Strong-name signed assemblies can only grant friend access to strong name-signed assemblies + + + + VLDTR_E_RID_OUTOFRANGE + "Rid is out of range." + Rid is out of range. + + + + VLDTR_E_STRING_INVALID + "String offset is invalid." + String offset is invalid. + + + + VLDTR_E_GUID_INVALID + "GUID offset is invalid." + GUID offset is invalid. + + + + VLDTR_E_BLOB_INVALID + "Blob offset if invalid." + Blob offset if invalid. + + + + VLDTR_E_MR_BADCALLINGCONV + "MemberRef has invalid calling convention." + MemberRef has invalid calling convention. + + + + VLDTR_E_SIGNULL + "Signature specified is zero-sized." + Signature specified is zero-sized. + + + + VLDTR_E_MD_BADCALLINGCONV + "Method signature has invalid calling convention." + Method signature has invalid calling convention. + + + + VLDTR_E_MD_THISSTATIC + "Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention." + Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention. + + + + VLDTR_E_MD_NOTTHISNOTSTATIC + "Method is not marked static but is not HASTHIS or EXPLICITTHIS." + Method is not marked static but is not HASTHIS/EXPLICITTHIS. + + + + VLDTR_E_MD_NOARGCNT + "Method signature is missing the argument count." + Method signature is missing the argument count. + + + + VLDTR_E_SIG_MISSELTYPE + "Signature missing element type." + Signature missing element type. + + + + VLDTR_E_SIG_MISSTKN + "Signature missing token." + Signature missing token. + + + + VLDTR_E_SIG_TKNBAD + "Signature has bad token." + Signature has bad token. + + + + VLDTR_E_SIG_MISSFPTR + "Signature is missing function pointer." + Signature is missing function pointer. + + + + VLDTR_E_SIG_MISSFPTRARGCNT + "Signature has function pointer missing argument count." + Signature has function pointer missing argument count. + + + + VLDTR_E_SIG_MISSRANK + "Signature is missing rank specification." + Signature is missing rank specification. + + + + VLDTR_E_SIG_MISSNSIZE + "Signature is missing count of sized dimensions." + Signature is missing count of sized dimensions. + + + + VLDTR_E_SIG_MISSSIZE + "Signature is missing size of dimension." + Signature is missing size of dimension. + + + + VLDTR_E_SIG_MISSNLBND + "Signature is missing count of lower bounds." + Signature is missing count of lower bounds. + + + + VLDTR_E_SIG_MISSLBND + "Signature is missing a lower bound." + Signature is missing a lower bound. + + + + VLDTR_E_SIG_BADELTYPE + "Signature has bad element type." + Signature has bad element type. + + + + VLDTR_E_TD_ENCLNOTNESTED + "TypeDef not nested has encloser." + TypeDef not nested has encloser. + + + + VLDTR_E_FMD_PINVOKENOTSTATIC + "Field or method is PInvoke but is not marked Static." + Field/method is PInvoke but is not marked Static. + + + + VLDTR_E_SIG_SENTINMETHODDEF + "E_T_SENTINEL in MethodDef signature." + E_T_SENTINEL in MethodDef signature + + + + VLDTR_E_SIG_SENTMUSTVARARG + "E_T_SENTINEL <=> VARARG." + E_T_SENTINEL <=> VARARG + + + + VLDTR_E_SIG_MULTSENTINELS + "Multiple E_T_SENTINELs." + Multiple E_T_SENTINELs + + + + VLDTR_E_SIG_MISSARG + "Signature missing argument." + Signature missing argument + + + + VLDTR_E_SIG_BYREFINFIELD + "Field of ByRef type." + Field of ByRef type + + + + CORDBG_E_UNRECOVERABLE_ERROR + "Unrecoverable API error." + Unrecoverable API error. + + + + CORDBG_E_PROCESS_TERMINATED + "Process was terminated." + Process was terminated. + + + + CORDBG_E_PROCESS_NOT_SYNCHRONIZED + "Process not synchronized." + Process not synchronized. + + + + CORDBG_E_CLASS_NOT_LOADED + "A class is not loaded." + A class is not loaded. + + + + CORDBG_E_IL_VAR_NOT_AVAILABLE + "An IL variable is not available at the current native IP." + An IL variable is not available at the + + + + CORDBG_E_BAD_REFERENCE_VALUE + "A reference value was found to be bad during dereferencing." + A reference value was found to be bad + + + + CORDBG_E_FIELD_NOT_AVAILABLE + "A field in a class is not available, because the runtime optimized it away." + A field in a class is not available, + + + + CORDBG_E_NON_NATIVE_FRAME + "'Native-frame-only' operation on non-native frame." + "Native frame only" operation on + + + + CORDBG_E_CODE_NOT_AVAILABLE + "The code is currently unavailable." + The code is currently unavailable + + + + CORDBG_E_FUNCTION_NOT_IL + "Attempt to get a ICorDebugFunction for a function that is not IL." + Attempt to get a ICorDebugFunction for + + + + CORDBG_E_CANT_SET_IP_INTO_FINALLY + "SetIP is not possible because SetIP would move EIP from outside of an exception handling finally clause to a point inside of one." + SetIP isn't possible, because SetIP would + + + + CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY + "SetIP is not possible because it would move EIP from within an exception handling finally clause to a point outside of one." + SetIP isn't possible because it would move + + + + CORDBG_E_CANT_SET_IP_INTO_CATCH + "SetIP is not possible, because SetIP would move EIP from outside of an exception handling catch clause to a point inside of one." + SetIP isn't possible, because SetIP would + + + + CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME + "SetIP cannot be done on any frame except the leaf frame." + Setip cannot be done on any frame except + + + + CORDBG_E_SET_IP_IMPOSSIBLE + "SetIP is not allowed." + SetIP isn't allowed. For example, there is + + + + CORDBG_E_FUNC_EVAL_BAD_START_POINT + "Func eval cannot work. Bad starting point." + Func eval can't work if we're, for example, + + + + CORDBG_E_INVALID_OBJECT + "This object value is no longer valid." + This object value is no longer valid. + + + + CORDBG_E_FUNC_EVAL_NOT_COMPLETE + "CordbEval::GetResult called before func eval has finished." + If you call CordbEval::GetResult before the + + + + CORDBG_E_STATIC_VAR_NOT_AVAILABLE + "A static variable is not available because it has not been initialized yet." + A static variable isn't available because + + + + CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER + "SetIP cannot leave or enter a filter." + SetIP can't leave or enter a filter + + + + CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE + "JIT settings for ZAP modules cannot be changed." + You can't change JIT settings for ZAP + + + + CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 + "SetIP is not possible because it would move EIP from within a finally clause to a point outside of one on WIN64 platforms." + SetIP isn't possible because it would move + + + + CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 + "SetIP is not possible because it would move EIP from within a catch clause to a point outside of one on WIN64 platforms." + SetIP isn't possible because it would move + + + + CORDBG_E_CANT_SET_TO_JMC + "Cannot use JMC on this code (likely wrong JIT settings)." + Can't use JMC on this code (likely wrong jit settings). + + + + CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME + "Internal frame markers have no associated context." + Internal frame markers have no associated context. + + + + CORDBG_E_NOT_CHILD_FRAME + "The current frame is not a child frame." + The current frame is not a child frame. + + + + CORDBG_E_NON_MATCHING_CONTEXT + "The provided CONTEXT does not match the specified thread." + The provided CONTEXT does not match the specified thread. + The stack pointer in the provided CONTEXT must match the cached stack base and stack limit of the thread. + + + + + CORDBG_E_PAST_END_OF_STACK + "The stackwalker is now past the end of stack. No information is available." + The stackwalker is now past the end of stack. No information is available. + + + + CORDBG_E_FUNC_EVAL_CANNOT_UPDATE_REGISTER_IN_NONLEAF_FRAME + "Func eval cannot update a variable stored in a register on a non-leaf frame. The most likely cause is that such a variable is passed as a ref/out argument." + Func eval cannot update a variable stored in a register on a non-leaf frame. The most likely cause is that such a variable is passed as a ref/out argument. + + + + CORDBG_E_BAD_THREAD_STATE + "The state of the thread is invalid." + The state of the thread is invalid. + + + + CORDBG_E_DEBUGGER_ALREADY_ATTACHED + "This process has already been attached." + This process has already been attached to + + + + CORDBG_E_SUPERFLOUS_CONTINUE + "Returned from a call to Continue that was not matched with a stopping event." + Returned from a call to Continue that was + + + + CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME + "Cannot perfrom SetValue on non-leaf frames." + Can't perfrom SetValue on non-leaf frames. + + + + CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED + "Tried to do Edit and Continue on a module that was not started in Edit and Continue mode." + Tried to do EnC on a module that wasn't + + + + CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION + "SetIP cannot be done on any exception." + Setip cannot be done on any exception + + + + CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL + "The 'variable' does not exist because it is a literal optimized away by the compiler." + The 'variable' doesn't exist because it is a + + + + CORDBG_E_PROCESS_DETACHED + "Process has been detached." + Process has been detached from + + + + CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS + "Adding a field to a value or layout class is prohibited." + Adding a field to a value or layout class is prohibitted, + + + + CORDBG_E_FIELD_NOT_STATIC + "GetStaticFieldValue called on a non-static field." + Returned if someone tries to call GetStaticFieldValue + + + + CORDBG_E_FIELD_NOT_INSTANCE + "Returned if someone tries to call GetStaticFieldValue on a non-instance field." + Returned if someone tries to call GetStaticFieldValue + + + + CORDBG_E_ENC_JIT_CANT_UPDATE + "The JIT is unable to update the method." + The JIT is unable to update the method. + + + + CORDBG_E_ENC_INTERNAL_ERROR + "Internal Runtime Error while doing Edit-and-Continue." + Generic message for "Something user doesn't control went wrong" message. + + + + CORDBG_E_ENC_HANGING_FIELD + "The field was added via Edit and Continue after the class was loaded." + The field was added via EnC after the class was loaded, and so instead of the the field being contiguous with the other fields, it's 'hanging' off the instance or type. This error is used to indicate that either the storage for this field is not yet available and so the field value cannot be read, or the debugger needs to use an EnC specific code path to get the value. + + + + CORDBG_E_MODULE_NOT_LOADED + "Module not loaded." + If the module isn't loaded, including if it's been unloaded. + + + + CORDBG_E_UNABLE_TO_SET_BREAKPOINT + "Cannot set a breakpoint here." + Can't set a breakpoint here. + + + + CORDBG_E_DEBUGGING_NOT_POSSIBLE + "Debugging is not possible due to an incompatibility within the CLR implementation." + Debugging isn't possible due to an incompatibility within the CLR implementation. + + + + CORDBG_E_KERNEL_DEBUGGER_ENABLED + "A kernel debugger is enabled on the system. User-mode debugging will trap to the kernel debugger." + Debugging isn't possible because a kernel debugger is enabled on the system. + + + + CORDBG_E_KERNEL_DEBUGGER_PRESENT + "A kernel debugger is present on the system. User-mode debugging will trap to the kernel debugger." + Debugging isn't possible because a kernel debugger is present on the system. + + + + CORDBG_E_INCOMPATIBLE_PROTOCOL + "The debugger's protocol is incompatible with the debuggee." + The debugger's protocol is incompatible with the debuggee. + + + + CORDBG_E_TOO_MANY_PROCESSES + "The debugger can only handle a finite number of debuggees." + The debugger can only handle a finite number of debuggees. + + + + CORDBG_E_INTEROP_NOT_SUPPORTED + "Interop debugging is not supported." + Interop debugging is not supported + + + + CORDBG_E_NO_REMAP_BREAKPIONT + "Cannot call RemapFunction until have received RemapBreakpoint." + Cannot call RemapFunction until have received RemapBreakpoint + + + + CORDBG_E_OBJECT_NEUTERED + "Object is in a zombie state." + Object has been neutered (it's in a zombie state). + + + + CORPROF_E_FUNCTION_NOT_COMPILED + "Function not yet compiled." + Function not yet compiled. + + + + CORPROF_E_DATAINCOMPLETE + "The ID is not fully loaded/defined yet." + The ID is not fully loaded/defined yet. + + + + CORPROF_E_FUNCTION_NOT_IL + "The Method has no associated IL." + The Method has no associated IL + + + + CORPROF_E_NOT_MANAGED_THREAD + "The thread has never run managed code before." + The thread has never run managed code before + + + + CORPROF_E_CALL_ONLY_FROM_INIT + "The function may only be called during profiler initialization." + The function may only be called during profiler init + + + + + CORPROF_E_NOT_YET_AVAILABLE + "Requested information is not yet available." + This is a general error used to indicated that the information + + + + CORPROF_E_TYPE_IS_PARAMETERIZED + "The given type is a generic and cannot be used with this method." + The given type is a generic and cannot be used with this method. + + + + CORPROF_E_FUNCTION_IS_PARAMETERIZED + "The given function is a generic and cannot be used with this method." + The given function is a generic and cannot be used with this method. + + + + CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD + A profiler tried to walk the stack of an invalid thread + + + + CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX + A profiler can not walk a thread that is currently executing unmanaged code + + + + CORPROF_E_STACKSNAPSHOT_UNSAFE + A stackwalk at this point may cause dead locks or data corruption + + + + CORPROF_E_STACKSNAPSHOT_ABORTED + Stackwalking callback requested the walk to abort + + + + CORPROF_E_LITERALS_HAVE_NO_ADDRESS + Returned when asked for the address of a static that is a literal. + + + + CORPROF_E_UNSUPPORTED_CALL_SEQUENCE + A call was made at an unsupported time. Examples include illegally calling a profiling API method asynchronously, calling a method that might trigger a GC at an unsafe time, and calling a method at a time that could cause locks to be taken out of order. + + + + CORPROF_E_ASYNCHRONOUS_UNSAFE + A legal asynchronous call was made at an unsafe time (e.g., CLR locks are held) + + + + CORPROF_E_CLASSID_IS_ARRAY + The specified ClassID cannot be inspected by this function because it is an array + + + + CORPROF_E_CLASSID_IS_COMPOSITE + The specified ClassID is a non-array composite type (e.g., ref) and cannot be inspected + + + + CORPROF_E_PROFILER_DETACHING + The profiler's call into the CLR is disallowed because the profiler is attempting to detach. + + + + CORPROF_E_PROFILER_NOT_ATTACHABLE + The profiler does not support attaching to a live process. + + + + CORPROF_E_UNRECOGNIZED_PIPE_MSG_FORMAT + The message sent on the profiling API attach pipe is in an unrecognized format. + + + + CORPROF_E_PROFILER_ALREADY_ACTIVE + The request to attach a profiler was denied because a profiler is already loaded. + + + + CORPROF_E_PROFILEE_INCOMPATIBLE_WITH_TRIGGER + Unable to request a profiler attach because the target profilee's runtime is of a version incompatible with the current process calling AttachProfiler(). + + + + CORPROF_E_IPC_FAILED + AttachProfiler() encountered an error while communicating on the pipe to the target profilee. This is often caused by a target profilee that is shutting down or killed while AttachProfiler() is reading or writing the pipe. + + + + CORPROF_E_PROFILEE_PROCESS_NOT_FOUND + AttachProfiler() was unable to find a profilee with the specified process ID. + + + + CORPROF_E_CALLBACK3_REQUIRED + Profiler must implement ICorProfilerCallback3 interface for this call to be supported. + + + + CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER + This call was attempted by a profiler that attached to the process after startup, but this call is only supported by profilers that are loaded into the process on startup. + + + + CORPROF_E_IRREVERSIBLE_INSTRUMENTATION_PRESENT + Detach is impossible because the profiler has either instrumented IL or inserted enter/leave hooks. Detach was not attempted; the profiler is still fully attached. + + + + CORPROF_E_RUNTIME_UNINITIALIZED + The profiler called a function that cannot complete because the CLR is not yet fully initialized. The profiler may try again once the CLR has fully started. + + + + CORPROF_E_IMMUTABLE_FLAGS_SET + Detach is impossible because immutable flags were set by the profiler at startup. Detach was not attempted; the profiler is still fully attached. + + + + CORPROF_E_PROFILER_NOT_YET_INITIALIZED + The profiler called a function that cannot complete because the profiler is not yet fully initialized. + + + + CORPROF_E_INCONSISTENT_WITH_FLAGS + The profiler called a function that first requires additional flags to be set in the event mask. This HRESULT may also indicate that the profiler called a function that first requires that some of the flags currently set in the event mask be reset. + + + + CORPROF_E_PROFILER_CANCEL_ACTIVATION + The profiler has requested that the CLR instance not load the profiler into this process. + + + + CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE + Concurrent GC mode is enabled, which prevents use of COR_PRF_MONITOR_GC + + + + CORPROF_E_DEBUGGING_DISABLED + This functionality requires CoreCLR debugging to be enabled. + + + + CORPROF_E_TIMEOUT_WAITING_FOR_CONCURRENT_GC + Timed out on waiting for concurrent GC to finish during attach. + + + + CORPROF_E_MODULE_IS_DYNAMIC + The specified module was dynamically generated (e.g., via Reflection.Emit API), and is thus not supported by this API method. + + + + CORPROF_E_CALLBACK4_REQUIRED + Profiler must implement ICorProfilerCallback4 interface for this call to be supported. + + + + CORPROF_E_REJIT_NOT_ENABLED + This call is not supported unless ReJIT is first enabled during initialization by setting COR_PRF_ENABLE_REJIT via SetEventMask. + + + + CORPROF_E_FUNCTION_IS_COLLECTIBLE + The specified function is instantiated into a collectible assembly, and is thus not supported by this API method. + + + + CORPROF_E_CALLBACK6_REQUIRED + Profiler must implement ICorProfilerCallback6 interface for this call to be supported. + + + + + + CORPROF_E_CALLBACK7_REQUIRED + Profiler must implement ICorProfilerCallback7 interface for this call to be supported. + + + + CORPROF_E_REJIT_INLINING_DISABLED + The runtime's tracking of inlined methods for ReJIT is not enabled. + + + + CORDIAGIPC_E_BAD_ENCODING + The runtime was unable to decode the Header or Payload. + + + + CORDIAGIPC_E_UNKNOWN_COMMAND + The specified CommandSet or CommandId is unknown. + + + + CORDIAGIPC_E_UNKNOWN_MAGIC + The magic version of Diagnostics IPC is unknown. + + + + CORDIAGIPC_E_UNKNOWN_ERROR + An unknown error occurred in the Diagnpostics IPC Server. + + + + CORPROF_E_SUSPENSION_IN_PROGRESS + The runtime cannot be suspened since a suspension is already in progress. + + + + SECURITY_E_INCOMPATIBLE_SHARE + "Loading this assembly would produce a different grant set from other instances." + Loading this assembly would produce a different grant set from other instances + + + + SECURITY_E_UNVERIFIABLE + "Unverifiable code failed policy check." + Unverifable code failed policy check + + + + SECURITY_E_INCOMPATIBLE_EVIDENCE + "Assembly already loaded without additional security evidence." + Assembly already loaded without additional security evidence. + + + + CORSEC_E_POLICY_EXCEPTION + "PolicyException thrown." + PolicyException thrown + + + + CORSEC_E_MIN_GRANT_FAIL + "Failed to grant minimum permission requests." + Failed to grant minimum permission requests + + + + CORSEC_E_NO_EXEC_PERM + "Failed to grant permission to execute." + Failed to grant permission to execute + + + + CORSEC_E_XMLSYNTAX + "XML Syntax error." + XML Syntax error + + + + CORSEC_E_INVALID_STRONGNAME + "Strong name validation failed." + Strong name validation failed + + + + CORSEC_E_MISSING_STRONGNAME + "Assembly is not strong named." + Assembly is not strong named + + + + CORSEC_E_INVALID_IMAGE_FORMAT + "Invalid assembly file format." + Invalid assembly file format + + + + CORSEC_E_INVALID_PUBLICKEY + "Invalid assembly public key." + Invalid assembly public key + + + + CORSEC_E_SIGNATURE_MISMATCH + "Signature size mismatch." + Signature size mismatch + + + + CORSEC_E_CRYPTO + "Failure during Cryptographic operation." + generic CryptographicException + + + + CORSEC_E_CRYPTO_UNEX_OPER + "Unexpected Cryptographic operation." + generic CryptographicUnexpectedOperationException + + + + CORSECATTR_E_BAD_ACTION + "Invalid security action code." + Invalid security action code + + + + COR_E_EXCEPTION + "General Exception" + Base class for all exceptions in the runtime + + + + COR_E_SYSTEM + "System.Exception" + The base class for the runtime's "less serious" exceptions + + + + COR_E_ARGUMENTOUTOFRANGE + "An argument was out of its legal range." + An argument was out of its legal range. + + + + COR_E_ARRAYTYPEMISMATCH + "Attempted to store an object of the wrong type in an array." + Attempted to store an object of the wrong type in an array + + + + COR_E_CONTEXTMARSHAL + "Attempted to marshal an object across a context boundary." + + + + + COR_E_TIMEOUT + "Operation timed out." + + + + + COR_E_EXECUTIONENGINE + "Internal CLR error." + An internal error happened in the Common Language Runtime's Execution Engine + + + + COR_E_FIELDACCESS + "Access to this field is denied." + Access to this field is denied. + + + + COR_E_INDEXOUTOFRANGE + "Array subscript out of range." + Attempted to access an element within an array by using an index that is + + + + COR_E_INVALIDOPERATION + "An operation is not legal in the current state." + An operation is not legal in the current state. + + + + COR_E_SECURITY + "An error relating to security occurred." + An error relating to security occurred. + + + + + COR_E_SERIALIZATION + "An error relating to serialization occurred." + An error relating to serialization has occurred. + + + + COR_E_VERIFICATION + "A verification failure has occurred." + A verification failure occurred + + + + COR_E_METHODACCESS + "Access to this method is denied." + Access to this method is denied. + + + + COR_E_MISSINGFIELD + "Field does not exist." + An attempt was made to dynamically access a field that does not exist. + + + + COR_E_MISSINGMEMBER + "Member does not exist." + An attempt was made to dynamically invoke or access a field or method + + + + COR_E_MISSINGMETHOD + "Method does not exist." + An attempt was made to dynamically invoke a method that does not exist + + + + COR_E_MULTICASTNOTSUPPORTED + "Attempt to combine delegates that are not multicast." + Attempted to combine delegates that are not multicast + + + + COR_E_NOTSUPPORTED + "Operation is not supported." + The operation is not supported + + + + COR_E_OVERFLOW + "Arithmetic, casting or conversion operation overflowed or underflowed." + An arithmetic, casting, or conversion operation overflowed or underflowed. + + + + COR_E_RANK + "An array has the wrong number of dimensions for a particular operation." + An array has the wrong number of dimensions for a particular operation. + + + + COR_E_SYNCHRONIZATIONLOCK + "This operation must be called from a synchronized block." + Wait(), Notify() or NotifyAll() was called from an unsynchronized ** block of c + + + + COR_E_THREADINTERRUPTED + "Thread was interrupted from a waiting state." + Indicates that the thread was interrupted from a waiting state + + + + COR_E_MEMBERACCESS + "Access to this member is denied." + Access to this member is denied. + + + + COR_E_THREADSTATE + "Thread is in an invalid state for this operation." + Indicate that the Thread class is in an invalid state for the method call + + + + COR_E_THREADSTOP + "Thread is stopping." + Thrown into a thread to cause it to stop. This exception is typically not caught + + + + COR_E_TYPELOAD + "Could not find or load a type." + Could not find or load a specific type (class, enum, etc). + + + + COR_E_ENTRYPOINTNOTFOUND + "Could not find the specified DllImport entrypoint." + Could not find the specified DllImport entry point + + + + COR_E_DLLNOTFOUND + "Could not find the specified DllImport Dll." + Could not find the specified DllImport DLL. + + + + COR_E_THREADSTART + Indicate that a user thread fails to start. + + + + COR_E_INVALIDCOMOBJECT + "An invalid __ComObject has been used." + An invalid __ComObject has been used. + + + + COR_E_NOTFINITENUMBER + "Not a Number." + Thrown if value (a floating point number) is either the not a number value (NaN) or +- infinity value + + + + COR_E_DUPLICATEWAITOBJECT + "An object appears more than once in the wait objects array." + An object appears more than once in the wait objects array. + + + + COR_E_SEMAPHOREFULL + "Reached maximum count for semaphore." + Adding the given count to the semaphore would cause it to exceed its maximum count. + + + + COR_E_WAITHANDLECANNOTBEOPENED + "No semaphore of the given name exists." + No Semaphore of the given name exists. + + + + COR_E_ABANDONEDMUTEX + "The wait completed due to an abandoned mutex." + The wait completed due to an abandoned mutex. + + + + COR_E_THREADABORTED + "Thread has aborted." + Thrown into a thread to cause it to abort. Not catchable. + + + + COR_E_INVALIDOLEVARIANTTYPE + "OLE Variant has an invalid type." + The type of an OLE variant that was passed into the runtime is invalid. + + + + COR_E_MISSINGMANIFESTRESOURCE + "An expected resource in the assembly manifest was missing." + An expected resource in the assembly manifest was missing. + + + + COR_E_SAFEARRAYTYPEMISMATCH + "A mismatch has occurred between the runtime type of the array and the sub type recorded in the metadata." + A mismatch has occurred between the runtime type of the array and the subtype recorded in the metadata + + + + COR_E_TYPEINITIALIZATION + "Uncaught exception during type initialization." + An exception was thrown by a type's initializer (.cctor). + + + + COR_E_MARSHALDIRECTIVE + "Invalid marshaling directives." + The marshaling directives are invalid. + + + + COR_E_MISSINGSATELLITEASSEMBLY + "An expected satellite assembly containing the ultimate fallback resources for a given culture was not found or could not be loaded." + An expected satellite assembly containing the ultimate fallback resources + + + + COR_E_FORMAT + "The format of one argument does not meet the contract of the method." + The format of one argument does not meet the contract of the method. + + + + COR_E_SAFEARRAYRANKMISMATCH + "A mismatch has occurred between the runtime rank of the array and the rank recorded in the metadata." + A mismatch has occurred between the runtime rank of the array and the rank recorded in the metadata + + + + COR_E_PLATFORMNOTSUPPORTED + "Operation is not supported on this platform." + The method is not supported on this platform + + + + COR_E_INVALIDPROGRAM + "Invalid IL or CLR metadata." + A program contained invalid IL or bad metadata. Usually this is a compiler bug. + + + + COR_E_OPERATIONCANCELED + "The operation was cancelled." + The operation was cancelled. + + + + COR_E_INSUFFICIENTMEMORY + Not enough memory was available for an operation. + + + + COR_E_RUNTIMEWRAPPED + An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException. + + + + COR_E_DATAMISALIGNED + "A datatype misalignment was detected in a load or store instruction." + A datatype misalignment was detected in a load or store instruction. + + + + COR_E_CODECONTRACTFAILED + "A managed code contract (ie, precondition, postcondition, invariant, or assert) failed." + A managed code contract (ie, precondition, postcondition, invariant, or assert) failed. + + + + COR_E_TYPEACCESS + "Access to this type is denied." + Access to this type is denied. + + + + COR_E_ACCESSING_CCW + "Fail to access a CCW because the corresponding managed object is already collected." + Fail to access a CCW because the corresponding managed object is already collected. + + + + COR_E_KEYNOTFOUND + "The given key was not present in the dictionary." + + + + + COR_E_INSUFFICIENTEXECUTIONSTACK + "Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space." + Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space. + + + + COR_E_APPLICATION + "Application exception" + The base class for all "less serious" exceptions. + + + + COR_E_INVALIDFILTERCRITERIA + "The given filter criteria does not match the filter content." + The given filter criteria does not match the filter contract. + + + + COR_E_REFLECTIONTYPELOAD + "Could not find or load a specific class that was requested through Reflection." + Could not find or load a specific class that was requested through Reflection + + + + COR_E_TARGET + "Attempt to invoke non-static method with a null Object." + - If you attempt to invoke a non-static method with a null Object - If you atte + + + + COR_E_TARGETINVOCATION + "Uncaught exception thrown by method called through Reflection." + If the method called throws an exception + + + + COR_E_CUSTOMATTRIBUTEFORMAT + "Custom attribute has invalid format." + If the binary format of a custom attribute is invalid. + + + + COR_E_IO + "Error during managed I/O." + Some sort of I/O error. + + + + COR_E_FILELOAD + "Could not find or load a specific file." + + + + + COR_E_OBJECTDISPOSED + "The object has already been disposed." + The object has already been disposed. + + + + COR_E_FAILFAST + "Runtime operation halted by call to System.Environment.FailFast()." + Runtime operation halted by call to System.Environment.FailFast(). + + + + COR_E_HOSTPROTECTION + "The host has forbidden this operation." + Attempted to perform an operation that was forbidden by the host. + + + + COR_E_ILLEGAL_REENTRANCY + "Attempted to call into managed code when executing inside a low level extensibility point." + Attempted to call into managed code when executing inside a low level extensibility point. + + + + CLR_E_SHIM_RUNTIMELOAD + "Failed to load the runtime." + Failed to load the runtime + + + + CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND + "A runtime has already been bound for legacy activation policy use." + + + + VER_E_FIELD_SIG + "[field sig]" + + + + VER_E_CIRCULAR_VAR_CONSTRAINTS + "Method parent has circular class type parameter constraints." + + + + VER_E_CIRCULAR_MVAR_CONSTRAINTS + "Method has circular method type parameter constraints." + + + + COR_E_Data + + + + VLDTR_E_SIG_BADVOID + "Illegal 'void' in signature." + Illegal "void" in signature + + + + VLDTR_E_GP_ILLEGAL_VARIANT_MVAR + "GenericParam is a method type parameter and must be non-variant." + GenericParam is a method type parameter and must be non-variant + + + + CORDBG_E_THREAD_NOT_SCHEDULED + "Thread is not scheduled. Thus we may not have OSThreadId, handle, or context." + Thread is not scheduled. Thus we may not have OSThreadId, handle, or context + + + + CORDBG_E_HANDLE_HAS_BEEN_DISPOSED + "Handle has been disposed." + Handle has been disposed. + + + + CORDBG_E_NONINTERCEPTABLE_EXCEPTION + "Cannot intercept this exception." + Cant intercept this exception. + + + + CORDBG_E_INTERCEPT_FRAME_ALREADY_SET + "The intercept frame for this exception has already been set." + The intercept frame for this exception has already been set. + + + + CORDBG_E_NO_NATIVE_PATCH_AT_ADDR + "There is no native patch at the given address." + there's no native patch at the given address. + + + + CORDBG_E_MUST_BE_INTEROP_DEBUGGING + "This API is only allowed when interop debugging." + This API is only allowed when interop debugging. + + + + CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR + "There is already a native patch at the address." + There's already a native patch at the address + + + + CORDBG_E_TIMEOUT + "A wait timed out, likely an indication of deadlock." + a wait timed out .. likely an indication of deadlock. + + + + CORDBG_E_CANT_CALL_ON_THIS_THREAD + "Cannot use the API on this thread." + Can't use the API on this thread. + + + + CORDBG_E_ENC_INFOLESS_METHOD + "Method was not JIT'd in EnC mode." + Method was not JITed in EnC mode + + + + CORDBG_E_ENC_IN_FUNCLET + "Method is in a callable handler/filter. Cannot increase stack." + Method is in a callable handler/filter. Cant grow stack + + + + CORDBG_E_ENC_EDIT_NOT_SUPPORTED + "Attempt to perform unsupported edit." + Attempt to perform unsupported edit + + + + CORDBG_E_NOTREADY + "The LS is not in a good spot to perform the requested operation." + The LS is not in a good spot to perform the requested operation. + + + + CORDBG_E_CANNOT_RESOLVE_ASSEMBLY + "We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token." + We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token. + + + + CORDBG_E_MUST_BE_IN_LOAD_MODULE + "Must be in context of LoadModule callback to perform requested operation." + Must be in context of LoadModule callback to perform requested operation + + + + CORDBG_E_CANNOT_BE_ON_ATTACH + "Requested operation cannot be performed during an attach operation." + Requested operation cannot be performed during an attach operation + + + + CORDBG_E_NGEN_NOT_SUPPORTED + "NGEN must be supported to perform the requested operation." + NGEN must be supported to perform the requested operation + + + + CORDBG_E_ILLEGAL_SHUTDOWN_ORDER + "Trying to shutdown out of order." + Trying to shutdown out of order. + + + + CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS + "Debugging fiber mode managed process is not supported." + For Whidbey, we don't support debugging fiber mode managed process + + + + CORDBG_E_MUST_BE_IN_CREATE_PROCESS + "Must be in context of CreateProcess callback to perform requested operation." + Must be in context of CreateProcess callback to perform requested operation + + + + CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS + "All outstanding func-evals have not completed, detaching is not allowed at this time." + All outstanding func-evals have not completed, detaching is not allowed at this time. + + + + CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS + "All outstanding steppers have not been closed, detaching is not allowed at this time." + All outstanding steppers have not been closed, detaching is not allowed at this time. + + + + CORDBG_E_CANT_INTEROP_STEP_OUT + "Cannot have an ICorDebugStepper do a native step-out." + Can't have an ICorDebugStepper do a native step-out. + + + + CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS + "All outstanding breakpoints have not been closed, detaching is not allowed at this time." + All outstanding breakpoints have not been closed, detaching is not allowed at this time. + + + + CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW + "The operation is illegal because of a stack overflow." + the operation is illegal because of a stackoverflow. + + + + CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT + "The operation failed because it is a GC unsafe point." + The operation failed because it's a GC unsafe point. + + + + CORDBG_E_ILLEGAL_IN_PROLOG + "The operation failed because the thread is in the prolog." + The operation failed because the thread is in the prolog + + + + CORDBG_E_ILLEGAL_IN_NATIVE_CODE + "The operation failed because the thread is in native code." + The operation failed because the thread is in native code + + + + CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE + "The operation failed because the thread is in optimized code." + The operation failed because the thread is in optimized code. + + + + CORDBG_E_APPDOMAIN_MISMATCH + "A supplied object or type belongs to the wrong AppDomain." + A supplied object or type belongs to the wrong AppDomain + + + + CORDBG_E_CONTEXT_UNVAILABLE + "The thread's context is not available." + The thread's context is not available. + + + + CORDBG_E_UNCOMPATIBLE_PLATFORMS + "The operation failed because debuggee and debugger are on incompatible platforms." + The operation failed because debuggee and debugger are on incompatible platform + + + + CORDBG_E_DEBUGGING_DISABLED + "The operation failed because the debugging has been disabled" + The operation failed because the debugging has been disabled + + + + CORDBG_E_DETACH_FAILED_ON_ENC + "Detach is illegal after an Edit and Continue on a module." + Detach is illegal after a module has been EnCed. + + + + CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE + "Cannot intercept the current exception at the specified frame." + Interception of the current exception is not legal + + + + CORDBG_E_HELPER_MAY_DEADLOCK + "The debugger helper thread cannot obtain the locks it needs to perform this operation." + Helper thread can not safely run code. The opereration may work at a later time. + + + + CORDBG_E_MISSING_METADATA + "The operation failed because the debugger could not get the metadata." + The operation failed because the debugger could not get the metadata. + + + + CORDBG_E_TARGET_INCONSISTENT + "The debuggee is in a corrupt state." + The debuggee is in a corrupt state. + + + + CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES + "Detach failed because there are outstanding resources in the target." + The debugger is holding resource in the target (such as GC handles, function evaluations, etc). + These resources must be released through the appropriate ICorDebug API before detach can succeed. + + + + CORDBG_E_TARGET_READONLY + "The debuggee is read-only." + The provided ICorDebugDataTarget does not implement ICorDebugMutableDataTarget. + + + + CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS + "The version of clr.dll in the target does not match the one mscordacwks.dll was built for." + A clr/mscordacwks mismatch will cause DAC to fail to initialize in ClrDataAccess::Initialize + + + + CORDBG_E_MODULE_LOADED_FROM_DISK + "Symbols are not supplied for modules loaded from disk." + Symbols are not supplied for modules loaded from disk + + + + CORDBG_E_SYMBOLS_NOT_AVAILABLE + "The application did not supply symbols when it loaded or created this module, or they are not yet available." + The application did not supply symbols when it loaded or created this module, or they are not yet available + + + + CORDBG_E_DEBUG_COMPONENT_MISSING + "A debug component is not installed." + A debug component is not installed + + + + CORDBG_E_LIBRARY_PROVIDER_ERROR + "The ICLRDebuggingLibraryProvider callback returned an error or did not provide a valid handle." + The ICLRDebuggingLibraryProvider callback returned an error or did not provide a valid handle + + + + CORDBG_E_NOT_CLR + "The module at the base address indicated was not recognized as a CLR" + The module at the base address indicated was not recognized as a CLR + + + + CORDBG_E_MISSING_DATA_TARGET_INTERFACE + "The provided data target does not implement the required interfaces for this version of the runtime" + The provided data target does not implement the required interfaces for this version of the runtime + + + + CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL + "This debugging model is unsupported by the specified runtime" + This debugging model is unsupported by the specified runtime + + + + CORDBG_E_UNSUPPORTED_FORWARD_COMPAT + "The debugger is not designed to support the version of the CLR the debuggee is using." + The debugger is not designed to support the version of the CLR the debuggee is using. + + + + CORDBG_E_UNSUPPORTED_VERSION_STRUCT + "The version struct has an unrecognized value for wStructVersion" + The version struct has an unrecognized value for wStructVersion + + + + CORDBG_E_READVIRTUAL_FAILURE + "A call into a ReadVirtual implementation returned failure" + A call into a ReadVirtual implementation returned failure + + + + CORDBG_E_VALUE_POINTS_TO_FUNCTION + "The Debugging API doesn't support dereferencing function pointers." + The Debugging API doesn't support dereferencing function pointers. + + + + CORDBG_E_CORRUPT_OBJECT + "The address provided does not point to a valid managed object." + The address provided does not point to a valid managed object. + + + + CORDBG_E_GC_STRUCTURES_INVALID + "The GC heap structures are not in a valid state for traversal." + The GC heap structures are not in a valid state for traversal. + + + + CORDBG_E_INVALID_OPCODE + "The specified IL offset or opcode is not supported for this operation." + The specified IL offset or opcode is not supported for this operation. + + + + CORDBG_E_UNSUPPORTED + "The specified action is unsupported by this version of the runtime." + The specified action is unsupported by this version of the runtime. + + + + CORDBG_E_MISSING_DEBUGGER_EXPORTS + "The debuggee memory space does not have the expected debugging export table." + The debuggee memory space does not have the expected debugging export table. + + + + CORDBG_E_DATA_TARGET_ERROR + "Failure when calling a data target method." + Failure when calling a data target method. + + + + CORDBG_E_NO_IMAGE_AVAILABLE + "Couldn't find a native image." + Couldn't find a native image. + + + + CORDBG_E_UNSUPPORTED_DELEGATE + "The delegate contains a delegate currently not supported by the API." + The delegate contains a delegate currently not supported by the API. + + + + PEFMT_E_64BIT + "File is PE32+." + File is PE32+ + + + + PEFMT_E_32BIT + "File is PE32" + File is PE32 + + + + NGEN_E_SYS_ASM_NI_MISSING + "NGen cannot proceed because Mscorlib.dll does not have a native image" + Compiling any assembly other than mscorlib in the absence of mscorlib.ni.dll is not allowed. + + + + CLDB_E_INTERNALERROR + + + + CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW + "The bound assembly has a version that is lower than that of the request." + For AppX binder, indicates that bound assembly has a version lower than that requested, and we will refuse version rollback. + + + + CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH + "The assembly version has a public key token that does not match that of the request." + For AppX binder, indicates that bound assembly's public key token doesn't match the key in the assembly name. + + + + CLR_E_BIND_IMAGE_UNAVAILABLE + "The requested image was not found or is unavailable." + Occurs if a request for a native image is made on an ICLRPrivAssembly interface when one is not available. + + + + CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT + "The provided identity format is not recognized." + If a binder is provided an identity format that it cannot parse, it returns this error. + + + + CLR_E_BIND_ASSEMBLY_NOT_FOUND + "A binding for the specified assembly name was not found." + Returned by binders that bind based on assembly identity. + + + + CLR_E_BIND_TYPE_NOT_FOUND + "A binding for the specified type name was not found." + Returned by binders that bind based on type identity. + + + + CLR_E_BIND_SYS_ASM_NI_MISSING + "Could not use native image because Mscorlib.dll is missing a native image" + Returned when loading an assembly that only has a native image and no IL and cannot hardbind to mscorlib.ni.dll. + + + + CLR_E_BIND_NI_SECURITY_FAILURE + "Native image was generated in a different trust level than present at runtime" + Returned when an assembly is NGened in full trust and then used in partial trust or vice versa. + + + + CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH + "Native image identity mismatch with respect to its dependencies" + Returned when an assembly's identities have changed so the native image is no longer valid. + + + + CLR_E_GC_OOM + "Failfast due to an OOM during a GC" + During a GC when we try to allocate memory for GC datastructures we could not. + + + + CLR_E_GC_BAD_AFFINITY_CONFIG + "GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't specify any CPUs the current process is affinitized to." + During a GC initialization, the affinity mask specified via GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't contain any CPUs the current process is affinitized to. + + + + CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT + "GCHeapAffinitizeRanges configuration string has invalid format." + During a GC initialization, the GCHeapAffinitizeRanges config couldn't be parsed due to its invalid format. + + + + CLR_E_CROSSGEN_NO_IBC_DATA_FOUND + "Cannot compile using the PartialNgen flag because no IBC data was found." + During crossgen compilation, the PartialNgen flag was set, but no IBC data was found in the resources section of the input image, and no IBC file was externally provided. + + + + COR_E_UNAUTHORIZEDACCESS + 0x80070005 // Access is denied. + + + + COR_E_ARGUMENT + 0x80070057 // An argument does not meet the contract of the method. + + + + COR_E_INVALIDCAST + 0x80004002 // Indicates a bad cast condition + + + + COR_E_OUTOFMEMORY + 0x8007000E // The EE thows this exception when no more memory is avaible to continue execution + + + + COR_E_NULLREFERENCE + 0x80004003 // Dereferencing a null reference. In general class libraries should not throw this + + + + COR_E_ARITHMETIC + 0x80070216 // Overflow or underflow in mathematical operations. + + + + COR_E_PATHTOOLONG + The specified path was too long. + + + + COR_E_FILENOTFOUND + + + + + COR_E_ENDOFSTREAM + Thrown when the End of file is reached + + + + COR_E_DIRECTORYNOTFOUND + The specified path couldn't be found. + + + + COR_E_STACKOVERFLOW + 0x800703E9 // Is raised by the EE when the execution stack overflows as it is attempting to ex + + + + COR_E_AMBIGUOUSMATCH + While late binding to a method via reflection, could not resolve between + + + + COR_E_TARGETPARAMCOUNT + DISP_E_BADPARAMCOUNT // There was a mismatch between number of arguments provided and the number expected + + + + COR_E_DIVIDEBYZERO + DISP_E_DIVBYZERO // Attempted to divide a number by zero. + + + + COR_E_BADIMAGEFORMAT + "The format of a DLL or executable being loaded is invalid." + The format of DLL or executable being loaded is invalid. + + + + diff --git a/lib/coreclr/src/inc/corexcep.h b/lib/coreclr/src/inc/corexcep.h new file mode 100644 index 0000000000..9235a9846f --- /dev/null +++ b/lib/coreclr/src/inc/corexcep.h @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/********************************************************************* + ** ** + ** CorExcep.h - lists the exception codes used by the CLR. ** + ** ** + *********************************************************************/ + + +#ifndef __COREXCEP_H__ +#define __COREXCEP_H__ + +// All COM+ exceptions are expressed as a RaiseException with this exception +// code. If you change this value, you must also change +// mscorlib\src\system\Exception.cs's _COMPlusExceptionCode value. + +#define EXCEPTION_MSVC 0xe06d7363 // 0xe0000000 | 'msc' + +#define EXCEPTION_COMPLUS 0xe0434352 // 0xe0000000 | 'CCR' + +#define EXCEPTION_HIJACK 0xe0434f4e // 0xe0000000 | 'COM'+1 + +#if defined(_DEBUG) +#define EXCEPTION_INTERNAL_ASSERT 0xe0584d4e // 0xe0000000 | 'XMN' + // An internal Assert will raise this exception when the config + // value "RaiseExceptionOnAssert" si specified. This is used in + // stress to facilitate failure triaging. +#endif + +// This is the exception code to report SetupThread failure to caller of reverse pinvoke +// It is misleading to use our COM+ exception code, since this is not a managed exception. +// In the end, we picked e0455858 (EXX). +#define EXCEPTION_EXX 0xe0455858 // 0xe0000000 | 'EXX' +#endif // __COREXCEP_H__ diff --git a/lib/coreclr/src/inc/corhdr.h b/lib/coreclr/src/inc/corhdr.h new file mode 100644 index 0000000000..18b4dec319 --- /dev/null +++ b/lib/coreclr/src/inc/corhdr.h @@ -0,0 +1,1931 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** CorHdr.h - contains definitions for the Runtime structures, ** +** + + ** needed to work with metadata. ** + ** ** + *****************************************************************************/ +// +// The top most managed code structure in a EXE or DLL is the IMAGE_COR20_HEADER +// see code:#ManagedHeader for more + +#ifndef __CORHDR_H__ +#define __CORHDR_H__ + +#define FRAMEWORK_REGISTRY_KEY "Software\\Microsoft\\.NETFramework" +#define FRAMEWORK_REGISTRY_KEY_W W("Software\\Microsoft\\.NETFramework") + +// keys for HKCU +#ifdef _WIN64 +#define USER_FRAMEWORK_REGISTRY_KEY "Software\\Microsoft\\.NETFramework64" +#define USER_FRAMEWORK_REGISTRY_KEY_W W("Software\\Microsoft\\.NETFramework64") +#else +#define USER_FRAMEWORK_REGISTRY_KEY "Software\\Microsoft\\.NETFramework" +#define USER_FRAMEWORK_REGISTRY_KEY_W W("Software\\Microsoft\\.NETFramework") +#endif + + +#ifdef _MSC_VER +#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union. +#endif +typedef LPVOID mdScope; // Obsolete; not used in the runtime. +typedef ULONG32 mdToken; // Generic token + + +// Token definitions + + +typedef mdToken mdModule; // Module token (roughly, a scope) +typedef mdToken mdTypeRef; // TypeRef reference (this or other scope) +typedef mdToken mdTypeDef; // TypeDef in this scope +typedef mdToken mdFieldDef; // Field in this scope +typedef mdToken mdMethodDef; // Method in this scope +typedef mdToken mdParamDef; // param token +typedef mdToken mdInterfaceImpl; // interface implementation token + +typedef mdToken mdMemberRef; // MemberRef (this or other scope) +typedef mdToken mdCustomAttribute; // attribute token +typedef mdToken mdPermission; // DeclSecurity + +typedef mdToken mdSignature; // Signature object +typedef mdToken mdEvent; // event token +typedef mdToken mdProperty; // property token + +typedef mdToken mdModuleRef; // Module reference (for the imported modules) + +// Assembly tokens. +typedef mdToken mdAssembly; // Assembly token. +typedef mdToken mdAssemblyRef; // AssemblyRef token. +typedef mdToken mdFile; // File token. +typedef mdToken mdExportedType; // ExportedType token. +typedef mdToken mdManifestResource; // ManifestResource token. + +typedef mdToken mdTypeSpec; // TypeSpec object + +typedef mdToken mdGenericParam; // formal parameter to generic type or method +typedef mdToken mdMethodSpec; // instantiation of a generic method +typedef mdToken mdGenericParamConstraint; // constraint on a formal generic parameter + +// Application string. +typedef mdToken mdString; // User literal string token. + +typedef mdToken mdCPToken; // constantpool token + +#ifndef MACROS_NOT_SUPPORTED +typedef ULONG RID; +#else +typedef unsigned RID; +#endif // MACROS_NOT_SUPPORTED + +typedef enum ReplacesGeneralNumericDefines +{ +// Directory entry macro for CLR data. +#ifndef IMAGE_DIRECTORY_ENTRY_COMHEADER + IMAGE_DIRECTORY_ENTRY_COMHEADER =14, +#endif // IMAGE_DIRECTORY_ENTRY_COMHEADER +} ReplacesGeneralNumericDefines; + + +// The COMIMAGE_FLAGS_32BITREQUIRED and COMIMAGE_FLAGS_32BITPREFERRED flags defined below interact as a pair +// in order to get the performance profile we desire for platform neutral assemblies while retaining backwards +// compatibility with pre-4.5 runtimes/OSs, which don't know about COMIMAGE_FLAGS_32BITPREFERRED. +// +// COMIMAGE_FLAGS_32BITREQUIRED originally meant "this assembly is x86-only" (required to distinguish platform +// neutral assemblies which also mark their PE MachineType as IMAGE_FILE_MACHINE_I386). +// +// COMIMAGE_FLAGS_32BITPREFERRED has been added so we can create a sub-class of platform neutral assembly that +// prefers to be loaded into 32-bit environment for perf reasons, but is still compatible with 64-bit +// environments. +// +// In order to retain maximum backwards compatibility you cannot simply read or write one of these flags +// however. You must treat them as a pair, a two-bit field with the following meanings: +// +// 32BITREQUIRED 32BITPREFERRED +// 0 0 : no special meaning, MachineType and ILONLY flag determine image requirements +// 0 1 : illegal, reserved for future use +// 1 0 : image is x86-specific +// 1 1 : image is platform neutral and prefers to be loaded 32-bit when possible +// +// To simplify manipulation of these flags the following macros are provided below. + +#define COR_IS_32BIT_REQUIRED(_flags) \ + (((_flags) & (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) == (COMIMAGE_FLAGS_32BITREQUIRED)) + +#define COR_IS_32BIT_PREFERRED(_flags) \ + (((_flags) & (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) == (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) + +#define COR_SET_32BIT_REQUIRED(_flagsfield) \ + do { _flagsfield = (_flagsfield & ~COMIMAGE_FLAGS_32BITPREFERRED) | COMIMAGE_FLAGS_32BITREQUIRED; } while (false) + +#define COR_SET_32BIT_PREFERRED(_flagsfield) \ + do { _flagsfield |= COMIMAGE_FLAGS_32BITPREFERRED|COMIMAGE_FLAGS_32BITREQUIRED; } while (false) + +#define COR_CLEAR_32BIT_REQUIRED(_flagsfield) \ + do { _flagsfield &= ~(COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED); } while (false) + +#define COR_CLEAR_32BIT_PREFERRED(_flagsfield) \ + do { _flagsfield &= ~(COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED); } while (false) + + +#ifndef __IMAGE_COR20_HEADER_DEFINED__ +#define __IMAGE_COR20_HEADER_DEFINED__ + +typedef enum ReplacesCorHdrNumericDefines +{ +// COM+ Header entry point flags. + COMIMAGE_FLAGS_ILONLY =0x00000001, + COMIMAGE_FLAGS_32BITREQUIRED =0x00000002, // *** Do not manipulate this bit directly (see notes above) + COMIMAGE_FLAGS_IL_LIBRARY =0x00000004, + COMIMAGE_FLAGS_STRONGNAMESIGNED =0x00000008, + COMIMAGE_FLAGS_NATIVE_ENTRYPOINT =0x00000010, + COMIMAGE_FLAGS_TRACKDEBUGDATA =0x00010000, + COMIMAGE_FLAGS_32BITPREFERRED =0x00020000, // *** Do not manipulate this bit directly (see notes above) + + +// Version flags for image. + COR_VERSION_MAJOR_V2 =2, + COR_VERSION_MAJOR =COR_VERSION_MAJOR_V2, + COR_VERSION_MINOR =5, + COR_DELETED_NAME_LENGTH =8, + COR_VTABLEGAP_NAME_LENGTH =8, + +// Maximum size of a NativeType descriptor. + NATIVE_TYPE_MAX_CB =1, + COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE=0xFF, + +// V-table constants + COR_VTABLE_32BIT =0x01, // V-table slots are 32-bits in size. + COR_VTABLE_64BIT =0x02, // V-table slots are 64-bits in size. + COR_VTABLE_FROM_UNMANAGED =0x04, // If set, transition from unmanaged. + COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN=0x08, // NEW + COR_VTABLE_CALL_MOST_DERIVED =0x10, // Call most derived method described by + +// EATJ constants + IMAGE_COR_EATJ_THUNK_SIZE = 32, // Size of a jump thunk reserved range. + +// Max name lengths + //@todo: Change to unlimited name lengths. + MAX_CLASS_NAME =1024, + MAX_PACKAGE_NAME =1024, +} ReplacesCorHdrNumericDefines; + +// #ManagedHeader +// +// A managed code EXE or DLL uses the same basic format that unmanaged executables use call the Portable +// Executable (PE) format. See http://en.wikipedia.org/wiki/Portable_Executable or +// http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx for more on this format and RVAs. +// +// PE files define fixed table of well known entry pointers call Directory entries. Each entry holds the +// relative virtual address (RVA) and length of a blob of data within the PE file. You can see these using +// the command +// +// link /dump /headers +// +// +// Managed code has defined one of these entries (the 14th see code:IMAGE_DIRECTORY_ENTRY_COMHEADER) and the RVA points +// that the IMAGE_COR20_HEADER. This header shows up in the previous dump as the following line +// +// // Managed code is identified by is following line +// +// 2008 [ 48] RVA [size] of COM Descriptor Directory +// +// The IMAGE_COR20_HEADER is mostly just RVA:Length pairs (pointers) to other interesting data structures. +// The most important of these is the MetaData tables. The easiest way of looking at meta-data is using +// the IlDasm.exe tool. +// +// MetaData holds most of the information in the IL image. The exceptions are resource blobs and the IL +// instructions streams for individual methods. Instead the Meta-data for a method holds an RVA to a +// code:IMAGE_COR_ILMETHOD which holds all the IL stream (and exception handling information). +// +// Precompiled (NGEN) images use the same IMAGE_COR20_HEADER but also use the ManagedNativeHeader field to +// point at structures that only exist in precompiled images. +// +typedef struct IMAGE_COR20_HEADER +{ + // Header versioning + DWORD cb; + WORD MajorRuntimeVersion; + WORD MinorRuntimeVersion; + + // Symbol table and startup information + IMAGE_DATA_DIRECTORY MetaData; + DWORD Flags; + + // The main program if it is an EXE (not used if a DLL?) + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. + // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint + // (depricated for DLLs, use modules constructors intead). + union { + DWORD EntryPointToken; + DWORD EntryPointRVA; + }; + + // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and + // code:PEFile.GetResource and accessible from managed code from + // System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into + // this blob, so logically the blob is a set of resources. + IMAGE_DATA_DIRECTORY Resources; + // IL assemblies can be signed with a public-private key to validate who created it. The signature goes + // here if this feature is used. + IMAGE_DATA_DIRECTORY StrongNameSignature; + + IMAGE_DATA_DIRECTORY CodeManagerTable; // Depricated, not used + // Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points) + IMAGE_DATA_DIRECTORY VTableFixups; + IMAGE_DATA_DIRECTORY ExportAddressTableJumps; + + // null for ordinary IL images. In NGEN images it points at a code:CORCOMPILE_HEADER structure. + // In Ready2Run images it points to a READYTORUN_HEADER. + IMAGE_DATA_DIRECTORY ManagedNativeHeader; + +} IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; + +#else // !__IMAGE_COR20_HEADER_DEFINED__ + +// @TODO: This is required because we pull in the COM+ 2.0 PE header +// definition from WinNT.h, and these constants have not yet propogated to there. +// +#define COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN 0x08 +#define COMIMAGE_FLAGS_32BITPREFERRED 0x00020000 + +#endif // __IMAGE_COR20_HEADER_DEFINED__ + + +// The most recent version. + +#define COR_CTOR_METHOD_NAME ".ctor" +#define COR_CTOR_METHOD_NAME_W W(".ctor") +#define COR_CCTOR_METHOD_NAME ".cctor" +#define COR_CCTOR_METHOD_NAME_W W(".cctor") + +#define COR_ENUM_FIELD_NAME "value__" +#define COR_ENUM_FIELD_NAME_W W("value__") + +// The predefined name for deleting a typeDef,MethodDef, FieldDef, Property and Event +#define COR_DELETED_NAME_A "_Deleted" +#define COR_DELETED_NAME_W W("_Deleted") +#define COR_VTABLEGAP_NAME_A "_VtblGap" +#define COR_VTABLEGAP_NAME_W W("_VtblGap") + +// We intentionally use strncmp so that we will ignore any suffix +#define IsDeletedName(strName) (strncmp(strName, COR_DELETED_NAME_A, COR_DELETED_NAME_LENGTH) == 0) +#define IsVtblGapName(strName) (strncmp(strName, COR_VTABLEGAP_NAME_A, COR_VTABLEGAP_NAME_LENGTH) == 0) + +// TypeDef/ExportedType attr bits, used by DefineTypeDef. +typedef enum CorTypeAttr +{ + // Use this mask to retrieve the type visibility information. + tdVisibilityMask = 0x00000007, + tdNotPublic = 0x00000000, // Class is not public scope. + tdPublic = 0x00000001, // Class is public scope. + tdNestedPublic = 0x00000002, // Class is nested with public visibility. + tdNestedPrivate = 0x00000003, // Class is nested with private visibility. + tdNestedFamily = 0x00000004, // Class is nested with family visibility. + tdNestedAssembly = 0x00000005, // Class is nested with assembly visibility. + tdNestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility. + tdNestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility. + + // Use this mask to retrieve class layout information + tdLayoutMask = 0x00000018, + tdAutoLayout = 0x00000000, // Class fields are auto-laid out + tdSequentialLayout = 0x00000008, // Class fields are laid out sequentially + tdExplicitLayout = 0x00000010, // Layout is supplied explicitly + // end layout mask + + // Use this mask to retrieve class semantics information. + tdClassSemanticsMask = 0x00000020, + tdClass = 0x00000000, // Type is a class. + tdInterface = 0x00000020, // Type is an interface. + // end semantics mask + + // Special semantics in addition to class semantics. + tdAbstract = 0x00000080, // Class is abstract + tdSealed = 0x00000100, // Class is concrete and may not be extended + tdSpecialName = 0x00000400, // Class name is special. Name describes how. + + // Implementation attributes. + tdImport = 0x00001000, // Class / interface is imported + tdSerializable = 0x00002000, // The class is Serializable. + tdWindowsRuntime = 0x00004000, // The type is a Windows Runtime type + + // Use tdStringFormatMask to retrieve string information for native interop + tdStringFormatMask = 0x00030000, + tdAnsiClass = 0x00000000, // LPTSTR is interpreted as ANSI in this class + tdUnicodeClass = 0x00010000, // LPTSTR is interpreted as UNICODE + tdAutoClass = 0x00020000, // LPTSTR is interpreted automatically + tdCustomFormatClass = 0x00030000, // A non-standard encoding specified by CustomFormatMask + tdCustomFormatMask = 0x00C00000, // Use this mask to retrieve non-standard encoding information for native interop. The meaning of the values of these 2 bits is unspecified. + + // end string format mask + + tdBeforeFieldInit = 0x00100000, // Initialize the class any time before first static field access. + tdForwarder = 0x00200000, // This ExportedType is a type forwarder. + + // Flags reserved for runtime use. + tdReservedMask = 0x00040800, + tdRTSpecialName = 0x00000800, // Runtime should check name encoding. + tdHasSecurity = 0x00040000, // Class has security associate with it. +} CorTypeAttr; + + +// Macros for accessing the members of the CorTypeAttr. +#define IsTdNotPublic(x) (((x) & tdVisibilityMask) == tdNotPublic) +#define IsTdPublic(x) (((x) & tdVisibilityMask) == tdPublic) +#define IsTdNestedPublic(x) (((x) & tdVisibilityMask) == tdNestedPublic) +#define IsTdNestedPrivate(x) (((x) & tdVisibilityMask) == tdNestedPrivate) +#define IsTdNestedFamily(x) (((x) & tdVisibilityMask) == tdNestedFamily) +#define IsTdNestedAssembly(x) (((x) & tdVisibilityMask) == tdNestedAssembly) +#define IsTdNestedFamANDAssem(x) (((x) & tdVisibilityMask) == tdNestedFamANDAssem) +#define IsTdNestedFamORAssem(x) (((x) & tdVisibilityMask) == tdNestedFamORAssem) +#define IsTdNested(x) (((x) & tdVisibilityMask) >= tdNestedPublic) + +#define IsTdAutoLayout(x) (((x) & tdLayoutMask) == tdAutoLayout) +#define IsTdSequentialLayout(x) (((x) & tdLayoutMask) == tdSequentialLayout) +#define IsTdExplicitLayout(x) (((x) & tdLayoutMask) == tdExplicitLayout) + +#define IsTdClass(x) (((x) & tdClassSemanticsMask) == tdClass) +#define IsTdInterface(x) (((x) & tdClassSemanticsMask) == tdInterface) + +#define IsTdAbstract(x) ((x) & tdAbstract) +#define IsTdSealed(x) ((x) & tdSealed) +#define IsTdSpecialName(x) ((x) & tdSpecialName) + +#define IsTdImport(x) ((x) & tdImport) +#define IsTdSerializable(x) ((x) & tdSerializable) +#define IsTdWindowsRuntime(x) ((x) & tdWindowsRuntime) + +#define IsTdAnsiClass(x) (((x) & tdStringFormatMask) == tdAnsiClass) +#define IsTdUnicodeClass(x) (((x) & tdStringFormatMask) == tdUnicodeClass) +#define IsTdAutoClass(x) (((x) & tdStringFormatMask) == tdAutoClass) +#define IsTdCustomFormatClass(x) (((x) & tdStringFormatMask) == tdCustomFormatClass) +#define IsTdBeforeFieldInit(x) ((x) & tdBeforeFieldInit) +#define IsTdForwarder(x) ((x) & tdForwarder) + +#define IsTdRTSpecialName(x) ((x) & tdRTSpecialName) +#define IsTdHasSecurity(x) ((x) & tdHasSecurity) + +// MethodDef attr bits, Used by DefineMethod. +typedef enum CorMethodAttr +{ + // member access mask - Use this mask to retrieve accessibility information. + mdMemberAccessMask = 0x0007, + mdPrivateScope = 0x0000, // Member not referenceable. + mdPrivate = 0x0001, // Accessible only by the parent type. + mdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. + mdAssem = 0x0003, // Accessibly by anyone in the Assembly. + mdFamily = 0x0004, // Accessible only by type and sub-types. + mdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. + mdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. + // end member access mask + + // method contract attributes. + mdStatic = 0x0010, // Defined on type, else per instance. + mdFinal = 0x0020, // Method may not be overridden. + mdVirtual = 0x0040, // Method virtual. + mdHideBySig = 0x0080, // Method hides by name+sig, else just by name. + + // vtable layout mask - Use this mask to retrieve vtable attributes. + mdVtableLayoutMask = 0x0100, + mdReuseSlot = 0x0000, // The default. + mdNewSlot = 0x0100, // Method always gets a new slot in the vtable. + // end vtable layout mask + + // method implementation attributes. + mdCheckAccessOnOverride = 0x0200, // Overridability is the same as the visibility. + mdAbstract = 0x0400, // Method does not provide an implementation. + mdSpecialName = 0x0800, // Method is special. Name describes how. + + // interop attributes + mdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. + mdUnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code. + + // Reserved flags for runtime use only. + mdReservedMask = 0xd000, + mdRTSpecialName = 0x1000, // Runtime should check name encoding. + mdHasSecurity = 0x4000, // Method has security associate with it. + mdRequireSecObject = 0x8000, // Method calls another method containing security code. + +} CorMethodAttr; + +// Macros for accessing the members of CorMethodAttr. +#define IsMdPrivateScope(x) (((x) & mdMemberAccessMask) == mdPrivateScope) +#define IsMdPrivate(x) (((x) & mdMemberAccessMask) == mdPrivate) +#define IsMdFamANDAssem(x) (((x) & mdMemberAccessMask) == mdFamANDAssem) +#define IsMdAssem(x) (((x) & mdMemberAccessMask) == mdAssem) +#define IsMdFamily(x) (((x) & mdMemberAccessMask) == mdFamily) +#define IsMdFamORAssem(x) (((x) & mdMemberAccessMask) == mdFamORAssem) +#define IsMdPublic(x) (((x) & mdMemberAccessMask) == mdPublic) + +#define IsMdStatic(x) ((x) & mdStatic) +#define IsMdFinal(x) ((x) & mdFinal) +#define IsMdVirtual(x) ((x) & mdVirtual) +#define IsMdHideBySig(x) ((x) & mdHideBySig) + +#define IsMdReuseSlot(x) (((x) & mdVtableLayoutMask) == mdReuseSlot) +#define IsMdNewSlot(x) (((x) & mdVtableLayoutMask) == mdNewSlot) + +#define IsMdCheckAccessOnOverride(x) ((x) & mdCheckAccessOnOverride) +#define IsMdAbstract(x) ((x) & mdAbstract) +#define IsMdSpecialName(x) ((x) & mdSpecialName) + +#define IsMdPinvokeImpl(x) ((x) & mdPinvokeImpl) +#define IsMdUnmanagedExport(x) ((x) & mdUnmanagedExport) + +#define IsMdRTSpecialName(x) ((x) & mdRTSpecialName) +#define IsMdInstanceInitializer(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CTOR_METHOD_NAME)) +#define IsMdInstanceInitializerW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CTOR_METHOD_NAME_W)) +#define IsMdClassConstructor(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CCTOR_METHOD_NAME)) +#define IsMdClassConstructorW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CCTOR_METHOD_NAME_W)) +#define IsMdHasSecurity(x) ((x) & mdHasSecurity) +#define IsMdRequireSecObject(x) ((x) & mdRequireSecObject) + +// FieldDef attr bits, used by DefineField. +typedef enum CorFieldAttr +{ + // member access mask - Use this mask to retrieve accessibility information. + fdFieldAccessMask = 0x0007, + fdPrivateScope = 0x0000, // Member not referenceable. + fdPrivate = 0x0001, // Accessible only by the parent type. + fdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. + fdAssembly = 0x0003, // Accessibly by anyone in the Assembly. + fdFamily = 0x0004, // Accessible only by type and sub-types. + fdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. + fdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. + // end member access mask + + // field contract attributes. + fdStatic = 0x0010, // Defined on type, else per instance. + fdInitOnly = 0x0020, // Field may only be initialized, not written to after init. + fdLiteral = 0x0040, // Value is compile time constant. + fdNotSerialized = 0x0080, // Field does not have to be serialized when type is remoted. + + fdSpecialName = 0x0200, // field is special. Name describes how. + + // interop attributes + fdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. + + // Reserved flags for runtime use only. + fdReservedMask = 0x9500, + fdRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. + fdHasFieldMarshal = 0x1000, // Field has marshalling information. + fdHasDefault = 0x8000, // Field has default. + fdHasFieldRVA = 0x0100, // Field has RVA. +} CorFieldAttr; + +// Macros for accessing the members of CorFieldAttr. +#define IsFdPrivateScope(x) (((x) & fdFieldAccessMask) == fdPrivateScope) +#define IsFdPrivate(x) (((x) & fdFieldAccessMask) == fdPrivate) +#define IsFdFamANDAssem(x) (((x) & fdFieldAccessMask) == fdFamANDAssem) +#define IsFdAssembly(x) (((x) & fdFieldAccessMask) == fdAssembly) +#define IsFdFamily(x) (((x) & fdFieldAccessMask) == fdFamily) +#define IsFdFamORAssem(x) (((x) & fdFieldAccessMask) == fdFamORAssem) +#define IsFdPublic(x) (((x) & fdFieldAccessMask) == fdPublic) + +#define IsFdStatic(x) ((x) & fdStatic) +#define IsFdInitOnly(x) ((x) & fdInitOnly) +#define IsFdLiteral(x) ((x) & fdLiteral) +#define IsFdNotSerialized(x) ((x) & fdNotSerialized) + +#define IsFdPinvokeImpl(x) ((x) & fdPinvokeImpl) +#define IsFdSpecialName(x) ((x) & fdSpecialName) +#define IsFdHasFieldRVA(x) ((x) & fdHasFieldRVA) + +#define IsFdRTSpecialName(x) ((x) & fdRTSpecialName) +#define IsFdHasFieldMarshal(x) ((x) & fdHasFieldMarshal) +#define IsFdHasDefault(x) ((x) & fdHasDefault) + +// Param attr bits, used by DefineParam. +typedef enum CorParamAttr +{ + pdIn = 0x0001, // Param is [In] + pdOut = 0x0002, // Param is [out] + pdOptional = 0x0010, // Param is optional + + // Reserved flags for Runtime use only. + pdReservedMask = 0xf000, + pdHasDefault = 0x1000, // Param has default value. + pdHasFieldMarshal = 0x2000, // Param has FieldMarshal. + + pdUnused = 0xcfe0, +} CorParamAttr; + +// Macros for accessing the members of CorParamAttr. +#define IsPdIn(x) ((x) & pdIn) +#define IsPdOut(x) ((x) & pdOut) +#define IsPdOptional(x) ((x) & pdOptional) + +#define IsPdHasDefault(x) ((x) & pdHasDefault) +#define IsPdHasFieldMarshal(x) ((x) & pdHasFieldMarshal) + + +// Property attr bits, used by DefineProperty. +typedef enum CorPropertyAttr +{ + prSpecialName = 0x0200, // property is special. Name describes how. + + // Reserved flags for Runtime use only. + prReservedMask = 0xf400, + prRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. + prHasDefault = 0x1000, // Property has default + + prUnused = 0xe9ff, +} CorPropertyAttr; + +// Macros for accessing the members of CorPropertyAttr. +#define IsPrSpecialName(x) ((x) & prSpecialName) + +#define IsPrRTSpecialName(x) ((x) & prRTSpecialName) +#define IsPrHasDefault(x) ((x) & prHasDefault) + +// Event attr bits, used by DefineEvent. +typedef enum CorEventAttr +{ + evSpecialName = 0x0200, // event is special. Name describes how. + + // Reserved flags for Runtime use only. + evReservedMask = 0x0400, + evRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. +} CorEventAttr; + +// Macros for accessing the members of CorEventAttr. +#define IsEvSpecialName(x) ((x) & evSpecialName) + +#define IsEvRTSpecialName(x) ((x) & evRTSpecialName) + + +// MethodSemantic attr bits, used by DefineProperty, DefineEvent. +typedef enum CorMethodSemanticsAttr +{ + msSetter = 0x0001, // Setter for property + msGetter = 0x0002, // Getter for property + msOther = 0x0004, // other method for property or event + msAddOn = 0x0008, // AddOn method for event + msRemoveOn = 0x0010, // RemoveOn method for event + msFire = 0x0020, // Fire method for event +} CorMethodSemanticsAttr; + +// Macros for accessing the members of CorMethodSemanticsAttr. +#define IsMsSetter(x) ((x) & msSetter) +#define IsMsGetter(x) ((x) & msGetter) +#define IsMsOther(x) ((x) & msOther) +#define IsMsAddOn(x) ((x) & msAddOn) +#define IsMsRemoveOn(x) ((x) & msRemoveOn) +#define IsMsFire(x) ((x) & msFire) + + +// DeclSecurity attr bits, used by DefinePermissionSet. +typedef enum CorDeclSecurity +{ + dclActionMask = 0x001f, // Mask allows growth of enum. + dclActionNil = 0x0000, // + dclRequest = 0x0001, // + dclDemand = 0x0002, // + dclAssert = 0x0003, // + dclDeny = 0x0004, // + dclPermitOnly = 0x0005, // + dclLinktimeCheck = 0x0006, // + dclInheritanceCheck = 0x0007, // + dclRequestMinimum = 0x0008, // + dclRequestOptional = 0x0009, // + dclRequestRefuse = 0x000a, // + dclPrejitGrant = 0x000b, // Persisted grant set at prejit time + dclPrejitDenied = 0x000c, // Persisted denied set at prejit time + dclNonCasDemand = 0x000d, // + dclNonCasLinkDemand = 0x000e, // + dclNonCasInheritance = 0x000f, // + dclMaximumValue = 0x000f, // Maximum legal value +} CorDeclSecurity; + +// Macros for accessing the members of CorDeclSecurity. +#define IsDclActionNil(x) (((x) & dclActionMask) == dclActionNil) + +// Is this a demand that can trigger a stackwalk? +#define IsDclActionAnyStackModifier(x) ((((x) & dclActionMask) == dclAssert) || \ + (((x) & dclActionMask) == dclDeny) || \ + (((x) & dclActionMask) == dclPermitOnly)) + +// Is this an assembly level attribute (i.e. not applicable on Type/Member)? +#define IsAssemblyDclAction(x) (((x) >= dclRequestMinimum) && \ + ((x) <= dclRequestRefuse)) + +// Is this an NGen only attribute? +#define IsNGenOnlyDclAction(x) (((x) == dclPrejitGrant) || \ + ((x) == dclPrejitDenied)) + + +// MethodImpl attr bits, used by DefineMethodImpl. +typedef enum CorMethodImpl +{ + // code impl mask + miCodeTypeMask = 0x0003, // Flags about code type. + miIL = 0x0000, // Method impl is IL. + miNative = 0x0001, // Method impl is native. + miOPTIL = 0x0002, // Method impl is OPTIL + miRuntime = 0x0003, // Method impl is provided by the runtime. + // end code impl mask + + // managed mask + miManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged. + miUnmanaged = 0x0004, // Method impl is unmanaged, otherwise managed. + miManaged = 0x0000, // Method impl is managed. + // end managed mask + + // implementation info and interop + miForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios. + miPreserveSig = 0x0080, // Indicates method sig is not to be mangled to do HRESULT conversion. + + miInternalCall = 0x1000, // Reserved for internal use. + + miSynchronized = 0x0020, // Method is single threaded through the body. + miNoInlining = 0x0008, // Method may not be inlined. + miAggressiveInlining = 0x0100, // Method should be inlined if possible. + miNoOptimization = 0x0040, // Method may not be optimized. + miAggressiveOptimization = 0x0200, // Method may contain hot code and should be aggressively optimized. + + // These are the flags that are allowed in MethodImplAttribute's Value + // property. This should include everything above except the code impl + // flags (which are used for MethodImplAttribute's MethodCodeType field). + miUserMask = miManagedMask | miForwardRef | miPreserveSig | + miInternalCall | miSynchronized | + miNoInlining | miAggressiveInlining | + miNoOptimization | miAggressiveOptimization, + + miMaxMethodImplVal = 0xffff, // Range check value +} CorMethodImpl; + +// Macros for accesing the members of CorMethodImpl. +#define IsMiIL(x) (((x) & miCodeTypeMask) == miIL) +#define IsMiNative(x) (((x) & miCodeTypeMask) == miNative) +#define IsMiOPTIL(x) (((x) & miCodeTypeMask) == miOPTIL) +#define IsMiRuntime(x) (((x) & miCodeTypeMask) == miRuntime) + +#define IsMiUnmanaged(x) (((x) & miManagedMask) == miUnmanaged) +#define IsMiManaged(x) (((x) & miManagedMask) == miManaged) + +#define IsMiForwardRef(x) ((x) & miForwardRef) +#define IsMiPreserveSig(x) ((x) & miPreserveSig) + +#define IsMiInternalCall(x) ((x) & miInternalCall) + +#define IsMiSynchronized(x) ((x) & miSynchronized) +#define IsMiNoInlining(x) ((x) & miNoInlining) +#define IsMiAggressiveInlining(x) ((x) & miAggressiveInlining) +#define IsMiNoOptimization(x) ((x) & miNoOptimization) +#define IsMiAggressiveOptimization(x) (((x) & (miAggressiveOptimization | miNoOptimization)) == miAggressiveOptimization) + +// PinvokeMap attr bits, used by DefinePinvokeMap. +typedef enum CorPinvokeMap +{ + pmNoMangle = 0x0001, // Pinvoke is to use the member name as specified. + + // Use this mask to retrieve the CharSet information. + pmCharSetMask = 0x0006, + pmCharSetNotSpec = 0x0000, + pmCharSetAnsi = 0x0002, + pmCharSetUnicode = 0x0004, + pmCharSetAuto = 0x0006, + + + pmBestFitUseAssem = 0x0000, + pmBestFitEnabled = 0x0010, + pmBestFitDisabled = 0x0020, + pmBestFitMask = 0x0030, + + pmThrowOnUnmappableCharUseAssem = 0x0000, + pmThrowOnUnmappableCharEnabled = 0x1000, + pmThrowOnUnmappableCharDisabled = 0x2000, + pmThrowOnUnmappableCharMask = 0x3000, + + pmSupportsLastError = 0x0040, // Information about target function. Not relevant for fields. + + // None of the calling convention flags is relevant for fields. + pmCallConvMask = 0x0700, + pmCallConvWinapi = 0x0100, // Pinvoke will use native callconv appropriate to target windows platform. + pmCallConvCdecl = 0x0200, + pmCallConvStdcall = 0x0300, + pmCallConvThiscall = 0x0400, // In M9, pinvoke will raise exception. + pmCallConvFastcall = 0x0500, + + pmMaxValue = 0xFFFF, +} CorPinvokeMap; + +// Macros for accessing the members of CorPinvokeMap +#define IsPmNoMangle(x) ((x) & pmNoMangle) + +#define IsPmCharSetNotSpec(x) (((x) & pmCharSetMask) == pmCharSetNotSpec) +#define IsPmCharSetAnsi(x) (((x) & pmCharSetMask) == pmCharSetAnsi) +#define IsPmCharSetUnicode(x) (((x) & pmCharSetMask) == pmCharSetUnicode) +#define IsPmCharSetAuto(x) (((x) & pmCharSetMask) == pmCharSetAuto) + +#define IsPmSupportsLastError(x) ((x) & pmSupportsLastError) + +#define IsPmCallConvWinapi(x) (((x) & pmCallConvMask) == pmCallConvWinapi) +#define IsPmCallConvCdecl(x) (((x) & pmCallConvMask) == pmCallConvCdecl) +#define IsPmCallConvStdcall(x) (((x) & pmCallConvMask) == pmCallConvStdcall) +#define IsPmCallConvThiscall(x) (((x) & pmCallConvMask) == pmCallConvThiscall) +#define IsPmCallConvFastcall(x) (((x) & pmCallConvMask) == pmCallConvFastcall) + +#define IsPmBestFitEnabled(x) (((x) & pmBestFitMask) == pmBestFitEnabled) +#define IsPmBestFitDisabled(x) (((x) & pmBestFitMask) == pmBestFitDisabled) +#define IsPmBestFitUseAssem(x) (((x) & pmBestFitMask) == pmBestFitUseAssem) + +#define IsPmThrowOnUnmappableCharEnabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharEnabled) +#define IsPmThrowOnUnmappableCharDisabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharDisabled) +#define IsPmThrowOnUnmappableCharUseAssem(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharUseAssem) + +// Assembly attr bits, used by DefineAssembly. +typedef enum CorAssemblyFlags +{ + afPublicKey = 0x0001, // The assembly ref holds the full (unhashed) public key. + + afPA_None = 0x0000, // Processor Architecture unspecified + afPA_MSIL = 0x0010, // Processor Architecture: neutral (PE32) + afPA_x86 = 0x0020, // Processor Architecture: x86 (PE32) + afPA_IA64 = 0x0030, // Processor Architecture: Itanium (PE32+) + afPA_AMD64 = 0x0040, // Processor Architecture: AMD X64 (PE32+) + afPA_ARM = 0x0050, // Processor Architecture: ARM (PE32) + afPA_ARM64 = 0x0060, // Processor Architecture: ARM64 (PE32+) + afPA_NoPlatform = 0x0070, // applies to any platform but cannot run on any (e.g. reference assembly), should not have "specified" set + afPA_Specified = 0x0080, // Propagate PA flags to AssemblyRef record + afPA_Mask = 0x0070, // Bits describing the processor architecture + afPA_FullMask = 0x00F0, // Bits describing the PA incl. Specified + afPA_Shift = 0x0004, // NOT A FLAG, shift count in PA flags <--> index conversion + + afEnableJITcompileTracking = 0x8000, // From "DebuggableAttribute". + afDisableJITcompileOptimizer = 0x4000, // From "DebuggableAttribute". + afDebuggableAttributeMask = 0xc000, + + afRetargetable = 0x0100, // The assembly can be retargeted (at runtime) to an + // assembly from a different publisher. + + afContentType_Default = 0x0000, + afContentType_WindowsRuntime = 0x0200, + afContentType_Mask = 0x0E00, // Bits describing ContentType +} CorAssemblyFlags; + +// Macros for accessing the members of CorAssemblyFlags. +#define IsAfRetargetable(x) ((x) & afRetargetable) +#define IsAfContentType_Default(x) (((x) & afContentType_Mask) == afContentType_Default) +#define IsAfContentType_WindowsRuntime(x) (((x) & afContentType_Mask) == afContentType_WindowsRuntime) + +// Macros for accessing the Processor Architecture flags of CorAssemblyFlags. +#define IsAfPA_MSIL(x) (((x) & afPA_Mask) == afPA_MSIL) +#define IsAfPA_x86(x) (((x) & afPA_Mask) == afPA_x86) +#define IsAfPA_IA64(x) (((x) & afPA_Mask) == afPA_IA64) +#define IsAfPA_AMD64(x) (((x) & afPA_Mask) == afPA_AMD64) +#define IsAfPA_ARM(x) (((x) & afPA_Mask) == afPA_ARM) +#define IsAfPA_ARM64(x) (((x) & afPA_Mask) == afPA_ARM64) +#define IsAfPA_NoPlatform(x) (((x) & afPA_FullMask) == afPA_NoPlatform) +#define IsAfPA_Specified(x) ((x) & afPA_Specified) +#define PAIndex(x) (((x) & afPA_Mask) >> afPA_Shift) +#define PAFlag(x) (((x) << afPA_Shift) & afPA_Mask) +#define PrepareForSaving(x) ((x) & (((x) & afPA_Specified) ? ~afPA_Specified : ~afPA_FullMask)) + +#define IsAfEnableJITcompileTracking(x) ((x) & afEnableJITcompileTracking) +#define IsAfDisableJITcompileOptimizer(x) ((x) & afDisableJITcompileOptimizer) + +// Macros for accessing the public key flags of CorAssemblyFlags. +#define IsAfPublicKey(x) ((x) & afPublicKey) +#define IsAfPublicKeyToken(x) (((x) & afPublicKey) == 0) + + +// ManifestResource attr bits, used by DefineManifestResource. +typedef enum CorManifestResourceFlags +{ + mrVisibilityMask = 0x0007, + mrPublic = 0x0001, // The Resource is exported from the Assembly. + mrPrivate = 0x0002, // The Resource is private to the Assembly. +} CorManifestResourceFlags; + +// Macros for accessing the members of CorManifestResourceFlags. +#define IsMrPublic(x) (((x) & mrVisibilityMask) == mrPublic) +#define IsMrPrivate(x) (((x) & mrVisibilityMask) == mrPrivate) + + +// File attr bits, used by DefineFile. +typedef enum CorFileFlags +{ + ffContainsMetaData = 0x0000, // This is not a resource file + ffContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file +} CorFileFlags; + +// Macros for accessing the members of CorFileFlags. +#define IsFfContainsMetaData(x) (!((x) & ffContainsNoMetaData)) +#define IsFfContainsNoMetaData(x) ((x) & ffContainsNoMetaData) + +// PE file kind bits, returned by IMetaDataImport2::GetPEKind() +typedef enum CorPEKind +{ + peNot = 0x00000000, // not a PE file + peILonly = 0x00000001, // flag IL_ONLY is set in COR header + pe32BitRequired=0x00000002, // flag 32BITREQUIRED is set and 32BITPREFERRED is clear in COR header + pe32Plus = 0x00000004, // PE32+ file (64 bit) + pe32Unmanaged=0x00000008, // PE32 without COR header + pe32BitPreferred=0x00000010 // flags 32BITREQUIRED and 32BITPREFERRED are set in COR header +} CorPEKind; + + +// GenericParam bits, used by DefineGenericParam. +typedef enum CorGenericParamAttr +{ + // Variance of type parameters, only applicable to generic parameters + // for generic interfaces and delegates + gpVarianceMask = 0x0003, + gpNonVariant = 0x0000, + gpCovariant = 0x0001, + gpContravariant = 0x0002, + + // Special constraints, applicable to any type parameters + gpSpecialConstraintMask = 0x001C, + gpNoSpecialConstraint = 0x0000, + gpReferenceTypeConstraint = 0x0004, // type argument must be a reference type + gpNotNullableValueTypeConstraint = 0x0008, // type argument must be a value type but not Nullable + gpDefaultConstructorConstraint = 0x0010, // type argument must have a public default constructor +} CorGenericParamAttr; + +// structures and enums moved from COR.H +typedef unsigned __int8 COR_SIGNATURE; + +typedef COR_SIGNATURE* PCOR_SIGNATURE; // pointer to a cor sig. Not void* so that + // the bytes can be incremented easily +typedef const COR_SIGNATURE* PCCOR_SIGNATURE; + + +typedef const char * MDUTF8CSTR; +typedef char * MDUTF8STR; + +//***************************************************************************** +// +// Element type for Cor signature +// +//***************************************************************************** + +typedef enum CorElementType +{ + ELEMENT_TYPE_END = 0x00, + ELEMENT_TYPE_VOID = 0x01, + ELEMENT_TYPE_BOOLEAN = 0x02, + ELEMENT_TYPE_CHAR = 0x03, + ELEMENT_TYPE_I1 = 0x04, + ELEMENT_TYPE_U1 = 0x05, + ELEMENT_TYPE_I2 = 0x06, + ELEMENT_TYPE_U2 = 0x07, + ELEMENT_TYPE_I4 = 0x08, + ELEMENT_TYPE_U4 = 0x09, + ELEMENT_TYPE_I8 = 0x0a, + ELEMENT_TYPE_U8 = 0x0b, + ELEMENT_TYPE_R4 = 0x0c, + ELEMENT_TYPE_R8 = 0x0d, + ELEMENT_TYPE_STRING = 0x0e, + + // every type above PTR will be simple type + ELEMENT_TYPE_PTR = 0x0f, // PTR + ELEMENT_TYPE_BYREF = 0x10, // BYREF + + // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. + ELEMENT_TYPE_VALUETYPE = 0x11, // VALUETYPE + ELEMENT_TYPE_CLASS = 0x12, // CLASS + ELEMENT_TYPE_VAR = 0x13, // a class type variable VAR + ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... + ELEMENT_TYPE_GENERICINST = 0x15, // GENERICINST ... + ELEMENT_TYPE_TYPEDBYREF = 0x16, // TYPEDREF (it takes no args) a typed referece to some other type + + ELEMENT_TYPE_I = 0x18, // native integer size + ELEMENT_TYPE_U = 0x19, // native unsigned integer size + ELEMENT_TYPE_FNPTR = 0x1b, // FNPTR + ELEMENT_TYPE_OBJECT = 0x1c, // Shortcut for System.Object + ELEMENT_TYPE_SZARRAY = 0x1d, // Shortcut for single dimension zero lower bound array + // SZARRAY + ELEMENT_TYPE_MVAR = 0x1e, // a method type variable MVAR + + // This is only for binding + ELEMENT_TYPE_CMOD_REQD = 0x1f, // required C modifier : E_T_CMOD_REQD + ELEMENT_TYPE_CMOD_OPT = 0x20, // optional C modifier : E_T_CMOD_OPT + + // This is for signatures generated internally (which will not be persisted in any way). + ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL + + // Note that this is the max of base type excluding modifiers + ELEMENT_TYPE_MAX = 0x22, // first invalid element type + + + ELEMENT_TYPE_MODIFIER = 0x40, + ELEMENT_TYPE_SENTINEL = 0x01 | ELEMENT_TYPE_MODIFIER, // sentinel for varargs + ELEMENT_TYPE_PINNED = 0x05 | ELEMENT_TYPE_MODIFIER, + +} CorElementType; + + +//***************************************************************************** +// +// Serialization types for Custom attribute support +// +//***************************************************************************** + +typedef enum CorSerializationType +{ + SERIALIZATION_TYPE_UNDEFINED = 0, + SERIALIZATION_TYPE_BOOLEAN = ELEMENT_TYPE_BOOLEAN, + SERIALIZATION_TYPE_CHAR = ELEMENT_TYPE_CHAR, + SERIALIZATION_TYPE_I1 = ELEMENT_TYPE_I1, + SERIALIZATION_TYPE_U1 = ELEMENT_TYPE_U1, + SERIALIZATION_TYPE_I2 = ELEMENT_TYPE_I2, + SERIALIZATION_TYPE_U2 = ELEMENT_TYPE_U2, + SERIALIZATION_TYPE_I4 = ELEMENT_TYPE_I4, + SERIALIZATION_TYPE_U4 = ELEMENT_TYPE_U4, + SERIALIZATION_TYPE_I8 = ELEMENT_TYPE_I8, + SERIALIZATION_TYPE_U8 = ELEMENT_TYPE_U8, + SERIALIZATION_TYPE_R4 = ELEMENT_TYPE_R4, + SERIALIZATION_TYPE_R8 = ELEMENT_TYPE_R8, + SERIALIZATION_TYPE_STRING = ELEMENT_TYPE_STRING, + SERIALIZATION_TYPE_SZARRAY = ELEMENT_TYPE_SZARRAY, // Shortcut for single dimension zero lower bound array + SERIALIZATION_TYPE_TYPE = 0x50, + SERIALIZATION_TYPE_TAGGED_OBJECT= 0x51, + SERIALIZATION_TYPE_FIELD = 0x53, + SERIALIZATION_TYPE_PROPERTY = 0x54, + SERIALIZATION_TYPE_ENUM = 0x55 +} CorSerializationType; + +// +// Calling convention flags. +// + + +typedef enum CorCallingConvention +{ + IMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0, + + IMAGE_CEE_CS_CALLCONV_VARARG = 0x5, + IMAGE_CEE_CS_CALLCONV_FIELD = 0x6, + IMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x7, + IMAGE_CEE_CS_CALLCONV_PROPERTY = 0x8, + IMAGE_CEE_CS_CALLCONV_UNMGD = 0x9, + IMAGE_CEE_CS_CALLCONV_GENERICINST = 0xa, // generic method instantiation + IMAGE_CEE_CS_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for 64bit vararg PInvoke calls + IMAGE_CEE_CS_CALLCONV_MAX = 0xc, // first invalid calling convention + + + // The high bits of the calling convention convey additional info + IMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits + IMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter + IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature + IMAGE_CEE_CS_CALLCONV_GENERIC = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) + // 0x80 is reserved for internal use +} CorCallingConvention; + +#define IMAGE_CEE_CS_CALLCONV_INSTANTIATION IMAGE_CEE_CS_CALLCONV_GENERICINST + +typedef enum CorUnmanagedCallingConvention +{ + IMAGE_CEE_UNMANAGED_CALLCONV_C = 0x1, + IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL = 0x2, + IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL = 0x3, + IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL = 0x4, + + IMAGE_CEE_CS_CALLCONV_C = IMAGE_CEE_UNMANAGED_CALLCONV_C, + IMAGE_CEE_CS_CALLCONV_STDCALL = IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL, + IMAGE_CEE_CS_CALLCONV_THISCALL = IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL, + IMAGE_CEE_CS_CALLCONV_FASTCALL = IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL, + +} CorUnmanagedCallingConvention; + + +typedef enum CorArgType +{ + IMAGE_CEE_CS_END = 0x0, + IMAGE_CEE_CS_VOID = 0x1, + IMAGE_CEE_CS_I4 = 0x2, + IMAGE_CEE_CS_I8 = 0x3, + IMAGE_CEE_CS_R4 = 0x4, + IMAGE_CEE_CS_R8 = 0x5, + IMAGE_CEE_CS_PTR = 0x6, + IMAGE_CEE_CS_OBJECT = 0x7, + IMAGE_CEE_CS_STRUCT4 = 0x8, + IMAGE_CEE_CS_STRUCT32 = 0x9, + IMAGE_CEE_CS_BYVALUE = 0xA, +} CorArgType; + + +//***************************************************************************** +// +// Native type for N-Direct +// +//***************************************************************************** + +typedef enum CorNativeType +{ + + // Kepp this in-synch with ndp\clr\src\BCL\System\runtime\interopservices\attributes.cs + + NATIVE_TYPE_END = 0x0, //DEPRECATED + NATIVE_TYPE_VOID = 0x1, //DEPRECATED + NATIVE_TYPE_BOOLEAN = 0x2, // (4 byte boolean value: TRUE = non-zero, FALSE = 0) + NATIVE_TYPE_I1 = 0x3, + NATIVE_TYPE_U1 = 0x4, + NATIVE_TYPE_I2 = 0x5, + NATIVE_TYPE_U2 = 0x6, + NATIVE_TYPE_I4 = 0x7, + NATIVE_TYPE_U4 = 0x8, + NATIVE_TYPE_I8 = 0x9, + NATIVE_TYPE_U8 = 0xa, + NATIVE_TYPE_R4 = 0xb, + NATIVE_TYPE_R8 = 0xc, + NATIVE_TYPE_SYSCHAR = 0xd, //DEPRECATED + NATIVE_TYPE_VARIANT = 0xe, //DEPRECATED + NATIVE_TYPE_CURRENCY = 0xf, + NATIVE_TYPE_PTR = 0x10, //DEPRECATED + + NATIVE_TYPE_DECIMAL = 0x11, //DEPRECATED + NATIVE_TYPE_DATE = 0x12, //DEPRECATED + NATIVE_TYPE_BSTR = 0x13, //COMINTEROP + NATIVE_TYPE_LPSTR = 0x14, + NATIVE_TYPE_LPWSTR = 0x15, + NATIVE_TYPE_LPTSTR = 0x16, + NATIVE_TYPE_FIXEDSYSSTRING = 0x17, + NATIVE_TYPE_OBJECTREF = 0x18, //DEPRECATED + NATIVE_TYPE_IUNKNOWN = 0x19, //COMINTEROP + NATIVE_TYPE_IDISPATCH = 0x1a, //COMINTEROP + NATIVE_TYPE_STRUCT = 0x1b, + NATIVE_TYPE_INTF = 0x1c, //COMINTEROP + NATIVE_TYPE_SAFEARRAY = 0x1d, //COMINTEROP + NATIVE_TYPE_FIXEDARRAY = 0x1e, + NATIVE_TYPE_INT = 0x1f, + NATIVE_TYPE_UINT = 0x20, + + NATIVE_TYPE_NESTEDSTRUCT = 0x21, //DEPRECATED (use NATIVE_TYPE_STRUCT) + + NATIVE_TYPE_BYVALSTR = 0x22, //COMINTEROP + + NATIVE_TYPE_ANSIBSTR = 0x23, //COMINTEROP + + NATIVE_TYPE_TBSTR = 0x24, // select BSTR or ANSIBSTR depending on platform + //COMINTEROP + + NATIVE_TYPE_VARIANTBOOL = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0) + //COMINTEROP + NATIVE_TYPE_FUNC = 0x26, + + NATIVE_TYPE_ASANY = 0x28, + + NATIVE_TYPE_ARRAY = 0x2a, + NATIVE_TYPE_LPSTRUCT = 0x2b, + + NATIVE_TYPE_CUSTOMMARSHALER = 0x2c, // Custom marshaler native type. This must be followed + // by a string of the following format: + // "Native type name/0Custom marshaler type name/0Optional cookie/0" + // Or + // "{Native type GUID}/0Custom marshaler type name/0Optional cookie/0" + + NATIVE_TYPE_ERROR = 0x2d, // This native type coupled with ELEMENT_TYPE_I4 will map to VT_HRESULT + //COMINTEROP + + NATIVE_TYPE_IINSPECTABLE = 0x2e, + NATIVE_TYPE_HSTRING = 0x2f, + NATIVE_TYPE_LPUTF8STR = 0x30, // utf-8 string + NATIVE_TYPE_MAX = 0x50, // first invalid element type +} CorNativeType; + + +enum +{ + DESCR_GROUP_METHODDEF = 0, // DESCR group for MethodDefs + DESCR_GROUP_METHODIMPL, // DESCR group for MethodImpls +}; + +/***********************************************************************************/ +// a COR_ILMETHOD_SECT is a generic container for attributes that are private +// to a particular method. The COR_ILMETHOD structure points to one of these +// (see GetSect()). COR_ILMETHOD_SECT can decode the Kind of attribute (but not +// its internal data layout, and can skip past the current attibute to find the +// Next one. The overhead for COR_ILMETHOD_SECT is a minimum of 2 bytes. + +typedef enum CorILMethodSect // codes that identify attributes +{ + CorILMethod_Sect_Reserved = 0, + CorILMethod_Sect_EHTable = 1, + CorILMethod_Sect_OptILTable = 2, + + CorILMethod_Sect_KindMask = 0x3F, // The mask for decoding the type code + CorILMethod_Sect_FatFormat = 0x40, // fat format + CorILMethod_Sect_MoreSects = 0x80, // there is another attribute after this one +} CorILMethodSect; + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ + +typedef struct IMAGE_COR_ILMETHOD_SECT_SMALL +{ + BYTE Kind; + BYTE DataSize; + +} IMAGE_COR_ILMETHOD_SECT_SMALL; + + + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ +typedef struct IMAGE_COR_ILMETHOD_SECT_FAT +{ + unsigned Kind : 8; + unsigned DataSize : 24; + +} IMAGE_COR_ILMETHOD_SECT_FAT; + + + +/***********************************************************************************/ +/* If COR_ILMETHOD_SECT_HEADER::Kind() = CorILMethod_Sect_EHTable then the attribute + is a list of exception handling clauses. There are two formats, fat or small +*/ +typedef enum CorExceptionFlag // definitions for the Flags field below (for both big and small) +{ + COR_ILEXCEPTION_CLAUSE_NONE, // This is a typed handler + COR_ILEXCEPTION_CLAUSE_OFFSETLEN = 0x0000, // Deprecated + COR_ILEXCEPTION_CLAUSE_DEPRECATED = 0x0000, // Deprecated + COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter + COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause + COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // Fault clause (finally that is called on exception only) + COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This clause was duplicated to a funclet which was pulled out of line +} CorExceptionFlag; + +/***********************************/ +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT +{ + CorExceptionFlag Flags; + DWORD TryOffset; + DWORD TryLength; // relative to start of try block + DWORD HandlerOffset; + DWORD HandlerLength; // relative to start of handler + union { + DWORD ClassToken; // use for type-based exception handlers + DWORD FilterOffset; // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set) + }; +} IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT; + +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_FAT +{ + IMAGE_COR_ILMETHOD_SECT_FAT SectFat; + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size +} IMAGE_COR_ILMETHOD_SECT_EH_FAT; + +/***********************************/ +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL +{ +#ifdef _WIN64 + unsigned Flags : 16; +#else // !_WIN64 + CorExceptionFlag Flags : 16; +#endif + unsigned TryOffset : 16; + unsigned TryLength : 8; // relative to start of try block + unsigned HandlerOffset : 16; + unsigned HandlerLength : 8; // relative to start of handler + union { + DWORD ClassToken; + DWORD FilterOffset; + }; +} IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; + +/***********************************/ +typedef struct IMAGE_COR_ILMETHOD_SECT_EH_SMALL +{ + IMAGE_COR_ILMETHOD_SECT_SMALL SectSmall; + WORD Reserved; + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size +} IMAGE_COR_ILMETHOD_SECT_EH_SMALL; + + + +typedef union IMAGE_COR_ILMETHOD_SECT_EH +{ + IMAGE_COR_ILMETHOD_SECT_EH_SMALL Small; + IMAGE_COR_ILMETHOD_SECT_EH_FAT Fat; +} IMAGE_COR_ILMETHOD_SECT_EH; + + +/***********************************************************************************/ +// Legal values for +// * code:IMAGE_COR_ILMETHOD_FAT::Flags or +// * code:IMAGE_COR_ILMETHOD_TINY::Flags_CodeSize fields. +// +// The only semantic flag at present is CorILMethod_InitLocals +typedef enum CorILMethodFlags +{ + CorILMethod_InitLocals = 0x0010, // call default constructor on all local vars + CorILMethod_MoreSects = 0x0008, // there is another attribute after this one + + CorILMethod_CompressedIL = 0x0040, // Not used. + + // Indicates the format for the COR_ILMETHOD header + CorILMethod_FormatShift = 3, + CorILMethod_FormatMask = ((1 << CorILMethod_FormatShift) - 1), + CorILMethod_TinyFormat = 0x0002, // use this code if the code size is even + CorILMethod_SmallFormat = 0x0000, + CorILMethod_FatFormat = 0x0003, + CorILMethod_TinyFormat1 = 0x0006, // use this code if the code size is odd +} CorILMethodFlags; + +/***************************************************************************/ +/* Used when the method is tiny (< 64 bytes), and there are no local vars */ +typedef struct IMAGE_COR_ILMETHOD_TINY +{ + BYTE Flags_CodeSize; +} IMAGE_COR_ILMETHOD_TINY; + +/************************************/ +// This strucuture is the 'fat' layout, where no compression is attempted. +// Note that this structure can be added on at the end, thus making it extensible +typedef struct IMAGE_COR_ILMETHOD_FAT +{ + unsigned Flags : 12; // Flags see code:CorILMethodFlags + unsigned Size : 4; // size in DWords of this structure (currently 3) + unsigned MaxStack : 16; // maximum number of items (I4, I, I8, obj ...), on the operand stack + DWORD CodeSize; // size of the code + mdSignature LocalVarSigTok; // token that indicates the signature of the local vars (0 means none) + +} IMAGE_COR_ILMETHOD_FAT; + +// an IMAGE_COR_ILMETHOD holds the IL instructions for a individual method. To save space they come in two +// flavors Fat and Tiny. Conceptually Tiny is just a compressed version of Fat, so code:IMAGE_COR_ILMETHOD_FAT +// is the logical structure for all headers. Conceptually this blob holds the IL, the Exception Handling +// Tables, the local variable information and some flags. +typedef union IMAGE_COR_ILMETHOD +{ + IMAGE_COR_ILMETHOD_TINY Tiny; + IMAGE_COR_ILMETHOD_FAT Fat; +} IMAGE_COR_ILMETHOD; + +//***************************************************************************** +// Non VOS v-table entries. Define an array of these pointed to by +// IMAGE_COR20_HEADER.VTableFixups. Each entry describes a contiguous array of +// v-table slots. The slots start out initialized to the meta data token value +// for the method they need to call. At image load time, the CLR Loader will +// turn each entry into a pointer to machine code for the CPU and can be +// called directly. +//***************************************************************************** + +typedef struct IMAGE_COR_VTABLEFIXUP +{ + ULONG RVA; // Offset of v-table array in image. + USHORT Count; // How many entries at location. + USHORT Type; // COR_VTABLE_xxx type of entries. +} IMAGE_COR_VTABLEFIXUP; + + + + + +//***************************************************************************** +//***************************************************************************** +// +// M E T A - D A T A D E C L A R A T I O N S +// +//***************************************************************************** +//***************************************************************************** + +//***************************************************************************** +// +// Enums for SetOption API. +// +//***************************************************************************** + +// flags for MetaDataCheckDuplicatesFor +typedef enum CorCheckDuplicatesFor +{ + MDDupAll = 0xffffffff, + MDDupENC = MDDupAll, + MDNoDupChecks = 0x00000000, + MDDupTypeDef = 0x00000001, + MDDupInterfaceImpl = 0x00000002, + MDDupMethodDef = 0x00000004, + MDDupTypeRef = 0x00000008, + MDDupMemberRef = 0x00000010, + MDDupCustomAttribute = 0x00000020, + MDDupParamDef = 0x00000040, + MDDupPermission = 0x00000080, + MDDupProperty = 0x00000100, + MDDupEvent = 0x00000200, + MDDupFieldDef = 0x00000400, + MDDupSignature = 0x00000800, + MDDupModuleRef = 0x00001000, + MDDupTypeSpec = 0x00002000, + MDDupImplMap = 0x00004000, + MDDupAssemblyRef = 0x00008000, + MDDupFile = 0x00010000, + MDDupExportedType = 0x00020000, + MDDupManifestResource = 0x00040000, + MDDupGenericParam = 0x00080000, + MDDupMethodSpec = 0x00100000, + MDDupGenericParamConstraint = 0x00200000, + // gap for debug junk + MDDupAssembly = 0x10000000, + + // This is the default behavior on metadata. It will check duplicates for TypeRef, MemberRef, Signature, TypeSpec and MethodSpec. + MDDupDefault = MDNoDupChecks | MDDupTypeRef | MDDupMemberRef | MDDupSignature | MDDupTypeSpec | MDDupMethodSpec, +} CorCheckDuplicatesFor; + +// flags for MetaDataRefToDefCheck +typedef enum CorRefToDefCheck +{ + // default behavior is to always perform TypeRef to TypeDef and MemberRef to MethodDef/FieldDef optimization + MDRefToDefDefault = 0x00000003, + MDRefToDefAll = 0xffffffff, + MDRefToDefNone = 0x00000000, + MDTypeRefToDef = 0x00000001, + MDMemberRefToDef = 0x00000002 +} CorRefToDefCheck; + + +// MetaDataNotificationForTokenMovement +typedef enum CorNotificationForTokenMovement +{ + // default behavior is to notify TypeRef, MethodDef, MemberRef, and FieldDef token remaps + MDNotifyDefault = 0x0000000f, + MDNotifyAll = 0xffffffff, + MDNotifyNone = 0x00000000, + MDNotifyMethodDef = 0x00000001, + MDNotifyMemberRef = 0x00000002, + MDNotifyFieldDef = 0x00000004, + MDNotifyTypeRef = 0x00000008, + + MDNotifyTypeDef = 0x00000010, + MDNotifyParamDef = 0x00000020, + MDNotifyInterfaceImpl = 0x00000040, + MDNotifyProperty = 0x00000080, + MDNotifyEvent = 0x00000100, + MDNotifySignature = 0x00000200, + MDNotifyTypeSpec = 0x00000400, + MDNotifyCustomAttribute = 0x00000800, + MDNotifySecurityValue = 0x00001000, + MDNotifyPermission = 0x00002000, + MDNotifyModuleRef = 0x00004000, + + MDNotifyNameSpace = 0x00008000, + + MDNotifyAssemblyRef = 0x01000000, + MDNotifyFile = 0x02000000, + MDNotifyExportedType = 0x04000000, + MDNotifyResource = 0x08000000, +} CorNotificationForTokenMovement; + + +typedef enum CorSetENC +{ + MDSetENCOn = 0x00000001, // Deprecated name. + MDSetENCOff = 0x00000002, // Deprecated name. + + MDUpdateENC = 0x00000001, // ENC mode. Tokens don't move; can be updated. + MDUpdateFull = 0x00000002, // "Normal" update mode. + MDUpdateExtension = 0x00000003, // Extension mode. Tokens don't move, adds only. + MDUpdateIncremental = 0x00000004, // Incremental compilation + MDUpdateDelta = 0x00000005, // If ENC on, save only deltas. + MDUpdateMask = 0x00000007, + + +} CorSetENC; + +#define IsENCDelta(x) (((x) & MDUpdateMask) == MDUpdateDelta) + +// flags used in SetOption when pair with MetaDataErrorIfEmitOutOfOrder guid +typedef enum CorErrorIfEmitOutOfOrder +{ + MDErrorOutOfOrderDefault = 0x00000000, // default not to generate any error + MDErrorOutOfOrderNone = 0x00000000, // do not generate error for out of order emit + MDErrorOutOfOrderAll = 0xffffffff, // generate out of order emit for method, field, param, property, and event + MDMethodOutOfOrder = 0x00000001, // generate error when methods are emitted out of order + MDFieldOutOfOrder = 0x00000002, // generate error when fields are emitted out of order + MDParamOutOfOrder = 0x00000004, // generate error when params are emitted out of order + MDPropertyOutOfOrder = 0x00000008, // generate error when properties are emitted out of order + MDEventOutOfOrder = 0x00000010, // generate error when events are emitted out of order +} CorErrorIfEmitOutOfOrder; + + +// flags used in SetOption when pair with MetaDataImportOption guid +typedef enum CorImportOptions +{ + MDImportOptionDefault = 0x00000000, // default to skip over deleted records + MDImportOptionAll = 0xFFFFFFFF, // Enumerate everything + MDImportOptionAllTypeDefs = 0x00000001, // all of the typedefs including the deleted typedef + MDImportOptionAllMethodDefs = 0x00000002, // all of the methoddefs including the deleted ones + MDImportOptionAllFieldDefs = 0x00000004, // all of the fielddefs including the deleted ones + MDImportOptionAllProperties = 0x00000008, // all of the properties including the deleted ones + MDImportOptionAllEvents = 0x00000010, // all of the events including the deleted ones + MDImportOptionAllCustomAttributes = 0x00000020, // all of the custom attributes including the deleted ones + MDImportOptionAllExportedTypes = 0x00000040, // all of the ExportedTypes including the deleted ones + +} CorImportOptions; + + +// flags for MetaDataThreadSafetyOptions +typedef enum CorThreadSafetyOptions +{ + // default behavior is to have thread safety turn off. This means that MetaData APIs will not take reader/writer + // lock. Clients is responsible to make sure the properly thread synchornization when using MetaData APIs. + MDThreadSafetyDefault = 0x00000000, + MDThreadSafetyOff = 0x00000000, + MDThreadSafetyOn = 0x00000001, +} CorThreadSafetyOptions; + + +// flags for MetaDataLinkerOptions +typedef enum CorLinkerOptions +{ + // default behavior is not to keep private types + MDAssembly = 0x00000000, + MDNetModule = 0x00000001, +} CorLinkerOptions; + +// flags for MetaDataMergeOptions +typedef enum MergeFlags +{ + MergeFlagsNone = 0, + MergeManifest = 0x00000001, + DropMemberRefCAs = 0x00000002, + NoDupCheck = 0x00000004, + MergeExportedTypes = 0x00000008 +} MergeFlags; + +// flags for MetaDataPreserveLocalRefs +typedef enum CorLocalRefPreservation +{ + MDPreserveLocalRefsNone = 0x00000000, + MDPreserveLocalTypeRef = 0x00000001, + MDPreserveLocalMemberRef = 0x00000002 +} CorLocalRefPreservation; + +// +// struct used to retrieve field offset +// used by GetClassLayout and SetClassLayout +// + +#ifndef _COR_FIELD_OFFSET_ +#define _COR_FIELD_OFFSET_ + +typedef struct COR_FIELD_OFFSET +{ + mdFieldDef ridOfField; + ULONG ulOffset; +} COR_FIELD_OFFSET; + +#endif + + +// +// Token tags. +// +typedef enum CorTokenType +{ + mdtModule = 0x00000000, // + mdtTypeRef = 0x01000000, // + mdtTypeDef = 0x02000000, // + mdtFieldDef = 0x04000000, // + mdtMethodDef = 0x06000000, // + mdtParamDef = 0x08000000, // + mdtInterfaceImpl = 0x09000000, // + mdtMemberRef = 0x0a000000, // + mdtCustomAttribute = 0x0c000000, // + mdtPermission = 0x0e000000, // + mdtSignature = 0x11000000, // + mdtEvent = 0x14000000, // + mdtProperty = 0x17000000, // + mdtMethodImpl = 0x19000000, // + mdtModuleRef = 0x1a000000, // + mdtTypeSpec = 0x1b000000, // + mdtAssembly = 0x20000000, // + mdtAssemblyRef = 0x23000000, // + mdtFile = 0x26000000, // + mdtExportedType = 0x27000000, // + mdtManifestResource = 0x28000000, // + mdtGenericParam = 0x2a000000, // + mdtMethodSpec = 0x2b000000, // + mdtGenericParamConstraint = 0x2c000000, + + mdtString = 0x70000000, // + mdtName = 0x71000000, // + mdtBaseType = 0x72000000, // Leave this on the high end value. This does not correspond to metadata table +} CorTokenType; + +// +// Build / decompose tokens. +// +#define RidToToken(rid,tktype) ((rid) |= (tktype)) +#define TokenFromRid(rid,tktype) ((rid) | (tktype)) +#define RidFromToken(tk) ((RID) ((tk) & 0x00ffffff)) +#define TypeFromToken(tk) ((ULONG32)((tk) & 0xff000000)) +#define IsNilToken(tk) ((RidFromToken(tk)) == 0) + +// +// Nil tokens +// +#define mdTokenNil ((mdToken)0) +#define mdModuleNil ((mdModule)mdtModule) +#define mdTypeRefNil ((mdTypeRef)mdtTypeRef) +#define mdTypeDefNil ((mdTypeDef)mdtTypeDef) +#define mdFieldDefNil ((mdFieldDef)mdtFieldDef) +#define mdMethodDefNil ((mdMethodDef)mdtMethodDef) +#define mdParamDefNil ((mdParamDef)mdtParamDef) +#define mdInterfaceImplNil ((mdInterfaceImpl)mdtInterfaceImpl) +#define mdMemberRefNil ((mdMemberRef)mdtMemberRef) +#define mdCustomAttributeNil ((mdCustomAttribute)mdtCustomAttribute) +#define mdPermissionNil ((mdPermission)mdtPermission) +#define mdSignatureNil ((mdSignature)mdtSignature) +#define mdEventNil ((mdEvent)mdtEvent) +#define mdPropertyNil ((mdProperty)mdtProperty) +#define mdModuleRefNil ((mdModuleRef)mdtModuleRef) +#define mdTypeSpecNil ((mdTypeSpec)mdtTypeSpec) +#define mdAssemblyNil ((mdAssembly)mdtAssembly) +#define mdAssemblyRefNil ((mdAssemblyRef)mdtAssemblyRef) +#define mdFileNil ((mdFile)mdtFile) +#define mdExportedTypeNil ((mdExportedType)mdtExportedType) +#define mdManifestResourceNil ((mdManifestResource)mdtManifestResource) + +#define mdGenericParamNil ((mdGenericParam)mdtGenericParam) +#define mdGenericParamConstraintNil ((mdGenericParamConstraint)mdtGenericParamConstraint) +#define mdMethodSpecNil ((mdMethodSpec)mdtMethodSpec) + +#define mdStringNil ((mdString)mdtString) + +// +// Open bits. +// +typedef enum CorOpenFlags +{ + ofRead = 0x00000000, // Open scope for read + ofWrite = 0x00000001, // Open scope for write. + ofReadWriteMask = 0x00000001, // Mask for read/write bit. + + ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory. + + ofReadOnly = 0x00000010, // Open scope for read. Will be unable to QI for a IMetadataEmit* interface + ofTakeOwnership = 0x00000020, // The memory was allocated with CoTaskMemAlloc and will be freed by the metadata + + // These are obsolete and are ignored. + // ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image + // ofManifestMetadata = 0x00000008, // Open scope on ngen image, return the manifest metadata instead of the IL metadata + ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib. + ofNoTransform = 0x00001000, // Disable automatic transforms of .winmd files. + + // Internal bits + ofReserved1 = 0x00000100, // Reserved for internal use. + ofReserved2 = 0x00000200, // Reserved for internal use. + ofReserved3 = 0x00000400, // Reserved for internal use. + ofReserved = 0xffffef40 // All the reserved bits. + +} CorOpenFlags; + +#define IsOfRead(x) (((x) & ofReadWriteMask) == ofRead) +#define IsOfReadWrite(x) (((x) & ofReadWriteMask) == ofWrite) + +#define IsOfCopyMemory(x) ((x) & ofCopyMemory) + +#define IsOfReadOnly(x) ((x) & ofReadOnly) +#define IsOfTakeOwnership(x) ((x) & ofTakeOwnership) + +#define IsOfReserved(x) (((x) & ofReserved) != 0) + +// +// Type of file mapping returned by code:IMetaDataInfo::GetFileMapping. +// +typedef enum CorFileMapping +{ + fmFlat = 0, // Flat file mapping - file is mapped as data file (code:SEC_IMAGE flag was not + // passed to code:CreateFileMapping). + fmExecutableImage = 1, // Executable image file mapping - file is mapped for execution + // (either via code:LoadLibrary or code:CreateFileMapping with code:SEC_IMAGE flag). +} CorFileMapping; + + +typedef CorTypeAttr CorRegTypeAttr; + +// +// Opaque type for an enumeration handle. +// +typedef void *HCORENUM; + + +// Note that this must be kept in sync with System.AttributeTargets. +typedef enum CorAttributeTargets +{ + catAssembly = 0x0001, + catModule = 0x0002, + catClass = 0x0004, + catStruct = 0x0008, + catEnum = 0x0010, + catConstructor = 0x0020, + catMethod = 0x0040, + catProperty = 0x0080, + catField = 0x0100, + catEvent = 0x0200, + catInterface = 0x0400, + catParameter = 0x0800, + catDelegate = 0x1000, + catGenericParameter = 0x4000, + + catAll = catAssembly | catModule | catClass | catStruct | catEnum | catConstructor | + catMethod | catProperty | catField | catEvent | catInterface | catParameter | catDelegate | catGenericParameter, + catClassMembers = catClass | catStruct | catEnum | catConstructor | catMethod | catProperty | catField | catEvent | catDelegate | catInterface, + +} CorAttributeTargets; + +#ifndef MACROS_NOT_SUPPORTED +// +// Some well-known custom attributes +// +#ifndef IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS + #define IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS) +#endif + +#define INTEROP_DISPID_TYPE_W W("System.Runtime.InteropServices.DispIdAttribute") +#define INTEROP_DISPID_TYPE "System.Runtime.InteropServices.DispIdAttribute" +#define INTEROP_DISPID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4} + +#define INTEROP_INTERFACETYPE_TYPE_W W("System.Runtime.InteropServices.InterfaceTypeAttribute") +#define INTEROP_INTERFACETYPE_TYPE "System.Runtime.InteropServices.InterfaceTypeAttribute" +#define INTEROP_INTERFACETYPE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_CLASSINTERFACE_TYPE_W W("System.Runtime.InteropServices.ClassInterfaceAttribute") +#define INTEROP_CLASSINTERFACE_TYPE "System.Runtime.InteropServices.ClassInterfaceAttribute" +#define INTEROP_CLASSINTERFACE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMVISIBLE_TYPE_W W("System.Runtime.InteropServices.ComVisibleAttribute") +#define INTEROP_COMVISIBLE_TYPE "System.Runtime.InteropServices.ComVisibleAttribute" +#define INTEROP_COMVISIBLE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_COMREGISTERFUNCTION_TYPE_W W("System.Runtime.InteropServices.ComRegisterFunctionAttribute") +#define INTEROP_COMREGISTERFUNCTION_TYPE "System.Runtime.InteropServices.ComRegisterFunctionAttribute" +#define INTEROP_COMREGISTERFUNCTION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_COMUNREGISTERFUNCTION_TYPE_W W("System.Runtime.InteropServices.ComUnregisterFunctionAttribute") +#define INTEROP_COMUNREGISTERFUNCTION_TYPE "System.Runtime.InteropServices.ComUnregisterFunctionAttribute" +#define INTEROP_COMUNREGISTERFUNCTION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_IMPORTEDFROMTYPELIB_TYPE_W W("System.Runtime.InteropServices.ImportedFromTypeLibAttribute") +#define INTEROP_IMPORTEDFROMTYPELIB_TYPE "System.Runtime.InteropServices.ImportedFromTypeLibAttribute" +#define INTEROP_IMPORTEDFROMTYPELIB_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_PRIMARYINTEROPASSEMBLY_TYPE_W W("System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute") +#define INTEROP_PRIMARYINTEROPASSEMBLY_TYPE "System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute" +#define INTEROP_PRIMARYINTEROPASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4, ELEMENT_TYPE_I4} + +#define INTEROP_IDISPATCHIMPL_TYPE_W W("System.Runtime.InteropServices.IDispatchImplAttribute") +#define INTEROP_IDISPATCHIMPL_TYPE "System.Runtime.InteropServices.IDispatchImplAttribute" +#define INTEROP_IDISPATCHIMPL_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMSOURCEINTERFACES_TYPE_W W("System.Runtime.InteropServices.ComSourceInterfacesAttribute") +#define INTEROP_COMSOURCEINTERFACES_TYPE "System.Runtime.InteropServices.ComSourceInterfacesAttribute" +#define INTEROP_COMSOURCEINTERFACES_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_COMDEFAULTINTERFACE_TYPE_W W("System.Runtime.InteropServices.ComDefaultInterfaceAttribute") +#define INTEROP_COMDEFAULTINTERFACE_TYPE "System.Runtime.InteropServices.ComDefaultInterfaceAttribute" + +#define INTEROP_COMCONVERSIONLOSS_TYPE_W W("System.Runtime.InteropServices.ComConversionLossAttribute") +#define INTEROP_COMCONVERSIONLOSS_TYPE "System.Runtime.InteropServices.ComConversionLossAttribute" +#define INTEROP_COMCONVERSIONLOSS_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_BESTFITMAPPING_TYPE_W W("System.Runtime.InteropServices.BestFitMappingAttribute") +#define INTEROP_BESTFITMAPPING_TYPE "System.Runtime.InteropServices.BestFitMappingAttribute" +#define INTEROP_BESTFITMAPPING_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_TYPELIBTYPE_TYPE_W W("System.Runtime.InteropServices.TypeLibTypeAttribute") +#define INTEROP_TYPELIBTYPE_TYPE "System.Runtime.InteropServices.TypeLibTypeAttribute" +#define INTEROP_TYPELIBTYPE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_TYPELIBFUNC_TYPE_W W("System.Runtime.InteropServices.TypeLibFuncAttribute") +#define INTEROP_TYPELIBFUNC_TYPE "System.Runtime.InteropServices.TypeLibFuncAttribute" +#define INTEROP_TYPELIBFUNC_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_TYPELIBVAR_TYPE_W W("System.Runtime.InteropServices.TypeLibVarAttribute") +#define INTEROP_TYPELIBVAR_TYPE "System.Runtime.InteropServices.TypeLibVarAttribute" +#define INTEROP_TYPELIBVAR_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_MARSHALAS_TYPE_W W("System.Runtime.InteropServices.MarshalAsAttribute") +#define INTEROP_MARSHALAS_TYPE "System.Runtime.InteropServices.MarshalAsAttribute" +#define INTEROP_MARSHALAS_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} + +#define INTEROP_COMIMPORT_TYPE_W W("System.Runtime.InteropServices.ComImportAttribute") +#define INTEROP_COMIMPORT_TYPE "System.Runtime.InteropServices.ComImportAttribute" +#define INTEROP_COMIMPORT_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_GUID_TYPE_W W("System.Runtime.InteropServices.GuidAttribute") +#define INTEROP_GUID_TYPE "System.Runtime.InteropServices.GuidAttribute" +#define INTEROP_GUID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_DEFAULTMEMBER_TYPE_W W("System.Reflection.DefaultMemberAttribute") +#define INTEROP_DEFAULTMEMBER_TYPE "System.Reflection.DefaultMemberAttribute" +#define INTEROP_DEFAULTMEMBER_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_COMEMULATE_TYPE_W W("System.Runtime.InteropServices.ComEmulateAttribute") +#define INTEROP_COMEMULATE_TYPE "System.Runtime.InteropServices.ComEmulateAttribute" +#define INTEROP_COMEMULATE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_PRESERVESIG_TYPE_W W("System.Runtime.InteropServices.PreserveSigAttribure") +#define INTEROP_PRESERVESIG_TYPE "System.Runtime.InteropServices.PreserveSigAttribure" +#define INTEROP_PRESERVESIG_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_IN_TYPE_W W("System.Runtime.InteropServices.InAttribute") +#define INTEROP_IN_TYPE "System.Runtime.InteropServices.InAttribute" +#define INTEROP_IN_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_OUT_TYPE_W W("System.Runtime.InteropServices.OutAttribute") +#define INTEROP_OUT_TYPE "System.Runtime.InteropServices.OutAttribute" +#define INTEROP_OUT_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_COMALIASNAME_TYPE_W W("System.Runtime.InteropServices.ComAliasNameAttribute") +#define INTEROP_COMALIASNAME_TYPE "System.Runtime.InteropServices.ComAliasNameAttribute" +#define INTEROP_COMALIASNAME_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define INTEROP_PARAMARRAY_TYPE_W W("System.ParamArrayAttribute") +#define INTEROP_PARAMARRAY_TYPE "System.ParamArrayAttribute" +#define INTEROP_PARAMARRAY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_LCIDCONVERSION_TYPE_W W("System.Runtime.InteropServices.LCIDConversionAttribute") +#define INTEROP_LCIDCONVERSION_TYPE "System.Runtime.InteropServices.LCIDConversionAttribute" +#define INTEROP_LCIDCONVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4} + +#define INTEROP_COMSUBSTITUTABLEINTERFACE_TYPE_W W("System.Runtime.InteropServices.ComSubstitutableInterfaceAttribute") +#define INTEROP_COMSUBSTITUTABLEINTERFACE_TYPE "System.Runtime.InteropServices.ComSubstitutableInterfaceAttribute" +#define INTEROP_COMSUBSTITUTABLEINTERFACE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_DECIMALVALUE_TYPE_W W("System.Runtime.CompilerServices.DecimalConstantAttribute") +#define INTEROP_DECIMALVALUE_TYPE "System.Runtime.CompilerServices.DecimalConstantAttribute" +#define INTEROP_DECIMALVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 5, ELEMENT_TYPE_VOID, ELEMENT_TYPE_U1, ELEMENT_TYPE_U1, ELEMENT_TYPE_U4, ELEMENT_TYPE_U4, ELEMENT_TYPE_U4} + +#define INTEROP_DATETIMEVALUE_TYPE_W W("System.Runtime.CompilerServices.DateTimeConstantAttribute") +#define INTEROP_DATETIMEVALUE_TYPE "System.Runtime.CompilerServices.DateTimeConstantAttribute" +#define INTEROP_DATETIMEVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I8} + +#define INTEROP_IUNKNOWNVALUE_TYPE_W W("System.Runtime.CompilerServices.IUnknownConstantAttribute") +#define INTEROP_IUNKNOWNVALUE_TYPE "System.Runtime.CompilerServices.IUnknownConstantAttribute" +#define INTEROP_IUNKNOWNVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_IDISPATCHVALUE_TYPE_W W("System.Runtime.CompilerServices.IDispatchConstantAttribute") +#define INTEROP_IDISPATCHVALUE_TYPE "System.Runtime.CompilerServices.IDispatchConstantAttribute" +#define INTEROP_IDISPATCHVALUE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_AUTOPROXY_TYPE_W W("System.Runtime.InteropServices.AutomationProxyAttribute") +#define INTEROP_AUTOPROXY_TYPE "System.Runtime.InteropServices.AutomationProxyAttribute" +#define INTEROP_AUTOPROXY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_BOOLEAN} + +#define INTEROP_TYPELIBIMPORTCLASS_TYPE_W W("System.Runtime.InteropServices.TypeLibImportClassAttribute") +#define INTEROP_TYPELIBIMPORTCLASS_TYPE "System.Runtime.InteropServices.TypeLibImportClassAttribute" + + +#define INTEROP_TYPELIBVERSION_TYPE_W W("System.Runtime.InteropServices.TypeLibVersionAttribute") +#define INTEROP_TYPELIBVERSION_TYPE "System.Runtime.InteropServices.TypeLibVersionAttribute" +#define INTEROP_TYPELIBVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2} + +#define INTEROP_COMCOMPATIBLEVERSION_TYPE_W W("System.Runtime.InteropServices.ComCompatibleVersionAttribute") +#define INTEROP_COMCOMPATIBLEVERSION_TYPE "System.Runtime.InteropServices.ComCompatibleVersionAttribute" +#define INTEROP_COMCOMPATIBLEVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 4, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2} + +#define INTEROP_COMEVENTINTERFACE_TYPE_W W("System.Runtime.InteropServices.ComEventInterfaceAttribute") +#define INTEROP_COMEVENTINTERFACE_TYPE "System.Runtime.InteropServices.ComEventInterfaceAttribute" + +#define INTEROP_COCLASS_TYPE_W W("System.Runtime.InteropServices.CoClassAttribute") +#define INTEROP_COCLASS_TYPE "System.Runtime.InteropServices.CoClassAttribute" + +#define INTEROP_SERIALIZABLE_TYPE_W W("System.SerializableAttribute") +#define INTEROP_SERIALIZABLE_TYPE "System.SerializableAttribute" +#define INTEROP_SERIALIZABLE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_TYPE_W W("System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute") +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_TYPE "System.Runtime.InteropServices.SetWin32ContextInIDispatchAttribute" +#define INTEROP_SETWIN32CONTEXTINIDISPATCHATTRIBUTE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define FORWARD_INTEROP_STUB_METHOD_TYPE_W W("System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute") +#define FORWARD_INTEROP_STUB_METHOD_TYPE "System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute" + +#define FRIEND_ASSEMBLY_TYPE_W W("System.Runtime.CompilerServices.InternalsVisibleToAttribute") +#define FRIEND_ASSEMBLY_TYPE "System.Runtime.CompilerServices.InternalsVisibleToAttribute" +#define FRIEND_ASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING, ELEMENT_TYPE_BOOLEAN} + +#define SUBJECT_ASSEMBLY_TYPE_W W("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute") +#define SUBJECT_ASSEMBLY_TYPE "System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute" +#define SUBJECT_ASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} + +#define DISABLED_PRIVATE_REFLECTION_TYPE_W W("System.Runtime.CompilerServices.DisablePrivateReflectionAttribute") +#define DISABLED_PRIVATE_REFLECTION_TYPE "System.Runtime.CompilerServices.DisablePrivateReflectionAttribute" +#define DISABLED_PRIVATE_REFLECTION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define DEFAULTDOMAIN_STA_TYPE_W W("System.STAThreadAttribute") +#define DEFAULTDOMAIN_STA_TYPE "System.STAThreadAttribute" +#define DEFAULTDOMAIN_STA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define DEFAULTDOMAIN_MTA_TYPE_W W("System.MTAThreadAttribute") +#define DEFAULTDOMAIN_MTA_TYPE "System.MTAThreadAttribute" +#define DEFAULTDOMAIN_MTA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} + +#define NONVERSIONABLE_TYPE_W W("System.Runtime.Versioning.NonVersionableAttribute") +#define NONVERSIONABLE_TYPE "System.Runtime.Versioning.NonVersionableAttribute" + +// Keep in sync with CompilationRelaxations.cs +typedef enum CompilationRelaxationsEnum +{ + CompilationRelaxations_NoStringInterning = 0x0008, + +} CompilationRelaxationEnum; + +#define COMPILATIONRELAXATIONS_TYPE_W W("System.Runtime.CompilerServices.CompilationRelaxationsAttribute") +#define COMPILATIONRELAXATIONS_TYPE "System.Runtime.CompilerServices.CompilationRelaxationsAttribute" + + +// Keep in sync with RuntimeCompatibilityAttribute.cs +#define RUNTIMECOMPATIBILITY_TYPE_W W("System.Runtime.CompilerServices.RuntimeCompatibilityAttribute") +#define RUNTIMECOMPATIBILITY_TYPE "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" + + +// Keep in sync with AssemblySettingAttributes.cs + +typedef enum NGenHintEnum +{ + NGenDefault = 0x0000, // No preference specified + + NGenEager = 0x0001, // NGen at install time + NGenLazy = 0x0002, // NGen after install time + NGenNever = 0x0003 // Assembly should not be ngened +} NGenHintEnum; + +typedef enum LoadHintEnum +{ + LoadDefault = 0x0000, // No preference specified + + LoadAlways = 0x0001, // Dependency is always loaded + LoadSometimes = 0x0002, // Dependency is sometimes loaded + LoadNever = 0x0003 // Dependency is never loaded +} LoadHintEnum; + +#define DEFAULTDEPENDENCY_TYPE_W W("System.Runtime.CompilerServices.DefaultDependencyAttribute") +#define DEFAULTDEPENDENCY_TYPE "System.Runtime.CompilerServices.DefaultDependencyAttribute" + +#define DEPENDENCY_TYPE_W W("System.Runtime.CompilerServices.DependencyAttribute") +#define DEPENDENCY_TYPE "System.Runtime.CompilerServices.DependencyAttribute" + +#define TARGET_FRAMEWORK_TYPE_W W("System.Runtime.Versioning.TargetFrameworkAttribute") +#define TARGET_FRAMEWORK_TYPE "System.Runtime.Versioning.TargetFrameworkAttribute" + +#define ASSEMBLY_METADATA_TYPE_W W("System.Reflection.AssemblyMetadataAttribute") +#define ASSEMBLY_METADATA_TYPE "System.Reflection.AssemblyMetadataAttribute" + + +#define CMOD_CALLCONV_NAMESPACE_OLD "System.Runtime.InteropServices" +#define CMOD_CALLCONV_NAMESPACE "System.Runtime.CompilerServices" +#define CMOD_CALLCONV_NAME_CDECL "CallConvCdecl" +#define CMOD_CALLCONV_NAME_STDCALL "CallConvStdcall" +#define CMOD_CALLCONV_NAME_THISCALL "CallConvThiscall" +#define CMOD_CALLCONV_NAME_FASTCALL "CallConvFastcall" + +#endif // MACROS_NOT_SUPPORTED + +// +// GetSaveSize accuracy +// +#ifndef _CORSAVESIZE_DEFINED_ +#define _CORSAVESIZE_DEFINED_ +typedef enum CorSaveSize +{ + cssAccurate = 0x0000, // Find exact save size, accurate but slower. + cssQuick = 0x0001, // Estimate save size, may pad estimate, but faster. + cssDiscardTransientCAs = 0x0002, // remove all of the CAs of discardable types +} CorSaveSize; +#endif + +#define COR_IS_METHOD_MANAGED_IL(flags) ((flags & 0xf) == (miIL | miManaged)) +#define COR_IS_METHOD_MANAGED_OPTIL(flags) ((flags & 0xf) == (miOPTIL | miManaged)) +#define COR_IS_METHOD_MANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miManaged)) +#define COR_IS_METHOD_UNMANAGED_NATIVE(flags) ((flags & 0xf) == (miNative | miUnmanaged)) + +// +// Enum used with NATIVE_TYPE_ARRAY. +// +typedef enum NativeTypeArrayFlags +{ + ntaSizeParamIndexSpecified = 0x0001, + ntaReserved = 0xfffe // All the reserved bits. +} NativeTypeArrayFlags; + +// +// Opaque types for security properties and values. +// +typedef void * PSECURITY_PROPS ; +typedef void * PSECURITY_VALUE ; +typedef void ** PPSECURITY_PROPS ; +typedef void ** PPSECURITY_VALUE ; + +//------------------------------------- +//--- Security data structures +//------------------------------------- + +// Descriptor for a single security custom attribute. +typedef struct COR_SECATTR { + mdMemberRef tkCtor; // Ref to constructor of security attribute. + const void *pCustomAttribute; // Blob describing ctor args and field/property values. + ULONG cbCustomAttribute; // Length of the above blob. +} COR_SECATTR; + +#endif // __CORHDR_H__ + diff --git a/lib/coreclr/src/inc/corhlpr.cpp b/lib/coreclr/src/inc/corhlpr.cpp new file mode 100644 index 0000000000..ba803a5616 --- /dev/null +++ b/lib/coreclr/src/inc/corhlpr.cpp @@ -0,0 +1,307 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/**************************************************************************** + ** ** + ** Corhlpr.h - signature helpers. ** + ** ** + ****************************************************************************/ +#ifndef SOS_INCLUDE + +#ifdef _BLD_CLR +#include "utilcode.h" +#endif +#include "corhlpr.h" +#include + +#endif // !SOS_INCLUDE + + +//***************************************************************************** +// +//***** File format helper classes +// +//***************************************************************************** + +extern "C" { + +/***************************************************************************/ +/* Note that this construtor does not set the LocalSig, but has the + advantage that it does not have any dependancy on EE structures. + inside the EE use the FunctionDesc constructor */ + +void __stdcall DecoderInit(void *pThis, COR_ILMETHOD *header) +{ + COR_ILMETHOD_DECODER *decoder = (COR_ILMETHOD_DECODER *)pThis; + + memset(decoder, 0, sizeof(COR_ILMETHOD_DECODER)); + if (header->Tiny.IsTiny()) + { + decoder->SetMaxStack(header->Tiny.GetMaxStack()); + decoder->Code = header->Tiny.GetCode(); + decoder->SetCodeSize(header->Tiny.GetCodeSize()); + decoder->SetFlags(CorILMethod_TinyFormat); + return; + } + if (header->Fat.IsFat()) + { +#ifdef _WIN64 + if((((size_t) header) & 3) == 0) // header is aligned +#else + _ASSERTE((((size_t) header) & 3) == 0); // header is aligned +#endif + { + *((COR_ILMETHOD_FAT *)decoder) = header->Fat; + decoder->Code = header->Fat.GetCode(); + if (header->Fat.GetSize() >= (sizeof(COR_ILMETHOD_FAT) / 4)) // Size if valid + { + decoder->Sect = header->Fat.GetSect(); + if ((decoder->Sect != NULL) && (decoder->Sect->Kind() == CorILMethod_Sect_EHTable)) + { + decoder->EH = (COR_ILMETHOD_SECT_EH *)decoder->Sect; + decoder->Sect = decoder->Sect->Next(); + } + } + } + return; + } +} // DecoderInit + +// Calculate the total method size. First get address of end of code. If there are no sections, then +// the end of code addr marks end of COR_ILMETHOD. Otherwise find addr of end of last section and use it +// to mark end of COR_ILMETHOD. Assumes that the code is directly followed +// by each section in the on-disk format +int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header) +{ + COR_ILMETHOD_DECODER* decoder = (COR_ILMETHOD_DECODER*)pThis; + + if (decoder->Code == NULL) + return 0; + + BYTE *lastAddr = (BYTE*)decoder->Code + decoder->GetCodeSize(); // addr of end of code + const COR_ILMETHOD_SECT *sect = decoder->EH; + if (sect != 0 && sect->Next() == 0) + { + lastAddr = (BYTE *)sect + sect->DataSize(); + } + else + { + const COR_ILMETHOD_SECT *nextSect; + for (sect = decoder->Sect; sect; sect = nextSect) + { + nextSect = sect->Next(); + if (nextSect == 0) + { + // sect points to the last section, so set lastAddr + lastAddr = (BYTE *)sect + sect->DataSize(); + break; + } + } + } + return (int)(lastAddr - (BYTE*)header); +} + +/*********************************************************************/ +/* APIs for emitting sections etc */ + +unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL moreSections) +{ + if (header->GetMaxStack() <= 8 && (header->GetFlags() & ~CorILMethod_FormatMask) == 0 + && header->GetLocalVarSigTok() == 0 && header->GetCodeSize() < 64 && !moreSections) + return(sizeof(COR_ILMETHOD_TINY)); + + return(sizeof(COR_ILMETHOD_FAT)); +} + +/*********************************************************************/ + // emit the header (bestFormat) return amount emitted +unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, + BOOL moreSections, BYTE* outBuff) +{ +#ifndef SOS_INCLUDE +#ifdef _DEBUG + BYTE* origBuff = outBuff; +#endif +#endif // !SOS_INCLUDE + if (size == 1) { + // Tiny format + *outBuff++ = (BYTE) (CorILMethod_TinyFormat | (header->GetCodeSize() << 2)); + } + else { + // Fat format + _ASSERTE((((size_t) outBuff) & 3) == 0); // header is dword aligned + COR_ILMETHOD_FAT* fatHeader = (COR_ILMETHOD_FAT*) outBuff; + outBuff += sizeof(COR_ILMETHOD_FAT); + *fatHeader = *header; + fatHeader->SetFlags(fatHeader->GetFlags() | CorILMethod_FatFormat); + _ASSERTE((fatHeader->GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); + if (moreSections) + fatHeader->SetFlags(fatHeader->GetFlags() | CorILMethod_MoreSects); + fatHeader->SetSize(sizeof(COR_ILMETHOD_FAT) / 4); + } +#ifndef SOS_INCLUDE + _ASSERTE(&origBuff[size] == outBuff); +#endif // !SOS_INCLUDE + return(size); +} + +/*********************************************************************/ +/* static */ +IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) +{ + if (((COR_ILMETHOD_SECT_EH *)pSectEH)->IsFat()) + return(&(((COR_ILMETHOD_SECT_EH *)pSectEH)->Fat.Clauses[idx])); + + COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)buff; + COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx]; + + // mask to remove sign extension - cast just wouldn't work + fatClause->SetFlags((CorExceptionFlag)(smallClause->GetFlags()&0x0000ffff)); + fatClause->SetClassToken(smallClause->GetClassToken()); + fatClause->SetTryOffset(smallClause->GetTryOffset()); + fatClause->SetTryLength(smallClause->GetTryLength()); + fatClause->SetHandlerLength(smallClause->GetHandlerLength()); + fatClause->SetHandlerOffset(smallClause->GetHandlerOffset()); + return(buff); +} +/*********************************************************************/ + // compute the size of the section (best format) + // codeSize is the size of the method + // deprecated +unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize) +{ + return((ehCount)? SectEH_SizeWorst(ehCount) : 0); +} + + // will return worse-case size and then Emit will return actual size +unsigned __stdcall SectEH_SizeWorst(unsigned ehCount) +{ + return((ehCount)? (COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)) : 0); +} + + // will return exact size which will match the size returned by Emit +unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) +{ + if (ehCount == 0) + return(0); + + unsigned smallSize = COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount); + if (smallSize > COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) + return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); + for (unsigned i = 0; i < ehCount; i++) { + COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; + if (fatClause->GetTryOffset() > 0xFFFF || + fatClause->GetTryLength() > 0xFF || + fatClause->GetHandlerOffset() > 0xFFFF || + fatClause->GetHandlerLength() > 0xFF) { + return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); + } + } + return smallSize; +} + +/*********************************************************************/ + + // emit the section (best format); +unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, + BOOL moreSections, BYTE* outBuff, + ULONG* ehTypeOffsets) +{ + if (size == 0) + return(0); + + _ASSERTE((((size_t) outBuff) & 3) == 0); // header is dword aligned + BYTE* origBuff = outBuff; + if (ehCount <= 0) + return 0; + + // Initialize the ehTypeOffsets array. + if (ehTypeOffsets) + { + for (unsigned int i = 0; i < ehCount; i++) + ehTypeOffsets[i] = (ULONG) -1; + } + + if (COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount) < COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) { + COR_ILMETHOD_SECT_EH_SMALL* EHSect = (COR_ILMETHOD_SECT_EH_SMALL*) outBuff; + unsigned i; + for (i = 0; i < ehCount; i++) { + COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; + if (fatClause->GetTryOffset() > 0xFFFF || + fatClause->GetTryLength() > 0xFF || + fatClause->GetHandlerOffset() > 0xFFFF || + fatClause->GetHandlerLength() > 0xFF) { + break; // fall through and generate as FAT + } + _ASSERTE((fatClause->GetFlags() & ~0xFFFF) == 0); + _ASSERTE((fatClause->GetTryOffset() & ~0xFFFF) == 0); + _ASSERTE((fatClause->GetTryLength() & ~0xFF) == 0); + _ASSERTE((fatClause->GetHandlerOffset() & ~0xFFFF) == 0); + _ASSERTE((fatClause->GetHandlerLength() & ~0xFF) == 0); + + COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; + smallClause->SetFlags((CorExceptionFlag) fatClause->GetFlags()); + smallClause->SetTryOffset(fatClause->GetTryOffset()); + smallClause->SetTryLength(fatClause->GetTryLength()); + smallClause->SetHandlerOffset(fatClause->GetHandlerOffset()); + smallClause->SetHandlerLength(fatClause->GetHandlerLength()); + smallClause->SetClassToken(fatClause->GetClassToken()); + } + if (i >= ehCount) { + // if actually got through all the clauses and they are small enough + EHSect->Kind = CorILMethod_Sect_EHTable; + if (moreSections) + EHSect->Kind |= CorILMethod_Sect_MoreSects; +#ifndef SOS_INCLUDE + EHSect->DataSize = EHSect->Size(ehCount); +#else + EHSect->DataSize = (BYTE) EHSect->Size(ehCount); +#endif // !SOS_INCLUDE + EHSect->Reserved = 0; + _ASSERTE(EHSect->DataSize == EHSect->Size(ehCount)); // make sure didn't overflow + outBuff = (BYTE*) &EHSect->Clauses[ehCount]; + // Set the offsets for the exception type tokens. + if (ehTypeOffsets) + { + for (i = 0; i < ehCount; i++) { + COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; + if (smallClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) + { + _ASSERTE(! IsNilToken(smallClause->GetClassToken())); + ehTypeOffsets[i] = (ULONG)((BYTE *)&smallClause->ClassToken - origBuff); + } + } + } + return(size); + } + } + // either total size too big or one of constituent elements too big (eg. offset or length) + COR_ILMETHOD_SECT_EH_FAT* EHSect = (COR_ILMETHOD_SECT_EH_FAT*) outBuff; + EHSect->SetKind(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat); + if (moreSections) + EHSect->SetKind(EHSect->GetKind() | CorILMethod_Sect_MoreSects); + + EHSect->SetDataSize(EHSect->Size(ehCount)); + memcpy(EHSect->Clauses, clauses, ehCount * sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); + outBuff = (BYTE*) &EHSect->Clauses[ehCount]; + _ASSERTE(&origBuff[size] == outBuff); + // Set the offsets for the exception type tokens. + if (ehTypeOffsets) + { + for (unsigned int i = 0; i < ehCount; i++) { + COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&EHSect->Clauses[i]; + if (fatClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) + { + _ASSERTE(! IsNilToken(fatClause->GetClassToken())); + ehTypeOffsets[i] = (ULONG)((BYTE *)&fatClause->ClassToken - origBuff); + } + } + } + return(size); +} + +} // extern "C" + + diff --git a/lib/coreclr/src/inc/corhlpr.h b/lib/coreclr/src/inc/corhlpr.h new file mode 100644 index 0000000000..5b263a5382 --- /dev/null +++ b/lib/coreclr/src/inc/corhlpr.h @@ -0,0 +1,698 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** Corhlpr.h - ** + ** ** + *****************************************************************************/ + + +#ifndef __CORHLPR_H__ +#define __CORHLPR_H__ + +#if defined(_MSC_VER) && defined(_X86_) && !defined(FPO_ON) +#pragma optimize("y", on) // Small critical routines, don't put in EBP frame +#define FPO_ON 1 +#define CORHLPR_TURNED_FPO_ON 1 +#endif + +#include "cor.h" +#include "corhdr.h" +#include "corerror.h" + +// This header is consumed both within the runtime and externally. In the former +// case we need to wrap memory allocations, in the latter there is no +// infrastructure to support this. Detect which way we're building and provide a +// very simple abstraction layer (handles allocating bytes only). +#ifdef _BLD_CLR +#include "new.hpp" + + +#define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes] +#define NEW_THROWS(_bytes) new BYTE[_bytes] +void DECLSPEC_NORETURN ThrowOutOfMemory(); +inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() +{ + ThrowOutOfMemory(); +} +#else +#define NEW_NOTHROW(_bytes) new BYTE[_bytes] +#define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes) +static inline void DECLSPEC_NORETURN __CorHlprThrowOOM() +{ + RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); +} +static inline BYTE *__CorHlprNewThrows(size_t bytes) +{ + BYTE *pbMemory = new BYTE[bytes]; + if (pbMemory == NULL) + __CorHlprThrowOOM(); + return pbMemory; +} +inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() +{ + __CorHlprThrowOOM(); +} +#endif + + +//***************************************************************************** +// There are a set of macros commonly used in the helpers which you will want +// to override to get richer behavior. The following defines what is needed +// if you chose not to do the extra work. +//***************************************************************************** +#ifndef IfFailGoto +#define IfFailGoto(EXPR, LABEL) \ +do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0) +#endif + +#ifndef IfFailGo +#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) +#endif + +#ifndef IfFailRet +#define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0) +#endif + +#ifndef IfNullRet +#define IfNullRet(EXPR) do { if ((EXPR) == NULL){ return (E_OUTOFMEMORY); } } while (0) +#endif + + +#ifndef _ASSERTE +#define _ASSERTE(expr) +#endif + +#ifndef COUNTOF +#define COUNTOF(a) (sizeof(a) / sizeof(*a)) +#endif + +#if !BIGENDIAN +#define VAL16(x) x +#define VAL32(x) x +#endif + + +//***************************************************************************** +// +//***** Macro to assist with cleaning up local static variables +// +//***************************************************************************** + +#define CHECK_LOCAL_STATIC_VAR(x) \ + x \ + +//***************************************************************************** +// +//***** Utility helpers +// +//***************************************************************************** + + +#define MAX_CLASSNAME_LENGTH 1024 + +//***************************************************************************** +// +//***** Signature helpers +// +//***************************************************************************** + +inline bool isCallConv(unsigned sigByte, CorCallingConvention conv) +{ + return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv); +} + +//***************************************************************************** +// +//***** File format helper classes +// +//***************************************************************************** + + + +//***************************************************************************** +typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL { + //Data follows + const BYTE* Data() const + { + return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL)); + } + + bool IsSmall() const + { + return (Kind & CorILMethod_Sect_FatFormat) == 0; + } + + bool More() const + { + return (Kind & CorILMethod_Sect_MoreSects) != 0; + } +} COR_ILMETHOD_SECT_SMALL; + + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ +typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT { + //Data follows + const BYTE* Data() const + { + return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT)); + } + + //Endian-safe wrappers + unsigned GetKind() const { + /* return Kind; */ + return *(BYTE*)this; + } + void SetKind(unsigned kind) { + /* Kind = kind; */ + *(BYTE*)this = (BYTE)kind; + } + + unsigned GetDataSize() const { + /* return DataSize; */ + BYTE* p = (BYTE*)this; + return ((unsigned)*(p+1)) | + (((unsigned)*(p+2)) << 8) | + (((unsigned)*(p+3)) << 16); + } + void SetDataSize(unsigned datasize) { + /* DataSize = dataSize; */ + BYTE* p = (BYTE*)this; + *(p+1) = (BYTE)(datasize); + *(p+2) = (BYTE)(datasize >> 8); + *(p+3) = (BYTE)(datasize >> 16); + } +} COR_ILMETHOD_SECT_FAT; + +typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_FAT : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT { + //Endian-safe wrappers + CorExceptionFlag GetFlags() const { + return (CorExceptionFlag)VAL32((unsigned)Flags); + } + void SetFlags(CorExceptionFlag flags) { + Flags = (CorExceptionFlag)VAL32((unsigned)flags); + } + + DWORD GetTryOffset() const { + return VAL32(TryOffset); + } + void SetTryOffset(DWORD Offset) { + TryOffset = VAL32(Offset); + } + + DWORD GetTryLength() const { + return VAL32(TryLength); + } + void SetTryLength(DWORD Length) { + TryLength = VAL32(Length); + } + + DWORD GetHandlerOffset() const { + return VAL32(HandlerOffset); + } + void SetHandlerOffset(DWORD Offset) { + HandlerOffset = VAL32(Offset); + } + + DWORD GetHandlerLength() const { + return VAL32(HandlerLength); + } + void SetHandlerLength(DWORD Length) { + HandlerLength = VAL32(Length); + } + + DWORD GetClassToken() const { + return VAL32(ClassToken); + } + void SetClassToken(DWORD tok) { + ClassToken = VAL32(tok); + } + + DWORD GetFilterOffset() const { + return VAL32(FilterOffset); + } + void SetFilterOffset(DWORD offset) { + FilterOffset = VAL32(offset); + } + +} COR_ILMETHOD_SECT_EH_CLAUSE_FAT; + +//***************************************************************************** +struct COR_ILMETHOD_SECT_EH_FAT : public COR_ILMETHOD_SECT_FAT { + static unsigned Size(unsigned ehCount) { + return (sizeof(COR_ILMETHOD_SECT_EH_FAT) + + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * (ehCount-1)); + } + + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size +}; + +typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_SMALL : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL { + //Endian-safe wrappers + CorExceptionFlag GetFlags() const { + return (CorExceptionFlag)VAL16((SHORT)Flags); + } + void SetFlags(CorExceptionFlag flags) { + Flags = (CorExceptionFlag)VAL16((SHORT)flags); + } + + DWORD GetTryOffset() const { + return VAL16(TryOffset); + } + void SetTryOffset(DWORD Offset) { + _ASSERTE((Offset & ~0xffff) == 0); + TryOffset = VAL16(Offset); + } + + DWORD GetTryLength() const { + return TryLength; + } + void SetTryLength(DWORD Length) { + _ASSERTE((Length & ~0xff) == 0); + TryLength = Length; + } + + DWORD GetHandlerOffset() const { + return VAL16(HandlerOffset); + } + void SetHandlerOffset(DWORD Offset) { + _ASSERTE((Offset & ~0xffff) == 0); + HandlerOffset = VAL16(Offset); + } + + DWORD GetHandlerLength() const { + return HandlerLength; + } + void SetHandlerLength(DWORD Length) { + _ASSERTE((Length & ~0xff) == 0); + HandlerLength = Length; + } + + DWORD GetClassToken() const { + return VAL32(ClassToken); + } + void SetClassToken(DWORD tok) { + ClassToken = VAL32(tok); + } + + DWORD GetFilterOffset() const { + return VAL32(FilterOffset); + } + void SetFilterOffset(DWORD offset) { + FilterOffset = VAL32(offset); + } +} COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; + +//***************************************************************************** +struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL { + static unsigned Size(unsigned ehCount) { + return (sizeof(COR_ILMETHOD_SECT_EH_SMALL) + + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL) * (ehCount-1)); + } + + WORD Reserved; // alignment padding + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size +}; + + +/************************************/ +/* NOTE this structure must be DWORD aligned!! */ +struct COR_ILMETHOD_SECT +{ + bool More() const + { + return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0); + } + + CorILMethodSect Kind() const + { + return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask)); + } + + const COR_ILMETHOD_SECT* Next() const + { + if (!More()) return(0); + return ((COR_ILMETHOD_SECT*)(((BYTE *)this) + DataSize()))->Align(); + } + + const BYTE* Data() const + { + if (IsFat()) return(AsFat()->Data()); + return(AsSmall()->Data()); + } + + unsigned DataSize() const + { + if (Kind() == CorILMethod_Sect_EHTable) + { + // VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX + // in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works + // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX + // (see VSWhidbey #99031 and related bugs for details). + + if (IsFat()) + return Fat.Size(Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); + else + return Small.Size(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)); + } + else + { + if (IsFat()) return(AsFat()->GetDataSize()); + return(AsSmall()->DataSize); + } + } + + friend struct COR_ILMETHOD; + friend struct tagCOR_ILMETHOD_FAT; + friend struct tagCOR_ILMETHOD_TINY; + bool IsFat() const + { + return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); + } + + const COR_ILMETHOD_SECT* Align() const + { + return((COR_ILMETHOD_SECT*) ((((UINT_PTR) this) + 3) & ~3)); + } + +protected: + const COR_ILMETHOD_SECT_FAT* AsFat() const + { + return((COR_ILMETHOD_SECT_FAT*) this); + } + + const COR_ILMETHOD_SECT_SMALL* AsSmall() const + { + return((COR_ILMETHOD_SECT_SMALL*) this); + } + +public: + // The body is either a COR_ILMETHOD_SECT_SMALL or COR_ILMETHOD_SECT_FAT + // (as indicated by the CorILMethod_Sect_FatFormat bit + union { + COR_ILMETHOD_SECT_EH_SMALL Small; + COR_ILMETHOD_SECT_EH_FAT Fat; + }; +}; + + +/***********************************/ +// exported functions (implementation in Format\Format.cpp: +extern "C" { +IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff); + // compute the size of the section (best format) + // codeSize is the size of the method + // deprecated +unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize); + + // will return worse-case size and then Emit will return actual size +unsigned __stdcall SectEH_SizeWorst(unsigned ehCount); + + // will return exact size which will match the size returned by Emit +unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses); + + // emit the section (best format); +unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, + BOOL moreSections, BYTE* outBuff, + ULONG* ehTypeOffsets = 0); +} // extern "C" + + +struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT +{ + unsigned EHCount() const + { + return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) : + (Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL))); + } + + // return one clause in its fat form. Use 'buff' if needed + const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const + { + return SectEH_EHClause((void *)this, idx, buff); + }; + // compute the size of the section (best format) + // codeSize is the size of the method + // deprecated + unsigned static Size(unsigned ehCount, unsigned codeSize) + { + return SectEH_SizeWithCode(ehCount, codeSize); + }; + + // will return worse-case size and then Emit will return actual size + unsigned static Size(unsigned ehCount) + { + return SectEH_SizeWorst(ehCount); + }; + + // will return exact size which will match the size returned by Emit + unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) + { + return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses); + }; + + // emit the section (best format); + unsigned static Emit(unsigned size, unsigned ehCount, + const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, + bool moreSections, BYTE* outBuff, + ULONG* ehTypeOffsets = 0) + { + return SectEH_Emit(size, ehCount, + (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses, + moreSections, outBuff, ehTypeOffsets); + }; +}; + + +/***************************************************************************/ +/* Used when the method is tiny (< 64 bytes), and there are no local vars */ +typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY +{ + bool IsTiny() const + { + return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); + } + + unsigned GetCodeSize() const + { + return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1)); + } + + unsigned GetMaxStack() const + { + return(8); + } + + BYTE* GetCode() const + { + return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); + } + + DWORD GetLocalVarSigTok() const + { + return(0); + } + + COR_ILMETHOD_SECT* GetSect() const + { + return(0); + } +} COR_ILMETHOD_TINY; + + +/************************************/ +// This strucuture is the 'fat' layout, where no compression is attempted. +// Note that this structure can be added on at the end, thus making it extensible +typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT +{ + //Endian-safe wrappers + unsigned GetSize() const { + /* return Size; */ + BYTE* p = (BYTE*)this; + return *(p+1) >> 4; + } + void SetSize(unsigned size) { + /* Size = size; */ + BYTE* p = (BYTE*)this; + *(p+1) = (BYTE)((*(p+1) & 0x0F) | (size << 4)); + } + + unsigned GetFlags() const { + /* return Flags; */ + BYTE* p = (BYTE*)this; + return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8); + } + void SetFlags(unsigned flags) { + /* flags = Flags; */ + BYTE* p = (BYTE*)this; + *p = (BYTE)flags; + *(p+1) = (BYTE)((*(p+1) & 0xF0) | ((flags >> 8) & 0x0F)); + } + + bool IsFat() const { + /* return((IMAGE_COR_ILMETHOD_FAT::GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); */ + return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat; + } + + unsigned GetMaxStack() const { + /* return MaxStack; */ + return VAL16(*(USHORT*)((BYTE*)this+2)); + } + void SetMaxStack(unsigned maxStack) { + /* MaxStack = maxStack; */ + *(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack); + } + + unsigned GetCodeSize() const + { + return VAL32(CodeSize); + } + + void SetCodeSize(DWORD Size) + { + CodeSize = VAL32(Size); + } + + mdToken GetLocalVarSigTok() const + { + return VAL32(LocalVarSigTok); + } + + void SetLocalVarSigTok(mdSignature tok) + { + LocalVarSigTok = VAL32(tok); + } + + BYTE* GetCode() const { + return(((BYTE*) this) + 4*GetSize()); + } + + bool More() const { + // return (GetFlags() & CorILMethod_MoreSects) != 0; + return (*(BYTE*)this & CorILMethod_MoreSects) != 0; + } + + const COR_ILMETHOD_SECT* GetSect() const { + if (!More()) return (0); + return(((COR_ILMETHOD_SECT*) (GetCode() + GetCodeSize()))->Align()); + } +} COR_ILMETHOD_FAT; + + +extern "C" { +/************************************/ +// exported functions (impl. Format\Format.cpp) +unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL MoreSections); + // emit the header (bestFormat) return amount emitted +unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, + BOOL moreSections, BYTE* outBuff); +} + +struct COR_ILMETHOD +{ + // a COR_ILMETHOD header should not be decoded by hand. Instead us + // COR_ILMETHOD_DECODER to decode it. + friend class COR_ILMETHOD_DECODER; + + // compute the size of the header (best format) + unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections) + { + return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections); + }; + // emit the header (bestFormat) return amount emitted + unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header, + bool moreSections, BYTE* outBuff) + { + return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff); + }; + +//private: + union + { + COR_ILMETHOD_TINY Tiny; + COR_ILMETHOD_FAT Fat; + }; + // Code follows the Header, then immedately after the code comes + // any sections (COR_ILMETHOD_SECT). +}; + +extern "C" { +/***************************************************************************/ +/* COR_ILMETHOD_DECODER is the only way functions internal to the EE should + fetch data from a COR_ILMETHOD. This way any dependancy on the file format + (and the multiple ways of encoding the header) is centralized to the + COR_ILMETHOD_DECODER constructor) */ + void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header); + int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header); +} // extern "C" + +class COR_ILMETHOD_DECODER : public COR_ILMETHOD_FAT +{ +public: + // This returns an uninitialized decoder, suitable for placement new but nothing + // else. Use with caution. + COR_ILMETHOD_DECODER() {} + + // Typically the ONLY way you should access COR_ILMETHOD is through + // this constructor so format changes are easier. + COR_ILMETHOD_DECODER(const COR_ILMETHOD* header) + { + DecoderInit(this,(COR_ILMETHOD*)header); + }; + + // The above variant of the constructor can not do a 'complete' job, because + // it can not look up the local variable signature meta-data token. + // This method should be used when you have access to the Meta data API + // If the construction fails, the 'Code' field is set to 0 + + enum DecoderStatus {SUCCESS, FORMAT_ERROR, VERIFICATION_ERROR}; + + // If we want the decoder to verify the that local signature is OK we + // will pass a non-NULL value for wbStatus + // + // When using LazyInit we want ask that the local signature be verified + // But if we fail verification we still need access to the 'Code' field + // Because we may be able to demand SkipVerification and thus it was OK + // to have had a verification error. + + COR_ILMETHOD_DECODER(COR_ILMETHOD* header, + void *pInternalImport, + DecoderStatus* wbStatus); + + unsigned EHCount() const + { + return (EH != 0) ? EH->EHCount() : 0; + } + + unsigned GetHeaderSize() const + { + return GetCodeSize() + ((EH != 0) ? EH->DataSize() : 0); + } + + // returns total size of method for use in copying + int GetOnDiskSize(const COR_ILMETHOD* header) + { + return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header); + } + + // Flags these are available because we inherit COR_ILMETHOD_FAT + // MaxStack + // CodeSize + const BYTE * Code; + PCCOR_SIGNATURE LocalVarSig; // pointer to signature blob, or 0 if none + DWORD cbLocalVarSig; // size of dignature blob, or 0 if none + const COR_ILMETHOD_SECT_EH * EH; // eh table if any 0 if none + const COR_ILMETHOD_SECT * Sect; // additional sections 0 if none +}; // class COR_ILMETHOD_DECODER + +#if defined(CORHLPR_TURNED_FPO_ON) +#pragma optimize("", on) // Go back to command line default optimizations +#undef CORHLPR_TURNED_FPO_ON +#undef FPO_ON +#endif + +#endif // __CORHLPR_H__ diff --git a/lib/coreclr/src/inc/corhlprpriv.cpp b/lib/coreclr/src/inc/corhlprpriv.cpp new file mode 100644 index 0000000000..47e0cb13d6 --- /dev/null +++ b/lib/coreclr/src/inc/corhlprpriv.cpp @@ -0,0 +1,313 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/**************************************************************************** + ** ** + ** Corhlprpriv.cpp - signature helpers. ** + ** ** + ****************************************************************************/ +#ifndef SOS_INCLUDE + +#ifdef _BLD_CLR +#include "utilcode.h" +#endif +#include "corhlprpriv.h" +#include + +/************************************************************************************* +* +* implementation of CQuickMemoryBase +* +*************************************************************************************/ + +template +HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) +{ +#ifdef _BLD_CLR +#ifdef _DEBUG +#ifndef DACCESS_COMPILE + // Exercise heap for OOM-fault injection purposes + // But we can't do this if current thread suspends EE + if (!IsSuspendEEThread ()) + { + BYTE *pTmp = NEW_NOTHROW(iItems); + if (!pTmp) + { + return E_OUTOFMEMORY; + } + delete [] pTmp; + } +#endif +#endif +#endif + BYTE *pbBuffNew; + if (iItems <= cbTotal) + { + iSize = iItems; + return NOERROR; + } + +#ifdef _BLD_CLR +#ifndef DACCESS_COMPILE + // not allowed to do allocation if current thread suspends EE + if (IsSuspendEEThread ()) + return E_OUTOFMEMORY; +#endif +#endif + pbBuffNew = NEW_NOTHROW(iItems + INCREMENT); + if (!pbBuffNew) + return E_OUTOFMEMORY; + if (pbBuff) + { + memcpy(pbBuffNew, pbBuff, cbTotal); + delete [] pbBuff; + } + else + { + _ASSERTE(cbTotal == SIZE); + memcpy(pbBuffNew, rgData, cbTotal); + } + cbTotal = iItems + INCREMENT; + iSize = iItems; + pbBuff = pbBuffNew; + return NOERROR; +} + + +/************************************************************************************* +* +* get number of bytes consumed by one argument/return type +* +*************************************************************************************/ +#define CHECK_REMAINDER if(cbTotal >= cbTotalMax){hr=E_FAIL; goto ErrExit;} +HRESULT _CountBytesOfOneArg( + PCCOR_SIGNATURE pbSig, + ULONG *pcbTotal) // Initially, *pcbTotal contains the remaining size of the sig blob +{ + ULONG cb; + ULONG cbTotal=0; + ULONG cbTotalMax; + CorElementType ulElementType; + ULONG ulData; + ULONG ulTemp; + int iData; + mdToken tk; + ULONG cArg; + ULONG callingconv; + ULONG cArgsIndex; + HRESULT hr = NOERROR; + + if(pcbTotal==NULL) return E_FAIL; + cbTotalMax = *pcbTotal; + + CHECK_REMAINDER; + cbTotal = CorSigUncompressElementType(pbSig, &ulElementType); + while (CorIsModifierElementType((CorElementType) ulElementType)) + { + CHECK_REMAINDER; + cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType); + } + switch (ulElementType) + { + case ELEMENT_TYPE_SZARRAY: + case 0x1e /* obsolete */: + // skip over base type + CHECK_REMAINDER; + cb = cbTotalMax - cbTotal; + IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); + cbTotal += cb; + break; + + case ELEMENT_TYPE_FNPTR: + CHECK_REMAINDER; + cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv); + + // remember number of bytes to represent the arg counts + CHECK_REMAINDER; + cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg); + + // how many bytes to represent the return type + CHECK_REMAINDER; + cb = cbTotalMax - cbTotal; + IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); + cbTotal += cb; + + // loop through argument + for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) + { + CHECK_REMAINDER; + cb = cbTotalMax - cbTotal; + IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); + cbTotal += cb; + } + + break; + + case ELEMENT_TYPE_ARRAY: + // syntax : ARRAY BaseType [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] + + // skip over base type + CHECK_REMAINDER; + cb = cbTotalMax - cbTotal; + IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); + cbTotal += cb; + + // Parse for the rank + CHECK_REMAINDER; + cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); + + // if rank == 0, we are done + if (ulData == 0) + break; + + // any size of dimension specified? + CHECK_REMAINDER; + cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); + while (ulData--) + { + CHECK_REMAINDER; + cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp); + } + + // any lower bound specified? + CHECK_REMAINDER; + cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); + + while (ulData--) + { + CHECK_REMAINDER; + cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData); + } + + break; + case ELEMENT_TYPE_VALUETYPE: + case ELEMENT_TYPE_CLASS: + case ELEMENT_TYPE_CMOD_REQD: + case ELEMENT_TYPE_CMOD_OPT: + // count the bytes for the token compression + CHECK_REMAINDER; + cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk); + if ( ulElementType == ELEMENT_TYPE_CMOD_REQD || + ulElementType == ELEMENT_TYPE_CMOD_OPT) + { + // skip over base type + CHECK_REMAINDER; + cb = cbTotalMax - cbTotal; + IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); + cbTotal += cb; + } + break; + default: + break; + } + + *pcbTotal = cbTotal; +ErrExit: + return hr; +} +#undef CHECK_REMAINDER + +//***************************************************************************** +// copy fixed part of VarArg signature to a buffer +//***************************************************************************** +HRESULT _GetFixedSigOfVarArg( // S_OK or error. + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of COM+ method signature + ULONG cbSigBlob, // [IN] size of signature + CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature + ULONG *pcbSigBlob) // [OUT] number of bytes written to the above output buffer +{ + HRESULT hr = NOERROR; + ULONG cbCalling; + ULONG cbTyArgsNumber = 0; // number of bytes to store the type arg count (generics only) + ULONG cbArgsNumber; // number of bytes to store the original arg count + ULONG cbArgsNumberTemp; // number of bytes to store the fixed arg count + ULONG cbTotal = 0; // total of number bytes for return type + all fixed arguments + ULONG cbCur = 0; // index through the pvSigBlob + ULONG cb; + ULONG cArg; + ULONG cTyArg; + ULONG callingconv; + ULONG cArgsIndex; + CorElementType ulElementType; + BYTE *pbSig; + + _ASSERTE (pvSigBlob && pcbSigBlob); + + // remember the number of bytes to represent the calling convention + cbCalling = CorSigUncompressData (pvSigBlob, &callingconv); + if (cbCalling == ((ULONG)(-1))) + { + return E_INVALIDARG; + } + _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG)); + cbCur += cbCalling; + + if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC) + { + cbTyArgsNumber = CorSigUncompressData(&pvSigBlob[cbCur], &cTyArg); + if (cbTyArgsNumber == ((ULONG)(-1))) + { + return E_INVALIDARG; + } + cbCur += cbTyArgsNumber; + } + + // remember number of bytes to represent the arg counts + cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg); + if (cbArgsNumber == ((ULONG)(-1))) + { + return E_INVALIDARG; + } + + cbCur += cbArgsNumber; + + // how many bytes to represent the return type + cb = cbSigBlob-cbCur; + IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); + cbCur += cb; + cbTotal += cb; + + // loop through argument until we found ELEMENT_TYPE_SENTINEL or run + // out of arguments + for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) + { + _ASSERTE(cbCur < cbSigBlob); + + // peak the outer most ELEMENT_TYPE_* + CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType); + if (ulElementType == ELEMENT_TYPE_SENTINEL) + break; + cb = cbSigBlob-cbCur; + IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); + cbTotal += cb; + cbCur += cb; + } + + cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg); + + // now cbCalling : the number of bytes needed to store the calling convention + // cbArgNumberTemp : number of bytes to store the fixed arg count + // cbTotal : the number of bytes to store the ret and fixed arguments + + *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal; + + // resize the buffer + IfFailGo( pqbSig->ReSizeNoThrow(*pcbSigBlob) ); + pbSig = (BYTE *)pqbSig->Ptr(); + + // copy over the calling convention + cb = CorSigCompressData(callingconv, pbSig); + + // copy over the fixed arg count + cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]); + + // copy over the fixed args + ret type + memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal); + +ErrExit: + return hr; +} + + +#endif // !SOS_INCLUDE diff --git a/lib/coreclr/src/inc/corhlprpriv.h b/lib/coreclr/src/inc/corhlprpriv.h new file mode 100644 index 0000000000..5eeec2098f --- /dev/null +++ b/lib/coreclr/src/inc/corhlprpriv.h @@ -0,0 +1,773 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** Corhlprpriv.h - ** + ** ** + *****************************************************************************/ + +#ifndef __CORHLPRPRIV_H__ +#define __CORHLPRPRIV_H__ + +#include "corhlpr.h" +#include "fstring.h" + +#if defined(_MSC_VER) && defined(_TARGET_X86_) +#pragma optimize("y", on) // If routines don't get inlined, don't pay the EBP frame penalty +#endif + +//***************************************************************************** +// +//***** Utility helpers +// +//***************************************************************************** + +#ifndef SOS_INCLUDE + +//***************************************************************************** +// +// **** CQuickBytes +// This helper class is useful for cases where 90% of the time you allocate 512 +// or less bytes for a data structure. This class contains a 512 byte buffer. +// Alloc() will return a pointer to this buffer if your allocation is small +// enough, otherwise it asks the heap for a larger buffer which is freed for +// you. No mutex locking is required for the small allocation case, making the +// code run faster, less heap fragmentation, etc... Each instance will allocate +// 520 bytes, so use accordinly. +// +//***************************************************************************** +namespace NSQuickBytesHelper +{ + template + struct _AllocBytes; + + template <> + struct _AllocBytes + { + static BYTE *Invoke(SIZE_T iItems) + { + return NEW_THROWS(iItems); + } + }; + + template <> + struct _AllocBytes + { + static BYTE *Invoke(SIZE_T iItems) + { + return NEW_NOTHROW(iItems); + } + }; +}; + +void DECLSPEC_NORETURN ThrowHR(HRESULT hr); + +template +class CQuickMemoryBase +{ +protected: + template + static ELEM_T Min(ELEM_T a, ELEM_T b) + { return a < b ? a : b; } + + template + static ELEM_T Max(ELEM_T a, ELEM_T b) + { return a < b ? b : a; } + + // bGrow - indicates that this is a resize and that the original data + // needs to be copied over. + // bThrow - indicates whether or not memory allocations will throw. + template + void *_Alloc(SIZE_T iItems) + { +#if defined(_BLD_CLR) && defined(_DEBUG) + { // Exercise heap for OOM-fault injection purposes + BYTE * pb = NSQuickBytesHelper::_AllocBytes::Invoke(iItems); + _ASSERTE(!bThrow || pb != NULL); // _AllocBytes would have thrown if bThrow == TRUE + if (pb == NULL) return NULL; // bThrow == FALSE and we failed to allocate memory + delete [] pb; // Success, delete allocated memory. + } +#endif + if (iItems <= cbTotal) + { // Fits within existing memory allocation + iSize = iItems; + } + else if (iItems <= SIZE) + { // Will fit in internal buffer. + if (pbBuff == NULL) + { // Any previous allocation is in the internal buffer and the new + // allocation fits in the internal buffer, so just update the size. + iSize = iItems; + cbTotal = SIZE; + } + else + { // There was a previous allocation, sitting in pbBuff + if (bGrow) + { // If growing, need to copy any existing data over. + memcpy(&rgData[0], pbBuff, Min(cbTotal, SIZE)); + } + + delete [] pbBuff; + pbBuff = NULL; + iSize = iItems; + cbTotal = SIZE; + } + } + else + { // Need to allocate a new buffer + SIZE_T cbTotalNew = iItems + (bGrow ? INCREMENT : 0); + BYTE * pbBuffNew = NSQuickBytesHelper::_AllocBytes::Invoke(cbTotalNew); + + if (!bThrow && pbBuffNew == NULL) + { // Allocation failed. Zero out structure. + if (pbBuff != NULL) + { // Delete old buffer + delete [] pbBuff; + } + pbBuff = NULL; + iSize = 0; + cbTotal = 0; + return NULL; + } + + if (bGrow && cbTotal > 0) + { // If growing, need to copy any existing data over. + memcpy(pbBuffNew, (BYTE *)Ptr(), Min(cbTotal, cbTotalNew)); + } + + if (pbBuff != NULL) + { // Delete old pre-existing buffer + delete [] pbBuff; + pbBuff = NULL; + } + + pbBuff = pbBuffNew; + cbTotal = cbTotalNew; + iSize = iItems; + } + + return Ptr(); + } + +public: + void Init() + { + pbBuff = 0; + iSize = 0; + cbTotal = SIZE; + } + + void Destroy() + { + if (pbBuff) + { + delete [] pbBuff; + pbBuff = 0; + } + } + + void *AllocThrows(SIZE_T iItems) + { + return _Alloc(iItems); + } + + void *AllocNoThrow(SIZE_T iItems) + { + return _Alloc(iItems); + } + + void ReSizeThrows(SIZE_T iItems) + { + _Alloc(iItems); + } + +#ifdef __GNUC__ + // This makes sure that we will not get an undefined symbol + // when building a release version of libcoreclr using LLVM/GCC. + __attribute__((used)) +#endif // __GNUC__ + HRESULT ReSizeNoThrow(SIZE_T iItems); + + void Shrink(SIZE_T iItems) + { + _ASSERTE(iItems <= cbTotal); + iSize = iItems; + } + + operator PVOID() + { + return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); + } + + void *Ptr() + { + return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); + } + + const void *Ptr() const + { + return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); + } + + SIZE_T Size() const + { + return (iSize); + } + + SIZE_T MaxSize() const + { + return (cbTotal); + } + + void Maximize() + { + iSize = cbTotal; + } + + + // Convert UTF8 string to UNICODE string, optimized for speed + HRESULT ConvertUtf8_UnicodeNoThrow(const char * utf8str) + { + bool allAscii; + DWORD length; + + HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); + + if (SUCCEEDED(hr)) + { + LPWSTR buffer = (LPWSTR) AllocNoThrow((length + 1) * sizeof(WCHAR)); + + if (buffer == NULL) + { + hr = E_OUTOFMEMORY; + } + else + { + hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); + } + } + + return hr; + } + + // Convert UTF8 string to UNICODE string, optimized for speed + void ConvertUtf8_Unicode(const char * utf8str) + { + bool allAscii; + DWORD length; + + HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); + + if (SUCCEEDED(hr)) + { + LPWSTR buffer = (LPWSTR) AllocThrows((length + 1) * sizeof(WCHAR)); + + hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); + } + + if (FAILED(hr)) + { + ThrowHR(hr); + } + } + + // Convert UNICODE string to UTF8 string, optimized for speed + void ConvertUnicode_Utf8(const WCHAR * pString) + { + bool allAscii; + DWORD length; + + HRESULT hr = FString::Unicode_Utf8_Length(pString, & allAscii, & length); + + if (SUCCEEDED(hr)) + { + LPSTR buffer = (LPSTR) AllocThrows((length + 1) * sizeof(char)); + + hr = FString::Unicode_Utf8(pString, allAscii, buffer, length); + } + + if (FAILED(hr)) + { + ThrowHR(hr); + } + } + + // Copy single byte string and hold it + const char * SetStringNoThrow(const char * pStr, SIZE_T len) + { + LPSTR buffer = (LPSTR) AllocNoThrow(len + 1); + + if (buffer != NULL) + { + memcpy(buffer, pStr, len); + buffer[len] = 0; + } + + return buffer; + } + +#ifdef DACCESS_COMPILE + void + EnumMemoryRegions(CLRDataEnumMemoryFlags flags) + { + // Assume that 'this' is enumerated, either explicitly + // or because this class is embedded in another. + DacEnumMemoryRegion(dac_cast(pbBuff), iSize); + } +#endif // DACCESS_COMPILE + + BYTE *pbBuff; + SIZE_T iSize; // number of bytes used + SIZE_T cbTotal; // total bytes allocated in the buffer + // use UINT64 to enforce the alignment of the memory + UINT64 rgData[(SIZE+sizeof(UINT64)-1)/sizeof(UINT64)]; +}; + +// These should be multiples of 8 so that data can be naturally aligned. +#define CQUICKBYTES_BASE_SIZE 512 +#define CQUICKBYTES_INCREMENTAL_SIZE 128 + +class CQuickBytesBase : public CQuickMemoryBase +{ +}; + + +class CQuickBytes : public CQuickBytesBase +{ +public: + CQuickBytes() + { + Init(); + } + + ~CQuickBytes() + { + Destroy(); + } +}; + +/* to be used as static variable - no constructor/destructor, assumes zero + initialized memory */ +class CQuickBytesStatic : public CQuickBytesBase +{ +}; + +template +class CQuickBytesSpecifySizeBase : public CQuickMemoryBase +{ +}; + +template +class CQuickBytesSpecifySize : public CQuickBytesSpecifySizeBase +{ +public: + CQuickBytesSpecifySize() + { + this->Init(); + } + + ~CQuickBytesSpecifySize() + { + this->Destroy(); + } +}; + +/* to be used as static variable - no constructor/destructor, assumes zero + initialized memory */ +template +class CQuickBytesSpecifySizeStatic : public CQuickBytesSpecifySizeBase +{ +}; + +template class CQuickArrayBase : public CQuickBytesBase +{ +public: + T* AllocThrows(SIZE_T iItems) + { + CheckOverflowThrows(iItems); + return (T*)CQuickBytesBase::AllocThrows(iItems * sizeof(T)); + } + + void ReSizeThrows(SIZE_T iItems) + { + CheckOverflowThrows(iItems); + CQuickBytesBase::ReSizeThrows(iItems * sizeof(T)); + } + + T* AllocNoThrow(SIZE_T iItems) + { + if (!CheckOverflowNoThrow(iItems)) + { + return NULL; + } + return (T*)CQuickBytesBase::AllocNoThrow(iItems * sizeof(T)); + } + + HRESULT ReSizeNoThrow(SIZE_T iItems) + { + if (!CheckOverflowNoThrow(iItems)) + { + return E_OUTOFMEMORY; + } + return CQuickBytesBase::ReSizeNoThrow(iItems * sizeof(T)); + } + + void Shrink(SIZE_T iItems) + { + CQuickBytesBase::Shrink(iItems * sizeof(T)); + } + + T* Ptr() + { + return (T*) CQuickBytesBase::Ptr(); + } + + const T* Ptr() const + { + return (T*) CQuickBytesBase::Ptr(); + } + + SIZE_T Size() const + { + return CQuickBytesBase::Size() / sizeof(T); + } + + SIZE_T MaxSize() const + { + return CQuickBytesBase::cbTotal / sizeof(T); + } + + T& operator[] (SIZE_T ix) + { + _ASSERTE(ix < Size()); + return *(Ptr() + ix); + } + + const T& operator[] (SIZE_T ix) const + { + _ASSERTE(ix < Size()); + return *(Ptr() + ix); + } + +private: + inline + BOOL CheckOverflowNoThrow(SIZE_T iItems) + { + SIZE_T totalSize = iItems * sizeof(T); + + if (totalSize / sizeof(T) != iItems) + { + return FALSE; + } + + return TRUE; + } + + inline + void CheckOverflowThrows(SIZE_T iItems) + { + if (!CheckOverflowNoThrow(iItems)) + { + THROW_OUT_OF_MEMORY(); + } + } +}; + +template class CQuickArray : public CQuickArrayBase +{ +public: + CQuickArray() + { + this->Init(); + } + + ~CQuickArray() + { + this->Destroy(); + } +}; + +// This is actually more of a stack with array access. Essentially, you can +// only add elements through Push and remove them through Pop, but you can +// access and modify any random element with the index operator. You cannot +// access elements that have not been added. + +template +class CQuickArrayList : protected CQuickArray +{ +private: + SIZE_T m_curSize; + +public: + // Make these specific functions public. + using CQuickArray::AllocThrows; + using CQuickArray::ReSizeThrows; + using CQuickArray::AllocNoThrow; + using CQuickArray::ReSizeNoThrow; + using CQuickArray::MaxSize; + + CQuickArrayList() + : m_curSize(0) + { + this->Init(); + } + + ~CQuickArrayList() + { + this->Destroy(); + } + + // Can only access values that have been pushed. + T& operator[] (SIZE_T ix) + { + _ASSERTE(ix < m_curSize); + return CQuickArray::operator[](ix); + } + + // Can only access values that have been pushed. + const T& operator[] (SIZE_T ix) const + { + _ASSERTE(ix < m_curSize); + return CQuickArray::operator[](ix); + } + + // THROWS: Resizes if necessary. + void Push(const T & value) + { + // Resize if necessary - thows. + if (m_curSize + 1 >= CQuickArray::Size()) + ReSizeThrows((m_curSize + 1) * 2); + + // Append element to end of array. + _ASSERTE(m_curSize + 1 < CQuickArray::Size()); + SIZE_T ix = m_curSize++; + (*this)[ix] = value; + } + + T Pop() + { + _ASSERTE(m_curSize > 0); + T retval = (*this)[m_curSize - 1]; + INDEBUG(ZeroMemory(&(this->Ptr()[m_curSize - 1]), sizeof(T));) + --m_curSize; + return retval; + } + + SIZE_T Size() const + { + return m_curSize; + } + + void Shrink() + { + CQuickArray::Shrink(m_curSize); + } +}; + + +/* to be used as static variable - no constructor/destructor, assumes zero + initialized memory */ +template class CQuickArrayStatic : public CQuickArrayBase +{ +}; + +typedef CQuickArrayBase CQuickWSTRBase; +typedef CQuickArray CQuickWSTR; +typedef CQuickArrayStatic CQuickWSTRStatic; + +typedef CQuickArrayBase CQuickSTRBase; +typedef CQuickArray CQuickSTR; +typedef CQuickArrayStatic CQuickSTRStatic; + +class RidBitmap +{ +public: + HRESULT InsertToken(mdToken token) + { + HRESULT hr = S_OK; + mdToken rid = RidFromToken(token); + SIZE_T index = rid / 8; + BYTE bit = (1 << (rid % 8)); + + if (index >= buffer.Size()) + { + SIZE_T oldSize = buffer.Size(); + SIZE_T newSize = index+1+oldSize/8; + IfFailRet(buffer.ReSizeNoThrow(newSize)); + memset(&buffer[oldSize], 0, newSize-oldSize); + } + + buffer[index] |= bit; + return hr; + } + + bool IsTokenInBitmap(mdToken token) + { + mdToken rid = RidFromToken(token); + SIZE_T index = rid / 8; + BYTE bit = (1 << (rid % 8)); + + return ((index < buffer.Size()) && (buffer[index] & bit)); + } + + void Reset() + { + if (buffer.Size()) + { + memset(&buffer[0], 0, buffer.Size()); + } + } + +private: + CQuickArray buffer; +}; + +//***************************************************************************** +// +//***** Signature helpers +// +//***************************************************************************** + +HRESULT _CountBytesOfOneArg( + PCCOR_SIGNATURE pbSig, + ULONG *pcbTotal); + +HRESULT _GetFixedSigOfVarArg( // S_OK or error. + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of CLR signature + ULONG cbSigBlob, // [IN] size of signature + CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature + ULONG *pcbSigBlob); // [OUT] number of bytes written to the above output buffer + +#endif //!SOS_INCLUDE + +#if defined(_MSC_VER) && defined(_TARGET_X86_) +#pragma optimize("", on) // restore command line default optimizations +#endif + + +//--------------------------------------------------------------------------------------- +// +// Reads compressed integer from buffer pData, fills the result to *pnDataOut. Advances buffer pointer. +// Doesn't read behind the end of the buffer (the end starts at pDataEnd). +// +inline +__checkReturn +HRESULT +CorSigUncompressData_EndPtr( + PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer + PCCOR_SIGNATURE pDataEnd, // End of buffer + DWORD * pnDataOut) // [OUT] Compressed integer read from the buffer +{ + _ASSERTE(pData <= pDataEnd); + HRESULT hr = S_OK; + + INT_PTR cbDataSize = pDataEnd - pData; + if (cbDataSize > 4) + { // Compressed integer cannot be bigger than 4 bytes + cbDataSize = 4; + } + DWORD dwDataSize = (DWORD)cbDataSize; + + ULONG cbDataOutLength; + IfFailRet(CorSigUncompressData( + pData, + dwDataSize, + pnDataOut, + &cbDataOutLength)); + pData += cbDataOutLength; + + return hr; +} // CorSigUncompressData_EndPtr + +//--------------------------------------------------------------------------------------- +// +// Reads CorElementType (1 byte) from buffer pData, fills the result to *pTypeOut. Advances buffer pointer. +// Doesn't read behind the end of the buffer (the end starts at pDataEnd). +// +inline +__checkReturn +HRESULT +CorSigUncompressElementType_EndPtr( + PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer + PCCOR_SIGNATURE pDataEnd, // End of buffer + CorElementType * pTypeOut) // [OUT] ELEMENT_TYPE_* value read from the buffer +{ + _ASSERTE(pData <= pDataEnd); + // We don't expect pData > pDataEnd, but the runtime check doesn't cost much and it is more secure in + // case caller has a bug + if (pData >= pDataEnd) + { // No data + return META_E_BAD_SIGNATURE; + } + // Read 'type' as 1 byte + *pTypeOut = (CorElementType)*pData; + pData++; + + return S_OK; +} // CorSigUncompressElementType_EndPtr + +//--------------------------------------------------------------------------------------- +// +// Reads pointer (4/8 bytes) from buffer pData, fills the result to *ppvPointerOut. Advances buffer pointer. +// Doesn't read behind the end of the buffer (the end starts at pDataEnd). +// +inline +__checkReturn +HRESULT +CorSigUncompressPointer_EndPtr( + PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer + PCCOR_SIGNATURE pDataEnd, // End of buffer + void ** ppvPointerOut) // [OUT] Pointer value read from the buffer +{ + _ASSERTE(pData <= pDataEnd); + // We could just skip this check as pointers should be only in trusted (and therefore correct) + // signatures and we check for that on the caller side, but it won't hurt to have this check and it will + // make it easier to catch invalid signatures in trusted code (e.g. IL stubs, NGEN images, etc.) + if (pData + sizeof(void *) > pDataEnd) + { // Not enough data in the buffer + _ASSERTE(!"This signature is invalid. Note that caller should check that it is not comming from untrusted source!"); + return META_E_BAD_SIGNATURE; + } + *ppvPointerOut = *(void * UNALIGNED *)pData; + pData += sizeof(void *); + + return S_OK; +} // CorSigUncompressPointer_EndPtr + +//--------------------------------------------------------------------------------------- +// +// Reads compressed TypeDef/TypeRef/TypeSpec token, fills the result to *pnDataOut. Advances buffer pointer. +// Doesn't read behind the end of the buffer (the end starts at pDataEnd). +// +inline +__checkReturn +HRESULT +CorSigUncompressToken_EndPtr( + PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer + PCCOR_SIGNATURE pDataEnd, // End of buffer + mdToken * ptkTokenOut) // [OUT] Token read from the buffer +{ + _ASSERTE(pData <= pDataEnd); + HRESULT hr = S_OK; + + INT_PTR cbDataSize = pDataEnd - pData; + if (cbDataSize > 4) + { // Compressed token cannot be bigger than 4 bytes + cbDataSize = 4; + } + DWORD dwDataSize = (DWORD)cbDataSize; + + ULONG cbTokenOutLength; + IfFailRet(CorSigUncompressToken( + pData, + dwDataSize, + ptkTokenOut, + &cbTokenOutLength)); + pData += cbTokenOutLength; + + return hr; +} // CorSigUncompressToken_EndPtr + +#endif // __CORHLPRPRIV_H__ diff --git a/lib/coreclr/src/inc/corhost.h b/lib/coreclr/src/inc/corhost.h new file mode 100644 index 0000000000..09ea994b59 --- /dev/null +++ b/lib/coreclr/src/inc/corhost.h @@ -0,0 +1,278 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +//***************************************************************************** +// CorHost.h +// +// Class factories are used by the pluming in COM to activate new objects. +// This module contains the class factory code to instantiate the debugger +// objects described in . +// +//***************************************************************************** + +#ifndef __CorHost__h__ +#define __CorHost__h__ + + +#include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions +#ifdef CreateSemaphore +#undef CreateSemaphore +#endif + +#include "mscoree.h" + +#include "clrinternal.h" + +#include "holder.h" + +#include "clrprivhosting.h" + +#ifdef FEATURE_COMINTEROP +#include "activation.h" // WinRT activation. +#endif + +class DangerousNonHostedSpinLock; + +#define INVALID_STACK_BASE_MARKER_FOR_CHECK_STATE 2 + +class AppDomain; +class Assembly; + + +class CorRuntimeHostBase +{ +protected: + CorRuntimeHostBase() + :m_Started(FALSE), + m_cRef(0) + {LIMITED_METHOD_CONTRACT;} + + STDMETHODIMP_(ULONG) AddRef(void); + + // Starts the runtime. This is equivalent to CoInitializeCor() + STDMETHODIMP Start(); + + STDMETHODIMP MapFile( // Return code. + HANDLE hFile, // [in] Handle for file + HMODULE *hMapAddress // [out] HINSTANCE for mapped file + ); + + STDMETHODIMP LocksHeldByLogicalThread( // Return code. + DWORD *pCount // [out] Number of locks that the current thread holds. + ); + +protected: + BOOL m_Started; // Has START been called? + + LONG m_cRef; // Ref count. + + static ULONG m_Version; // Version of ICorRuntimeHost. + // Some functions are only available in ICLRRuntimeHost. + // Some functions are no-op in ICLRRuntimeHost. + + STDMETHODIMP UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone); + + STDMETHODIMP UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode); +public: + static ULONG GetHostVersion() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE (m_Version != 0); + return m_Version; + } + +}; + + +class ConnectionNameTable; +typedef DPTR(class ConnectionNameTable) PTR_ConnectionNameTable; + +class CrstStatic; + +// Defines the precedence (in increading oder) of the two symbol reading knobs +enum ESymbolReadingSetBy +{ + eSymbolReadingSetByDefault, + eSymbolReadingSetByConfig, // EEConfig - config file, env var, etc. + eSymbolReadingSetByHost, // Hosting API - highest precedence + eSymbolReadingSetBy_COUNT +}; + +class CorHost2 : + public CorRuntimeHostBase +#ifndef FEATURE_PAL + , public IPrivateManagedExceptionReporting /* This interface is for internal Watson testing only*/ +#endif // FEATURE_PAL + , public ICLRRuntimeHost4 +{ + friend struct _DacGlobals; + +public: + CorHost2(); + virtual ~CorHost2() {} + + // *** IUnknown methods *** + STDMETHODIMP QueryInterface(REFIID riid, void** ppv); + STDMETHODIMP_(ULONG) AddRef(void) + { + WRAPPER_NO_CONTRACT; + return CorRuntimeHostBase::AddRef(); + } + STDMETHODIMP_(ULONG) Release(void); + + + // *** ICorRuntimeHost methods *** + +#ifndef FEATURE_PAL + // defined in IPrivateManagedExceptionReporting interface for internal Watson testing only + STDMETHODIMP GetBucketParametersForCurrentException(BucketParameters *pParams); +#endif // FEATURE_PAL + + // Starts the runtime. This is equivalent to CoInitializeCor(). + STDMETHODIMP Start(); + STDMETHODIMP Stop(); + + STDMETHODIMP ExecuteInAppDomain(DWORD dwAppDomainId, + FExecuteInAppDomainCallback pCallback, + void * cookie); + + STDMETHODIMP LocksHeldByLogicalThread( // Return code. + DWORD *pCount // [out] Number of locks that the current thread holds. + ) + { + WRAPPER_NO_CONTRACT; + return CorRuntimeHostBase::LocksHeldByLogicalThread(pCount); + } + + // Class factory hook-up. + static HRESULT CreateObject(REFIID riid, void **ppUnk); + + STDMETHODIMP MapFile( // Return code. + HANDLE hFile, // [in] Handle for file + HMODULE *hMapAddress // [out] HINSTANCE for mapped file + ) + { + WRAPPER_NO_CONTRACT; + return CorRuntimeHostBase::MapFile(hFile,hMapAddress); + } + + STDMETHODIMP STDMETHODCALLTYPE SetHostControl( + IHostControl* pHostControl); + + STDMETHODIMP STDMETHODCALLTYPE GetCLRControl( + ICLRControl** pCLRControl); + + STDMETHODIMP UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone); + + STDMETHODIMP UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode); + + STDMETHODIMP GetCurrentAppDomainId(DWORD *pdwAppDomainId); + + STDMETHODIMP ExecuteApplication(LPCWSTR pwzAppFullName, + DWORD dwManifestPaths, + LPCWSTR *ppwzManifestPaths, + DWORD dwActivationData, + LPCWSTR *ppwzActivationData, + int *pReturnValue); + + STDMETHODIMP ExecuteInDefaultAppDomain(LPCWSTR pwzAssemblyPath, + LPCWSTR pwzTypeName, + LPCWSTR pwzMethodName, + LPCWSTR pwzArgument, + DWORD *pReturnValue); + + // *** ICLRRuntimeHost2 methods *** + STDMETHODIMP CreateAppDomainWithManager( + LPCWSTR wszFriendlyName, + DWORD dwSecurityFlags, + LPCWSTR wszAppDomainManagerAssemblyName, + LPCWSTR wszAppDomainManagerTypeName, + int nProperties, + LPCWSTR* pPropertyNames, + LPCWSTR* pPropertyValues, + DWORD* pAppDomainID); + + STDMETHODIMP CreateDelegate( + DWORD appDomainID, + LPCWSTR wszAssemblyName, + LPCWSTR wszClassName, + LPCWSTR wszMethodName, + INT_PTR* fnPtr); + + STDMETHODIMP Authenticate(ULONGLONG authKey); + + STDMETHODIMP RegisterMacEHPort(); + STDMETHODIMP SetStartupFlags(STARTUP_FLAGS flag); + STDMETHODIMP DllGetActivationFactory( + DWORD appDomainID, + LPCWSTR wszTypeName, + IActivationFactory ** factory); + + STDMETHODIMP ExecuteAssembly( + DWORD dwAppDomainId, + LPCWSTR pwzAssemblyPath, + int argc, + LPCWSTR* argv, + DWORD* pReturnValue); + + static STARTUP_FLAGS GetStartupFlags(); + + static BOOL HasStarted() + { + return m_RefCount != 0; + } + +private: + // This flag indicates if this instance was the first to load and start CoreCLR + BOOL m_fFirstToLoadCLR; + + // This flag will be used to ensure that a CoreCLR host can invoke Start/Stop in pairs only. + BOOL m_fStarted; + BOOL m_fAppDomainCreated; // this flag is used when an appdomain can only create a single appdomain + + // Helpers for both ICLRRuntimeHost2 and ICLRPrivRuntime + HRESULT _CreateAppDomain( + LPCWSTR wszFriendlyName, + DWORD dwFlags, + LPCWSTR wszAppDomainManagerAssemblyName, + LPCWSTR wszAppDomainManagerTypeName, + int nProperties, + LPCWSTR* pPropertyNames, + LPCWSTR* pPropertyValues, + DWORD* pAppDomainID); + + HRESULT _CreateDelegate( + DWORD appDomainID, + LPCWSTR wszAssemblyName, + LPCWSTR wszClassName, + LPCWSTR wszMethodName, + INT_PTR* fnPtr); + + // entrypoint helper to be wrapped in a filter to process unhandled exceptions + VOID ExecuteMainInner(Assembly* pRootAssembly); + + static LONG m_RefCount; + + SVAL_DECL(STARTUP_FLAGS, m_dwStartupFlags); +}; + +#ifdef FEATURE_COMINTEROP +extern "C" +HRESULT STDMETHODCALLTYPE DllGetActivationFactoryImpl( + LPCWSTR wszAssemblyName, + LPCWSTR wszTypeName, + LPCWSTR wszCodeBase, + IActivationFactory ** factory); + +#endif // defined(FEATURE_COMINTEROP) + +extern SIZE_T Host_SegmentSize; +extern SIZE_T Host_MaxGen0Size; +extern BOOL Host_fSegmentSizeSet; +extern BOOL Host_fMaxGen0SizeSet; + +#define PARTIAL_TRUST_VISIBLE_ASSEMBLIES_PROPERTY W("PARTIAL_TRUST_VISIBLE_ASSEMBLIES") +#endif // __CorHost__h__ diff --git a/lib/coreclr/src/inc/corimage.h b/lib/coreclr/src/inc/corimage.h new file mode 100644 index 0000000000..554eb2042a --- /dev/null +++ b/lib/coreclr/src/inc/corimage.h @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +// + +/*============================================================ +** +** CorImage.h +** +** IMAGEHLP routines so we can avoid early binding to that DLL. +** +===========================================================*/ + +#ifndef _CORIMAGE_H_ +#define _CORIMAGE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +IMAGE_NT_HEADERS *Cor_RtlImageNtHeader(VOID *pvBase, + ULONG FileLength); + +PIMAGE_SECTION_HEADER +Cor_RtlImageRvaToSection(PTR_IMAGE_NT_HEADERS NtHeaders, + ULONG Rva, + ULONG FileLength); + +PIMAGE_SECTION_HEADER +Cor_RtlImageRvaRangeToSection(PTR_IMAGE_NT_HEADERS NtHeaders, + ULONG Rva, + ULONG Range, + ULONG FileLength); + +DWORD Cor_RtlImageRvaToOffset(PTR_IMAGE_NT_HEADERS NtHeaders, + ULONG Rva, + ULONG FileLength); + +PBYTE Cor_RtlImageRvaToVa(PTR_IMAGE_NT_HEADERS NtHeaders, + PBYTE Base, + ULONG Rva, + ULONG FileLength); + +PBYTE Cor_RtlImageDirToVa(PTR_IMAGE_NT_HEADERS NtHeaders, + PBYTE Base, + UINT DirIndex, + ULONG FileLength); + +PBYTE Cor_RtlImageRvaToVa32(PTR_IMAGE_NT_HEADERS32 NtHeaders, + PBYTE Base, + ULONG Rva, + ULONG FileLength); + +PBYTE Cor_RtlImageRvaToVa64(PTR_IMAGE_NT_HEADERS64 NtHeaders, + PBYTE Base, + ULONG Rva, + ULONG FileLength); + +#ifdef __cplusplus +} +#endif + +#endif // _CORIMAGE_H_ diff --git a/lib/coreclr/src/inc/corinfo.h b/lib/coreclr/src/inc/corinfo.h new file mode 100644 index 0000000000..9cc849043e --- /dev/null +++ b/lib/coreclr/src/inc/corinfo.h @@ -0,0 +1,3267 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +/*****************************************************************************\ +* * +* CorInfo.h - EE / Code generator interface * +* * +******************************************************************************* +* +* This file exposes CLR runtime functionality. It can be used by compilers, +* both Just-in-time and ahead-of-time, to generate native code which +* executes in the runtime environment. +******************************************************************************* + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier +// must be updated. See code:JITEEVersionIdentifier for more information. +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#EEJitContractDetails + +The semantic contract between the EE and the JIT should be documented here It is incomplete, but as time goes +on, that hopefully will change + +See file:../../doc/BookOfTheRuntime/JIT/JIT%20Design.doc for details on the JIT compiler. See +code:EEStartup#TableOfContents for information on the runtime as a whole. + +------------------------------------------------------------------------------- +#Tokens + +The tokens in IL stream needs to be resolved to EE handles (CORINFO_CLASS/METHOD/FIELD_HANDLE) that +the runtime operates with. ICorStaticInfo::resolveToken is the method that resolves the found in IL stream +to set of EE handles (CORINFO_RESOLVED_TOKEN). All other APIs take resolved token as input. This design +avoids redundant token resolutions. + +The token validation is done as part of token resolution. The JIT is not required to do explicit upfront +token validation. + +------------------------------------------------------------------------------- +#ClassConstruction + +First of all class contruction comes in two flavors precise and 'beforeFieldInit'. In C# you get the former +if you declare an explicit class constructor method and the later if you declaratively initialize static +fields. Precise class construction guarentees that the .cctor is run precisely before the first access to any +method or field of the class. 'beforeFieldInit' semantics guarentees only that the .cctor will be run some +time before the first static field access (note that calling methods (static or insance) or accessing +instance fields does not cause .cctors to be run). + +Next you need to know that there are two kinds of code generation that can happen in the JIT: appdomain +neutral and appdomain specialized. The difference between these two kinds of code is how statics are handled. +For appdomain specific code, the address of a particular static variable is embeded in the code. This makes +it usable only for one appdomain (since every appdomain gets a own copy of its statics). Appdomain neutral +code calls a helper that looks up static variables off of a thread local variable. Thus the same code can be +used by mulitple appdomains in the same process. + +Generics also introduce a similar issue. Code for generic classes might be specialised for a particular set +of type arguments, or it could use helpers to access data that depends on type parameters and thus be shared +across several instantiations of the generic type. + +Thus there four cases + + * BeforeFieldInitCCtor - Unshared code. Cctors are only called when static fields are fetched. At the + time the method that touches the static field is JITed (or fixed up in the case of NGENed code), the + .cctor is called. + * BeforeFieldInitCCtor - Shared code. Since the same code is used for multiple classes, the act of JITing + the code can not be used as a hook. However, it is also the case that since the code is shared, it + can not wire in a particular address for the static and thus needs to use a helper that looks up the + correct address based on the thread ID. This helper does the .cctor check, and thus no additional + cctor logic is needed. + * PreciseCCtor - Unshared code. Any time a method is JITTed (or fixed up in the case of NGEN), a cctor + check for the class of the method being JITTed is done. In addition the JIT inserts explicit checks + before any static field accesses. Instance methods and fields do NOT have hooks because a .ctor + method must be called before the instance can be created. + * PreciseCctor - Shared code .cctor checks are placed in the prolog of every .ctor and static method. All + methods that access static fields have an explicit .cctor check before use. Again instance methods + don't have hooks because a .ctor would have to be called first. + +Technically speaking, however the optimization of avoiding checks on instance methods is flawed. It requires +that a .ctor always preceed a call to an instance methods. This break down when + + * A NULL is passed to an instance method. + * A .ctor does not call its superclasses .ctor. This allows an instance to be created without necessarily + calling all the .cctors of all the superclasses. A virtual call can then be made to a instance of a + superclass without necessarily calling the superclass's .cctor. + * The class is a value class (which exists without a .ctor being called) + +Nevertheless, the cost of plugging these holes is considered to high and the benefit is low. + +---------------------------------------------------------------------- + +#ClassConstructionFlags + +Thus the JIT's cctor responsibilities require it to check with the EE on every static field access using +initClass and before jitting any method to see if a .cctor check must be placed in the prolog. + + * CORINFO_FLG_BEFOREFIELDINIT indicate the class has beforeFieldInit semantics. The jit does not strictly + need this information however, it is valuable in optimizing static field fetch helper calls. Helper + call for classes with BeforeFieldInit semantics can be hoisted before other side effects where + classes with precise .cctor semantics do not allow this optimization. + +Inlining also complicates things. Because the class could have precise semantics it is also required that the +inlining of any constructor or static method must also do the initClass check. The inliner has the option of +inserting any required runtime check or simply not inlining the function. + +------------------------------------------------------------------------------- + +#StaticFields + +The first 4 options are mutially exclusive + + * CORINFO_FLG_HELPER If the field has this set, then the JIT must call getFieldHelper and call the + returned helper with the object ref (for an instance field) and a fieldDesc. Note that this should be + able to handle ANY field so to get a JIT up quickly, it has the option of using helper calls for all + field access (and skip the complexity below). Note that for statics it is assumed that you will + alwasy ask for the ADDRESSS helper and to the fetch in the JIT. + + * CORINFO_FLG_SHARED_HELPER This is currently only used for static fields. If this bit is set it means + that the field is feched by a helper call that takes a module identifier (see getModuleDomainID) and + a class identifier (see getClassDomainID) as arguments. The exact helper to call is determined by + getSharedStaticBaseHelper. The return value is of this function is the base of all statics in the + module. The offset from getFieldOffset must be added to this value to get the address of the field + itself. (see also CORINFO_FLG_STATIC_IN_HEAP). + + + * CORINFO_FLG_GENERICS_STATIC This is currently only used for static fields (of generic type). This + function is intended to be called with a Generic handle as a argument (from embedGenericHandle). The + exact helper to call is determined by getSharedStaticBaseHelper. The returned value is the base of + all statics in the class. The offset from getFieldOffset must be added to this value to get the + address of the (see also CORINFO_FLG_STATIC_IN_HEAP). + + * CORINFO_FLG_TLS This indicate that the static field is a Windows style Thread Local Static. (We also + have managed thread local statics, which work through the HELPER. Support for this is considered + legacy, and going forward, the EE should + + * This is a normal static field. Its address in in memory is determined by getFieldAddress. (see + also CORINFO_FLG_STATIC_IN_HEAP). + + +This last field can modify any of the cases above except CORINFO_FLG_HELPER + +CORINFO_FLG_STATIC_IN_HEAP This is currently only used for static fields of value classes. If the field has +this set then after computing what would normally be the field, what you actually get is a object pointer +(that must be reported to the GC) to a boxed version of the value. Thus the actual field address is computed +by addr = (*addr+sizeof(OBJECTREF)) + +Instance fields + + * CORINFO_FLG_HELPER This is used if the class is MarshalByRef, which means that the object might be a + proxyt to the real object in some other appdomain or process. If the field has this set, then the JIT + must call getFieldHelper and call the returned helper with the object ref. If the helper returned is + helpers that are for structures the args are as follows + + * CORINFO_HELP_GETFIELDSTRUCT - args are: retBuff, object, fieldDesc + * CORINFO_HELP_SETFIELDSTRUCT - args are object fieldDesc value + +The other GET helpers take an object fieldDesc and return the value The other SET helpers take an object +fieldDesc and value + + Note that unlike static fields there is no helper to take the address of a field because in general there + is no address for proxies (LDFLDA is illegal on proxies). + + CORINFO_FLG_EnC This is to support adding new field for edit and continue. This field also indicates that + a helper is needed to access this field. However this helper is always CORINFO_HELP_GETFIELDADDR, and + this helper always takes the object and field handle and returns the address of the field. It is the + JIT's responcibility to do the fetch or set. + +------------------------------------------------------------------------------- + +TODO: Talk about initializing strutures before use + + +******************************************************************************* +*/ + +#ifndef _COR_INFO_H_ +#define _COR_INFO_H_ + +#include +#include + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// #JITEEVersionIdentifier +// +// This GUID represents the version of the JIT/EE interface. Any time the interface between the JIT and +// the EE changes (by adding or removing methods to any interface shared between them), this GUID should +// be changed. This is the identifier verified by ICorJitCompiler::getVersionIdentifier(). +// +// You can use "uuidgen.exe -s" to generate this value. +// +// **** NOTE TO INTEGRATORS: +// +// If there is a merge conflict here, because the version changed in two different places, you must +// create a **NEW** GUID, not simply choose one or the other! +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if !defined(SELECTANY) +#if defined(__GNUC__) + #define SELECTANY extern __attribute__((weak)) +#else + #define SELECTANY extern __declspec(selectany) +#endif +#endif + +SELECTANY const GUID JITEEVersionIdentifier = { /* d609bed1-7831-49fc-bd49-b6f054dd4d46 */ + 0xd609bed1, + 0x7831, + 0x49fc, + {0xbd, 0x49, 0xb6, 0xf0, 0x54, 0xdd, 0x4d, 0x46} +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// END JITEEVersionIdentifier +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// For System V on the CLR type system number of registers to pass in and return a struct is the same. +// The CLR type system allows only up to 2 eightbytes to be passed in registers. There is no SSEUP classification types. +#define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS 2 +#define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_RETURN_IN_REGISTERS 2 +#define CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS 16 + +// System V struct passing +// The Classification types are described in the ABI spec at http://www.x86-64.org/documentation/abi.pdf +enum SystemVClassificationType : unsigned __int8 +{ + SystemVClassificationTypeUnknown = 0, + SystemVClassificationTypeStruct = 1, + SystemVClassificationTypeNoClass = 2, + SystemVClassificationTypeMemory = 3, + SystemVClassificationTypeInteger = 4, + SystemVClassificationTypeIntegerReference = 5, + SystemVClassificationTypeIntegerByRef = 6, + SystemVClassificationTypeSSE = 7, + // SystemVClassificationTypeSSEUp = Unused, // Not supported by the CLR. + // SystemVClassificationTypeX87 = Unused, // Not supported by the CLR. + // SystemVClassificationTypeX87Up = Unused, // Not supported by the CLR. + // SystemVClassificationTypeComplexX87 = Unused, // Not supported by the CLR. + + // Internal flags - never returned outside of the classification implementation. + + // This value represents a very special type with two eightbytes. + // First ByRef, second Integer (platform int). + // The VM has a special Elem type for this type - ELEMENT_TYPE_TYPEDBYREF. + // This is the classification counterpart for that element type. It is used to detect + // the special TypedReference type and specialize its classification. + // This type is represented as a struct with two fields. The classification needs to do + // special handling of it since the source/methadata type of the fieds is IntPtr. + // The VM changes the first to ByRef. The second is left as IntPtr (TYP_I_IMPL really). The classification needs to match this and + // special handling is warranted (similar thing is done in the getGCLayout function for this type). + SystemVClassificationTypeTypedReference = 8, + SystemVClassificationTypeMAX = 9, +}; + +// Represents classification information for a struct. +struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR +{ + SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR() + { + Initialize(); + } + + bool passedInRegisters; // Whether the struct is passable/passed (this includes struct returning) in registers. + unsigned __int8 eightByteCount; // Number of eightbytes for this struct. + SystemVClassificationType eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The eightbytes type classification. + unsigned __int8 eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The size of the eightbytes (an eightbyte could include padding. This represents the no padding size of the eightbyte). + unsigned __int8 eightByteOffsets[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The start offset of the eightbytes (in bytes). + + // Members + + //------------------------------------------------------------------------ + // CopyFrom: Copies a struct classification into this one. + // + // Arguments: + // 'copyFrom' the struct classification to copy from. + // + void CopyFrom(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& copyFrom) + { + passedInRegisters = copyFrom.passedInRegisters; + eightByteCount = copyFrom.eightByteCount; + + for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++) + { + eightByteClassifications[i] = copyFrom.eightByteClassifications[i]; + eightByteSizes[i] = copyFrom.eightByteSizes[i]; + eightByteOffsets[i] = copyFrom.eightByteOffsets[i]; + } + } + + //------------------------------------------------------------------------ + // IsIntegralSlot: Returns whether the eightbyte at slotIndex is of integral type. + // + // Arguments: + // 'slotIndex' the slot number we are determining if it is of integral type. + // + // Return value: + // returns true if we the eightbyte at index slotIndex is of integral type. + // + + bool IsIntegralSlot(unsigned slotIndex) const + { + return ((eightByteClassifications[slotIndex] == SystemVClassificationTypeInteger) || + (eightByteClassifications[slotIndex] == SystemVClassificationTypeIntegerReference) || + (eightByteClassifications[slotIndex] == SystemVClassificationTypeIntegerByRef)); + } + + //------------------------------------------------------------------------ + // IsSseSlot: Returns whether the eightbyte at slotIndex is SSE type. + // + // Arguments: + // 'slotIndex' the slot number we are determining if it is of SSE type. + // + // Return value: + // returns true if we the eightbyte at index slotIndex is of SSE type. + // + // Follows the rules of the AMD64 System V ABI specification at www.x86-64.org/documentation/abi.pdf. + // Please refer to it for definitions/examples. + // + bool IsSseSlot(unsigned slotIndex) const + { + return (eightByteClassifications[slotIndex] == SystemVClassificationTypeSSE); + } + +private: + void Initialize() + { + passedInRegisters = false; + eightByteCount = 0; + + for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++) + { + eightByteClassifications[i] = SystemVClassificationTypeUnknown; + eightByteSizes[i] = 0; + eightByteOffsets[i] = 0; + } + } +}; + +// CorInfoHelpFunc defines the set of helpers (accessed via the ICorDynamicInfo::getHelperFtn()) +// These helpers can be called by native code which executes in the runtime. +// Compilers can emit calls to these helpers. +// +// The signatures of the helpers are below (see RuntimeHelperArgumentCheck) + +enum CorInfoHelpFunc +{ + CORINFO_HELP_UNDEF, // invalid value. This should never be used + + /* Arithmetic helpers */ + + CORINFO_HELP_DIV, // For the ARM 32-bit integer divide uses a helper call :-( + CORINFO_HELP_MOD, + CORINFO_HELP_UDIV, + CORINFO_HELP_UMOD, + + CORINFO_HELP_LLSH, + CORINFO_HELP_LRSH, + CORINFO_HELP_LRSZ, + CORINFO_HELP_LMUL, + CORINFO_HELP_LMUL_OVF, + CORINFO_HELP_ULMUL_OVF, + CORINFO_HELP_LDIV, + CORINFO_HELP_LMOD, + CORINFO_HELP_ULDIV, + CORINFO_HELP_ULMOD, + CORINFO_HELP_LNG2DBL, // Convert a signed int64 to a double + CORINFO_HELP_ULNG2DBL, // Convert a unsigned int64 to a double + CORINFO_HELP_DBL2INT, + CORINFO_HELP_DBL2INT_OVF, + CORINFO_HELP_DBL2LNG, + CORINFO_HELP_DBL2LNG_OVF, + CORINFO_HELP_DBL2UINT, + CORINFO_HELP_DBL2UINT_OVF, + CORINFO_HELP_DBL2ULNG, + CORINFO_HELP_DBL2ULNG_OVF, + CORINFO_HELP_FLTREM, + CORINFO_HELP_DBLREM, + CORINFO_HELP_FLTROUND, + CORINFO_HELP_DBLROUND, + + /* Allocating a new object. Always use ICorClassInfo::getNewHelper() to decide + which is the right helper to use to allocate an object of a given type. */ + + CORINFO_HELP_NEW_CROSSCONTEXT, // cross context new object + CORINFO_HELP_NEWFAST, + CORINFO_HELP_NEWSFAST, // allocator for small, non-finalizer, non-array object + CORINFO_HELP_NEWSFAST_FINALIZE, // allocator for small, finalizable, non-array object + CORINFO_HELP_NEWSFAST_ALIGN8, // allocator for small, non-finalizer, non-array object, 8 byte aligned + CORINFO_HELP_NEWSFAST_ALIGN8_VC,// allocator for small, value class, 8 byte aligned + CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, // allocator for small, finalizable, non-array object, 8 byte aligned + CORINFO_HELP_NEW_MDARR, // multi-dim array helper (with or without lower bounds - dimensions passed in as vararg) + CORINFO_HELP_NEW_MDARR_NONVARARG,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array) + CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation + CORINFO_HELP_NEWARR_1_R2R_DIRECT, // wrapper for R2R direct call, which extracts method table from ArrayTypeDesc + CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays + CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays + CORINFO_HELP_NEWARR_1_ALIGN8, // like VC, but aligns the array start + + CORINFO_HELP_STRCNS, // create a new string literal + CORINFO_HELP_STRCNS_CURRENT_MODULE, // create a new string literal from the current module (used by NGen code) + + /* Object model */ + + CORINFO_HELP_INITCLASS, // Initialize class if not already initialized + CORINFO_HELP_INITINSTCLASS, // Initialize class for instantiated type + + // Use ICorClassInfo::getCastingHelper to determine + // the right helper to use + + CORINFO_HELP_ISINSTANCEOFINTERFACE, // Optimized helper for interfaces + CORINFO_HELP_ISINSTANCEOFARRAY, // Optimized helper for arrays + CORINFO_HELP_ISINSTANCEOFCLASS, // Optimized helper for classes + CORINFO_HELP_ISINSTANCEOFANY, // Slow helper for any type + + CORINFO_HELP_CHKCASTINTERFACE, + CORINFO_HELP_CHKCASTARRAY, + CORINFO_HELP_CHKCASTCLASS, + CORINFO_HELP_CHKCASTANY, + CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases + // has been taken care of by the inlined check + + CORINFO_HELP_BOX, + CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable + CORINFO_HELP_UNBOX, + CORINFO_HELP_UNBOX_NULLABLE, // special form of unboxing for Nullable + CORINFO_HELP_GETREFANY, // Extract the byref from a TypedReference, checking that it is the expected type + + CORINFO_HELP_ARRADDR_ST, // assign to element of object array with type-checking + CORINFO_HELP_LDELEMA_REF, // does a precise type comparision and returns address + + /* Exceptions */ + + CORINFO_HELP_THROW, // Throw an exception object + CORINFO_HELP_RETHROW, // Rethrow the currently active exception + CORINFO_HELP_USER_BREAKPOINT, // For a user program to break to the debugger + CORINFO_HELP_RNGCHKFAIL, // array bounds check failed + CORINFO_HELP_OVERFLOW, // throw an overflow exception + CORINFO_HELP_THROWDIVZERO, // throw a divide by zero exception + CORINFO_HELP_THROWNULLREF, // throw a null reference exception + + CORINFO_HELP_INTERNALTHROW, // Support for really fast jit + CORINFO_HELP_VERIFICATION, // Throw a VerificationException + CORINFO_HELP_SEC_UNMGDCODE_EXCPT, // throw a security unmanaged code exception + CORINFO_HELP_FAIL_FAST, // Kill the process avoiding any exceptions or stack and data dependencies (use for GuardStack unsafe buffer checks) + + CORINFO_HELP_METHOD_ACCESS_EXCEPTION,//Throw an access exception due to a failed member/class access check. + CORINFO_HELP_FIELD_ACCESS_EXCEPTION, + CORINFO_HELP_CLASS_ACCESS_EXCEPTION, + + CORINFO_HELP_ENDCATCH, // call back into the EE at the end of a catch block + + /* Synchronization */ + + CORINFO_HELP_MON_ENTER, + CORINFO_HELP_MON_EXIT, + CORINFO_HELP_MON_ENTER_STATIC, + CORINFO_HELP_MON_EXIT_STATIC, + + CORINFO_HELP_GETCLASSFROMMETHODPARAM, // Given a generics method handle, returns a class handle + CORINFO_HELP_GETSYNCFROMCLASSHANDLE, // Given a generics class handle, returns the sync monitor + // in its ManagedClassObject + + /* Security callout support */ + + CORINFO_HELP_SECURITY_PROLOG, // Required if CORINFO_FLG_SECURITYCHECK is set, or CORINFO_FLG_NOSECURITYWRAP is not set + CORINFO_HELP_SECURITY_PROLOG_FRAMED, // Slow version of CORINFO_HELP_SECURITY_PROLOG. Used for instrumentation. + + CORINFO_HELP_METHOD_ACCESS_CHECK, // Callouts to runtime security access checks + CORINFO_HELP_FIELD_ACCESS_CHECK, + CORINFO_HELP_CLASS_ACCESS_CHECK, + + CORINFO_HELP_DELEGATE_SECURITY_CHECK, // Callout to delegate security transparency check + + /* Verification runtime callout support */ + + CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, // Do a Demand for UnmanagedCode permission at runtime + + /* GC support */ + + CORINFO_HELP_STOP_FOR_GC, // Call GC (force a GC) + CORINFO_HELP_POLL_GC, // Ask GC if it wants to collect + + CORINFO_HELP_STRESS_GC, // Force a GC, but then update the JITTED code to be a noop call + CORINFO_HELP_CHECK_OBJ, // confirm that ECX is a valid object pointer (debugging only) + + /* GC Write barrier support */ + + CORINFO_HELP_ASSIGN_REF, // universal helpers with F_CALL_CONV calling convention + CORINFO_HELP_CHECKED_ASSIGN_REF, + CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. + + CORINFO_HELP_ASSIGN_BYREF, + CORINFO_HELP_ASSIGN_STRUCT, + + + /* Accessing fields */ + + // For COM object support (using COM get/set routines to update object) + // and EnC and cross-context support + CORINFO_HELP_GETFIELD8, + CORINFO_HELP_SETFIELD8, + CORINFO_HELP_GETFIELD16, + CORINFO_HELP_SETFIELD16, + CORINFO_HELP_GETFIELD32, + CORINFO_HELP_SETFIELD32, + CORINFO_HELP_GETFIELD64, + CORINFO_HELP_SETFIELD64, + CORINFO_HELP_GETFIELDOBJ, + CORINFO_HELP_SETFIELDOBJ, + CORINFO_HELP_GETFIELDSTRUCT, + CORINFO_HELP_SETFIELDSTRUCT, + CORINFO_HELP_GETFIELDFLOAT, + CORINFO_HELP_SETFIELDFLOAT, + CORINFO_HELP_GETFIELDDOUBLE, + CORINFO_HELP_SETFIELDDOUBLE, + + CORINFO_HELP_GETFIELDADDR, + + CORINFO_HELP_GETSTATICFIELDADDR_CONTEXT, // Helper for context-static fields + CORINFO_HELP_GETSTATICFIELDADDR_TLS, // Helper for PE TLS fields + + // There are a variety of specialized helpers for accessing static fields. The JIT should use + // ICorClassInfo::getSharedStaticsOrCCtorHelper to determine which helper to use + + // Helpers for regular statics + CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, + CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, + CORINFO_HELP_GETSHARED_GCSTATIC_BASE, + CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, + CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, + CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR, + CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS, + CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS, + // Helper to class initialize shared generic with dynamicclass, but not get static field address + CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS, + + // Helpers for thread statics + CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, + CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE, + CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, + CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, + CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, + CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, + CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, + CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, + + /* Debugger */ + + CORINFO_HELP_DBG_IS_JUST_MY_CODE, // Check if this is "JustMyCode" and needs to be stepped through. + + /* Profiling enter/leave probe addresses */ + CORINFO_HELP_PROF_FCN_ENTER, // record the entry to a method (caller) + CORINFO_HELP_PROF_FCN_LEAVE, // record the completion of current method (caller) + CORINFO_HELP_PROF_FCN_TAILCALL, // record the completionof current method through tailcall (caller) + + /* Miscellaneous */ + + CORINFO_HELP_BBT_FCN_ENTER, // record the entry to a method for collecting Tuning data + + CORINFO_HELP_PINVOKE_CALLI, // Indirect pinvoke call + CORINFO_HELP_TAILCALL, // Perform a tail call + + CORINFO_HELP_GETCURRENTMANAGEDTHREADID, + + CORINFO_HELP_INIT_PINVOKE_FRAME, // initialize an inlined PInvoke Frame for the JIT-compiler + + CORINFO_HELP_MEMSET, // Init block of memory + CORINFO_HELP_MEMCPY, // Copy block of memory + + CORINFO_HELP_RUNTIMEHANDLE_METHOD, // determine a type/field/method handle at run-time + CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG, // determine a type/field/method handle at run-time, with IBC logging + CORINFO_HELP_RUNTIMEHANDLE_CLASS, // determine a type/field/method handle at run-time + CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG, // determine a type/field/method handle at run-time, with IBC logging + + CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, // Convert from a TypeHandle (native structure pointer) to RuntimeType at run-time + CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL, // Convert from a TypeHandle (native structure pointer) to RuntimeType at run-time, the type may be null + CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, // Convert from a MethodDesc (native structure pointer) to RuntimeMethodHandle at run-time + CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, // Convert from a FieldDesc (native structure pointer) to RuntimeFieldHandle at run-time + CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time + CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time, handle might point to a null type + + CORINFO_HELP_ARE_TYPES_EQUIVALENT, // Check whether two TypeHandles (native structure pointers) are equivalent + + CORINFO_HELP_VIRTUAL_FUNC_PTR, // look up a virtual method at run-time + //CORINFO_HELP_VIRTUAL_FUNC_PTR_LOG, // look up a virtual method at run-time, with IBC logging + + // Not a real helpers. Instead of taking handle arguments, these helpers point to a small stub that loads the handle argument and calls the static helper. + CORINFO_HELP_READYTORUN_NEW, + CORINFO_HELP_READYTORUN_NEWARR_1, + CORINFO_HELP_READYTORUN_ISINSTANCEOF, + CORINFO_HELP_READYTORUN_CHKCAST, + CORINFO_HELP_READYTORUN_STATIC_BASE, + CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, + CORINFO_HELP_READYTORUN_GENERIC_HANDLE, + CORINFO_HELP_READYTORUN_DELEGATE_CTOR, + CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, + + CORINFO_HELP_EE_PRESTUB, // Not real JIT helper. Used in native images. + + CORINFO_HELP_EE_PRECODE_FIXUP, // Not real JIT helper. Used for Precode fixup in native images. + CORINFO_HELP_EE_PINVOKE_FIXUP, // Not real JIT helper. Used for PInvoke target fixup in native images. + CORINFO_HELP_EE_VSD_FIXUP, // Not real JIT helper. Used for VSD cell fixup in native images. + CORINFO_HELP_EE_EXTERNAL_FIXUP, // Not real JIT helper. Used for to fixup external method thunks in native images. + CORINFO_HELP_EE_VTABLE_FIXUP, // Not real JIT helper. Used for inherited vtable slot fixup in native images. + + CORINFO_HELP_EE_REMOTING_THUNK, // Not real JIT helper. Used for remoting precode in native images. + + CORINFO_HELP_EE_PERSONALITY_ROUTINE,// Not real JIT helper. Used in native images. + CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET,// Not real JIT helper. Used in native images to detect filter funclets. + + // ASSIGN_REF_EAX - CHECKED_ASSIGN_REF_EBP: NOGC_WRITE_BARRIERS JIT helper calls + // + // For unchecked versions EDX is required to point into GC heap. + // + // NOTE: these helpers are only used for x86. + CORINFO_HELP_ASSIGN_REF_EAX, // EAX holds GC ptr, do a 'mov [EDX], EAX' and inform GC + CORINFO_HELP_ASSIGN_REF_EBX, // EBX holds GC ptr, do a 'mov [EDX], EBX' and inform GC + CORINFO_HELP_ASSIGN_REF_ECX, // ECX holds GC ptr, do a 'mov [EDX], ECX' and inform GC + CORINFO_HELP_ASSIGN_REF_ESI, // ESI holds GC ptr, do a 'mov [EDX], ESI' and inform GC + CORINFO_HELP_ASSIGN_REF_EDI, // EDI holds GC ptr, do a 'mov [EDX], EDI' and inform GC + CORINFO_HELP_ASSIGN_REF_EBP, // EBP holds GC ptr, do a 'mov [EDX], EBP' and inform GC + + CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, // These are the same as ASSIGN_REF above ... + CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, // ... but also check if EDX points into heap. + CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, + CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, + CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, + CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, + + CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR, // Return the reference to a counter to decide to take cloned path in debug stress. + CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, // Print a message that a loop cloning optimization has occurred in debug mode. + + CORINFO_HELP_THROW_ARGUMENTEXCEPTION, // throw ArgumentException + CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, // throw ArgumentOutOfRangeException + CORINFO_HELP_THROW_NOT_IMPLEMENTED, // throw NotImplementedException + CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, // throw PlatformNotSupportedException + CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, // throw TypeNotSupportedException + + CORINFO_HELP_JIT_PINVOKE_BEGIN, // Transition to preemptive mode before a P/Invoke, frame is the first argument + CORINFO_HELP_JIT_PINVOKE_END, // Transition to cooperative mode after a P/Invoke, frame is the first argument + + CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument + CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument + + CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle + + CORINFO_HELP_COUNT, +}; + +#define CORINFO_HELP_READYTORUN_ATYPICAL_CALLSITE 0x40000000 + +//This describes the signature for a helper method. +enum CorInfoHelpSig +{ + CORINFO_HELP_SIG_UNDEF, + CORINFO_HELP_SIG_NO_ALIGN_STUB, + CORINFO_HELP_SIG_NO_UNWIND_STUB, + CORINFO_HELP_SIG_REG_ONLY, + CORINFO_HELP_SIG_4_STACK, + CORINFO_HELP_SIG_8_STACK, + CORINFO_HELP_SIG_12_STACK, + CORINFO_HELP_SIG_16_STACK, + CORINFO_HELP_SIG_8_VA, //2 arguments plus varargs + + CORINFO_HELP_SIG_EBPCALL, //special calling convention that uses EDX and + //EBP as arguments + + CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB, + + CORINFO_HELP_SIG_COUNT +}; + +// The enumeration is returned in 'getSig','getType', getArgType methods +enum CorInfoType +{ + CORINFO_TYPE_UNDEF = 0x0, + CORINFO_TYPE_VOID = 0x1, + CORINFO_TYPE_BOOL = 0x2, + CORINFO_TYPE_CHAR = 0x3, + CORINFO_TYPE_BYTE = 0x4, + CORINFO_TYPE_UBYTE = 0x5, + CORINFO_TYPE_SHORT = 0x6, + CORINFO_TYPE_USHORT = 0x7, + CORINFO_TYPE_INT = 0x8, + CORINFO_TYPE_UINT = 0x9, + CORINFO_TYPE_LONG = 0xa, + CORINFO_TYPE_ULONG = 0xb, + CORINFO_TYPE_NATIVEINT = 0xc, + CORINFO_TYPE_NATIVEUINT = 0xd, + CORINFO_TYPE_FLOAT = 0xe, + CORINFO_TYPE_DOUBLE = 0xf, + CORINFO_TYPE_STRING = 0x10, // Not used, should remove + CORINFO_TYPE_PTR = 0x11, + CORINFO_TYPE_BYREF = 0x12, + CORINFO_TYPE_VALUECLASS = 0x13, + CORINFO_TYPE_CLASS = 0x14, + CORINFO_TYPE_REFANY = 0x15, + + // CORINFO_TYPE_VAR is for a generic type variable. + // Generic type variables only appear when the JIT is doing + // verification (not NOT compilation) of generic code + // for the EE, in which case we're running + // the JIT in "import only" mode. + + CORINFO_TYPE_VAR = 0x16, + CORINFO_TYPE_COUNT, // number of jit types +}; + +enum CorInfoTypeWithMod +{ + CORINFO_TYPE_MASK = 0x3F, // lower 6 bits are type mask + CORINFO_TYPE_MOD_PINNED = 0x40, // can be applied to CLASS, or BYREF to indiate pinned +}; + +inline CorInfoType strip(CorInfoTypeWithMod val) { + return CorInfoType(val & CORINFO_TYPE_MASK); +} + +// The enumeration is returned in 'getSig' + +enum CorInfoCallConv +{ + // These correspond to CorCallingConvention + + CORINFO_CALLCONV_DEFAULT = 0x0, + CORINFO_CALLCONV_C = 0x1, + CORINFO_CALLCONV_STDCALL = 0x2, + CORINFO_CALLCONV_THISCALL = 0x3, + CORINFO_CALLCONV_FASTCALL = 0x4, + CORINFO_CALLCONV_VARARG = 0x5, + CORINFO_CALLCONV_FIELD = 0x6, + CORINFO_CALLCONV_LOCAL_SIG = 0x7, + CORINFO_CALLCONV_PROPERTY = 0x8, + CORINFO_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for IL stub PInvoke vararg calls + + CORINFO_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits + CORINFO_CALLCONV_GENERIC = 0x10, + CORINFO_CALLCONV_HASTHIS = 0x20, + CORINFO_CALLCONV_EXPLICITTHIS=0x40, + CORINFO_CALLCONV_PARAMTYPE = 0x80, // Passed last. Same as CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG +}; + +#ifdef UNIX_X86_ABI +inline bool IsCallerPop(CorInfoCallConv callConv) +{ + unsigned int umask = CORINFO_CALLCONV_STDCALL + | CORINFO_CALLCONV_THISCALL + | CORINFO_CALLCONV_FASTCALL; + + return !(callConv & umask); +} +#endif // UNIX_X86_ABI + +enum CorInfoUnmanagedCallConv +{ + // These correspond to CorUnmanagedCallingConvention + + CORINFO_UNMANAGED_CALLCONV_UNKNOWN, + CORINFO_UNMANAGED_CALLCONV_C, + CORINFO_UNMANAGED_CALLCONV_STDCALL, + CORINFO_UNMANAGED_CALLCONV_THISCALL, + CORINFO_UNMANAGED_CALLCONV_FASTCALL +}; + +// These are returned from getMethodOptions +enum CorInfoOptions +{ + CORINFO_OPT_INIT_LOCALS = 0x00000010, // zero initialize all variables + + CORINFO_GENERICS_CTXT_FROM_THIS = 0x00000020, // is this shared generic code that access the generic context from the this pointer? If so, then if the method has SEH then the 'this' pointer must always be reported and kept alive. + CORINFO_GENERICS_CTXT_FROM_METHODDESC = 0x00000040, // is this shared generic code that access the generic context from the ParamTypeArg(that is a MethodDesc)? If so, then if the method has SEH then the 'ParamTypeArg' must always be reported and kept alive. Same as CORINFO_CALLCONV_PARAMTYPE + CORINFO_GENERICS_CTXT_FROM_METHODTABLE = 0x00000080, // is this shared generic code that access the generic context from the ParamTypeArg(that is a MethodTable)? If so, then if the method has SEH then the 'ParamTypeArg' must always be reported and kept alive. Same as CORINFO_CALLCONV_PARAMTYPE + CORINFO_GENERICS_CTXT_MASK = (CORINFO_GENERICS_CTXT_FROM_THIS | + CORINFO_GENERICS_CTXT_FROM_METHODDESC | + CORINFO_GENERICS_CTXT_FROM_METHODTABLE), + CORINFO_GENERICS_CTXT_KEEP_ALIVE = 0x00000100, // Keep the generics context alive throughout the method even if there is no explicit use, and report its location to the CLR + +}; + +// +// what type of code region we are in +// +enum CorInfoRegionKind +{ + CORINFO_REGION_NONE, + CORINFO_REGION_HOT, + CORINFO_REGION_COLD, + CORINFO_REGION_JIT, +}; + + +// these are the attribute flags for fields and methods (getMethodAttribs) +enum CorInfoFlag +{ +// CORINFO_FLG_UNUSED = 0x00000001, +// CORINFO_FLG_UNUSED = 0x00000002, + CORINFO_FLG_PROTECTED = 0x00000004, + CORINFO_FLG_STATIC = 0x00000008, + CORINFO_FLG_FINAL = 0x00000010, + CORINFO_FLG_SYNCH = 0x00000020, + CORINFO_FLG_VIRTUAL = 0x00000040, +// CORINFO_FLG_UNUSED = 0x00000080, + CORINFO_FLG_NATIVE = 0x00000100, + CORINFO_FLG_INTRINSIC_TYPE = 0x00000200, // This type is marked by [Intrinsic] + CORINFO_FLG_ABSTRACT = 0x00000400, + + CORINFO_FLG_EnC = 0x00000800, // member was added by Edit'n'Continue + + // These are internal flags that can only be on methods + CORINFO_FLG_FORCEINLINE = 0x00010000, // The method should be inlined if possible. + CORINFO_FLG_SHAREDINST = 0x00020000, // the code for this method is shared between different generic instantiations (also set on classes/types) + CORINFO_FLG_DELEGATE_INVOKE = 0x00040000, // "Delegate + CORINFO_FLG_PINVOKE = 0x00080000, // Is a P/Invoke call + CORINFO_FLG_SECURITYCHECK = 0x00100000, // Is one of the security routines that does a stackwalk (e.g. Assert, Demand) + CORINFO_FLG_NOGCCHECK = 0x00200000, // This method is FCALL that has no GC check. Don't put alone in loops + CORINFO_FLG_INTRINSIC = 0x00400000, // This method MAY have an intrinsic ID + CORINFO_FLG_CONSTRUCTOR = 0x00800000, // This method is an instance or type initializer + CORINFO_FLG_AGGRESSIVE_OPT = 0x01000000, // The method may contain hot code and should be aggressively optimized if possible + CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS = 0x02000000, // Indicates that tier 0 JIT should not be used for a method that contains a loop + CORINFO_FLG_NOSECURITYWRAP = 0x04000000, // The method requires no security checks + CORINFO_FLG_DONT_INLINE = 0x10000000, // The method should not be inlined + CORINFO_FLG_DONT_INLINE_CALLER = 0x20000000, // The method should not be inlined, nor should its callers. It cannot be tail called. + CORINFO_FLG_JIT_INTRINSIC = 0x40000000, // Method is a potential jit intrinsic; verify identity by name check + + // These are internal flags that can only be on Classes + CORINFO_FLG_VALUECLASS = 0x00010000, // is the class a value class +// This flag is define din the Methods section, but is also valid on classes. +// CORINFO_FLG_SHAREDINST = 0x00020000, // This class is satisfies TypeHandle::IsCanonicalSubtype + CORINFO_FLG_VAROBJSIZE = 0x00040000, // the object size varies depending of constructor args + CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently) + CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union) + CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface + CORINFO_FLG_CONTEXTFUL = 0x00400000, // is this a contextful class? + CORINFO_FLG_CUSTOMLAYOUT = 0x00800000, // does this struct have custom layout? + CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ? + CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ? + CORINFO_FLG_MARSHAL_BYREF = 0x04000000, // is this a subclass of MarshalByRef ? + CORINFO_FLG_CONTAINS_STACK_PTR = 0x08000000, // This class has a stack pointer inside it + CORINFO_FLG_VARIANCE = 0x10000000, // MethodTable::HasVariance (sealed does *not* mean uncast-able) + CORINFO_FLG_BEFOREFIELDINIT = 0x20000000, // Additional flexibility for when to run .cctor (see code:#ClassConstructionFlags) + CORINFO_FLG_GENERIC_TYPE_VARIABLE = 0x40000000, // This is really a handle for a variable type + CORINFO_FLG_UNSAFE_VALUECLASS = 0x80000000, // Unsafe (C++'s /GS) value type +}; + +// Flags computed by a runtime compiler +enum CorInfoMethodRuntimeFlags +{ + CORINFO_FLG_BAD_INLINEE = 0x00000001, // The method is not suitable for inlining + CORINFO_FLG_VERIFIABLE = 0x00000002, // The method has verifiable code + CORINFO_FLG_UNVERIFIABLE = 0x00000004, // The method has unverifiable code + CORINFO_FLG_SWITCHED_TO_MIN_OPT = 0x00000008, // The JIT decided to switch to MinOpt for this method, when it was not requested + CORINFO_FLG_SWITCHED_TO_OPTIMIZED = 0x00000010, // The JIT decided to switch to tier 1 for this method, when a different tier was requested +}; + + +enum CORINFO_ACCESS_FLAGS +{ + CORINFO_ACCESS_ANY = 0x0000, // Normal access + CORINFO_ACCESS_THIS = 0x0001, // Accessed via the this reference + CORINFO_ACCESS_UNWRAP = 0x0002, // Accessed via an unwrap reference + + CORINFO_ACCESS_NONNULL = 0x0004, // Instance is guaranteed non-null + + CORINFO_ACCESS_LDFTN = 0x0010, // Accessed via ldftn + + // Field access flags + CORINFO_ACCESS_GET = 0x0100, // Field get (ldfld) + CORINFO_ACCESS_SET = 0x0200, // Field set (stfld) + CORINFO_ACCESS_ADDRESS = 0x0400, // Field address (ldflda) + CORINFO_ACCESS_INIT_ARRAY = 0x0800, // Field use for InitializeArray + CORINFO_ACCESS_ATYPICAL_CALLSITE = 0x4000, // Atypical callsite that cannot be disassembled by delay loading helper + CORINFO_ACCESS_INLINECHECK= 0x8000, // Return fieldFlags and fieldAccessor only. Used by JIT64 during inlining. +}; + +// These are the flags set on an CORINFO_EH_CLAUSE +enum CORINFO_EH_CLAUSE_FLAGS +{ + CORINFO_EH_CLAUSE_NONE = 0, + CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter + CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause + CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause + CORINFO_EH_CLAUSE_DUPLICATE = 0x0008, // Duplicated clause. This clause was duplicated to a funclet which was pulled out of line + CORINFO_EH_CLAUSE_SAMETRY = 0x0010, // This clause covers same try block as the previous one. (Used by CoreRT ABI.) +}; + +// This enumeration is passed to InternalThrow +enum CorInfoException +{ + CORINFO_NullReferenceException, + CORINFO_DivideByZeroException, + CORINFO_InvalidCastException, + CORINFO_IndexOutOfRangeException, + CORINFO_OverflowException, + CORINFO_SynchronizationLockException, + CORINFO_ArrayTypeMismatchException, + CORINFO_RankException, + CORINFO_ArgumentNullException, + CORINFO_ArgumentException, + CORINFO_Exception_Count, +}; + + +// This enumeration is returned by getIntrinsicID. Methods corresponding to +// these values will have "well-known" specified behavior. Calls to these +// methods could be replaced with inlined code corresponding to the +// specified behavior (without having to examine the IL beforehand). + +enum CorInfoIntrinsics +{ + CORINFO_INTRINSIC_Sin, + CORINFO_INTRINSIC_Cos, + CORINFO_INTRINSIC_Cbrt, + CORINFO_INTRINSIC_Sqrt, + CORINFO_INTRINSIC_Abs, + CORINFO_INTRINSIC_Round, + CORINFO_INTRINSIC_Cosh, + CORINFO_INTRINSIC_Sinh, + CORINFO_INTRINSIC_Tan, + CORINFO_INTRINSIC_Tanh, + CORINFO_INTRINSIC_Asin, + CORINFO_INTRINSIC_Asinh, + CORINFO_INTRINSIC_Acos, + CORINFO_INTRINSIC_Acosh, + CORINFO_INTRINSIC_Atan, + CORINFO_INTRINSIC_Atan2, + CORINFO_INTRINSIC_Atanh, + CORINFO_INTRINSIC_Log10, + CORINFO_INTRINSIC_Pow, + CORINFO_INTRINSIC_Exp, + CORINFO_INTRINSIC_Ceiling, + CORINFO_INTRINSIC_Floor, + CORINFO_INTRINSIC_GetChar, // fetch character out of string + CORINFO_INTRINSIC_Array_GetDimLength, // Get number of elements in a given dimension of an array + CORINFO_INTRINSIC_Array_Get, // Get the value of an element in an array + CORINFO_INTRINSIC_Array_Address, // Get the address of an element in an array + CORINFO_INTRINSIC_Array_Set, // Set the value of an element in an array + CORINFO_INTRINSIC_StringGetChar, // fetch character out of string + CORINFO_INTRINSIC_StringLength, // get the length + CORINFO_INTRINSIC_InitializeArray, // initialize an array from static data + CORINFO_INTRINSIC_GetTypeFromHandle, + CORINFO_INTRINSIC_RTH_GetValueInternal, + CORINFO_INTRINSIC_TypeEQ, + CORINFO_INTRINSIC_TypeNEQ, + CORINFO_INTRINSIC_Object_GetType, + CORINFO_INTRINSIC_StubHelpers_GetStubContext, + CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr, + CORINFO_INTRINSIC_StubHelpers_GetNDirectTarget, + CORINFO_INTRINSIC_InterlockedAdd32, + CORINFO_INTRINSIC_InterlockedAdd64, + CORINFO_INTRINSIC_InterlockedXAdd32, + CORINFO_INTRINSIC_InterlockedXAdd64, + CORINFO_INTRINSIC_InterlockedXchg32, + CORINFO_INTRINSIC_InterlockedXchg64, + CORINFO_INTRINSIC_InterlockedCmpXchg32, + CORINFO_INTRINSIC_InterlockedCmpXchg64, + CORINFO_INTRINSIC_MemoryBarrier, + CORINFO_INTRINSIC_GetCurrentManagedThread, + CORINFO_INTRINSIC_GetManagedThreadId, + CORINFO_INTRINSIC_ByReference_Ctor, + CORINFO_INTRINSIC_ByReference_Value, + CORINFO_INTRINSIC_Span_GetItem, + CORINFO_INTRINSIC_ReadOnlySpan_GetItem, + CORINFO_INTRINSIC_GetRawHandle, + + CORINFO_INTRINSIC_Count, + CORINFO_INTRINSIC_Illegal = -1, // Not a true intrinsic, +}; + +// Can a value be accessed directly from JITed code. +enum InfoAccessType +{ + IAT_VALUE, // The info value is directly available + IAT_PVALUE, // The value needs to be accessed via an indirection + IAT_PPVALUE, // The value needs to be accessed via a double indirection + IAT_RELPVALUE // The value needs to be accessed via a relative indirection +}; + +enum CorInfoGCType +{ + TYPE_GC_NONE, // no embedded objectrefs + TYPE_GC_REF, // Is an object ref + TYPE_GC_BYREF, // Is an interior pointer - promote it but don't scan it + TYPE_GC_OTHER // requires type-specific treatment +}; + +enum CorInfoClassId +{ + CLASSID_SYSTEM_OBJECT, + CLASSID_TYPED_BYREF, + CLASSID_TYPE_HANDLE, + CLASSID_FIELD_HANDLE, + CLASSID_METHOD_HANDLE, + CLASSID_STRING, + CLASSID_ARGUMENT_HANDLE, + CLASSID_RUNTIME_TYPE, +}; + +enum CorInfoInline +{ + INLINE_PASS = 0, // Inlining OK + + // failures are negative + INLINE_FAIL = -1, // Inlining not OK for this case only + INLINE_NEVER = -2, // This method should never be inlined, regardless of context +}; + +enum CorInfoInlineRestrictions +{ + INLINE_RESPECT_BOUNDARY = 0x00000001, // You can inline if there are no calls from the method being inlined + INLINE_NO_CALLEE_LDSTR = 0x00000002, // You can inline only if you guarantee that if inlinee does an ldstr + // inlinee's module will never see that string (by any means). + // This is due to how we implement the NoStringInterningAttribute + // (by reusing the fixup table). + INLINE_SAME_THIS = 0x00000004, // You can inline only if the callee is on the same this reference as caller +}; + +enum CorInfoInlineTypeCheck +{ + CORINFO_INLINE_TYPECHECK_NONE = 0x00000000, // It's not okay to compare type's vtable with a native type handle + CORINFO_INLINE_TYPECHECK_PASS = 0x00000001, // It's okay to compare type's vtable with a native type handle + CORINFO_INLINE_TYPECHECK_USE_HELPER = 0x00000002, // Use a specialized helper to compare type's vtable with native type handle +}; + +enum CorInfoInlineTypeCheckSource +{ + CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE = 0x00000000, // Type handle comes from the vtable + CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN = 0x00000001, // Type handle comes from an ldtoken +}; + +// If you add more values here, keep it in sync with TailCallTypeMap in ..\vm\ClrEtwAll.man +// and the string enum in CEEInfo::reportTailCallDecision in ..\vm\JITInterface.cpp +enum CorInfoTailCall +{ + TAILCALL_OPTIMIZED = 0, // Optimized tail call (epilog + jmp) + TAILCALL_RECURSIVE = 1, // Optimized into a loop (only when a method tail calls itself) + TAILCALL_HELPER = 2, // Helper assisted tail call (call to JIT_TailCall) + + // failures are negative + TAILCALL_FAIL = -1, // Couldn't do a tail call +}; + +enum CorInfoCanSkipVerificationResult +{ + CORINFO_VERIFICATION_CANNOT_SKIP = 0, // Cannot skip verification during jit time. + CORINFO_VERIFICATION_CAN_SKIP = 1, // Can skip verification during jit time. + CORINFO_VERIFICATION_RUNTIME_CHECK = 2, // Cannot skip verification during jit time, + // but need to insert a callout to the VM to ask during runtime + // whether to raise a verification or not (if the method is unverifiable). + CORINFO_VERIFICATION_DONT_JIT = 3, // Cannot skip verification during jit time, + // but do not jit the method if is is unverifiable. +}; + +enum CorInfoInitClassResult +{ + CORINFO_INITCLASS_NOT_REQUIRED = 0x00, // No class initialization required, but the class is not actually initialized yet + // (e.g. we are guaranteed to run the static constructor in method prolog) + CORINFO_INITCLASS_INITIALIZED = 0x01, // Class initialized + CORINFO_INITCLASS_SPECULATIVE = 0x02, // Class may be initialized speculatively + CORINFO_INITCLASS_USE_HELPER = 0x04, // The JIT must insert class initialization helper call. + CORINFO_INITCLASS_DONT_INLINE = 0x08, // The JIT should not inline the method requesting the class initialization. The class + // initialization requires helper class now, but will not require initialization + // if the method is compiled standalone. Or the method cannot be inlined due to some + // requirement around class initialization such as shared generics. +}; + +// Reason codes for making indirect calls +#define INDIRECT_CALL_REASONS() \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_UNKNOWN) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_EXOTIC) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_PINVOKE) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_GENERIC) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_NO_CODE) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_FIXUPS) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_STUB) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_REMOTING) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_CER) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_METHOD) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_FIRST_CALL) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_VALUE_TYPE) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_CANT_PATCH) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_PROFILING) \ + INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_OTHER_LOADER_MODULE) \ + +enum CorInfoIndirectCallReason +{ + #undef INDIRECT_CALL_REASON_FUNC + #define INDIRECT_CALL_REASON_FUNC(x) x, + INDIRECT_CALL_REASONS() + + #undef INDIRECT_CALL_REASON_FUNC + + CORINFO_INDIRECT_CALL_COUNT +}; + +// This is for use when the JIT is compiling an instantiation +// of generic code. The JIT needs to know if the generic code itself +// (which can be verified once and for all independently of the +// instantiations) passed verification. +enum CorInfoInstantiationVerification +{ + // The method is NOT a concrete instantiation (eg. List.Add()) of a method + // in a generic class or a generic method. It is either the typical instantiation + // (eg. List.Add()) or entirely non-generic. + INSTVER_NOT_INSTANTIATION = 0, + + // The method is an instantiation of a method in a generic class or a generic method, + // and the generic class was successfully verified + INSTVER_GENERIC_PASSED_VERIFICATION = 1, + + // The method is an instantiation of a method in a generic class or a generic method, + // and the generic class failed verification + INSTVER_GENERIC_FAILED_VERIFICATION = 2, +}; + +// When using CORINFO_HELPER_TAILCALL, the JIT needs to pass certain special +// calling convention/argument passing/handling details to the helper +enum CorInfoHelperTailCallSpecialHandling +{ + CORINFO_TAILCALL_NORMAL = 0x00000000, + CORINFO_TAILCALL_STUB_DISPATCH_ARG = 0x00000001, +}; + + +inline bool dontInline(CorInfoInline val) { + return(val < 0); +} + +// Cookie types consumed by the code generator (these are opaque values +// not inspected by the code generator): + +typedef struct CORINFO_ASSEMBLY_STRUCT_* CORINFO_ASSEMBLY_HANDLE; +typedef struct CORINFO_MODULE_STRUCT_* CORINFO_MODULE_HANDLE; +typedef struct CORINFO_DEPENDENCY_STRUCT_* CORINFO_DEPENDENCY_HANDLE; +typedef struct CORINFO_CLASS_STRUCT_* CORINFO_CLASS_HANDLE; +typedef struct CORINFO_METHOD_STRUCT_* CORINFO_METHOD_HANDLE; +typedef struct CORINFO_FIELD_STRUCT_* CORINFO_FIELD_HANDLE; +typedef struct CORINFO_ARG_LIST_STRUCT_* CORINFO_ARG_LIST_HANDLE; // represents a list of argument types +typedef struct CORINFO_JUST_MY_CODE_HANDLE_*CORINFO_JUST_MY_CODE_HANDLE; +typedef struct CORINFO_PROFILING_STRUCT_* CORINFO_PROFILING_HANDLE; // a handle guaranteed to be unique per process +typedef struct CORINFO_GENERIC_STRUCT_* CORINFO_GENERIC_HANDLE; // a generic handle (could be any of the above) + +// what is actually passed on the varargs call +typedef struct CORINFO_VarArgInfo * CORINFO_VARARGS_HANDLE; + +// Generic tokens are resolved with respect to a context, which is usually the method +// being compiled. The CORINFO_CONTEXT_HANDLE indicates which exact instantiation +// (or the open instantiation) is being referred to. +// CORINFO_CONTEXT_HANDLE is more tightly scoped than CORINFO_MODULE_HANDLE. For cases +// where the exact instantiation does not matter, CORINFO_MODULE_HANDLE is used. +typedef CORINFO_METHOD_HANDLE CORINFO_CONTEXT_HANDLE; + +typedef struct CORINFO_DEPENDENCY_STRUCT_ +{ + CORINFO_MODULE_HANDLE moduleFrom; + CORINFO_MODULE_HANDLE moduleTo; +} CORINFO_DEPENDENCY; + +// Bit-twiddling of contexts assumes word-alignment of method handles and type handles +// If this ever changes, some other encoding will be needed +enum CorInfoContextFlags +{ + CORINFO_CONTEXTFLAGS_METHOD = 0x00, // CORINFO_CONTEXT_HANDLE is really a CORINFO_METHOD_HANDLE + CORINFO_CONTEXTFLAGS_CLASS = 0x01, // CORINFO_CONTEXT_HANDLE is really a CORINFO_CLASS_HANDLE + CORINFO_CONTEXTFLAGS_MASK = 0x01 +}; + +#define MAKE_CLASSCONTEXT(c) (CORINFO_CONTEXT_HANDLE((size_t) (c) | CORINFO_CONTEXTFLAGS_CLASS)) +#define MAKE_METHODCONTEXT(m) (CORINFO_CONTEXT_HANDLE((size_t) (m) | CORINFO_CONTEXTFLAGS_METHOD)) + +enum CorInfoSigInfoFlags +{ + CORINFO_SIGFLAG_IS_LOCAL_SIG = 0x01, + CORINFO_SIGFLAG_IL_STUB = 0x02, +}; + +struct CORINFO_SIG_INST +{ + unsigned classInstCount; + CORINFO_CLASS_HANDLE * classInst; // (representative, not exact) instantiation for class type variables in signature + unsigned methInstCount; + CORINFO_CLASS_HANDLE * methInst; // (representative, not exact) instantiation for method type variables in signature +}; + +struct CORINFO_SIG_INFO +{ + CorInfoCallConv callConv; + CORINFO_CLASS_HANDLE retTypeClass; // if the return type is a value class, this is its handle (enums are normalized) + CORINFO_CLASS_HANDLE retTypeSigClass;// returns the value class as it is in the sig (enums are not converted to primitives) + CorInfoType retType : 8; + unsigned flags : 8; // used by IL stubs code + unsigned numArgs : 16; + struct CORINFO_SIG_INST sigInst; // information about how type variables are being instantiated in generic code + CORINFO_ARG_LIST_HANDLE args; + PCCOR_SIGNATURE pSig; + unsigned cbSig; + CORINFO_MODULE_HANDLE scope; // passed to getArgClass + mdToken token; + + CorInfoCallConv getCallConv() { return CorInfoCallConv((callConv & CORINFO_CALLCONV_MASK)); } + bool hasThis() { return ((callConv & CORINFO_CALLCONV_HASTHIS) != 0); } + bool hasExplicitThis() { return ((callConv & CORINFO_CALLCONV_EXPLICITTHIS) != 0); } + unsigned totalILArgs() { return (numArgs + hasThis()); } + bool isVarArg() { return ((getCallConv() == CORINFO_CALLCONV_VARARG) || (getCallConv() == CORINFO_CALLCONV_NATIVEVARARG)); } + bool hasTypeArg() { return ((callConv & CORINFO_CALLCONV_PARAMTYPE) != 0); } +}; + +struct CORINFO_METHOD_INFO +{ + CORINFO_METHOD_HANDLE ftn; + CORINFO_MODULE_HANDLE scope; + BYTE * ILCode; + unsigned ILCodeSize; + unsigned maxStack; + unsigned EHcount; + CorInfoOptions options; + CorInfoRegionKind regionKind; + CORINFO_SIG_INFO args; + CORINFO_SIG_INFO locals; +}; + +//---------------------------------------------------------------------------- +// Looking up handles and addresses. +// +// When the JIT requests a handle, the EE may direct the JIT that it must +// access the handle in a variety of ways. These are packed as +// CORINFO_CONST_LOOKUP +// or CORINFO_LOOKUP (contains either a CORINFO_CONST_LOOKUP or a CORINFO_RUNTIME_LOOKUP) +// +// Constant Lookups v. Runtime Lookups (i.e. when will Runtime Lookups be generated?) +// ----------------------------------------------------------------------------------- +// +// CORINFO_LOOKUP_KIND is part of the result type of embedGenericHandle, +// getVirtualCallInfo and any other functions that may require a +// runtime lookup when compiling shared generic code. +// +// CORINFO_LOOKUP_KIND indicates whether a particular token in the instruction stream can be: +// (a) Mapped to a handle (type, field or method) at compile-time (!needsRuntimeLookup) +// (b) Must be looked up at run-time, and if so which runtime lookup technique should be used (see below) +// +// If the JIT or EE does not support code sharing for generic code, then +// all CORINFO_LOOKUP results will be "constant lookups", i.e. +// the needsRuntimeLookup of CORINFO_LOOKUP.lookupKind.needsRuntimeLookup +// will be false. +// +// Constant Lookups +// ---------------- +// +// Constant Lookups are either: +// IAT_VALUE: immediate (relocatable) values, +// IAT_PVALUE: immediate values access via an indirection through an immediate (relocatable) address +// IAT_RELPVALUE: immediate values access via a relative indirection through an immediate offset +// IAT_PPVALUE: immediate values access via a double indirection through an immediate (relocatable) address +// +// Runtime Lookups +// --------------- +// +// CORINFO_LOOKUP_KIND is part of the result type of embedGenericHandle, +// getVirtualCallInfo and any other functions that may require a +// runtime lookup when compiling shared generic code. +// +// CORINFO_LOOKUP_KIND indicates whether a particular token in the instruction stream can be: +// (a) Mapped to a handle (type, field or method) at compile-time (!needsRuntimeLookup) +// (b) Must be looked up at run-time using the class dictionary +// stored in the vtable of the this pointer (needsRuntimeLookup && THISOBJ) +// (c) Must be looked up at run-time using the method dictionary +// stored in the method descriptor parameter passed to a generic +// method (needsRuntimeLookup && METHODPARAM) +// (d) Must be looked up at run-time using the class dictionary stored +// in the vtable parameter passed to a method in a generic +// struct (needsRuntimeLookup && CLASSPARAM) + +struct CORINFO_CONST_LOOKUP +{ + // If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field) + // Otherwise, it's a representative... + // If accessType is + // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address + // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle + // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle + // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle + + InfoAccessType accessType; + union + { + CORINFO_GENERIC_HANDLE handle; + void * addr; + }; +}; + +enum CORINFO_RUNTIME_LOOKUP_KIND +{ + CORINFO_LOOKUP_THISOBJ, + CORINFO_LOOKUP_METHODPARAM, + CORINFO_LOOKUP_CLASSPARAM, +}; + +struct CORINFO_LOOKUP_KIND +{ + bool needsRuntimeLookup; + CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind; + + // The 'runtimeLookupFlags' and 'runtimeLookupArgs' fields + // are just for internal VM / ZAP communication, not to be used by the JIT. + WORD runtimeLookupFlags; + void * runtimeLookupArgs; +} ; + + +// CORINFO_RUNTIME_LOOKUP indicates the details of the runtime lookup +// operation to be performed. +// +// CORINFO_MAXINDIRECTIONS is the maximum number of +// indirections used by runtime lookups. +// This accounts for up to 2 indirections to get at a dictionary followed by a possible spill slot +// +#define CORINFO_MAXINDIRECTIONS 4 +#define CORINFO_USEHELPER ((WORD) 0xffff) + +struct CORINFO_RUNTIME_LOOKUP +{ + // This is signature you must pass back to the runtime lookup helper + LPVOID signature; + + // Here is the helper you must call. It is one of CORINFO_HELP_RUNTIMEHANDLE_* helpers. + CorInfoHelpFunc helper; + + // Number of indirections to get there + // CORINFO_USEHELPER = don't know how to get it, so use helper function at run-time instead + // 0 = use the this pointer itself (e.g. token is C inside code in sealed class C) + // or method desc itself (e.g. token is method void M::mymeth() inside code in M::mymeth) + // Otherwise, follow each byte-offset stored in the "offsets[]" array (may be negative) + WORD indirections; + + // If set, test for null and branch to helper if null + bool testForNull; + + // If set, test the lowest bit and dereference if set (see code:FixupPointer) + bool testForFixup; + + SIZE_T offsets[CORINFO_MAXINDIRECTIONS]; + + // If set, first offset is indirect. + // 0 means that value stored at first offset (offsets[0]) from pointer is next pointer, to which the next offset + // (offsets[1]) is added and so on. + // 1 means that value stored at first offset (offsets[0]) from pointer is offset1, and the next pointer is + // stored at pointer+offsets[0]+offset1. + bool indirectFirstOffset; + + // If set, second offset is indirect. + // 0 means that value stored at second offset (offsets[1]) from pointer is next pointer, to which the next offset + // (offsets[2]) is added and so on. + // 1 means that value stored at second offset (offsets[1]) from pointer is offset2, and the next pointer is + // stored at pointer+offsets[1]+offset2. + bool indirectSecondOffset; +} ; + +// Result of calling embedGenericHandle +struct CORINFO_LOOKUP +{ + CORINFO_LOOKUP_KIND lookupKind; + + union + { + // If kind.needsRuntimeLookup then this indicates how to do the lookup + CORINFO_RUNTIME_LOOKUP runtimeLookup; + + // If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field) + // Otherwise, it's a representative... If accessType is + // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address + // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle + // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle + // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle + CORINFO_CONST_LOOKUP constLookup; + }; +}; + +enum CorInfoGenericHandleType +{ + CORINFO_HANDLETYPE_UNKNOWN, + CORINFO_HANDLETYPE_CLASS, + CORINFO_HANDLETYPE_METHOD, + CORINFO_HANDLETYPE_FIELD +}; + +//---------------------------------------------------------------------------- +// Embedding type, method and field handles (for "ldtoken" or to pass back to helpers) + +// Result of calling embedGenericHandle +struct CORINFO_GENERICHANDLE_RESULT +{ + CORINFO_LOOKUP lookup; + + // compileTimeHandle is guaranteed to be either NULL or a handle that is usable during compile time. + // It must not be embedded in the code because it might not be valid at run-time. + CORINFO_GENERIC_HANDLE compileTimeHandle; + + // Type of the result + CorInfoGenericHandleType handleType; +}; + +#define CORINFO_ACCESS_ALLOWED_MAX_ARGS 4 + +enum CorInfoAccessAllowedHelperArgType +{ + CORINFO_HELPER_ARG_TYPE_Invalid = 0, + CORINFO_HELPER_ARG_TYPE_Field = 1, + CORINFO_HELPER_ARG_TYPE_Method = 2, + CORINFO_HELPER_ARG_TYPE_Class = 3, + CORINFO_HELPER_ARG_TYPE_Module = 4, + CORINFO_HELPER_ARG_TYPE_Const = 5, +}; +struct CORINFO_HELPER_ARG +{ + union + { + CORINFO_FIELD_HANDLE fieldHandle; + CORINFO_METHOD_HANDLE methodHandle; + CORINFO_CLASS_HANDLE classHandle; + CORINFO_MODULE_HANDLE moduleHandle; + size_t constant; + }; + CorInfoAccessAllowedHelperArgType argType; + + void Set(CORINFO_METHOD_HANDLE handle) + { + argType = CORINFO_HELPER_ARG_TYPE_Method; + methodHandle = handle; + } + + void Set(CORINFO_FIELD_HANDLE handle) + { + argType = CORINFO_HELPER_ARG_TYPE_Field; + fieldHandle = handle; + } + + void Set(CORINFO_CLASS_HANDLE handle) + { + argType = CORINFO_HELPER_ARG_TYPE_Class; + classHandle = handle; + } + + void Set(size_t value) + { + argType = CORINFO_HELPER_ARG_TYPE_Const; + constant = value; + } +}; + +struct CORINFO_HELPER_DESC +{ + CorInfoHelpFunc helperNum; + unsigned numArgs; + CORINFO_HELPER_ARG args[CORINFO_ACCESS_ALLOWED_MAX_ARGS]; +}; + +//---------------------------------------------------------------------------- +// getCallInfo and CORINFO_CALL_INFO: The EE instructs the JIT about how to make a call +// +// callKind +// -------- +// +// CORINFO_CALL : +// Indicates that the JIT can use getFunctionEntryPoint to make a call, +// i.e. there is nothing abnormal about the call. The JITs know what to do if they get this. +// Except in the case of constraint calls (see below), [targetMethodHandle] will hold +// the CORINFO_METHOD_HANDLE that a call to findMethod would +// have returned. +// This flag may be combined with nullInstanceCheck=TRUE for uses of callvirt on methods that can +// be resolved at compile-time (non-virtual, final or sealed). +// +// CORINFO_CALL_CODE_POINTER (shared generic code only) : +// Indicates that the JIT should do an indirect call to the entrypoint given by address, which may be specified +// as a runtime lookup by CORINFO_CALL_INFO::codePointerLookup. +// [targetMethodHandle] will not hold a valid value. +// This flag may be combined with nullInstanceCheck=TRUE for uses of callvirt on methods whose target method can +// be resolved at compile-time but whose instantiation can be resolved only through runtime lookup. +// +// CORINFO_VIRTUALCALL_STUB (interface calls) : +// Indicates that the EE supports "stub dispatch" and request the JIT to make a +// "stub dispatch" call (an indirect call through CORINFO_CALL_INFO::stubLookup, +// similar to CORINFO_CALL_CODE_POINTER). +// "Stub dispatch" is a specialized calling sequence (that may require use of NOPs) +// which allow the runtime to determine the call-site after the call has been dispatched. +// If the call is too complex for the JIT (e.g. because +// fetching the dispatch stub requires a runtime lookup, i.e. lookupKind.needsRuntimeLookup +// is set) then the JIT is allowed to implement the call as if it were CORINFO_VIRTUALCALL_LDVIRTFTN +// [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would +// have returned. +// This flag is always accompanied by nullInstanceCheck=TRUE. +// +// CORINFO_VIRTUALCALL_LDVIRTFTN (virtual generic methods) : +// Indicates that the EE provides no way to implement the call directly and +// that the JIT should use a LDVIRTFTN sequence (as implemented by CORINFO_HELP_VIRTUAL_FUNC_PTR) +// followed by an indirect call. +// [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would +// have returned. +// This flag is always accompanied by nullInstanceCheck=TRUE though typically the null check will +// be implicit in the access through the instance pointer. +// +// CORINFO_VIRTUALCALL_VTABLE (regular virtual methods) : +// Indicates that the EE supports vtable dispatch and that the JIT should use getVTableOffset etc. +// to implement the call. +// [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would +// have returned. +// This flag is always accompanied by nullInstanceCheck=TRUE though typically the null check will +// be implicit in the access through the instance pointer. +// +// thisTransform and constraint calls +// ---------------------------------- +// +// For evertyhing besides "constrained." calls "thisTransform" is set to +// CORINFO_NO_THIS_TRANSFORM. +// +// For "constrained." calls the EE attempts to resolve the call at compile +// time to a more specific method, or (shared generic code only) to a runtime lookup +// for a code pointer for the more specific method. +// +// In order to permit this, the "this" pointer supplied for a "constrained." call +// is a byref to an arbitrary type (see the IL spec). The "thisTransform" field +// will indicate how the JIT must transform the "this" pointer in order +// to be able to call the resolved method: +// +// CORINFO_NO_THIS_TRANSFORM --> Leave it as a byref to an unboxed value type +// CORINFO_BOX_THIS --> Box it to produce an object +// CORINFO_DEREF_THIS --> Deref the byref to get an object reference +// +// In addition, the "kind" field will be set as follows for constraint calls: + +// CORINFO_CALL --> the call was resolved at compile time, and +// can be compiled like a normal call. +// CORINFO_CALL_CODE_POINTER --> the call was resolved, but the target address will be +// computed at runtime. Only returned for shared generic code. +// CORINFO_VIRTUALCALL_STUB, +// CORINFO_VIRTUALCALL_LDVIRTFTN, +// CORINFO_VIRTUALCALL_VTABLE --> usual values indicating that a virtual call must be made + +enum CORINFO_CALL_KIND +{ + CORINFO_CALL, + CORINFO_CALL_CODE_POINTER, + CORINFO_VIRTUALCALL_STUB, + CORINFO_VIRTUALCALL_LDVIRTFTN, + CORINFO_VIRTUALCALL_VTABLE +}; + +// Indicates that the CORINFO_VIRTUALCALL_VTABLE lookup needn't do a chunk indirection +#define CORINFO_VIRTUALCALL_NO_CHUNK 0xFFFFFFFF + +enum CORINFO_THIS_TRANSFORM +{ + CORINFO_NO_THIS_TRANSFORM, + CORINFO_BOX_THIS, + CORINFO_DEREF_THIS +}; + +enum CORINFO_CALLINFO_FLAGS +{ + CORINFO_CALLINFO_NONE = 0x0000, + CORINFO_CALLINFO_ALLOWINSTPARAM = 0x0001, // Can the compiler generate code to pass an instantiation parameters? Simple compilers should not use this flag + CORINFO_CALLINFO_CALLVIRT = 0x0002, // Is it a virtual call? + CORINFO_CALLINFO_KINDONLY = 0x0004, // This is set to only query the kind of call to perform, without getting any other information + CORINFO_CALLINFO_VERIFICATION = 0x0008, // Gets extra verification information. + CORINFO_CALLINFO_SECURITYCHECKS = 0x0010, // Perform security checks. + CORINFO_CALLINFO_LDFTN = 0x0020, // Resolving target of LDFTN + CORINFO_CALLINFO_ATYPICAL_CALLSITE = 0x0040, // Atypical callsite that cannot be disassembled by delay loading helper +}; + +enum CorInfoIsAccessAllowedResult +{ + CORINFO_ACCESS_ALLOWED = 0, // Call allowed + CORINFO_ACCESS_ILLEGAL = 1, // Call not allowed + CORINFO_ACCESS_RUNTIME_CHECK = 2, // Ask at runtime whether to allow the call or not +}; + + +// This enum is used for JIT to tell EE where this token comes from. +// E.g. Depending on different opcodes, we might allow/disallow certain types of tokens or +// return different types of handles (e.g. boxed vs. regular entrypoints) +enum CorInfoTokenKind +{ + CORINFO_TOKENKIND_Class = 0x01, + CORINFO_TOKENKIND_Method = 0x02, + CORINFO_TOKENKIND_Field = 0x04, + CORINFO_TOKENKIND_Mask = 0x07, + + // token comes from CEE_LDTOKEN + CORINFO_TOKENKIND_Ldtoken = 0x10 | CORINFO_TOKENKIND_Class | CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field, + + // token comes from CEE_CASTCLASS or CEE_ISINST + CORINFO_TOKENKIND_Casting = 0x20 | CORINFO_TOKENKIND_Class, + + // token comes from CEE_NEWARR + CORINFO_TOKENKIND_Newarr = 0x40 | CORINFO_TOKENKIND_Class, + + // token comes from CEE_BOX + CORINFO_TOKENKIND_Box = 0x80 | CORINFO_TOKENKIND_Class, + + // token comes from CEE_CONSTRAINED + CORINFO_TOKENKIND_Constrained = 0x100 | CORINFO_TOKENKIND_Class, + + // token comes from CEE_NEWOBJ + CORINFO_TOKENKIND_NewObj = 0x200 | CORINFO_TOKENKIND_Method, + + // token comes from CEE_LDVIRTFTN + CORINFO_TOKENKIND_Ldvirtftn = 0x400 | CORINFO_TOKENKIND_Method, +}; + +struct CORINFO_RESOLVED_TOKEN +{ + // + // [In] arguments of resolveToken + // + CORINFO_CONTEXT_HANDLE tokenContext; //Context for resolution of generic arguments + CORINFO_MODULE_HANDLE tokenScope; + mdToken token; //The source token + CorInfoTokenKind tokenType; + + // + // [Out] arguments of resolveToken. + // - Type handle is always non-NULL. + // - At most one of method and field handles is non-NULL (according to the token type). + // - Method handle is an instantiating stub only for generic methods. Type handle + // is required to provide the full context for methods in generic types. + // + CORINFO_CLASS_HANDLE hClass; + CORINFO_METHOD_HANDLE hMethod; + CORINFO_FIELD_HANDLE hField; + + // + // [Out] TypeSpec and MethodSpec signatures for generics. NULL otherwise. + // + PCCOR_SIGNATURE pTypeSpec; + ULONG cbTypeSpec; + PCCOR_SIGNATURE pMethodSpec; + ULONG cbMethodSpec; +}; + +struct CORINFO_CALL_INFO +{ + CORINFO_METHOD_HANDLE hMethod; //target method handle + unsigned methodFlags; //flags for the target method + + unsigned classFlags; //flags for CORINFO_RESOLVED_TOKEN::hClass + + CORINFO_SIG_INFO sig; + + //Verification information + unsigned verMethodFlags; // flags for CORINFO_RESOLVED_TOKEN::hMethod + CORINFO_SIG_INFO verSig; + //All of the regular method data is the same... hMethod might not be the same as CORINFO_RESOLVED_TOKEN::hMethod + + + //If set to: + // - CORINFO_ACCESS_ALLOWED - The access is allowed. + // - CORINFO_ACCESS_ILLEGAL - This access cannot be allowed (i.e. it is public calling private). The + // JIT may either insert the callsiteCalloutHelper into the code (as per a verification error) or + // call throwExceptionFromHelper on the callsiteCalloutHelper. In this case callsiteCalloutHelper + // is guaranteed not to return. + // - CORINFO_ACCESS_RUNTIME_CHECK - The jit must insert the callsiteCalloutHelper at the call site. + // the helper may return + CorInfoIsAccessAllowedResult accessAllowed; + CORINFO_HELPER_DESC callsiteCalloutHelper; + + // See above section on constraintCalls to understand when these are set to unusual values. + CORINFO_THIS_TRANSFORM thisTransform; + + CORINFO_CALL_KIND kind; + BOOL nullInstanceCheck; + + // Context for inlining and hidden arg + CORINFO_CONTEXT_HANDLE contextHandle; + BOOL exactContextNeedsRuntimeLookup; // Set if contextHandle is approx handle. Runtime lookup is required to get the exact handle. + + // If kind.CORINFO_VIRTUALCALL_STUB then stubLookup will be set. + // If kind.CORINFO_CALL_CODE_POINTER then entryPointLookup will be set. + union + { + CORINFO_LOOKUP stubLookup; + + CORINFO_LOOKUP codePointerLookup; + }; + + CORINFO_CONST_LOOKUP instParamLookup; // Used by Ready-to-Run + + BOOL secureDelegateInvoke; +}; + +//---------------------------------------------------------------------------- +// getFieldInfo and CORINFO_FIELD_INFO: The EE instructs the JIT about how to access a field + +enum CORINFO_FIELD_ACCESSOR +{ + CORINFO_FIELD_INSTANCE, // regular instance field at given offset from this-ptr + CORINFO_FIELD_INSTANCE_WITH_BASE, // instance field with base offset (used by Ready-to-Run) + CORINFO_FIELD_INSTANCE_HELPER, // instance field accessed using helper (arguments are this, FieldDesc * and the value) + CORINFO_FIELD_INSTANCE_ADDR_HELPER, // instance field accessed using address-of helper (arguments are this and FieldDesc *) + + CORINFO_FIELD_STATIC_ADDRESS, // field at given address + CORINFO_FIELD_STATIC_RVA_ADDRESS, // RVA field at given address + CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER, // static field accessed using the "shared static" helper (arguments are ModuleID + ClassID) + CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER, // static field access using the "generic static" helper (argument is MethodTable *) + CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *) + CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access + CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper + + CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero) + CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty) + CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian +}; + +// Set of flags returned in CORINFO_FIELD_INFO::fieldFlags +enum CORINFO_FIELD_FLAGS +{ + CORINFO_FLG_FIELD_STATIC = 0x00000001, + CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field + CORINFO_FLG_FIELD_FINAL = 0x00000004, + CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object + CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime) + CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field + CORINFO_FLG_FIELD_PROTECTED = 0x00000040, +}; + +struct CORINFO_FIELD_INFO +{ + CORINFO_FIELD_ACCESSOR fieldAccessor; + unsigned fieldFlags; + + // Helper to use if the field access requires it + CorInfoHelpFunc helper; + + // Field offset if there is one + DWORD offset; + + CorInfoType fieldType; + CORINFO_CLASS_HANDLE structType; //possibly null + + //See CORINFO_CALL_INFO.accessAllowed + CorInfoIsAccessAllowedResult accessAllowed; + CORINFO_HELPER_DESC accessCalloutHelper; + + CORINFO_CONST_LOOKUP fieldLookup; // Used by Ready-to-Run +}; + +//---------------------------------------------------------------------------- +// Exception handling + +struct CORINFO_EH_CLAUSE +{ + CORINFO_EH_CLAUSE_FLAGS Flags; + DWORD TryOffset; + DWORD TryLength; + DWORD HandlerOffset; + DWORD HandlerLength; + union + { + DWORD ClassToken; // use for type-based exception handlers + DWORD FilterOffset; // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set) + }; +}; + +enum CORINFO_OS +{ + CORINFO_WINNT, + CORINFO_PAL, +}; + +struct CORINFO_CPU +{ + DWORD dwCPUType; + DWORD dwFeatures; + DWORD dwExtendedFeatures; +}; + +enum CORINFO_RUNTIME_ABI +{ + CORINFO_DESKTOP_ABI = 0x100, + CORINFO_CORECLR_ABI = 0x200, + CORINFO_CORERT_ABI = 0x300, +}; + +// For some highly optimized paths, the JIT must generate code that directly +// manipulates internal EE data structures. The getEEInfo() helper returns +// this structure containing the needed offsets and values. +struct CORINFO_EE_INFO +{ + // Information about the InlinedCallFrame structure layout + struct InlinedCallFrameInfo + { + // Size of the Frame structure + unsigned size; + + unsigned offsetOfGSCookie; + unsigned offsetOfFrameVptr; + unsigned offsetOfFrameLink; + unsigned offsetOfCallSiteSP; + unsigned offsetOfCalleeSavedFP; + unsigned offsetOfCallTarget; + unsigned offsetOfReturnAddress; + // This offset is used only for ARM + unsigned offsetOfSPAfterProlog; + } + inlinedCallFrameInfo; + + // Offsets into the Thread structure + unsigned offsetOfThreadFrame; // offset of the current Frame + unsigned offsetOfGCState; // offset of the preemptive/cooperative state of the Thread + + // Delegate offsets + unsigned offsetOfDelegateInstance; + unsigned offsetOfDelegateFirstTarget; + + // Secure delegate offsets + unsigned offsetOfSecureDelegateIndirectCell; + + // Remoting offsets + unsigned offsetOfTransparentProxyRP; + unsigned offsetOfRealProxyServer; + + // Array offsets + unsigned offsetOfObjArrayData; + + // Reverse PInvoke offsets + unsigned sizeOfReversePInvokeFrame; + + // OS Page size + size_t osPageSize; + + // Null object offset + size_t maxUncheckedOffsetForNullObject; + + // Target ABI. Combined with target architecture and OS to determine + // GC, EH, and unwind styles. + CORINFO_RUNTIME_ABI targetAbi; + + CORINFO_OS osType; + unsigned osMajor; + unsigned osMinor; + unsigned osBuild; +}; + +// This is used to indicate that a finally has been called +// "locally" by the try block +enum { LCL_FINALLY_MARK = 0xFC }; // FC = "Finally Call" + +/********************************************************************************** + * The following is the internal structure of an object that the compiler knows about + * when it generates code + **********************************************************************************/ + +#include + +typedef void* CORINFO_MethodPtr; // a generic method pointer + +struct CORINFO_Object +{ + CORINFO_MethodPtr *methTable; // the vtable for the object +}; + +struct CORINFO_String : public CORINFO_Object +{ + unsigned stringLen; + wchar_t chars[1]; // actually of variable size +}; + +struct CORINFO_Array : public CORINFO_Object +{ + unsigned length; +#ifdef _WIN64 + unsigned alignpad; +#endif // _WIN64 + +#if 0 + /* Multi-dimensional arrays have the lengths and bounds here */ + unsigned dimLength[length]; + unsigned dimBound[length]; +#endif + + union + { + __int8 i1Elems[1]; // actually of variable size + unsigned __int8 u1Elems[1]; + __int16 i2Elems[1]; + unsigned __int16 u2Elems[1]; + __int32 i4Elems[1]; + unsigned __int32 u4Elems[1]; + float r4Elems[1]; + }; +}; + +#include +struct CORINFO_Array8 : public CORINFO_Object +{ + unsigned length; +#ifdef _WIN64 + unsigned alignpad; +#endif // _WIN64 + + union + { + double r8Elems[1]; + __int64 i8Elems[1]; + unsigned __int64 u8Elems[1]; + }; +}; + +#include + +struct CORINFO_RefArray : public CORINFO_Object +{ + unsigned length; +#ifdef _WIN64 + unsigned alignpad; +#endif // _WIN64 + +#if 0 + /* Multi-dimensional arrays have the lengths and bounds here */ + unsigned dimLength[length]; + unsigned dimBound[length]; +#endif + + CORINFO_Object* refElems[1]; // actually of variable size; +}; + +struct CORINFO_RefAny +{ + void * dataPtr; + CORINFO_CLASS_HANDLE type; +}; + +// The jit assumes the CORINFO_VARARGS_HANDLE is a pointer to a subclass of this +struct CORINFO_VarArgInfo +{ + unsigned argBytes; // number of bytes the arguments take up. + // (The CORINFO_VARARGS_HANDLE counts as an arg) +}; + +#include + +#define SIZEOF__CORINFO_Object TARGET_POINTER_SIZE /* methTable */ + +#define OFFSETOF__CORINFO_Array__length SIZEOF__CORINFO_Object +#ifdef _TARGET_64BIT_ +#define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */ + sizeof(unsigned __int32) /* alignpad */) +#else +#define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */) +#endif + +#define OFFSETOF__CORINFO_TypedReference__dataPtr 0 +#define OFFSETOF__CORINFO_TypedReference__type (OFFSETOF__CORINFO_TypedReference__dataPtr + TARGET_POINTER_SIZE /* dataPtr */) + +#define OFFSETOF__CORINFO_String__stringLen SIZEOF__CORINFO_Object +#define OFFSETOF__CORINFO_String__chars (OFFSETOF__CORINFO_String__stringLen + sizeof(unsigned __int32) /* stringLen */) + +enum CorInfoSecurityRuntimeChecks +{ + CORINFO_ACCESS_SECURITY_NONE = 0, + CORINFO_ACCESS_SECURITY_TRANSPARENCY = 0x0001 // check that transparency rules are enforced between the caller and callee +}; + + +/* data to optimize delegate construction */ +struct DelegateCtorArgs +{ + void * pMethod; + void * pArg3; + void * pArg4; + void * pArg5; +}; + +// use offsetof to get the offset of the fields above +#include // offsetof + +// Guard-stack cookie for preventing against stack buffer overruns +typedef SIZE_T GSCookie; + +#include "cordebuginfo.h" + +/**********************************************************************************/ +// Some compilers cannot arbitrarily allow the handler nesting level to grow +// arbitrarily during Edit'n'Continue. +// This is the maximum nesting level that a compiler needs to support for EnC + +const int MAX_EnC_HANDLER_NESTING_LEVEL = 6; + +// Results from type comparison queries +enum class TypeCompareState +{ + MustNot = -1, // types are not equal + May = 0, // types may be equal (must test at runtime) + Must = 1, // type are equal +}; + +// +// This interface is logically split into sections for each class of information +// (ICorMethodInfo, ICorModuleInfo, etc.). This split used to exist physically as well +// using virtual inheritance, but was eliminated to improve efficiency of the JIT-EE +// interface calls. +// +class ICorStaticInfo +{ +public: + /**********************************************************************************/ + // + // ICorMethodInfo + // + /**********************************************************************************/ + + // return flags (defined above, CORINFO_FLG_PUBLIC ...) + virtual DWORD getMethodAttribs ( + CORINFO_METHOD_HANDLE ftn /* IN */ + ) = 0; + + // sets private JIT flags, which can be, retrieved using getAttrib. + virtual void setMethodAttribs ( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CorInfoMethodRuntimeFlags attribs /* IN */ + ) = 0; + + // Given a method descriptor ftnHnd, extract signature information into sigInfo + // + // 'memberParent' is typically only set when verifying. It should be the + // result of calling getMemberParent. + virtual void getMethodSig ( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_SIG_INFO *sig, /* OUT */ + CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ + ) = 0; + + /********************************************************************* + * Note the following methods can only be used on functions known + * to be IL. This includes the method being compiled and any method + * that 'getMethodInfo' returns true for + *********************************************************************/ + + // return information about a method private to the implementation + // returns false if method is not IL, or is otherwise unavailable. + // This method is used to fetch data needed to inline functions + virtual bool getMethodInfo ( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_METHOD_INFO* info /* OUT */ + ) = 0; + + // Decides if you have any limitations for inlining. If everything's OK, it will return + // INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this + // function must respect. If caller passes pRestrictions = NULL, if there are any restrictions + // INLINE_FAIL will be returned + // + // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls) + // + // The inlined method need not be verified + + virtual CorInfoInline canInline ( + CORINFO_METHOD_HANDLE callerHnd, /* IN */ + CORINFO_METHOD_HANDLE calleeHnd, /* IN */ + DWORD* pRestrictions /* OUT */ + ) = 0; + + // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all + // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the + // JIT. + virtual void reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, + CORINFO_METHOD_HANDLE inlineeHnd, + CorInfoInline inlineResult, + const char * reason) = 0; + + + // Returns false if the call is across security boundaries thus we cannot tailcall + // + // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls) + virtual bool canTailCall ( + CORINFO_METHOD_HANDLE callerHnd, /* IN */ + CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */ + CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */ + bool fIsTailPrefix /* IN */ + ) = 0; + + // Reports whether or not a method can be tail called, and why. + // canTailCall is responsible for reporting all results when it returns + // false. All other results are reported by the JIT. + virtual void reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, + CORINFO_METHOD_HANDLE calleeHnd, + bool fIsTailPrefix, + CorInfoTailCall tailCallResult, + const char * reason) = 0; + + // get individual exception handler + virtual void getEHinfo( + CORINFO_METHOD_HANDLE ftn, /* IN */ + unsigned EHnumber, /* IN */ + CORINFO_EH_CLAUSE* clause /* OUT */ + ) = 0; + + // return class it belongs to + virtual CORINFO_CLASS_HANDLE getMethodClass ( + CORINFO_METHOD_HANDLE method + ) = 0; + + // return module it belongs to + virtual CORINFO_MODULE_HANDLE getMethodModule ( + CORINFO_METHOD_HANDLE method + ) = 0; + + // This function returns the offset of the specified method in the + // vtable of it's owning class or interface. + virtual void getMethodVTableOffset ( + CORINFO_METHOD_HANDLE method, /* IN */ + unsigned* offsetOfIndirection, /* OUT */ + unsigned* offsetAfterIndirection, /* OUT */ + bool* isRelative /* OUT */ + ) = 0; + + // Find the virtual method in implementingClass that overrides virtualMethod, + // or the method in implementingClass that implements the interface method + // represented by virtualMethod. + // + // Return null if devirtualization is not possible. Owner type is optional + // and provides additional context for shared interface devirtualization. + virtual CORINFO_METHOD_HANDLE resolveVirtualMethod( + CORINFO_METHOD_HANDLE virtualMethod, /* IN */ + CORINFO_CLASS_HANDLE implementingClass, /* IN */ + CORINFO_CONTEXT_HANDLE ownerType = NULL /* IN */ + ) = 0; + + // Get the unboxed entry point for a method, if possible. + virtual CORINFO_METHOD_HANDLE getUnboxedEntry( + CORINFO_METHOD_HANDLE ftn, + bool* requiresInstMethodTableArg = NULL /* OUT */ + ) = 0; + + // Given T, return the type of the default EqualityComparer. + // Returns null if the type can't be determined exactly. + virtual CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass( + CORINFO_CLASS_HANDLE elemType + ) = 0; + + // Given resolved token that corresponds to an intrinsic classified as + // a CORINFO_INTRINSIC_GetRawHandle intrinsic, fetch the handle associated + // with the token. If this is not possible at compile-time (because the current method's + // code is shared and the token contains generic parameters) then indicate + // how the handle should be looked up at runtime. + virtual void expandRawHandleIntrinsic( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_GENERICHANDLE_RESULT * pResult) = 0; + + // If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set, + // getIntrinsicID() returns the intrinsic ID. + // *pMustExpand tells whether or not JIT must expand the intrinsic. + virtual CorInfoIntrinsics getIntrinsicID( + CORINFO_METHOD_HANDLE method, + bool* pMustExpand = NULL /* OUT */ + ) = 0; + + // Is the given module the System.Numerics.Vectors module? + // This defaults to false. + virtual bool isInSIMDModule( + CORINFO_CLASS_HANDLE classHnd + ) { return false; } + + // return the unmanaged calling convention for a PInvoke + virtual CorInfoUnmanagedCallConv getUnmanagedCallConv( + CORINFO_METHOD_HANDLE method + ) = 0; + + // return if any marshaling is required for PInvoke methods. Note that + // method == 0 => calli. The call site sig is only needed for the varargs or calli case + virtual BOOL pInvokeMarshalingRequired( + CORINFO_METHOD_HANDLE method, + CORINFO_SIG_INFO* callSiteSig + ) = 0; + + // Check constraints on method type arguments (only). + // The parent class should be checked separately using satisfiesClassConstraints(parent). + virtual BOOL satisfiesMethodConstraints( + CORINFO_CLASS_HANDLE parent, // the exact parent of the method + CORINFO_METHOD_HANDLE method + ) = 0; + + // Given a delegate target class, a target method parent class, a target method, + // a delegate class, check if the method signature is compatible with the Invoke method of the delegate + // (under the typical instantiation of any free type variables in the memberref signatures). + virtual BOOL isCompatibleDelegate( + CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */ + CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */ + CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */ + CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */ + BOOL *pfIsOpenDelegate /* is the delegate open */ + ) = 0; + + // Indicates if the method is an instance of the generic + // method that passes (or has passed) verification + virtual CorInfoInstantiationVerification isInstantiationOfVerifiedGeneric ( + CORINFO_METHOD_HANDLE method /* IN */ + ) = 0; + + // Loads the constraints on a typical method definition, detecting cycles; + // for use in verification. + virtual void initConstraintsForVerification( + CORINFO_METHOD_HANDLE method, /* IN */ + BOOL *pfHasCircularClassConstraints, /* OUT */ + BOOL *pfHasCircularMethodConstraint /* OUT */ + ) = 0; + + // Returns enum whether the method does not require verification + // Also see ICorModuleInfo::canSkipVerification + virtual CorInfoCanSkipVerificationResult canSkipMethodVerification ( + CORINFO_METHOD_HANDLE ftnHandle + ) = 0; + + // load and restore the method + virtual void methodMustBeLoadedBeforeCodeIsRun( + CORINFO_METHOD_HANDLE method + ) = 0; + + virtual CORINFO_METHOD_HANDLE mapMethodDeclToMethodImpl( + CORINFO_METHOD_HANDLE method + ) = 0; + + // Returns the global cookie for the /GS unsafe buffer checks + // The cookie might be a constant value (JIT), or a handle to memory location (Ngen) + virtual void getGSCookie( + GSCookie * pCookieVal, // OUT + GSCookie ** ppCookieVal // OUT + ) = 0; + + /**********************************************************************************/ + // + // ICorModuleInfo + // + /**********************************************************************************/ + + // Resolve metadata token into runtime method handles. This function may not + // return normally (e.g. it may throw) if it encounters invalid metadata or other + // failures during token resolution. + virtual void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; + + // Attempt to resolve a metadata token into a runtime method handle. Returns true + // if resolution succeeded and false otherwise (e.g. if it encounters invalid metadata + // during token reoslution). This method should be used instead of `resolveToken` in + // situations that need to be resilient to invalid metadata. + virtual bool tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; + + // Signature information about the call sig + virtual void findSig ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned sigTOK, /* IN */ + CORINFO_CONTEXT_HANDLE context, /* IN */ + CORINFO_SIG_INFO *sig /* OUT */ + ) = 0; + + // for Varargs, the signature at the call site may differ from + // the signature at the definition. Thus we need a way of + // fetching the call site information + virtual void findCallSiteSig ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned methTOK, /* IN */ + CORINFO_CONTEXT_HANDLE context, /* IN */ + CORINFO_SIG_INFO *sig /* OUT */ + ) = 0; + + virtual CORINFO_CLASS_HANDLE getTokenTypeAsHandle ( + CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */) = 0; + + // Returns true if the module does not require verification + // + // If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the + // module does not currently require verification in the current AppDomain. + // This decision could change in the future, and so should not be cached. + // If it is cached, it should only be used as a hint. + // This is only used by ngen for calculating certain hints. + // + + // Returns enum whether the module does not require verification + // Also see ICorMethodInfo::canSkipMethodVerification(); + virtual CorInfoCanSkipVerificationResult canSkipVerification ( + CORINFO_MODULE_HANDLE module /* IN */ + ) = 0; + + // Checks if the given metadata token is valid + virtual BOOL isValidToken ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK /* IN */ + ) = 0; + + // Checks if the given metadata token is valid StringRef + virtual BOOL isValidStringRef ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK /* IN */ + ) = 0; + + virtual BOOL shouldEnforceCallvirtRestriction( + CORINFO_MODULE_HANDLE scope + ) = 0; + + /**********************************************************************************/ + // + // ICorClassInfo + // + /**********************************************************************************/ + + // If the value class 'cls' is isomorphic to a primitive type it will + // return that type, otherwise it will return CORINFO_TYPE_VALUECLASS + virtual CorInfoType asCorInfoType ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // for completeness + virtual const char* getClassName ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Return class name as in metadata, or nullptr if there is none. + // Suitable for non-debugging use. + virtual const char* getClassNameFromMetadata ( + CORINFO_CLASS_HANDLE cls, + const char **namespaceName /* OUT */ + ) = 0; + + // Return the type argument of the instantiated generic class, + // which is specified by the index + virtual CORINFO_CLASS_HANDLE getTypeInstantiationArgument( + CORINFO_CLASS_HANDLE cls, + unsigned index + ) = 0; + + + // Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen + // If fNamespace=TRUE, include the namespace/enclosing classes + // If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters + // If fAssembly=TRUE, suffix with a comma and the full assembly qualification + // return size of representation + virtual int appendClassName( + __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf, + int* pnBufLen, + CORINFO_CLASS_HANDLE cls, + BOOL fNamespace, + BOOL fFullInst, + BOOL fAssembly + ) = 0; + + // Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) & CORINFO_FLG_VALUECLASS, except faster. + virtual BOOL isValueClass(CORINFO_CLASS_HANDLE cls) = 0; + + // Decides how the JIT should do the optimization to inline the check for + // GetTypeFromHandle(handle) == obj.GetType() (for CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE) + // GetTypeFromHandle(X) == GetTypeFromHandle(Y) (for CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN) + virtual CorInfoInlineTypeCheck canInlineTypeCheck(CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) = 0; + + // If this method returns true, JIT will do optimization to inline the check for + // GetTypeFromHandle(handle) == obj.GetType() + virtual BOOL canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls) = 0; + + // return flags (defined above, CORINFO_FLG_PUBLIC ...) + virtual DWORD getClassAttribs ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value + // of this type must be stack-allocated. This will generally be true only if the struct + // contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows + // an optimization: the JIT may assume that return buffer pointers for return types for which this predicate + // returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return + // buffers do not require GC write barriers. + virtual BOOL isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls) = 0; + + virtual CORINFO_MODULE_HANDLE getClassModule ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Returns the assembly that contains the module "mod". + virtual CORINFO_ASSEMBLY_HANDLE getModuleAssembly ( + CORINFO_MODULE_HANDLE mod + ) = 0; + + // Returns the name of the assembly "assem". + virtual const char* getAssemblyName ( + CORINFO_ASSEMBLY_HANDLE assem + ) = 0; + + // Allocate and delete process-lifetime objects. Should only be + // referred to from static fields, lest a leak occur. + // Note that "LongLifetimeFree" does not execute destructors, if "obj" + // is an array of a struct type with a destructor. + virtual void* LongLifetimeMalloc(size_t sz) = 0; + virtual void LongLifetimeFree(void* obj) = 0; + + virtual size_t getClassModuleIdForStatics ( + CORINFO_CLASS_HANDLE cls, + CORINFO_MODULE_HANDLE *pModule, + void **ppIndirection + ) = 0; + + // return the number of bytes needed by an instance of the class + virtual unsigned getClassSize ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // return the number of bytes needed by an instance of the class allocated on the heap + virtual unsigned getHeapClassSize( + CORINFO_CLASS_HANDLE cls + ) = 0; + + virtual BOOL canAllocateOnStack( + CORINFO_CLASS_HANDLE cls + ) = 0; + + virtual unsigned getClassAlignmentRequirement ( + CORINFO_CLASS_HANDLE cls, + BOOL fDoubleAlignHint = FALSE + ) = 0; + + // This is only called for Value classes. It returns a boolean array + // in representing of 'cls' from a GC perspective. The class is + // assumed to be an array of machine words + // (of length // getClassSize(cls) / TARGET_POINTER_SIZE), + // 'gcPtrs' is a pointer to an array of BYTEs of this length. + // getClassGClayout fills in this array so that gcPtrs[i] is set + // to one of the CorInfoGCType values which is the GC type of + // the i-th machine word of an object of type 'cls' + // returns the number of GC pointers in the array + virtual unsigned getClassGClayout ( + CORINFO_CLASS_HANDLE cls, /* IN */ + BYTE *gcPtrs /* OUT */ + ) = 0; + + // returns the number of instance fields in a class + virtual unsigned getClassNumInstanceFields ( + CORINFO_CLASS_HANDLE cls /* IN */ + ) = 0; + + virtual CORINFO_FIELD_HANDLE getFieldInClass( + CORINFO_CLASS_HANDLE clsHnd, + INT num + ) = 0; + + virtual BOOL checkMethodModifier( + CORINFO_METHOD_HANDLE hMethod, + LPCSTR modifier, + BOOL fOptional + ) = 0; + + // returns the "NEW" helper optimized for "newCls." + virtual CorInfoHelpFunc getNewHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + bool * pHasSideEffects = NULL /* OUT */ + ) = 0; + + // returns the newArr (1-Dim array) helper optimized for "arrayCls." + virtual CorInfoHelpFunc getNewArrHelper( + CORINFO_CLASS_HANDLE arrayCls + ) = 0; + + // returns the optimized "IsInstanceOf" or "ChkCast" helper + virtual CorInfoHelpFunc getCastingHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fThrowing + ) = 0; + + // returns helper to trigger static constructor + virtual CorInfoHelpFunc getSharedCCtorHelper( + CORINFO_CLASS_HANDLE clsHnd + ) = 0; + + virtual CorInfoHelpFunc getSecurityPrologHelper( + CORINFO_METHOD_HANDLE ftn + ) = 0; + + // This is not pretty. Boxing nullable actually returns + // a boxed not a boxed Nullable. This call allows the verifier + // to call back to the EE on the 'box' instruction and get the transformed + // type to use for verification. + virtual CORINFO_CLASS_HANDLE getTypeForBox( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // returns the correct box helper for a particular class. Note + // that if this returns CORINFO_HELP_BOX, the JIT can assume + // 'standard' boxing (allocate object and copy), and optimize + virtual CorInfoHelpFunc getBoxHelper( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // returns the unbox helper. If 'helperCopies' points to a true + // value it means the JIT is requesting a helper that unboxes the + // value into a particular location and thus has the signature + // void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj) + // Otherwise (it is null or points at a FALSE value) it is requesting + // a helper that returns a pointer to the unboxed data + // void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj) + // The EE has the option of NOT returning the copy style helper + // (But must be able to always honor the non-copy style helper) + // The EE set 'helperCopies' on return to indicate what kind of + // helper has been created. + + virtual CorInfoHelpFunc getUnBoxHelper( + CORINFO_CLASS_HANDLE cls + ) = 0; + + virtual bool getReadyToRunHelper( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_LOOKUP_KIND * pGenericLookupKind, + CorInfoHelpFunc id, + CORINFO_CONST_LOOKUP * pLookup + ) = 0; + + virtual void getReadyToRunDelegateCtorHelper( + CORINFO_RESOLVED_TOKEN * pTargetMethod, + CORINFO_CLASS_HANDLE delegateType, + CORINFO_LOOKUP * pLookup + ) = 0; + + virtual const char* getHelperName( + CorInfoHelpFunc + ) = 0; + + // This function tries to initialize the class (run the class constructor). + // this function returns whether the JIT must insert helper calls before + // accessing static field or method. + // + // See code:ICorClassInfo#ClassConstruction. + virtual CorInfoInitClassResult initClass( + CORINFO_FIELD_HANDLE field, // Non-NULL - inquire about cctor trigger before static field access + // NULL - inquire about cctor trigger in method prolog + CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog + CORINFO_CONTEXT_HANDLE context, // Exact context of method + BOOL speculative = FALSE // TRUE means don't actually run it + ) = 0; + + // This used to be called "loadClass". This records the fact + // that the class must be loaded (including restored if necessary) before we execute the + // code that we are currently generating. When jitting code + // the function loads the class immediately. When zapping code + // the zapper will if necessary use the call to record the fact that we have + // to do a fixup/restore before running the method currently being generated. + // + // This is typically used to ensure value types are loaded before zapped + // code that manipulates them is executed, so that the GC can access information + // about those value types. + virtual void classMustBeLoadedBeforeCodeIsRun( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // returns the class handle for the special builtin classes + virtual CORINFO_CLASS_HANDLE getBuiltinClass ( + CorInfoClassId classId + ) = 0; + + // "System.Int32" ==> CORINFO_TYPE_INT.. + virtual CorInfoType getTypeForPrimitiveValueClass( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // "System.Int32" ==> CORINFO_TYPE_INT.. + // "System.UInt32" ==> CORINFO_TYPE_UINT.. + virtual CorInfoType getTypeForPrimitiveNumericClass( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // TRUE if child is a subtype of parent + // if parent is an interface, then does child implement / extend parent + virtual BOOL canCast( + CORINFO_CLASS_HANDLE child, // subtype (extends parent) + CORINFO_CLASS_HANDLE parent // base type + ) = 0; + + // TRUE if cls1 and cls2 are considered equivalent types. + virtual BOOL areTypesEquivalent( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2 + ) = 0; + + // See if a cast from fromClass to toClass will succeed, fail, or needs + // to be resolved at runtime. + virtual TypeCompareState compareTypesForCast( + CORINFO_CLASS_HANDLE fromClass, + CORINFO_CLASS_HANDLE toClass + ) = 0; + + // See if types represented by cls1 and cls2 compare equal, not + // equal, or the comparison needs to be resolved at runtime. + virtual TypeCompareState compareTypesForEquality( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2 + ) = 0; + + // Returns the intersection of cls1 and cls2. + virtual CORINFO_CLASS_HANDLE mergeClasses( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2 + ) = 0; + + // Returns true if cls2 is known to be a more specific type + // than cls1 (a subtype or more restrictive shared type) + // for purposes of jit type tracking. This is a hint to the + // jit for optimization; it does not have correctness + // implications. + virtual BOOL isMoreSpecificType( + CORINFO_CLASS_HANDLE cls1, + CORINFO_CLASS_HANDLE cls2 + ) = 0; + + // Given a class handle, returns the Parent type. + // For COMObjectType, it returns Class Handle of System.Object. + // Returns 0 if System.Object is passed in. + virtual CORINFO_CLASS_HANDLE getParentType ( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Returns the CorInfoType of the "child type". If the child type is + // not a primitive type, *clsRet will be set. + // Given an Array of Type Foo, returns Foo. + // Given BYREF Foo, returns Foo + virtual CorInfoType getChildType ( + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_CLASS_HANDLE *clsRet + ) = 0; + + // Check constraints on type arguments of this class and parent classes + virtual BOOL satisfiesClassConstraints( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Check if this is a single dimensional array type + virtual BOOL isSDArray( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Get the numbmer of dimensions in an array + virtual unsigned getArrayRank( + CORINFO_CLASS_HANDLE cls + ) = 0; + + // Get static field data for an array + virtual void * getArrayInitializationData( + CORINFO_FIELD_HANDLE field, + DWORD size + ) = 0; + + // Check Visibility rules. + virtual CorInfoIsAccessAllowedResult canAccessClass( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_HELPER_DESC *pAccessHelper /* If canAccessMethod returns something other + than ALLOWED, then this is filled in. */ + ) = 0; + + /**********************************************************************************/ + // + // ICorFieldInfo + // + /**********************************************************************************/ + + // this function is for debugging only. It returns the field name + // and if 'moduleName' is non-null, it sets it to something that will + // says which method (a class name, or a module name) + virtual const char* getFieldName ( + CORINFO_FIELD_HANDLE ftn, /* IN */ + const char **moduleName /* OUT */ + ) = 0; + + // return class it belongs to + virtual CORINFO_CLASS_HANDLE getFieldClass ( + CORINFO_FIELD_HANDLE field + ) = 0; + + // Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set + // the field's value class (if 'structType' == 0, then don't bother + // the structure info). + // + // 'memberParent' is typically only set when verifying. It should be the + // result of calling getMemberParent. + virtual CorInfoType getFieldType( + CORINFO_FIELD_HANDLE field, + CORINFO_CLASS_HANDLE *structType = NULL, + CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ + ) = 0; + + // return the data member's instance offset + virtual unsigned getFieldOffset( + CORINFO_FIELD_HANDLE field + ) = 0; + + // TODO: jit64 should be switched to the same plan as the i386 jits - use + // getClassGClayout to figure out the need for writebarrier helper, and inline the copying. + // The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS + virtual bool isWriteBarrierHelperRequired( + CORINFO_FIELD_HANDLE field) = 0; + + virtual void getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, + CORINFO_METHOD_HANDLE callerHandle, + CORINFO_ACCESS_FLAGS flags, + CORINFO_FIELD_INFO *pResult + ) = 0; + + // Returns true iff "fldHnd" represents a static field. + virtual bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) = 0; + + /*********************************************************************************/ + // + // ICorDebugInfo + // + /*********************************************************************************/ + + // Query the EE to find out where interesting break points + // in the code are. The native compiler will ensure that these places + // have a corresponding break point in native code. + // + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will + // be used only as a hint and the native compiler should not change its + // code generation. + virtual void getBoundaries( + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + unsigned int *cILOffsets, // [OUT] size of pILOffsets + DWORD **pILOffsets, // [OUT] IL offsets of interest + // jit MUST free with freeArray! + ICorDebugInfo::BoundaryTypes *implictBoundaries // [OUT] tell jit, all boundries of this type + ) = 0; + + // Report back the mapping from IL to native code, + // this map should include all boundaries that 'getBoundaries' + // reported as interesting to the debugger. + + // Note that debugger (and profiler) is assuming that all of the + // offsets form a contiguous block of memory, and that the + // OffsetMapping is sorted in order of increasing native offset. + virtual void setBoundaries( + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + ULONG32 cMap, // [IN] size of pMap + ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest. + // jit allocated with allocateArray, EE frees + ) = 0; + + // Query the EE to find out the scope of local varables. + // normally the JIT would trash variables after last use, but + // under debugging, the JIT needs to keep them live over their + // entire scope so that they can be inspected. + // + // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will + // be used only as a hint and the native compiler should not change its + // code generation. + virtual void getVars( + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + ULONG32 *cVars, // [OUT] size of 'vars' + ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest + // jit MUST free with freeArray! + bool *extendOthers // [OUT] it TRUE, then assume the scope + // of unmentioned vars is entire method + ) = 0; + + // Report back to the EE the location of every variable. + // note that the JIT might split lifetimes into different + // locations etc. + + virtual void setVars( + CORINFO_METHOD_HANDLE ftn, // [IN] method of interest + ULONG32 cVars, // [IN] size of 'vars' + ICorDebugInfo::NativeVarInfo *vars // [IN] map telling where local vars are stored at what points + // jit allocated with allocateArray, EE frees + ) = 0; + + /*-------------------------- Misc ---------------------------------------*/ + + // Used to allocate memory that needs to handed to the EE. + // For eg, use this to allocated memory for reporting debug info, + // which will be handed to the EE by setVars() and setBoundaries() + virtual void * allocateArray( + ULONG cBytes + ) = 0; + + // JitCompiler will free arrays passed by the EE using this + // For eg, The EE returns memory in getVars() and getBoundaries() + // to the JitCompiler, which the JitCompiler should release using + // freeArray() + virtual void freeArray( + void *array + ) = 0; + + /*********************************************************************************/ + // + // ICorArgInfo + // + /*********************************************************************************/ + + // advance the pointer to the argument list. + // a ptr of 0, is special and always means the first argument + virtual CORINFO_ARG_LIST_HANDLE getArgNext ( + CORINFO_ARG_LIST_HANDLE args /* IN */ + ) = 0; + + // Get the type of a particular argument + // CORINFO_TYPE_UNDEF is returned when there are no more arguments + // If the type returned is a primitive type (or an enum) *vcTypeRet set to NULL + // otherwise it is set to the TypeHandle associted with the type + // Enumerations will always look their underlying type (probably should fix this) + // Otherwise vcTypeRet is the type as would be seen by the IL, + // The return value is the type that is used for calling convention purposes + // (Thus if the EE wants a value class to be passed like an int, then it will + // return CORINFO_TYPE_INT + virtual CorInfoTypeWithMod getArgType ( + CORINFO_SIG_INFO* sig, /* IN */ + CORINFO_ARG_LIST_HANDLE args, /* IN */ + CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */ + ) = 0; + + // If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it + virtual CORINFO_CLASS_HANDLE getArgClass ( + CORINFO_SIG_INFO* sig, /* IN */ + CORINFO_ARG_LIST_HANDLE args /* IN */ + ) = 0; + + // Returns type of HFA for valuetype + virtual CorInfoType getHFAType ( + CORINFO_CLASS_HANDLE hClass + ) = 0; + + /***************************************************************************** + * ICorErrorInfo contains methods to deal with SEH exceptions being thrown + * from the corinfo interface. These methods may be called when an exception + * with code EXCEPTION_COMPLUS is caught. + *****************************************************************************/ + + // Returns the HRESULT of the current exception + virtual HRESULT GetErrorHRESULT( + struct _EXCEPTION_POINTERS *pExceptionPointers + ) = 0; + + // Fetches the message of the current exception + // Returns the size of the message (including terminating null). This can be + // greater than bufferLength if the buffer is insufficient. + virtual ULONG GetErrorMessage( + __inout_ecount(bufferLength) LPWSTR buffer, + ULONG bufferLength + ) = 0; + + // returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the + // exception, abort some work (like the inlining) and continue compilation + // returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE + // things like ThreadStoppedException ... + // returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE + + virtual int FilterException( + struct _EXCEPTION_POINTERS *pExceptionPointers + ) = 0; + + // Cleans up internal EE tracking when an exception is caught. + virtual void HandleException( + struct _EXCEPTION_POINTERS *pExceptionPointers + ) = 0; + + virtual void ThrowExceptionForJitResult( + HRESULT result) = 0; + + //Throws an exception defined by the given throw helper. + virtual void ThrowExceptionForHelper( + const CORINFO_HELPER_DESC * throwHelper) = 0; + + // Runs the given function under an error trap. This allows the JIT to make calls + // to interface functions that may throw exceptions without needing to be aware of + // the EH ABI, exception types, etc. Returns true if the given function completed + // successfully and false otherwise. + virtual bool runWithErrorTrap( + void (*function)(void*), // The function to run + void* parameter // The context parameter that will be passed to the function and the handler + ) = 0; + +/***************************************************************************** + * ICorStaticInfo contains EE interface methods which return values that are + * constant from invocation to invocation. Thus they may be embedded in + * persisted information like statically generated code. (This is of course + * assuming that all code versions are identical each time.) + *****************************************************************************/ + + // Return details about EE internal data structures + virtual void getEEInfo( + CORINFO_EE_INFO *pEEInfoOut + ) = 0; + + // Returns name of the JIT timer log + virtual LPCWSTR getJitTimeLogFilename() = 0; + + /*********************************************************************************/ + // + // Diagnostic methods + // + /*********************************************************************************/ + + // this function is for debugging only. Returns method token. + // Returns mdMethodDefNil for dynamic methods. + virtual mdMethodDef getMethodDefFromMethod( + CORINFO_METHOD_HANDLE hMethod + ) = 0; + + // this function is for debugging only. It returns the method name + // and if 'moduleName' is non-null, it sets it to something that will + // says which method (a class name, or a module name) + virtual const char* getMethodName ( + CORINFO_METHOD_HANDLE ftn, /* IN */ + const char **moduleName /* OUT */ + ) = 0; + + // Return method name as in metadata, or nullptr if there is none, + // and optionally return the class, enclosing class, and namespace names + // as in metadata. + // Suitable for non-debugging use. + virtual const char* getMethodNameFromMetadata( + CORINFO_METHOD_HANDLE ftn, /* IN */ + const char **className, /* OUT */ + const char **namespaceName, /* OUT */ + const char **enclosingClassName /* OUT */ + ) = 0; + + // this function is for debugging only. It returns a value that + // is will always be the same for a given method. It is used + // to implement the 'jitRange' functionality + virtual unsigned getMethodHash ( + CORINFO_METHOD_HANDLE ftn /* IN */ + ) = 0; + + // this function is for debugging only. + virtual size_t findNameOfToken ( + CORINFO_MODULE_HANDLE module, /* IN */ + mdToken metaTOK, /* IN */ + __out_ecount (FQNameCapacity) char * szFQName, /* OUT */ + size_t FQNameCapacity /* IN */ + ) = 0; + + // returns whether the struct is enregisterable. Only valid on a System V VM. Returns true on success, false on failure. + virtual bool getSystemVAmd64PassStructInRegisterDescriptor( + /* IN */ CORINFO_CLASS_HANDLE structHnd, + /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr + ) = 0; + +}; + +/***************************************************************************** + * ICorDynamicInfo contains EE interface methods which return values that may + * change from invocation to invocation. They cannot be embedded in persisted + * data; they must be requeried each time the EE is run. + *****************************************************************************/ + +class ICorDynamicInfo : public ICorStaticInfo +{ +public: + + // + // These methods return values to the JIT which are not constant + // from session to session. + // + // These methods take an extra parameter : void **ppIndirection. + // If a JIT supports generation of prejit code (install-o-jit), it + // must pass a non-null value for this parameter, and check the + // resulting value. If *ppIndirection is NULL, code should be + // generated normally. If non-null, then the value of + // *ppIndirection is an address in the cookie table, and the code + // generator needs to generate an indirection through the table to + // get the resulting value. In this case, the return result of the + // function must NOT be directly embedded in the generated code. + // + // Note that if a JIT does not support prejit code generation, it + // may ignore the extra parameter & pass the default of NULL - the + // prejit ICorDynamicInfo implementation will see this & generate + // an error if the jitter is used in a prejit scenario. + // + + // Return details about EE internal data structures + + virtual DWORD getThreadTLSIndex( + void **ppIndirection = NULL + ) = 0; + + virtual const void * getInlinedCallFrameVptr( + void **ppIndirection = NULL + ) = 0; + + virtual LONG * getAddrOfCaptureThreadGlobal( + void **ppIndirection = NULL + ) = 0; + + // return the native entry point to an EE helper (see CorInfoHelpFunc) + virtual void* getHelperFtn ( + CorInfoHelpFunc ftnNum, + void **ppIndirection = NULL + ) = 0; + + // return a callable address of the function (native code). This function + // may return a different value (depending on whether the method has + // been JITed or not. + virtual void getFunctionEntryPoint( + CORINFO_METHOD_HANDLE ftn, /* IN */ + CORINFO_CONST_LOOKUP * pResult, /* OUT */ + CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY) = 0; + + // return a directly callable address. This can be used similarly to the + // value returned by getFunctionEntryPoint() except that it is + // guaranteed to be multi callable entrypoint. + virtual void getFunctionFixedEntryPoint( + CORINFO_METHOD_HANDLE ftn, + CORINFO_CONST_LOOKUP * pResult) = 0; + + // get the synchronization handle that is passed to monXstatic function + virtual void* getMethodSync( + CORINFO_METHOD_HANDLE ftn, + void **ppIndirection = NULL + ) = 0; + + // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). + // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. + virtual CorInfoHelpFunc getLazyStringLiteralHelper( + CORINFO_MODULE_HANDLE handle + ) = 0; + + virtual CORINFO_MODULE_HANDLE embedModuleHandle( + CORINFO_MODULE_HANDLE handle, + void **ppIndirection = NULL + ) = 0; + + virtual CORINFO_CLASS_HANDLE embedClassHandle( + CORINFO_CLASS_HANDLE handle, + void **ppIndirection = NULL + ) = 0; + + virtual CORINFO_METHOD_HANDLE embedMethodHandle( + CORINFO_METHOD_HANDLE handle, + void **ppIndirection = NULL + ) = 0; + + virtual CORINFO_FIELD_HANDLE embedFieldHandle( + CORINFO_FIELD_HANDLE handle, + void **ppIndirection = NULL + ) = 0; + + // Given a module scope (module), a method handle (context) and + // a metadata token (metaTOK), fetch the handle + // (type, field or method) associated with the token. + // If this is not possible at compile-time (because the current method's + // code is shared and the token contains generic parameters) + // then indicate how the handle should be looked up at run-time. + // + virtual void embedGenericHandle( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + BOOL fEmbedParent, // TRUE - embeds parent type handle of the field/method handle + CORINFO_GENERICHANDLE_RESULT * pResult) = 0; + + // Return information used to locate the exact enclosing type of the current method. + // Used only to invoke .cctor method from code shared across generic instantiations + // !needsRuntimeLookup statically known (enclosing type of method itself) + // needsRuntimeLookup: + // CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param + // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param + // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param + virtual CORINFO_LOOKUP_KIND getLocationOfThisType( + CORINFO_METHOD_HANDLE context + ) = 0; + + // NOTE: the two methods below--getPInvokeUnmanagedTarget and getAddressOfPInvokeFixup--are + // deprecated. New code should instead use getAddressOfPInvokeTarget, which subsumes the + // functionality of these methods. + + // return the unmanaged target *if method has already been prelinked.* + virtual void* getPInvokeUnmanagedTarget( + CORINFO_METHOD_HANDLE method, + void **ppIndirection = NULL + ) = 0; + + // return address of fixup area for late-bound PInvoke calls. + virtual void* getAddressOfPInvokeFixup( + CORINFO_METHOD_HANDLE method, + void **ppIndirection = NULL + ) = 0; + + // return the address of the PInvoke target. May be a fixup area in the + // case of late-bound PInvoke calls. + virtual void getAddressOfPInvokeTarget( + CORINFO_METHOD_HANDLE method, + CORINFO_CONST_LOOKUP *pLookup + ) = 0; + + // Generate a cookie based on the signature that would needs to be passed + // to CORINFO_HELP_PINVOKE_CALLI + virtual LPVOID GetCookieForPInvokeCalliSig( + CORINFO_SIG_INFO* szMetaSig, + void ** ppIndirection = NULL + ) = 0; + + // returns true if a VM cookie can be generated for it (might be false due to cross-module + // inlining, in which case the inlining should be aborted) + virtual bool canGetCookieForPInvokeCalliSig( + CORINFO_SIG_INFO* szMetaSig + ) = 0; + + // Gets a handle that is checked to see if the current method is + // included in "JustMyCode" + virtual CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle( + CORINFO_METHOD_HANDLE method, + CORINFO_JUST_MY_CODE_HANDLE**ppIndirection = NULL + ) = 0; + + // Gets a method handle that can be used to correlate profiling data. + // This is the IP of a native method, or the address of the descriptor struct + // for IL. Always guaranteed to be unique per process, and not to move. */ + virtual void GetProfilingHandle( + BOOL *pbHookFunction, + void **pProfilerHandle, + BOOL *pbIndirectedHandles + ) = 0; + + // Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values. + virtual void getCallInfo( + // Token info + CORINFO_RESOLVED_TOKEN * pResolvedToken, + + //Generics info + CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, + + //Security info + CORINFO_METHOD_HANDLE callerHandle, + + //Jit info + CORINFO_CALLINFO_FLAGS flags, + + //out params + CORINFO_CALL_INFO *pResult + ) = 0; + + virtual BOOL canAccessFamily(CORINFO_METHOD_HANDLE hCaller, + CORINFO_CLASS_HANDLE hInstanceType) = 0; + + // Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class + // except reflection emitted classes and generics) + virtual BOOL isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) = 0; + + // returns the class's domain ID for accessing shared statics + virtual unsigned getClassDomainID ( + CORINFO_CLASS_HANDLE cls, + void **ppIndirection = NULL + ) = 0; + + + // return the data's address (for static fields only) + virtual void* getFieldAddress( + CORINFO_FIELD_HANDLE field, + void **ppIndirection = NULL + ) = 0; + + // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed + // static readonly fields, if there is a unique location for the static and the class + // is already initialized. + // + // If pIsSpeculative is not NULL, fetch the class handle for the value of all ref-class + // typed static fields, if there is a unique location for the static and the field is + // not null. + // + // Set *pIsSpeculative true if this type may change over time (field is not readonly or + // is readonly but class has not yet finished initialization). Set *pIsSpeculative false + // if this type will not change. + virtual CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( + CORINFO_FIELD_HANDLE field, + bool *pIsSpeculative = NULL + ) = 0; + + // registers a vararg sig & returns a VM cookie for it (which can contain other stuff) + virtual CORINFO_VARARGS_HANDLE getVarArgsHandle( + CORINFO_SIG_INFO *pSig, + void **ppIndirection = NULL + ) = 0; + + // returns true if a VM cookie can be generated for it (might be false due to cross-module + // inlining, in which case the inlining should be aborted) + virtual bool canGetVarArgsHandle( + CORINFO_SIG_INFO *pSig + ) = 0; + + // Allocate a string literal on the heap and return a handle to it + virtual InfoAccessType constructStringLiteral( + CORINFO_MODULE_HANDLE module, + mdToken metaTok, + void **ppValue + ) = 0; + + virtual InfoAccessType emptyStringLiteral( + void **ppValue + ) = 0; + + // (static fields only) given that 'field' refers to thread local store, + // return the ID (TLS index), which is used to find the begining of the + // TLS data area for the particular DLL 'field' is associated with. + virtual DWORD getFieldThreadLocalStoreID ( + CORINFO_FIELD_HANDLE field, + void **ppIndirection = NULL + ) = 0; + + // Sets another object to intercept calls to "self" and current method being compiled + virtual void setOverride( + ICorDynamicInfo *pOverride, + CORINFO_METHOD_HANDLE currentMethod + ) = 0; + + // Adds an active dependency from the context method's module to the given module + // This is internal callback for the EE. JIT should not call it directly. + virtual void addActiveDependency( + CORINFO_MODULE_HANDLE moduleFrom, + CORINFO_MODULE_HANDLE moduleTo + ) = 0; + + virtual CORINFO_METHOD_HANDLE GetDelegateCtor( + CORINFO_METHOD_HANDLE methHnd, + CORINFO_CLASS_HANDLE clsHnd, + CORINFO_METHOD_HANDLE targetMethodHnd, + DelegateCtorArgs * pCtorData + ) = 0; + + virtual void MethodCompileComplete( + CORINFO_METHOD_HANDLE methHnd + ) = 0; + + // return a thunk that will copy the arguments for the given signature. + virtual void* getTailCallCopyArgsThunk ( + CORINFO_SIG_INFO *pSig, + CorInfoHelperTailCallSpecialHandling flags + ) = 0; + + // Optionally, convert calli to regular method call. This is for PInvoke argument marshalling. + virtual bool convertPInvokeCalliToCall( + CORINFO_RESOLVED_TOKEN * pResolvedToken, + bool fMustConvert + ) = 0; +}; + +/**********************************************************************************/ + +// It would be nicer to use existing IMAGE_REL_XXX constants instead of defining our own here... +#define IMAGE_REL_BASED_REL32 0x10 +#define IMAGE_REL_BASED_THUMB_BRANCH24 0x13 + +// The identifier for ARM32-specific PC-relative address +// computation corresponds to the following instruction +// sequence: +// l0: movw rX, #imm_lo // 4 byte +// l4: movt rX, #imm_hi // 4 byte +// l8: add rX, pc <- after this instruction rX = relocTarget +// +// Program counter at l8 is address of l8 + 4 +// Address of relocated movw/movt is l0 +// So, imm should be calculated as the following: +// imm = relocTarget - (l8 + 4) = relocTarget - (l0 + 8 + 4) = relocTarget - (l_0 + 12) +// So, the value of offset correction is 12 +// +#define IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL 0x14 + +#endif // _COR_INFO_H_ diff --git a/lib/coreclr/src/inc/corjit.h b/lib/coreclr/src/inc/corjit.h new file mode 100644 index 0000000000..6892e06a2c --- /dev/null +++ b/lib/coreclr/src/inc/corjit.h @@ -0,0 +1,461 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*****************************************************************************\ +* * +* CorJit.h - EE / JIT interface * +* * +* Version 1.0 * +******************************************************************************* +* * +* * +* * +\*****************************************************************************/ + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier +// must be updated. See code:JITEEVersionIdentifier for more information. +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _COR_JIT_H_ +#define _COR_JIT_H_ + +#include + +#include + +#include + +/*****************************************************************************/ + // These are error codes returned by CompileMethod +enum CorJitResult +{ + // Note that I dont use FACILITY_NULL for the facility number, + // we may want to get a 'real' facility number + CORJIT_OK = NO_ERROR, + CORJIT_BADCODE = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 1), + CORJIT_OUTOFMEM = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 2), + CORJIT_INTERNALERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 3), + CORJIT_SKIPPED = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 4), + CORJIT_RECOVERABLEERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 5), +}; + +/***************************************************************************** +Here is how CORJIT_FLAG_SKIP_VERIFICATION should be interepreted. +Note that even if any method is inlined, it need not be verified. + +if (CORJIT_FLAG_SKIP_VERIFICATION is passed in to ICorJitCompiler::compileMethod()) +{ + No verification needs to be done. + Just compile the method, generating unverifiable code if necessary +} +else +{ + switch(ICorMethodInfo::isInstantiationOfVerifiedGeneric()) + { + case INSTVER_NOT_INSTANTIATION: + + // + // Non-generic case, or open generic instantiation + // + + switch(canSkipMethodVerification()) + { + case CORINFO_VERIFICATION_CANNOT_SKIP: + { + ICorMethodInfo::initConstraintsForVerification(&circularConstraints) + if (circularConstraints) + { + Just emit code to call CORINFO_HELP_VERIFICATION + The IL will not be compiled + } + else + { + Verify the method. + if (unverifiable code is detected) + { + In place of branches with unverifiable code, emit code to call CORINFO_HELP_VERIFICATION + Mark the method (and any of its instantiations) as unverifiable + } + Compile the rest of the verifiable code + } + } + + case CORINFO_VERIFICATION_CAN_SKIP: + { + No verification needs to be done. + Just compile the method, generating unverifiable code if necessary + } + + case CORINFO_VERIFICATION_RUNTIME_CHECK: + { + ICorMethodInfo::initConstraintsForVerification(&circularConstraints) + if (circularConstraints) + { + Just emit code to call CORINFO_HELP_VERIFICATION + The IL will not be compiled + + TODO: This could be changed to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK + } + else + { + Verify the method. + if (unverifiable code is detected) + { + In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK + Mark the method (and any of its instantiations) as unverifiable + } + Compile the method, generating unverifiable code if necessary + } + } + case CORINFO_VERIFICATION_DONT_JIT: + { + ICorMethodInfo::initConstraintsForVerification(&circularConstraints) + if (circularConstraints) + { + Just emit code to call CORINFO_HELP_VERIFICATION + The IL will not be compiled + } + else + { + Verify the method. + if (unverifiable code is detected) + { + Fail the jit + } + } + } + } + + case INSTVER_GENERIC_PASSED_VERIFICATION: + { + This cannot ever happen because the VM would pass in CORJIT_FLAG_SKIP_VERIFICATION. + } + + case INSTVER_GENERIC_FAILED_VERIFICATION: + + switch(canSkipMethodVerification()) + { + case CORINFO_VERIFICATION_CANNOT_SKIP: + { + This cannot be supported because the compiler does not know which branches should call CORINFO_HELP_VERIFICATION. + The CLR will throw a VerificationException instead of trying to compile this method + } + + case CORINFO_VERIFICATION_CAN_SKIP: + { + This cannot ever happen because the CLR would pass in CORJIT_FLAG_SKIP_VERIFICATION. + } + + case CORINFO_VERIFICATION_RUNTIME_CHECK: + { + No verification needs to be done. + In the prolog, emit code to call CORINFO_HELP_VERIFICATION_RUNTIME_CHECK + Compile the method, generating unverifiable code if necessary + } + case CORINFO_VERIFICATION_DONT_JIT: + { + Fail the jit + } + } + } +} + +*/ + +/*****************************************************************************/ +// These are flags passed to ICorJitInfo::allocMem +// to guide the memory allocation for the code, readonly data, and read-write data +enum CorJitAllocMemFlag +{ + CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will be use the normal alignment + CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned + CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned +}; + +inline CorJitAllocMemFlag operator |(CorJitAllocMemFlag a, CorJitAllocMemFlag b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +enum CorJitFuncKind +{ + CORJIT_FUNC_ROOT, // The main/root function (always id==0) + CORJIT_FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler) + CORJIT_FUNC_FILTER // a funclet associated with an EH filter +}; + +// We have a performance-investigation mode (defined by the FEATURE_USE_ASM_GC_WRITE_BARRIERS and +// FEATURE_COUNT_GC_WRITE_BARRIER preprocessor symbols) in which the JIT adds an argument of this +// enumeration to checked write barrier calls in order to classify them. +enum CheckedWriteBarrierKinds { + CWBKind_Unclassified, // Not one of the ones below. + CWBKind_RetBuf, // Store through a return buffer pointer argument. + CWBKind_ByRefArg, // Store through a by-ref argument (not an implicit return buffer). + CWBKind_OtherByRefLocal, // Store through a by-ref local variable. + CWBKind_AddrOfLocal, // Store through the address of a local (arguably a bug that this happens at all). +}; + +#include "corjithost.h" + +extern "C" void __stdcall jitStartup(ICorJitHost* host); + +class ICorJitCompiler; +class ICorJitInfo; +struct IEEMemoryManager; + +extern "C" ICorJitCompiler* __stdcall getJit(); + +// #EEToJitInterface +// ICorJitCompiler is the interface that the EE uses to get IL bytecode converted to native code. Note that +// to accomplish this the JIT has to call back to the EE to get symbolic information. The code:ICorJitInfo +// type passed as 'comp' to compileMethod is the mechanism to get this information. This is often the more +// interesting interface. +// +// +class ICorJitCompiler +{ +public: + // compileMethod is the main routine to ask the JIT Compiler to create native code for a method. The + // method to be compiled is passed in the 'info' parameter, and the code:ICorJitInfo is used to allow the + // JIT to resolve tokens, and make any other callbacks needed to create the code. nativeEntry, and + // nativeSizeOfCode are just for convenience because the JIT asks the EE for the memory to emit code into + // (see code:ICorJitInfo.allocMem), so really the EE already knows where the method starts and how big + // it is (in fact, it could be in more than one chunk). + // + // * In the 32 bit jit this is implemented by code:CILJit.compileMethod + // * For the 64 bit jit this is implemented by code:PreJit.compileMethod + // + // Note: Obfuscators that are hacking the JIT depend on this method having __stdcall calling convention + virtual CorJitResult __stdcall compileMethod ( + ICorJitInfo *comp, /* IN */ + struct CORINFO_METHOD_INFO *info, /* IN */ + unsigned /* code:CorJitFlag */ flags, /* IN */ + BYTE **nativeEntry, /* OUT */ + ULONG *nativeSizeOfCode /* OUT */ + ) = 0; + + // Some JIT compilers (most notably Phoenix), cache information about EE structures from one invocation + // of the compiler to the next. This can be a problem when appdomains are unloaded, as some of this + // cached information becomes stale. The code:ICorJitCompiler.isCacheCleanupRequired is called by the EE + // early first to see if jit needs these notifications, and if so, the EE will call ClearCache is called + // whenever the compiler should abandon its cache (eg on appdomain unload) + virtual void clearCache() = 0; + virtual BOOL isCacheCleanupRequired() = 0; + + // Do any appropriate work at process shutdown. Default impl is to do nothing. + virtual void ProcessShutdownWork(ICorStaticInfo* info) {}; + + // The EE asks the JIT for a "version identifier". This represents the version of the JIT/EE interface. + // If the JIT doesn't implement the same JIT/EE interface expected by the EE (because the JIT doesn't + // return the version identifier that the EE expects), then the EE fails to load the JIT. + // + virtual void getVersionIdentifier( + GUID* versionIdentifier /* OUT */ + ) = 0; + + // When the EE loads the System.Numerics.Vectors assembly, it asks the JIT what length (in bytes) of + // SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD + // intrinsics, so the EE should use the default size (i.e. the size of the IL implementation). + virtual unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return 0; } + + // IL obfuscators sometimes interpose on the EE-JIT interface. This function allows the VM to + // tell the JIT to use a particular ICorJitCompiler to implement the methods of this interface, + // and not to implement those methods itself. The JIT must not return this method when getJit() + // is called. Instead, it must pass along all calls to this interface from within its own + // ICorJitCompiler implementation. If 'realJitCompiler' is nullptr, then the JIT should resume + // executing all the functions itself. + virtual void setRealJit(ICorJitCompiler* realJitCompiler) { } + +}; + +//------------------------------------------------------------------------------------------ +// #JitToEEInterface +// +// ICorJitInfo is the main interface that the JIT uses to call back to the EE and get information. It is +// the companion to code:ICorJitCompiler#EEToJitInterface. The concrete implementation of this in the +// runtime is the code:CEEJitInfo type. There is also a version of this for the NGEN case. +// +// See code:ICorMethodInfo#EEJitContractDetails for subtle conventions used by this interface. +// +// There is more information on the JIT in the book of the runtime entry +// http://devdiv/sites/CLR/Product%20Documentation/2.0/BookOfTheRuntime/JIT/JIT%20Design.doc +// +class ICorJitInfo : public ICorDynamicInfo +{ +public: + // OBSOLETE: return memory manager that the JIT can use to allocate a regular memory + virtual IEEMemoryManager* getMemoryManager() = 0; + + // get a block of memory for the code, readonly data, and read-write data + virtual void allocMem ( + ULONG hotCodeSize, /* IN */ + ULONG coldCodeSize, /* IN */ + ULONG roDataSize, /* IN */ + ULONG xcptnsCount, /* IN */ + CorJitAllocMemFlag flag, /* IN */ + void ** hotCodeBlock, /* OUT */ + void ** coldCodeBlock, /* OUT */ + void ** roDataBlock /* OUT */ + ) = 0; + + // Reserve memory for the method/funclet's unwind information. + // Note that this must be called before allocMem. It should be + // called once for the main method, once for every funclet, and + // once for every block of cold code for which allocUnwindInfo + // will be called. + // + // This is necessary because jitted code must allocate all the + // memory needed for the unwindInfo at the allocMem call. + // For prejitted code we split up the unwinding information into + // separate sections .rdata and .pdata. + // + virtual void reserveUnwindInfo ( + BOOL isFunclet, /* IN */ + BOOL isColdCode, /* IN */ + ULONG unwindSize /* IN */ + ) = 0; + + // Allocate and initialize the .rdata and .pdata for this method or + // funclet, and get the block of memory needed for the machine-specific + // unwind information (the info for crawling the stack frame). + // Note that allocMem must be called first. + // + // Parameters: + // + // pHotCode main method code buffer, always filled in + // pColdCode cold code buffer, only filled in if this is cold code, + // null otherwise + // startOffset start of code block, relative to appropriate code buffer + // (e.g. pColdCode if cold, pHotCode if hot). + // endOffset end of code block, relative to appropriate code buffer + // unwindSize size of unwind info pointed to by pUnwindBlock + // pUnwindBlock pointer to unwind info + // funcKind type of funclet (main method code, handler, filter) + // + virtual void allocUnwindInfo ( + BYTE * pHotCode, /* IN */ + BYTE * pColdCode, /* IN */ + ULONG startOffset, /* IN */ + ULONG endOffset, /* IN */ + ULONG unwindSize, /* IN */ + BYTE * pUnwindBlock, /* IN */ + CorJitFuncKind funcKind /* IN */ + ) = 0; + + // Get a block of memory needed for the code manager information, + // (the info for enumerating the GC pointers while crawling the + // stack frame). + // Note that allocMem must be called first + virtual void * allocGCInfo ( + size_t size /* IN */ + ) = 0; + + virtual void yieldExecution() = 0; + + // Indicate how many exception handler blocks are to be returned. + // This is guaranteed to be called before any 'setEHinfo' call. + // Note that allocMem must be called before this method can be called. + virtual void setEHcount ( + unsigned cEH /* IN */ + ) = 0; + + // Set the values for one particular exception handler block. + // + // Handler regions should be lexically contiguous. + // This is because FinallyIsUnwinding() uses lexicality to + // determine if a "finally" clause is executing. + virtual void setEHinfo ( + unsigned EHnumber, /* IN */ + const CORINFO_EH_CLAUSE *clause /* IN */ + ) = 0; + + // Level -> fatalError, Level 2 -> Error, Level 3 -> Warning + // Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ... + // returns non-zero if the logging succeeded + virtual BOOL logMsg(unsigned level, const char* fmt, va_list args) = 0; + + // do an assert. will return true if the code should retry (DebugBreak) + // returns false, if the assert should be igored. + virtual int doAssert(const char* szFile, int iLine, const char* szExpr) = 0; + + virtual void reportFatalError(CorJitResult result) = 0; + + struct BlockCounts // Also defined by: CORBBTPROF_BLOCK_DATA + { + UINT32 ILOffset; + UINT32 ExecutionCount; + }; + + // allocate a basic block profile buffer where execution counts will be stored + // for jitted basic blocks. + virtual HRESULT allocMethodBlockCounts ( + UINT32 count, // The number of basic blocks that we have + BlockCounts ** pBlockCounts // pointer to array of tuples + ) = 0; + + // get profile information to be used for optimizing the current method. The format + // of the buffer is the same as the format the JIT passes to allocBBProfileBuffer. + virtual HRESULT getMethodBlockCounts( + CORINFO_METHOD_HANDLE ftnHnd, + UINT32 * pCount, // pointer to the count of tuples + BlockCounts ** pBlockCounts, // pointer to array of tuples + UINT32 * pNumRuns // pointer to the total number of profile scenarios run + ) = 0; + + // Associates a native call site, identified by its offset in the native code stream, with + // the signature information and method handle the JIT used to lay out the call site. If + // the call site has no signature information (e.g. a helper call) or has no method handle + // (e.g. a CALLI P/Invoke), then null should be passed instead. + virtual void recordCallSite( + ULONG instrOffset, /* IN */ + CORINFO_SIG_INFO * callSig, /* IN */ + CORINFO_METHOD_HANDLE methodHandle /* IN */ + ) = 0; + + // A relocation is recorded if we are pre-jitting. + // A jump thunk may be inserted if we are jitting + virtual void recordRelocation( + void * location, /* IN */ + void * target, /* IN */ + WORD fRelocType, /* IN */ + WORD slotNum = 0, /* IN */ + INT32 addlDelta = 0 /* IN */ + ) = 0; + + virtual WORD getRelocTypeHint(void * target) = 0; + + // A callback to identify the range of address known to point to + // compiler-generated native entry points that call back into + // MSIL. + virtual void getModuleNativeEntryPointRange( + void ** pStart, /* OUT */ + void ** pEnd /* OUT */ + ) = 0; + + // For what machine does the VM expect the JIT to generate code? The VM + // returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM + // is cross-compiling (such as the case for crossgen), it will return a + // different value than if it was compiling for the host architecture. + // + virtual DWORD getExpectedTargetArchitecture() = 0; + + // Fetches extended flags for a particular compilation instance. Returns + // the number of bytes written to the provided buffer. + virtual DWORD getJitFlags( + CORJIT_FLAGS* flags, /* IN: Points to a buffer that will hold the extended flags. */ + DWORD sizeInBytes /* IN: The size of the buffer. Note that this is effectively a + version number for the CORJIT_FLAGS value. */ + ) = 0; +}; + +/**********************************************************************************/ +#endif // _COR_CORJIT_H_ diff --git a/lib/coreclr/src/inc/corjitflags.h b/lib/coreclr/src/inc/corjitflags.h new file mode 100644 index 0000000000..84fb42f083 --- /dev/null +++ b/lib/coreclr/src/inc/corjitflags.h @@ -0,0 +1,250 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier +// must be updated. See code:JITEEVersionIdentifier for more information. +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _COR_JIT_FLAGS_H_ +#define _COR_JIT_FLAGS_H_ + +class CORJIT_FLAGS +{ +public: + + enum CorJitFlag + { + CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a + // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). + CORJIT_FLAG_SPEED_OPT = 0, + CORJIT_FLAG_SIZE_OPT = 1, + CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) + CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode + CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info + CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necesarily debuggable code) + CORJIT_FLAG_GCPOLL_CALLS = 6, // Emit calls to JIT_POLLGC for thread suspension. + CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete + + #if defined(_TARGET_X86_) + + CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke + CORJIT_FLAG_TARGET_P4 = 9, + CORJIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction + CORJIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction + CORJIT_FLAG_USE_SSE2 = 12, // Generated code may use SSE-2 instructions + + #else // !defined(_TARGET_X86_) + + CORJIT_FLAG_UNUSED1 = 8, + CORJIT_FLAG_UNUSED2 = 9, + CORJIT_FLAG_UNUSED3 = 10, + CORJIT_FLAG_UNUSED4 = 11, + CORJIT_FLAG_UNUSED5 = 12, + + #endif // !defined(_TARGET_X86_) + + CORJIT_FLAG_UNUSED6 = 13, + + #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + CORJIT_FLAG_USE_AVX = 14, + CORJIT_FLAG_USE_AVX2 = 15, + CORJIT_FLAG_USE_AVX_512 = 16, + + #else // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + CORJIT_FLAG_UNUSED7 = 14, + CORJIT_FLAG_UNUSED8 = 15, + CORJIT_FLAG_UNUSED9 = 16, + + #endif // !defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + CORJIT_FLAG_FEATURE_SIMD = 17, + #else + CORJIT_FLAG_UNUSED10 = 17, + #endif // !(defined(_TARGET_X86_) || defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_)) + + CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. + CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation + CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues + CORJIT_FLAG_PROF_REJIT_NOPS = 21, // Insert NOPs to ensure code is re-jitable + CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining + CORJIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below + CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. + CORJIT_FLAG_RELOC = 25, // Generate relocatable code + CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function + CORJIT_FLAG_IL_STUB = 27, // method is an IL stub + CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections + CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information + CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information + CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame + CORJIT_FLAG_ALIGN_LOOPS = 32, // add NOPs before loops to align them at 16 byte boundaries + CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) + CORJIT_FLAG_GCPOLL_INLINE = 34, // JIT must inline calls to GCPoll when possible + CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions + CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog + CORJIT_FLAG_DESKTOP_QUIRKS = 38, // The JIT should generate desktop-quirk-compatible code + CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible + CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code + +#if defined(_TARGET_ARM_) + CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records +#else // !defined(_TARGET_ARM_) + CORJIT_FLAG_UNUSED11 = 41, +#endif // !defined(_TARGET_ARM_) + + CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method + +#if defined(_TARGET_ARM64_) + + CORJIT_FLAG_HAS_ARM64_AES = 43, // ID_AA64ISAR0_EL1.AES is 1 or better + CORJIT_FLAG_HAS_ARM64_ATOMICS = 44, // ID_AA64ISAR0_EL1.Atomic is 2 or better + CORJIT_FLAG_HAS_ARM64_CRC32 = 45, // ID_AA64ISAR0_EL1.CRC32 is 1 or better + CORJIT_FLAG_HAS_ARM64_DCPOP = 46, // ID_AA64ISAR1_EL1.DPB is 1 or better + CORJIT_FLAG_HAS_ARM64_DP = 47, // ID_AA64ISAR0_EL1.DP is 1 or better + CORJIT_FLAG_HAS_ARM64_FCMA = 48, // ID_AA64ISAR1_EL1.FCMA is 1 or better + CORJIT_FLAG_HAS_ARM64_FP = 49, // ID_AA64PFR0_EL1.FP is 0 or better + CORJIT_FLAG_HAS_ARM64_FP16 = 50, // ID_AA64PFR0_EL1.FP is 1 or better + CORJIT_FLAG_HAS_ARM64_JSCVT = 51, // ID_AA64ISAR1_EL1.JSCVT is 1 or better + CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better + CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better + CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better + CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better + CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better + CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better + CORJIT_FLAG_HAS_ARM64_SIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better + CORJIT_FLAG_HAS_ARM64_SIMD_V81 = 59, // ID_AA64ISAR0_EL1.RDM is 1 or better + CORJIT_FLAG_HAS_ARM64_SIMD_FP16 = 60, // ID_AA64PFR0_EL1.AdvSIMD is 1 or better + CORJIT_FLAG_HAS_ARM64_SM3 = 61, // ID_AA64ISAR0_EL1.SM3 is 1 or better + CORJIT_FLAG_HAS_ARM64_SM4 = 62, // ID_AA64ISAR0_EL1.SM4 is 1 or better + CORJIT_FLAG_HAS_ARM64_SVE = 63 // ID_AA64PFR0_EL1.SVE is 1 or better + +#elif defined(_TARGET_X86_) || defined(_TARGET_AMD64_) + + CORJIT_FLAG_USE_SSE3 = 43, + CORJIT_FLAG_USE_SSSE3 = 44, + CORJIT_FLAG_USE_SSE41 = 45, + CORJIT_FLAG_USE_SSE42 = 46, + CORJIT_FLAG_USE_AES = 47, + CORJIT_FLAG_USE_BMI1 = 48, + CORJIT_FLAG_USE_BMI2 = 49, + CORJIT_FLAG_USE_FMA = 50, + CORJIT_FLAG_USE_LZCNT = 51, + CORJIT_FLAG_USE_PCLMULQDQ = 52, + CORJIT_FLAG_USE_POPCNT = 53, + CORJIT_FLAG_UNUSED23 = 54, + CORJIT_FLAG_UNUSED24 = 55, + CORJIT_FLAG_UNUSED25 = 56, + CORJIT_FLAG_UNUSED26 = 57, + CORJIT_FLAG_UNUSED27 = 58, + CORJIT_FLAG_UNUSED28 = 59, + CORJIT_FLAG_UNUSED29 = 60, + CORJIT_FLAG_UNUSED30 = 61, + CORJIT_FLAG_UNUSED31 = 62, + CORJIT_FLAG_UNUSED32 = 63 + + +#else // !defined(_TARGET_ARM64_) &&!defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + + CORJIT_FLAG_UNUSED12 = 43, + CORJIT_FLAG_UNUSED13 = 44, + CORJIT_FLAG_UNUSED14 = 45, + CORJIT_FLAG_UNUSED15 = 46, + CORJIT_FLAG_UNUSED16 = 47, + CORJIT_FLAG_UNUSED17 = 48, + CORJIT_FLAG_UNUSED18 = 49, + CORJIT_FLAG_UNUSED19 = 50, + CORJIT_FLAG_UNUSED20 = 51, + CORJIT_FLAG_UNUSED21 = 52, + CORJIT_FLAG_UNUSED22 = 53, + CORJIT_FLAG_UNUSED23 = 54, + CORJIT_FLAG_UNUSED24 = 55, + CORJIT_FLAG_UNUSED25 = 56, + CORJIT_FLAG_UNUSED26 = 57, + CORJIT_FLAG_UNUSED27 = 58, + CORJIT_FLAG_UNUSED28 = 59, + CORJIT_FLAG_UNUSED29 = 60, + CORJIT_FLAG_UNUSED30 = 61, + CORJIT_FLAG_UNUSED31 = 62, + CORJIT_FLAG_UNUSED32 = 63 + +#endif // !defined(_TARGET_ARM64_) &&!defined(_TARGET_X86_) && !defined(_TARGET_AMD64_) + }; + + CORJIT_FLAGS() + : corJitFlags(0) + { + // empty + } + + // Convenience constructor to set exactly one flag. + CORJIT_FLAGS(CorJitFlag flag) + : corJitFlags(0) + { + Set(flag); + } + + CORJIT_FLAGS(const CORJIT_FLAGS& other) + { + corJitFlags = other.corJitFlags; + } + + void Reset() + { + corJitFlags = 0; + } + + void Set(CorJitFlag flag) + { + corJitFlags |= 1ULL << (unsigned __int64)flag; + } + + void Clear(CorJitFlag flag) + { + corJitFlags &= ~(1ULL << (unsigned __int64)flag); + } + + bool IsSet(CorJitFlag flag) const + { + return (corJitFlags & (1ULL << (unsigned __int64)flag)) != 0; + } + + void Add(const CORJIT_FLAGS& other) + { + corJitFlags |= other.corJitFlags; + } + + void Remove(const CORJIT_FLAGS& other) + { + corJitFlags &= ~other.corJitFlags; + } + + bool IsEmpty() const + { + return corJitFlags == 0; + } + + // DO NOT USE THIS FUNCTION! (except in very restricted special cases) + unsigned __int64 GetFlagsRaw() + { + return corJitFlags; + } + +private: + + unsigned __int64 corJitFlags; +}; + + +#endif // _COR_JIT_FLAGS_H_ diff --git a/lib/coreclr/src/inc/corjithost.h b/lib/coreclr/src/inc/corjithost.h new file mode 100644 index 0000000000..b2ab80646b --- /dev/null +++ b/lib/coreclr/src/inc/corjithost.h @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __CORJITHOST_H__ +#define __CORJITHOST_H__ + +// ICorJitHost +// +// ICorJitHost provides the interface that the JIT uses to access some functionality that +// would normally be provided by the operating system. This is intended to allow for +// host-specific policies re: memory allocation, configuration value access, etc. It is +// expected that the `ICorJitHost` value provided to `jitStartup` lives at least as +// long as the JIT itself. +class ICorJitHost +{ +public: + // Allocate memory of the given size in bytes. + virtual void* allocateMemory(size_t size) = 0; + + // Frees memory previous obtained by a call to `ICorJitHost::allocateMemory`. + virtual void freeMemory(void* block) = 0; + + // Return an integer config value for the given key, if any exists. + virtual int getIntConfigValue( + const wchar_t* name, + int defaultValue + ) = 0; + + // Return a string config value for the given key, if any exists. + virtual const wchar_t* getStringConfigValue( + const wchar_t* name + ) = 0; + + // Free a string ConfigValue returned by the runtime. + // JITs using the getStringConfigValue query are required + // to return the string values to the runtime for deletion. + // This avoids leaking the memory in the JIT. + virtual void freeStringConfigValue( + const wchar_t* value + ) = 0; + + // Allocate memory slab of the given size in bytes. The host is expected to pool + // these for a good performance. + virtual void* allocateSlab(size_t size, size_t* pActualSize) + { + *pActualSize = size; + return allocateMemory(size); + } + + // Free memory slab of the given size in bytes. + virtual void freeSlab(void* slab, size_t actualSize) + { + freeMemory(slab); + } +}; + +#endif diff --git a/lib/coreclr/src/inc/corpriv.h b/lib/coreclr/src/inc/corpriv.h new file mode 100644 index 0000000000..cb504bdd02 --- /dev/null +++ b/lib/coreclr/src/inc/corpriv.h @@ -0,0 +1,474 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: CORPRIV.H +// +// =========================================================================== + +#ifndef _CORPRIV_H_ +#define _CORPRIV_H_ +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 + +// %%Includes: --------------------------------------------------------------- +// avoid taking DLL import hit on intra-DLL calls +#define NODLLIMPORT +#include +#include "cor.h" +#include "corimage.h" +#include "metadata.h" +#include +#include "peinformation.h" +// + +interface IAssemblyName; + +// PE images loaded through the runtime. +typedef struct _dummyCOR { BYTE b; } *HCORMODULE; + +class UTSemReadWrite; + +// Helper function to get a pointer to the Dispenser interface. +STDAPI MetaDataGetDispenser( // Return HRESULT + REFCLSID rclsid, // The class to desired. + REFIID riid, // Interface wanted on class factory. + LPVOID FAR *ppv); // Return interface pointer here. + +BOOL RuntimeFileNotFound(HRESULT hr); + +// Helper function to get an Internal interface with an in-memory metadata section +STDAPI GetMetaDataInternalInterface( + LPVOID pData, // [IN] in memory metadata section + ULONG cbData, // [IN] size of the metadata section + DWORD flags, // [IN] CorOpenFlags + REFIID riid, // [IN] desired interface + void **ppv); // [OUT] returned interface + +// Helper function to get an internal scopeless interface given a scope. +STDAPI GetMetaDataInternalInterfaceFromPublic( + IUnknown *pv, // [IN] Given interface + REFIID riid, // [IN] desired interface + void **ppv); // [OUT] returned interface + +// Helper function to get an internal scopeless interface given a scope. +STDAPI GetMetaDataPublicInterfaceFromInternal( + void *pv, // [IN] Given interface + REFIID riid, // [IN] desired interface + void **ppv); // [OUT] returned interface + +// Converts an internal MD import API into the read/write version of this API. +// This could support edit and continue, or modification of the metadata at +// runtime (say for profiling). +STDAPI ConvertMDInternalImport( // S_OK or error. + IMDInternalImport *pIMD, // [IN] The metadata to be updated. + IMDInternalImport **ppIMD); // [OUT] Put RW interface here. + +STDAPI GetAssemblyMDInternalImport( // Return code. + LPCWSTR szFileName, // [IN] The scope to open. + REFIID riid, // [IN] The interface desired. + IUnknown **ppIUnk); // [OUT] Return interface on success. + +HRESULT GetAssemblyMDInternalImportFromImage( + HCORMODULE hImage, //[IN] pointer to module handle to get the metadata from. + REFIID riid, //[IN] The interface desired. + IUnknown **ppIUnk); //[OUT] Return Interface on success. + +STDAPI GetAssemblyMDInternalImportByStream( // Return code. + IStream *pIStream, // [IN] The IStream for the file + UINT64 AssemblyId, // [IN] Unique Id for the assembly + REFIID riid, // [IN] The interface desired. + IUnknown **ppIUnk); // [OUT] Return interface on success. + + +enum MDInternalImportFlags +{ + MDInternalImport_Default = 0, + MDInternalImport_NoCache = 1, // Do not share/cached the results of opening the image +#ifdef FEATURE_PREJIT + MDInternalImport_TrustedNativeImage = 2, // The image is a native image, and so its format can be trusted + MDInternalImport_ILMetaData = 4, // Open the IL metadata, even if this is a native image + MDInternalImport_TrustedNativeImage_and_IL = MDInternalImport_TrustedNativeImage | MDInternalImport_ILMetaData, +#endif + MDInternalImport_OnlyLookInCache =0x20, // Only look in the cache. (If the cache does not have the image already loaded, return NULL) +}; // enum MDInternalImportFlags + + + +STDAPI GetAssemblyMDInternalImportEx( // Return code. + LPCWSTR szFileName, // [IN] The scope to open. + REFIID riid, // [IN] The interface desired. + MDInternalImportFlags flags, // [in] Flags to control opening the assembly + IUnknown **ppIUnk, // [OUT] Return interface on success. + HANDLE hFile = INVALID_HANDLE_VALUE); + +STDAPI GetAssemblyMDInternalImportByStreamEx( // Return code. + IStream *pIStream, // [IN] The IStream for the file + UINT64 AssemblyId, // [IN] Unique Id for the assembly + REFIID riid, // [IN] The interface desired. + MDInternalImportFlags flags, // [in] Flags to control opening the assembly + IUnknown **ppIUnk); // [OUT] Return interface on success. + + +// Returns part of the "Zap string" which describes the properties of a native image + +__success(SUCCEEDED(return)) +STDAPI GetNativeImageDescription( + __in_z LPCWSTR wzCustomString, // [IN] Custom string of the native image + DWORD dwConfigMask, // [IN] Config mask of the native image + __out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR pwzZapInfo,// [OUT] The description string. Can be NULL to find the size of buffer to allocate + LPDWORD pdwLength); // [IN/OUT] Length of the pwzZapInfo buffer on IN. + // Number of WCHARs (including termintating NULL) on OUT + + +class CQuickBytes; + + +// predefined constant for parent token for global functions +#define COR_GLOBAL_PARENT_TOKEN TokenFromRid(1, mdtTypeDef) + + + +////////////////////////////////////////////////////////////////////////// +// +////////////////////////////////////////////////////////////////////////// + +// %%Interfaces: ------------------------------------------------------------- + +// interface IMetaDataHelper + +// {AD93D71D-E1F2-11d1-9409-0000F8083460} +EXTERN_GUID(IID_IMetaDataHelper, 0xad93d71d, 0xe1f2, 0x11d1, 0x94, 0x9, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); + +#undef INTERFACE +#define INTERFACE IMetaDataHelper +DECLARE_INTERFACE_(IMetaDataHelper, IUnknown) +{ + // helper functions + // This function is exposing the ability to translate signature from a given + // source scope to a given target scope. + // + STDMETHOD(TranslateSigWithScope)( + IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface + const void *pbHashValue, // [IN] Hash Blob for Assembly. + ULONG cbHashValue, // [IN] Count of bytes. + IMetaDataImport *import, // [IN] importing interface + PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope + ULONG cbSigBlob, // [IN] count of bytes of signature + IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface + IMetaDataEmit *emit, // [IN] emit interface + PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature + ULONG cbTranslatedSigMax, + ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature + + STDMETHOD(GetMetadata)( + ULONG ulSelect, // [IN] Selector. + void **ppData) PURE; // [OUT] Put pointer to data here. + + STDMETHOD_(IUnknown *, GetCachedInternalInterface)(BOOL fWithLock) PURE; // S_OK or error + STDMETHOD(SetCachedInternalInterface)(IUnknown * pUnk) PURE; // S_OK or error + STDMETHOD_(UTSemReadWrite*, GetReaderWriterLock)() PURE; // return the reader writer lock + STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; +}; // IMetaDataHelper + + +EXTERN_GUID(IID_IMetaDataEmitHelper, 0x5c240ae4, 0x1e09, 0x11d3, 0x94, 0x24, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); + +#undef INTERFACE +#define INTERFACE IMetaDataEmitHelper +DECLARE_INTERFACE_(IMetaDataEmitHelper, IUnknown) +{ + // emit helper functions + STDMETHOD(DefineMethodSemanticsHelper)( + mdToken tkAssociation, // [IN] property or event token + DWORD dwFlags, // [IN] semantics + mdMethodDef md) PURE; // [IN] method to associated with + + STDMETHOD(SetFieldLayoutHelper)( // Return hresult. + mdFieldDef fd, // [IN] field to associate the layout info + ULONG ulOffset) PURE; // [IN] the offset for the field + + STDMETHOD(DefineEventHelper) ( + mdTypeDef td, // [IN] the class/interface on which the event is being defined + LPCWSTR szEvent, // [IN] Name of the event + DWORD dwEventFlags, // [IN] CorEventAttr + mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class + mdEvent *pmdEvent) PURE; // [OUT] output event token + + STDMETHOD(AddDeclarativeSecurityHelper) ( + mdToken tk, // [IN] Parent token (typedef/methoddef) + DWORD dwAction, // [IN] Security action (CorDeclSecurity) + void const *pValue, // [IN] Permission set blob + DWORD cbValue, // [IN] Byte count of permission set blob + mdPermission*pmdPermission) PURE; // [OUT] Output permission token + + STDMETHOD(SetResolutionScopeHelper)( // Return hresult. + mdTypeRef tr, // [IN] TypeRef record to update + mdToken rs) PURE; // [IN] new ResolutionScope + + STDMETHOD(SetManifestResourceOffsetHelper)( // Return hresult. + mdManifestResource mr, // [IN] The manifest token + ULONG ulOffset) PURE; // [IN] new offset + + STDMETHOD(SetTypeParent)( // Return hresult. + mdTypeDef td, // [IN] Type definition + mdToken tkExtends) PURE; // [IN] parent type + + STDMETHOD(AddInterfaceImpl)( // Return hresult. + mdTypeDef td, // [IN] Type definition + mdToken tkInterface) PURE; // [IN] interface type + +}; // IMetaDataEmitHelper + +////////////////////////////////////////////////////////////////////////////// +// enum CorElementTypeZapSig defines some additional internal ELEMENT_TYPE's +// values that are only used by ZapSig signatures. +////////////////////////////////////////////////////////////////////////////// +typedef enum CorElementTypeZapSig +{ + // ZapSig encoding for ELEMENT_TYPE_VAR and ELEMENT_TYPE_MVAR. It is always followed + // by the RID of a GenericParam token, encoded as a compressed integer. + ELEMENT_TYPE_VAR_ZAPSIG = 0x3b, + + // ZapSig encoding for an array MethodTable to allow it to remain such after decoding + // (rather than being transformed into the TypeHandle representing that array) + // + // The element is always followed by ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY + ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG = 0x3c, + + // ZapSig encoding for native value types in IL stubs. IL stub signatures may contain + // ELEMENT_TYPE_INTERNAL followed by ParamTypeDesc with ELEMENT_TYPE_VALUETYPE element + // type. It acts like a modifier to the underlying structure making it look like its + // unmanaged view (size determined by unmanaged layout, blittable, no GC pointers). + // + // ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG is used when encoding such types to NGEN images. + // The signature looks like this: ET_NATIVE_VALUETYPE_ZAPSIG ET_VALUETYPE . + // See code:ZapSig.GetSignatureForTypeHandle and code:SigPointer.GetTypeHandleThrowing + // where the encoding/decoding takes place. + ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG = 0x3d, + + ELEMENT_TYPE_CANON_ZAPSIG = 0x3e, // zapsig encoding for [mscorlib]System.__Canon + ELEMENT_TYPE_MODULE_ZAPSIG = 0x3f, // zapsig encoding for external module id# + +} CorElementTypeZapSig; + +typedef enum CorCallingConventionInternal +{ + // IL stub signatures containing types that need to be restored have the highest + // bit of the calling convention set. + IMAGE_CEE_CS_CALLCONV_NEEDSRESTORE = 0x80, + +} CorCallingConventionInternal; + +////////////////////////////////////////////////////////////////////////// +// Obsoleted ELEMENT_TYPE values which are not supported anymore. +// They are not part of CLI ECMA spec, they were only experimental before v1.0 RTM. +// They are needed for indexing arrays initialized using file:corTypeInfo.h +// 0x17 ... VALUEARRAY +// 0x1a ... CPU native floating-point type +////////////////////////////////////////////////////////////////////////// +#define ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED ((CorElementType) 0x17) +#define ELEMENT_TYPE_R_UNSUPPORTED ((CorElementType) 0x1a) + +// Use this guid in the SetOption if Reflection.Emit wants to control size of the initially allocated +// MetaData. See values: code:CorMetaDataInitialSize. +// +// {2675b6bf-f504-4cb4-a4d5-084eea770ddc} +EXTERN_GUID(MetaDataInitialSize, 0x2675b6bf, 0xf504, 0x4cb4, 0xa4, 0xd5, 0x08, 0x4e, 0xea, 0x77, 0x0d, 0xdc); + +// Allowed values for code:MetaDataInitialSize option. +typedef enum CorMetaDataInitialSize +{ + MDInitialSizeDefault = 0, + MDInitialSizeMinimal = 1 +} CorMetaDataInitialSize; + +// Internal extension of open flags code:CorOpenFlags +typedef enum CorOpenFlagsInternal +{ +#ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES + // Flag code:ofTrustedImage is used by mscordbi.dll, therefore defined in file:CorPriv.h + ofTrustedImage = ofReserved3 // We trust this PE file (we are willing to do a LoadLibrary on it). + // It is optional and only an (VM) optimization - typically for NGEN images + // opened by debugger. +#endif +} CorOpenFlagsInternal; + +#ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES +#define IsOfTrustedImage(x) ((x) & ofTrustedImage) +#endif + +// %%Classes: ---------------------------------------------------------------- +#ifndef lengthof +#define lengthof(rg) (sizeof(rg)/sizeof(rg[0])) +#endif + +#define COR_MODULE_CLASS "" +#define COR_WMODULE_CLASS W("") + +STDAPI RuntimeOpenImage(LPCWSTR pszFileName, HCORMODULE* hHandle); +STDAPI RuntimeOpenImageInternal(LPCWSTR pszFileName, HCORMODULE* hHandle, + DWORD *pdwLength, MDInternalImportFlags flags, HANDLE hFile = INVALID_HANDLE_VALUE); +STDAPI RuntimeOpenImageByStream(IStream* pIStream, UINT64 AssemblyId, DWORD dwModuleId, + HCORMODULE* hHandle, DWORD *pdwLength, MDInternalImportFlags flags); + +void RuntimeAddRefHandle(HCORMODULE hHandle); +STDAPI RuntimeReleaseHandle(HCORMODULE hHandle); +STDAPI RuntimeGetImageBase(HCORMODULE hHandle, LPVOID* base, BOOL bMapped, COUNT_T* dwSize); +STDAPI RuntimeGetImageKind(HCORMODULE hHandle, DWORD* pdwKind, DWORD* pdwMachine); +STDAPI RuntimeOSHandle(HCORMODULE hHandle, HMODULE* hModule); +STDAPI RuntimeGetAssemblyStrongNameHashForModule(HCORMODULE hModule, + IMetaDataImport *pMDimport, + BYTE *pbSNHash, + DWORD *pcbSNHash); +STDAPI RuntimeGetMDInternalImport(HCORMODULE hHandle, + MDInternalImportFlags flags, + IMDInternalImport** ppMDImport); + +FORCEINLINE +void ReleaseHCorModule(HCORMODULE hModule) +{ + HRESULT hr = RuntimeReleaseHandle(hModule); + _ASSERTE(SUCCEEDED(hr)); +} + +typedef Wrapper, ReleaseHCorModule, (UINT_PTR) NULL> HCORMODULEHolder; + + +// =========================================================================== +// ISNAssemblySignature (similar to IAssemblySignature in V1) +// +// This is a private interface that allows querying of the strong name +// signature. +// This can be used for (strong-named) assemblies added to the GAC as +// a unique identifier. +// + +// {848845BC-0C4A-42e3-8915-DC850112443D} +EXTERN_GUID(IID_ISNAssemblySignature, 0x848845BC, 0x0C4A, 0x42e3, 0x89, 0x15, 0xDC, 0x85, 0x01, 0x12, 0x44, 0x3D); + +#undef INTERFACE +#define INTERFACE ISNAssemblySignature +DECLARE_INTERFACE_(ISNAssemblySignature, IUnknown) +{ + // Returns the strong-name signature if the assembly is strong-name-signed + // Returns the MVID if the assembly is delay-signed. + // Fails if the assembly is not signed at all. + STDMETHOD(GetSNAssemblySignature) ( + BYTE *pbSig, // [IN, OUT] Buffer to write signature + DWORD *pcbSig // [IN, OUT] Size of buffer, bytes written + ) PURE; +}; + +//------------------------------------- +//--- ICeeGenInternal +//------------------------------------- +// {9fd3c7af-dc4e-4b9b-be22-9cf8cc577489} +EXTERN_GUID(IID_ICeeGenInternal, 0x9fd3c7af, 0xdc4e, 0x4b9b, 0xbe, 0x22, 0x9c, 0xf8, 0xcc, 0x57, 0x74, 0x89); + +#undef INTERFACE +#define INTERFACE ICeeGenInternal +DECLARE_INTERFACE_(ICeeGenInternal, IUnknown) +{ + STDMETHOD (SetInitialGrowth) (DWORD growth) PURE; +}; + +// +// IGetIMDInternalImport +// +// Private interface exposed by +// AssemblyMDInternalImport - gives us access to the internally stored IMDInternalImport*. +// +// RegMeta, WinMDImport - supports the internal GetMetaDataInternalInterfaceFromPublic() "api". +// +// {92B2FEF9-F7F5-420d-AD42-AECEEE10A1EF} +EXTERN_GUID(IID_IGetIMDInternalImport, 0x92b2fef9, 0xf7f5, 0x420d, 0xad, 0x42, 0xae, 0xce, 0xee, 0x10, 0xa1, 0xef); +#undef INTERFACE +#define INTERFACE IGetIMDInternalImport +DECLARE_INTERFACE_(IGetIMDInternalImport, IUnknown) +{ + STDMETHOD(GetIMDInternalImport) ( + IMDInternalImport ** ppIMDInternalImport // [OUT] Buffer to receive IMDInternalImport* + ) PURE; +}; + +// =========================================================================== +#ifdef FEATURE_PREJIT +// =========================================================================== + +// Use the default JIT compiler +#define DEFAULT_NGEN_COMPILER_DLL_NAME W("clrjit.dll") + +#ifndef DACCESS_COMPILE + +/* --------------------------------------------------------------------------- * + * NGen logger + * --------------------------------------------------------------------------- */ + #include "mscorsvc.h" + +struct ICorSvcLogger; +class SvcLogger +{ +public: + + SvcLogger(); + ~SvcLogger(); + void ReleaseLogger(); + void SetSvcLogger(ICorSvcLogger *pCorSvcLoggerArg); + BOOL HasSvcLogger(); + ICorSvcLogger* GetSvcLogger(); + void Printf(const CHAR *format, ...); + void SvcPrintf(const CHAR *format, ...); + void Printf(const WCHAR *format, ...); + void Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...); + void SvcPrintf(const WCHAR *format, ...); + void Log(const WCHAR *message, CorSvcLogLevel logLevel = LogLevel_Warning); + //Need to add this to allocate StackSString, as we don't want static class + +private: + + void LogHelper(SString s, CorSvcLogLevel logLevel = LogLevel_Success); + //instantiations that need VM services like contracts in dllmain. + void CheckInit(); + + StackSString* pss; + ICorSvcLogger *pCorSvcLogger; +}; // class SvcLogger + +SvcLogger *GetSvcLogger(); +BOOL HasSvcLogger(); +#endif // #ifndef DACCESS_COMPILE + +// =========================================================================== +#endif // #ifdef FEATURE_PREJIT +// =========================================================================== + +struct CORCOMPILE_ASSEMBLY_SIGNATURE; +struct CORCOMPILE_VERSION_INFO; +struct CORCOMPILE_DEPENDENCY; +typedef GUID CORCOMPILE_NGEN_SIGNATURE; + + +//********************************************************************** +// Internal versions of shim functions for use by the CLR. + +STDAPI GetCORSystemDirectoryInternaL( + SString& pBuffer + ); + +//LONGPATH:TODO: Remove this once Desktop usage has been removed +STDAPI GetCORSystemDirectoryInternal( + __out_ecount_part_opt(cchBuffer, *pdwLength) LPWSTR pBuffer, + DWORD cchBuffer, + __out_opt DWORD* pdwLength + ); + +STDAPI GetCORVersionInternal( + __out_ecount_z_opt(cchBuffer) LPWSTR pBuffer, + DWORD cchBuffer, + __out DWORD *pdwLength); + +#endif // _CORPRIV_H_ +// EOF ======================================================================= + diff --git a/lib/coreclr/src/inc/corprof.idl b/lib/coreclr/src/inc/corprof.idl new file mode 100644 index 0000000000..1d66137b10 --- /dev/null +++ b/lib/coreclr/src/inc/corprof.idl @@ -0,0 +1,4058 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/************************************************************************************** + ** ** + ** Corprof.idl - CLR Profiling interfaces. ** + ** ** + **************************************************************************************/ + +/* -------------------------------------------------------------------------- * + * Imported types + * -------------------------------------------------------------------------- */ + +#if !DEFINITIONS_FROM_NON_IMPORTABLE_PLACES + +cpp_quote("#define CorDB_CONTROL_Profiling \"Cor_Enable_Profiling\"") +cpp_quote("#define CorDB_CONTROL_ProfilingL L\"Cor_Enable_Profiling\"") + +cpp_quote("#if 0") + + +import "unknwn.idl"; + +typedef LONG32 mdToken; +typedef mdToken mdModule; +typedef mdToken mdTypeDef; +typedef mdToken mdMethodDef; +typedef mdToken mdFieldDef; +typedef ULONG CorElementType; + +// Forward declaration of enum in CorHdr.h +enum CorElementType; + +// Forward declaration of structs in Cor.h + +typedef struct +{ + DWORD dwOSPlatformId; // Operating system platform. + DWORD dwOSMajorVersion; // OS Major version. + DWORD dwOSMinorVersion; // OS Minor version. +} OSINFO; + +typedef struct +{ + USHORT usMajorVersion; // Major Version. + USHORT usMinorVersion; // Minor Version. + USHORT usBuildNumber; // Build Number. + USHORT usRevisionNumber; // Revision Number. + LPWSTR szLocale; // Locale. + ULONG cbLocale; // [IN/OUT] Size of the buffer in wide chars/Actual size. + DWORD *rProcessor; // Processor ID array. + ULONG ulProcessor; // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in. + OSINFO *rOS; // OSINFO array. + ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. +} ASSEMBLYMETADATA; + +cpp_quote("#endif") + +typedef const BYTE *LPCBYTE; +typedef BYTE *LPBYTE; + +typedef BYTE COR_SIGNATURE; +typedef COR_SIGNATURE* PCOR_SIGNATURE; +typedef const COR_SIGNATURE* PCCOR_SIGNATURE; + +#endif + + +cpp_quote("#ifndef _COR_IL_MAP") +cpp_quote("#define _COR_IL_MAP") + +#ifdef INTERNAL_DOCS +// Note that this structure is also defined in CorDebug.idl - PROPAGATE CHANGES +// BOTH WAYS, or this'll become a really insidious bug some day. +#endif +typedef struct _COR_IL_MAP +{ + ULONG32 oldOffset; // Old IL offset relative to beginning of function + ULONG32 newOffset; // New IL offset relative to beginning of function + BOOL fAccurate; //put here for compatibility with the Debugger structure. +} COR_IL_MAP; + +cpp_quote("#endif //_COR_IL_MAP") + +cpp_quote("#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_") +cpp_quote("#define _COR_DEBUG_IL_TO_NATIVE_MAP_") + +/* ICorProfilerInfo:: GetILToNativeMapping returns an array of + * COR_DEBUG_IL_TO_NATIVE_MAP structures. In order to convey that certain + * ranges of native instructions correspond to special regions of code (for + * example, the prolog), an entry in the array may have it's ilOffset field set + * to one of these values. + */ +typedef enum CorDebugIlToNativeMappingTypes +{ + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3 +} CorDebugIlToNativeMappingTypes; + +typedef struct COR_DEBUG_IL_TO_NATIVE_MAP +{ + ULONG32 ilOffset; + ULONG32 nativeStartOffset; + ULONG32 nativeEndOffset; +} COR_DEBUG_IL_TO_NATIVE_MAP; + +cpp_quote("#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_") + +cpp_quote("#ifndef _COR_FIELD_OFFSET_") +cpp_quote("#define _COR_FIELD_OFFSET_") + +typedef struct _COR_FIELD_OFFSET +{ + mdFieldDef ridOfField; // fieldDef token of the field + ULONG ulOffset; // offset (from the ObjectID pointer) of the field +} COR_FIELD_OFFSET; + +cpp_quote("#endif // _COR_FIELD_OFFSET_") + + +#ifndef DO_NO_IMPORTS +import "wtypes.idl"; +import "unknwn.idl"; +#endif + +#define STDMETHODCALLTYPE + +typedef UINT_PTR ProcessID; +typedef UINT_PTR AssemblyID; +typedef UINT_PTR AppDomainID; +typedef UINT_PTR ModuleID; +typedef UINT_PTR ClassID; +typedef UINT_PTR ThreadID; +typedef UINT_PTR ContextID; +typedef UINT_PTR FunctionID; +typedef UINT_PTR ObjectID; +typedef UINT_PTR GCHandleID; +typedef UINT_PTR COR_PRF_ELT_INFO; +typedef UINT_PTR ReJITID; + +typedef union {FunctionID functionID; UINT_PTR clientID;} FunctionIDOrClientID; + +/* + * The FunctionIDMapper type definition is used by the + * ICorProfilerInfo::SetFunctionIDMapper method to specify + * a function that will be called to map FunctionIDs to alternative + * values that will be passed to the function entry and function exit + * callbacks supplied to the ICorProfilerInfo::SetEnterLeaveFunctionHooks + * method. The mapper can be set only once and it is recommended to do so + * in the Initialize callback. + * + * NOTE: There is a known bug in this API that must be worked around. + * The return value of FunctionIDMapper cannot be NULL (unless the boolean + * value in pbHookTheFunction is FALSE). All other values are treated as + * opaque data to be passed to the entry/exit callback functions. The use + * of a NULL return value will produce unpredictable results, including + * possibly halting the process. + * + * NOTE: Profilers should be tolerant of cases where multiple threads of + * a profiled app are calling the same method simultaneously. In such + * cases, the profiler may receive multiple FunctionIDMapper callbacks + * for the same functionId. The profiler should be certain to return + * the same values from this callback when it is called multiple times + * with the same functionId. + * + */ +typedef UINT_PTR __stdcall FunctionIDMapper( + FunctionID funcId, + BOOL *pbHookFunction); + +typedef UINT_PTR __stdcall FunctionIDMapper2( + FunctionID funcId, + void *clientData, + BOOL *pbHookFunction); + +/* + * Enum for specifying how much data to pass back with a stack snapshot + */ +typedef enum _COR_PRF_SNAPSHOT_INFO +{ + COR_PRF_SNAPSHOT_DEFAULT = 0x0, + + // Return a register context for each frame + COR_PRF_SNAPSHOT_REGISTER_CONTEXT = 0x1, + + // Use a quicker stack walk algorithm based on the EBP frame chain. This is available + // on x86 only. + COR_PRF_SNAPSHOT_X86_OPTIMIZED = 0x2, +} COR_PRF_SNAPSHOT_INFO; + +/* + * Opaque handle that represents information about a given stack frame. It is only + * valid during the callback to which it is passed. + */ +typedef UINT_PTR COR_PRF_FRAME_INFO; + +/* + * Describes a range of function arguments stored contiguously in left-to-right + * order in memory. + */ +typedef struct _COR_PRF_FUNCTION_ARGUMENT_RANGE +{ + UINT_PTR startAddress; // start address of the range + ULONG length; // contiguous length of the range +} COR_PRF_FUNCTION_ARGUMENT_RANGE; + +/* + * Describes the locations in memory of a function's arguments, in + * left-to-right order. Note that arguments stored in registers are + * spilled to memory to build these structures. + */ +typedef struct _COR_PRF_FUNCTION_ARGUMENT_INFO +{ + ULONG numRanges; // number of chunks of arguments + ULONG totalArgumentSize; // total size of arguments + COR_PRF_FUNCTION_ARGUMENT_RANGE ranges[1]; // chunks +} COR_PRF_FUNCTION_ARGUMENT_INFO; + +/* + * Represents one contiguous chunk of native code + */ +typedef struct _COR_PRF_CODE_INFO +{ + UINT_PTR startAddress; + SIZE_T size; +} COR_PRF_CODE_INFO; + +/* + * Enum for describing the type of static a field is. These may be bit-wise + * or'ed with each other if the field is multiple types. + */ +typedef enum +{ + COR_PRF_FIELD_NOT_A_STATIC = 0x0, + COR_PRF_FIELD_APP_DOMAIN_STATIC = 0x1, + COR_PRF_FIELD_THREAD_STATIC = 0x2, + COR_PRF_FIELD_CONTEXT_STATIC = 0x4, + COR_PRF_FIELD_RVA_STATIC = 0x8 +} COR_PRF_STATIC_TYPE; + +/* + * Represents a function uniquely by combining the FunctionID + * with a ReJITID. + */ +typedef struct _COR_PRF_FUNCTION +{ + FunctionID functionId; + ReJITID reJitId; +} COR_PRF_FUNCTION; + + +/* + * Structure populated by profiler when declaring additional assembly references + * that the CLR should consider when performing an assembly reference closure + * walk. See ICorProfilerCallback6::GetAssemblyReferences and + * ICorProfilerAssemblyReferenceProvider::AddAssemblyReference + */ +typedef struct _COR_PRF_ASSEMBLY_REFERENCE_INFO +{ + void *pbPublicKeyOrToken; // Public key or token of the assembly. + ULONG cbPublicKeyOrToken; // Count of bytes in the public key or token. + LPCWSTR szName; // Name of the assembly being referenced. + ASSEMBLYMETADATA * pMetaData; // Assembly MetaData, as defined in cor.h + void *pbHashValue; // Hash Blob. + ULONG cbHashValue; // Count of bytes in the Hash Blob. + DWORD dwAssemblyRefFlags; // Flags. +} COR_PRF_ASSEMBLY_REFERENCE_INFO; + + +/* + * Represents a IL methods uniquely by combining the module ID and method token. + */ +typedef struct _COR_PRF_METHOD +{ + ModuleID moduleId; + mdMethodDef methodId; +} COR_PRF_METHOD; + +/* + * NOTE!!! + * + * The following applies to ALL FunctionEnter[2,3], FunctionLeave[2,3], + * FunctionTailcall[2,3] hooks below: + * + * It is VERY IMPORTANT to note that these function implementations must be + * __declspec(naked), since the EE is not saving any registers before calling + * any of them. YOU MUST SAVE ALL REGISTERS YOU USE, INCLUDING FPU REGISTERS + * IF THE FPU STACK IS NOT EMPTY AND YOU INTEND TO USE IT. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + + /* + * NOTE: DEPRECATED IN V2 + * + * These functions are considered deprecated in V2 and higher. They will + * continue to work, but incur a performance penalty for usage. For equivalent + * functionality, use the FunctionEnter3/Leave3/Tailcall3 callbacks with + * bits cleared for COR_PRF_ENABLE_FRAME_INFO, COR_PRF_ENABLE_FUNCTION_RETVAL + * and COR_PRF_ENABLE_FUNCTION_ARGS. + */ +typedef void STDMETHODCALLTYPE FunctionEnter( + FunctionID funcID); + +typedef void STDMETHODCALLTYPE FunctionLeave( + FunctionID funcID); + +typedef void STDMETHODCALLTYPE FunctionTailcall( + FunctionID funcID); + +/* + * NOTE: DEPRECATED IN V4 + * + * These functions are considered deprecated in V4 and higher. They will + * continue to work, but incur a performance penalty for usage. For equivalent + * functionality, use the FunctionEnter3/Leave3/Tailcall3 callbacks. + */ + +typedef void STDMETHODCALLTYPE FunctionEnter2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, + COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo); + +typedef void STDMETHODCALLTYPE FunctionLeave2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, + COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange); + +typedef void STDMETHODCALLTYPE FunctionTailcall2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func); + +/* + * When you are not interested in inspecting arguments or return values, then + * use these to be notified as functions are called and return. Use + * SetEnterLeaveFunctionHooks3 to register your implementations of these + * functions. + * + * functionIDOrClientID: if the profiler returned a remapped value from + * FunctionIDMapper[2], then this is that remapped value; else it is the + * true FunctionID of the function. + */ + +typedef void STDMETHODCALLTYPE FunctionEnter3( + FunctionIDOrClientID functionIDOrClientID); + +typedef void STDMETHODCALLTYPE FunctionLeave3( + FunctionIDOrClientID functionIDOrClientID); + +typedef void STDMETHODCALLTYPE FunctionTailcall3( + FunctionIDOrClientID functionIDOrClientID); + +/* + * When you are interested in inspecting arguments and return values, then + * use these to be notified as functions are called and return. Use + * SetEnterLeaveFunctionHooks3WithInfo to register your implementations of these + * functions. + * + * functionIDOrClientID: if the profiler returned a remapped value from + * FunctionIDMapper[2], then this is that remapped value; else it is the + * true FunctionID of the function. + * + * eltInfo is an opaque handle that represents information about a given stack frame. + * It is only valid during the callback to which it is passed. + */ + +typedef void STDMETHODCALLTYPE FunctionEnter3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +typedef void STDMETHODCALLTYPE FunctionLeave3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +typedef void STDMETHODCALLTYPE FunctionTailcall3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +/* + * Stack snapshot callback definition. + * + * This callback is called once per managed frame or run of unmanaged frames. + * + * funcID is the FunctionID of the managed function. If funcID == 0, the callback is + * for a run of unmanaged frames. The profiler may either ignore the frame, or use + * the register context to perform its own unmanaged stackwalk. + * + * ip is the native IP in the frame + * + * frameInfo is the COR_PRF_FRAME_INFO for this frame. It is only valid for + * use during this callback. + * + * context is a Win32 CONTEXT struct for the current platform (size given in + * contextSize). It will only be valid if the COR_PRF_SNAPSHOT_CONTEXT flag + * was passed to DoStackSnapshot. + * + * clientData is a void* passed straight through from DoStackSnapshot + * + * NOTE: One must limit the complexity of work done in StackSnapshotCallback. + * For example, particularly when using DoStackSnapshot in an asynchronous manner, + * the target thread may be holding locks. Executing code within StackSnapshotCallback + * that requires the same locks could lead to deadlock. + */ +typedef HRESULT __stdcall StackSnapshotCallback( + FunctionID funcId, + UINT_PTR ip, + COR_PRF_FRAME_INFO frameInfo, + ULONG32 contextSize, + BYTE context[], + void *clientData); + +/* Callback for each object reference */ +typedef BOOL STDMETHODCALLTYPE ObjectReferenceCallback(ObjectID root, ObjectID* reference, void *clientData); + +typedef enum +{ + // These flags represent classes of callback events + COR_PRF_MONITOR_NONE = 0x00000000, + + // MONITOR_FUNCTION_UNLOADS controls the + // FunctionUnloadStarted callback. + COR_PRF_MONITOR_FUNCTION_UNLOADS = 0x00000001, + + // MONITOR_CLASS_LOADS controls the ClassLoad* + // and ClassUnload* callbacks. + // See the comments on those callbacks for important + // behavior changes in V2. + COR_PRF_MONITOR_CLASS_LOADS = 0x00000002, + + // MONITOR_MODULE_LOADS controls the + // ModuleLoad*, ModuleUnload*, and ModuleAttachedToAssembly + // callbacks. + COR_PRF_MONITOR_MODULE_LOADS = 0x00000004, + + // MONITOR_ASSEMBLY_LOADS controls the + // AssemblyLoad* and AssemblyUnload* callbacks + COR_PRF_MONITOR_ASSEMBLY_LOADS = 0x00000008, + + // MONITOR_APPDOMAIN_LOADS controls the + // AppDomainCreation* and AppDomainShutdown* callbacks + COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x00000010, + + // MONITOR_JIT_COMPILATION controls the + // JITCompilation*, JITFunctionPitched, and JITInlining + // callbacks. + COR_PRF_MONITOR_JIT_COMPILATION = 0x00000020, + + + // MONITOR_EXCEPTIONS controls the ExceptionThrown, + // ExceptionSearch*, ExceptionOSHandler*, ExceptionUnwind*, + // and ExceptionCatcher* callbacks. + COR_PRF_MONITOR_EXCEPTIONS = 0x00000040, + + // MONITOR_GC controls the GarbageCollectionStarted/Finished, + // MovedReferences, SurvivingReferences, + // ObjectReferences, ObjectsAllocatedByClass, + // RootReferences*, HandleCreated/Destroyed, and FinalizeableObjectQueued + // callbacks. + COR_PRF_MONITOR_GC = 0x00000080, + + // MONITOR_OBJECT_ALLOCATED controls the + // ObjectAllocated callback. + COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x00000100, + + // MONITOR_THREADS controls the ThreadCreated, + // ThreadDestroyed, ThreadAssignedToOSThread, + // and ThreadNameChanged callbacks. + COR_PRF_MONITOR_THREADS = 0x00000200, + + // MONITOR_REMOTING controls the Remoting* + // callbacks. + COR_PRF_MONITOR_REMOTING = 0x00000400, + + // MONITOR_CODE_TRANSITIONS controls the + // UnmanagedToManagedTransition and + // ManagedToUnmanagedTransition callbacks. + COR_PRF_MONITOR_CODE_TRANSITIONS = 0x00000800, + + // MONITOR_ENTERLEAVE controls the + // FunctionEnter*/Leave*/Tailcall* callbacks + COR_PRF_MONITOR_ENTERLEAVE = 0x00001000, + + // MONITOR_CCW controls the COMClassicVTable* + // callbacks. + COR_PRF_MONITOR_CCW = 0x00002000, + + // MONITOR_REMOTING_COOKIE controls whether + // a cookie will be passed to the Remoting* callbacks + COR_PRF_MONITOR_REMOTING_COOKIE = 0x00004000 | COR_PRF_MONITOR_REMOTING, + + // MONITOR_REMOTING_ASYNC controls whether + // the Remoting* callbacks will monitor async events + COR_PRF_MONITOR_REMOTING_ASYNC = 0x00008000 | COR_PRF_MONITOR_REMOTING, + + // MONITOR_SUSPENDS controls the RuntimeSuspend*, + // RuntimeResume*, RuntimeThreadSuspended, and + // RuntimeThreadResumed callbacks. + COR_PRF_MONITOR_SUSPENDS = 0x00010000, + + // MONITOR_CACHE_SEARCHES controls the + // JITCachedFunctionSearch* callbacks. + // See the comments on those callbacks for important + // behavior changes in V2. + COR_PRF_MONITOR_CACHE_SEARCHES = 0x00020000, + + // NOTE: ReJIT is now supported again. The profiler must set this flag on + // startup in order to use RequestReJIT or RequestRevert. If the profiler specifies + // this flag, then the profiler must also specify COR_PRF_DISABLE_ALL_NGEN_IMAGES + COR_PRF_ENABLE_REJIT = 0x00040000, + + // V2 MIGRATION WARNING: DEPRECATED + // Inproc debugging is no longer supported. ENABLE_INPROC_DEBUGGING + // has no effect. + COR_PRF_ENABLE_INPROC_DEBUGGING = 0x00080000, + + // V2 MIGRATION NOTE: DEPRECATED + // The runtime now always tracks IL-native maps; this flag is thus always + // considered to be set. + COR_PRF_ENABLE_JIT_MAPS = 0x00100000, + + // DISABLE_INLINING tells the runtime to disable all inlining + COR_PRF_DISABLE_INLINING = 0x00200000, + + // DISABLE_OPTIMIZATIONS tells the runtime to disable all code optimizations + COR_PRF_DISABLE_OPTIMIZATIONS = 0x00400000, + + // ENABLE_OBJECT_ALLOCATED tells the runtime that the profiler may want + // object allocation notifications. This must be set during initialization if the profiler + // ever wants object notifications (using COR_PRF_MONITOR_OBJECT_ALLOCATED) + COR_PRF_ENABLE_OBJECT_ALLOCATED = 0x00800000, + + // MONITOR_CLR_EXCEPTIONS controls the ExceptionCLRCatcher* + // callbacks. + COR_PRF_MONITOR_CLR_EXCEPTIONS = 0x01000000, + + // All callback events are enabled with this flag + COR_PRF_MONITOR_ALL = 0x0107FFFF, + + // ENABLE_FUNCTION_ARGS enables argument tracing through FunctionEnter2. + COR_PRF_ENABLE_FUNCTION_ARGS = 0X02000000, + + // ENABLE_FUNCTION_RETVAL enables retval tracing through FunctionLeave2. + COR_PRF_ENABLE_FUNCTION_RETVAL = 0X04000000, + + // ENABLE_FRAME_INFO enables retrieval of exact ClassIDs for generic functions using + // GetFunctionInfo2 with a COR_PRF_FRAME_INFO obtained from FunctionEnter2. + COR_PRF_ENABLE_FRAME_INFO = 0X08000000, + + // ENABLE_STACK_SNAPSHOT enables the used of DoStackSnapshot calls. + COR_PRF_ENABLE_STACK_SNAPSHOT = 0X10000000, + + // USE_PROFILE_IMAGES causes the native image search to look for profiler-enhanced + // images. If no profiler-enhanced image is found for a given assembly the + // runtime will fallback to JIT for that assembly. + COR_PRF_USE_PROFILE_IMAGES = 0x20000000, + + // COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST will disable security + // transparency checks normally done during JIT compilation and class loading for + // full trust assemblies. This can make some instrumentation easier to perform. + COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST + = 0x40000000, + + // Prevents all NGEN images (including profiler-enhanced images) from loading. If + // this and COR_PRF_USE_PROFILE_IMAGES are both specified, + // COR_PRF_DISABLE_ALL_NGEN_IMAGES wins. + COR_PRF_DISABLE_ALL_NGEN_IMAGES = 0x80000000, + + // The mask for valid mask bits + COR_PRF_ALL = 0x8FFFFFFF, + + // COR_PRF_REQUIRE_PROFILE_IMAGE represents all flags that require profiler-enhanced + // images. + COR_PRF_REQUIRE_PROFILE_IMAGE = COR_PRF_USE_PROFILE_IMAGES | + COR_PRF_MONITOR_CODE_TRANSITIONS | + COR_PRF_MONITOR_ENTERLEAVE, + + COR_PRF_ALLOWABLE_AFTER_ATTACH = COR_PRF_MONITOR_THREADS | + COR_PRF_MONITOR_MODULE_LOADS | + COR_PRF_MONITOR_ASSEMBLY_LOADS | + COR_PRF_MONITOR_APPDOMAIN_LOADS | + COR_PRF_ENABLE_STACK_SNAPSHOT | + COR_PRF_MONITOR_GC | + COR_PRF_MONITOR_SUSPENDS | + COR_PRF_MONITOR_CLASS_LOADS | + COR_PRF_MONITOR_EXCEPTIONS | + COR_PRF_MONITOR_JIT_COMPILATION | + COR_PRF_ENABLE_REJIT, + + // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. + // Trying to change any of these flags elsewhere will result in a + // failed HRESULT. + COR_PRF_MONITOR_IMMUTABLE = COR_PRF_MONITOR_CODE_TRANSITIONS | + COR_PRF_MONITOR_REMOTING | + COR_PRF_MONITOR_REMOTING_COOKIE | + COR_PRF_MONITOR_REMOTING_ASYNC | + COR_PRF_ENABLE_INPROC_DEBUGGING | + COR_PRF_ENABLE_JIT_MAPS | + COR_PRF_DISABLE_OPTIMIZATIONS | + COR_PRF_DISABLE_INLINING | + COR_PRF_ENABLE_OBJECT_ALLOCATED | + COR_PRF_ENABLE_FUNCTION_ARGS | + COR_PRF_ENABLE_FUNCTION_RETVAL | + COR_PRF_ENABLE_FRAME_INFO | + COR_PRF_USE_PROFILE_IMAGES | + COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST | + COR_PRF_DISABLE_ALL_NGEN_IMAGES +} COR_PRF_MONITOR; + +/* + * Additional flags the profiler can specify via SetEventMask2 when loading + */ +typedef enum +{ + COR_PRF_HIGH_MONITOR_NONE = 0x00000000, + + COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x00000001, + + COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x00000002, + + COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS = 0x00000004, + + COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x00000008, + + COR_PRF_HIGH_BASIC_GC = 0x00000010, + + // Enables the MovedReferences/MovedReferences2 callback for compacting GCs only. + COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS = 0x00000020, + + COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0, + + // Enables the large object allocation monitoring according to the LOH threshold. + COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x00000040, + + COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | + COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | + COR_PRF_HIGH_BASIC_GC | + COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS | + COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED, + + // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. + // Trying to change any of these flags elsewhere will result in a + // failed HRESULT. + COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION, + +} COR_PRF_HIGH_MONITOR; + +/* + * COR_PRF_MISC contains miscellaneous constant ID's used for special + * purposes. + */ +typedef enum +{ + // PROFILER_PARENT_UNKNOWN is the AssemblyID used by GetModuleInfo + // when a module has not yet been attached to an assembly. + PROFILER_PARENT_UNKNOWN = 0xFFFFFFFD, + + // PROFILER_GLOBAL_CLASS is a ClassID used for globals that belong to no class + PROFILER_GLOBAL_CLASS = 0xFFFFFFFE, + + // PROFILER_GLOBAL_MODULE is a ModuleID used for globals that belong + // to no module in particular + PROFILER_GLOBAL_MODULE = 0xFFFFFFFF +} COR_PRF_MISC; + +/* + * COR_PRF_JIT_CACHE contains values used to express the result of a + * cached function search. Note that FOUND is 0, and thus this is not truly + * a boolean. + */ +typedef enum +{ + COR_PRF_CACHED_FUNCTION_FOUND, + COR_PRF_CACHED_FUNCTION_NOT_FOUND +} COR_PRF_JIT_CACHE; + +/* + * COR_PRF_TRANSITION_REASON contains values used to describe + * the reason for a ManagedToUnmanaged or UnmanagedToManagedTransition + * callback. + */ +typedef enum +{ + COR_PRF_TRANSITION_CALL, + COR_PRF_TRANSITION_RETURN +} COR_PRF_TRANSITION_REASON; + +/* + * COR_PRF_SUSPEND_REASON contains values used to describe the + * reason for suspending the runtime. See the RuntimeSuspension* + * callbacks for detailed descriptions of each. + */ +typedef enum +{ + COR_PRF_SUSPEND_OTHER = 0, + COR_PRF_SUSPEND_FOR_GC = 1, + COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN = 2, + COR_PRF_SUSPEND_FOR_CODE_PITCHING = 3, + COR_PRF_SUSPEND_FOR_SHUTDOWN = 4, + COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, + COR_PRF_SUSPEND_FOR_GC_PREP = 7, + COR_PRF_SUSPEND_FOR_REJIT = 8, +} COR_PRF_SUSPEND_REASON; + +/* + * COR_PRF_RUNTIME_TYPE contains values used to indicate the + * type of runtime. + */ +typedef enum +{ + COR_PRF_DESKTOP_CLR = 0x1, + COR_PRF_CORE_CLR = 0x2, +} COR_PRF_RUNTIME_TYPE; + +/* + * COR_PRF_REJIT_FLAGS contains values used to control the behavior of + * RequestReJITWithInliners. + */ +typedef enum +{ + // ReJITted methods will be prevented from being inlined + COR_PRF_REJIT_BLOCK_INLINING = 0x1, + + // This flag controls whether the runtime will call GetReJITParameters + // on methods that are ReJITted because they inline a method that was requested + // for ReJIT + COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 +} COR_PRF_REJIT_FLAGS; + + +/* -------------------------------------------------------------------------- * + * Forward declarations + * -------------------------------------------------------------------------- */ + +interface ICorProfilerCallback; +interface ICorProfilerCallback2; +interface ICorProfilerCallback3; +interface ICorProfilerCallback4; +interface ICorProfilerInfo; +interface ICorProfilerInfo2; +interface ICorProfilerInfo3; +interface ICorProfilerInfo4; +interface ICorProfilerObjectEnum; +interface ICorProfilerFunctionEnum; +interface ICorProfilerModuleEnum; +interface ICorProfilerThreadEnum; +interface ICorProfilerMethodEnum; +interface IMethodMalloc; +interface ICorProfilerFunctionControl; +interface ICorProfilerAssemblyReferenceProvider; +/* -------------------------------------------------------------------------- * + * User Callback interface + * -------------------------------------------------------------------------- */ + +/* + * The ICorProfilerCallback interface is used by the CLR to notify a + * code profiler when events have occurred that the code profiler has registered + * an in interest in receiving. This is the primary callback interface through + * which the CLR communicates with the code profiler. A code profiler + * must register this callback interface in the Win32 registry. This object has + * several methods that receive notification from the runtime when an event is + * about to occur in an executing runtime process. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + */ + +[ + object, + uuid(176FBED1-A55C-4796-98CA-A9DA0EF883E7), + pointer_default(unique), + local +] +interface ICorProfilerCallback : IUnknown +{ + + /* + * + * STARTUP/SHUTDOWN EVENTS + * + */ + + /* + * The CLR calls Initialize to setup the code profiler + * whenever a new CLR application is started. The call provides + * an IUnknown interface pointer that should be QI'd for an ICorProfilerInfo + * interface pointer. + * + * NOTE: this is the only opportunity to enable callbacks that are a part + * of COR_PRF_MONITOR_IMMUTABLE, since they can no longer be changed after + * returning from this function. This is done through SetEventMask on the + * ICorProfilerInfo object. + */ + HRESULT Initialize( + [in] IUnknown *pICorProfilerInfoUnk); + + /* + * The CLR calls Shutdown to notify the code profiler that + * the application is exiting. This is the profiler's last opportunity to + * safely call functions on the ICorProfilerInfo interface. After returning + * from this function the runtime will proceed to unravel its internal data + * structures and any calls to ICorProfilerInfo are undefined in their + * behaviour. + * + * NOTE: Certain IMMUTABLE events may still occur after Shutdown. + * + * NOTE: Shutdown will only fire where the managed application that is being + * profiled was started running managed code (i.e., the initial frame on the + * process' stack is managed). If the application being profiled started + * life as unmanaged code, which later 'jumped into' managed code (thereby + * creating an instance of the CLR), then Shutdown will not fire. In these + * cases, the profiler should include a DllMain routine in their library that + * uses Win32's DLL_PROCESS_DETACH call to free any resources and perform tidy-up + * processing of its data (flush traces to disk, etc) + * + * NOTE: The profiler must in general cope with unexpected shutdowns, such as + * when the process is "killed" by Win32's TerminateProcess. + * + * NOTE: Sometimes the CLR will violently kill certain managed threads + * (background threads) without delivering orderly destruction messages for them. + */ + HRESULT Shutdown(); + + + /* + * + * APPLICATION DOMAIN EVENTS + * + */ + + /* + * Called when an application domain creation has begun and ended. + * The ID is not valid for any information request until the Finished + * event is called. + * + * Some parts of app domain loading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of app domain creation succeeded. + */ + HRESULT AppDomainCreationStarted( + [in] AppDomainID appDomainId); + + HRESULT AppDomainCreationFinished( + [in] AppDomainID appDomainId, + [in] HRESULT hrStatus); + + /* + * Called before and after an app domain is unloaded from a process. + * The ID is no longer valid after the Started event returns. + * + * Some parts of app domain unloading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of app domain unloading succeeded. + */ + HRESULT AppDomainShutdownStarted( + [in] AppDomainID appDomainId); + + HRESULT AppDomainShutdownFinished( + [in] AppDomainID appDomainId, + [in] HRESULT hrStatus); + + /* + * + * ASSEMBLY EVENTS + * + */ + + /* + * Called when an Assembly load has begun and ended. The ID is not valid + * for any information request until the Finished event is called. + * + * Some parts of assembly loading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of assembly loading succeeded. + */ + HRESULT AssemblyLoadStarted( + [in] AssemblyID assemblyId); + + HRESULT AssemblyLoadFinished( + [in] AssemblyID assemblyId, + [in] HRESULT hrStatus); + + /* + * Called before and after an assembly is unloaded. + * The ID is no longer valid after the Started event returns. + * + * Some parts of assembly unloading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of assembly unloading succeeded. + */ + HRESULT AssemblyUnloadStarted( + [in] AssemblyID assemblyId); + + HRESULT AssemblyUnloadFinished( + [in] AssemblyID assemblyId, + [in] HRESULT hrStatus); + + + /* + * + * MODULE EVENTS + * + */ + + /* + * Called when a module load has begun and ended. The ID is not valid + * for any information request until the Finished event is called. + * + * Some parts of module loading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of module loading succeeded. + * + * Note that when a module load is reported as finished this indicates + * that the load has completed but it has not yet returned to the caller. + * This is the opportunity for the profiler to note that other notifications regarding + * this module may start coming afterwards however internal safeguards + * protecting the runtime from recursive loading are still present and so it is + * a bad time to begin inquiries on this module. The notification is informational + * only. + * + * Note: ModuleLoadFinished is a reasonable time to interrogate MetaData via API's + * like GetModuleMetadata, however APIs that create (e.g. ClassID's and FunctionID's) + * are not safe to use here. Profiler writers are advised to stay in the universe of + * tokens. + * + */ + HRESULT ModuleLoadStarted( + [in] ModuleID moduleId); + + HRESULT ModuleLoadFinished( + [in] ModuleID moduleId, + [in] HRESULT hrStatus); + + /* + * Called before and after a module is unloaded. + * The ID is no longer valid after the Started event returns. + * + * Some parts of module unloading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of module unloading succeeded. + */ + HRESULT ModuleUnloadStarted( + [in] ModuleID moduleId); + + HRESULT ModuleUnloadFinished( + [in] ModuleID moduleId, + [in] HRESULT hrStatus); + + /* + * A module can get loaded through legacy means (ie: IAT or LoadLibrary) or + * through a metadata reference. The CLR loader therefore has many code + * paths for determining what assembly a module lives in. It is therefore + * possible that after a ModuleLoadFinished event, the module does not + * know what assembly it is in and getting the parent AssemblyID is not possible. + * This event is fired when the module is officially attached to its parent + * assembly. Calling GetModuleInfo after this function is called will return the + * proper parent assembly. + */ + HRESULT ModuleAttachedToAssembly( + [in] ModuleID moduleId, + [in] AssemblyID AssemblyId); + + + /* + * + * CLASS EVENTS + * + */ + + /* + * Called when a class load has begun and ended. The ID is not valid + * for any information request until the Finished event is called. + * + * Some parts of class loading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of class loading succeeded. + * + * Note that when a class load is reported as finished this indicates + * that the load has completed but it has not yet returned to the caller. + * This is the opportunity for the profiler to note that other notifications regarding + * this class may start coming afterwards however internal safeguards + * protecting the runtime from recursive loading are still present and so it is + * a bad time to begin inquiries on this class. The notification is informational + * only. + * + */ + HRESULT ClassLoadStarted( + [in] ClassID classId); + + HRESULT ClassLoadFinished( + [in] ClassID classId, + [in] HRESULT hrStatus); + + /* + * Called before and after a class is unloaded. + * The ID is no longer valid after the Started event returns. + * + * Some parts of class unloading may take place lazily at some time + * after the Finished callback. Therefore, while a failure HRESULT in + * hrStatus definitely indicates a failure, a success HRESULT only indicates + * that the first part of class unloading succeeded. + */ + HRESULT ClassUnloadStarted( + [in] ClassID classId); + + HRESULT ClassUnloadFinished( + [in] ClassID classId, + [in] HRESULT hrStatus); + + /* + * + * JIT EVENTS + * + */ + + /* + * The CLR calls FunctionUnloadStarted to notify the code + * profiler that a function is being unloaded. After returning from this + * call, the FunctionID is no longer valid. + */ + HRESULT FunctionUnloadStarted( + [in] FunctionID functionId); + + + /* + * The CLR calls JITCompilationStarted to notify the code + * profiler that the JIT compiler is starting to compile a function. + * + * The fIsSafeToBlock argument tells the profiler whether or not blocking + * will affect the operation of the runtime. If true, blocking may cause + * the runtime to wait for the calling thread to return from this callback. + * Although this will not harm the runtime, it will skew the profiling + * results. + * + * NOTE: It is possible to receive more than one JITCompilationStarted/ + * JITCompilationFinished pair for each method. This is because of how + * the runtime handles class constructors: method A starts to be JIT'd, + * then realizes that the class ctor for class B needs to be run, so + * JIT's it and runs it, and while it's running makes a call to original + * method A, which causes it to be JIT'd again, and causes the original + * (incomplete) JIT'ing of A to be aborted. However, both attempts to + * JIT A are reported with JIT compilation events. If the profiler is + * going to replace IL code for this method with SetILFunctionBody, then + * it must do so for both JITCompilationStarted events, but may use the + * same IL block for both. + * + * NOTE: A profiler should be tolerant of the sequence of JIT callbacks + * received in cases where two threads are simultaneously calling a + * method. For example, thread A receives JITCompilationStarted. + * But before thread A receives JITCompilationFinished, thread B + * receives FunctionEnter with the functionId from thread A's + * JITCompilationStarted callback. It may appear that functionId should + * not yet be valid because JITCompilationFinished had not yet been + * received. But it is indeed valid in such a case. + */ + HRESULT JITCompilationStarted( + [in] FunctionID functionId, + [in] BOOL fIsSafeToBlock); + + /* + * The CLR calls JITCompilationFinished to notify the code + * profiler that the JIT compiler has finished compiling a function. + * + * The fIsSafeToBlock argument tells the profiler whether or not blocking + * will affect the operation of the runtime. If true, blocking may cause + * the runtime to wait for the calling thread to return from this callback. + * Although this will not harm the runtime, it will skew the profiling + * results. + * + * The FunctionID is now valid in ICorProfilerInfo APIs. + * + * The hrStatus provides the success or failure of the operation + */ + HRESULT JITCompilationFinished( + [in] FunctionID functionId, + [in] HRESULT hrStatus, + [in] BOOL fIsSafeToBlock); + + /* + * V2 MIGRATION WARNING: DOES NOT ALWAYS OCCUR + * The JITCachedFunctionSearchStarted/Finished callbacks + * will now occur only for some functions in regular NGEN images; + * only profiler-optimized NGEN images will generate callbacks for + * all functions in the image. Profilers which do not use these callbacks + * to force a function to be JIT-compiled should move to using a lazy + * strategy for gathering function information. + * + * This notifies the profiler when a search for a prejitted function is + * starting. + * + * functionId: the function for which the search is being performed. + * bUseCachedFunction: if true, the EE uses the cached function (if applicable) + * if false, the EE jits the function instead of + * using a pre-jitted version. + * + * NOTE: Profilers should be tolerant of cases where multiple threads of + * a profiled app are calling the same method simultaneously. For example, + * thread A may receive JITCachedFunctionSearchStarted (and the + * profiler sets *pbUseCachedFunction=FALSE to force a JIT), thread A + * then receives JITCompilationStarted/JITCompilationFinished, then + * thread B receives another JITCachedFunctionSearchStarted for the same + * method. It might appear odd to receive this final callback, since the + * profiler already stated its intention to JIT the method. But this is + * occurring because the CLR in thread B decided to send this callback + * before thread A responded to JITCachedFunctionSearchStarted + * with *pbUseCachedFunction=FALSE, and the thread B callback + * hadn't actually been sent until now due how the threads + * happened to be scheduled. In such cases where the profiler + * receives duplicate JITCachedFunctionSearchStarted callbacks for + * the same functionId, the profiler should be certain to set + * *pbUseCachedFunction to the same value from this callback + * when it is called multiple times with the same functionId. + */ + HRESULT JITCachedFunctionSearchStarted( + [in] FunctionID functionId, + [out] BOOL *pbUseCachedFunction); + + /* + * V2 MIGRATION WARNING: DOES NOT ALWAYS OCCUR + * The JITCachedFunctionSearchStarted/Finished callbacks + * will now occur only for some functions in regular NGEN images; + * only profiler-optimized NGEN images will generate callbacks for + * all functions in the image. Profilers which do not use these callbacks + * to force a function to be JIT-compiled should move to using a lazy + * strategy for gathering function information. + * + * This notifies the profiler when a search for a cached function has been + * performed. + * + * functionId: the function for which the search has been performed. + * result: the result of the search. There are two possible results: + * COR_PRF_CACHED_FUNCTION_FOUND + * COR_PRF_CACHED_FUNCTION_NOT_FOUND + * + */ + HRESULT JITCachedFunctionSearchFinished( + [in] FunctionID functionId, + [in] COR_PRF_JIT_CACHE result); + + /* + * The CLR calls JITFunctionPitched to notify the profiler + * that a jitted function was removed from memory. If the pitched + * function is called in the future, the profiler will receive new + * JIT compilation events as it is re-jitted. + * + * Currently the CLR JIT does not pitch functions, so this callback + * will not be received. + * + * NOTE: the FunctionID is not valid until it is re-jitted. When it is + * re-jitted, it will use the same FunctionID value. + */ + HRESULT JITFunctionPitched( + [in] FunctionID functionId); + + /* + * The CLR calls JITInlining to notify the profiler that the jitter + * is about to inline calleeId into callerId. Set pfShouldInline to FALSE + * to prevent the callee from being inlined into the caller, and set to + * TRUE to allow the inline to occur. + * + * NOTE: Inlined functions do not provide Enter/Leave events, so if you desire + * an accurate callgraph, you should set FALSE. Be aware that + * setting FALSE will affect performance, since inlining typically + * increases speed and reduces separate jitting events for the inlined + * method. + * + * NOTE: It is also possible to globally disable inlining by setting the + * COR_PRF_DISABLE_INLINING flag. + */ + HRESULT JITInlining( + [in] FunctionID callerId, + [in] FunctionID calleeId, + [out] BOOL *pfShouldInline); + + /* + * + * THREAD EVENTS + * + */ + + /* + * The CLR calls ThreadCreated to notify the code profiler + * that a thread has been created. The ThreadID is valid immediately. + */ + HRESULT ThreadCreated( + [in] ThreadID threadId); + + /* + * The CLR calls ThreadDestroyed to notify the code profiler + * that a thread has been destroyed. The ThreadID is no longer valid + * at the time of this call. + */ + HRESULT ThreadDestroyed( + [in] ThreadID threadId); + + /* + * The CLR calls ThreadAssignedToOSThread to tell the profiler + * that a managed thread is being implemented via a particualr OS thread. + * This callback exists so that the profiler can maintain an accurate + * OS to Managed thread mapping across fibres. + */ + HRESULT ThreadAssignedToOSThread( + [in] ThreadID managedThreadId, + [in] DWORD osThreadId); + + /* + * + * REMOTING EVENTS + * + */ + + // + // Client-side events + // + + /* + * NOTE: each of the following pairs of callbacks will occur on the same + * thread + * RemotingClientInvocationStarted & RemotingClientSendingMessage + * RemotingClientReceivingReply & RemotingClientInvocationFinished + * RemotingServerInvocationReturned & RemotingServerSendingReply + * + * There are a few issues with the remoting callbacks that should be outlined. + * First, remoting function execution is not reflected by the profiler API, so + * the notifications for functions that are called from the client and executed + * to the server are not properly received. The actual invocation happens via a + * proxy object. That creates the illusion to the profiler that certain + * functions get jit-compiled but they never get used. Second, the profiler does + * not receive accurate notifications for asynchronous remoting events. + */ + + /* + * The CLR calls RemotingClientInvocationStarted to notify the profiler that + * a remoting call has begun. This event is the same for synchronous and + * asynchronous calls. + */ + HRESULT RemotingClientInvocationStarted(); + + /* + * The CLR calls RemotingClientSendingMessage to notify the profiler that + * a remoting call is requiring the the caller to send an invocation request through + * a remoting channel. + * + * pCookie - if remoting GUID cookies are active, this value will correspond with the + * the value provided in RemotingServerReceivingMessage, if the channel + * succeeds in transmitting the message, and if GUID cookies are active on + * the server-side process. This allows easy pairing of remoting calls, + * and the creation of a logical call stack. + * fIsAsync - is true if the call is asynchronous. + */ + HRESULT RemotingClientSendingMessage( + [in] GUID *pCookie, + [in] BOOL fIsAsync); + + /* + * The CLR calls RemotingClientReceivingReply to notify the profiler that + * the server-side portion of a remoting call has completed and that the client is + * now receiving and about to process the reply. + * + * pCookie - if remoting GUID cookies are active, this value will correspond with the + * the value provided in RemotingServerSendingReply, if the channel + * succeeds in transmitting the message, and if GUID cookies are active on + * the server-side process. This allows easy pairing of remoting calls. + * fIsAsync - is true if the call is asynchronous. + */ + HRESULT RemotingClientReceivingReply( + [in] GUID *pCookie, + [in] BOOL fIsAsync); + + /* + * The CLR calls RemotingClientInvocationFinished to notify the profiler that + * a remoting invocation has run to completion on the client side. If the call was + * synchronous, this means that it has also run to completion on the server side. If + * the call was asynchronous, a reply may still be expected when the call is handled. + * If the call is asynchronous, and a reply is expected, then the reply will occur in + * the form of a call to RemotingClientReceivingReply and an additional call to + * RemotingClientInvocationFinished to indicate the required secondary processing of + * an asynchronous call. + */ + HRESULT RemotingClientInvocationFinished(); + + // + // Server-side events + // + + /* + * The CLR calls RemotingServerReceivingMessage to notify the profiler that + * the process has received a remote method invocation (or activation) request. If + * the message request is asynchronous, then the request may be serviced by any + * arbitrary thread. + * + * pCookie - if remoting GUID cookies are active, this value will correspond with the + * the value provided in RemotingClientSendingMessage, if the channel + * succeeds in transmitting the message, and if GUID cookies are active on + * the client-side process. This allows easy pairing of remoting calls. + * fIsAsync - is true if the call is asynchronous. + */ + HRESULT RemotingServerReceivingMessage( + [in] GUID *pCookie, + [in] BOOL fIsAsync); + + /* + * The CLR calls RemotingServerInvocationStarted to notify the profiler that + * the process is invoking a method due to a remote method invocation request. + */ + HRESULT RemotingServerInvocationStarted(); + + /* + * The CLR calls RemotingServerInvocationReturned to notify the profiler that + * the process has finished invoking a method due to a remote method invocation request. + */ + HRESULT RemotingServerInvocationReturned(); + + /* + * The CLR calls RemotingServerSendingReply to notify the profiler that + * the process has finished processing a remote method invocation request and is + * about to transmit the reply through a channel. + * + * pCookie - if remoting GUID cookies are active, this value will correspond with the + * the value provided in RemotingClientReceivingReply, if the channel + * succeeds in transmitting the message, and if GUID cookies are active on + * the client-side process. This allows easy pairing of remoting calls. + * fIsAsync - is true if the call is asynchronous. + */ + HRESULT RemotingServerSendingReply( + [in] GUID *pCookie, + [in] BOOL fIsAsync); + + /* + * + * TRANSITION EVENTS + * + */ + + /* + * The CLR calls UnmanagedToManagedTransition to notify the + * code profiler that a transition from unmanaged code to managed code has + * occurred. functionId is always the ID of the callee, and reason + * indicates whether the transition was due to a call into managed code from + * unmanaged, or a return from an unmanaged function called by a managed one. + * + * Note that if the reason is COR_PRF_TRANSITION_RETURN and the functionId is + * non-NULL, then the functionId is that of the unmanaged function, and will + * never have been jitted. Unmanaged functions still have some basic + * information associated with them, such as a name, and some metadata. + * + * Note that if the reason is COR_PRF_TRANSITION_RETURN and the callee was + * a PInvoke call indirect, then the runtime does not know the destination + * of the call and functionId will be NULL. + * + * Note that if the reason is COR_PRF_TRANSITION_CALL then it may be possible + * that the callee has not yet been JIT-compiled. + */ + HRESULT UnmanagedToManagedTransition( + [in] FunctionID functionId, + [in] COR_PRF_TRANSITION_REASON reason); + + + /* + * The CLR calls ManagedToUnmanagedTransition to notify the + * code profiler that a transition from managed code to unmanaged code has + * occurred. functionId is always the ID of the callee, and reason + * indicates whether the transition was due to a call into unmanaged code from + * managed, or a return from an managed function called by an unmanaged one. + * + * Note that if the reason is COR_PRF_TRANSITION_CALL, then the functionId + * is that of the unmanaged function, and will never have been jitted. + * Unmanaged functions still have some basic information associated with + * them, such as a name, and some metadata. + * + * Note that if the reason is COR_PRF_TRANSITION_CALL and the callee is + * a PInvoke call indirect, then the runtime does not know the destination + * of the call and functionId will be NULL. + */ + HRESULT ManagedToUnmanagedTransition( + [in] FunctionID functionId, + [in] COR_PRF_TRANSITION_REASON reason); + + + /* + * + * RUNTIME SUSPENSION EVENTS + * + */ + + /* + * The CLR calls RuntimeSuspendStarted to notify the code profiler + * that the runtime is about to suspend all of the runtime threads. + * All runtime threads that are in unmanaged code are permitted to continue + * running until they try to re-enter the runtime, at which point they will + * also suspend until the runtime resumes. This also applies to new threads + * that enter the runtime. All threads within the runtime are either + * suspended immediately if they are in interruptible code, or asked to + * suspend when they do reach interruptible code. + * + * suspendReason make be any of the following values: + * COR_PRF_SUSPEND_FOR_GC + * the runtime is suspending to service a GC request. The GC-related + * callbacks will occur between the RuntimeSuspendFinished and + * RuntimeResumeStarted events. + * COR_PRF_SUSPEND_FOR_CODE_PITCHING + * the runtime is suspending so that code pitching may occur. This + * only occurs when the EJit is active with code pitching enabled. + * Code pitching callbacks will occur between the + * RuntimeSuspendFinished and RuntimeResumeStarted events. + * COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN + * the runtime is suspending so that an AppDomain can be shut down. + * While the runtime is suspended, the runtime will determine which + * threads are in the AppDomain that is being shut down, set them to + * abort when they resume, and then resumes the runtime. There are + * no AppDomain-specific callbacks during this suspension. + * COR_PRF_SUSPEND_FOR_SHUTDOWN + * the runtime is shutting down, and it must suspend all threads to + * complete the operation. + * COR_PRF_SUSPEND_FOR_GC_PREP + * the runtime is preparing for a GC. + * COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER + * the runtime is suspending for in-process debugging. + * COR_PRF_SUSPEND_OTHER + * the runtime is suspending for a reason other than those above. + */ + HRESULT RuntimeSuspendStarted( + [in] COR_PRF_SUSPEND_REASON suspendReason); + + /* + * The CLR calls RuntimeSuspendFinished to notify the code profiler + * that the runtime has suspended all threads needed for a runtime + * suspension. Note that not all runtime threads are required to be + * suspended, as described in the comment for RuntimeSuspendStarted. + * + * NOTE: It is guaranteed that this event will occur on the same ThreadID + * as RuntimeSuspendStarted occurred on. + */ + HRESULT RuntimeSuspendFinished(); + + /* + * The CLR calls RuntimeSuspendAborted to notify the code profiler + * that the runtime is aborting the runtime suspension that was occurring. + * This may occur if two threads simultaneously attempt to suspend the + * runtime. + * + * NOTE: It is guaranteed that this event will occur on the same ThreadID + * as the RuntimeSuspendStarted occurred on, and that only one of + * RuntimeSuspendFinished and RuntimeSuspendAborted may occur on a single + * thread following a RuntimeSuspendStarted event. + */ + HRESULT RuntimeSuspendAborted(); + + /* + * The CLR calls RuntimeResumeStarted to notify the code profiler + * that the runtime is about to resume all of the runtime threads. + */ + HRESULT RuntimeResumeStarted(); + + /* + * The CLR calls RuntimeResumeFinished to notify the code profiler + * that the runtime has finished resuming all of it's threads and is now + * back in normal operation. + * + * NOTE: It is *NOT* guaranteed that this event will occur on the same + * ThreadID as the RuntimeSuspendStarted occurred on, but is guaranteed + * to occur on the same ThreadID as the RuntimeResumeStarted occurred on. + */ + HRESULT RuntimeResumeFinished(); + + /* + * The CLR calls RuntimeThreadSuspended to notify the code profiler + * that a particular thread has been suspended. + * + * This notification may occur any time between the RuntimeSuspendStarted + * and the associated RuntimeResumeStarted. Notifications that occur + * between RuntimeSuspendFinished and RuntimeResumeStarted are for + * threads that had been running in unmanaged code and were suspended + * upon entry to the runtime. + */ + HRESULT RuntimeThreadSuspended( + [in] ThreadID threadId); + + /* + * The CLR calls RuntimeThreadResumed to notify the code profiler + * that a particular thread has been resumed after being suspended due to + * a runtime suspension. + */ + HRESULT RuntimeThreadResumed( + [in] ThreadID threadId); + + /* + * + * GC EVENTS + * + * NOTE: All of these callbacks (except ObjectAllocated) are made while the + * runtime is suspended, so none of the ObjectID values can change until + * the runtime resumes and another GC occurs. + * + * NOTE: The profiler will receive GC-related events (except ObjectAllocated) + * when the profiler has been suspended for COR_PRF_SUSPEND_FOR_GC *except* + * for one special case. When the runtime is shutting down, there is a + * stage where it is suspended for COR_PRF_SUSPEND_FOR_SHUTDOWN reason and + * is never resumed. But after this suspension a garbage collection may + * occur without a COR_PRF_SUSPEND_FOR_GC suspension notification, and + * the profiler will thus receive GC-related callbacks. + * + * NOTE: All of these callbacks (except ObjectAllocated) may be called more than + * once during the same GC. These calls should be considered multiple parts of + * one long report; the profiler should simply aggregate the information provided + * in all of them. + */ + + /* + * The CLR calls MovedReferences with information about + * object references that moved as a result of garbage collection. + * + * cMovedObjectIDRanges is a count of the number of ObjectID ranges that + * were moved. + * oldObjectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values before being moved. + * newObjectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values after being moved. + * cObjectIDRangeLength is an array of elements, each of which states the + * size of the moved ObjectID value range. + * + * The last three arguments of this function are parallel arrays. + * + * In other words, if an ObjectID value lies within the range + * oldObjectIDRangeStart[i] <= ObjectID < oldObjectIDRangeStart[i] + cObjectIDRangeLength[i] + * for 0 <= i < cMovedObjectIDRanges, then the ObjectID value has changed to + * ObjectID - oldObjectIDRangeStart[i] + newObjectIDRangeStart[i] + * + * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback + * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers + * should not attempt to inspect objects during a MovedReferences call. At + * GarbageCollectionFinished, all objects have been moved to their new locations, and + * inspection may be done. + * + * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as ULONG_MAX + * on 64-bit platforms. Use ICorProfilerCallback4::MovedReferences2 instead. + */ + HRESULT MovedReferences( + [in] ULONG cMovedObjectIDRanges, + [in, size_is(cMovedObjectIDRanges)] ObjectID oldObjectIDRangeStart[] , + [in, size_is(cMovedObjectIDRanges)] ObjectID newObjectIDRangeStart[] , + [in, size_is(cMovedObjectIDRanges)] ULONG cObjectIDRangeLength[] ); + + /* + * The CLR calls ObjectAllocated to notify the code profiler + * an object was allocated on the heap. This notification does not fire + * for allocations from the stack, nor from unmanaged memory. + * + * It is possible to receive a classId that corresponds to a regular class + * that has not been loaded yet. The profiler will receive a class load + * callback for that class immediately after the object creation callback. + */ + HRESULT ObjectAllocated( + [in] ObjectID objectId, + [in] ClassID classId); + + /* + * The CLR calls ObjectsAllocatedByClass to notify the code + * profiler about the number of objects of a particular class that were + * allocated since the previous garbage collection. The classes and the + * counts are passed in parallel arrays. (Classes for which no instances + * have been allocated since the previous GC are omitted entirely.) + * + * NOTE: This callback will not report objects allocated in the large + * object heap. + * + * NOTE: The numbers here are only estimates. Use ObjectAllocated for + * exact counts. + */ + HRESULT ObjectsAllocatedByClass( + [in] ULONG cClassCount, + [in, size_is(cClassCount)] ClassID classIds[] , + [in, size_is(cClassCount)] ULONG cObjects[] ); + + /* + * The CLR calls ObjectReferences to provide information + * about objects in memory referenced by a given object. This function + * is called for each object remaining in the GC heap after a collection + * has completed. If the profiler returns an error from this callback, + * the profiling services will discontinue invoking this callback until the + * next GC. This callback can be used in conjunction with the + * RootReferences callback to create a complete object reference graph for + * the runtime. + * + * NOTE: The CLR will ensure that each object reference is reported only + * once by this function. + * + * NOTE: None of the objectIDs returned by ObjectReferences are valid during the callback + * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers + * should not attempt to inspect objects during an ObjectReferences call. At + * GarbageCollectionFinished, all objects have been moved to their new locations, and + * inspection may be done. + */ + HRESULT ObjectReferences( + [in] ObjectID objectId, + [in] ClassID classId, + [in] ULONG cObjectRefs, + [in, size_is(cObjectRefs)] ObjectID objectRefIds[] ); + + /* + * The CLR calls RootReferences with information about root + * references after a garbage collection has occurred. Static object + * references and references to objects on a stack are co-mingled in the + * arrays. + * + * NOTE: It is possible to get NULL ObjectIDs in the RootReferences callback. + * For example, all object references declared on the stack are treated as + * roots by the GC, and will always be reported. + * + * NOTE: None of the objectIDs returned by RootReferences are valid during the callback + * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers + * should not attempt to inspect objects during a RootReferences call. At + * GarbageCollectionFinished, all objects have been moved to their new locations, and + * inspection may be done. + */ + HRESULT RootReferences( + [in] ULONG cRootRefs, + [in, size_is(cRootRefs)] ObjectID rootRefIds[] ); + + + /* + * + * EXCEPTION EVENTS + * + */ + + // + // Exception creation + // + + /* + * The CLR calls ExceptionThrown to notify the code + * profiler that an exception has been thrown. + * + * NOTE: This function is only called if the exception reaches + * managed code. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionThrown( + [in] ObjectID thrownObjectId); + + // + // Search phase + // + + /* + * The CLR calls ExceptionSearchFunctionEnter to notify the profiler + * that the search phase of exception handling has entered a function. + */ + HRESULT ExceptionSearchFunctionEnter( + [in] FunctionID functionId); + + /* + * The CLR calls ExceptionSearchFunctionLeave to notify the profiler + * that the search phase of exception handling has left a function. + */ + HRESULT ExceptionSearchFunctionLeave(); + + /* + * The CLR will call ExceptionSearchFilterEnter just before excecuting + * a user filter. The functionID is that of the function containing the filter. + */ + HRESULT ExceptionSearchFilterEnter( + [in] FunctionID functionId); + + /* + * The CLR will call ExceptionSearchFilterLeave immediately after + * executing a user filter. + */ + HRESULT ExceptionSearchFilterLeave(); + + /* + * The CLR will call ExceptionSearchCatcherFound when the search + * phase of exception handling has located a handler for the exception that + * was thrown. + */ + HRESULT ExceptionSearchCatcherFound( + [in] FunctionID functionId); + + /* + * DEPRECATED. It is the job of the unmanaged profiler to detect OS + * handling of exceptions. + */ + HRESULT ExceptionOSHandlerEnter( + [in] UINT_PTR __unused); + + /* + * DEPRECATED. It is the job of the unmanaged profiler to detect OS + * handling of exceptions. + */ + HRESULT ExceptionOSHandlerLeave( + [in] UINT_PTR __unused); + + // + // Unwind phase + // + + /* + * The CLR calls ExceptionUnwindFunctionEnter to notify the profiler + * that the unwind phase of exception handling has entered a function. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionUnwindFunctionEnter( + [in] FunctionID functionId); + + /* + * The CLR calls ExceptionUnwindFunctionLeave to notify the profiler + * that the unwind phase of exception handling has left a function. The + * function instance and it's stack data has now been removed from the stack. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionUnwindFunctionLeave(); + + /* + * The CLR calls ExceptionUnwindFinallyEnter to notify the profiler + * that the unwind phase of exception is entering a finally clause contained + * in the specified function. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionUnwindFinallyEnter( + [in] FunctionID functionId); + + /* + * The CLR calls ExceptionUnwindFinallyLeave to notify the profiler + * that the unwind phase of exception is leaving a finally clause. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionUnwindFinallyLeave(); + + /* + * The CLR calls this function just before passing control to + * the appropriate catch block. Note that this is called only if the + * catch point is in JIT'ed code. An exception that is caught in + * unmanaged code, or in the internal code of the CLR will + * not generate this notification. The ObjectID is passed again since + * a GC could have moved the object since the ExceptionThrown + * notification. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionCatcherEnter( + [in] FunctionID functionId, + [in] ObjectID objectId); + + /* + * The CLR calls ExceptionCatcherLeave when the runtime leaves + * the catcher's code. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + */ + HRESULT ExceptionCatcherLeave(); + + /* + * CLR<->COM interop vtable creation/destruction. + */ + + /* + * The CLR calls this function when an CLR<->COM interop vtable + * for a particular IID and for a particular class has been created. + * This provides the ClassID of the class for which this vtable has been + * created, the IID it implements, the start of the vtable and how many + * slots are in it. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + * + * NOTE: It is possible to receive a NULL GUID if the interface is + * internal only. + */ + HRESULT COMClassicVTableCreated( + [in] ClassID wrappedClassId, + [in] REFGUID implementedIID, + [in] void *pVTable, + [in] ULONG cSlots); + + /* + * The CLR calls this function when a CLR<->COM interop vtable is + * being destroyed. Provided are the ClassID, IID and vtable pointer for + * the destroyed vtable. + * + * NOTE: The profiler should not block here, since the stack may not be in a + * GC-friendly state and so preemptive GC cannot be enabled. If the + * profiler blocks here and a GC is attempted, the runtime will block + * until this callback returns. Also, the profiler may NOT call into + * managed code or in any way cause a managed memory allocation. + * + * NOTE: It is possible to receive a NULL GUID if the interface is + * internal only. + * + * NOTE: This callback is likely never to occur, since the destruction of + * vtables occurs very close to Shutdown. + */ + HRESULT COMClassicVTableDestroyed( + [in] ClassID wrappedClassId, + [in] REFGUID implementedIID, + [in] void *pVTable); + + /* + * DEPRECATED. These callbacks are no longer delivered. + */ + HRESULT ExceptionCLRCatcherFound(); + + HRESULT ExceptionCLRCatcherExecute(); +} + +/* + * COR_PRF_GC_ROOT_KIND describes the kind of GC root exposed by + * the RootReferences2 callback. + */ + +typedef enum +{ + COR_PRF_GC_ROOT_STACK = 1, // Variables on the stack + COR_PRF_GC_ROOT_FINALIZER = 2, // Entry in the finalizer queue + COR_PRF_GC_ROOT_HANDLE = 3, // GC Handle + COR_PRF_GC_ROOT_OTHER = 0 //Misc. roots +} COR_PRF_GC_ROOT_KIND; + + +/* + * COR_PRF_GC_ROOT_FLAGS describes properties of a GC root + * exposed by the RootReferences callback. + */ + +typedef enum +{ + COR_PRF_GC_ROOT_PINNING = 0x1, // Prevents GC from moving the object + COR_PRF_GC_ROOT_WEAKREF = 0x2, // Does not prevent collection + COR_PRF_GC_ROOT_INTERIOR = 0x4, // Refers to a field of the object rather than the object itself + COR_PRF_GC_ROOT_REFCOUNTED = 0x8, // Whether it prevents collection depends on a refcount - if not, + // COR_PRF_GC_ROOT_WEAKREF will be set also +} COR_PRF_GC_ROOT_FLAGS; + + +/* + * COR_PRF_FINALIZER_FLAGS is used by FinalizableObjectQueued to describe + * the finalizer for the object. + */ + +typedef enum +{ + COR_PRF_FINALIZER_CRITICAL = 0x1 // Critical finalizer +} COR_PRF_FINALIZER_FLAGS; + + +/* + * COR_PRF_GC_GENERATION contains the numbers used to represent each GC generation + * in the GetGenerationBounds and GetObjectGeneration functions. + */ + +typedef enum +{ + COR_PRF_GC_GEN_0 = 0, + COR_PRF_GC_GEN_1 = 1, + COR_PRF_GC_GEN_2 = 2, + COR_PRF_GC_LARGE_OBJECT_HEAP = 3 +} COR_PRF_GC_GENERATION; + + +/* + * COR_PRF_GC_GENERATION_RANGE describes a range of memory in the GetGenerationBounds and GetObjectGeneration functions. + * Note that the rangeLength member is only guaranteed to be accurate if GetGenerationBounds or GetObjectGeneration are + * called from a GarbageCollectionStarted or GarbageCollectionFinished notification + */ +typedef struct COR_PRF_GC_GENERATION_RANGE +{ + COR_PRF_GC_GENERATION generation; // what generation the range of memory belongs to + ObjectID rangeStart; // the start of the range + UINT_PTR rangeLength; // the used length of the range + UINT_PTR rangeLengthReserved; // the amount of memory reserved for the range (including rangeLength) + +} COR_PRF_GC_GENERATION_RANGE; + + + +/* + * COR_PRF_CLAUSE_TYPE defines the various clause codes for the EX clauses + */ +typedef enum +{ + COR_PRF_CLAUSE_NONE = 0, // not a real clause (only used in error cases) + COR_PRF_CLAUSE_FILTER = 1, + COR_PRF_CLAUSE_CATCH = 2, + COR_PRF_CLAUSE_FINALLY = 3, +} COR_PRF_CLAUSE_TYPE; + +/* + * COR_PRF_EX_CLAUSE_INFO identifies a specific exception clause instance and its associated frame. + * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used to get the + * native address and frame information for the exception clause (catch/finally/filter) that is + * about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) or has just + * been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). + */ +typedef struct COR_PRF_EX_CLAUSE_INFO +{ + COR_PRF_CLAUSE_TYPE clauseType; // the type of clause we just entered or left + UINT_PTR programCounter; // the native entry point of the clause handler (e.g. EIP) + UINT_PTR framePointer; // the logical frame pointer (e.g. EBP) for that clause handler + UINT_PTR shadowStackPointer; // the shadow stack pointer (IA64 only, BSP) +} COR_PRF_EX_CLAUSE_INFO; + +/* + * COR_PRF_GC_REASON describes the reason for a given GC. + */ +typedef enum +{ + COR_PRF_GC_INDUCED = 1, // Induced by GC.Collect + COR_PRF_GC_OTHER = 0 // Anything else +} COR_PRF_GC_REASON; + +/* + * Bits from COR_PRF_MODULE_FLAGS are returned to the profiler in GetModuleInfo2's + * pdwModuleFlags output parameter. Some combinations of 2 or more flags are possible, + * though not all combinations are possible. + */ +typedef enum +{ + // The module was loaded from disk + COR_PRF_MODULE_DISK = 0x00000001, + + // The module had been generated via NGEN + COR_PRF_MODULE_NGEN = 0x00000002, + + // The module was created via methods in the Reflection.Emit namespace + COR_PRF_MODULE_DYNAMIC = 0x00000004, + + // The module's lifetime is managed by the garbage collector. + COR_PRF_MODULE_COLLECTIBLE = 0x00000008, + + // The module contains no metadata and is used strictly as a resource. The managed + // equivalent of this bit is the System.Reflection.Module.IsResource() method. + COR_PRF_MODULE_RESOURCE = 0x00000010, + + // The module's layout in memory is flat, as opposed to mapped. For modules that have + // this bit set, profilers that directly read information out of the PE header will + // need to be careful when interpreting RVAs present in the PE header. + COR_PRF_MODULE_FLAT_LAYOUT = 0x00000020, + + // The Windows Runtime content type flag is set in the metadata for this module's + // assembly + COR_PRF_MODULE_WINDOWS_RUNTIME = 0x00000040, +} COR_PRF_MODULE_FLAGS; +/* + * The ICorProfilerCallback2 interface is used by the CLR to notify a + * code profiler when events have occurred that the code profiler has registered + * an in interest in receiving. These are new callbacks implemented in V2.0 + * of the runtime. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + */ + +[ + object, + uuid(8A8CC829-CCF2-49fe-BBAE-0F022228071A), + pointer_default(unique), + local +] +interface ICorProfilerCallback2 : ICorProfilerCallback +{ + + /* + * + * THREAD EVENTS + * + */ + + /* + * The CLR calls ThreadNameChanged to notify the code profiler + * that a thread's name has changed. + * + * name is not NULL terminated. + * + */ + HRESULT ThreadNameChanged( + [in] ThreadID threadId, + [in] ULONG cchName, + [in, annotation("_In_reads_opt_(cchName)")] WCHAR name[]); + + /* + * + * GARBAGE COLLECTION EVENTS + * + */ + + /* + * The CLR calls GarbageCollectionStarted before beginning a + * garbage collection. All GC callbacks pertaining to this + * collection will occur between the GarbageCollectionStarted + * callback and the corresponding GarbageCollectionFinished + * callback. Corresponding GarbageCollectionStarted and + * GarbageCollectionFinished callbacks need not occur on the same thread. + * + * cGenerations indicates the total number of entries in + * the generationCollected array + * generationCollected is an array of booleans, indexed + * by COR_PRF_GC_GENERATIONS, indicating which + * generations are being collected in this collection + * reason indicates whether this GC was induced + * by the application calling GC.Collect(). + * + * NOTE: It is safe to inspect objects in their original locations + * during this callback. The GC will begin moving objects after + * the profiler returns from this callback. Therefore, after + * returning, the profiler should consider all ObjectIDs to be invalid + * until it receives a GarbageCollectionFinished callback. + */ + HRESULT GarbageCollectionStarted( + [in] int cGenerations, + [in, size_is(cGenerations)] BOOL generationCollected[], + [in] COR_PRF_GC_REASON reason); + + /* + * The CLR calls SurvivingReferences with information about + * object references that survived a garbage collection. + * + * Generally, the CLR calls SurvivingReferences for non-compacting garbage collections. + * For compacting garbage collections, MovedReferences is called instead. + * + * The exception to this rule is that the CLR always calls SurvivingReferences for objects + * in the large object heap, which is not compacted. + * + * Multiple calls to SurvivingReferences may be received during a particular + * garbage collection, due to limited internal buffering, multiple threads reporting + * in the case of server gc, and other reasons. + * In the case of multiple calls, the information is cumulative - all of the references + * reported in any SurvivingReferences call survive this collection. + * + * cSurvivingObjectIDRanges is a count of the number of ObjectID ranges that + * survived. + * objectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values that survived the collection. + * cObjectIDRangeLength is an array of elements, each of which states the + * size of the surviving ObjectID value range. + * + * The last two arguments of this function are parallel arrays. + * + * In other words, if an ObjectID value lies within the range + * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] + * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection + * + * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as ULONG_MAX + * on 64-bit platforms. Use ICorProfilerCallback4::SurvivingReferences2 instead. + */ + HRESULT SurvivingReferences( + [in] ULONG cSurvivingObjectIDRanges, + [in, size_is(cSurvivingObjectIDRanges)] ObjectID objectIDRangeStart[] , + [in, size_is(cSurvivingObjectIDRanges)] ULONG cObjectIDRangeLength[] ); + /* + * The CLR calls GarbageCollectionFinished after a garbage + * collection has completed and all GC callbacks have been + * issued for it. + * + * NOTE: It is now safe to inspect objects in their + * final locations. + */ + HRESULT GarbageCollectionFinished(); + + /* + * The CLR calls FinalizeableObjectQueued to notify the code profiler + * that an object with a finalizer (destructor in C# parlance) has + * just been queued to the finalizer thread for execution of its + * Finalize method. + * + * finalizerFlags describes aspects of the finalizer, and takes its + * value from COR_PRF_FINALIZER_FLAGS. + * + */ + + HRESULT FinalizeableObjectQueued( + [in] DWORD finalizerFlags, + [in] ObjectID objectID); + + /* + * The CLR calls RootReferences2 with information about root + * references after a garbage collection has occurred. + * For each root reference in rootRefIds, there is information in + * rootClassifications to classify it. Depending on the classification, + * rootsIds may contain additional information. The information in + * rootKinds and rootFlags contains information about the location and + * properties of the reference. + * + * If the profiler implements ICorProfilerCallback2, both + * ICorProfilerCallback::RootReferences and ICorProfilerCallback2::RootReferences2 + * are called. As the information passed to RootReferences2 is a superset + * of the one passed to RootReferences, profilers will normally implement + * one or the other, but not both. + * + * If the root kind is STACK, the ID is the FunctionID of the + * function containing the variable. If the FunctionID is 0, the function + * is an unnamed function internal to the CLR. + * + * If the root kind is HANDLE, the ID is the GCHandleID. + * + * For the other root kinds, the ID is an opaque value and should + * be ignored. + * + * It's possible for entries in rootRefIds to be 0 - this just + * implies the corresponding root reference was null and thus did not + * refer to an object on the managed heap. + * + * NOTE: None of the objectIDs returned by RootReferences2 are valid during the callback + * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers + * should not attempt to inspect objects during a RootReferences2 call. At + * GarbageCollectionFinished, all objects have been moved to their new locations, and + * inspection may be done. + */ + + HRESULT RootReferences2( + [in] ULONG cRootRefs, + [in, size_is(cRootRefs)] ObjectID rootRefIds[], + [in, size_is(cRootRefs)] COR_PRF_GC_ROOT_KIND rootKinds[], + [in, size_is(cRootRefs)] COR_PRF_GC_ROOT_FLAGS rootFlags[], + [in, size_is(cRootRefs)] UINT_PTR rootIds[]); + + /* + * The CLR calls HandleCreated when a gc handle has been created. + * + */ + + HRESULT HandleCreated( + [in] GCHandleID handleId, + [in] ObjectID initialObjectId); + + /* + * The CLR calls HandleDestroyed when a gc handle has been destroyed. + * + */ + + HRESULT HandleDestroyed( + [in] GCHandleID handleId); +} + +[ + object, + uuid(4FD2ED52-7731-4b8d-9469-03D2CC3086C5), + pointer_default(unique), + local +] +interface ICorProfilerCallback3 : ICorProfilerCallback2 +{ + HRESULT InitializeForAttach( + [in] IUnknown * pCorProfilerInfoUnk, + [in] void * pvClientData, + [in] UINT cbClientData); + + HRESULT ProfilerAttachComplete(); + + HRESULT ProfilerDetachSucceeded(); +}; + +[ + object, + uuid(7B63B2E3-107D-4d48-B2F6-F61E229470D2), + pointer_default(unique), + local +] +interface ICorProfilerCallback4 : ICorProfilerCallback3 +{ + /* + * Similar to JITCompilationStarted, except called when rejitting a method + */ + HRESULT ReJITCompilationStarted( + [in] FunctionID functionId, + [in] ReJITID rejitId, + [in] BOOL fIsSafeToBlock); + + /* + * This is called exactly once per method (which may represent more than + * one function id), to allow the code profiler to set alternate code + * generation flags or a new method body. + */ + HRESULT GetReJITParameters( + [in] ModuleID moduleId, + [in] mdMethodDef methodId, + [in] ICorProfilerFunctionControl *pFunctionControl); + + /* + * Similar to JITCompilationFinished, except called when rejitting a method + */ + HRESULT ReJITCompilationFinished( + [in] FunctionID functionId, + [in] ReJITID rejitId, + [in] HRESULT hrStatus, + [in] BOOL fIsSafeToBlock); + + /* + * This is called to report an error encountered while processing a ReJIT request. + * This may either be called from within the RequestReJIT call itself, or called after + * RequestReJIT returns, if the error was encountered later on. + */ + HRESULT ReJITError( + [in] ModuleID moduleId, + [in] mdMethodDef methodId, + [in] FunctionID functionId, + [in] HRESULT hrStatus); + + /* + * The CLR calls MovedReferences with information about + * object references that moved as a result of garbage collection. + * + * cMovedObjectIDRanges is a count of the number of ObjectID ranges that + * were moved. + * oldObjectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values before being moved. + * newObjectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values after being moved. + * cObjectIDRangeLength is an array of elements, each of which states the + * size of the moved ObjectID value range. + * + * The last three arguments of this function are parallel arrays. + * + * In other words, if an ObjectID value lies within the range + * oldObjectIDRangeStart[i] <= ObjectID < oldObjectIDRangeStart[i] + cObjectIDRangeLength[i] + * for 0 <= i < cMovedObjectIDRanges, then the ObjectID value has changed to + * ObjectID - oldObjectIDRangeStart[i] + newObjectIDRangeStart[i] + * + * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback + * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers + * should not attempt to inspect objects during a MovedReferences call. At + * GarbageCollectionFinished, all objects have been moved to their new locations, and + * inspection may be done. + * + * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::MovedReferences2 + * is called first and ICorProfilerCallback::MovedReferences is called second but only if + * ICorProfilerCallback4::MovedReferences2 returned success. Profilers can return failure + * from ICorProfilerCallback4::MovedReferences2 to save some chattiness. + */ + HRESULT MovedReferences2( + [in] ULONG cMovedObjectIDRanges, + [in, size_is(cMovedObjectIDRanges)] ObjectID oldObjectIDRangeStart[] , + [in, size_is(cMovedObjectIDRanges)] ObjectID newObjectIDRangeStart[] , + [in, size_is(cMovedObjectIDRanges)] SIZE_T cObjectIDRangeLength[] ); + + /* + * The CLR calls SurvivingReferences with information about + * object references that survived a garbage collection. + * + * Generally, the CLR calls SurvivingReferences for non-compacting garbage collections. + * For compacting garbage collections, MovedReferences is called instead. + * + * The exception to this rule is that the CLR always calls SurvivingReferences for objects + * in the large object heap, which is not compacted. + * + * Multiple calls to SurvivingReferences may be received during a particular + * garbage collection, due to limited internal buffering, multiple threads reporting + * in the case of server gc, and other reasons. + * In the case of multiple calls, the information is cumulative - all of the references + * reported in any SurvivingReferences call survive this collection. + * + * cSurvivingObjectIDRanges is a count of the number of ObjectID ranges that + * survived. + * objectIDRangeStart is an array of elements, each of which is the start + * value of a range of ObjectID values that survived the collection. + * cObjectIDRangeLength is an array of elements, each of which states the + * size of the surviving ObjectID value range. + * + * The last two arguments of this function are parallel arrays. + * + * In other words, if an ObjectID value lies within the range + * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] + * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection + * + * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::SurvivingReferences2 + * is called first and ICorProfilerCallback2::SurvivingReferences is called second but only if + * ICorProfilerCallback4::SurvivingReferences2 returned success. Profilers can return failure + * from ICorProfilerCallback4::SurvivingReferences2 to save some chattiness. + */ + HRESULT SurvivingReferences2( + [in] ULONG cSurvivingObjectIDRanges, + [in, size_is(cSurvivingObjectIDRanges)] ObjectID objectIDRangeStart[] , + [in, size_is(cSurvivingObjectIDRanges)] SIZE_T cObjectIDRangeLength[] ); + +}; + + +[ + object, + uuid(8DFBA405-8C9F-45F8-BFFA-83B14CEF78B5), + pointer_default(unique), + local +] +interface ICorProfilerCallback5 : ICorProfilerCallback4 +{ + /* + * The CLR calls ConditionalWeakTableElementReferences with information + * about dependent handles after a garbage collection has occurred. + * + * For each root ID in rootIds, keyRefIds will contain the ObjectID for + * the primary element in the dependent handle pair, and valueRefIds will + * contain the ObjectID for the secondary element (keyRefIds[i] keeps + * valueRefIds[i] alive). + * + * NOTE: None of the objectIDs returned by ConditionalWeakTableElementReferences + * are valid during the callback itself, as the GC may be in the middle + * of moving objects from old to new. Thus profilers should not attempt + * to inspect objects during a ConditionalWeakTableElementReferences call. + * At GarbageCollectionFinished, all objects have been moved to their new + * locations, and inspection may be done. + */ + HRESULT ConditionalWeakTableElementReferences( + [in] ULONG cRootRefs, + [in, size_is(cRootRefs)] ObjectID keyRefIds[], + [in, size_is(cRootRefs)] ObjectID valueRefIds[], + [in, size_is(cRootRefs)] GCHandleID rootIds[]); +}; + + +[ + object, + uuid(FC13DF4B-4448-4F4F-950C-BA8D19D00C36), + pointer_default(unique), + local +] +interface ICorProfilerCallback6 : ICorProfilerCallback5 +{ + // Controlled by the COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES event mask flag. + // Notifies the profiler of a very early stage in the loading of an Assembly, where the CLR + // performs an assembly reference closure walk. This is useful ONLY if the profiler will need + // to modify the metadata of the Assembly to add AssemblyRefs (later, in ModuleLoadFinished). In + // such a case, the profiler should implement this callback as well, to inform the CLR that assembly references + // will be added once the module has loaded. This is useful to ensure that assembly sharing decisions + // made by the CLR during this early stage remain valid even though the profiler plans to modify the metadata + // assembly references later on. This can be used to avoid some instances where profiler metadata + // modifications can cause the SECURITY_E_INCOMPATIBLE_SHARE error to be thrown. + // + // The profiler uses the ICorProfilerAssemblyReferenceProvider provided to add assembly references + // to the CLR assembly reference closure walker. The ICorProfilerAssemblyReferenceProvider + // should only be used from within this callback. The profiler will still need to explicitly add assembly + // references via IMetaDataAssemblyEmit, from within the ModuleLoadFinished callback for the referencing assembly, + // even though the profiler implements this GetAssemblyReferences callback. This callback does not result in + // modified metadata; only in a modified assembly reference closure walk. + // + // The profiler should be prepared to receive duplicate calls to this callback for the same assembly, + // and should respond identically for each such duplicate call (by making the same set of + // ICorProfilerAssemblyReferenceProvider::AddAssemblyReference calls). + HRESULT GetAssemblyReferences( + [in, string] const WCHAR * wszAssemblyPath, + [in] ICorProfilerAssemblyReferenceProvider * pAsmRefProvider); +}; + + +[ + object, + uuid(F76A2DBA-1D52-4539-866C-2AA518F9EFC3), + pointer_default(unique), + local +] +interface ICorProfilerCallback7 : ICorProfilerCallback6 +{ + // This event is triggered whenever the symbol stream associated with an + // in-memory module is updated. Even when symbols are provided up-front in + // a call to the managed API Assembly.Load(byte[], byte[], ...) the runtime + // may not actually associate the symbolic data with the module until after + // the ModuleLoadFinished callback has occured. This event provides a later + // opportunity to collect symbols for such modules. + // + // This event is controlled by the COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED + // event mask flag. + // + // Note: This event is not currently raised for symbols implicitly created or + // modified via Reflection.Emit APIs. + HRESULT ModuleInMemorySymbolsUpdated(ModuleID moduleId); +} + + +[ + object, + uuid(5BED9B15-C079-4D47-BFE2-215A140C07E0), + pointer_default(unique), + local +] +interface ICorProfilerCallback8 : ICorProfilerCallback7 +{ + // This event is triggered whenever a dynamic method is jit compiled. + // These include various IL Stubs and LCG Methods. + // The goal is to provide profiler writers with enough information to identify + // it to users as beyond unknown code addresses. + // Note: FunctionID's provided here cannot be used to resolve to their metadata + // tokens since dynamic methods have no metadata. + // + // Documentation Note: pILHeader is only valid during the callback + + HRESULT DynamicMethodJITCompilationStarted( + [in] FunctionID functionId, + [in] BOOL fIsSafeToBlock, + [in] LPCBYTE pILHeader, + [in] ULONG cbILHeader); + + HRESULT DynamicMethodJITCompilationFinished( + [in] FunctionID functionId, + [in] HRESULT hrStatus, + [in] BOOL fIsSafeToBlock); +} + +[ + object, + uuid(27583EC3-C8F5-482F-8052-194B8CE4705A), + pointer_default(unique), + local +] +interface ICorProfilerCallback9 : ICorProfilerCallback8 +{ + // This event is triggered whenever a dynamic method is garbage collected + // and subsequently unloaded. + + HRESULT DynamicMethodUnloaded([in] FunctionID functionId); +} + + +/* + * COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific + * method. A combination of COR_PRF_CODEGEN_FLAGS is provided by the + * profiler in its call to ICorProfilerFunctionControl::SetCodegenFlags() + * when rejitting a method. + */ +typedef enum +{ + COR_PRF_CODEGEN_DISABLE_INLINING = 0x0001, + COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x0002, +} COR_PRF_CODEGEN_FLAGS; + + +/* + * The CLR implements the ICorProfilerInfo interface. This interface is + * used by a code profiler to communicate with the CLR to control event + * monitoring and request information. The CLR passes an + * ICorProfilerInfo interface to each code profiler during initialization. + * + * A code profiler can call methods on the ICorProfilerInfo interface to get + * information about managed code being executed under the control of the CLR + * + * The ICorProfilerInfo interface implemented by the CLR uses the free + * threaded model. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + * + */ + +[ + object, + uuid(28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48), + pointer_default(unique), + local +] +interface ICorProfilerInfo : IUnknown +{ + /* + * The code profiler calls GetClassFromObject to obtain the ClassID of an + * object given its ObjectID. + */ + HRESULT GetClassFromObject( + [in] ObjectID objectId, + [out] ClassID *pClassId); + + /* + * V2 MIGRATION WARNING - DOES NOT WORK FOR GENERIC TYPES + * + * This function will be removed in a future release, so + * use GetClassFromTokenAndTypeArgs for all types. + */ + HRESULT GetClassFromToken( + [in] ModuleID moduleId, + [in] mdTypeDef typeDef, + [out] ClassID *pClassId); + + /* + * V2 MIGRATION WARNING - WILL NOT WORK WITH .NET FRAMEWORK + * FUNCTIONS + * + * This function will be removed in a future release; use GetCodeInfo2 + * in all cases. + */ + HRESULT GetCodeInfo( + [in] FunctionID functionId, + [out] LPCBYTE *pStart, + [out] ULONG *pcSize); + + /* + * RECOMMENDATION: USE GetEventMask2 INSTEAD. WHILE THIS METHOD CONTINUES TO + * TO WORK, GetEventMask2 PROVIDES MORE FUNCTIONALITY. + * + * The code profiler calls GetEventMask to obtain the current event + * categories for which it is to receive event notifications from the COM+ + * Runtime. + */ + HRESULT GetEventMask( + [out] DWORD *pdwEvents); + + /* + * The code profiler calls GetFunctionFromIP to map an instruction pointer + * in managed code to a FunctionID. + */ + HRESULT GetFunctionFromIP( + [in] LPCBYTE ip, + [out] FunctionID *pFunctionId); + + /* + * V2 MIGRATION WARNING - WILL NOT WORK FOR GENERIC FUNCTIONS OR + * FUNCTIONS ON GENERIC TYPES + * + * This function will be removed in a future release, so use + * GetFunctionFromTokenAndTypeArgs for all functions. + */ + HRESULT GetFunctionFromToken( + [in] ModuleID moduleId, + [in] mdToken token, + [out] FunctionID *pFunctionId); + + /* + * The code profiler calls GetHandleFromThread to map a ThreadID to a Win32 + * thread handle. The profiler must call DuplicateHandle on the handle + * before using it. + */ + HRESULT GetHandleFromThread( + [in] ThreadID threadId, + [out] HANDLE *phThread); + + /* + * The code profiler calls GetObjectSize to obtain the size of an object. + * Note that types like arrays and strings may have a different size for each object. + * + * THIS API IS OBSOLETE. It does not work for objects >4GB on 64-bit platforms. + * Use ICorProfilerInfo4::GetObjectSize2 instead. + */ + HRESULT GetObjectSize( + [in] ObjectID objectId, + [out] ULONG *pcSize); + + /* + * This will return S_OK if the ClassID provided is an array class, and will + * fill out the information for any non-null out params. S_FALSE will be + * returned if the ClassID is not an array. + * + * classId : the ClassID to return information about + * pBaseElemType : the array's base element type + * pBaseClassId : the base ClassID if the element type == ELEMENT_TYPE_CLASS + * pcRank : the number of dimensions of the array + */ + HRESULT IsArrayClass( + [in] ClassID classId, + [out] CorElementType *pBaseElemType, + [out] ClassID *pBaseClassId, + [out] ULONG *pcRank); + + /* + * The code profiler calls GetThreadInfo to obtain the current Win32 thread ID for + * the specified thread. + */ + HRESULT GetThreadInfo( + [in] ThreadID threadId, + [out] DWORD *pdwWin32ThreadId); + + /* + * The code profiler calls GetCurrentThreadID to get the managed thread ID + * for the current thread. + * + * NOTE: GetCurrentThreadID may return CORPROF_E_NOT_MANAGED_THREAD if the + * current thread is an internal runtime thread, and the returned value of + * pThreadId will be NULL. + */ + HRESULT GetCurrentThreadID( + [out] ThreadID *pThreadId); + + /* + * V2 MIGRATION NOTE - More information is available for generic types + * from GetClassIDInfo2. + * + * Returns the parent module a class is defined in, along with the + * metadata token for the class. One can call GetModuleMetaData + * to obtain the metadata interface for a given module. The token + * can then be used to access the metadata for this class. + */ + HRESULT GetClassIDInfo( + [in] ClassID classId, + [out] ModuleID *pModuleId, + [out] mdTypeDef *pTypeDefToken); + + /* + * Return the parent class for a given function. Also return the metadata + * token which can be used to read the metadata. + * + * V2 MIGRATION WARNING - LESS INFORMATION FOR GENERIC CLASSES + * The ClassID of a function on a generic class may not be obtainable without + * more context about the use of the function. In this case, *pClassId will be 0; + * try using GetFunctionInfo2 with a COR_PRF_FRAME_INFO to give more context. + */ + HRESULT GetFunctionInfo( + [in] FunctionID functionId, + [out] ClassID *pClassId, + [out] ModuleID *pModuleId, + [out] mdToken *pToken); + + /* + * RECOMMENDATION: USE SetEventMask2 INSTEAD. WHILE THIS METHOD CONTINUES TO + * TO WORK, SetEventMask2 PROVIDES MORE FUNCTIONALITY. + * + * The code profiler calls SetEventMask to set the event categories for + * which it is set to receive notification from the CLR. + */ + HRESULT SetEventMask( + [in] DWORD dwEvents); + + /* + * The code profiler calls SetFunctionHooks to specify handlers + * for FunctionEnter, FunctionLeave, and FunctionTailcall. + * + * Note that only one set of callbacks may be active at a time. Thus, + * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 + * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) + * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks + * when both are set. + * + * Each function pointer may be null to disable that callback. + * + * SetEnterLeaveFunctionHooks may only be called from the + * profiler's Initialize() callback. + */ + HRESULT SetEnterLeaveFunctionHooks( + [in] FunctionEnter *pFuncEnter, + [in] FunctionLeave *pFuncLeave, + [in] FunctionTailcall *pFuncTailcall); + + /* + * This is used for mapping FunctionIDs to alternative values that will be + * passed to the callbacks + */ + HRESULT SetFunctionIDMapper( + [in] FunctionIDMapper *pFunc); + + /* + * For a given function, retrieve the token value and an instance of the + * meta data interface which can be used against this token. + */ + HRESULT GetTokenAndMetaDataFromFunction( + [in] FunctionID functionId, + [in] REFIID riid, + [out] IUnknown **ppImport, + [out] mdToken *pToken); + + /* + * Retrieve information about a given module. + * + * When the module is loaded from disk, the name returned will be the filename; + * otherwise, the name will be the name from the metadata Module table (i.e., + * the same as the managed System.Reflection.Module.ScopeName). + * + * NOTE: While this function may be called as soon as the moduleId is alive, + * the AssemblyID of the containing assembly will not be available until the + * ModuleAttachedToAssembly callback. + * + * NOTE: More information is available by using ICorProfilerInfo3::GetModuleInfo2 instead. + */ + HRESULT GetModuleInfo( + [in] ModuleID moduleId, + [out] LPCBYTE *ppBaseLoadAddress, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out, annotation("_Out_writes_to_(cchName, *pcchName)")] + WCHAR szName[] , + [out] AssemblyID *pAssemblyId); + + /* + * Get a metadata interface instance which maps to the given module. + * One may ask for the metadata to be opened in read+write mode, but + * this will result in slower metadata execution of the program, because + * changes made to the metadata cannot be optimized as they were from + * the compiler. + * + * NOTE: Some modules (such as resource modules) have no metadata. In + * those cases, GetModuleMetaData will return S_FALSE, and a NULL + * IUnknown. + * + * NOTE: the only values valid for dwOpenFlags are ofRead and ofWrite. + */ + HRESULT GetModuleMetaData( + [in] ModuleID moduleId, + [in] DWORD dwOpenFlags, + [in] REFIID riid, + [out] IUnknown **ppOut); + + /* + * Retrieve a pointer to the body of a method starting at it's header. + * A method is scoped by the module it lives in. Because this function + * is designed to give a tool access to IL before it has been loaded + * by the Runtime, it uses the metadata token of the method to find + * the instance desired. + * + * GetILFunctionBody can return CORPROF_E_FUNCTION_NOT_IL if the methodId + * points to a method without any IL (such as an abstract method, or a + * P/Invoke method). + */ + HRESULT GetILFunctionBody( + [in] ModuleID moduleId, + [in] mdMethodDef methodId, + [out] LPCBYTE *ppMethodHeader, + [out] ULONG *pcbMethodSize); + + /* + * IL method bodies must be located as RVA's to the loaded module, which + * means they come after the module within 4 gb. In order to make it + * easier for a tool to swap out the body of a method, this allocator + * will ensure memory is allocated within that range. + */ + HRESULT GetILFunctionBodyAllocator( + [in] ModuleID moduleId, + [out] IMethodMalloc **ppMalloc); + + /* + * Replaces the method body for a function in a module. This will replace + * the RVA of the method in the metadata to point to this new method body, + * and adjust any internal data structures as required. This function can + * only be called on those methods which have never been compiled by a JITTER. + * Please use the GetILFunctionAllocator to allocate space for the new method to + * ensure the buffer is compatible. + */ + HRESULT SetILFunctionBody( + [in] ModuleID moduleId, + [in] mdMethodDef methodid, + [in] LPCBYTE pbNewILMethodHeader); + + /* + * Retrieve app domain information given its id. + */ + HRESULT GetAppDomainInfo( + [in] AppDomainID appDomainId, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out, annotation("_Out_writes_to_(cchName, *pcchName)")] + WCHAR szName[] , + [out] ProcessID *pProcessId); + + /* + * Retrieve information about an assembly given its ID. + */ + HRESULT GetAssemblyInfo( + [in] AssemblyID assemblyId, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out, annotation("_Out_writes_to_(cchName, *pcchName)")] + WCHAR szName[] , + [out] AppDomainID *pAppDomainId, + [out] ModuleID *pModuleId); + + + /* + * V2 MIGRATION WARNING: DEPRECATED. Returns E_NOTIMPL always. + * + * See ICorProfilerInfo4::RequestReJIT instead + * + */ + HRESULT SetFunctionReJIT( + [in] FunctionID functionId); + + /* + * ForceGC forces a GC to occur within the runtime. + * + * NOTE: This method needs to be called from a thread that does not have any + * profiler callbacks on its stack. The most convenient way to implement this is + * to create a separate thread within the profiler and have it call ForceGC when + * signalled. + */ + HRESULT ForceGC(); + + /* + * + * V2 MIGRATION NOTE - Calling SetILInstrumentedCodeMap on any one + * of the multiple FunctionIDs that represent a generic function in a given + * AppDomain will affect all instantiations of that function in the AppDomain. + * + * fStartJit should be set to true the first time this function is called for + * a given FunctionID, and false thereafter. + * + * The format of the map is as follows: + * The debugger will assume that each oldOffset refers to an IL offset + * within the original, unmodified IL code. newOffset refers to the corresponding + * IL offset within the new, instrumented code. + * + * The map should be sorted in increasing order. For stepping to work properly: + * - Instrumented IL should not be reordered (so both old & new are sorted) + * - original IL should not be removed + * - the map should include entries to map all of the sequence points from the pdb. + * + * The map does not interpolate missing entries. So given the following map: + * (0 old, 0 new) + * (5 old, 10 new) + * (9 old, 20 new) + * - An old offset of 0,1,2,3,4 will be mapped to a new offset of 0 + * - An old offset of 5,6,7, or 8 will be mapped to new offset 10. + * - An old offset of 9 or higher will be mapped to new offset 20. + * - A new offset of 0, 1,...8,9 will be mapped to old offset 0 + * - A new offset of 10,11,...18,19 will be mapped to old offset 5. + * - A new offset of 20 or higher will be mapped to old offset 9. + * + */ + HRESULT SetILInstrumentedCodeMap( + [in] FunctionID functionId, + [in] BOOL fStartJit, + [in] ULONG cILMapEntries, + [in, size_is(cILMapEntries)] COR_IL_MAP rgILMapEntries[] ); + + /* + * DEPRECATED. + */ + HRESULT GetInprocInspectionInterface( + [out] IUnknown **ppicd); + + /* + * DEPRECATED. + */ + HRESULT GetInprocInspectionIThisThread( + [out] IUnknown **ppicd); + + /* + * This will return the ContextID currently associated with the calling + * runtime thread. This will set pContextId to NULL if the calling thread + * is not a runtime thread. + */ + HRESULT GetThreadContext( + [in] ThreadID threadId, + [out] ContextID *pContextId); + + /* + * DEPRECATED. + */ + HRESULT BeginInprocDebugging( + [in] BOOL fThisThreadOnly, + [out] DWORD *pdwProfilerContext); + + /* + * DEPRECATED. + */ + HRESULT EndInprocDebugging( + [in] DWORD dwProfilerContext); + + /* + * GetILToNativeMapping returns a map from IL offsets to native + * offsets for this code. An array of COR_PROF_IL_TO_NATIVE_MAP + * structs will be returned, and some of the ilOffsets in this array + * may be the values specified in CorDebugIlToNativeMappingTypes. + */ + HRESULT GetILToNativeMapping( + [in] FunctionID functionId, + [in] ULONG32 cMap, + [out] ULONG32 *pcMap, + [out, size_is(cMap), length_is(*pcMap)] + COR_DEBUG_IL_TO_NATIVE_MAP map[]); +} + +/* + * The CLR implements the ICorProfilerInfo2 interface. This interface is + * used by a code profiler to communicate with the CLR to control event + * monitoring and request information. The CLR passes an + * ICorProfilerInfo2 interface to each code profiler during initialization. + * + * A code profiler can call methods on the ICorProfilerInfo2 interface to get + * information about managed code being executed under the control of the CLR + * + * The ICorProfilerInfo2 interface implemented by the CLR uses the free + * threaded model. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + * + */ + +[ + object, + uuid(CC0935CD-A518-487d-B0BB-A93214E65478), + pointer_default(unique), + local +] +interface ICorProfilerInfo2 : ICorProfilerInfo +{ + /* + * The code profiler calls DoStackSnapshot to do sparse one-off stack snapshots. + * + * Passing NULL for thread yields a snapshot of the current thread. If a ThreadID + * of a different thread is passed, the runtime will suspend that thread, perform + * the snapshot, and resume. + * + * infoFlags come from the COR_PRF_SNAPSHOT_INFO enum. + * + * context is a platform-dependent CONTEXT structure, representing the complete + * register context that the profiling API will use to seed the stack walk. If this + * is non-NULL, it must point to JITd or NGENd code, or else DoStackSnapshot + * will return CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX. Contexts are + * only provided by profilers that hijack threads to force them to walk their + * own stacks; profilers should not attempt to provide a context when walking + * another thread's stack. If context is NULL, the stack walk will begin at the + * last available managed frame for the target thread. + * + * See the definition of StackSnapshotCallback for more information. + */ + HRESULT DoStackSnapshot( + [in] ThreadID thread, + [in] StackSnapshotCallback *callback, + [in] ULONG32 infoFlags, + [in] void *clientData, + [in, size_is(contextSize)] BYTE context[], + [in] ULONG32 contextSize); + + /* + * The code profiler calls SetFunctionHooks2 to specify handlers + * for FunctionEnter2, FunctionLeave2, and FunctionTailcall2 + * callbacks. + * + * Note that only one set of callbacks may be active at a time. Thus, + * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 + * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) + * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks + * when both are set. + * + * Each pointer may be null to disable that particular callback. + * + * SetEnterLeaveFunctionHooks2 may only be called from the + * profiler's Initialize() callback. + */ + HRESULT SetEnterLeaveFunctionHooks2( + [in] FunctionEnter2 *pFuncEnter, + [in] FunctionLeave2 *pFuncLeave, + [in] FunctionTailcall2 *pFuncTailcall); + + /* + * GetFunctionInfo2 returns the parent class of a function, plus the + * function's metadata token and the ClassIDs of its type arguments + * (if any). + * + * When a COR_PRF_FRAME_INFO obtained from a FunctionEnter2 + * callback is passed, the ClassID and all type arguments will be exact. + * + * When a COR_PRF_FRAME_INFO from any other source is passed, or + * when 0 is passed as the frameInfo argument, exact ClassID and type + * arguments cannot always be determined. The value returned in pClassId + * may be NULL and some type args will come back as System.Object. + * + */ + HRESULT GetFunctionInfo2( + [in] FunctionID funcId, + [in] COR_PRF_FRAME_INFO frameInfo, + [out] ClassID *pClassId, + [out] ModuleID *pModuleId, + [out] mdToken *pToken, + [in] ULONG32 cTypeArgs, + [out] ULONG32 *pcTypeArgs, + [out] ClassID typeArgs[]); + + /* + * GetStringLayout returns detailed information about how string objects are stored. + * + * *pBufferLengthOffset is the offset (from the ObjectID pointer) to a DWORD that + * stores the length of the string's buffer + * + * *pStringLengthOffset is the offset (from the ObjectID pointer) to a DWORD that + * stores the length of the string itself + * + * *pBufferOffset is the offset (from the ObjectID pointer) to the actual buffer + * of wide characters + * + * Strings may or may not be null-terminated. + */ + HRESULT GetStringLayout( + [out] ULONG *pBufferLengthOffset, + [out] ULONG *pStringLengthOffset, + [out] ULONG *pBufferOffset); + + /* + * GetClassLayout returns detailed information how a specific class is stored. + * It only returns the fields defined by the class itself; if the parent class + * defined fields as well, the profiler must call GetClassLayout on the parent class + * to obtain those fields. + * + * It will fail with E_INVALIDARG for string and array classes. + */ + HRESULT GetClassLayout( + [in] ClassID classID, + [in, out] COR_FIELD_OFFSET rFieldOffset[], + [in] ULONG cFieldOffset, + [out] ULONG *pcFieldOffset, + [out] ULONG *pulClassSize); + + /* + * Returns the parent module a class is defined in, along with the + * metadata token for the class, the ClassID of its parent class, and the + * ClassIDs of its type arguments (if any). + * + * One can call GetModuleMetaData to obtain the metadata interface for + * a given module. The token can then be used to access the metadata for this + * class. + */ + HRESULT GetClassIDInfo2( + [in] ClassID classId, + [out] ModuleID *pModuleId, + [out] mdTypeDef *pTypeDefToken, + [out] ClassID *pParentClassId, + [in] ULONG32 cNumTypeArgs, + [out] ULONG32 *pcNumTypeArgs, + [out] ClassID typeArgs[]); + + /* + * GetCodeInfo2 returns the extents of native code associated with the + * given FunctionID. These extents are returned sorted in order of increasing + * IL offset. + */ + HRESULT GetCodeInfo2( + [in] FunctionID functionID, + [in] ULONG32 cCodeInfos, + [out] ULONG32 *pcCodeInfos, + [out, size_is(cCodeInfos), length_is(*pcCodeInfos)] + COR_PRF_CODE_INFO codeInfos[]); + + /* + * GetClassFromTokenAndTypeArgs returns the ClassID of a type given its metadata + * token (typedef) and the ClassIDs of its type arguments (if any). + * + * cTypeArgs must be equal to the number of type parameters for the given type + * (0 for non-generic types) + * typeArgs may be NULL if cTypeArgs == 0 + * + * Calling this function with a TypeRef token can have unpredictable results; callers + * should resolve the TypeRef to a TypeDef and use that. + * + * If the type is not already loaded, calling this function will cause it to be. + * Loading is a dangerous operation in many contexts. For example, calling + * this function during loading of modules or other types could lead to an infinite + * loop as the runtime attempts to circularly load things. + * + * In general, use of this function is discouraged. If profilers are interested in + * events for a particular type, they should store the ModuleID and TypeDef of that type, + * and use GetClassIDInfo2 to check whether a given ClassID is the desired type. + */ + HRESULT GetClassFromTokenAndTypeArgs( + [in] ModuleID moduleID, + [in] mdTypeDef typeDef, + [in] ULONG32 cTypeArgs, + [in, size_is(cTypeArgs)] ClassID typeArgs[], + [out] ClassID* pClassID); + + /* + * GetFunctionFromTokenAndTypeArgs returns the FunctionID of a function given + * its metadata token (methoddef), containing class, and type args (if any). + * + * classID may be 0 if the containing class is not generic + * typeArgs may be NULL if cTypeArgs == 0 + * + * Calling this function with a MethodRef token can have unpredictable results; callers + * should resolve the MethodRef to a MethodDef and use that. + * + * If the function is not already loaded, calling this function will cause it to be. + * Loading is a dangerous operation in many contexts. For example, calling + * this function during loading of modules or types could lead to an infinite + * loop as the runtime attempts to circularly load things. + * + * In general, use of this function is discouraged. If profilers are interested in + * events for a particular function, they should store the ModuleID and MethodDef of that function, + * and use GetFunctionInfo2 to check whether a given FunctionID is the desired function. + */ + HRESULT GetFunctionFromTokenAndTypeArgs( + [in] ModuleID moduleID, + [in] mdMethodDef funcDef, + [in] ClassID classId, + [in] ULONG32 cTypeArgs, + [in, size_is(cTypeArgs)] ClassID typeArgs[], + [out] FunctionID* pFunctionID); + + /* + * Returns an enumerator over all frozen objects in the given module. + */ + HRESULT EnumModuleFrozenObjects( + [in] ModuleID moduleID, + [out] ICorProfilerObjectEnum** ppEnum); + + + + /* + * GetArrayObjectInfo returns detailed information about an array object. + * objectId is a valid array object. + * cDimensions is the rank (# of dimensions). + * On success: + * pDimensionSizes, pDimensionLowerBounds are parallel arrays describing the size and lower bound for each dimension. + * (*ppData) is a pointer to the raw buffer for the array, which is laid out according to the C++ + * convention + */ + HRESULT GetArrayObjectInfo( + [in] ObjectID objectId, + [in] ULONG32 cDimensions, + [out, size_is(cDimensions)] ULONG32 pDimensionSizes[], + [out, size_is(cDimensions)] int pDimensionLowerBounds[], + [out] BYTE **ppData); + + /* + * GetBoxClassLayout returns information about how a particular value type is laid out + * when boxed. + * + * *pBufferOffset is the offset (from the ObjectID pointer) to where the value type + * is stored within the box. The value type's class layout may then be used to + * interpret it. + */ + HRESULT GetBoxClassLayout( + [in] ClassID classId, + [out] ULONG32 *pBufferOffset); + + + /* + * GetThreadAppDomain returns the AppDomainID currently associated with\ + * the given ThreadID + */ + HRESULT GetThreadAppDomain( + [in] ThreadID threadId, + [out] AppDomainID *pAppDomainId); + + + /* + * GetRVAStaticAddress gets the address of the home for the given + * RVA static. It must be called from a managed thread. Otherwise, + * it will return CORPROF_E_NOT_MANAGED_THREAD. + */ + HRESULT GetRVAStaticAddress( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [out] void **ppAddress); + + /* + * GetAppDomainStaticAddress gets the address of the home for the given + * AppDomain static in the given AppDomain. + * + * This function may return CORPROF_E_DATAINCOMPLETE if the given static + * has not been assigned a home in the given AppDomain. + */ + HRESULT GetAppDomainStaticAddress( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [in] AppDomainID appDomainId, + [out] void **ppAddress); + + /* + * GetThreadStaticAddress gets the address of the home for the given + * Thread static in the given Thread. threadId must be the current thread + * ID or NULL, which means using curernt thread ID. + * + * This function may return CORPROF_E_DATAINCOMPLETE if the given static + * has not been assigned a home in the given Thread. + */ + HRESULT GetThreadStaticAddress( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [in] ThreadID threadId, + [out] void **ppAddress); + + /* + * GetContextStaticAddress gets the address of the home for the given + * Context static in the given context. It must be called from a managed + * thread. Otherwise, it will return CORPROF_E_NOT_MANAGED_THREAD. + * + * This function may return CORPROF_E_DATAINCOMPLETE if the given static + * has not been assigned a home in the given Context. + */ + HRESULT GetContextStaticAddress( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [in] ContextID contextId, + [out] void **ppAddress); + + /* + * GetStaticFieldInfo gets COR_PRF_STATIC_TYPE for a specific + * field in a class. This information can be used to decide which + * function to call to get the address of the static. + * + * NOTE: One should still check the metadata for a static to ensure + * it is actually going to have an address. Statics that are literals + * (aka constants) exist only in the metadata and do not have an address. + * + */ + HRESULT GetStaticFieldInfo( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [out] COR_PRF_STATIC_TYPE *pFieldInfo); + + /* + * GetGenerationBounds returns the memory regions that make up a given + * GC generation in memory. It may be called from any profiler callback as long + * as a GC is not in progress. (To be exact, it may be called from any callback + * except for those that occur between GarbageCollectionStarted and GarbageCollectionFinished.) + * + * Most shifting of generations takes place during garbage collections; between + * collections generations may grow, but generally do not move around. Therefore + * the most interesting places to call this function are in GarbageCollectionStarted + * and Finished. + * + * During program startup, some objects are allocated by the CLR itself, generally + * in generations 3 and 0. So by the time managed code starts executing, these + * generations will already contain objects. Generations 1 and 2 will be normally + * empty, except for dummy objects generated by the garbage collector (of size 12 + * bytes in 32-bit implementations of the CLR, larger in 64-bit implementaions). + * You may also see generation 2 ranges that are inside modules generated by ngen. + * These are "frozen objects" generated at ngen time rather than allocated by the + * garbage collector. + * + * cObjectRanges is a count of the number of elements allocated by the caller for + * the ranges array + * pcObjectRanges is an out param for the number of ranges in the given generation + * ranges is an array of elements of type COR_PRF_GC_GENERATION_RANGE, each of which + * describes a range of memory used by the garbage collector + */ + + HRESULT GetGenerationBounds( + [in] ULONG cObjectRanges, + [out] ULONG *pcObjectRanges, + [out, size_is(cObjectRanges), length_is(*pcObjectRanges)] COR_PRF_GC_GENERATION_RANGE ranges[]); + + /* + * GetObjectGeneration returns which generation the given object is currently in, along + * with the start and length of the segment containing the object. It may be called + * at any time as long as a GC is not in progress. + */ + + HRESULT GetObjectGeneration( + [in] ObjectID objectId, + [out] COR_PRF_GC_GENERATION_RANGE *range); + + + /* + * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used + * to get the native address and frame information for the exception clause (catch/finally/filter) + * that is about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) + * or has just been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). + * + * This call may be made at any time after one of the Enter calls above until either the matching + * Leave call is received or until a nested exception throws out of the current clause in which case + * there will be no Leave notification for that clause. Note it is not possible for a throw to escape + * a Filter so there is always a Leave in that case. + * + * Return values: + * S_OK indicates success + * S_FALSE indicates that no exception clause is active + * CORPROF_E_NOT_MANAGED_THREAD indicates an unmanaged thread. + */ + + HRESULT GetNotifiedExceptionClauseInfo( + [out] COR_PRF_EX_CLAUSE_INFO *pinfo); +} + +/* + * The CLR implements the ICorProfilerInfo3 interface. This interface is + * used by a code profiler to communicate with the CLR to control event + * monitoring and request information. The CLR passes an + * ICorProfilerInfo3 interface to each code profiler during initialization. + * + * A code profiler can call methods on the ICorProfilerInfo3 interface to get + * information about managed code being executed under the control of the CLR + * + * The ICorProfilerInfo3 interface implemented by the CLR uses the free + * threaded model. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + * + */ + +[ + object, + uuid(B555ED4F-452A-4E54-8B39-B5360BAD32A0), + pointer_default(unique), + local +] +interface ICorProfilerInfo3 : ICorProfilerInfo2 +{ + /* + * Returns an enumerator for all previously jitted functions. May overlap with + * functions previously reported via CompilationStarted callbacks. + * NOTE: The returned enumeration will only include '0' for the value of the + * COR_PRF_FUNCTION::reJitId field. If you require valid COR_PRF_FUNCTION::reJitId values, use + * ICorProfilerInfo4::EnumJITedFunctions2. + */ + HRESULT EnumJITedFunctions([out] ICorProfilerFunctionEnum** ppEnum); + + HRESULT RequestProfilerDetach([in] DWORD dwExpectedCompletionMilliseconds); + + HRESULT SetFunctionIDMapper2( + [in] FunctionIDMapper2 *pFunc, + [in] void *clientData); + + /* + * GetStringLayout2 returns detailed information about how string objects are stored. + * + * *pStringLengthOffset is the offset (from the ObjectID pointer) to a DWORD that + * stores the length of the string itself + * + * *pBufferOffset is the offset (from the ObjectID pointer) to the actual buffer + * of wide characters + * + * Strings may or may not be null-terminated. + */ + HRESULT GetStringLayout2( + [out] ULONG *pStringLengthOffset, + [out] ULONG *pBufferOffset); + + /* + * The code profiler calls SetFunctionHooks3 to specify handlers + * for FunctionEnter3, FunctionLeave3, and FunctionTailcall3, and calls + * SetFunctionHooks3WithInfo to specify handlers for FunctionEnter3WithInfo, + * FunctionLeave3WithInfo, and FunctionTailcall3WithInfo. + * + * Note that only one set of callbacks may be active at a time. Thus, + * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 + * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) + * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks + * when both are set. + * + * Each function pointer may be null to disable that callback. + * + * SetEnterLeaveFunctionHooks3(WithInfo) may only be called from the + * profiler's Initialize() callback. + */ + HRESULT SetEnterLeaveFunctionHooks3( + [in] FunctionEnter3 *pFuncEnter3, + [in] FunctionLeave3 *pFuncLeave3, + [in] FunctionTailcall3 *pFuncTailcall3); + + + HRESULT SetEnterLeaveFunctionHooks3WithInfo( + [in] FunctionEnter3WithInfo *pFuncEnter3WithInfo, + [in] FunctionLeave3WithInfo *pFuncLeave3WithInfo, + [in] FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + /* + * The profiler can call GetFunctionEnter3Info to gather frame info and argument info + * in FunctionEnter3WithInfo callback. The profiler needs to allocate sufficient space + * for COR_PRF_FUNCTION_ARGUMENT_INFO of the function it's inspecting and indicate the + * size in a ULONG pointed by pcbArgumentInfo. + */ + HRESULT GetFunctionEnter3Info( + [in] FunctionID functionId, + [in] COR_PRF_ELT_INFO eltInfo, + [out] COR_PRF_FRAME_INFO *pFrameInfo, + [in, out] ULONG *pcbArgumentInfo, + [out, size_is(*pcbArgumentInfo)] COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + /* + * The profiler can call GetFunctionLeave3Info to gather frame info and return value + * in FunctionLeave3WithInfo callback. + */ + HRESULT GetFunctionLeave3Info( + [in] FunctionID functionId, + [in] COR_PRF_ELT_INFO eltInfo, + [out] COR_PRF_FRAME_INFO *pFrameInfo, + [out] COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + /* + * The profiler can call GetFunctionTailcall3Info to gather frame info in + * FunctionTailcall3WithInfo callback. + */ + HRESULT GetFunctionTailcall3Info( + [in] FunctionID functionId, + [in] COR_PRF_ELT_INFO eltInfo, + [out] COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT EnumModules([out] ICorProfilerModuleEnum** ppEnum); + + /* + * The profiler can call GetRuntimeInformation to query CLR version information. + * Passing NULL to any parameter is acceptable except pcchVersionString cannot + * be NULL if szVersionString is not NULL. + */ + HRESULT GetRuntimeInformation([out] USHORT *pClrInstanceId, + [out] COR_PRF_RUNTIME_TYPE *pRuntimeType, + [out] USHORT *pMajorVersion, + [out] USHORT *pMinorVersion, + [out] USHORT *pBuildNumber, + [out] USHORT *pQFEVersion, + [in] ULONG cchVersionString, + [out] ULONG *pcchVersionString, + [out, annotation("_Out_writes_to_(cchVersionString, *pcchVersionString)")] + WCHAR szVersionString[]); + + /* + * GetThreadStaticAddress2 gets the address of the home for the given + * Thread static in the given Thread. + * + * This function may return CORPROF_E_DATAINCOMPLETE if the given static + * has not been assigned a home in the given Thread. + */ + HRESULT GetThreadStaticAddress2( + [in] ClassID classId, + [in] mdFieldDef fieldToken, + [in] AppDomainID appDomainId, + [in] ThreadID threadId, + [out] void **ppAddress); + + /* + * GetAppDomainsContainingModule returns the AppDomainIDs in which the + * given module has been loaded + */ + HRESULT GetAppDomainsContainingModule( + [in] ModuleID moduleId, + [in] ULONG32 cAppDomainIds, + [out] ULONG32 *pcAppDomainIds, + [out, size_is(cAppDomainIds), length_is(*pcAppDomainIds)] AppDomainID appDomainIds[]); + + + /* + * Retrieve information about a given module. + * + * When the module is loaded from disk, the name returned will be the filename; + * otherwise, the name will be the name from the metadata Module table (i.e., + * the same as the managed System.Reflection.Module.ScopeName). + * + * *pdwModuleFlags will be filled in with a bitmask of values from COR_PRF_MODULE_FLAGS + * that specify some properties of the module. + * + * NOTE: While this function may be called as soon as the moduleId is alive, + * the AssemblyID of the containing assembly will not be available until the + * ModuleAttachedToAssembly callback. + * + */ + HRESULT GetModuleInfo2( + [in] ModuleID moduleId, + [out] LPCBYTE *ppBaseLoadAddress, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out, annotation("_Out_writes_to_(cchName, *pcchName)")] + WCHAR szName[], + [out] AssemblyID *pAssemblyId, + [out] DWORD *pdwModuleFlags); + + +} + + +/* + * This interface lets you iterate over the frozen objects from ngen images. + */ + +[ + object, + uuid(2C6269BD-2D13-4321-AE12-6686365FD6AF), + pointer_default(unique), + local +] +interface ICorProfilerObjectEnum : IUnknown +{ + HRESULT Skip( + [in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone( + [out] ICorProfilerObjectEnum **ppEnum); + + HRESULT GetCount( + [out] ULONG *pcelt); + + HRESULT Next( + [in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] ObjectID objects[], + [out] ULONG *pceltFetched); +} + + +/* + * This interface lets you iterate over functions in the runtime. + */ + +[ + object, + uuid(FF71301A-B994-429D-A10B-B345A65280EF), + pointer_default(unique), + local +] +interface ICorProfilerFunctionEnum : IUnknown +{ + HRESULT Skip([in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone([out] ICorProfilerFunctionEnum **ppEnum); + + HRESULT GetCount([out] ULONG *pcelt); + + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + COR_PRF_FUNCTION ids[], + [out] ULONG * pceltFetched); +}; + +/* + * This interface lets you iterate over modules in the runtime. + */ + +[ + object, + uuid(b0266d75-2081-4493-af7f-028ba34db891), + pointer_default(unique), + local +] +interface ICorProfilerModuleEnum : IUnknown +{ + HRESULT Skip([in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone([out] ICorProfilerModuleEnum **ppEnum); + + HRESULT GetCount([out] ULONG *pcelt); + + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ModuleID ids[], + [out] ULONG * pceltFetched); +}; + +/* + * NOTE: DEPRECATED, now you can use your any allocator. + * + * This is simple allocator that only allows you to allocate memory. + * You may not free it. This was used in conjunction with + * ICorProfilerInfo::SetILFunctionBody. + */ +[ + object, + uuid(A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8), + pointer_default(unique), + local +] +interface IMethodMalloc : IUnknown +{ + /* + * Tries to allocate memory above the start address of the module from + * which it was created. It is important to note that this method may + * fail to allocate the memory specified above the start address, and + * may as a result return NULL. + */ + PVOID Alloc( + [in] ULONG cb); +} + +/* + * The CLR implements the ICorProfilerFunctionControl interface. This interface + * is used by a code profiler to communicate with the CLR to control how the + * JIT should generate code when rejitting a specific method. + * + * The ICorProfilerFunctionControl interface implemented by the CLR uses the + * free threaded model. + */ + +[ + object, + uuid(F0963021-E1EA-4732-8581-E01B0BD3C0C6), + pointer_default(unique), + local +] +interface ICorProfilerFunctionControl : IUnknown +{ + /* + * Set one or more flags from COR_PRF_CODEGEN_FLAGS to control code + * generation just for this method. + */ + HRESULT SetCodegenFlags( + [in] DWORD flags); + + /* + * Override the method body. + */ + HRESULT SetILFunctionBody( + [in] ULONG cbNewILMethodHeader, + [in, size_is(cbNewILMethodHeader)] LPCBYTE pbNewILMethodHeader); + + /* + * This is not currently implemented, and will return E_NOTIMPL + */ + HRESULT SetILInstrumentedCodeMap( + [in] ULONG cILMapEntries, + [in, size_is(cILMapEntries)] COR_IL_MAP rgILMapEntries[]); + +} + +/* + * The CLR implements the ICorProfilerInfo4 interface. This interface is + * used by a code profiler to communicate with the CLR to control event + * monitoring and request information. The CLR passes an + * ICorProfilerInfo4 interface to each code profiler during initialization. + * + * A code profiler can call methods on the ICorProfilerInfo4 interface to get + * information about managed code being executed under the control of the CLR + * + * The ICorProfilerInfo4 interface implemented by the CLR uses the free + * threaded model. + * + * The methods implemented on this interface return S_OK on success, or E_FAIL + * on failure. + * + */ + +[ + object, + uuid(0d8fdcaa-6257-47bf-b1bf-94dac88466ee), + pointer_default(unique), + local +] +interface ICorProfilerInfo4 : ICorProfilerInfo3 +{ + HRESULT EnumThreads([out] ICorProfilerThreadEnum **ppEnum); + HRESULT InitializeCurrentThread(); + + /* + * Call RequestReJIT to have the runtime re-JIT a particular set of methods. + * A code profiler can then adjust the code generated when the method is + * re-JITed through the ICorProfilerFunctionControl interface. This does + * not impact currently executing methods, only future invocations. + * + * A return code of S_OK indicates that all of the requested methods were + * attempted to be rejitted. However, the profiler must implement + * ICorProfilerCallback4::ReJITError to determine which of the methods were + * successfully re-JITed. + * + * A failure return value (E_*) indicates some failure that prevents any + * re-JITs. + */ + HRESULT RequestReJIT( + [in] ULONG cFunctions, + [in, size_is(cFunctions)] ModuleID moduleIds[], + [in, size_is(cFunctions)] mdMethodDef methodIds[]); + + /* + * RequestRevert will instruct the runtime to revert to using/calling the + * original method (original IL and flags) rather than whatever was + * ReJITed. This does not change any currently active methods, only future + * invocations. + * + */ + HRESULT RequestRevert( + [in] ULONG cFunctions, + [in, size_is(cFunctions)] ModuleID moduleIds[], + [in, size_is(cFunctions)] mdMethodDef methodIds[], + [out, size_is(cFunctions)] HRESULT status[]); + + /* + * Same as GetCodeInfo2, except instead of always returning the code info + * associated with the original IL/function, you can request the code info + * for a particular re-JITed version of a function. + */ + HRESULT GetCodeInfo3( + [in] FunctionID functionID, + [in] ReJITID reJitId, + [in] ULONG32 cCodeInfos, + [out] ULONG32 * pcCodeInfos, + [out, size_is(cCodeInfos), length_is(*pcCodeInfos)] + COR_PRF_CODE_INFO codeInfos[]); + + /* + * Same as GetFunctionFromIP, but also returns which re-JITed version is + * associated with the IP address. + */ + HRESULT GetFunctionFromIP2( + [in] LPCBYTE ip, + [out] FunctionID * pFunctionId, + [out] ReJITID * pReJitId); + + /* + * GetReJITIDs can be used to find all of the re-JITed versions of the + * given function. + */ + HRESULT GetReJITIDs( + [in] FunctionID functionId, + [in] ULONG cReJitIds, + [out] ULONG * pcReJitIds, + [out, size_is(cReJitIds), length_is(*pcReJitIds)] + ReJITID reJitIds[]); + + /* + * Same as GetILToNativeMapping, but allows the code profiler to specify + * which re-JITed version it applies to. + */ + HRESULT GetILToNativeMapping2( + [in] FunctionID functionId, + [in] ReJITID reJitId, + [in] ULONG32 cMap, + [out] ULONG32 * pcMap, + [out, size_is(cMap),length_is(*pcMap)] + COR_DEBUG_IL_TO_NATIVE_MAP map[]); + + /* + * Returns an enumerator for all previously jitted functions. May overlap with + * functions previously reported via CompilationStarted callbacks. The returned + * enumeration will include values for the COR_PRF_FUNCTION::reJitId field + */ + HRESULT EnumJITedFunctions2([out] ICorProfilerFunctionEnum** ppEnum); + + /* + * The code profiler calls GetObjectSize to obtain the size of an object. + * Note that types like arrays and strings may have a different size for each object. + */ + HRESULT GetObjectSize2( + [in] ObjectID objectId, + [out] SIZE_T *pcSize); + +} + +[ + object, + uuid(07602928-CE38-4B83-81E7-74ADAF781214), + pointer_default(unique), + local +] +interface ICorProfilerInfo5 : ICorProfilerInfo4 +{ + /* + * The code profiler calls GetEventMask2 to obtain the current event + * categories for which it is to receive event notifications from the CLR + * + * *pdwEventsLow is a bitwise combination of values from COR_PRF_MONITOR + * *pdwEventsHigh is a bitwise combination of values from COR_PRF_HIGH_MONITOR + */ + HRESULT GetEventMask2( + [out] DWORD *pdwEventsLow, + [out] DWORD *pdwEventsHigh); + + /* + * The code profiler calls SetEventMask2 to set the event categories for + * which it is set to receive notification from the CLR. + * + * dwEventsLow is a bitwise combination of values from COR_PRF_MONITOR + * dwEventsHigh is a bitwise combination of values from COR_PRF_HIGH_MONITOR + */ + HRESULT SetEventMask2( + [in] DWORD dwEventsLow, + [in] DWORD dwEventsHigh); +}; + + +[ + object, + uuid(F30A070D-BFFB-46A7-B1D8-8781EF7B698A), + pointer_default(unique), + local +] +interface ICorProfilerInfo6 : ICorProfilerInfo5 +{ + /* + * Returns an enumerator for all methods that + * - belong to a given NGen or R2R module (inlinersModuleId) and + * - inlined a body of a given method (inlineeModuleId / inlineeMethodId). + * + * If incompleteData is set to TRUE after function is called, it means that the methods enumerator + * doesn't contain all methods inlining a given method. + * It can happen when one or more direct or indirect dependencies of inliners module haven't been loaded yet. + * If profiler needs accurate data it should retry later when more modules are loaded (preferably on each module load). + * + * It can be used to lift limitation on inlining for ReJIT. + * + * NOTE: If the inlinee method is decorated with the System.Runtime.Versioning.NonVersionable attribute then + * then some inliners may not ever be reported. If you need to get a full accounting you can avoid the issue + * by disabling the use of all native images. + * + */ + HRESULT EnumNgenModuleMethodsInliningThisMethod( + [in] ModuleID inlinersModuleId, + [in] ModuleID inlineeModuleId, + [in] mdMethodDef inlineeMethodId, + [out] BOOL *incompleteData, + [out] ICorProfilerMethodEnum** ppEnum); +}; + +[ + object, + uuid(9AEECC0D-63E0-4187-8C00-E312F503F663), + pointer_default(unique), + local +] +interface ICorProfilerInfo7 : ICorProfilerInfo6 +{ + /* + * Applies the newly emitted Metadata. + * + * This method can be used to apply the newly defined metadata by IMetadataEmit::Define* methods + * to the module. + * + * If metadata changes are made after ModuleLoadFinished callback, + * it is required to call this method before using the new metadata + */ + HRESULT ApplyMetaData( + [in] ModuleID moduleId); + + /* Returns the length of an in-memory symbol stream + * + * If the module has in-memory symbols the length of the stream will + * be placed in pCountSymbolBytes. If the module doesn't have in-memory + * symbols, *pCountSymbolBytes = 0 + * + * Returns S_OK if the length could be determined (even if it is 0) + * + * Note: The current implementation does not support reflection.emit. + * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. + */ + HRESULT GetInMemorySymbolsLength( + [in] ModuleID moduleId, + [out] DWORD* pCountSymbolBytes); + + /* Reads bytes from an in-memory symbol stream + * + * This function attempts to read countSymbolBytes of data starting at offset + * symbolsReadOffset within the in-memory stream. The data will be copied into + * pSymbolBytes which is expected to have countSymbolBytes of space available. + * pCountSymbolsBytesRead contains the actual number of bytes read which + * may be less than countSymbolBytes if the end of the stream is reached. + * + * Returns S_OK if a non-zero number of bytes were read. + * + * Note: The current implementation does not support reflection.emit. + * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. + */ + HRESULT ReadInMemorySymbols( + [in] ModuleID moduleId, + [in] DWORD symbolsReadOffset, + [out] BYTE* pSymbolBytes, + [in] DWORD countSymbolBytes, + [out] DWORD* pCountSymbolBytesRead); + +}; + +[ + object, + uuid(C5AC80A6-782E-4716-8044-39598C60CFBF), + pointer_default(unique), + local +] +interface ICorProfilerInfo8 : ICorProfilerInfo7 +{ + /* + * Determines if a function has associated metadata + * + * Certain methods like IL Stubs or LCG Methods do not have + * associated metadata that can be retrieved using the IMetaDataImport APIs. + * + * Such methods can be encountered by profilers through instruction pointers + * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted + * + * This API can be used to determine whether a FunctionID is dynamic. + */ + HRESULT IsFunctionDynamic( [in] FunctionID functionId, + [out] BOOL *isDynamic); + + /* + * Maps a managed code instruction pointer to a FunctionID. + * + * GetFunctionFromIP2 fails for dynamic methods, this method works for + * both dynamic and non-dynamic methods. It is a superset of GetFunctionFromIP2 + */ + HRESULT GetFunctionFromIP3([in] LPCBYTE ip, + [out] FunctionID *functionId, + [out] ReJITID * pReJitId); + + /* + * Retrieves informaiton about dynamic methods + * + * Certain methods like IL Stubs or LCG do not have + * associated metadata that can be retrieved using the IMetaDataImport APIs. + * + * Such methods can be encountered by profilers through instruction pointers + * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted + * + * This API can be used to retrieve information about dynamic methods + * including a friendly name if available. + */ + HRESULT GetDynamicFunctionInfo( [in] FunctionID functionId, + [out] ModuleID *moduleId, + [out] PCCOR_SIGNATURE *ppvSig, + [out] ULONG *pbSig, + [in] ULONG cchName, + [out] ULONG *pcchName, + [out] WCHAR wszName[]); +}; + +[ + object, + uuid(008170DB-F8CC-4796-9A51-DC8AA0B47012), + pointer_default(unique), + local +] +interface ICorProfilerInfo9 : ICorProfilerInfo8 +{ + //Given functionId + rejitId, enumerate the native code start address of all jitted versions of this code that currently exist + HRESULT GetNativeCodeStartAddresses(FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[]); + + //Given the native code start address, return the native->IL mapping information for this jitted version of the code + HRESULT GetILToNativeMapping3(UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[]); + + //Given the native code start address, return the the blocks of virtual memory that store this code (method code is not necessarily stored in a single contiguous memory region) + HRESULT GetCodeInfo4(UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32* pcCodeInfos, COR_PRF_CODE_INFO codeInfos[]); +}; + +[ + object, + uuid(2F1B5152-C869-40C9-AA5F-3ABE026BD720), + pointer_default(unique), + local +] +interface ICorProfilerInfo10 : ICorProfilerInfo9 +{ + // Given an ObjectID, callback and clientData, enumerates each object reference (if any). + HRESULT EnumerateObjectReferences(ObjectID objectId, ObjectReferenceCallback callback, void* clientData); + + // Given an ObjectID, determines whether it is in a read only segment. + HRESULT IsFrozenObject(ObjectID objectId, BOOL *pbFrozen); + + // Gets the value of the configured LOH Threshold. + HRESULT GetLOHObjectSizeThreshold(DWORD *pThreshold); + + /* + * This method will ReJIT the methods requested, as well as any inliners + * of the methods requested. + * + * RequestReJIT does not do any tracking of inlined methods. The profiler + * was expected to track inlining and call RequestReJIT for all inliners + * to make sure every instance of an inlined method was ReJITted. + * This poses a problem with ReJIT on attach, since the profiler was + * not present to monitor inlining. This method can be called to guarantee + * that the full set of inliners will be ReJITted as well. + */ + HRESULT RequestReJITWithInliners( + [in] DWORD dwRejitFlags, + [in] ULONG cFunctions, + [in, size_is(cFunctions)] ModuleID moduleIds[], + [in, size_is(cFunctions)] mdMethodDef methodIds[]); + + // Suspend the runtime without performing a GC. + HRESULT SuspendRuntime(); + + // Restart the runtime from a previous suspension. + HRESULT ResumeRuntime(); +} + +/* +* This interface lets you iterate over methods in the runtime. +*/ + +[ + object, + uuid(FCCEE788-0088-454B-A811-C99F298D1942), + pointer_default(unique), + local +] +interface ICorProfilerMethodEnum : IUnknown +{ + HRESULT Skip([in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone([out] ICorProfilerMethodEnum **ppEnum); + + HRESULT GetCount([out] ULONG *pcelt); + + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + COR_PRF_METHOD elements[], + [out] ULONG * pceltFetched); +} + +/* + * This interface lets you iterate over threads in the runtime. + */ + +[ + object, + uuid(571194f7-25ed-419f-aa8b-7016b3159701), + pointer_default(unique), + local +] +interface ICorProfilerThreadEnum : IUnknown +{ + HRESULT Skip([in] ULONG celt); + + HRESULT Reset(); + + HRESULT Clone([out] ICorProfilerThreadEnum **ppEnum); + + HRESULT GetCount([out] ULONG *pcelt); + + HRESULT Next([in] ULONG celt, + [out, size_is(celt), length_is(*pceltFetched)] + ThreadID ids[], + [out] ULONG * pceltFetched); +} + + +/* + * This interface is given to the profiler in the GetAssemblyReferences() callback, to + * allow the profiler to inform the CLR of assembly references that the profiler plans to + * add later on during ModuleLoadFinished. This improves the accuracy of the CLR assembly + * reference closure walker, and its algorithms for determining whether assemblies may be shared + * + * This interface is valid for use only within the GetAssemblyReferences callback that passed + * this interface to the profiler + */ +[ + object, + uuid(66A78C24-2EEF-4F65-B45F-DD1D8038BF3C), + pointer_default(unique), + local +] +interface ICorProfilerAssemblyReferenceProvider : IUnknown +{ + // The profiler calls this for each target assembly it plans to reference from the + // assembly specified in the wszAssemblyPath argument of the GetAssemblyReferences callback. + HRESULT AddAssemblyReference(const COR_PRF_ASSEMBLY_REFERENCE_INFO * pAssemblyRefInfo); +}; diff --git a/lib/coreclr/src/inc/corpub.idl b/lib/coreclr/src/inc/corpub.idl new file mode 100644 index 0000000000..f5f0e73640 --- /dev/null +++ b/lib/coreclr/src/inc/corpub.idl @@ -0,0 +1,265 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* -------------------------------------------------------------------------- * + * Common Language Runtime Process Publishing Interfaces + * -------------------------------------------------------------------------- */ + +cpp_quote("#if 0") +#ifndef DO_NO_IMPORTS +import "unknwn.idl"; +#endif +cpp_quote("#endif") + +typedef enum +{ + COR_PUB_MANAGEDONLY = 0x00000001 // Must always be set, + // only enumerates + // managed processes +} COR_PUB_ENUMPROCESS; + + +/* -------------------------------------------------------------------------- * + * Forward declarations + * -------------------------------------------------------------------------- */ +#pragma warning(push) +#pragma warning(disable:28718) //Unable to annotate as this is not a local interface + +interface ICorPublish; +interface ICorPublishProcess; +interface ICorPublishAppDomain; +interface ICorPublishProcessEnum; +interface ICorPublishAppDomainEnum; + +#pragma warning(pop) + +/* ------------------------------------------------------------------------- * + * Library defintion + * ------------------------------------------------------------------------- */ + +[ + uuid(e97ca460-657d-11d3-8d5b-00104b35e7ef), + version(1.0), + helpstring("Common Language Runtime Process Publishing Library") +] +library CorpubProcessLib +{ + importlib("STDOLE2.TLB"); + + // CorPublish is a shared component across all version of the runtime. + [ + uuid(047a9a40-657e-11d3-8d5b-00104b35e7ef) + ] + coclass CorpubPublish + { + [default] interface ICorPublish; + interface ICorPublishProcess; + interface ICorPublishAppDomain; + interface ICorPublishProcessEnum; + interface ICorPublishAppDomainEnum; + }; +}; + + +/* -------------------------------------------------------------------------- * + * Interface definitions + * -------------------------------------------------------------------------- */ + +/* + * This interface is the top level interface for publishing of processes. + */ +[ + object, + uuid(9613A0E7-5A68-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublish : IUnknown +{ + /* + * Retrieves a list of managed processes on this machine which + * the current user has permission to debug. In this version, + * Type must always be equal to COR_PUB_MANAGEDONLY. + * The list is based on a snapshot of the processes running when + * the enum method is called. The enumerator will not reflect any + * processes that start before or terminate after EnumProcesses is called. + * If EnumProcesses is called more than once on this ICorPublish + * instance, a new up-to-date enumeration will be returned without + * affecting any previous ones. + */ + HRESULT EnumProcesses([in] COR_PUB_ENUMPROCESS Type, + [out] ICorPublishProcessEnum **ppIEnum); + + /* + * Gets a new ICorPublishProcess object for the managed process + * with the given process ID. Returns failure if the process doesn't + * exist, or isn't a managed process that can be debugged by the current + * user. + */ + HRESULT GetProcess([in] unsigned pid, + [out] ICorPublishProcess **ppProcess); +} + +/* + * An abstract enumerator. + */ +[ + object, + uuid(C0B22967-5A69-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublishEnum : IUnknown +{ + /* + * Moves the current position forward the given number of + * elements. + */ + HRESULT Skip([in] ULONG celt); + + /* + * Sets the position of the enumerator to the beginning of the + * enumeration. + */ + HRESULT Reset(); + + /* + * Creates another enumerator with the same current position + * as this one. + */ + HRESULT Clone([out] ICorPublishEnum **ppEnum); + + /* + * Gets the number of elements in the enumeration + */ + HRESULT GetCount([out] ULONG *pcelt); +}; + +#pragma warning(push) +#pragma warning(disable:28718) +/* + * Describes a process on a machine. + */ +[ + object, + uuid(18D87AF1-5A6A-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublishProcess : IUnknown +{ + /* + * Returns true if the process is known to have managed code + * running in it. Since this version of ICorPublish only provides access + * to managed processes, this method always returns true. + */ + HRESULT IsManaged([out] BOOL *pbManaged); + + /* + * Enumerates the list of known application domains in this process. + * This list is based on a snapshot of the existing AppDomains when + * this method is called. This method may be called more than + * once to create a new up-to-date list. Existing enumerations will not + * be affected by calls to this method. If the process has been + * terminated, this will fail with CORDBG_E_PROCESS_TERMINATED. + */ + HRESULT EnumAppDomains([out] ICorPublishAppDomainEnum **ppEnum); + + /* + * Returns the OS ID for this process. + */ + HRESULT GetProcessID([out] unsigned *pid); + + /* + * Get the full path of the executable for this process. + * If szName is non-null, this copies up to cchName characters (including + * the null terminator) into szName, and ensures it is null-terminated. + * If pcchName is non-null, the actual number of characters in the name + * (including the null terminator) is stored there. This method returns + * S_OK regardless of how many characters were copied. + */ + HRESULT GetDisplayName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR *szName); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable:28718) +/* + * Provide information on an Application Domain object. + */ +[ + object, + uuid(D6315C8F-5A6A-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublishAppDomain : IUnknown +{ + /* + * Gets the identification number of this application domain. + * Note that this number is unique to this AppDomain, but only + * within the containing process. + */ + HRESULT GetID([out] ULONG32 *puId); + + /* + * Get the name for an application domain. + * If szName is non-null, this copies up to cchName characters (including + * the null terminator) into szName, and ensures it is null-terminated. + * If pcchName is non-null, the actual number of characters in the name + * (including the null terminator) is stored there. This method returns + * S_OK regardless of how many characters were copied. + */ + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR *szName); +} +#pragma warning(pop) + + +/* + * Enumerate a list of processes based on the filter criteria given + * when the enumerator object was created. + */ +[ + object, + uuid(A37FBD41-5A69-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublishProcessEnum : ICorPublishEnum +{ + /* + * Gets the next "celt" processes in the enumeration. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), + length_is(*pceltFetched)] ICorPublishProcess **objects, + [out] ULONG *pceltFetched); +} + +/* + * Enumerate a list of app domains based in a process. + */ +[ + object, + uuid(9F0C98F5-5A6A-11d3-8F84-00A0C9B4D50C), + pointer_default(unique), + local +] +interface ICorPublishAppDomainEnum : ICorPublishEnum +{ + /* + * Gets the next "celt" application domains in the enumeration. + */ + HRESULT Next([in] ULONG celt, + [out, size_is(celt), + length_is(*pceltFetched)] ICorPublishAppDomain **objects, + [out] ULONG *pceltFetched); +} + diff --git a/lib/coreclr/src/inc/corsym.idl b/lib/coreclr/src/inc/corsym.idl new file mode 100644 index 0000000000..8d7aa3f67d --- /dev/null +++ b/lib/coreclr/src/inc/corsym.idl @@ -0,0 +1,1785 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* ------------------------------------------------------------------------- * + * Common Language Runtime Debugging Symbol Reader/Writer/Binder Interfaces + * ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- * + * Imported types + * ------------------------------------------------------------------------- */ + +cpp_quote("#if 0") +typedef UINT32 mdToken; +typedef mdToken mdTypeDef; +typedef mdToken mdMethodDef; +typedef SIZE_T IMAGE_DEBUG_DIRECTORY; +cpp_quote("#endif") + +cpp_quote("#ifndef __CORHDR_H__") +typedef mdToken mdSignature; +cpp_quote("#endif") + +#include "winerror.h" + +/* ------------------------------------------------------------------------- * + * Guids for known languages, language vendors, and document types + * ------------------------------------------------------------------------- */ + +cpp_quote("EXTERN_GUID(CorSym_LanguageType_C, 0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_CPlusPlus, 0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_CSharp, 0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_Basic, 0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_Java, 0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_Cobol, 0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_Pascal, 0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_ILAssembly, 0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_JScript, 0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x00, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_SMC, 0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);") +cpp_quote("EXTERN_GUID(CorSym_LanguageType_MCPlusPlus, 0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") +cpp_quote("EXTERN_GUID(CorSym_LanguageVendor_Microsoft, 0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") +cpp_quote("EXTERN_GUID(CorSym_DocumentType_Text, 0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);") +cpp_quote("EXTERN_GUID(CorSym_DocumentType_MC, 0xeb40cb65, 0x3c1f, 0x4352, 0x9d, 0x7b, 0xba, 0xf, 0xc4, 0x7a, 0x9d, 0x77);") + +#ifdef INTEROPLIB +module LanguageType +{ + const LPSTR C = "{63a08714-fc37-11d2-904c-00c04fa302a1}"; + const LPSTR CPlusPlus = "{3a12d0b7-c26c-11d0-b442-00a0244a1dd2}"; + const LPSTR CSharp = "{3f5162f8-07c6-11d3-9053-00c04fa302a1}"; + const LPSTR Basic = "{3a12d0b8-c26c-11d0-b442-00a0244a1dd2}"; + const LPSTR Java = "{3a12d0b4-c26c-11d0-b442-00a0244a1dd2}"; + const LPSTR Cobol = "{af046cd1-d0e1-11d2-977c-00a0c9b4d50c}"; + const LPSTR Pascal = "{af046cd2-d0e1-11d2-977c-00a0c9b4d50c}"; + const LPSTR ILAssembly ="{af046cd3-d0e1-11d2-977c-00a0c9b4d50c}"; + const LPSTR JScript = "{3a12d0b6-c26c-11d0-b442-00a0244a1dd2}"; + const LPSTR SMC = "{0d9b9f7b-6611-11d3-bd2a-0000f80849bd}"; + const LPSTR MCPlusPlus ="{4b35fde8-07c6-11d3-9053-00c04fa302a1}"; +} + + +module ErrorCodes80 +{ + const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead); +} + + +#endif // ndef INTEROPLIB + + +/* ------------------------------------------------------------------------- * + * Guids for known Source Hash Algorithms + * ------------------------------------------------------------------------- */ + +cpp_quote("EXTERN_GUID(CorSym_SourceHash_MD5, 0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99);") +cpp_quote("EXTERN_GUID(CorSym_SourceHash_SHA1, 0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60);") + + +/* ------------------------------------------------------------------------- * + * Forward declarations + * ------------------------------------------------------------------------- */ + +interface ISymUnmanagedDocument; +interface ISymUnmanagedDocumentWriter; +interface ISymUnmanagedMethod; +interface ISymUnmanagedNamespace; +interface ISymUnmanagedReader; +interface ISymUnmanagedReaderSymbolSearchInfo; +interface ISymUnmanagedScope; +interface ISymUnmanagedVariable; +interface ISymUnmanagedSymbolSearchInfo; +interface ISymUnmanagedWriter; +interface ISymUnmanagedWriter2; +interface ISymUnmanagedBinder; + +/* ------------------------------------------------------------------------- * + * CorSymAddrKind -- specifies the kinds of addresses used by the interfaces + * ------------------------------------------------------------------------- */ + +typedef enum CorSymAddrKind +{ + /* + * ADDR_IL_OFFSET: addr1 = IL local var or param index. + */ + ADDR_IL_OFFSET = 1, + + /* + * ADDR_NATIVE_RVA: addr1 = RVA into module. + */ + ADDR_NATIVE_RVA = 2, + + /* + * ADDR_NATIVE_REGISTER: addr1 = register the var is stored in. + */ + ADDR_NATIVE_REGISTER = 3, + + /* + * ADDR_NATIVE_REGREL: addr1 = register, addr2 = offset. + */ + ADDR_NATIVE_REGREL = 4, + + /* + * ADDR_NATIVE_OFFSET: addr1 = offset from start of parent. + */ + ADDR_NATIVE_OFFSET = 5, + + /* + * ADDR_NATIVE_REGREG: addr1 = reg low, addr2 = reg high. + */ + ADDR_NATIVE_REGREG = 6, + + /* + * ADDR_NATIVE_REGSTK: addr1 = reg low, addr2 = reg stk, addr3 = offset. + */ + ADDR_NATIVE_REGSTK = 7, + + /* + * ADDR_NATIVE_STKREG: addr1 = reg stk, addr2 = offset, addr3 = reg high. + */ + ADDR_NATIVE_STKREG = 8, + + /* + * ADDR_BITFIELD: addr1 = field start, addr = field length. + */ + ADDR_BITFIELD = 9, + + /* + * ADDR_NATIVE_SECTOFF: addr1 = section, addr = offset + */ + ADDR_NATIVE_ISECTOFFSET = 10 + +} CorSymAddrKind; + +typedef enum CorSymVarFlag { + + /* + * VAR_IS_COMP_GEN: Variable is compiler generated. + */ + VAR_IS_COMP_GEN = 1 + +} CorSymVarFlag; + +/* ------------------------------------------------------------------------- * + * Library defintion + * + * Use the _SxS coclasses for tools designed to work with .NET Framework + * 1.1 and above. On computers that only have version 1.0 installed, fall + * back to the _deprecated coclasses if CoCreating the _SxS ones fails. + * ------------------------------------------------------------------------- */ + +#ifndef INTEROPLIB + +[ + uuid(7E348441-7E1F-380E-A0F6-22668F0F9E4B), + version(1.0), + helpstring("Common Language Runtime Symbol Store 1.0 Type Library") +] +library CorSymLib +{ + importlib("STDOLE2.TLB"); + +#endif // ndef INTEROPLIB + + + [ + uuid(108296C1-281E-11d3-BD22-0000F80849BD) + ] + coclass CorSymWriter_deprecated + { + [default] interface ISymUnmanagedWriter; + }; + + [ + uuid(108296C2-281E-11d3-BD22-0000F80849BD) + ] + coclass CorSymReader_deprecated + { + [default] interface ISymUnmanagedReader; + }; + + [ + uuid(AA544D41-28CB-11d3-BD22-0000F80849BD) + ] + coclass CorSymBinder_deprecated + { + [default] interface ISymUnmanagedBinder; + }; + + [ + uuid(0AE2DEB0-F901-478b-BB9F-881EE8066788) + ] + coclass CorSymWriter_SxS + { + [default] interface ISymUnmanagedWriter; + }; + + [ + uuid(0A3976C5-4529-4ef8-B0B0-42EED37082CD) + ] + coclass CorSymReader_SxS + { + [default] interface ISymUnmanagedReader; + }; + + [ + uuid(0A29FF9E-7F9C-4437-8B11-F424491E3931) + ] + coclass CorSymBinder_SxS + { + [default] interface ISymUnmanagedBinder; + }; + + +#ifndef INTEROPLIB +}; +#endif // ndef INTEROPLIB + + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedBinder interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(AA544D42-28CB-11d3-BD22-0000F80849BD), + pointer_default(unique) +] +interface ISymUnmanagedBinder : IUnknown +{ + /* + * Given a metadata interface and a file name, returns the + * correct ISymUnmanagedReader that will read the debugging symbols + * associated with the module. + * + * This will only open the Pdb if it is next to the Exe. + * This change has been made for security purposes + * + * If you need a more extensive search for the pdb + * use ISymUnmanagedBinder2. + */ + + HRESULT GetReaderForFile([in] IUnknown *importer, + [in] const WCHAR *fileName, + [in] const WCHAR *searchPath, + [out, retval] ISymUnmanagedReader **pRetVal); + + /* + * Given a metadata interface and a stream that contains + * the symbol store, returns the correct ISymUnmanagedReader + * that will read the debugging symbols from the given + * symbol store. + */ + HRESULT GetReaderFromStream([in] IUnknown *importer, + [in] IStream *pstream, + [out,retval] ISymUnmanagedReader **pRetVal); +}; + +typedef enum CorSymSearchPolicyAttributes +{ + AllowRegistryAccess = 0x1, // query the registry for symbol search paths + AllowSymbolServerAccess = 0x2, // access a symbol server + AllowOriginalPathAccess = 0x4, // look at the path specified in Debug Directory + AllowReferencePathAccess = 0x8 // look for PDB in the place where the exe is. +} CorSymSearchPolicyAttributes; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedBinder2 interface: QI from an ISymUnmanagedBinder + * ------------------------------------------------------------------------- */ +[ + object, + uuid(ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434), + pointer_default(unique) +] +interface ISymUnmanagedBinder2 : ISymUnmanagedBinder +{ + /* + * Given a metadata interface and a file name, returns the correct + * ISymUnmanagedReader interface that will read the debugging symbols associated + * with the module. + * + * This version of the function can search for the PDB in areas other than + * right next to the module. + * The search policy can be controlled by combining CorSymSearchPolicyAttributes + * e.g AllowReferencePathAccess|AllowSymbolServerAccess will look for the pdb next + * to the PE file and on a symbol server, but won't query the registry or use the path + * in the PE file. + * If a searchPath is provided, those directories will always be searched. + */ + + HRESULT GetReaderForFile2([in] IUnknown *importer, + [in] const WCHAR *fileName, + [in] const WCHAR *searchPath, + [in] ULONG32 searchPolicy, + [out,retval] ISymUnmanagedReader **pRetVal); + +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedBinder3 interface: QI from an ISymUnmanagedBinder + * ------------------------------------------------------------------------- */ +[ + object, + uuid(28AD3D43-B601-4d26-8A1B-25F9165AF9D7), + pointer_default(unique) +] +interface ISymUnmanagedBinder3 : ISymUnmanagedBinder2 +{ + /* + * GetReaderFromCallback allows the user to implement supply via callback either an + * IID_IDiaReadExeAtRVACallback or IID_IDiaReadExeAtOffsetCallback to obtain the + * Debug directory information from memory. + */ + HRESULT GetReaderFromCallback([in] IUnknown *importer, + [in] const WCHAR *fileName, + [in] const WCHAR *searchPath, + [in] ULONG32 searchPolicy, + [in] IUnknown *callback, + [out,retval] ISymUnmanagedReader **pRetVal); +}; + +cpp_quote("static const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead);") + +[ + object, + uuid(969708D2-05E5-4861-A3B0-96E473CDF63F), + pointer_default(unique) +] +interface ISymUnmanagedDispose : IUnknown +{ + + /* + * Calling this function will cause the underlying object to + * release all internal references and return failure on any subsequent + * method calls. + */ + + HRESULT Destroy(); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedDocument interface + * + * Represents a document referenced by a symbol store. A document is defined + * by an URL and a document type GUID. Using the URL and document type GUID, + * one can locate the document however it is stored. Document source can + * optionally be stored in the symbol store, and retrieved through this + * interface. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(40DE4037-7C81-3E1E-B022-AE1ABFF2CA08), + pointer_default(unique) +] +interface ISymUnmanagedDocument : IUnknown +{ + /* + * Return the URL for this document. + */ + HRESULT GetURL([in] ULONG32 cchUrl, + [out] ULONG32 *pcchUrl, + [out, size_is(cchUrl), + length_is(*pcchUrl)] WCHAR szUrl[]); + + /* + * Get the document type of this document. + */ + HRESULT GetDocumentType([out, retval] GUID* pRetVal); + + /* + * Get the language id of this document. + */ + HRESULT GetLanguage([out, retval] GUID* pRetVal); + + /* + * Get the language vendor of this document. + */ + HRESULT GetLanguageVendor([out, retval] GUID* pRetVal); + + /* + * Get the check sum algorithm id. Returns a guid of all zeros if + * there is no checksum. + */ + HRESULT GetCheckSumAlgorithmId([out, retval] GUID* pRetVal); + + /* + * Get the check sum. + */ + HRESULT GetCheckSum([in] ULONG32 cData, + [out] ULONG32 *pcData, + [out, size_is(cData), + length_is(*pcData)] BYTE data[]); + + /* + * Given a line in this document that may or may not be a sequence + * point, return the closest line that is a sequence point. */ + HRESULT FindClosestLine([in] ULONG32 line, + [out, retval] ULONG32* pRetVal); + + /* + * Returns true if the document has source embedded in the + * debugging symbols. + */ + HRESULT HasEmbeddedSource([out, retval] BOOL *pRetVal); + + /* + * Returns the length, in bytes, of the embedded source. + */ + HRESULT GetSourceLength([out, retval] ULONG32* pRetVal); + + /* + * Returns the embedded source into the given buffer. The buffer must + * be large enough to hold the source. + */ + HRESULT GetSourceRange([in] ULONG32 startLine, + [in] ULONG32 startColumn, + [in] ULONG32 endLine, + [in] ULONG32 endColumn, + [in] ULONG32 cSourceBytes, + [out] ULONG32 *pcSourceBytes, + [out, size_is(cSourceBytes), + length_is(*pcSourceBytes)] BYTE source[]); + +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedDocumentWriter interface + * + * Provides functions for writing to a document referenced by a symbol + * store. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006), + pointer_default(unique) +] +interface ISymUnmanagedDocumentWriter : IUnknown +{ + /* + * Sets embedded source for a document being written. + */ + HRESULT SetSource([in] ULONG32 sourceSize, + [in, size_is(sourceSize)] BYTE source[]); + + /* + * Sets check sum info. + */ + HRESULT SetCheckSum([in] GUID algorithmId, + [in] ULONG32 checkSumSize, + [in, size_is(checkSumSize)] BYTE checkSum[]); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedMethod interface + * + * Represents a method within the symbol store. Provides access to only the + * symbol-related attributes of a method, rather than type-related attributes. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(B62B923C-B500-3158-A543-24F307A8B7E1), + pointer_default(unique) +] +interface ISymUnmanagedMethod : IUnknown +{ + /* + * Return the metadata token for this method. + */ + HRESULT GetToken([out, retval] mdMethodDef *pToken); + + /* + * Get the count of sequence points within this method. + */ + HRESULT GetSequencePointCount([out, retval] ULONG32* pRetVal); + + /* + * Get the root lexical scope within this method. + * This scope encloses the entire method. + */ + HRESULT GetRootScope([out, retval] ISymUnmanagedScope** pRetVal); + + /* + * Get the most enclosing lexical scope within this method that + * encloses the given offset. This can be used to start + * local variable searches. + */ + HRESULT GetScopeFromOffset([in] ULONG32 offset, + [out, retval] ISymUnmanagedScope** pRetVal); + + /* + * Given a position within a document, return the offset within + * this method that cooresponds to the position. + */ + HRESULT GetOffset([in] ISymUnmanagedDocument* document, + [in] ULONG32 line, + [in] ULONG32 column, + [out, retval] ULONG32* pRetVal); + + /* + * Given a position in a document, return an array of start/end + * offset paris that correspond to the ranges of IL that the + * position covers within this method. The array is an array of + * integers and is [start,end,start,end]. The number of range + * pairs is the length of the array / 2. + */ + HRESULT GetRanges([in] ISymUnmanagedDocument* document, + [in] ULONG32 line, + [in] ULONG32 column, + [in] ULONG32 cRanges, + [out] ULONG32 *pcRanges, + [out, size_is(cRanges), + length_is(*pcRanges)] ULONG32 ranges[]); + + /* + * Get the parameters for this method. The parameters are returned + * in the order they are defined within the method's signature. + */ + HRESULT GetParameters([in] ULONG32 cParams, + [out] ULONG32 *pcParams, + [out, size_is(cParams), + length_is(*pcParams)] ISymUnmanagedVariable* params[]); + + /* + * Get the namespace that this method is defined within. + */ + HRESULT GetNamespace([out] ISymUnmanagedNamespace **pRetVal); + + /* + * Get the start/end document positions for the source of this + * method. The first array position is the start while the second + * is the end. Returns true if positions were defined, false + * otherwise. + */ + HRESULT GetSourceStartEnd([in] ISymUnmanagedDocument *docs[2], + [in] ULONG32 lines[2], + [in] ULONG32 columns[2], + [out] BOOL *pRetVal); + + /* + * Get all the sequence points within this method. + */ + HRESULT GetSequencePoints([in] ULONG32 cPoints, + [out] ULONG32 *pcPoints, + [in, size_is(cPoints)] ULONG32 offsets[], + [in, size_is(cPoints)] ISymUnmanagedDocument* documents[], + [in, size_is(cPoints)] ULONG32 lines[], + [in, size_is(cPoints)] ULONG32 columns[], + [in, size_is(cPoints)] ULONG32 endLines[], + [in, size_is(cPoints)] ULONG32 endColumns[]); +}; + +[ + object, + uuid(85E891DA-A631-4c76-ACA2-A44A39C46B8C), + pointer_default(unique) +] +interface ISymENCUnmanagedMethod : IUnknown +{ + /* + * Get the file name for the line associated with offset dwOffset. + */ + HRESULT GetFileNameFromOffset([in] ULONG32 dwOffset, + [in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * Get the Line information associated with dwOffset. + * If dwOffset is not a sequence point it is associated with the previous one. + * pdwStartOffset provides the associated sequence point. + */ + HRESULT GetLineFromOffset([in] ULONG32 dwOffset, + [out] ULONG32* pline, + [out] ULONG32* pcolumn, + [out] ULONG32* pendLine, + [out] ULONG32* pendColumn, + [out] ULONG32* pdwStartOffset); + + /* + * Get the number of Documents that this method has lines in. + */ + HRESULT GetDocumentsForMethodCount([out, retval] ULONG32* pRetVal); + + /* + * Get the documents this method has lines in. + */ + HRESULT GetDocumentsForMethod([in] ULONG32 cDocs, + [out] ULONG32 *pcDocs, + [in, size_is(cDocs)] ISymUnmanagedDocument* documents[]); + /* + * Get the smallest start line and largest end line, for the method, in a specific document. + */ + HRESULT GetSourceExtentInDocument([in] ISymUnmanagedDocument *document, + [out] ULONG32* pstartLine, + [out] ULONG32* pendLine); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedNamespace interface + * + * Represents a namespace. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(0DFF7289-54F8-11d3-BD28-0000F80849BD), + pointer_default(unique) +] +interface ISymUnmanagedNamespace : IUnknown +{ + /* + * Get the name of this namespace. + */ + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * Get the children of this namespace. + */ + HRESULT GetNamespaces([in] ULONG32 cNameSpaces, + [out] ULONG32 *pcNameSpaces, + [out, size_is(cNameSpaces), + length_is(*pcNameSpaces)] + ISymUnmanagedNamespace* namespaces[]); + + /* + * Return all variables defined at global scope within this namespace. + */ + HRESULT GetVariables([in] ULONG32 cVars, + [out] ULONG32 *pcVars, + [out, size_is(cVars), + length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedReader interface + * + * Represents a symbol reader. Provides access to documents, methods, and + * variables within a symbol store. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5), + pointer_default(unique) +] +interface ISymUnmanagedReader : IUnknown +{ + /* + * Find a document. Language, vendor, and document type are optional. + */ + HRESULT GetDocument([in] WCHAR *url, + [in] GUID language, + [in] GUID languageVendor, + [in] GUID documentType, + [out, retval] ISymUnmanagedDocument** pRetVal); + + /* + * Return an array of all the documents defined in the symbol store. + */ + HRESULT GetDocuments([in] ULONG32 cDocs, + [out] ULONG32 *pcDocs, + [out, size_is(cDocs), + length_is(*pcDocs)] ISymUnmanagedDocument *pDocs[]); + + /* + * Return the method that was specified as the user entry point + * for the module, if any. This would be, perhaps, the user's main + * method rather than compiler generated stubs before main. + */ + HRESULT GetUserEntryPoint([out, retval] mdMethodDef *pToken); + + /* + * Get a symbol reader method given a method token. + */ + HRESULT GetMethod([in] mdMethodDef token, + [out, retval] ISymUnmanagedMethod** pRetVal); + + /* + * Get a symbol reader method given a method token and an E&C + * version number. Version numbers start at 1 and are incremented + * each time the method is changed due to an E&C operation. + */ + HRESULT GetMethodByVersion([in] mdMethodDef token, + [in] int version, + [out, retval] ISymUnmanagedMethod** pRetVal); + + /* + * Return a non-local variable given its parent and name. + */ + HRESULT GetVariables([in] mdToken parent, + [in] ULONG32 cVars, + [out] ULONG32 *pcVars, + [out, size_is(cVars), + length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); + /* + * Return all global variables. + */ + HRESULT GetGlobalVariables([in] ULONG32 cVars, + [out] ULONG32 *pcVars, + [out, size_is(cVars), + length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); + + /* + * Given a position in a document, return the ISymUnmanagedMethod that + * contains that position. + */ + HRESULT GetMethodFromDocumentPosition([in] ISymUnmanagedDocument* document, + [in] ULONG32 line, + [in] ULONG32 column, + [out, retval] ISymUnmanagedMethod** pRetVal); + + /* + * Gets a custom attribute based upon its name. Not to be + * confused with Metadata custom attributes, these attributes are + * held in the symbol store. + */ + HRESULT GetSymAttribute([in] mdToken parent, + [in] WCHAR *name, + [in] ULONG32 cBuffer, + [out] ULONG32 *pcBuffer, + [out, size_is(cBuffer), + length_is(*pcBuffer)] BYTE buffer[]); + + /* + * Get the namespaces defined at global scope within this symbol store. + */ + HRESULT GetNamespaces([in] ULONG32 cNameSpaces, + [out] ULONG32 *pcNameSpaces, + [out, size_is(cNameSpaces), + length_is(*pcNameSpaces)] + ISymUnmanagedNamespace* namespaces[]); + + /* + * Initialize the symbol reader with the metadata importer interface + * that this reader will be associated with, along with the filename + * of the module. This can only be called once, and must be called + * before any other reader methods are called. + * + * Note: you need only specify one of the filename or the pIStream, + * not both. The searchPath parameter is optional. + */ + HRESULT Initialize([in] IUnknown *importer, + [in] const WCHAR *filename, + [in] const WCHAR *searchPath, + [in] IStream *pIStream); + + /* + * Update the existing symbol reader with a delta symbol store. This + * is used in EnC scenarios as a way to update the symbol store to + * match deltas to the original PE file. + * + * Only one of the filename or pIStream parameters need be specified. + * If a filename is specified, the symbol store will be updated with + * the symbols in that file. If a IStream is specified, the store will + * be updated with the data from the IStream. + */ + HRESULT UpdateSymbolStore([in] const WCHAR *filename, + [in] IStream *pIStream); + + /* + * Update the existing symbol reader with a delta symbol + * store. This is much like UpdateSymbolStore, but the given detla + * acts as a complete replacement rather than an update. + * + * Only one of the filename or pIStream parameters need be specified. + * If a filename is specified, the symbol store will be updated with + * the symbols in that file. If a IStream is specified, the store will + * be updated with the data from the IStream. + */ + HRESULT ReplaceSymbolStore([in] const WCHAR *filename, + [in] IStream *pIStream); + + /* + * Provides the on disk filename of the symbol store. + */ + + HRESULT GetSymbolStoreFileName( [in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * Given a position in a document, return the ISymUnmanagedMethods that + * contains that position. + */ + HRESULT GetMethodsFromDocumentPosition([in] ISymUnmanagedDocument* document, + [in] ULONG32 line, + [in] ULONG32 column, + [in] ULONG32 cMethod, + [out] ULONG32* pcMethod, + [out, size_is(cMethod), + length_is(*pcMethod)] ISymUnmanagedMethod* pRetVal[]); + + /* + * Get the given version of the given document. + * The document version starts at 1 and is incremented each time + * the document is updated via UpdateSymbols. + * bCurrent is true is this is the latest version of the document. + */ + HRESULT GetDocumentVersion([in] ISymUnmanagedDocument *pDoc, + [out] int* version, + [out] BOOL* pbCurrent); + + /* + * The method version starts at 1 and is incremented each time + * the method is recompiled. (This can happen without changes to the method.) + */ + HRESULT GetMethodVersion([in] ISymUnmanagedMethod* pMethod, + [out] int* version); + +}; + +// +// ISymUnmanagedSourceServerModule +// +// QI for this interface from an ISymUnmanagedReader +[ + object, + uuid(997DD0CC-A76F-4c82-8D79-EA87559D27AD), + pointer_default(unique) +] +interface ISymUnmanagedSourceServerModule : IUnknown +{ + // returns the source server data for the module + // caller must free using CoTaskMemFree() + HRESULT GetSourceServerData( + [out] ULONG* pDataByteCount, + [out, size_is (, *pDataByteCount)] BYTE** ppData); + +} + +// QI for this interface from an ISymUnmanagedReader +[ + object, + uuid(E502D2DD-8671-4338-8F2A-FC08229628C4), + pointer_default(unique) +] +interface ISymUnmanagedENCUpdate : IUnknown +{ + + // UpdateSymbolStore2: + + // Line deltas allow a compiler to omit functions that have not been modified from + // the pdb stream provided the line information meets the following condition. + // The correct line information can be determined with the old pdb line info and + // one delta for all lines in the function. + // + + typedef struct _SYMLINEDELTA + { + mdMethodDef mdMethod; + INT32 delta; + } SYMLINEDELTA; + + HRESULT UpdateSymbolStore2([in] IStream *pIStream, + [in] SYMLINEDELTA* pDeltaLines, + [in] ULONG cDeltaLines); + + HRESULT GetLocalVariableCount([in] mdMethodDef mdMethodToken, + [out] ULONG *pcLocals); + + HRESULT GetLocalVariables([in] mdMethodDef mdMethodToken, + [in] ULONG cLocals, + [out, size_is(cLocals), + length_is(*pceltFetched)] ISymUnmanagedVariable *rgLocals[], + [out] ULONG *pceltFetched); + + // Perf: Allow method boundaries to be computed before the first + // UpdateSymbolStore2. + HRESULT InitializeForEnc(); + + // + // This allows updating the line info for a method that has not been recompiled, + // but whose lines have moved independently. A delta for each statement is allowed. + // + HRESULT UpdateMethodLines([in] mdMethodDef mdMethodToken, + [in, size_is(cDeltas)] INT32* pDeltas, + [in] ULONG cDeltas); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedReaderSymbolSearchInfo interface + * ------------------------------------------------------------------------- */ + +// QI for this interface from an ISymUnmanagedReader +[ + object, + uuid(20D9645D-03CD-4e34-9C11-9848A5B084F1), + pointer_default(unique) +] +interface ISymUnmanagedReaderSymbolSearchInfo : IUnknown +{ + HRESULT GetSymbolSearchInfoCount([out] ULONG32 *pcSearchInfo); + + HRESULT GetSymbolSearchInfo([in] ULONG32 cSearchInfo, + [out] ULONG32 *pcSearchInfo, + [out, size_is(cSearchInfo), + length_is(*pcSearchInfo)] ISymUnmanagedSymbolSearchInfo **rgpSearchInfo); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedScope interface + * + * Represents a lexical scope within a method. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(68005D0F-B8E0-3B01-84D5-A11A94154942), + pointer_default(unique) +] +interface ISymUnmanagedScope : IUnknown +{ + /* + * Get the method that contains this scope. + */ + HRESULT GetMethod([out, retval] ISymUnmanagedMethod** pRetVal); + + /* + * Get the parent scope of this scope. + */ + HRESULT GetParent([out, retval] ISymUnmanagedScope** pRetVal); + + /* + * Get the children of this scope. + */ + HRESULT GetChildren([in] ULONG32 cChildren, + [out] ULONG32 *pcChildren, + [out, size_is(cChildren), + length_is(*pcChildren)] ISymUnmanagedScope* children[]); + + /* + * Get the start offset for this scope, + */ + HRESULT GetStartOffset([out, retval] ULONG32* pRetVal); + + /* + * Get the end offset for this scope. + */ + HRESULT GetEndOffset([out, retval] ULONG32* pRetVal); + + /* + * Get a count of the number of local variables defined within this + * scope. + */ + HRESULT GetLocalCount([out, retval] ULONG32 *pRetVal); + + /* + * Get the local variables defined within this scope. + */ + HRESULT GetLocals([in] ULONG32 cLocals, + [out] ULONG32 *pcLocals, + [out, size_is(cLocals), + length_is(*pcLocals)] ISymUnmanagedVariable* locals[]); + + /* + * Get the namespaces that are being "used" within this scope. + */ + HRESULT GetNamespaces([in] ULONG32 cNameSpaces, + [out] ULONG32 *pcNameSpaces, + [out, size_is(cNameSpaces), + length_is(*pcNameSpaces)] + ISymUnmanagedNamespace* namespaces[]); +}; + +[ + object, + uuid(48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9), + pointer_default(unique) +] +interface ISymUnmanagedConstant : IUnknown +{ + /* + * Get the name of this constant. + */ + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + HRESULT GetValue(VARIANT* pValue); + + HRESULT GetSignature([in] ULONG32 cSig, + [out] ULONG32 *pcSig, + [out, size_is(cSig), + length_is(*pcSig)] BYTE sig[]); + +}; + +/* + * QI for this interface from an ISymUnmanagedScope. + */ +[ + object, + uuid(AE932FBA-3FD8-4dba-8232-30A2309B02DB), + pointer_default(unique) +] +interface ISymUnmanagedScope2 : ISymUnmanagedScope +{ + /* + * Get a count of the number of constants defined within this + * scope. + */ + HRESULT GetConstantCount([out, retval] ULONG32 *pRetVal); + /* + * Get the local constants defined within this scope. + */ + HRESULT GetConstants([in] ULONG32 cConstants, + [out] ULONG32 *pcConstants, + [out, size_is(cConstants), + length_is(*pcConstants)] ISymUnmanagedConstant* constants[]); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedVariable interface + * + * Represents a variable--a parameter, a local variable, or a field. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB), + pointer_default(unique) +] +interface ISymUnmanagedVariable : IUnknown +{ + /* + * Get the name of this variable. + */ + HRESULT GetName([in] ULONG32 cchName, + [out] ULONG32 *pcchName, + [out, size_is(cchName), + length_is(*pcchName)] WCHAR szName[]); + + /* + * Get the attribute flags for this variable. + */ + HRESULT GetAttributes([out, retval] ULONG32* pRetVal); + + /* + * Get the signature of this variable. + */ + HRESULT GetSignature([in] ULONG32 cSig, + [out] ULONG32 *pcSig, + [out, size_is(cSig), + length_is(*pcSig)] BYTE sig[]); + + /* + * Get the kind of address of this variable + * The retval will be one of the CorSymAddrKind constants. + */ + HRESULT GetAddressKind([out, retval] ULONG32* pRetVal); + + /* + * Get the first address field for this variable. Its meaning depends + * on the address kind. + */ + HRESULT GetAddressField1([out, retval] ULONG32* pRetVal); + + /* + * Get the second address field for this variable. Its meaning depends + * on the address kind. + */ + HRESULT GetAddressField2([out, retval] ULONG32* pRetVal); + + /* + * Get the third address field for this variable. Its meaning depends + * on the address kind. + */ + HRESULT GetAddressField3([out, retval] ULONG32* pRetVal); + + /* + * Get the start offset of this variable within its parent. If this is + * a local variable within a scope, this will fall within the offsets + * defined for the scope. + */ + HRESULT GetStartOffset([out, retval] ULONG32* pRetVal); + + /* + * Get the end offset of this variable within its parent. If this is + * a local variable within a scope, this will fall within the offsets + * defined for the scope. + */ + HRESULT GetEndOffset([out, retval] ULONG32* pRetVal); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedSymbolSearchInfo interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(F8B3534A-A46B-4980-B520-BEC4ACEABA8F), + pointer_default(unique) +] +interface ISymUnmanagedSymbolSearchInfo : IUnknown +{ + HRESULT GetSearchPathLength([out] ULONG32 *pcchPath); + + HRESULT GetSearchPath([in] ULONG32 cchPath, + [out] ULONG32 *pcchPath, + [out, size_is(cchPath), + length_is(*pcchPath)] WCHAR szPath[]); + + HRESULT GetHRESULT([out] HRESULT *phr); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedWriter interface + * + * Represents a symbol writer. Provides methods to define documents, + * sequence points, lexical scopes, and variables. + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(ED14AA72-78E2-4884-84E2-334293AE5214), + pointer_default(unique) +] +interface ISymUnmanagedWriter : IUnknown +{ + /* + * Define a source document. Guid's will be provided for languages, + * vendors, and document types that we currently know about. + */ + HRESULT DefineDocument([in] const WCHAR *url, + [in] const GUID *language, + [in] const GUID *languageVendor, + [in] const GUID *documentType, + [out, retval] ISymUnmanagedDocumentWriter** pRetVal); + + /* + * Define the method that the user has defined as their entry point + * for this module. This would be, perhaps, the user's main method + * rather than compiler generated stubs before main. + */ + HRESULT SetUserEntryPoint([in] mdMethodDef entryMethod); + + /* + * Open a method to emit symbol information into. The given method + * becomes the current method for calls do define sequence points, + * parameters and lexical scopes. There is an implicit lexical + * scope around the entire method. Re-opening a method that has + * been previously closed effectivley erases any previously + * defined symbols for that method. + * + * There can be only one open method at a time. + */ + HRESULT OpenMethod([in] mdMethodDef method); + + /* + * Close the current method. Once a method is closed, no more + * symbols can be defined within it. + */ + HRESULT CloseMethod(); + + /* + * Open a new lexical scope in the current method. The scope + * becomes the new current scope and is effectivley pushed onto a + * stack of scopes. startOffset is the offset, in bytes from the + * beginning of the method, of the first instruction in the + * lexical scope. Scopes must form a hierarchy. Siblings are not + * allowed to overlap. + * + * OpenScope returns an opaque scope id that can be used with + * SetScopeRange to define a scope's start/end offset at a later + * time. In this case, the offsets passed to OpenScope and + * CloseScope are ignored. + * + * Note: scope id's are only valid in the current method. + */ + HRESULT OpenScope([in] ULONG32 startOffset, + [out, retval] ULONG32* pRetVal); + + /* + * Close the current lexical scope. Once a scope is closed no more + * variables can be defined within it. endOffset points past the + * last instruction in the scope. + */ + HRESULT CloseScope([in] ULONG32 endOffset); + + /* + * Define the offset range for a given lexical scope. + */ + HRESULT SetScopeRange([in] ULONG32 scopeID, + [in] ULONG32 startOffset, + [in] ULONG32 endOffset); + + /* + * Define a single variable in the current lexical + * scope. startOffset and endOffset are optional. If 0, then they + * are ignored and the variable is defined over the entire + * scope. If non-zero, then they must fall within the offsets of + * the current scope. This can be called multiple times for a + * variable of the same name that has multiple homes throughout a + * scope. (Note: start/end offsets must not overlap in such a + * case.) + */ + HRESULT DefineLocalVariable([in] const WCHAR *name, + [in] ULONG32 attributes, + [in] ULONG32 cSig, + [in, size_is(cSig)] unsigned char signature[], + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3, + [in] ULONG32 startOffset, + [in] ULONG32 endOffset); + + /* + * Define a single parameter in the current method. The type of + * each parameter is taken from its position (sequence) within the + * method's signature. + * + * Note: if parameters are defined in the metadata for a given + * method, then clearly one would not have to define them again + * with calls to this method. The symbol readers will have to be + * smart enough to check the normal metadata for these first then + * fall back to the symbol store. + */ + HRESULT DefineParameter([in] const WCHAR *name, + [in] ULONG32 attributes, + [in] ULONG32 sequence, + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3); + + /* + * Define a single variable not within a method. This is used for + * certian fields in classes, bitfields, etc. + */ + HRESULT DefineField([in] mdTypeDef parent, + [in] const WCHAR *name, + [in] ULONG32 attributes, + [in] ULONG32 cSig, + [in, size_is(cSig)] unsigned char signature[], + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3); + + /* + * Define a single global variable. + */ + HRESULT DefineGlobalVariable([in] const WCHAR *name, + [in] ULONG32 attributes, + [in] ULONG32 cSig, + [in, size_is(cSig)] unsigned char signature[], + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3); + + /* + * Close will close the ISymUnmanagedWriter and commit the symbols + * to the symbol store. The ISymUnmanagedWriter becomes invalid + * after this call for further updates. + */ + HRESULT Close(); + + /* + * Defines a custom attribute based upon its name. Not to be + * confused with Metadata custom attributes, these attributes are + * held in the symbol store. + */ + HRESULT SetSymAttribute([in] mdToken parent, + [in] const WCHAR *name, + [in] ULONG32 cData, + [in, size_is(cData)] unsigned char data[]); + + /* + * Opens a new namespace. Call this before defining methods or + * variables that live within a namespace. Namespaces can be nested. + */ + HRESULT OpenNamespace([in] const WCHAR *name); + + /* + * Close the most recently opened namespace. + */ + HRESULT CloseNamespace(); + + /* + * Specifies that the given, fully qualified namespace name is + * being used within the currently open lexical scope. Closing the + * current scope will also stop using the namespace, and the + * namespace will be in use in all scopes that inherit from the + * currently open scope. + */ + HRESULT UsingNamespace([in] const WCHAR *fullName); + + /* + * Specifies the true start and end of a method within a source + * file. Use this to specify the extent of a method independently + * of what sequence points exist within the method. + */ + HRESULT SetMethodSourceRange([in] ISymUnmanagedDocumentWriter *startDoc, + [in] ULONG32 startLine, + [in] ULONG32 startColumn, + [in] ISymUnmanagedDocumentWriter *endDoc, + [in] ULONG32 endLine, + [in] ULONG32 endColumn); + + /* + * Sets the metadata emitter interface that this writer will be + * associated with. Also sets the output filename of where the + * debugging symbols will be written. This can only be called once, + * and must be called before any other writer methods are called. + * + * Some writers may require a filename, while others may not. A + * filename can always be passed to this method, however, with + * no ill effects on writers that do not use it. + * + * The pIStream parameter is optional. If specified, the symbol + * writer will emit the symbols into the given IStream rather than + * to the file specified in filename. + * + * The fFullBuild parameter indicates to the symbol writer whether + * this is a full build or an incremental build. + */ + HRESULT Initialize([in] IUnknown *emitter, + [in] const WCHAR *filename, + [in] IStream *pIStream, + [in] BOOL fFullBuild); + + /* + * Returns the necessary info for a compiler to write the + * necessary debug directory entry into the PE header. + * + * pIDD should point to a IMAGE_DEBUG_DIRECTORY that the symbol + * writer will fill out. All fields except for TimeDateStamp and + * PointerToRawData will be filled out by the symbol writer. (The + * compiler is responsible for setting TimeDateStamp and + * PointerToRawData appropiatley.) + * + * data should point to a buffer large enough to hold the debug + * data for the symbol store. + * + * A compiler should call this method, then emit the data blob to + * the PE file and set the PointerToRawData field in the + * IMAGE_DEBUG_DIRECTORY to point to the emitted data. Then, the + * IMAGE_DEBUG_DIRECTORY should be written to the PE file. The + * compiler should also set the TimeDateStamp field to equal the + * TimeDateStamp of the PE file being generated. + */ + HRESULT GetDebugInfo([in, out] IMAGE_DEBUG_DIRECTORY *pIDD, + [in] DWORD cData, + [out] DWORD *pcData, + [out, size_is(cData), + length_is(*pcData)] BYTE data[]); + + /* + * Define a group of sequence points within the current method. + * Each line/column defines the start of a statement within a + * method. Each end line/column defines the end of a statement + * with a method. (End line/column is optional.) The arrays should + * be sorted by offset. The offset is always the offset from the + * start of the method, in bytes. + */ + HRESULT DefineSequencePoints([in] ISymUnmanagedDocumentWriter* document, + [in] ULONG32 spCount, + [in, size_is(spCount)] ULONG32 offsets[], + [in, size_is(spCount)] ULONG32 lines[], + [in, size_is(spCount)] ULONG32 columns[], + [in, size_is(spCount)] ULONG32 endLines[], + [in, size_is(spCount)] ULONG32 endColumns[]); + + /* + * This method tells the symbol writer that a metadata token has + * been remapped as the metadata was emitted. If the symbol writer + * has stored the old token within the symbol store, it must + * either update the stored token to the new value, or persist the + * map for the corresponding symbol reader to remap during the + * read phase. + */ + HRESULT RemapToken([in] mdToken oldToken, + [in] mdToken newToken); + + /* + * Same as Initialize except that the final path name is the path string to + * name the final location of the pdb file. This is used in build enviroments in + * which the pdb is built in a temporary location and moved when the build is + * complete. + */ + HRESULT Initialize2([in] IUnknown *emitter, + [in] const WCHAR *tempfilename, + [in] IStream *pIStream, + [in] BOOL fFullBuild, + [in] const WCHAR *finalfilename); + + /* + * Defines a name for a constant value. + */ + HRESULT DefineConstant( [in] const WCHAR *name, + [in] VARIANT value, + [in] ULONG32 cSig, + [in, size_is(cSig)] unsigned char signature[]); + + /* + * Abort will close the ISymUnmanagedWriter without committing the symbols + * to the symbol store. The ISymUnmanagedWriter becomes invalid + * after this call for further updates. + */ + HRESULT Abort(); + +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedWriter2 interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(0B97726E-9E6D-4f05-9A26-424022093CAA), + pointer_default(unique) +] +interface ISymUnmanagedWriter2 : ISymUnmanagedWriter +{ + /* + * Define a single variable in the current lexical + * scope. startOffset and endOffset are optional. If 0, then they + * are ignored and the variable is defined over the entire + * scope. If non-zero, then they must fall within the offsets of + * the current scope. This can be called multiple times for a + * variable of the same name that has multiple homes throughout a + * scope. (Note: start/end offsets must not overlap in such a + * case.) + */ + HRESULT DefineLocalVariable2([in] const WCHAR *name, + [in] ULONG32 attributes, + [in] mdSignature sigToken, + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3, + [in] ULONG32 startOffset, + [in] ULONG32 endOffset); + + /* + * Define a single global variable. + */ + HRESULT DefineGlobalVariable2([in] const WCHAR *name, + [in] ULONG32 attributes, + [in] mdSignature sigToken, + [in] ULONG32 addrKind, + [in] ULONG32 addr1, + [in] ULONG32 addr2, + [in] ULONG32 addr3); + + + /* + * Defines a name for a constant value. + */ + HRESULT DefineConstant2( [in] const WCHAR *name, + [in] VARIANT value, + [in] mdSignature sigToken); + +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedWriter3 interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(12F1E02C-1E05-4B0E-9468-EBC9D1BB040F), + pointer_default(unique) +] +interface ISymUnmanagedWriter3 : ISymUnmanagedWriter2 +{ + /* + * Open a method, and also provide its real section offset in image + */ + HRESULT OpenMethod2( [in] mdMethodDef method, + [in] ULONG32 isect, + [in] ULONG32 offset); + + /* + * Commit the changes written so far to the stream + */ + + HRESULT Commit(); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedWriter4 interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(BC7E3F53-F458-4C23-9DBD-A189E6E96594), + pointer_default(unique) +] +interface ISymUnmanagedWriter4 : ISymUnmanagedWriter3 +{ + /* + * Functions the same as ISymUnmanagedWriter::GetDebugInfo with the exception + * that the path string is padded with zeros following the terminating null + * character to make the string data a fixed size of MAX_PATH. Padding is only + * given if the path string length itself is less than MAX_PATH. + * + * This makes writing tools that difference PE files easier. + */ + HRESULT GetDebugInfoWithPadding([in, out] IMAGE_DEBUG_DIRECTORY *pIDD, + [in] DWORD cData, + [out] DWORD *pcData, + [out, size_is(cData), + length_is(*pcData)] BYTE data[]); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedWriter5 interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(DCF7780D-BDE9-45DF-ACFE-21731A32000C), + pointer_default(unique) +] +interface ISymUnmanagedWriter5 : ISymUnmanagedWriter4 +{ + /* + * Open a special custom data section to emit token to source span mapping + * information into. Opening this section while a method is already open + * or vice versa is an error. + */ + HRESULT OpenMapTokensToSourceSpans(); + + /* + * Close the special custom data section for token to source span mapping + * information. Once it is closed no more mapping information can be added. + */ + HRESULT CloseMapTokensToSourceSpans(); + + /* + * Maps the given metadata token to the given source line span in the specified + * source file. + * + * Must be called between calls to OpenMapTokensToSourceSpans() and + * CloseMapTokensToSourceSpans(). + */ + HRESULT MapTokenToSourceSpan([in] mdToken token, + [in] ISymUnmanagedDocumentWriter* document, + [in] ULONG32 line, + [in] ULONG32 column, + [in] ULONG32 endLine, + [in] ULONG32 endColumn); +}; + + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedReader interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(A09E53B2-2A57-4cca-8F63-B84F7C35D4AA), + pointer_default(unique) +] +interface ISymUnmanagedReader2 : ISymUnmanagedReader +{ + /* + * Get a symbol reader method given a method token and an E&C + * version number. Version numbers start at 1 and are incremented + * each time the method is changed due to an E&C operation. + */ + HRESULT GetMethodByVersionPreRemap([in] mdMethodDef token, + [in] int version, + [out, retval] ISymUnmanagedMethod** pRetVal); + /* + * Gets a custom attribute based upon its name. Not to be + * confused with Metadata custom attributes, these attributes are + * held in the symbol store. + */ + HRESULT GetSymAttributePreRemap([in] mdToken parent, + [in] WCHAR *name, + [in] ULONG32 cBuffer, + [out] ULONG32 *pcBuffer, + [out, size_is(cBuffer), + length_is(*pcBuffer)] BYTE buffer[]); + + /* + * Gets every method that has line information in the provided Document. + */ + HRESULT GetMethodsInDocument([in] ISymUnmanagedDocument *document, + [in] ULONG32 cMethod, + [out] ULONG32* pcMethod, + [out, size_is(cMethod), + length_is(*pcMethod)] ISymUnmanagedMethod* pRetVal[]); + +}; + +/* ------------------------------------------------------------------------- * + * ISymNGenWriter interface + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(d682fd12-43de-411c-811b-be8404cea126), + pointer_default(unique) +] +interface ISymNGenWriter : IUnknown +{ + /* + * Add a new public symbol to the NGEN PDB. + */ + HRESULT AddSymbol([in] BSTR pSymbol, + [in] USHORT iSection, + [in] ULONGLONG rva); + + /* + * Adds a new section to the NGEN PDB. + */ + HRESULT AddSection([in] USHORT iSection, + [in] USHORT flags, + [in] long offset, + [in] long cb); +}; + + +/* ------------------------------------------------------------------------- * + * ISymNGenWriter2 interface + * ------------------------------------------------------------------------- */ +[ + object, + local, + uuid(B029E51B-4C55-4fe2-B993-9F7BC1F10DB4), + pointer_default(unique) +] +interface ISymNGenWriter2 : ISymNGenWriter +{ + HRESULT OpenModW([in] const wchar_t* wszModule, + [in] const wchar_t* wszObjFile, + [out] BYTE** ppmod); + + HRESULT CloseMod([in] BYTE* pmod); + + HRESULT ModAddSymbols([in] BYTE* pmod, [in] BYTE* pbSym, [in] long cb); + + HRESULT ModAddSecContribEx( + [in] BYTE* pmod, + [in] USHORT isect, + [in] long off, + [in] long cb, + [in] ULONG dwCharacteristics, + [in] DWORD dwDataCrc, + [in] DWORD dwRelocCrc); + + HRESULT QueryPDBNameExW( + [out, size_is(cchMax)] wchar_t wszPDB[], + [in] SIZE_T cchMax); +}; + + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedAsyncPropertiesWriter interface + * + * Allows definition of optional async method information per method symbol. + * Must use with an opened method (i.e. between calls to ISymUnmanagedWriter's + * OpenMethod and CloseMethod methods). + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(FC073774-1739-4232-BD56-A027294BEC15), + pointer_default(unique) +] +interface ISymUnmanagedAsyncMethodPropertiesWriter : IUnknown +{ + /* + * Sets the starting method that initiates the async operation. + * + * When performing a step-out of an async method, if the caller matches + * the kickoff method, we will step out synchronously. Otherwise, an + * async step-out will occur. + * + * This works in C#/VB because there is an initial method stub that + * creates the state machine object and starts if off, hence "kickoff" + * Still have to determine if this will work with F#. + */ + HRESULT DefineKickoffMethod([in] mdToken kickoffMethod); + + /* + * Sets the IL offset for the compiler generated catch handler that wraps + * an async method. + * + * The IL offset of the generated catch is used by the debugger to handle + * the catch as though it were non-user code even though it may occur in + * a user code method. In particular it is used in response to a + * CatchHandlerFound exception event. + */ + HRESULT DefineCatchHandlerILOffset([in] ULONG32 catchHandlerOffset); + + /* + * Define a group of async scopes within the current method. + * + * Each yield offset matches an await's return instruction, + * identifying a potential yield. Each breakpointMethod/breakpointOffset + * pair tells us where the asynchronous operation will resume + * (which may be in a different method). + */ + HRESULT DefineAsyncStepInfo([in] ULONG32 count, + [in, size_is(count)] ULONG32 yieldOffsets[], + [in, size_is(count)] ULONG32 breakpointOffset[], + [in, size_is(count)] mdToken breakpointMethod[]); +}; + +/* ------------------------------------------------------------------------- * + * ISymUnmanagedAsyncMethod interface + * + * This interface is the reading complement to + * ISymUnmanangedAsyncMethodPropertiesWriter + * ------------------------------------------------------------------------- */ + +[ + object, + uuid(B20D55B3-532E-4906-87E7-25BD5734ABD2), + pointer_default(unique) +] +interface ISymUnmanagedAsyncMethod : IUnknown +{ + /* + * Checks if the method has asynch information or not. + * + * If this method returns FALSE then it is invalid to call any + * other methods in this interface. They will all return + * E_UNEXPECTED in this case. + */ + HRESULT IsAsyncMethod([out, retval] BOOL* pRetVal); + + /* + * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineKickoffMethod + */ + HRESULT GetKickoffMethod([out, retval] mdToken* kickoffMethod); + + /* + * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineCatchHandlerILOffset + */ + HRESULT HasCatchHandlerILOffset([out, retval] BOOL* pRetVal); + + /* + * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineCatchHandlerILOffset + */ + HRESULT GetCatchHandlerILOffset([out, retval] ULONG32* pRetVal); + + /* + * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineAsyncStepInfo + */ + HRESULT GetAsyncStepInfoCount([out, retval] ULONG32* pRetVal); + + /* + * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineAsyncStepInfo + */ + HRESULT GetAsyncStepInfo([in] ULONG32 cStepInfo, + [out] ULONG32 *pcStepInfo, + [in, size_is(cStepInfo)] ULONG32 yieldOffsets[], + [in, size_is(cStepInfo)] ULONG32 breakpointOffset[], + [in, size_is(cStepInfo)] mdToken breakpointMethod[]); +}; diff --git a/lib/coreclr/src/inc/cortypeinfo.h b/lib/coreclr/src/inc/cortypeinfo.h new file mode 100644 index 0000000000..6cc7325768 --- /dev/null +++ b/lib/coreclr/src/inc/cortypeinfo.h @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This describes information about the COM+ primitive types + +// +// Note: This file gets parsed by the Mono IL Linker (https://github.com/mono/linker/) which may throw an exception during parsing. +// Specifically, this (https://github.com/mono/linker/blob/master/corebuild/integration/ILLink.Tasks/CreateRuntimeRootDescriptorFile.cs) will try to +// parse this header, and it may throw an exception while doing that. If you edit this file and get a build failure on msbuild.exe D:\repos\coreclr\build.proj +// you might want to check out the parser linked above. +// + + +#define NO_SIZE ((BYTE)-1) + +// TYPEINFO(type (CorElementType), namespace, class, size, gcType, isArray,isPrim, isFloat,isModifier,isGenVariable) + +TYPEINFO(ELEMENT_TYPE_END, NULL, NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x00 +TYPEINFO(ELEMENT_TYPE_VOID, "System", "Void", 0, TYPE_GC_NONE, false, true, false, false, false) // 0x01 +TYPEINFO(ELEMENT_TYPE_BOOLEAN, "System", "Boolean", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x02 +TYPEINFO(ELEMENT_TYPE_CHAR, "System", "Char", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x03 +TYPEINFO(ELEMENT_TYPE_I1, "System", "SByte", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x04 +TYPEINFO(ELEMENT_TYPE_U1, "System", "Byte", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x05 +TYPEINFO(ELEMENT_TYPE_I2, "System", "Int16", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x06 +TYPEINFO(ELEMENT_TYPE_U2, "System", "UInt16", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x07 +TYPEINFO(ELEMENT_TYPE_I4, "System", "Int32", 4, TYPE_GC_NONE, false, true, false, false, false) // 0x08 +TYPEINFO(ELEMENT_TYPE_U4, "System", "UInt32", 4, TYPE_GC_NONE, false, true, false, false, false) // 0x09 +TYPEINFO(ELEMENT_TYPE_I8, "System", "Int64", 8, TYPE_GC_NONE, false, true, false, false, false) // 0x0a +TYPEINFO(ELEMENT_TYPE_U8, "System", "UInt64", 8, TYPE_GC_NONE, false, true, false, false, false) // 0x0b + +TYPEINFO(ELEMENT_TYPE_R4, "System", "Single", 4, TYPE_GC_NONE, false, true, true, false, false) // 0x0c +TYPEINFO(ELEMENT_TYPE_R8, "System", "Double", 8, TYPE_GC_NONE, false, true, true, false, false) // 0x0d + +TYPEINFO(ELEMENT_TYPE_STRING, "System", "String", TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x0e +TYPEINFO(ELEMENT_TYPE_PTR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_NONE, false, false, false, true, false) // 0x0f +TYPEINFO(ELEMENT_TYPE_BYREF, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_BYREF, false, false, false, true, false) // 0x10 +TYPEINFO(ELEMENT_TYPE_VALUETYPE, NULL, NULL, NO_SIZE, TYPE_GC_OTHER, false, false, false, false, false) // 0x11 +TYPEINFO(ELEMENT_TYPE_CLASS, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x12 +TYPEINFO(ELEMENT_TYPE_VAR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, true) // 0x13 +TYPEINFO(ELEMENT_TYPE_ARRAY, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, true, false, false, true, false) // 0x14 + +TYPEINFO(ELEMENT_TYPE_GENERICINST, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, false) // 0x15 +TYPEINFO(ELEMENT_TYPE_TYPEDBYREF, "System", "TypedReference",2*TARGET_POINTER_SIZE,TYPE_GC_BYREF, false, false, false, false, false) // 0x16 +TYPEINFO(ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED, NULL,NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x17 (unsupported, not in the ECMA spec) + +TYPEINFO(ELEMENT_TYPE_I, "System", "IntPtr", TARGET_POINTER_SIZE, TYPE_GC_NONE, false, true, false, false, false) // 0x18 +TYPEINFO(ELEMENT_TYPE_U, "System", "UIntPtr", TARGET_POINTER_SIZE, TYPE_GC_NONE, false, true, false, false, false) // 0x19 +TYPEINFO(ELEMENT_TYPE_R_UNSUPPORTED,NULL, NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x1a (unsupported, not in the ECMA spec) + +TYPEINFO(ELEMENT_TYPE_FNPTR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x1b +TYPEINFO(ELEMENT_TYPE_OBJECT, "System", "Object", TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x1c +TYPEINFO(ELEMENT_TYPE_SZARRAY, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, true, false, false, true, false) // 0x1d +TYPEINFO(ELEMENT_TYPE_MVAR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, true) // x01e +TYPEINFO(ELEMENT_TYPE_CMOD_REQD, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x1f +TYPEINFO(ELEMENT_TYPE_CMOD_OPT, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x20 +TYPEINFO(ELEMENT_TYPE_INTERNAL, NULL, NULL, 0, TYPE_GC_OTHER, false, false, false, false, false) // 0x21 diff --git a/lib/coreclr/src/inc/crosscomp.h b/lib/coreclr/src/inc/crosscomp.h new file mode 100644 index 0000000000..62d1175d32 --- /dev/null +++ b/lib/coreclr/src/inc/crosscomp.h @@ -0,0 +1,378 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// crosscomp.h - cross-compilation enablement structures. +// + + +#pragma once + +#if (!defined(_WIN64) && defined(_TARGET_64BIT_)) || (defined(_WIN64) && !defined(_TARGET_64BIT_)) +#define CROSSBITNESS_COMPILE +#endif + +#if !defined(_ARM_) && defined(_TARGET_ARM_) // Non-ARM Host managing ARM related code + +#ifndef CROSS_COMPILE +#define CROSS_COMPILE +#endif + +#define ARM_MAX_BREAKPOINTS 8 +#define ARM_MAX_WATCHPOINTS 1 + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +typedef struct _NEON128 { + ULONGLONG Low; + LONGLONG High; +} NEON128, *PNEON128; + +typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { + // + // Control flags. + // + + DWORD ContextFlags; + + // + // Integer registers + // + + DWORD R0; + DWORD R1; + DWORD R2; + DWORD R3; + DWORD R4; + DWORD R5; + DWORD R6; + DWORD R7; + DWORD R8; + DWORD R9; + DWORD R10; + DWORD R11; + DWORD R12; + + // + // Control Registers + // + + DWORD Sp; + DWORD Lr; + DWORD Pc; + DWORD Cpsr; + + // + // Floating Point/NEON Registers + // + + DWORD Fpscr; + DWORD Padding; + union { + NEON128 Q[16]; + ULONGLONG D[32]; + DWORD S[32]; + }; + + // + // Debug registers + // + + DWORD Bvr[ARM_MAX_BREAKPOINTS]; + DWORD Bcr[ARM_MAX_BREAKPOINTS]; + DWORD Wvr[ARM_MAX_WATCHPOINTS]; + DWORD Wcr[ARM_MAX_WATCHPOINTS]; + + DWORD Padding2[2]; + +} T_CONTEXT, *PT_CONTEXT; + +// +// Define function table entry - a function table entry is generated for +// each frame function. +// + +#ifndef FEATURE_PAL +#ifdef _X86_ +typedef struct _RUNTIME_FUNCTION { + DWORD BeginAddress; + DWORD UnwindData; +} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; + +// +// Define unwind history table structure. +// + +#define UNWIND_HISTORY_TABLE_SIZE 12 + +typedef struct _UNWIND_HISTORY_TABLE_ENTRY { + DWORD ImageBase; + PRUNTIME_FUNCTION FunctionEntry; +} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY; + +typedef struct _UNWIND_HISTORY_TABLE { + DWORD Count; + BYTE LocalHint; + BYTE GlobalHint; + BYTE Search; + BYTE Once; + DWORD LowAddress; + DWORD HighAddress; + UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; +} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE; +#endif // _X86_ +#endif // !FEATURE_PAL + + +// +// Nonvolatile context pointer record. +// + +typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD R4; + PDWORD R5; + PDWORD R6; + PDWORD R7; + PDWORD R8; + PDWORD R9; + PDWORD R10; + PDWORD R11; + PDWORD Lr; + + PULONGLONG D8; + PULONGLONG D9; + PULONGLONG D10; + PULONGLONG D11; + PULONGLONG D12; + PULONGLONG D13; + PULONGLONG D14; + PULONGLONG D15; + +} T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; + +// +// Define dynamic function table entry. +// + +typedef +PRUNTIME_FUNCTION +(*PGET_RUNTIME_FUNCTION_CALLBACK) ( + IN DWORD64 ControlPc, + IN PVOID Context + ); + +typedef struct _T_DISPATCHER_CONTEXT { + ULONG ControlPc; + ULONG ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG EstablisherFrame; + ULONG TargetPc; + PT_CONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + ULONG ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PUCHAR NonVolatileRegisters; +} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; + +#if defined(FEATURE_PAL) || defined(_X86_) +#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION +#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION +#else +typedef struct _T_RUNTIME_FUNCTION { + DWORD BeginAddress; + DWORD UnwindData; +} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; +#endif + +#elif defined(_AMD64_) && defined(_TARGET_ARM64_) // Host amd64 managing ARM64 related code + +#ifndef CROSS_COMPILE +#define CROSS_COMPILE +#endif + +// +// Specify the number of breakpoints and watchpoints that the OS +// will track. Architecturally, ARM64 supports up to 16. In practice, +// however, almost no one implements more than 4 of each. +// + +#define ARM64_MAX_BREAKPOINTS 8 +#define ARM64_MAX_WATCHPOINTS 2 + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +typedef union _NEON128 { + struct { + ULONGLONG Low; + LONGLONG High; + }; + double D[2]; + float S[4]; + WORD H[8]; + BYTE B[16]; +} NEON128, *PNEON128; + +typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { + + // + // Control flags. + // + + /* +0x000 */ DWORD ContextFlags; + + // + // Integer registers + // + + /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel + /* +0x008 */ union { + struct { + DWORD64 X0; + DWORD64 X1; + DWORD64 X2; + DWORD64 X3; + DWORD64 X4; + DWORD64 X5; + DWORD64 X6; + DWORD64 X7; + DWORD64 X8; + DWORD64 X9; + DWORD64 X10; + DWORD64 X11; + DWORD64 X12; + DWORD64 X13; + DWORD64 X14; + DWORD64 X15; + DWORD64 X16; + DWORD64 X17; + DWORD64 X18; + DWORD64 X19; + DWORD64 X20; + DWORD64 X21; + DWORD64 X22; + DWORD64 X23; + DWORD64 X24; + DWORD64 X25; + DWORD64 X26; + DWORD64 X27; + DWORD64 X28; + }; + DWORD64 X[29]; + }; + /* +0x0f0 */ DWORD64 Fp; + /* +0x0f8 */ DWORD64 Lr; + /* +0x100 */ DWORD64 Sp; + /* +0x108 */ DWORD64 Pc; + + // + // Floating Point/NEON Registers + // + + /* +0x110 */ NEON128 V[32]; + /* +0x310 */ DWORD Fpcr; + /* +0x314 */ DWORD Fpsr; + + // + // Debug registers + // + + /* +0x318 */ DWORD Bcr[ARM64_MAX_BREAKPOINTS]; + /* +0x338 */ DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; + /* +0x378 */ DWORD Wcr[ARM64_MAX_WATCHPOINTS]; + /* +0x380 */ DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; + /* +0x390 */ + +} T_CONTEXT, *PT_CONTEXT; + +// _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) +typedef struct _T_RUNTIME_FUNCTION { + DWORD BeginAddress; + union { + DWORD UnwindData; + struct { + DWORD Flag : 2; + DWORD FunctionLength : 11; + DWORD RegF : 3; + DWORD RegI : 4; + DWORD H : 1; + DWORD CR : 2; + DWORD FrameSize : 9; + } PackedUnwindData; + }; +} T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; + + +// +// Define exception dispatch context structure. +// + +typedef struct _T_DISPATCHER_CONTEXT { + DWORD64 ControlPc; + DWORD64 ImageBase; + PT_RUNTIME_FUNCTION FunctionEntry; + DWORD64 EstablisherFrame; + DWORD64 TargetPc; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + DWORD ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PBYTE NonVolatileRegisters; +} T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; + + + +// +// Nonvolatile context pointer record. +// + +typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD64 X19; + PDWORD64 X20; + PDWORD64 X21; + PDWORD64 X22; + PDWORD64 X23; + PDWORD64 X24; + PDWORD64 X25; + PDWORD64 X26; + PDWORD64 X27; + PDWORD64 X28; + PDWORD64 Fp; + PDWORD64 Lr; + + PDWORD64 D8; + PDWORD64 D9; + PDWORD64 D10; + PDWORD64 D11; + PDWORD64 D12; + PDWORD64 D13; + PDWORD64 D14; + PDWORD64 D15; + +} T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; + +#else + +#define T_CONTEXT CONTEXT +#define PT_CONTEXT PCONTEXT + +#define T_DISPATCHER_CONTEXT DISPATCHER_CONTEXT +#define PT_DISPATCHER_CONTEXT PDISPATCHER_CONTEXT + +#define T_KNONVOLATILE_CONTEXT_POINTERS KNONVOLATILE_CONTEXT_POINTERS +#define PT_KNONVOLATILE_CONTEXT_POINTERS PKNONVOLATILE_CONTEXT_POINTERS + +#define T_RUNTIME_FUNCTION RUNTIME_FUNCTION +#define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION + +#endif + + +#ifdef CROSSGEN_COMPILE +void CrossGenNotSupported(const char * message); +#endif diff --git a/lib/coreclr/src/inc/crsttypes.h b/lib/coreclr/src/inc/crsttypes.h new file mode 100644 index 0000000000..e02c1206ea --- /dev/null +++ b/lib/coreclr/src/inc/crsttypes.h @@ -0,0 +1,513 @@ +// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#ifndef __CRST_TYPES_INCLUDED +#define __CRST_TYPES_INCLUDED + +// **** THIS IS AN AUTOMATICALLY GENERATED HEADER FILE -- DO NOT EDIT!!! **** + +// This file describes the range of Crst types available and their mapping to a numeric level (used by the +// runtime in debug mode to validate we're deadlock free). To modify these settings edit the +// file:CrstTypes.def file and run the clr\bin\CrstTypeTool utility to generate a new version of this file. + +// Each Crst type is declared as a value in the following CrstType enum. +enum CrstType +{ + CrstAllowedFiles = 0, + CrstAppDomainCache = 1, + CrstAppDomainHandleTable = 2, + CrstArgBasedStubCache = 3, + CrstAssemblyDependencyGraph = 4, + CrstAssemblyIdentityCache = 5, + CrstAssemblyList = 6, + CrstAssemblyLoader = 7, + CrstAvailableClass = 8, + CrstAvailableParamTypes = 9, + CrstBaseDomain = 10, + CrstCCompRC = 11, + CrstCer = 12, + CrstClassFactInfoHash = 13, + CrstClassInit = 14, + CrstClrNotification = 15, + CrstCLRPrivBinderMaps = 16, + CrstCLRPrivBinderMapsAdd = 17, + CrstCodeFragmentHeap = 18, + CrstCOMCallWrapper = 19, + CrstCOMWrapperCache = 20, + CrstConnectionNameTable = 21, + CrstContexts = 22, + CrstCoreCLRBinderLog = 23, + CrstCrstCLRPrivBinderLocalWinMDPath = 24, + CrstCSPCache = 25, + CrstDataTest1 = 26, + CrstDataTest2 = 27, + CrstDbgTransport = 28, + CrstDeadlockDetection = 29, + CrstDebuggerController = 30, + CrstDebuggerFavorLock = 31, + CrstDebuggerHeapExecMemLock = 32, + CrstDebuggerHeapLock = 33, + CrstDebuggerJitInfo = 34, + CrstDebuggerMutex = 35, + CrstDelegateToFPtrHash = 36, + CrstDomainLocalBlock = 37, + CrstDynamicIL = 38, + CrstDynamicMT = 39, + CrstDynLinkZapItems = 40, + CrstEtwTypeLogHash = 41, + CrstEventPipe = 42, + CrstEventStore = 43, + CrstException = 44, + CrstExecuteManLock = 45, + CrstExecuteManRangeLock = 46, + CrstFCall = 47, + CrstFriendAccessCache = 48, + CrstFuncPtrStubs = 49, + CrstFusionAppCtx = 50, + CrstGCCover = 51, + CrstGCMemoryPressure = 52, + CrstGlobalStrLiteralMap = 53, + CrstHandleTable = 54, + CrstHostAssemblyMap = 55, + CrstHostAssemblyMapAdd = 56, + CrstIbcProfile = 57, + CrstIJWFixupData = 58, + CrstIJWHash = 59, + CrstILStubGen = 60, + CrstInlineTrackingMap = 61, + CrstInstMethodHashTable = 62, + CrstInterfaceVTableMap = 63, + CrstInterop = 64, + CrstInteropData = 65, + CrstIOThreadpoolWorker = 66, + CrstIsJMCMethod = 67, + CrstISymUnmanagedReader = 68, + CrstJit = 69, + CrstJitGenericHandleCache = 70, + CrstJitInlineTrackingMap = 71, + CrstJitPerf = 72, + CrstJumpStubCache = 73, + CrstLeafLock = 74, + CrstListLock = 75, + CrstLoaderAllocator = 76, + CrstLoaderAllocatorReferences = 77, + CrstLoaderHeap = 78, + CrstMda = 79, + CrstMetadataTracker = 80, + CrstMethodDescBackpatchInfoTracker = 81, + CrstModIntPairList = 82, + CrstModule = 83, + CrstModuleFixup = 84, + CrstModuleLookupTable = 85, + CrstMulticoreJitHash = 86, + CrstMulticoreJitManager = 87, + CrstMUThunkHash = 88, + CrstNativeBinderInit = 89, + CrstNativeImageCache = 90, + CrstNls = 91, + CrstNotifyGdb = 92, + CrstObjectList = 93, + CrstOnEventManager = 94, + CrstPatchEntryPoint = 95, + CrstPEImage = 96, + CrstPEImagePDBStream = 97, + CrstPendingTypeLoadEntry = 98, + CrstPinHandle = 99, + CrstPinnedByrefValidation = 100, + CrstProfilerGCRefDataFreeList = 101, + CrstProfilingAPIStatus = 102, + CrstPublisherCertificate = 103, + CrstRCWCache = 104, + CrstRCWCleanupList = 105, + CrstRCWRefCache = 106, + CrstReadyToRunEntryPointToMethodDescMap = 107, + CrstReDacl = 108, + CrstReflection = 109, + CrstReJITDomainTable = 110, + CrstReJITGlobalRequest = 111, + CrstRemoting = 112, + CrstRetThunkCache = 113, + CrstRWLock = 114, + CrstSavedExceptionInfo = 115, + CrstSaveModuleProfileData = 116, + CrstSecurityStackwalkCache = 117, + CrstSharedAssemblyCreate = 118, + CrstSigConvert = 119, + CrstSingleUseLock = 120, + CrstSpecialStatics = 121, + CrstSqmManager = 122, + CrstStackSampler = 123, + CrstStressLog = 124, + CrstStrongName = 125, + CrstStubCache = 126, + CrstStubDispatchCache = 127, + CrstStubUnwindInfoHeapSegments = 128, + CrstSyncBlockCache = 129, + CrstSyncHashLock = 130, + CrstSystemBaseDomain = 131, + CrstSystemDomain = 132, + CrstSystemDomainDelayedUnloadList = 133, + CrstThreadIdDispenser = 134, + CrstThreadpoolEventCache = 135, + CrstThreadpoolTimerQueue = 136, + CrstThreadpoolWaitThreads = 137, + CrstThreadpoolWorker = 138, + CrstThreadStaticDataHashTable = 139, + CrstThreadStore = 140, + CrstTieredCompilation = 141, + CrstTPMethodTable = 142, + CrstTypeEquivalenceMap = 143, + CrstTypeIDMap = 144, + CrstUMEntryThunkCache = 145, + CrstUMThunkHash = 146, + CrstUniqueStack = 147, + CrstUnresolvedClassLock = 148, + CrstUnwindInfoTableLock = 149, + CrstVSDIndirectionCellLock = 150, + CrstWinRTFactoryCache = 151, + CrstWrapperTemplate = 152, + kNumberOfCrstTypes = 153 +}; + +#endif // __CRST_TYPES_INCLUDED + +// Define some debug data in one module only -- vm\crst.cpp. +#if defined(__IN_CRST_CPP) && defined(_DEBUG) + +// An array mapping CrstType to level. +int g_rgCrstLevelMap[] = +{ + 9, // CrstAllowedFiles + 9, // CrstAppDomainCache + 13, // CrstAppDomainHandleTable + 0, // CrstArgBasedStubCache + 0, // CrstAssemblyDependencyGraph + 0, // CrstAssemblyIdentityCache + 0, // CrstAssemblyList + 7, // CrstAssemblyLoader + 3, // CrstAvailableClass + 3, // CrstAvailableParamTypes + 7, // CrstBaseDomain + -1, // CrstCCompRC + 9, // CrstCer + 12, // CrstClassFactInfoHash + 8, // CrstClassInit + -1, // CrstClrNotification + 0, // CrstCLRPrivBinderMaps + 3, // CrstCLRPrivBinderMapsAdd + 6, // CrstCodeFragmentHeap + 0, // CrstCOMCallWrapper + 4, // CrstCOMWrapperCache + 0, // CrstConnectionNameTable + 16, // CrstContexts + -1, // CrstCoreCLRBinderLog + 0, // CrstCrstCLRPrivBinderLocalWinMDPath + 7, // CrstCSPCache + 3, // CrstDataTest1 + 0, // CrstDataTest2 + 0, // CrstDbgTransport + 0, // CrstDeadlockDetection + -1, // CrstDebuggerController + 3, // CrstDebuggerFavorLock + 0, // CrstDebuggerHeapExecMemLock + 0, // CrstDebuggerHeapLock + 4, // CrstDebuggerJitInfo + 10, // CrstDebuggerMutex + 0, // CrstDelegateToFPtrHash + 15, // CrstDomainLocalBlock + 0, // CrstDynamicIL + 3, // CrstDynamicMT + 3, // CrstDynLinkZapItems + 7, // CrstEtwTypeLogHash + 17, // CrstEventPipe + 0, // CrstEventStore + 0, // CrstException + 7, // CrstExecuteManLock + 0, // CrstExecuteManRangeLock + 3, // CrstFCall + 7, // CrstFriendAccessCache + 7, // CrstFuncPtrStubs + 5, // CrstFusionAppCtx + 10, // CrstGCCover + 0, // CrstGCMemoryPressure + 12, // CrstGlobalStrLiteralMap + 1, // CrstHandleTable + 0, // CrstHostAssemblyMap + 3, // CrstHostAssemblyMapAdd + 0, // CrstIbcProfile + 9, // CrstIJWFixupData + 0, // CrstIJWHash + 7, // CrstILStubGen + 3, // CrstInlineTrackingMap + 16, // CrstInstMethodHashTable + 0, // CrstInterfaceVTableMap + 17, // CrstInterop + 4, // CrstInteropData + 12, // CrstIOThreadpoolWorker + 0, // CrstIsJMCMethod + 7, // CrstISymUnmanagedReader + 8, // CrstJit + 0, // CrstJitGenericHandleCache + 15, // CrstJitInlineTrackingMap + -1, // CrstJitPerf + 6, // CrstJumpStubCache + 0, // CrstLeafLock + -1, // CrstListLock + 14, // CrstLoaderAllocator + 15, // CrstLoaderAllocatorReferences + 0, // CrstLoaderHeap + 0, // CrstMda + -1, // CrstMetadataTracker + 13, // CrstMethodDescBackpatchInfoTracker + 0, // CrstModIntPairList + 4, // CrstModule + 14, // CrstModuleFixup + 3, // CrstModuleLookupTable + 0, // CrstMulticoreJitHash + 12, // CrstMulticoreJitManager + 0, // CrstMUThunkHash + -1, // CrstNativeBinderInit + -1, // CrstNativeImageCache + 0, // CrstNls + 0, // CrstNotifyGdb + 2, // CrstObjectList + 0, // CrstOnEventManager + 0, // CrstPatchEntryPoint + 4, // CrstPEImage + 0, // CrstPEImagePDBStream + 18, // CrstPendingTypeLoadEntry + 0, // CrstPinHandle + 0, // CrstPinnedByrefValidation + 0, // CrstProfilerGCRefDataFreeList + 0, // CrstProfilingAPIStatus + 0, // CrstPublisherCertificate + 3, // CrstRCWCache + 0, // CrstRCWCleanupList + 3, // CrstRCWRefCache + 4, // CrstReadyToRunEntryPointToMethodDescMap + 0, // CrstReDacl + 9, // CrstReflection + 9, // CrstReJITDomainTable + 14, // CrstReJITGlobalRequest + 19, // CrstRemoting + 3, // CrstRetThunkCache + 0, // CrstRWLock + 3, // CrstSavedExceptionInfo + 0, // CrstSaveModuleProfileData + 0, // CrstSecurityStackwalkCache + 4, // CrstSharedAssemblyCreate + 3, // CrstSigConvert + 5, // CrstSingleUseLock + 0, // CrstSpecialStatics + 0, // CrstSqmManager + 0, // CrstStackSampler + -1, // CrstStressLog + 0, // CrstStrongName + 5, // CrstStubCache + 0, // CrstStubDispatchCache + 4, // CrstStubUnwindInfoHeapSegments + 3, // CrstSyncBlockCache + 0, // CrstSyncHashLock + 4, // CrstSystemBaseDomain + 12, // CrstSystemDomain + 0, // CrstSystemDomainDelayedUnloadList + 0, // CrstThreadIdDispenser + 0, // CrstThreadpoolEventCache + 7, // CrstThreadpoolTimerQueue + 7, // CrstThreadpoolWaitThreads + 12, // CrstThreadpoolWorker + 4, // CrstThreadStaticDataHashTable + 11, // CrstThreadStore + 9, // CrstTieredCompilation + 9, // CrstTPMethodTable + 3, // CrstTypeEquivalenceMap + 7, // CrstTypeIDMap + 3, // CrstUMEntryThunkCache + 0, // CrstUMThunkHash + 3, // CrstUniqueStack + 7, // CrstUnresolvedClassLock + 3, // CrstUnwindInfoTableLock + 3, // CrstVSDIndirectionCellLock + 3, // CrstWinRTFactoryCache + 3, // CrstWrapperTemplate +}; + +// An array mapping CrstType to a stringized name. +LPCSTR g_rgCrstNameMap[] = +{ + "CrstAllowedFiles", + "CrstAppDomainCache", + "CrstAppDomainHandleTable", + "CrstArgBasedStubCache", + "CrstAssemblyDependencyGraph", + "CrstAssemblyIdentityCache", + "CrstAssemblyList", + "CrstAssemblyLoader", + "CrstAvailableClass", + "CrstAvailableParamTypes", + "CrstBaseDomain", + "CrstCCompRC", + "CrstCer", + "CrstClassFactInfoHash", + "CrstClassInit", + "CrstClrNotification", + "CrstCLRPrivBinderMaps", + "CrstCLRPrivBinderMapsAdd", + "CrstCodeFragmentHeap", + "CrstCOMCallWrapper", + "CrstCOMWrapperCache", + "CrstConnectionNameTable", + "CrstContexts", + "CrstCoreCLRBinderLog", + "CrstCrstCLRPrivBinderLocalWinMDPath", + "CrstCSPCache", + "CrstDataTest1", + "CrstDataTest2", + "CrstDbgTransport", + "CrstDeadlockDetection", + "CrstDebuggerController", + "CrstDebuggerFavorLock", + "CrstDebuggerHeapExecMemLock", + "CrstDebuggerHeapLock", + "CrstDebuggerJitInfo", + "CrstDebuggerMutex", + "CrstDelegateToFPtrHash", + "CrstDomainLocalBlock", + "CrstDynamicIL", + "CrstDynamicMT", + "CrstDynLinkZapItems", + "CrstEtwTypeLogHash", + "CrstEventPipe", + "CrstEventStore", + "CrstException", + "CrstExecuteManLock", + "CrstExecuteManRangeLock", + "CrstFCall", + "CrstFriendAccessCache", + "CrstFuncPtrStubs", + "CrstFusionAppCtx", + "CrstGCCover", + "CrstGCMemoryPressure", + "CrstGlobalStrLiteralMap", + "CrstHandleTable", + "CrstHostAssemblyMap", + "CrstHostAssemblyMapAdd", + "CrstIbcProfile", + "CrstIJWFixupData", + "CrstIJWHash", + "CrstILStubGen", + "CrstInlineTrackingMap", + "CrstInstMethodHashTable", + "CrstInterfaceVTableMap", + "CrstInterop", + "CrstInteropData", + "CrstIOThreadpoolWorker", + "CrstIsJMCMethod", + "CrstISymUnmanagedReader", + "CrstJit", + "CrstJitGenericHandleCache", + "CrstJitInlineTrackingMap", + "CrstJitPerf", + "CrstJumpStubCache", + "CrstLeafLock", + "CrstListLock", + "CrstLoaderAllocator", + "CrstLoaderAllocatorReferences", + "CrstLoaderHeap", + "CrstMda", + "CrstMetadataTracker", + "CrstMethodDescBackpatchInfoTracker", + "CrstModIntPairList", + "CrstModule", + "CrstModuleFixup", + "CrstModuleLookupTable", + "CrstMulticoreJitHash", + "CrstMulticoreJitManager", + "CrstMUThunkHash", + "CrstNativeBinderInit", + "CrstNativeImageCache", + "CrstNls", + "CrstNotifyGdb", + "CrstObjectList", + "CrstOnEventManager", + "CrstPatchEntryPoint", + "CrstPEImage", + "CrstPEImagePDBStream", + "CrstPendingTypeLoadEntry", + "CrstPinHandle", + "CrstPinnedByrefValidation", + "CrstProfilerGCRefDataFreeList", + "CrstProfilingAPIStatus", + "CrstPublisherCertificate", + "CrstRCWCache", + "CrstRCWCleanupList", + "CrstRCWRefCache", + "CrstReadyToRunEntryPointToMethodDescMap", + "CrstReDacl", + "CrstReflection", + "CrstReJITDomainTable", + "CrstReJITGlobalRequest", + "CrstRemoting", + "CrstRetThunkCache", + "CrstRWLock", + "CrstSavedExceptionInfo", + "CrstSaveModuleProfileData", + "CrstSecurityStackwalkCache", + "CrstSharedAssemblyCreate", + "CrstSigConvert", + "CrstSingleUseLock", + "CrstSpecialStatics", + "CrstSqmManager", + "CrstStackSampler", + "CrstStressLog", + "CrstStrongName", + "CrstStubCache", + "CrstStubDispatchCache", + "CrstStubUnwindInfoHeapSegments", + "CrstSyncBlockCache", + "CrstSyncHashLock", + "CrstSystemBaseDomain", + "CrstSystemDomain", + "CrstSystemDomainDelayedUnloadList", + "CrstThreadIdDispenser", + "CrstThreadpoolEventCache", + "CrstThreadpoolTimerQueue", + "CrstThreadpoolWaitThreads", + "CrstThreadpoolWorker", + "CrstThreadStaticDataHashTable", + "CrstThreadStore", + "CrstTieredCompilation", + "CrstTPMethodTable", + "CrstTypeEquivalenceMap", + "CrstTypeIDMap", + "CrstUMEntryThunkCache", + "CrstUMThunkHash", + "CrstUniqueStack", + "CrstUnresolvedClassLock", + "CrstUnwindInfoTableLock", + "CrstVSDIndirectionCellLock", + "CrstWinRTFactoryCache", + "CrstWrapperTemplate", +}; + +// Define a special level constant for unordered locks. +#define CRSTUNORDERED (-1) + +// Define inline helpers to map Crst types to names and levels. +inline static int GetCrstLevel(CrstType crstType) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes); + return g_rgCrstLevelMap[crstType]; +} +inline static LPCSTR GetCrstName(CrstType crstType) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes); + return g_rgCrstNameMap[crstType]; +} + +#endif // defined(__IN_CRST_CPP) && defined(_DEBUG) diff --git a/lib/coreclr/src/inc/crtwrap.h b/lib/coreclr/src/inc/crtwrap.h new file mode 100644 index 0000000000..aca2437cc7 --- /dev/null +++ b/lib/coreclr/src/inc/crtwrap.h @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// CrtWrap.h +// +// Wrapper code for the C runtime library. +// +//***************************************************************************** + +#ifndef __CrtWrap_h__ +#define __CrtWrap_h__ + +#include +#include +#include +#include +#include "debugmacros.h" +#include +#include +#include +#include + +#ifndef FEATURE_PAL +// CoreCLR.dll uses linker .def files to control the exported symbols. +// Define DLLEXPORT macro as empty on Windows. +#define DLLEXPORT +#endif + +#endif // __CrtWrap_h__ diff --git a/lib/coreclr/src/inc/cvconst.h b/lib/coreclr/src/inc/cvconst.h new file mode 100644 index 0000000000..98eb19e257 --- /dev/null +++ b/lib/coreclr/src/inc/cvconst.h @@ -0,0 +1,3728 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// cvconst.h - codeview constant definitions +//----------------------------------------------------------------- +// +// Copyright Microsoft Corporation. All Rights Reserved. +// +//--------------------------------------------------------------- +#ifndef _CVCONST_H_ +#define _CVCONST_H_ + + + +// Enumeration for function call type + + +typedef enum CV_call_e { + CV_CALL_NEAR_C = 0x00, // near right to left push, caller pops stack + CV_CALL_FAR_C = 0x01, // far right to left push, caller pops stack + CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack + CV_CALL_FAR_PASCAL = 0x03, // far left to right push, callee pops stack + CV_CALL_NEAR_FAST = 0x04, // near left to right push with regs, callee pops stack + CV_CALL_FAR_FAST = 0x05, // far left to right push with regs, callee pops stack + CV_CALL_SKIPPED = 0x06, // skipped (unused) call index + CV_CALL_NEAR_STD = 0x07, // near standard call + CV_CALL_FAR_STD = 0x08, // far standard call + CV_CALL_NEAR_SYS = 0x09, // near sys call + CV_CALL_FAR_SYS = 0x0a, // far sys call + CV_CALL_THISCALL = 0x0b, // this call (this passed in register) + CV_CALL_MIPSCALL = 0x0c, // Mips call + CV_CALL_GENERIC = 0x0d, // Generic call sequence + CV_CALL_ALPHACALL = 0x0e, // Alpha call + CV_CALL_PPCCALL = 0x0f, // PPC call + CV_CALL_SHCALL = 0x10, // Hitachi SuperH call + CV_CALL_ARMCALL = 0x11, // ARM call + CV_CALL_AM33CALL = 0x12, // AM33 call + CV_CALL_TRICALL = 0x13, // TriCore Call + CV_CALL_SH5CALL = 0x14, // Hitachi SuperH-5 call + CV_CALL_M32RCALL = 0x15, // M32R Call + CV_CALL_CLRCALL = 0x16, // clr call + CV_CALL_INLINE = 0x17, // Marker for routines always inlined and thus lacking a convention + CV_CALL_NEAR_VECTOR = 0x18, // near left to right push with regs, callee pops stack + CV_CALL_RESERVED = 0x19 // first unused call enumeration + + // Do NOT add any more machine specific conventions. This is to be used for + // calling conventions in the source only (e.g. __cdecl, __stdcall). +} CV_call_e; + + +// Values for the access protection of class attributes + + +typedef enum CV_access_e { + CV_private = 1, + CV_protected = 2, + CV_public = 3 +} CV_access_e; + +typedef enum THUNK_ORDINAL { + THUNK_ORDINAL_NOTYPE, // standard thunk + THUNK_ORDINAL_ADJUSTOR, // "this" adjustor thunk + THUNK_ORDINAL_VCALL, // virtual call thunk + THUNK_ORDINAL_PCODE, // pcode thunk + THUNK_ORDINAL_LOAD, // thunk which loads the address to jump to + // via unknown means... + + // trampoline thunk ordinals - only for use in Trampoline thunk symbols + THUNK_ORDINAL_TRAMP_INCREMENTAL, + THUNK_ORDINAL_TRAMP_BRANCHISLAND, + +} THUNK_ORDINAL; + + +enum CV_SourceChksum_t { + CHKSUM_TYPE_NONE = 0, // indicates no checksum is available + CHKSUM_TYPE_MD5, + CHKSUM_TYPE_SHA1, + CHKSUM_TYPE_SHA_256, +}; + +// +// DIA enums +// + +enum SymTagEnum +{ + SymTagNull, + SymTagExe, + SymTagCompiland, + SymTagCompilandDetails, + SymTagCompilandEnv, + SymTagFunction, + SymTagBlock, + SymTagData, + SymTagAnnotation, + SymTagLabel, + SymTagPublicSymbol, + SymTagUDT, + SymTagEnum, + SymTagFunctionType, + SymTagPointerType, + SymTagArrayType, + SymTagBaseType, + SymTagTypedef, + SymTagBaseClass, + SymTagFriend, + SymTagFunctionArgType, + SymTagFuncDebugStart, + SymTagFuncDebugEnd, + SymTagUsingNamespace, + SymTagVTableShape, + SymTagVTable, + SymTagCustom, + SymTagThunk, + SymTagCustomType, + SymTagManagedType, + SymTagDimension, + SymTagCallSite, + SymTagInlineSite, + SymTagBaseInterface, + SymTagVectorType, + SymTagMatrixType, + SymTagHLSLType, + SymTagCaller, + SymTagCallee, + SymTagExport, + SymTagHeapAllocationSite, + SymTagCoffGroup, + SymTagMax +}; + +enum LocationType +{ + LocIsNull, + LocIsStatic, + LocIsTLS, + LocIsRegRel, + LocIsThisRel, + LocIsEnregistered, + LocIsBitField, + LocIsSlot, + LocIsIlRel, + LocInMetaData, + LocIsConstant, + LocTypeMax +}; + +enum DataKind +{ + DataIsUnknown, + DataIsLocal, + DataIsStaticLocal, + DataIsParam, + DataIsObjectPtr, + DataIsFileStatic, + DataIsGlobal, + DataIsMember, + DataIsStaticMember, + DataIsConstant +}; + +enum UdtKind +{ + UdtStruct, + UdtClass, + UdtUnion, + UdtInterface +}; + +enum BasicType +{ + btNoType = 0, + btVoid = 1, + btChar = 2, + btWChar = 3, + btInt = 6, + btUInt = 7, + btFloat = 8, + btBCD = 9, + btBool = 10, + btLong = 13, + btULong = 14, + btCurrency = 25, + btDate = 26, + btVariant = 27, + btComplex = 28, + btBit = 29, + btBSTR = 30, + btHresult = 31, + btChar16 = 32, // char16_t + btChar32 = 33, // char32_t +}; + + +// enumeration for type modifier values + +typedef enum CV_modifier_e { + // 0x0000 - 0x01ff - Reserved. + + CV_MOD_INVALID = 0x0000, + + // Standard modifiers. + + CV_MOD_CONST = 0x0001, + CV_MOD_VOLATILE = 0x0002, + CV_MOD_UNALIGNED = 0x0003, + + // 0x0200 - 0x03ff - HLSL modifiers. + + CV_MOD_HLSL_UNIFORM = 0x0200, + CV_MOD_HLSL_LINE = 0x0201, + CV_MOD_HLSL_TRIANGLE = 0x0202, + CV_MOD_HLSL_LINEADJ = 0x0203, + CV_MOD_HLSL_TRIANGLEADJ = 0x0204, + CV_MOD_HLSL_LINEAR = 0x0205, + CV_MOD_HLSL_CENTROID = 0x0206, + CV_MOD_HLSL_CONSTINTERP = 0x0207, + CV_MOD_HLSL_NOPERSPECTIVE = 0x0208, + CV_MOD_HLSL_SAMPLE = 0x0209, + CV_MOD_HLSL_CENTER = 0x020a, + CV_MOD_HLSL_SNORM = 0x020b, + CV_MOD_HLSL_UNORM = 0x020c, + CV_MOD_HLSL_PRECISE = 0x020d, + CV_MOD_HLSL_UAV_GLOBALLY_COHERENT = 0x020e, + + // 0x0400 - 0xffff - Unused. + +} CV_modifier_e; + + +// built-in type kinds + + +typedef enum CV_builtin_e { + + // 0x0000 - 0x01ff - Reserved. + CV_BI_INVALID = 0x0000, + + // 0x0200 - 0x03ff - HLSL types. + + CV_BI_HLSL_INTERFACE_POINTER = 0x0200, + CV_BI_HLSL_TEXTURE1D = 0x0201, + CV_BI_HLSL_TEXTURE1D_ARRAY = 0x0202, + CV_BI_HLSL_TEXTURE2D = 0x0203, + CV_BI_HLSL_TEXTURE2D_ARRAY = 0x0204, + CV_BI_HLSL_TEXTURE3D = 0x0205, + CV_BI_HLSL_TEXTURECUBE = 0x0206, + CV_BI_HLSL_TEXTURECUBE_ARRAY = 0x0207, + CV_BI_HLSL_TEXTURE2DMS = 0x0208, + CV_BI_HLSL_TEXTURE2DMS_ARRAY = 0x0209, + CV_BI_HLSL_SAMPLER = 0x020a, + CV_BI_HLSL_SAMPLERCOMPARISON = 0x020b, + CV_BI_HLSL_BUFFER = 0x020c, + CV_BI_HLSL_POINTSTREAM = 0x020d, + CV_BI_HLSL_LINESTREAM = 0x020e, + CV_BI_HLSL_TRIANGLESTREAM = 0x020f, + CV_BI_HLSL_INPUTPATCH = 0x0210, + CV_BI_HLSL_OUTPUTPATCH = 0x0211, + CV_BI_HLSL_RWTEXTURE1D = 0x0212, + CV_BI_HLSL_RWTEXTURE1D_ARRAY = 0x0213, + CV_BI_HLSL_RWTEXTURE2D = 0x0214, + CV_BI_HLSL_RWTEXTURE2D_ARRAY = 0x0215, + CV_BI_HLSL_RWTEXTURE3D = 0x0216, + CV_BI_HLSL_RWBUFFER = 0x0217, + CV_BI_HLSL_BYTEADDRESS_BUFFER = 0x0218, + CV_BI_HLSL_RWBYTEADDRESS_BUFFER = 0x0219, + CV_BI_HLSL_STRUCTURED_BUFFER = 0x021a, + CV_BI_HLSL_RWSTRUCTURED_BUFFER = 0x021b, + CV_BI_HLSL_APPEND_STRUCTURED_BUFFER = 0x021c, + CV_BI_HLSL_CONSUME_STRUCTURED_BUFFER= 0x021d, + CV_BI_HLSL_MIN8FLOAT = 0x021e, + CV_BI_HLSL_MIN10FLOAT = 0x021f, + CV_BI_HLSL_MIN16FLOAT = 0x0220, + CV_BI_HLSL_MIN12INT = 0x0221, + CV_BI_HLSL_MIN16INT = 0x0222, + CV_BI_HLSL_MIN16UINT = 0x0223, + + // 0x0400 - 0xffff - Unused. + +} CV_builtin_e; + + +// enum describing the compile flag source language + + +typedef enum CV_CFL_LANG { + CV_CFL_C = 0x00, + CV_CFL_CXX = 0x01, + CV_CFL_FORTRAN = 0x02, + CV_CFL_MASM = 0x03, + CV_CFL_PASCAL = 0x04, + CV_CFL_BASIC = 0x05, + CV_CFL_COBOL = 0x06, + CV_CFL_LINK = 0x07, + CV_CFL_CVTRES = 0x08, + CV_CFL_CVTPGD = 0x09, + CV_CFL_CSHARP = 0x0A, // C# + CV_CFL_VB = 0x0B, // Visual Basic + CV_CFL_ILASM = 0x0C, // IL (as in CLR) ASM + CV_CFL_JAVA = 0x0D, + CV_CFL_JSCRIPT = 0x0E, + CV_CFL_MSIL = 0x0F, // Unknown MSIL (LTCG of .NETMODULE) + CV_CFL_HLSL = 0x10, // High Level Shader Language +} CV_CFL_LANG; + + +// enum describing target processor + + +typedef enum CV_CPU_TYPE_e { + CV_CFL_8080 = 0x00, + CV_CFL_8086 = 0x01, + CV_CFL_80286 = 0x02, + CV_CFL_80386 = 0x03, + CV_CFL_80486 = 0x04, + CV_CFL_PENTIUM = 0x05, + CV_CFL_PENTIUMII = 0x06, + CV_CFL_PENTIUMPRO = CV_CFL_PENTIUMII, + CV_CFL_PENTIUMIII = 0x07, + CV_CFL_MIPS = 0x10, + CV_CFL_MIPSR4000 = CV_CFL_MIPS, // don't break current code + CV_CFL_MIPS16 = 0x11, + CV_CFL_MIPS32 = 0x12, + CV_CFL_MIPS64 = 0x13, + CV_CFL_MIPSI = 0x14, + CV_CFL_MIPSII = 0x15, + CV_CFL_MIPSIII = 0x16, + CV_CFL_MIPSIV = 0x17, + CV_CFL_MIPSV = 0x18, + CV_CFL_M68000 = 0x20, + CV_CFL_M68010 = 0x21, + CV_CFL_M68020 = 0x22, + CV_CFL_M68030 = 0x23, + CV_CFL_M68040 = 0x24, + CV_CFL_ALPHA = 0x30, + CV_CFL_ALPHA_21064 = 0x30, + CV_CFL_ALPHA_21164 = 0x31, + CV_CFL_ALPHA_21164A = 0x32, + CV_CFL_ALPHA_21264 = 0x33, + CV_CFL_ALPHA_21364 = 0x34, + CV_CFL_PPC601 = 0x40, + CV_CFL_PPC603 = 0x41, + CV_CFL_PPC604 = 0x42, + CV_CFL_PPC620 = 0x43, + CV_CFL_PPCFP = 0x44, + CV_CFL_PPCBE = 0x45, + CV_CFL_SH3 = 0x50, + CV_CFL_SH3E = 0x51, + CV_CFL_SH3DSP = 0x52, + CV_CFL_SH4 = 0x53, + CV_CFL_SHMEDIA = 0x54, + CV_CFL_ARM3 = 0x60, + CV_CFL_ARM4 = 0x61, + CV_CFL_ARM4T = 0x62, + CV_CFL_ARM5 = 0x63, + CV_CFL_ARM5T = 0x64, + CV_CFL_ARM6 = 0x65, + CV_CFL_ARM_XMAC = 0x66, + CV_CFL_ARM_WMMX = 0x67, + CV_CFL_ARM7 = 0x68, + CV_CFL_OMNI = 0x70, + CV_CFL_IA64 = 0x80, + CV_CFL_IA64_1 = 0x80, + CV_CFL_IA64_2 = 0x81, + CV_CFL_CEE = 0x90, + CV_CFL_AM33 = 0xA0, + CV_CFL_M32R = 0xB0, + CV_CFL_TRICORE = 0xC0, + CV_CFL_X64 = 0xD0, + CV_CFL_AMD64 = CV_CFL_X64, + CV_CFL_EBC = 0xE0, + CV_CFL_THUMB = 0xF0, + CV_CFL_ARMNT = 0xF4, + CV_CFL_ARM64 = 0xF6, + CV_CFL_D3D11_SHADER = 0x100, +} CV_CPU_TYPE_e; + +typedef enum CV_HREG_e { + // Register subset shared by all processor types, + // must not overlap with any of the ranges below, hence the high values + + CV_ALLREG_ERR = 30000, + CV_ALLREG_TEB = 30001, + CV_ALLREG_TIMER = 30002, + CV_ALLREG_EFAD1 = 30003, + CV_ALLREG_EFAD2 = 30004, + CV_ALLREG_EFAD3 = 30005, + CV_ALLREG_VFRAME= 30006, + CV_ALLREG_HANDLE= 30007, + CV_ALLREG_PARAMS= 30008, + CV_ALLREG_LOCALS= 30009, + CV_ALLREG_TID = 30010, + CV_ALLREG_ENV = 30011, + CV_ALLREG_CMDLN = 30012, + + + // Register set for the Intel 80x86 and ix86 processor series + // (plus PCODE registers) + + CV_REG_NONE = 0, + CV_REG_AL = 1, + CV_REG_CL = 2, + CV_REG_DL = 3, + CV_REG_BL = 4, + CV_REG_AH = 5, + CV_REG_CH = 6, + CV_REG_DH = 7, + CV_REG_BH = 8, + CV_REG_AX = 9, + CV_REG_CX = 10, + CV_REG_DX = 11, + CV_REG_BX = 12, + CV_REG_SP = 13, + CV_REG_BP = 14, + CV_REG_SI = 15, + CV_REG_DI = 16, + CV_REG_EAX = 17, + CV_REG_ECX = 18, + CV_REG_EDX = 19, + CV_REG_EBX = 20, + CV_REG_ESP = 21, + CV_REG_EBP = 22, + CV_REG_ESI = 23, + CV_REG_EDI = 24, + CV_REG_ES = 25, + CV_REG_CS = 26, + CV_REG_SS = 27, + CV_REG_DS = 28, + CV_REG_FS = 29, + CV_REG_GS = 30, + CV_REG_IP = 31, + CV_REG_FLAGS = 32, + CV_REG_EIP = 33, + CV_REG_EFLAGS = 34, + CV_REG_TEMP = 40, // PCODE Temp + CV_REG_TEMPH = 41, // PCODE TempH + CV_REG_QUOTE = 42, // PCODE Quote + CV_REG_PCDR3 = 43, // PCODE reserved + CV_REG_PCDR4 = 44, // PCODE reserved + CV_REG_PCDR5 = 45, // PCODE reserved + CV_REG_PCDR6 = 46, // PCODE reserved + CV_REG_PCDR7 = 47, // PCODE reserved + CV_REG_CR0 = 80, // CR0 -- control registers + CV_REG_CR1 = 81, + CV_REG_CR2 = 82, + CV_REG_CR3 = 83, + CV_REG_CR4 = 84, // Pentium + CV_REG_DR0 = 90, // Debug register + CV_REG_DR1 = 91, + CV_REG_DR2 = 92, + CV_REG_DR3 = 93, + CV_REG_DR4 = 94, + CV_REG_DR5 = 95, + CV_REG_DR6 = 96, + CV_REG_DR7 = 97, + CV_REG_GDTR = 110, + CV_REG_GDTL = 111, + CV_REG_IDTR = 112, + CV_REG_IDTL = 113, + CV_REG_LDTR = 114, + CV_REG_TR = 115, + + CV_REG_PSEUDO1 = 116, + CV_REG_PSEUDO2 = 117, + CV_REG_PSEUDO3 = 118, + CV_REG_PSEUDO4 = 119, + CV_REG_PSEUDO5 = 120, + CV_REG_PSEUDO6 = 121, + CV_REG_PSEUDO7 = 122, + CV_REG_PSEUDO8 = 123, + CV_REG_PSEUDO9 = 124, + + CV_REG_ST0 = 128, + CV_REG_ST1 = 129, + CV_REG_ST2 = 130, + CV_REG_ST3 = 131, + CV_REG_ST4 = 132, + CV_REG_ST5 = 133, + CV_REG_ST6 = 134, + CV_REG_ST7 = 135, + CV_REG_CTRL = 136, + CV_REG_STAT = 137, + CV_REG_TAG = 138, + CV_REG_FPIP = 139, + CV_REG_FPCS = 140, + CV_REG_FPDO = 141, + CV_REG_FPDS = 142, + CV_REG_ISEM = 143, + CV_REG_FPEIP = 144, + CV_REG_FPEDO = 145, + + CV_REG_MM0 = 146, + CV_REG_MM1 = 147, + CV_REG_MM2 = 148, + CV_REG_MM3 = 149, + CV_REG_MM4 = 150, + CV_REG_MM5 = 151, + CV_REG_MM6 = 152, + CV_REG_MM7 = 153, + + CV_REG_XMM0 = 154, // KATMAI registers + CV_REG_XMM1 = 155, + CV_REG_XMM2 = 156, + CV_REG_XMM3 = 157, + CV_REG_XMM4 = 158, + CV_REG_XMM5 = 159, + CV_REG_XMM6 = 160, + CV_REG_XMM7 = 161, + + CV_REG_XMM00 = 162, // KATMAI sub-registers + CV_REG_XMM01 = 163, + CV_REG_XMM02 = 164, + CV_REG_XMM03 = 165, + CV_REG_XMM10 = 166, + CV_REG_XMM11 = 167, + CV_REG_XMM12 = 168, + CV_REG_XMM13 = 169, + CV_REG_XMM20 = 170, + CV_REG_XMM21 = 171, + CV_REG_XMM22 = 172, + CV_REG_XMM23 = 173, + CV_REG_XMM30 = 174, + CV_REG_XMM31 = 175, + CV_REG_XMM32 = 176, + CV_REG_XMM33 = 177, + CV_REG_XMM40 = 178, + CV_REG_XMM41 = 179, + CV_REG_XMM42 = 180, + CV_REG_XMM43 = 181, + CV_REG_XMM50 = 182, + CV_REG_XMM51 = 183, + CV_REG_XMM52 = 184, + CV_REG_XMM53 = 185, + CV_REG_XMM60 = 186, + CV_REG_XMM61 = 187, + CV_REG_XMM62 = 188, + CV_REG_XMM63 = 189, + CV_REG_XMM70 = 190, + CV_REG_XMM71 = 191, + CV_REG_XMM72 = 192, + CV_REG_XMM73 = 193, + + CV_REG_XMM0L = 194, + CV_REG_XMM1L = 195, + CV_REG_XMM2L = 196, + CV_REG_XMM3L = 197, + CV_REG_XMM4L = 198, + CV_REG_XMM5L = 199, + CV_REG_XMM6L = 200, + CV_REG_XMM7L = 201, + + CV_REG_XMM0H = 202, + CV_REG_XMM1H = 203, + CV_REG_XMM2H = 204, + CV_REG_XMM3H = 205, + CV_REG_XMM4H = 206, + CV_REG_XMM5H = 207, + CV_REG_XMM6H = 208, + CV_REG_XMM7H = 209, + + CV_REG_MXCSR = 211, // XMM status register + + CV_REG_EDXEAX = 212, // EDX:EAX pair + + CV_REG_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_REG_EMM1L = 221, + CV_REG_EMM2L = 222, + CV_REG_EMM3L = 223, + CV_REG_EMM4L = 224, + CV_REG_EMM5L = 225, + CV_REG_EMM6L = 226, + CV_REG_EMM7L = 227, + + CV_REG_EMM0H = 228, + CV_REG_EMM1H = 229, + CV_REG_EMM2H = 230, + CV_REG_EMM3H = 231, + CV_REG_EMM4H = 232, + CV_REG_EMM5H = 233, + CV_REG_EMM6H = 234, + CV_REG_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_REG_MM00 = 236, + CV_REG_MM01 = 237, + CV_REG_MM10 = 238, + CV_REG_MM11 = 239, + CV_REG_MM20 = 240, + CV_REG_MM21 = 241, + CV_REG_MM30 = 242, + CV_REG_MM31 = 243, + CV_REG_MM40 = 244, + CV_REG_MM41 = 245, + CV_REG_MM50 = 246, + CV_REG_MM51 = 247, + CV_REG_MM60 = 248, + CV_REG_MM61 = 249, + CV_REG_MM70 = 250, + CV_REG_MM71 = 251, + + CV_REG_YMM0 = 252, // AVX registers + CV_REG_YMM1 = 253, + CV_REG_YMM2 = 254, + CV_REG_YMM3 = 255, + CV_REG_YMM4 = 256, + CV_REG_YMM5 = 257, + CV_REG_YMM6 = 258, + CV_REG_YMM7 = 259, + + CV_REG_YMM0H = 260, + CV_REG_YMM1H = 261, + CV_REG_YMM2H = 262, + CV_REG_YMM3H = 263, + CV_REG_YMM4H = 264, + CV_REG_YMM5H = 265, + CV_REG_YMM6H = 266, + CV_REG_YMM7H = 267, + + CV_REG_YMM0I0 = 268, // AVX integer registers + CV_REG_YMM0I1 = 269, + CV_REG_YMM0I2 = 270, + CV_REG_YMM0I3 = 271, + CV_REG_YMM1I0 = 272, + CV_REG_YMM1I1 = 273, + CV_REG_YMM1I2 = 274, + CV_REG_YMM1I3 = 275, + CV_REG_YMM2I0 = 276, + CV_REG_YMM2I1 = 277, + CV_REG_YMM2I2 = 278, + CV_REG_YMM2I3 = 279, + CV_REG_YMM3I0 = 280, + CV_REG_YMM3I1 = 281, + CV_REG_YMM3I2 = 282, + CV_REG_YMM3I3 = 283, + CV_REG_YMM4I0 = 284, + CV_REG_YMM4I1 = 285, + CV_REG_YMM4I2 = 286, + CV_REG_YMM4I3 = 287, + CV_REG_YMM5I0 = 288, + CV_REG_YMM5I1 = 289, + CV_REG_YMM5I2 = 290, + CV_REG_YMM5I3 = 291, + CV_REG_YMM6I0 = 292, + CV_REG_YMM6I1 = 293, + CV_REG_YMM6I2 = 294, + CV_REG_YMM6I3 = 295, + CV_REG_YMM7I0 = 296, + CV_REG_YMM7I1 = 297, + CV_REG_YMM7I2 = 298, + CV_REG_YMM7I3 = 299, + + CV_REG_YMM0F0 = 300, // AVX floating-point single precise registers + CV_REG_YMM0F1 = 301, + CV_REG_YMM0F2 = 302, + CV_REG_YMM0F3 = 303, + CV_REG_YMM0F4 = 304, + CV_REG_YMM0F5 = 305, + CV_REG_YMM0F6 = 306, + CV_REG_YMM0F7 = 307, + CV_REG_YMM1F0 = 308, + CV_REG_YMM1F1 = 309, + CV_REG_YMM1F2 = 310, + CV_REG_YMM1F3 = 311, + CV_REG_YMM1F4 = 312, + CV_REG_YMM1F5 = 313, + CV_REG_YMM1F6 = 314, + CV_REG_YMM1F7 = 315, + CV_REG_YMM2F0 = 316, + CV_REG_YMM2F1 = 317, + CV_REG_YMM2F2 = 318, + CV_REG_YMM2F3 = 319, + CV_REG_YMM2F4 = 320, + CV_REG_YMM2F5 = 321, + CV_REG_YMM2F6 = 322, + CV_REG_YMM2F7 = 323, + CV_REG_YMM3F0 = 324, + CV_REG_YMM3F1 = 325, + CV_REG_YMM3F2 = 326, + CV_REG_YMM3F3 = 327, + CV_REG_YMM3F4 = 328, + CV_REG_YMM3F5 = 329, + CV_REG_YMM3F6 = 330, + CV_REG_YMM3F7 = 331, + CV_REG_YMM4F0 = 332, + CV_REG_YMM4F1 = 333, + CV_REG_YMM4F2 = 334, + CV_REG_YMM4F3 = 335, + CV_REG_YMM4F4 = 336, + CV_REG_YMM4F5 = 337, + CV_REG_YMM4F6 = 338, + CV_REG_YMM4F7 = 339, + CV_REG_YMM5F0 = 340, + CV_REG_YMM5F1 = 341, + CV_REG_YMM5F2 = 342, + CV_REG_YMM5F3 = 343, + CV_REG_YMM5F4 = 344, + CV_REG_YMM5F5 = 345, + CV_REG_YMM5F6 = 346, + CV_REG_YMM5F7 = 347, + CV_REG_YMM6F0 = 348, + CV_REG_YMM6F1 = 349, + CV_REG_YMM6F2 = 350, + CV_REG_YMM6F3 = 351, + CV_REG_YMM6F4 = 352, + CV_REG_YMM6F5 = 353, + CV_REG_YMM6F6 = 354, + CV_REG_YMM6F7 = 355, + CV_REG_YMM7F0 = 356, + CV_REG_YMM7F1 = 357, + CV_REG_YMM7F2 = 358, + CV_REG_YMM7F3 = 359, + CV_REG_YMM7F4 = 360, + CV_REG_YMM7F5 = 361, + CV_REG_YMM7F6 = 362, + CV_REG_YMM7F7 = 363, + + CV_REG_YMM0D0 = 364, // AVX floating-point double precise registers + CV_REG_YMM0D1 = 365, + CV_REG_YMM0D2 = 366, + CV_REG_YMM0D3 = 367, + CV_REG_YMM1D0 = 368, + CV_REG_YMM1D1 = 369, + CV_REG_YMM1D2 = 370, + CV_REG_YMM1D3 = 371, + CV_REG_YMM2D0 = 372, + CV_REG_YMM2D1 = 373, + CV_REG_YMM2D2 = 374, + CV_REG_YMM2D3 = 375, + CV_REG_YMM3D0 = 376, + CV_REG_YMM3D1 = 377, + CV_REG_YMM3D2 = 378, + CV_REG_YMM3D3 = 379, + CV_REG_YMM4D0 = 380, + CV_REG_YMM4D1 = 381, + CV_REG_YMM4D2 = 382, + CV_REG_YMM4D3 = 383, + CV_REG_YMM5D0 = 384, + CV_REG_YMM5D1 = 385, + CV_REG_YMM5D2 = 386, + CV_REG_YMM5D3 = 387, + CV_REG_YMM6D0 = 388, + CV_REG_YMM6D1 = 389, + CV_REG_YMM6D2 = 390, + CV_REG_YMM6D3 = 391, + CV_REG_YMM7D0 = 392, + CV_REG_YMM7D1 = 393, + CV_REG_YMM7D2 = 394, + CV_REG_YMM7D3 = 395, + + CV_REG_BND0 = 396, + CV_REG_BND1 = 397, + CV_REG_BND2 = 398, + CV_REG_BND3 = 399, + + // registers for the 68K processors + + CV_R68_D0 = 0, + CV_R68_D1 = 1, + CV_R68_D2 = 2, + CV_R68_D3 = 3, + CV_R68_D4 = 4, + CV_R68_D5 = 5, + CV_R68_D6 = 6, + CV_R68_D7 = 7, + CV_R68_A0 = 8, + CV_R68_A1 = 9, + CV_R68_A2 = 10, + CV_R68_A3 = 11, + CV_R68_A4 = 12, + CV_R68_A5 = 13, + CV_R68_A6 = 14, + CV_R68_A7 = 15, + CV_R68_CCR = 16, + CV_R68_SR = 17, + CV_R68_USP = 18, + CV_R68_MSP = 19, + CV_R68_SFC = 20, + CV_R68_DFC = 21, + CV_R68_CACR = 22, + CV_R68_VBR = 23, + CV_R68_CAAR = 24, + CV_R68_ISP = 25, + CV_R68_PC = 26, + //reserved 27 + CV_R68_FPCR = 28, + CV_R68_FPSR = 29, + CV_R68_FPIAR = 30, + //reserved 31 + CV_R68_FP0 = 32, + CV_R68_FP1 = 33, + CV_R68_FP2 = 34, + CV_R68_FP3 = 35, + CV_R68_FP4 = 36, + CV_R68_FP5 = 37, + CV_R68_FP6 = 38, + CV_R68_FP7 = 39, + //reserved 40 + CV_R68_MMUSR030 = 41, + CV_R68_MMUSR = 42, + CV_R68_URP = 43, + CV_R68_DTT0 = 44, + CV_R68_DTT1 = 45, + CV_R68_ITT0 = 46, + CV_R68_ITT1 = 47, + //reserved 50 + CV_R68_PSR = 51, + CV_R68_PCSR = 52, + CV_R68_VAL = 53, + CV_R68_CRP = 54, + CV_R68_SRP = 55, + CV_R68_DRP = 56, + CV_R68_TC = 57, + CV_R68_AC = 58, + CV_R68_SCC = 59, + CV_R68_CAL = 60, + CV_R68_TT0 = 61, + CV_R68_TT1 = 62, + //reserved 63 + CV_R68_BAD0 = 64, + CV_R68_BAD1 = 65, + CV_R68_BAD2 = 66, + CV_R68_BAD3 = 67, + CV_R68_BAD4 = 68, + CV_R68_BAD5 = 69, + CV_R68_BAD6 = 70, + CV_R68_BAD7 = 71, + CV_R68_BAC0 = 72, + CV_R68_BAC1 = 73, + CV_R68_BAC2 = 74, + CV_R68_BAC3 = 75, + CV_R68_BAC4 = 76, + CV_R68_BAC5 = 77, + CV_R68_BAC6 = 78, + CV_R68_BAC7 = 79, + + // Register set for the MIPS 4000 + + CV_M4_NOREG = CV_REG_NONE, + + CV_M4_IntZERO = 10, /* CPU REGISTER */ + CV_M4_IntAT = 11, + CV_M4_IntV0 = 12, + CV_M4_IntV1 = 13, + CV_M4_IntA0 = 14, + CV_M4_IntA1 = 15, + CV_M4_IntA2 = 16, + CV_M4_IntA3 = 17, + CV_M4_IntT0 = 18, + CV_M4_IntT1 = 19, + CV_M4_IntT2 = 20, + CV_M4_IntT3 = 21, + CV_M4_IntT4 = 22, + CV_M4_IntT5 = 23, + CV_M4_IntT6 = 24, + CV_M4_IntT7 = 25, + CV_M4_IntS0 = 26, + CV_M4_IntS1 = 27, + CV_M4_IntS2 = 28, + CV_M4_IntS3 = 29, + CV_M4_IntS4 = 30, + CV_M4_IntS5 = 31, + CV_M4_IntS6 = 32, + CV_M4_IntS7 = 33, + CV_M4_IntT8 = 34, + CV_M4_IntT9 = 35, + CV_M4_IntKT0 = 36, + CV_M4_IntKT1 = 37, + CV_M4_IntGP = 38, + CV_M4_IntSP = 39, + CV_M4_IntS8 = 40, + CV_M4_IntRA = 41, + CV_M4_IntLO = 42, + CV_M4_IntHI = 43, + + CV_M4_Fir = 50, + CV_M4_Psr = 51, + + CV_M4_FltF0 = 60, /* Floating point registers */ + CV_M4_FltF1 = 61, + CV_M4_FltF2 = 62, + CV_M4_FltF3 = 63, + CV_M4_FltF4 = 64, + CV_M4_FltF5 = 65, + CV_M4_FltF6 = 66, + CV_M4_FltF7 = 67, + CV_M4_FltF8 = 68, + CV_M4_FltF9 = 69, + CV_M4_FltF10 = 70, + CV_M4_FltF11 = 71, + CV_M4_FltF12 = 72, + CV_M4_FltF13 = 73, + CV_M4_FltF14 = 74, + CV_M4_FltF15 = 75, + CV_M4_FltF16 = 76, + CV_M4_FltF17 = 77, + CV_M4_FltF18 = 78, + CV_M4_FltF19 = 79, + CV_M4_FltF20 = 80, + CV_M4_FltF21 = 81, + CV_M4_FltF22 = 82, + CV_M4_FltF23 = 83, + CV_M4_FltF24 = 84, + CV_M4_FltF25 = 85, + CV_M4_FltF26 = 86, + CV_M4_FltF27 = 87, + CV_M4_FltF28 = 88, + CV_M4_FltF29 = 89, + CV_M4_FltF30 = 90, + CV_M4_FltF31 = 91, + CV_M4_FltFsr = 92, + + + // Register set for the ALPHA AXP + + CV_ALPHA_NOREG = CV_REG_NONE, + + CV_ALPHA_FltF0 = 10, // Floating point registers + CV_ALPHA_FltF1 = 11, + CV_ALPHA_FltF2 = 12, + CV_ALPHA_FltF3 = 13, + CV_ALPHA_FltF4 = 14, + CV_ALPHA_FltF5 = 15, + CV_ALPHA_FltF6 = 16, + CV_ALPHA_FltF7 = 17, + CV_ALPHA_FltF8 = 18, + CV_ALPHA_FltF9 = 19, + CV_ALPHA_FltF10 = 20, + CV_ALPHA_FltF11 = 21, + CV_ALPHA_FltF12 = 22, + CV_ALPHA_FltF13 = 23, + CV_ALPHA_FltF14 = 24, + CV_ALPHA_FltF15 = 25, + CV_ALPHA_FltF16 = 26, + CV_ALPHA_FltF17 = 27, + CV_ALPHA_FltF18 = 28, + CV_ALPHA_FltF19 = 29, + CV_ALPHA_FltF20 = 30, + CV_ALPHA_FltF21 = 31, + CV_ALPHA_FltF22 = 32, + CV_ALPHA_FltF23 = 33, + CV_ALPHA_FltF24 = 34, + CV_ALPHA_FltF25 = 35, + CV_ALPHA_FltF26 = 36, + CV_ALPHA_FltF27 = 37, + CV_ALPHA_FltF28 = 38, + CV_ALPHA_FltF29 = 39, + CV_ALPHA_FltF30 = 40, + CV_ALPHA_FltF31 = 41, + + CV_ALPHA_IntV0 = 42, // Integer registers + CV_ALPHA_IntT0 = 43, + CV_ALPHA_IntT1 = 44, + CV_ALPHA_IntT2 = 45, + CV_ALPHA_IntT3 = 46, + CV_ALPHA_IntT4 = 47, + CV_ALPHA_IntT5 = 48, + CV_ALPHA_IntT6 = 49, + CV_ALPHA_IntT7 = 50, + CV_ALPHA_IntS0 = 51, + CV_ALPHA_IntS1 = 52, + CV_ALPHA_IntS2 = 53, + CV_ALPHA_IntS3 = 54, + CV_ALPHA_IntS4 = 55, + CV_ALPHA_IntS5 = 56, + CV_ALPHA_IntFP = 57, + CV_ALPHA_IntA0 = 58, + CV_ALPHA_IntA1 = 59, + CV_ALPHA_IntA2 = 60, + CV_ALPHA_IntA3 = 61, + CV_ALPHA_IntA4 = 62, + CV_ALPHA_IntA5 = 63, + CV_ALPHA_IntT8 = 64, + CV_ALPHA_IntT9 = 65, + CV_ALPHA_IntT10 = 66, + CV_ALPHA_IntT11 = 67, + CV_ALPHA_IntRA = 68, + CV_ALPHA_IntT12 = 69, + CV_ALPHA_IntAT = 70, + CV_ALPHA_IntGP = 71, + CV_ALPHA_IntSP = 72, + CV_ALPHA_IntZERO = 73, + + + CV_ALPHA_Fpcr = 74, // Control registers + CV_ALPHA_Fir = 75, + CV_ALPHA_Psr = 76, + CV_ALPHA_FltFsr = 77, + CV_ALPHA_SoftFpcr = 78, + + // Register Set for Motorola/IBM PowerPC + + /* + ** PowerPC General Registers ( User Level ) + */ + CV_PPC_GPR0 = 1, + CV_PPC_GPR1 = 2, + CV_PPC_GPR2 = 3, + CV_PPC_GPR3 = 4, + CV_PPC_GPR4 = 5, + CV_PPC_GPR5 = 6, + CV_PPC_GPR6 = 7, + CV_PPC_GPR7 = 8, + CV_PPC_GPR8 = 9, + CV_PPC_GPR9 = 10, + CV_PPC_GPR10 = 11, + CV_PPC_GPR11 = 12, + CV_PPC_GPR12 = 13, + CV_PPC_GPR13 = 14, + CV_PPC_GPR14 = 15, + CV_PPC_GPR15 = 16, + CV_PPC_GPR16 = 17, + CV_PPC_GPR17 = 18, + CV_PPC_GPR18 = 19, + CV_PPC_GPR19 = 20, + CV_PPC_GPR20 = 21, + CV_PPC_GPR21 = 22, + CV_PPC_GPR22 = 23, + CV_PPC_GPR23 = 24, + CV_PPC_GPR24 = 25, + CV_PPC_GPR25 = 26, + CV_PPC_GPR26 = 27, + CV_PPC_GPR27 = 28, + CV_PPC_GPR28 = 29, + CV_PPC_GPR29 = 30, + CV_PPC_GPR30 = 31, + CV_PPC_GPR31 = 32, + + /* + ** PowerPC Condition Register ( User Level ) + */ + CV_PPC_CR = 33, + CV_PPC_CR0 = 34, + CV_PPC_CR1 = 35, + CV_PPC_CR2 = 36, + CV_PPC_CR3 = 37, + CV_PPC_CR4 = 38, + CV_PPC_CR5 = 39, + CV_PPC_CR6 = 40, + CV_PPC_CR7 = 41, + + /* + ** PowerPC Floating Point Registers ( User Level ) + */ + CV_PPC_FPR0 = 42, + CV_PPC_FPR1 = 43, + CV_PPC_FPR2 = 44, + CV_PPC_FPR3 = 45, + CV_PPC_FPR4 = 46, + CV_PPC_FPR5 = 47, + CV_PPC_FPR6 = 48, + CV_PPC_FPR7 = 49, + CV_PPC_FPR8 = 50, + CV_PPC_FPR9 = 51, + CV_PPC_FPR10 = 52, + CV_PPC_FPR11 = 53, + CV_PPC_FPR12 = 54, + CV_PPC_FPR13 = 55, + CV_PPC_FPR14 = 56, + CV_PPC_FPR15 = 57, + CV_PPC_FPR16 = 58, + CV_PPC_FPR17 = 59, + CV_PPC_FPR18 = 60, + CV_PPC_FPR19 = 61, + CV_PPC_FPR20 = 62, + CV_PPC_FPR21 = 63, + CV_PPC_FPR22 = 64, + CV_PPC_FPR23 = 65, + CV_PPC_FPR24 = 66, + CV_PPC_FPR25 = 67, + CV_PPC_FPR26 = 68, + CV_PPC_FPR27 = 69, + CV_PPC_FPR28 = 70, + CV_PPC_FPR29 = 71, + CV_PPC_FPR30 = 72, + CV_PPC_FPR31 = 73, + + /* + ** PowerPC Floating Point Status and Control Register ( User Level ) + */ + CV_PPC_FPSCR = 74, + + /* + ** PowerPC Machine State Register ( Supervisor Level ) + */ + CV_PPC_MSR = 75, + + /* + ** PowerPC Segment Registers ( Supervisor Level ) + */ + CV_PPC_SR0 = 76, + CV_PPC_SR1 = 77, + CV_PPC_SR2 = 78, + CV_PPC_SR3 = 79, + CV_PPC_SR4 = 80, + CV_PPC_SR5 = 81, + CV_PPC_SR6 = 82, + CV_PPC_SR7 = 83, + CV_PPC_SR8 = 84, + CV_PPC_SR9 = 85, + CV_PPC_SR10 = 86, + CV_PPC_SR11 = 87, + CV_PPC_SR12 = 88, + CV_PPC_SR13 = 89, + CV_PPC_SR14 = 90, + CV_PPC_SR15 = 91, + + /* + ** For all of the special purpose registers add 100 to the SPR# that the + ** Motorola/IBM documentation gives with the exception of any imaginary + ** registers. + */ + + /* + ** PowerPC Special Purpose Registers ( User Level ) + */ + CV_PPC_PC = 99, // PC (imaginary register) + + CV_PPC_MQ = 100, // MPC601 + CV_PPC_XER = 101, + CV_PPC_RTCU = 104, // MPC601 + CV_PPC_RTCL = 105, // MPC601 + CV_PPC_LR = 108, + CV_PPC_CTR = 109, + + CV_PPC_COMPARE = 110, // part of XER (internal to the debugger only) + CV_PPC_COUNT = 111, // part of XER (internal to the debugger only) + + /* + ** PowerPC Special Purpose Registers ( Supervisor Level ) + */ + CV_PPC_DSISR = 118, + CV_PPC_DAR = 119, + CV_PPC_DEC = 122, + CV_PPC_SDR1 = 125, + CV_PPC_SRR0 = 126, + CV_PPC_SRR1 = 127, + CV_PPC_SPRG0 = 372, + CV_PPC_SPRG1 = 373, + CV_PPC_SPRG2 = 374, + CV_PPC_SPRG3 = 375, + CV_PPC_ASR = 280, // 64-bit implementations only + CV_PPC_EAR = 382, + CV_PPC_PVR = 287, + CV_PPC_BAT0U = 628, + CV_PPC_BAT0L = 629, + CV_PPC_BAT1U = 630, + CV_PPC_BAT1L = 631, + CV_PPC_BAT2U = 632, + CV_PPC_BAT2L = 633, + CV_PPC_BAT3U = 634, + CV_PPC_BAT3L = 635, + CV_PPC_DBAT0U = 636, + CV_PPC_DBAT0L = 637, + CV_PPC_DBAT1U = 638, + CV_PPC_DBAT1L = 639, + CV_PPC_DBAT2U = 640, + CV_PPC_DBAT2L = 641, + CV_PPC_DBAT3U = 642, + CV_PPC_DBAT3L = 643, + + /* + ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level ) + */ + + /* + ** Doesn't appear that IBM/Motorola has finished defining these. + */ + + CV_PPC_PMR0 = 1044, // MPC620, + CV_PPC_PMR1 = 1045, // MPC620, + CV_PPC_PMR2 = 1046, // MPC620, + CV_PPC_PMR3 = 1047, // MPC620, + CV_PPC_PMR4 = 1048, // MPC620, + CV_PPC_PMR5 = 1049, // MPC620, + CV_PPC_PMR6 = 1050, // MPC620, + CV_PPC_PMR7 = 1051, // MPC620, + CV_PPC_PMR8 = 1052, // MPC620, + CV_PPC_PMR9 = 1053, // MPC620, + CV_PPC_PMR10 = 1054, // MPC620, + CV_PPC_PMR11 = 1055, // MPC620, + CV_PPC_PMR12 = 1056, // MPC620, + CV_PPC_PMR13 = 1057, // MPC620, + CV_PPC_PMR14 = 1058, // MPC620, + CV_PPC_PMR15 = 1059, // MPC620, + + CV_PPC_DMISS = 1076, // MPC603 + CV_PPC_DCMP = 1077, // MPC603 + CV_PPC_HASH1 = 1078, // MPC603 + CV_PPC_HASH2 = 1079, // MPC603 + CV_PPC_IMISS = 1080, // MPC603 + CV_PPC_ICMP = 1081, // MPC603 + CV_PPC_RPA = 1082, // MPC603 + + CV_PPC_HID0 = 1108, // MPC601, MPC603, MPC620 + CV_PPC_HID1 = 1109, // MPC601 + CV_PPC_HID2 = 1110, // MPC601, MPC603, MPC620 ( IABR ) + CV_PPC_HID3 = 1111, // Not Defined + CV_PPC_HID4 = 1112, // Not Defined + CV_PPC_HID5 = 1113, // MPC601, MPC604, MPC620 ( DABR ) + CV_PPC_HID6 = 1114, // Not Defined + CV_PPC_HID7 = 1115, // Not Defined + CV_PPC_HID8 = 1116, // MPC620 ( BUSCSR ) + CV_PPC_HID9 = 1117, // MPC620 ( L2CSR ) + CV_PPC_HID10 = 1118, // Not Defined + CV_PPC_HID11 = 1119, // Not Defined + CV_PPC_HID12 = 1120, // Not Defined + CV_PPC_HID13 = 1121, // MPC604 ( HCR ) + CV_PPC_HID14 = 1122, // Not Defined + CV_PPC_HID15 = 1123, // MPC601, MPC604, MPC620 ( PIR ) + + // + // JAVA VM registers + // + + CV_JAVA_PC = 1, + + // + // Register set for the Hitachi SH3 + // + + CV_SH3_NOREG = CV_REG_NONE, + + CV_SH3_IntR0 = 10, // CPU REGISTER + CV_SH3_IntR1 = 11, + CV_SH3_IntR2 = 12, + CV_SH3_IntR3 = 13, + CV_SH3_IntR4 = 14, + CV_SH3_IntR5 = 15, + CV_SH3_IntR6 = 16, + CV_SH3_IntR7 = 17, + CV_SH3_IntR8 = 18, + CV_SH3_IntR9 = 19, + CV_SH3_IntR10 = 20, + CV_SH3_IntR11 = 21, + CV_SH3_IntR12 = 22, + CV_SH3_IntR13 = 23, + CV_SH3_IntFp = 24, + CV_SH3_IntSp = 25, + CV_SH3_Gbr = 38, + CV_SH3_Pr = 39, + CV_SH3_Mach = 40, + CV_SH3_Macl = 41, + + CV_SH3_Pc = 50, + CV_SH3_Sr = 51, + + CV_SH3_BarA = 60, + CV_SH3_BasrA = 61, + CV_SH3_BamrA = 62, + CV_SH3_BbrA = 63, + CV_SH3_BarB = 64, + CV_SH3_BasrB = 65, + CV_SH3_BamrB = 66, + CV_SH3_BbrB = 67, + CV_SH3_BdrB = 68, + CV_SH3_BdmrB = 69, + CV_SH3_Brcr = 70, + + // + // Additional registers for Hitachi SH processors + // + + CV_SH_Fpscr = 75, // floating point status/control register + CV_SH_Fpul = 76, // floating point communication register + + CV_SH_FpR0 = 80, // Floating point registers + CV_SH_FpR1 = 81, + CV_SH_FpR2 = 82, + CV_SH_FpR3 = 83, + CV_SH_FpR4 = 84, + CV_SH_FpR5 = 85, + CV_SH_FpR6 = 86, + CV_SH_FpR7 = 87, + CV_SH_FpR8 = 88, + CV_SH_FpR9 = 89, + CV_SH_FpR10 = 90, + CV_SH_FpR11 = 91, + CV_SH_FpR12 = 92, + CV_SH_FpR13 = 93, + CV_SH_FpR14 = 94, + CV_SH_FpR15 = 95, + + CV_SH_XFpR0 = 96, + CV_SH_XFpR1 = 97, + CV_SH_XFpR2 = 98, + CV_SH_XFpR3 = 99, + CV_SH_XFpR4 = 100, + CV_SH_XFpR5 = 101, + CV_SH_XFpR6 = 102, + CV_SH_XFpR7 = 103, + CV_SH_XFpR8 = 104, + CV_SH_XFpR9 = 105, + CV_SH_XFpR10 = 106, + CV_SH_XFpR11 = 107, + CV_SH_XFpR12 = 108, + CV_SH_XFpR13 = 109, + CV_SH_XFpR14 = 110, + CV_SH_XFpR15 = 111, + + // + // Register set for the ARM processor. + // + + CV_ARM_NOREG = CV_REG_NONE, + + CV_ARM_R0 = 10, + CV_ARM_R1 = 11, + CV_ARM_R2 = 12, + CV_ARM_R3 = 13, + CV_ARM_R4 = 14, + CV_ARM_R5 = 15, + CV_ARM_R6 = 16, + CV_ARM_R7 = 17, + CV_ARM_R8 = 18, + CV_ARM_R9 = 19, + CV_ARM_R10 = 20, + CV_ARM_R11 = 21, // Frame pointer, if allocated + CV_ARM_R12 = 22, + CV_ARM_SP = 23, // Stack pointer + CV_ARM_LR = 24, // Link Register + CV_ARM_PC = 25, // Program counter + CV_ARM_CPSR = 26, // Current program status register + + CV_ARM_ACC0 = 27, // DSP co-processor 0 40 bit accumulator + + // + // Registers for ARM VFP10 support + // + + CV_ARM_FPSCR = 40, + CV_ARM_FPEXC = 41, + + CV_ARM_FS0 = 50, + CV_ARM_FS1 = 51, + CV_ARM_FS2 = 52, + CV_ARM_FS3 = 53, + CV_ARM_FS4 = 54, + CV_ARM_FS5 = 55, + CV_ARM_FS6 = 56, + CV_ARM_FS7 = 57, + CV_ARM_FS8 = 58, + CV_ARM_FS9 = 59, + CV_ARM_FS10 = 60, + CV_ARM_FS11 = 61, + CV_ARM_FS12 = 62, + CV_ARM_FS13 = 63, + CV_ARM_FS14 = 64, + CV_ARM_FS15 = 65, + CV_ARM_FS16 = 66, + CV_ARM_FS17 = 67, + CV_ARM_FS18 = 68, + CV_ARM_FS19 = 69, + CV_ARM_FS20 = 70, + CV_ARM_FS21 = 71, + CV_ARM_FS22 = 72, + CV_ARM_FS23 = 73, + CV_ARM_FS24 = 74, + CV_ARM_FS25 = 75, + CV_ARM_FS26 = 76, + CV_ARM_FS27 = 77, + CV_ARM_FS28 = 78, + CV_ARM_FS29 = 79, + CV_ARM_FS30 = 80, + CV_ARM_FS31 = 81, + + // + // ARM VFP Floating Point Extra control registers + // + + CV_ARM_FPEXTRA0 = 90, + CV_ARM_FPEXTRA1 = 91, + CV_ARM_FPEXTRA2 = 92, + CV_ARM_FPEXTRA3 = 93, + CV_ARM_FPEXTRA4 = 94, + CV_ARM_FPEXTRA5 = 95, + CV_ARM_FPEXTRA6 = 96, + CV_ARM_FPEXTRA7 = 97, + + // XSCALE Concan co-processor registers + CV_ARM_WR0 = 128, + CV_ARM_WR1 = 129, + CV_ARM_WR2 = 130, + CV_ARM_WR3 = 131, + CV_ARM_WR4 = 132, + CV_ARM_WR5 = 133, + CV_ARM_WR6 = 134, + CV_ARM_WR7 = 135, + CV_ARM_WR8 = 136, + CV_ARM_WR9 = 137, + CV_ARM_WR10 = 138, + CV_ARM_WR11 = 139, + CV_ARM_WR12 = 140, + CV_ARM_WR13 = 141, + CV_ARM_WR14 = 142, + CV_ARM_WR15 = 143, + + // XSCALE Concan co-processor control registers + CV_ARM_WCID = 144, + CV_ARM_WCON = 145, + CV_ARM_WCSSF = 146, + CV_ARM_WCASF = 147, + CV_ARM_WC4 = 148, + CV_ARM_WC5 = 149, + CV_ARM_WC6 = 150, + CV_ARM_WC7 = 151, + CV_ARM_WCGR0 = 152, + CV_ARM_WCGR1 = 153, + CV_ARM_WCGR2 = 154, + CV_ARM_WCGR3 = 155, + CV_ARM_WC12 = 156, + CV_ARM_WC13 = 157, + CV_ARM_WC14 = 158, + CV_ARM_WC15 = 159, + + // + // ARM VFPv3/Neon extended floating Point + // + + CV_ARM_FS32 = 200, + CV_ARM_FS33 = 201, + CV_ARM_FS34 = 202, + CV_ARM_FS35 = 203, + CV_ARM_FS36 = 204, + CV_ARM_FS37 = 205, + CV_ARM_FS38 = 206, + CV_ARM_FS39 = 207, + CV_ARM_FS40 = 208, + CV_ARM_FS41 = 209, + CV_ARM_FS42 = 210, + CV_ARM_FS43 = 211, + CV_ARM_FS44 = 212, + CV_ARM_FS45 = 213, + CV_ARM_FS46 = 214, + CV_ARM_FS47 = 215, + CV_ARM_FS48 = 216, + CV_ARM_FS49 = 217, + CV_ARM_FS50 = 218, + CV_ARM_FS51 = 219, + CV_ARM_FS52 = 220, + CV_ARM_FS53 = 221, + CV_ARM_FS54 = 222, + CV_ARM_FS55 = 223, + CV_ARM_FS56 = 224, + CV_ARM_FS57 = 225, + CV_ARM_FS58 = 226, + CV_ARM_FS59 = 227, + CV_ARM_FS60 = 228, + CV_ARM_FS61 = 229, + CV_ARM_FS62 = 230, + CV_ARM_FS63 = 231, + + // ARM double-precision floating point + + CV_ARM_ND0 = 300, + CV_ARM_ND1 = 301, + CV_ARM_ND2 = 302, + CV_ARM_ND3 = 303, + CV_ARM_ND4 = 304, + CV_ARM_ND5 = 305, + CV_ARM_ND6 = 306, + CV_ARM_ND7 = 307, + CV_ARM_ND8 = 308, + CV_ARM_ND9 = 309, + CV_ARM_ND10 = 310, + CV_ARM_ND11 = 311, + CV_ARM_ND12 = 312, + CV_ARM_ND13 = 313, + CV_ARM_ND14 = 314, + CV_ARM_ND15 = 315, + CV_ARM_ND16 = 316, + CV_ARM_ND17 = 317, + CV_ARM_ND18 = 318, + CV_ARM_ND19 = 319, + CV_ARM_ND20 = 320, + CV_ARM_ND21 = 321, + CV_ARM_ND22 = 322, + CV_ARM_ND23 = 323, + CV_ARM_ND24 = 324, + CV_ARM_ND25 = 325, + CV_ARM_ND26 = 326, + CV_ARM_ND27 = 327, + CV_ARM_ND28 = 328, + CV_ARM_ND29 = 329, + CV_ARM_ND30 = 330, + CV_ARM_ND31 = 331, + + // ARM extended precision floating point + + CV_ARM_NQ0 = 400, + CV_ARM_NQ1 = 401, + CV_ARM_NQ2 = 402, + CV_ARM_NQ3 = 403, + CV_ARM_NQ4 = 404, + CV_ARM_NQ5 = 405, + CV_ARM_NQ6 = 406, + CV_ARM_NQ7 = 407, + CV_ARM_NQ8 = 408, + CV_ARM_NQ9 = 409, + CV_ARM_NQ10 = 410, + CV_ARM_NQ11 = 411, + CV_ARM_NQ12 = 412, + CV_ARM_NQ13 = 413, + CV_ARM_NQ14 = 414, + CV_ARM_NQ15 = 415, + + // + // Register set for ARM64 + // + + CV_ARM64_NOREG = CV_REG_NONE, + + // General purpose 32-bit integer registers + + CV_ARM64_W0 = 10, + CV_ARM64_W1 = 11, + CV_ARM64_W2 = 12, + CV_ARM64_W3 = 13, + CV_ARM64_W4 = 14, + CV_ARM64_W5 = 15, + CV_ARM64_W6 = 16, + CV_ARM64_W7 = 17, + CV_ARM64_W8 = 18, + CV_ARM64_W9 = 19, + CV_ARM64_W10 = 20, + CV_ARM64_W11 = 21, + CV_ARM64_W12 = 22, + CV_ARM64_W13 = 23, + CV_ARM64_W14 = 24, + CV_ARM64_W15 = 25, + CV_ARM64_W16 = 26, + CV_ARM64_W17 = 27, + CV_ARM64_W18 = 28, + CV_ARM64_W19 = 29, + CV_ARM64_W20 = 30, + CV_ARM64_W21 = 31, + CV_ARM64_W22 = 32, + CV_ARM64_W23 = 33, + CV_ARM64_W24 = 34, + CV_ARM64_W25 = 35, + CV_ARM64_W26 = 36, + CV_ARM64_W27 = 37, + CV_ARM64_W28 = 38, + CV_ARM64_W29 = 39, + CV_ARM64_W30 = 40, + CV_ARM64_WZR = 41, + + // General purpose 64-bit integer registers + + CV_ARM64_X0 = 50, + CV_ARM64_X1 = 51, + CV_ARM64_X2 = 52, + CV_ARM64_X3 = 53, + CV_ARM64_X4 = 54, + CV_ARM64_X5 = 55, + CV_ARM64_X6 = 56, + CV_ARM64_X7 = 57, + CV_ARM64_X8 = 58, + CV_ARM64_X9 = 59, + CV_ARM64_X10 = 60, + CV_ARM64_X11 = 61, + CV_ARM64_X12 = 62, + CV_ARM64_X13 = 63, + CV_ARM64_X14 = 64, + CV_ARM64_X15 = 65, + CV_ARM64_IP0 = 66, + CV_ARM64_IP1 = 67, + CV_ARM64_X18 = 68, + CV_ARM64_X19 = 69, + CV_ARM64_X20 = 70, + CV_ARM64_X21 = 71, + CV_ARM64_X22 = 72, + CV_ARM64_X23 = 73, + CV_ARM64_X24 = 74, + CV_ARM64_X25 = 75, + CV_ARM64_X26 = 76, + CV_ARM64_X27 = 77, + CV_ARM64_X28 = 78, + CV_ARM64_FP = 79, + CV_ARM64_LR = 80, + CV_ARM64_SP = 81, + CV_ARM64_ZR = 82, + + // statue register + + CV_ARM64_NZCV = 90, + + // 32-bit floating point registers + + CV_ARM64_S0 = 100, + CV_ARM64_S1 = 101, + CV_ARM64_S2 = 102, + CV_ARM64_S3 = 103, + CV_ARM64_S4 = 104, + CV_ARM64_S5 = 105, + CV_ARM64_S6 = 106, + CV_ARM64_S7 = 107, + CV_ARM64_S8 = 108, + CV_ARM64_S9 = 109, + CV_ARM64_S10 = 110, + CV_ARM64_S11 = 111, + CV_ARM64_S12 = 112, + CV_ARM64_S13 = 113, + CV_ARM64_S14 = 114, + CV_ARM64_S15 = 115, + CV_ARM64_S16 = 116, + CV_ARM64_S17 = 117, + CV_ARM64_S18 = 118, + CV_ARM64_S19 = 119, + CV_ARM64_S20 = 120, + CV_ARM64_S21 = 121, + CV_ARM64_S22 = 122, + CV_ARM64_S23 = 123, + CV_ARM64_S24 = 124, + CV_ARM64_S25 = 125, + CV_ARM64_S26 = 126, + CV_ARM64_S27 = 127, + CV_ARM64_S28 = 128, + CV_ARM64_S29 = 129, + CV_ARM64_S30 = 130, + CV_ARM64_S31 = 131, + + // 64-bit floating point registers + + CV_ARM64_D0 = 140, + CV_ARM64_D1 = 141, + CV_ARM64_D2 = 142, + CV_ARM64_D3 = 143, + CV_ARM64_D4 = 144, + CV_ARM64_D5 = 145, + CV_ARM64_D6 = 146, + CV_ARM64_D7 = 147, + CV_ARM64_D8 = 148, + CV_ARM64_D9 = 149, + CV_ARM64_D10 = 150, + CV_ARM64_D11 = 151, + CV_ARM64_D12 = 152, + CV_ARM64_D13 = 153, + CV_ARM64_D14 = 154, + CV_ARM64_D15 = 155, + CV_ARM64_D16 = 156, + CV_ARM64_D17 = 157, + CV_ARM64_D18 = 158, + CV_ARM64_D19 = 159, + CV_ARM64_D20 = 160, + CV_ARM64_D21 = 161, + CV_ARM64_D22 = 162, + CV_ARM64_D23 = 163, + CV_ARM64_D24 = 164, + CV_ARM64_D25 = 165, + CV_ARM64_D26 = 166, + CV_ARM64_D27 = 167, + CV_ARM64_D28 = 168, + CV_ARM64_D29 = 169, + CV_ARM64_D30 = 170, + CV_ARM64_D31 = 171, + + // 128-bit SIMD registers + + CV_ARM64_Q0 = 180, + CV_ARM64_Q1 = 181, + CV_ARM64_Q2 = 182, + CV_ARM64_Q3 = 183, + CV_ARM64_Q4 = 184, + CV_ARM64_Q5 = 185, + CV_ARM64_Q6 = 186, + CV_ARM64_Q7 = 187, + CV_ARM64_Q8 = 188, + CV_ARM64_Q9 = 189, + CV_ARM64_Q10 = 190, + CV_ARM64_Q11 = 191, + CV_ARM64_Q12 = 192, + CV_ARM64_Q13 = 193, + CV_ARM64_Q14 = 194, + CV_ARM64_Q15 = 195, + CV_ARM64_Q16 = 196, + CV_ARM64_Q17 = 197, + CV_ARM64_Q18 = 198, + CV_ARM64_Q19 = 199, + CV_ARM64_Q20 = 200, + CV_ARM64_Q21 = 201, + CV_ARM64_Q22 = 202, + CV_ARM64_Q23 = 203, + CV_ARM64_Q24 = 204, + CV_ARM64_Q25 = 205, + CV_ARM64_Q26 = 206, + CV_ARM64_Q27 = 207, + CV_ARM64_Q28 = 208, + CV_ARM64_Q29 = 209, + CV_ARM64_Q30 = 210, + CV_ARM64_Q31 = 211, + + // Floating point status register + + CV_ARM64_FPSR = 220, + + // + // Register set for Intel IA64 + // + + CV_IA64_NOREG = CV_REG_NONE, + + // Branch Registers + + CV_IA64_Br0 = 512, + CV_IA64_Br1 = 513, + CV_IA64_Br2 = 514, + CV_IA64_Br3 = 515, + CV_IA64_Br4 = 516, + CV_IA64_Br5 = 517, + CV_IA64_Br6 = 518, + CV_IA64_Br7 = 519, + + // Predicate Registers + + CV_IA64_P0 = 704, + CV_IA64_P1 = 705, + CV_IA64_P2 = 706, + CV_IA64_P3 = 707, + CV_IA64_P4 = 708, + CV_IA64_P5 = 709, + CV_IA64_P6 = 710, + CV_IA64_P7 = 711, + CV_IA64_P8 = 712, + CV_IA64_P9 = 713, + CV_IA64_P10 = 714, + CV_IA64_P11 = 715, + CV_IA64_P12 = 716, + CV_IA64_P13 = 717, + CV_IA64_P14 = 718, + CV_IA64_P15 = 719, + CV_IA64_P16 = 720, + CV_IA64_P17 = 721, + CV_IA64_P18 = 722, + CV_IA64_P19 = 723, + CV_IA64_P20 = 724, + CV_IA64_P21 = 725, + CV_IA64_P22 = 726, + CV_IA64_P23 = 727, + CV_IA64_P24 = 728, + CV_IA64_P25 = 729, + CV_IA64_P26 = 730, + CV_IA64_P27 = 731, + CV_IA64_P28 = 732, + CV_IA64_P29 = 733, + CV_IA64_P30 = 734, + CV_IA64_P31 = 735, + CV_IA64_P32 = 736, + CV_IA64_P33 = 737, + CV_IA64_P34 = 738, + CV_IA64_P35 = 739, + CV_IA64_P36 = 740, + CV_IA64_P37 = 741, + CV_IA64_P38 = 742, + CV_IA64_P39 = 743, + CV_IA64_P40 = 744, + CV_IA64_P41 = 745, + CV_IA64_P42 = 746, + CV_IA64_P43 = 747, + CV_IA64_P44 = 748, + CV_IA64_P45 = 749, + CV_IA64_P46 = 750, + CV_IA64_P47 = 751, + CV_IA64_P48 = 752, + CV_IA64_P49 = 753, + CV_IA64_P50 = 754, + CV_IA64_P51 = 755, + CV_IA64_P52 = 756, + CV_IA64_P53 = 757, + CV_IA64_P54 = 758, + CV_IA64_P55 = 759, + CV_IA64_P56 = 760, + CV_IA64_P57 = 761, + CV_IA64_P58 = 762, + CV_IA64_P59 = 763, + CV_IA64_P60 = 764, + CV_IA64_P61 = 765, + CV_IA64_P62 = 766, + CV_IA64_P63 = 767, + + CV_IA64_Preds = 768, + + // Banked General Registers + + CV_IA64_IntH0 = 832, + CV_IA64_IntH1 = 833, + CV_IA64_IntH2 = 834, + CV_IA64_IntH3 = 835, + CV_IA64_IntH4 = 836, + CV_IA64_IntH5 = 837, + CV_IA64_IntH6 = 838, + CV_IA64_IntH7 = 839, + CV_IA64_IntH8 = 840, + CV_IA64_IntH9 = 841, + CV_IA64_IntH10 = 842, + CV_IA64_IntH11 = 843, + CV_IA64_IntH12 = 844, + CV_IA64_IntH13 = 845, + CV_IA64_IntH14 = 846, + CV_IA64_IntH15 = 847, + + // Special Registers + + CV_IA64_Ip = 1016, + CV_IA64_Umask = 1017, + CV_IA64_Cfm = 1018, + CV_IA64_Psr = 1019, + + // Banked General Registers + + CV_IA64_Nats = 1020, + CV_IA64_Nats2 = 1021, + CV_IA64_Nats3 = 1022, + + // General-Purpose Registers + + // Integer registers + CV_IA64_IntR0 = 1024, + CV_IA64_IntR1 = 1025, + CV_IA64_IntR2 = 1026, + CV_IA64_IntR3 = 1027, + CV_IA64_IntR4 = 1028, + CV_IA64_IntR5 = 1029, + CV_IA64_IntR6 = 1030, + CV_IA64_IntR7 = 1031, + CV_IA64_IntR8 = 1032, + CV_IA64_IntR9 = 1033, + CV_IA64_IntR10 = 1034, + CV_IA64_IntR11 = 1035, + CV_IA64_IntR12 = 1036, + CV_IA64_IntR13 = 1037, + CV_IA64_IntR14 = 1038, + CV_IA64_IntR15 = 1039, + CV_IA64_IntR16 = 1040, + CV_IA64_IntR17 = 1041, + CV_IA64_IntR18 = 1042, + CV_IA64_IntR19 = 1043, + CV_IA64_IntR20 = 1044, + CV_IA64_IntR21 = 1045, + CV_IA64_IntR22 = 1046, + CV_IA64_IntR23 = 1047, + CV_IA64_IntR24 = 1048, + CV_IA64_IntR25 = 1049, + CV_IA64_IntR26 = 1050, + CV_IA64_IntR27 = 1051, + CV_IA64_IntR28 = 1052, + CV_IA64_IntR29 = 1053, + CV_IA64_IntR30 = 1054, + CV_IA64_IntR31 = 1055, + + // Register Stack + CV_IA64_IntR32 = 1056, + CV_IA64_IntR33 = 1057, + CV_IA64_IntR34 = 1058, + CV_IA64_IntR35 = 1059, + CV_IA64_IntR36 = 1060, + CV_IA64_IntR37 = 1061, + CV_IA64_IntR38 = 1062, + CV_IA64_IntR39 = 1063, + CV_IA64_IntR40 = 1064, + CV_IA64_IntR41 = 1065, + CV_IA64_IntR42 = 1066, + CV_IA64_IntR43 = 1067, + CV_IA64_IntR44 = 1068, + CV_IA64_IntR45 = 1069, + CV_IA64_IntR46 = 1070, + CV_IA64_IntR47 = 1071, + CV_IA64_IntR48 = 1072, + CV_IA64_IntR49 = 1073, + CV_IA64_IntR50 = 1074, + CV_IA64_IntR51 = 1075, + CV_IA64_IntR52 = 1076, + CV_IA64_IntR53 = 1077, + CV_IA64_IntR54 = 1078, + CV_IA64_IntR55 = 1079, + CV_IA64_IntR56 = 1080, + CV_IA64_IntR57 = 1081, + CV_IA64_IntR58 = 1082, + CV_IA64_IntR59 = 1083, + CV_IA64_IntR60 = 1084, + CV_IA64_IntR61 = 1085, + CV_IA64_IntR62 = 1086, + CV_IA64_IntR63 = 1087, + CV_IA64_IntR64 = 1088, + CV_IA64_IntR65 = 1089, + CV_IA64_IntR66 = 1090, + CV_IA64_IntR67 = 1091, + CV_IA64_IntR68 = 1092, + CV_IA64_IntR69 = 1093, + CV_IA64_IntR70 = 1094, + CV_IA64_IntR71 = 1095, + CV_IA64_IntR72 = 1096, + CV_IA64_IntR73 = 1097, + CV_IA64_IntR74 = 1098, + CV_IA64_IntR75 = 1099, + CV_IA64_IntR76 = 1100, + CV_IA64_IntR77 = 1101, + CV_IA64_IntR78 = 1102, + CV_IA64_IntR79 = 1103, + CV_IA64_IntR80 = 1104, + CV_IA64_IntR81 = 1105, + CV_IA64_IntR82 = 1106, + CV_IA64_IntR83 = 1107, + CV_IA64_IntR84 = 1108, + CV_IA64_IntR85 = 1109, + CV_IA64_IntR86 = 1110, + CV_IA64_IntR87 = 1111, + CV_IA64_IntR88 = 1112, + CV_IA64_IntR89 = 1113, + CV_IA64_IntR90 = 1114, + CV_IA64_IntR91 = 1115, + CV_IA64_IntR92 = 1116, + CV_IA64_IntR93 = 1117, + CV_IA64_IntR94 = 1118, + CV_IA64_IntR95 = 1119, + CV_IA64_IntR96 = 1120, + CV_IA64_IntR97 = 1121, + CV_IA64_IntR98 = 1122, + CV_IA64_IntR99 = 1123, + CV_IA64_IntR100 = 1124, + CV_IA64_IntR101 = 1125, + CV_IA64_IntR102 = 1126, + CV_IA64_IntR103 = 1127, + CV_IA64_IntR104 = 1128, + CV_IA64_IntR105 = 1129, + CV_IA64_IntR106 = 1130, + CV_IA64_IntR107 = 1131, + CV_IA64_IntR108 = 1132, + CV_IA64_IntR109 = 1133, + CV_IA64_IntR110 = 1134, + CV_IA64_IntR111 = 1135, + CV_IA64_IntR112 = 1136, + CV_IA64_IntR113 = 1137, + CV_IA64_IntR114 = 1138, + CV_IA64_IntR115 = 1139, + CV_IA64_IntR116 = 1140, + CV_IA64_IntR117 = 1141, + CV_IA64_IntR118 = 1142, + CV_IA64_IntR119 = 1143, + CV_IA64_IntR120 = 1144, + CV_IA64_IntR121 = 1145, + CV_IA64_IntR122 = 1146, + CV_IA64_IntR123 = 1147, + CV_IA64_IntR124 = 1148, + CV_IA64_IntR125 = 1149, + CV_IA64_IntR126 = 1150, + CV_IA64_IntR127 = 1151, + + // Floating-Point Registers + + // Low Floating Point Registers + CV_IA64_FltF0 = 2048, + CV_IA64_FltF1 = 2049, + CV_IA64_FltF2 = 2050, + CV_IA64_FltF3 = 2051, + CV_IA64_FltF4 = 2052, + CV_IA64_FltF5 = 2053, + CV_IA64_FltF6 = 2054, + CV_IA64_FltF7 = 2055, + CV_IA64_FltF8 = 2056, + CV_IA64_FltF9 = 2057, + CV_IA64_FltF10 = 2058, + CV_IA64_FltF11 = 2059, + CV_IA64_FltF12 = 2060, + CV_IA64_FltF13 = 2061, + CV_IA64_FltF14 = 2062, + CV_IA64_FltF15 = 2063, + CV_IA64_FltF16 = 2064, + CV_IA64_FltF17 = 2065, + CV_IA64_FltF18 = 2066, + CV_IA64_FltF19 = 2067, + CV_IA64_FltF20 = 2068, + CV_IA64_FltF21 = 2069, + CV_IA64_FltF22 = 2070, + CV_IA64_FltF23 = 2071, + CV_IA64_FltF24 = 2072, + CV_IA64_FltF25 = 2073, + CV_IA64_FltF26 = 2074, + CV_IA64_FltF27 = 2075, + CV_IA64_FltF28 = 2076, + CV_IA64_FltF29 = 2077, + CV_IA64_FltF30 = 2078, + CV_IA64_FltF31 = 2079, + + // High Floating Point Registers + CV_IA64_FltF32 = 2080, + CV_IA64_FltF33 = 2081, + CV_IA64_FltF34 = 2082, + CV_IA64_FltF35 = 2083, + CV_IA64_FltF36 = 2084, + CV_IA64_FltF37 = 2085, + CV_IA64_FltF38 = 2086, + CV_IA64_FltF39 = 2087, + CV_IA64_FltF40 = 2088, + CV_IA64_FltF41 = 2089, + CV_IA64_FltF42 = 2090, + CV_IA64_FltF43 = 2091, + CV_IA64_FltF44 = 2092, + CV_IA64_FltF45 = 2093, + CV_IA64_FltF46 = 2094, + CV_IA64_FltF47 = 2095, + CV_IA64_FltF48 = 2096, + CV_IA64_FltF49 = 2097, + CV_IA64_FltF50 = 2098, + CV_IA64_FltF51 = 2099, + CV_IA64_FltF52 = 2100, + CV_IA64_FltF53 = 2101, + CV_IA64_FltF54 = 2102, + CV_IA64_FltF55 = 2103, + CV_IA64_FltF56 = 2104, + CV_IA64_FltF57 = 2105, + CV_IA64_FltF58 = 2106, + CV_IA64_FltF59 = 2107, + CV_IA64_FltF60 = 2108, + CV_IA64_FltF61 = 2109, + CV_IA64_FltF62 = 2110, + CV_IA64_FltF63 = 2111, + CV_IA64_FltF64 = 2112, + CV_IA64_FltF65 = 2113, + CV_IA64_FltF66 = 2114, + CV_IA64_FltF67 = 2115, + CV_IA64_FltF68 = 2116, + CV_IA64_FltF69 = 2117, + CV_IA64_FltF70 = 2118, + CV_IA64_FltF71 = 2119, + CV_IA64_FltF72 = 2120, + CV_IA64_FltF73 = 2121, + CV_IA64_FltF74 = 2122, + CV_IA64_FltF75 = 2123, + CV_IA64_FltF76 = 2124, + CV_IA64_FltF77 = 2125, + CV_IA64_FltF78 = 2126, + CV_IA64_FltF79 = 2127, + CV_IA64_FltF80 = 2128, + CV_IA64_FltF81 = 2129, + CV_IA64_FltF82 = 2130, + CV_IA64_FltF83 = 2131, + CV_IA64_FltF84 = 2132, + CV_IA64_FltF85 = 2133, + CV_IA64_FltF86 = 2134, + CV_IA64_FltF87 = 2135, + CV_IA64_FltF88 = 2136, + CV_IA64_FltF89 = 2137, + CV_IA64_FltF90 = 2138, + CV_IA64_FltF91 = 2139, + CV_IA64_FltF92 = 2140, + CV_IA64_FltF93 = 2141, + CV_IA64_FltF94 = 2142, + CV_IA64_FltF95 = 2143, + CV_IA64_FltF96 = 2144, + CV_IA64_FltF97 = 2145, + CV_IA64_FltF98 = 2146, + CV_IA64_FltF99 = 2147, + CV_IA64_FltF100 = 2148, + CV_IA64_FltF101 = 2149, + CV_IA64_FltF102 = 2150, + CV_IA64_FltF103 = 2151, + CV_IA64_FltF104 = 2152, + CV_IA64_FltF105 = 2153, + CV_IA64_FltF106 = 2154, + CV_IA64_FltF107 = 2155, + CV_IA64_FltF108 = 2156, + CV_IA64_FltF109 = 2157, + CV_IA64_FltF110 = 2158, + CV_IA64_FltF111 = 2159, + CV_IA64_FltF112 = 2160, + CV_IA64_FltF113 = 2161, + CV_IA64_FltF114 = 2162, + CV_IA64_FltF115 = 2163, + CV_IA64_FltF116 = 2164, + CV_IA64_FltF117 = 2165, + CV_IA64_FltF118 = 2166, + CV_IA64_FltF119 = 2167, + CV_IA64_FltF120 = 2168, + CV_IA64_FltF121 = 2169, + CV_IA64_FltF122 = 2170, + CV_IA64_FltF123 = 2171, + CV_IA64_FltF124 = 2172, + CV_IA64_FltF125 = 2173, + CV_IA64_FltF126 = 2174, + CV_IA64_FltF127 = 2175, + + // Application Registers + + CV_IA64_ApKR0 = 3072, + CV_IA64_ApKR1 = 3073, + CV_IA64_ApKR2 = 3074, + CV_IA64_ApKR3 = 3075, + CV_IA64_ApKR4 = 3076, + CV_IA64_ApKR5 = 3077, + CV_IA64_ApKR6 = 3078, + CV_IA64_ApKR7 = 3079, + CV_IA64_AR8 = 3080, + CV_IA64_AR9 = 3081, + CV_IA64_AR10 = 3082, + CV_IA64_AR11 = 3083, + CV_IA64_AR12 = 3084, + CV_IA64_AR13 = 3085, + CV_IA64_AR14 = 3086, + CV_IA64_AR15 = 3087, + CV_IA64_RsRSC = 3088, + CV_IA64_RsBSP = 3089, + CV_IA64_RsBSPSTORE = 3090, + CV_IA64_RsRNAT = 3091, + CV_IA64_AR20 = 3092, + CV_IA64_StFCR = 3093, + CV_IA64_AR22 = 3094, + CV_IA64_AR23 = 3095, + CV_IA64_EFLAG = 3096, + CV_IA64_CSD = 3097, + CV_IA64_SSD = 3098, + CV_IA64_CFLG = 3099, + CV_IA64_StFSR = 3100, + CV_IA64_StFIR = 3101, + CV_IA64_StFDR = 3102, + CV_IA64_AR31 = 3103, + CV_IA64_ApCCV = 3104, + CV_IA64_AR33 = 3105, + CV_IA64_AR34 = 3106, + CV_IA64_AR35 = 3107, + CV_IA64_ApUNAT = 3108, + CV_IA64_AR37 = 3109, + CV_IA64_AR38 = 3110, + CV_IA64_AR39 = 3111, + CV_IA64_StFPSR = 3112, + CV_IA64_AR41 = 3113, + CV_IA64_AR42 = 3114, + CV_IA64_AR43 = 3115, + CV_IA64_ApITC = 3116, + CV_IA64_AR45 = 3117, + CV_IA64_AR46 = 3118, + CV_IA64_AR47 = 3119, + CV_IA64_AR48 = 3120, + CV_IA64_AR49 = 3121, + CV_IA64_AR50 = 3122, + CV_IA64_AR51 = 3123, + CV_IA64_AR52 = 3124, + CV_IA64_AR53 = 3125, + CV_IA64_AR54 = 3126, + CV_IA64_AR55 = 3127, + CV_IA64_AR56 = 3128, + CV_IA64_AR57 = 3129, + CV_IA64_AR58 = 3130, + CV_IA64_AR59 = 3131, + CV_IA64_AR60 = 3132, + CV_IA64_AR61 = 3133, + CV_IA64_AR62 = 3134, + CV_IA64_AR63 = 3135, + CV_IA64_RsPFS = 3136, + CV_IA64_ApLC = 3137, + CV_IA64_ApEC = 3138, + CV_IA64_AR67 = 3139, + CV_IA64_AR68 = 3140, + CV_IA64_AR69 = 3141, + CV_IA64_AR70 = 3142, + CV_IA64_AR71 = 3143, + CV_IA64_AR72 = 3144, + CV_IA64_AR73 = 3145, + CV_IA64_AR74 = 3146, + CV_IA64_AR75 = 3147, + CV_IA64_AR76 = 3148, + CV_IA64_AR77 = 3149, + CV_IA64_AR78 = 3150, + CV_IA64_AR79 = 3151, + CV_IA64_AR80 = 3152, + CV_IA64_AR81 = 3153, + CV_IA64_AR82 = 3154, + CV_IA64_AR83 = 3155, + CV_IA64_AR84 = 3156, + CV_IA64_AR85 = 3157, + CV_IA64_AR86 = 3158, + CV_IA64_AR87 = 3159, + CV_IA64_AR88 = 3160, + CV_IA64_AR89 = 3161, + CV_IA64_AR90 = 3162, + CV_IA64_AR91 = 3163, + CV_IA64_AR92 = 3164, + CV_IA64_AR93 = 3165, + CV_IA64_AR94 = 3166, + CV_IA64_AR95 = 3167, + CV_IA64_AR96 = 3168, + CV_IA64_AR97 = 3169, + CV_IA64_AR98 = 3170, + CV_IA64_AR99 = 3171, + CV_IA64_AR100 = 3172, + CV_IA64_AR101 = 3173, + CV_IA64_AR102 = 3174, + CV_IA64_AR103 = 3175, + CV_IA64_AR104 = 3176, + CV_IA64_AR105 = 3177, + CV_IA64_AR106 = 3178, + CV_IA64_AR107 = 3179, + CV_IA64_AR108 = 3180, + CV_IA64_AR109 = 3181, + CV_IA64_AR110 = 3182, + CV_IA64_AR111 = 3183, + CV_IA64_AR112 = 3184, + CV_IA64_AR113 = 3185, + CV_IA64_AR114 = 3186, + CV_IA64_AR115 = 3187, + CV_IA64_AR116 = 3188, + CV_IA64_AR117 = 3189, + CV_IA64_AR118 = 3190, + CV_IA64_AR119 = 3191, + CV_IA64_AR120 = 3192, + CV_IA64_AR121 = 3193, + CV_IA64_AR122 = 3194, + CV_IA64_AR123 = 3195, + CV_IA64_AR124 = 3196, + CV_IA64_AR125 = 3197, + CV_IA64_AR126 = 3198, + CV_IA64_AR127 = 3199, + + // CPUID Registers + + CV_IA64_CPUID0 = 3328, + CV_IA64_CPUID1 = 3329, + CV_IA64_CPUID2 = 3330, + CV_IA64_CPUID3 = 3331, + CV_IA64_CPUID4 = 3332, + + // Control Registers + + CV_IA64_ApDCR = 4096, + CV_IA64_ApITM = 4097, + CV_IA64_ApIVA = 4098, + CV_IA64_CR3 = 4099, + CV_IA64_CR4 = 4100, + CV_IA64_CR5 = 4101, + CV_IA64_CR6 = 4102, + CV_IA64_CR7 = 4103, + CV_IA64_ApPTA = 4104, + CV_IA64_ApGPTA = 4105, + CV_IA64_CR10 = 4106, + CV_IA64_CR11 = 4107, + CV_IA64_CR12 = 4108, + CV_IA64_CR13 = 4109, + CV_IA64_CR14 = 4110, + CV_IA64_CR15 = 4111, + CV_IA64_StIPSR = 4112, + CV_IA64_StISR = 4113, + CV_IA64_CR18 = 4114, + CV_IA64_StIIP = 4115, + CV_IA64_StIFA = 4116, + CV_IA64_StITIR = 4117, + CV_IA64_StIIPA = 4118, + CV_IA64_StIFS = 4119, + CV_IA64_StIIM = 4120, + CV_IA64_StIHA = 4121, + CV_IA64_CR26 = 4122, + CV_IA64_CR27 = 4123, + CV_IA64_CR28 = 4124, + CV_IA64_CR29 = 4125, + CV_IA64_CR30 = 4126, + CV_IA64_CR31 = 4127, + CV_IA64_CR32 = 4128, + CV_IA64_CR33 = 4129, + CV_IA64_CR34 = 4130, + CV_IA64_CR35 = 4131, + CV_IA64_CR36 = 4132, + CV_IA64_CR37 = 4133, + CV_IA64_CR38 = 4134, + CV_IA64_CR39 = 4135, + CV_IA64_CR40 = 4136, + CV_IA64_CR41 = 4137, + CV_IA64_CR42 = 4138, + CV_IA64_CR43 = 4139, + CV_IA64_CR44 = 4140, + CV_IA64_CR45 = 4141, + CV_IA64_CR46 = 4142, + CV_IA64_CR47 = 4143, + CV_IA64_CR48 = 4144, + CV_IA64_CR49 = 4145, + CV_IA64_CR50 = 4146, + CV_IA64_CR51 = 4147, + CV_IA64_CR52 = 4148, + CV_IA64_CR53 = 4149, + CV_IA64_CR54 = 4150, + CV_IA64_CR55 = 4151, + CV_IA64_CR56 = 4152, + CV_IA64_CR57 = 4153, + CV_IA64_CR58 = 4154, + CV_IA64_CR59 = 4155, + CV_IA64_CR60 = 4156, + CV_IA64_CR61 = 4157, + CV_IA64_CR62 = 4158, + CV_IA64_CR63 = 4159, + CV_IA64_SaLID = 4160, + CV_IA64_SaIVR = 4161, + CV_IA64_SaTPR = 4162, + CV_IA64_SaEOI = 4163, + CV_IA64_SaIRR0 = 4164, + CV_IA64_SaIRR1 = 4165, + CV_IA64_SaIRR2 = 4166, + CV_IA64_SaIRR3 = 4167, + CV_IA64_SaITV = 4168, + CV_IA64_SaPMV = 4169, + CV_IA64_SaCMCV = 4170, + CV_IA64_CR75 = 4171, + CV_IA64_CR76 = 4172, + CV_IA64_CR77 = 4173, + CV_IA64_CR78 = 4174, + CV_IA64_CR79 = 4175, + CV_IA64_SaLRR0 = 4176, + CV_IA64_SaLRR1 = 4177, + CV_IA64_CR82 = 4178, + CV_IA64_CR83 = 4179, + CV_IA64_CR84 = 4180, + CV_IA64_CR85 = 4181, + CV_IA64_CR86 = 4182, + CV_IA64_CR87 = 4183, + CV_IA64_CR88 = 4184, + CV_IA64_CR89 = 4185, + CV_IA64_CR90 = 4186, + CV_IA64_CR91 = 4187, + CV_IA64_CR92 = 4188, + CV_IA64_CR93 = 4189, + CV_IA64_CR94 = 4190, + CV_IA64_CR95 = 4191, + CV_IA64_CR96 = 4192, + CV_IA64_CR97 = 4193, + CV_IA64_CR98 = 4194, + CV_IA64_CR99 = 4195, + CV_IA64_CR100 = 4196, + CV_IA64_CR101 = 4197, + CV_IA64_CR102 = 4198, + CV_IA64_CR103 = 4199, + CV_IA64_CR104 = 4200, + CV_IA64_CR105 = 4201, + CV_IA64_CR106 = 4202, + CV_IA64_CR107 = 4203, + CV_IA64_CR108 = 4204, + CV_IA64_CR109 = 4205, + CV_IA64_CR110 = 4206, + CV_IA64_CR111 = 4207, + CV_IA64_CR112 = 4208, + CV_IA64_CR113 = 4209, + CV_IA64_CR114 = 4210, + CV_IA64_CR115 = 4211, + CV_IA64_CR116 = 4212, + CV_IA64_CR117 = 4213, + CV_IA64_CR118 = 4214, + CV_IA64_CR119 = 4215, + CV_IA64_CR120 = 4216, + CV_IA64_CR121 = 4217, + CV_IA64_CR122 = 4218, + CV_IA64_CR123 = 4219, + CV_IA64_CR124 = 4220, + CV_IA64_CR125 = 4221, + CV_IA64_CR126 = 4222, + CV_IA64_CR127 = 4223, + + // Protection Key Registers + + CV_IA64_Pkr0 = 5120, + CV_IA64_Pkr1 = 5121, + CV_IA64_Pkr2 = 5122, + CV_IA64_Pkr3 = 5123, + CV_IA64_Pkr4 = 5124, + CV_IA64_Pkr5 = 5125, + CV_IA64_Pkr6 = 5126, + CV_IA64_Pkr7 = 5127, + CV_IA64_Pkr8 = 5128, + CV_IA64_Pkr9 = 5129, + CV_IA64_Pkr10 = 5130, + CV_IA64_Pkr11 = 5131, + CV_IA64_Pkr12 = 5132, + CV_IA64_Pkr13 = 5133, + CV_IA64_Pkr14 = 5134, + CV_IA64_Pkr15 = 5135, + + // Region Registers + + CV_IA64_Rr0 = 6144, + CV_IA64_Rr1 = 6145, + CV_IA64_Rr2 = 6146, + CV_IA64_Rr3 = 6147, + CV_IA64_Rr4 = 6148, + CV_IA64_Rr5 = 6149, + CV_IA64_Rr6 = 6150, + CV_IA64_Rr7 = 6151, + + // Performance Monitor Data Registers + + CV_IA64_PFD0 = 7168, + CV_IA64_PFD1 = 7169, + CV_IA64_PFD2 = 7170, + CV_IA64_PFD3 = 7171, + CV_IA64_PFD4 = 7172, + CV_IA64_PFD5 = 7173, + CV_IA64_PFD6 = 7174, + CV_IA64_PFD7 = 7175, + CV_IA64_PFD8 = 7176, + CV_IA64_PFD9 = 7177, + CV_IA64_PFD10 = 7178, + CV_IA64_PFD11 = 7179, + CV_IA64_PFD12 = 7180, + CV_IA64_PFD13 = 7181, + CV_IA64_PFD14 = 7182, + CV_IA64_PFD15 = 7183, + CV_IA64_PFD16 = 7184, + CV_IA64_PFD17 = 7185, + + // Performance Monitor Config Registers + + CV_IA64_PFC0 = 7424, + CV_IA64_PFC1 = 7425, + CV_IA64_PFC2 = 7426, + CV_IA64_PFC3 = 7427, + CV_IA64_PFC4 = 7428, + CV_IA64_PFC5 = 7429, + CV_IA64_PFC6 = 7430, + CV_IA64_PFC7 = 7431, + CV_IA64_PFC8 = 7432, + CV_IA64_PFC9 = 7433, + CV_IA64_PFC10 = 7434, + CV_IA64_PFC11 = 7435, + CV_IA64_PFC12 = 7436, + CV_IA64_PFC13 = 7437, + CV_IA64_PFC14 = 7438, + CV_IA64_PFC15 = 7439, + + // Instruction Translation Registers + + CV_IA64_TrI0 = 8192, + CV_IA64_TrI1 = 8193, + CV_IA64_TrI2 = 8194, + CV_IA64_TrI3 = 8195, + CV_IA64_TrI4 = 8196, + CV_IA64_TrI5 = 8197, + CV_IA64_TrI6 = 8198, + CV_IA64_TrI7 = 8199, + + // Data Translation Registers + + CV_IA64_TrD0 = 8320, + CV_IA64_TrD1 = 8321, + CV_IA64_TrD2 = 8322, + CV_IA64_TrD3 = 8323, + CV_IA64_TrD4 = 8324, + CV_IA64_TrD5 = 8325, + CV_IA64_TrD6 = 8326, + CV_IA64_TrD7 = 8327, + + // Instruction Breakpoint Registers + + CV_IA64_DbI0 = 8448, + CV_IA64_DbI1 = 8449, + CV_IA64_DbI2 = 8450, + CV_IA64_DbI3 = 8451, + CV_IA64_DbI4 = 8452, + CV_IA64_DbI5 = 8453, + CV_IA64_DbI6 = 8454, + CV_IA64_DbI7 = 8455, + + // Data Breakpoint Registers + + CV_IA64_DbD0 = 8576, + CV_IA64_DbD1 = 8577, + CV_IA64_DbD2 = 8578, + CV_IA64_DbD3 = 8579, + CV_IA64_DbD4 = 8580, + CV_IA64_DbD5 = 8581, + CV_IA64_DbD6 = 8582, + CV_IA64_DbD7 = 8583, + + // + // Register set for the TriCore processor. + // + + CV_TRI_NOREG = CV_REG_NONE, + + // General Purpose Data Registers + + CV_TRI_D0 = 10, + CV_TRI_D1 = 11, + CV_TRI_D2 = 12, + CV_TRI_D3 = 13, + CV_TRI_D4 = 14, + CV_TRI_D5 = 15, + CV_TRI_D6 = 16, + CV_TRI_D7 = 17, + CV_TRI_D8 = 18, + CV_TRI_D9 = 19, + CV_TRI_D10 = 20, + CV_TRI_D11 = 21, + CV_TRI_D12 = 22, + CV_TRI_D13 = 23, + CV_TRI_D14 = 24, + CV_TRI_D15 = 25, + + // General Purpose Address Registers + + CV_TRI_A0 = 26, + CV_TRI_A1 = 27, + CV_TRI_A2 = 28, + CV_TRI_A3 = 29, + CV_TRI_A4 = 30, + CV_TRI_A5 = 31, + CV_TRI_A6 = 32, + CV_TRI_A7 = 33, + CV_TRI_A8 = 34, + CV_TRI_A9 = 35, + CV_TRI_A10 = 36, + CV_TRI_A11 = 37, + CV_TRI_A12 = 38, + CV_TRI_A13 = 39, + CV_TRI_A14 = 40, + CV_TRI_A15 = 41, + + // Extended (64-bit) data registers + + CV_TRI_E0 = 42, + CV_TRI_E2 = 43, + CV_TRI_E4 = 44, + CV_TRI_E6 = 45, + CV_TRI_E8 = 46, + CV_TRI_E10 = 47, + CV_TRI_E12 = 48, + CV_TRI_E14 = 49, + + // Extended (64-bit) address registers + + CV_TRI_EA0 = 50, + CV_TRI_EA2 = 51, + CV_TRI_EA4 = 52, + CV_TRI_EA6 = 53, + CV_TRI_EA8 = 54, + CV_TRI_EA10 = 55, + CV_TRI_EA12 = 56, + CV_TRI_EA14 = 57, + + CV_TRI_PSW = 58, + CV_TRI_PCXI = 59, + CV_TRI_PC = 60, + CV_TRI_FCX = 61, + CV_TRI_LCX = 62, + CV_TRI_ISP = 63, + CV_TRI_ICR = 64, + CV_TRI_BIV = 65, + CV_TRI_BTV = 66, + CV_TRI_SYSCON = 67, + CV_TRI_DPRx_0 = 68, + CV_TRI_DPRx_1 = 69, + CV_TRI_DPRx_2 = 70, + CV_TRI_DPRx_3 = 71, + CV_TRI_CPRx_0 = 68, + CV_TRI_CPRx_1 = 69, + CV_TRI_CPRx_2 = 70, + CV_TRI_CPRx_3 = 71, + CV_TRI_DPMx_0 = 68, + CV_TRI_DPMx_1 = 69, + CV_TRI_DPMx_2 = 70, + CV_TRI_DPMx_3 = 71, + CV_TRI_CPMx_0 = 68, + CV_TRI_CPMx_1 = 69, + CV_TRI_CPMx_2 = 70, + CV_TRI_CPMx_3 = 71, + CV_TRI_DBGSSR = 72, + CV_TRI_EXEVT = 73, + CV_TRI_SWEVT = 74, + CV_TRI_CREVT = 75, + CV_TRI_TRnEVT = 76, + CV_TRI_MMUCON = 77, + CV_TRI_ASI = 78, + CV_TRI_TVA = 79, + CV_TRI_TPA = 80, + CV_TRI_TPX = 81, + CV_TRI_TFA = 82, + + // + // Register set for the AM33 and related processors. + // + + CV_AM33_NOREG = CV_REG_NONE, + + // "Extended" (general purpose integer) registers + CV_AM33_E0 = 10, + CV_AM33_E1 = 11, + CV_AM33_E2 = 12, + CV_AM33_E3 = 13, + CV_AM33_E4 = 14, + CV_AM33_E5 = 15, + CV_AM33_E6 = 16, + CV_AM33_E7 = 17, + + // Address registers + CV_AM33_A0 = 20, + CV_AM33_A1 = 21, + CV_AM33_A2 = 22, + CV_AM33_A3 = 23, + + // Integer data registers + CV_AM33_D0 = 30, + CV_AM33_D1 = 31, + CV_AM33_D2 = 32, + CV_AM33_D3 = 33, + + // (Single-precision) floating-point registers + CV_AM33_FS0 = 40, + CV_AM33_FS1 = 41, + CV_AM33_FS2 = 42, + CV_AM33_FS3 = 43, + CV_AM33_FS4 = 44, + CV_AM33_FS5 = 45, + CV_AM33_FS6 = 46, + CV_AM33_FS7 = 47, + CV_AM33_FS8 = 48, + CV_AM33_FS9 = 49, + CV_AM33_FS10 = 50, + CV_AM33_FS11 = 51, + CV_AM33_FS12 = 52, + CV_AM33_FS13 = 53, + CV_AM33_FS14 = 54, + CV_AM33_FS15 = 55, + CV_AM33_FS16 = 56, + CV_AM33_FS17 = 57, + CV_AM33_FS18 = 58, + CV_AM33_FS19 = 59, + CV_AM33_FS20 = 60, + CV_AM33_FS21 = 61, + CV_AM33_FS22 = 62, + CV_AM33_FS23 = 63, + CV_AM33_FS24 = 64, + CV_AM33_FS25 = 65, + CV_AM33_FS26 = 66, + CV_AM33_FS27 = 67, + CV_AM33_FS28 = 68, + CV_AM33_FS29 = 69, + CV_AM33_FS30 = 70, + CV_AM33_FS31 = 71, + + // Special purpose registers + + // Stack pointer + CV_AM33_SP = 80, + + // Program counter + CV_AM33_PC = 81, + + // Multiply-divide/accumulate registers + CV_AM33_MDR = 82, + CV_AM33_MDRQ = 83, + CV_AM33_MCRH = 84, + CV_AM33_MCRL = 85, + CV_AM33_MCVF = 86, + + // CPU status words + CV_AM33_EPSW = 87, + CV_AM33_FPCR = 88, + + // Loop buffer registers + CV_AM33_LIR = 89, + CV_AM33_LAR = 90, + + // + // Register set for the Mitsubishi M32R + // + + CV_M32R_NOREG = CV_REG_NONE, + + CV_M32R_R0 = 10, + CV_M32R_R1 = 11, + CV_M32R_R2 = 12, + CV_M32R_R3 = 13, + CV_M32R_R4 = 14, + CV_M32R_R5 = 15, + CV_M32R_R6 = 16, + CV_M32R_R7 = 17, + CV_M32R_R8 = 18, + CV_M32R_R9 = 19, + CV_M32R_R10 = 20, + CV_M32R_R11 = 21, + CV_M32R_R12 = 22, // Gloabal Pointer, if used + CV_M32R_R13 = 23, // Frame Pointer, if allocated + CV_M32R_R14 = 24, // Link Register + CV_M32R_R15 = 25, // Stack Pointer + CV_M32R_PSW = 26, // Preocessor Status Register + CV_M32R_CBR = 27, // Condition Bit Register + CV_M32R_SPI = 28, // Interrupt Stack Pointer + CV_M32R_SPU = 29, // User Stack Pointer + CV_M32R_SPO = 30, // OS Stack Pointer + CV_M32R_BPC = 31, // Backup Program Counter + CV_M32R_ACHI = 32, // Accumulator High + CV_M32R_ACLO = 33, // Accumulator Low + CV_M32R_PC = 34, // Program Counter + + // + // Register set for the SuperH SHMedia processor including compact + // mode + // + + // Integer - 64 bit general registers + CV_SHMEDIA_NOREG = CV_REG_NONE, + CV_SHMEDIA_R0 = 10, + CV_SHMEDIA_R1 = 11, + CV_SHMEDIA_R2 = 12, + CV_SHMEDIA_R3 = 13, + CV_SHMEDIA_R4 = 14, + CV_SHMEDIA_R5 = 15, + CV_SHMEDIA_R6 = 16, + CV_SHMEDIA_R7 = 17, + CV_SHMEDIA_R8 = 18, + CV_SHMEDIA_R9 = 19, + CV_SHMEDIA_R10 = 20, + CV_SHMEDIA_R11 = 21, + CV_SHMEDIA_R12 = 22, + CV_SHMEDIA_R13 = 23, + CV_SHMEDIA_R14 = 24, + CV_SHMEDIA_R15 = 25, + CV_SHMEDIA_R16 = 26, + CV_SHMEDIA_R17 = 27, + CV_SHMEDIA_R18 = 28, + CV_SHMEDIA_R19 = 29, + CV_SHMEDIA_R20 = 30, + CV_SHMEDIA_R21 = 31, + CV_SHMEDIA_R22 = 32, + CV_SHMEDIA_R23 = 33, + CV_SHMEDIA_R24 = 34, + CV_SHMEDIA_R25 = 35, + CV_SHMEDIA_R26 = 36, + CV_SHMEDIA_R27 = 37, + CV_SHMEDIA_R28 = 38, + CV_SHMEDIA_R29 = 39, + CV_SHMEDIA_R30 = 40, + CV_SHMEDIA_R31 = 41, + CV_SHMEDIA_R32 = 42, + CV_SHMEDIA_R33 = 43, + CV_SHMEDIA_R34 = 44, + CV_SHMEDIA_R35 = 45, + CV_SHMEDIA_R36 = 46, + CV_SHMEDIA_R37 = 47, + CV_SHMEDIA_R38 = 48, + CV_SHMEDIA_R39 = 49, + CV_SHMEDIA_R40 = 50, + CV_SHMEDIA_R41 = 51, + CV_SHMEDIA_R42 = 52, + CV_SHMEDIA_R43 = 53, + CV_SHMEDIA_R44 = 54, + CV_SHMEDIA_R45 = 55, + CV_SHMEDIA_R46 = 56, + CV_SHMEDIA_R47 = 57, + CV_SHMEDIA_R48 = 58, + CV_SHMEDIA_R49 = 59, + CV_SHMEDIA_R50 = 60, + CV_SHMEDIA_R51 = 61, + CV_SHMEDIA_R52 = 62, + CV_SHMEDIA_R53 = 63, + CV_SHMEDIA_R54 = 64, + CV_SHMEDIA_R55 = 65, + CV_SHMEDIA_R56 = 66, + CV_SHMEDIA_R57 = 67, + CV_SHMEDIA_R58 = 68, + CV_SHMEDIA_R59 = 69, + CV_SHMEDIA_R60 = 70, + CV_SHMEDIA_R61 = 71, + CV_SHMEDIA_R62 = 72, + CV_SHMEDIA_R63 = 73, + + // Target Registers - 32 bit + CV_SHMEDIA_TR0 = 74, + CV_SHMEDIA_TR1 = 75, + CV_SHMEDIA_TR2 = 76, + CV_SHMEDIA_TR3 = 77, + CV_SHMEDIA_TR4 = 78, + CV_SHMEDIA_TR5 = 79, + CV_SHMEDIA_TR6 = 80, + CV_SHMEDIA_TR7 = 81, + CV_SHMEDIA_TR8 = 82, // future-proof + CV_SHMEDIA_TR9 = 83, // future-proof + CV_SHMEDIA_TR10 = 84, // future-proof + CV_SHMEDIA_TR11 = 85, // future-proof + CV_SHMEDIA_TR12 = 86, // future-proof + CV_SHMEDIA_TR13 = 87, // future-proof + CV_SHMEDIA_TR14 = 88, // future-proof + CV_SHMEDIA_TR15 = 89, // future-proof + + // Single - 32 bit fp registers + CV_SHMEDIA_FR0 = 128, + CV_SHMEDIA_FR1 = 129, + CV_SHMEDIA_FR2 = 130, + CV_SHMEDIA_FR3 = 131, + CV_SHMEDIA_FR4 = 132, + CV_SHMEDIA_FR5 = 133, + CV_SHMEDIA_FR6 = 134, + CV_SHMEDIA_FR7 = 135, + CV_SHMEDIA_FR8 = 136, + CV_SHMEDIA_FR9 = 137, + CV_SHMEDIA_FR10 = 138, + CV_SHMEDIA_FR11 = 139, + CV_SHMEDIA_FR12 = 140, + CV_SHMEDIA_FR13 = 141, + CV_SHMEDIA_FR14 = 142, + CV_SHMEDIA_FR15 = 143, + CV_SHMEDIA_FR16 = 144, + CV_SHMEDIA_FR17 = 145, + CV_SHMEDIA_FR18 = 146, + CV_SHMEDIA_FR19 = 147, + CV_SHMEDIA_FR20 = 148, + CV_SHMEDIA_FR21 = 149, + CV_SHMEDIA_FR22 = 150, + CV_SHMEDIA_FR23 = 151, + CV_SHMEDIA_FR24 = 152, + CV_SHMEDIA_FR25 = 153, + CV_SHMEDIA_FR26 = 154, + CV_SHMEDIA_FR27 = 155, + CV_SHMEDIA_FR28 = 156, + CV_SHMEDIA_FR29 = 157, + CV_SHMEDIA_FR30 = 158, + CV_SHMEDIA_FR31 = 159, + CV_SHMEDIA_FR32 = 160, + CV_SHMEDIA_FR33 = 161, + CV_SHMEDIA_FR34 = 162, + CV_SHMEDIA_FR35 = 163, + CV_SHMEDIA_FR36 = 164, + CV_SHMEDIA_FR37 = 165, + CV_SHMEDIA_FR38 = 166, + CV_SHMEDIA_FR39 = 167, + CV_SHMEDIA_FR40 = 168, + CV_SHMEDIA_FR41 = 169, + CV_SHMEDIA_FR42 = 170, + CV_SHMEDIA_FR43 = 171, + CV_SHMEDIA_FR44 = 172, + CV_SHMEDIA_FR45 = 173, + CV_SHMEDIA_FR46 = 174, + CV_SHMEDIA_FR47 = 175, + CV_SHMEDIA_FR48 = 176, + CV_SHMEDIA_FR49 = 177, + CV_SHMEDIA_FR50 = 178, + CV_SHMEDIA_FR51 = 179, + CV_SHMEDIA_FR52 = 180, + CV_SHMEDIA_FR53 = 181, + CV_SHMEDIA_FR54 = 182, + CV_SHMEDIA_FR55 = 183, + CV_SHMEDIA_FR56 = 184, + CV_SHMEDIA_FR57 = 185, + CV_SHMEDIA_FR58 = 186, + CV_SHMEDIA_FR59 = 187, + CV_SHMEDIA_FR60 = 188, + CV_SHMEDIA_FR61 = 189, + CV_SHMEDIA_FR62 = 190, + CV_SHMEDIA_FR63 = 191, + + // Double - 64 bit synonyms for 32bit fp register pairs + // subtract 128 to find first base single register + CV_SHMEDIA_DR0 = 256, + CV_SHMEDIA_DR2 = 258, + CV_SHMEDIA_DR4 = 260, + CV_SHMEDIA_DR6 = 262, + CV_SHMEDIA_DR8 = 264, + CV_SHMEDIA_DR10 = 266, + CV_SHMEDIA_DR12 = 268, + CV_SHMEDIA_DR14 = 270, + CV_SHMEDIA_DR16 = 272, + CV_SHMEDIA_DR18 = 274, + CV_SHMEDIA_DR20 = 276, + CV_SHMEDIA_DR22 = 278, + CV_SHMEDIA_DR24 = 280, + CV_SHMEDIA_DR26 = 282, + CV_SHMEDIA_DR28 = 284, + CV_SHMEDIA_DR30 = 286, + CV_SHMEDIA_DR32 = 288, + CV_SHMEDIA_DR34 = 290, + CV_SHMEDIA_DR36 = 292, + CV_SHMEDIA_DR38 = 294, + CV_SHMEDIA_DR40 = 296, + CV_SHMEDIA_DR42 = 298, + CV_SHMEDIA_DR44 = 300, + CV_SHMEDIA_DR46 = 302, + CV_SHMEDIA_DR48 = 304, + CV_SHMEDIA_DR50 = 306, + CV_SHMEDIA_DR52 = 308, + CV_SHMEDIA_DR54 = 310, + CV_SHMEDIA_DR56 = 312, + CV_SHMEDIA_DR58 = 314, + CV_SHMEDIA_DR60 = 316, + CV_SHMEDIA_DR62 = 318, + + // Vector - 128 bit synonyms for 32bit fp register quads + // subtract 384 to find first base single register + CV_SHMEDIA_FV0 = 512, + CV_SHMEDIA_FV4 = 516, + CV_SHMEDIA_FV8 = 520, + CV_SHMEDIA_FV12 = 524, + CV_SHMEDIA_FV16 = 528, + CV_SHMEDIA_FV20 = 532, + CV_SHMEDIA_FV24 = 536, + CV_SHMEDIA_FV28 = 540, + CV_SHMEDIA_FV32 = 544, + CV_SHMEDIA_FV36 = 548, + CV_SHMEDIA_FV40 = 552, + CV_SHMEDIA_FV44 = 556, + CV_SHMEDIA_FV48 = 560, + CV_SHMEDIA_FV52 = 564, + CV_SHMEDIA_FV56 = 568, + CV_SHMEDIA_FV60 = 572, + + // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers + // subtract 896 to find first base single register + CV_SHMEDIA_MTRX0 = 1024, + CV_SHMEDIA_MTRX16 = 1040, + CV_SHMEDIA_MTRX32 = 1056, + CV_SHMEDIA_MTRX48 = 1072, + + // Control - Implementation defined 64bit control registers + CV_SHMEDIA_CR0 = 2000, + CV_SHMEDIA_CR1 = 2001, + CV_SHMEDIA_CR2 = 2002, + CV_SHMEDIA_CR3 = 2003, + CV_SHMEDIA_CR4 = 2004, + CV_SHMEDIA_CR5 = 2005, + CV_SHMEDIA_CR6 = 2006, + CV_SHMEDIA_CR7 = 2007, + CV_SHMEDIA_CR8 = 2008, + CV_SHMEDIA_CR9 = 2009, + CV_SHMEDIA_CR10 = 2010, + CV_SHMEDIA_CR11 = 2011, + CV_SHMEDIA_CR12 = 2012, + CV_SHMEDIA_CR13 = 2013, + CV_SHMEDIA_CR14 = 2014, + CV_SHMEDIA_CR15 = 2015, + CV_SHMEDIA_CR16 = 2016, + CV_SHMEDIA_CR17 = 2017, + CV_SHMEDIA_CR18 = 2018, + CV_SHMEDIA_CR19 = 2019, + CV_SHMEDIA_CR20 = 2020, + CV_SHMEDIA_CR21 = 2021, + CV_SHMEDIA_CR22 = 2022, + CV_SHMEDIA_CR23 = 2023, + CV_SHMEDIA_CR24 = 2024, + CV_SHMEDIA_CR25 = 2025, + CV_SHMEDIA_CR26 = 2026, + CV_SHMEDIA_CR27 = 2027, + CV_SHMEDIA_CR28 = 2028, + CV_SHMEDIA_CR29 = 2029, + CV_SHMEDIA_CR30 = 2030, + CV_SHMEDIA_CR31 = 2031, + CV_SHMEDIA_CR32 = 2032, + CV_SHMEDIA_CR33 = 2033, + CV_SHMEDIA_CR34 = 2034, + CV_SHMEDIA_CR35 = 2035, + CV_SHMEDIA_CR36 = 2036, + CV_SHMEDIA_CR37 = 2037, + CV_SHMEDIA_CR38 = 2038, + CV_SHMEDIA_CR39 = 2039, + CV_SHMEDIA_CR40 = 2040, + CV_SHMEDIA_CR41 = 2041, + CV_SHMEDIA_CR42 = 2042, + CV_SHMEDIA_CR43 = 2043, + CV_SHMEDIA_CR44 = 2044, + CV_SHMEDIA_CR45 = 2045, + CV_SHMEDIA_CR46 = 2046, + CV_SHMEDIA_CR47 = 2047, + CV_SHMEDIA_CR48 = 2048, + CV_SHMEDIA_CR49 = 2049, + CV_SHMEDIA_CR50 = 2050, + CV_SHMEDIA_CR51 = 2051, + CV_SHMEDIA_CR52 = 2052, + CV_SHMEDIA_CR53 = 2053, + CV_SHMEDIA_CR54 = 2054, + CV_SHMEDIA_CR55 = 2055, + CV_SHMEDIA_CR56 = 2056, + CV_SHMEDIA_CR57 = 2057, + CV_SHMEDIA_CR58 = 2058, + CV_SHMEDIA_CR59 = 2059, + CV_SHMEDIA_CR60 = 2060, + CV_SHMEDIA_CR61 = 2061, + CV_SHMEDIA_CR62 = 2062, + CV_SHMEDIA_CR63 = 2063, + + CV_SHMEDIA_FPSCR = 2064, + + // Compact mode synonyms + CV_SHMEDIA_GBR = CV_SHMEDIA_R16, + CV_SHMEDIA_MACL = 90, // synonym for lower 32bits of media R17 + CV_SHMEDIA_MACH = 91, // synonym for upper 32bits of media R17 + CV_SHMEDIA_PR = CV_SHMEDIA_R18, + CV_SHMEDIA_T = 92, // synonym for lowest bit of media R19 + CV_SHMEDIA_FPUL = CV_SHMEDIA_FR32, + CV_SHMEDIA_PC = 93, + CV_SHMEDIA_SR = CV_SHMEDIA_CR0, + + // + // AMD64 registers + // + + CV_AMD64_AL = 1, + CV_AMD64_CL = 2, + CV_AMD64_DL = 3, + CV_AMD64_BL = 4, + CV_AMD64_AH = 5, + CV_AMD64_CH = 6, + CV_AMD64_DH = 7, + CV_AMD64_BH = 8, + CV_AMD64_AX = 9, + CV_AMD64_CX = 10, + CV_AMD64_DX = 11, + CV_AMD64_BX = 12, + CV_AMD64_SP = 13, + CV_AMD64_BP = 14, + CV_AMD64_SI = 15, + CV_AMD64_DI = 16, + CV_AMD64_EAX = 17, + CV_AMD64_ECX = 18, + CV_AMD64_EDX = 19, + CV_AMD64_EBX = 20, + CV_AMD64_ESP = 21, + CV_AMD64_EBP = 22, + CV_AMD64_ESI = 23, + CV_AMD64_EDI = 24, + CV_AMD64_ES = 25, + CV_AMD64_CS = 26, + CV_AMD64_SS = 27, + CV_AMD64_DS = 28, + CV_AMD64_FS = 29, + CV_AMD64_GS = 30, + CV_AMD64_FLAGS = 32, + CV_AMD64_RIP = 33, + CV_AMD64_EFLAGS = 34, + + // Control registers + CV_AMD64_CR0 = 80, + CV_AMD64_CR1 = 81, + CV_AMD64_CR2 = 82, + CV_AMD64_CR3 = 83, + CV_AMD64_CR4 = 84, + CV_AMD64_CR8 = 88, + + // Debug registers + CV_AMD64_DR0 = 90, + CV_AMD64_DR1 = 91, + CV_AMD64_DR2 = 92, + CV_AMD64_DR3 = 93, + CV_AMD64_DR4 = 94, + CV_AMD64_DR5 = 95, + CV_AMD64_DR6 = 96, + CV_AMD64_DR7 = 97, + CV_AMD64_DR8 = 98, + CV_AMD64_DR9 = 99, + CV_AMD64_DR10 = 100, + CV_AMD64_DR11 = 101, + CV_AMD64_DR12 = 102, + CV_AMD64_DR13 = 103, + CV_AMD64_DR14 = 104, + CV_AMD64_DR15 = 105, + + CV_AMD64_GDTR = 110, + CV_AMD64_GDTL = 111, + CV_AMD64_IDTR = 112, + CV_AMD64_IDTL = 113, + CV_AMD64_LDTR = 114, + CV_AMD64_TR = 115, + + CV_AMD64_ST0 = 128, + CV_AMD64_ST1 = 129, + CV_AMD64_ST2 = 130, + CV_AMD64_ST3 = 131, + CV_AMD64_ST4 = 132, + CV_AMD64_ST5 = 133, + CV_AMD64_ST6 = 134, + CV_AMD64_ST7 = 135, + CV_AMD64_CTRL = 136, + CV_AMD64_STAT = 137, + CV_AMD64_TAG = 138, + CV_AMD64_FPIP = 139, + CV_AMD64_FPCS = 140, + CV_AMD64_FPDO = 141, + CV_AMD64_FPDS = 142, + CV_AMD64_ISEM = 143, + CV_AMD64_FPEIP = 144, + CV_AMD64_FPEDO = 145, + + CV_AMD64_MM0 = 146, + CV_AMD64_MM1 = 147, + CV_AMD64_MM2 = 148, + CV_AMD64_MM3 = 149, + CV_AMD64_MM4 = 150, + CV_AMD64_MM5 = 151, + CV_AMD64_MM6 = 152, + CV_AMD64_MM7 = 153, + + CV_AMD64_XMM0 = 154, // KATMAI registers + CV_AMD64_XMM1 = 155, + CV_AMD64_XMM2 = 156, + CV_AMD64_XMM3 = 157, + CV_AMD64_XMM4 = 158, + CV_AMD64_XMM5 = 159, + CV_AMD64_XMM6 = 160, + CV_AMD64_XMM7 = 161, + + CV_AMD64_XMM0_0 = 162, // KATMAI sub-registers + CV_AMD64_XMM0_1 = 163, + CV_AMD64_XMM0_2 = 164, + CV_AMD64_XMM0_3 = 165, + CV_AMD64_XMM1_0 = 166, + CV_AMD64_XMM1_1 = 167, + CV_AMD64_XMM1_2 = 168, + CV_AMD64_XMM1_3 = 169, + CV_AMD64_XMM2_0 = 170, + CV_AMD64_XMM2_1 = 171, + CV_AMD64_XMM2_2 = 172, + CV_AMD64_XMM2_3 = 173, + CV_AMD64_XMM3_0 = 174, + CV_AMD64_XMM3_1 = 175, + CV_AMD64_XMM3_2 = 176, + CV_AMD64_XMM3_3 = 177, + CV_AMD64_XMM4_0 = 178, + CV_AMD64_XMM4_1 = 179, + CV_AMD64_XMM4_2 = 180, + CV_AMD64_XMM4_3 = 181, + CV_AMD64_XMM5_0 = 182, + CV_AMD64_XMM5_1 = 183, + CV_AMD64_XMM5_2 = 184, + CV_AMD64_XMM5_3 = 185, + CV_AMD64_XMM6_0 = 186, + CV_AMD64_XMM6_1 = 187, + CV_AMD64_XMM6_2 = 188, + CV_AMD64_XMM6_3 = 189, + CV_AMD64_XMM7_0 = 190, + CV_AMD64_XMM7_1 = 191, + CV_AMD64_XMM7_2 = 192, + CV_AMD64_XMM7_3 = 193, + + CV_AMD64_XMM0L = 194, + CV_AMD64_XMM1L = 195, + CV_AMD64_XMM2L = 196, + CV_AMD64_XMM3L = 197, + CV_AMD64_XMM4L = 198, + CV_AMD64_XMM5L = 199, + CV_AMD64_XMM6L = 200, + CV_AMD64_XMM7L = 201, + + CV_AMD64_XMM0H = 202, + CV_AMD64_XMM1H = 203, + CV_AMD64_XMM2H = 204, + CV_AMD64_XMM3H = 205, + CV_AMD64_XMM4H = 206, + CV_AMD64_XMM5H = 207, + CV_AMD64_XMM6H = 208, + CV_AMD64_XMM7H = 209, + + CV_AMD64_MXCSR = 211, // XMM status register + + CV_AMD64_EMM0L = 220, // XMM sub-registers (WNI integer) + CV_AMD64_EMM1L = 221, + CV_AMD64_EMM2L = 222, + CV_AMD64_EMM3L = 223, + CV_AMD64_EMM4L = 224, + CV_AMD64_EMM5L = 225, + CV_AMD64_EMM6L = 226, + CV_AMD64_EMM7L = 227, + + CV_AMD64_EMM0H = 228, + CV_AMD64_EMM1H = 229, + CV_AMD64_EMM2H = 230, + CV_AMD64_EMM3H = 231, + CV_AMD64_EMM4H = 232, + CV_AMD64_EMM5H = 233, + CV_AMD64_EMM6H = 234, + CV_AMD64_EMM7H = 235, + + // do not change the order of these regs, first one must be even too + CV_AMD64_MM00 = 236, + CV_AMD64_MM01 = 237, + CV_AMD64_MM10 = 238, + CV_AMD64_MM11 = 239, + CV_AMD64_MM20 = 240, + CV_AMD64_MM21 = 241, + CV_AMD64_MM30 = 242, + CV_AMD64_MM31 = 243, + CV_AMD64_MM40 = 244, + CV_AMD64_MM41 = 245, + CV_AMD64_MM50 = 246, + CV_AMD64_MM51 = 247, + CV_AMD64_MM60 = 248, + CV_AMD64_MM61 = 249, + CV_AMD64_MM70 = 250, + CV_AMD64_MM71 = 251, + + // Extended KATMAI registers + CV_AMD64_XMM8 = 252, // KATMAI registers + CV_AMD64_XMM9 = 253, + CV_AMD64_XMM10 = 254, + CV_AMD64_XMM11 = 255, + CV_AMD64_XMM12 = 256, + CV_AMD64_XMM13 = 257, + CV_AMD64_XMM14 = 258, + CV_AMD64_XMM15 = 259, + + CV_AMD64_XMM8_0 = 260, // KATMAI sub-registers + CV_AMD64_XMM8_1 = 261, + CV_AMD64_XMM8_2 = 262, + CV_AMD64_XMM8_3 = 263, + CV_AMD64_XMM9_0 = 264, + CV_AMD64_XMM9_1 = 265, + CV_AMD64_XMM9_2 = 266, + CV_AMD64_XMM9_3 = 267, + CV_AMD64_XMM10_0 = 268, + CV_AMD64_XMM10_1 = 269, + CV_AMD64_XMM10_2 = 270, + CV_AMD64_XMM10_3 = 271, + CV_AMD64_XMM11_0 = 272, + CV_AMD64_XMM11_1 = 273, + CV_AMD64_XMM11_2 = 274, + CV_AMD64_XMM11_3 = 275, + CV_AMD64_XMM12_0 = 276, + CV_AMD64_XMM12_1 = 277, + CV_AMD64_XMM12_2 = 278, + CV_AMD64_XMM12_3 = 279, + CV_AMD64_XMM13_0 = 280, + CV_AMD64_XMM13_1 = 281, + CV_AMD64_XMM13_2 = 282, + CV_AMD64_XMM13_3 = 283, + CV_AMD64_XMM14_0 = 284, + CV_AMD64_XMM14_1 = 285, + CV_AMD64_XMM14_2 = 286, + CV_AMD64_XMM14_3 = 287, + CV_AMD64_XMM15_0 = 288, + CV_AMD64_XMM15_1 = 289, + CV_AMD64_XMM15_2 = 290, + CV_AMD64_XMM15_3 = 291, + + CV_AMD64_XMM8L = 292, + CV_AMD64_XMM9L = 293, + CV_AMD64_XMM10L = 294, + CV_AMD64_XMM11L = 295, + CV_AMD64_XMM12L = 296, + CV_AMD64_XMM13L = 297, + CV_AMD64_XMM14L = 298, + CV_AMD64_XMM15L = 299, + + CV_AMD64_XMM8H = 300, + CV_AMD64_XMM9H = 301, + CV_AMD64_XMM10H = 302, + CV_AMD64_XMM11H = 303, + CV_AMD64_XMM12H = 304, + CV_AMD64_XMM13H = 305, + CV_AMD64_XMM14H = 306, + CV_AMD64_XMM15H = 307, + + CV_AMD64_EMM8L = 308, // XMM sub-registers (WNI integer) + CV_AMD64_EMM9L = 309, + CV_AMD64_EMM10L = 310, + CV_AMD64_EMM11L = 311, + CV_AMD64_EMM12L = 312, + CV_AMD64_EMM13L = 313, + CV_AMD64_EMM14L = 314, + CV_AMD64_EMM15L = 315, + + CV_AMD64_EMM8H = 316, + CV_AMD64_EMM9H = 317, + CV_AMD64_EMM10H = 318, + CV_AMD64_EMM11H = 319, + CV_AMD64_EMM12H = 320, + CV_AMD64_EMM13H = 321, + CV_AMD64_EMM14H = 322, + CV_AMD64_EMM15H = 323, + + // Low byte forms of some standard registers + CV_AMD64_SIL = 324, + CV_AMD64_DIL = 325, + CV_AMD64_BPL = 326, + CV_AMD64_SPL = 327, + + // 64-bit regular registers + CV_AMD64_RAX = 328, + CV_AMD64_RBX = 329, + CV_AMD64_RCX = 330, + CV_AMD64_RDX = 331, + CV_AMD64_RSI = 332, + CV_AMD64_RDI = 333, + CV_AMD64_RBP = 334, + CV_AMD64_RSP = 335, + + // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) + CV_AMD64_R8 = 336, + CV_AMD64_R9 = 337, + CV_AMD64_R10 = 338, + CV_AMD64_R11 = 339, + CV_AMD64_R12 = 340, + CV_AMD64_R13 = 341, + CV_AMD64_R14 = 342, + CV_AMD64_R15 = 343, + + CV_AMD64_R8B = 344, + CV_AMD64_R9B = 345, + CV_AMD64_R10B = 346, + CV_AMD64_R11B = 347, + CV_AMD64_R12B = 348, + CV_AMD64_R13B = 349, + CV_AMD64_R14B = 350, + CV_AMD64_R15B = 351, + + CV_AMD64_R8W = 352, + CV_AMD64_R9W = 353, + CV_AMD64_R10W = 354, + CV_AMD64_R11W = 355, + CV_AMD64_R12W = 356, + CV_AMD64_R13W = 357, + CV_AMD64_R14W = 358, + CV_AMD64_R15W = 359, + + CV_AMD64_R8D = 360, + CV_AMD64_R9D = 361, + CV_AMD64_R10D = 362, + CV_AMD64_R11D = 363, + CV_AMD64_R12D = 364, + CV_AMD64_R13D = 365, + CV_AMD64_R14D = 366, + CV_AMD64_R15D = 367, + + // AVX registers 256 bits + CV_AMD64_YMM0 = 368, + CV_AMD64_YMM1 = 369, + CV_AMD64_YMM2 = 370, + CV_AMD64_YMM3 = 371, + CV_AMD64_YMM4 = 372, + CV_AMD64_YMM5 = 373, + CV_AMD64_YMM6 = 374, + CV_AMD64_YMM7 = 375, + CV_AMD64_YMM8 = 376, + CV_AMD64_YMM9 = 377, + CV_AMD64_YMM10 = 378, + CV_AMD64_YMM11 = 379, + CV_AMD64_YMM12 = 380, + CV_AMD64_YMM13 = 381, + CV_AMD64_YMM14 = 382, + CV_AMD64_YMM15 = 383, + + // AVX registers upper 128 bits + CV_AMD64_YMM0H = 384, + CV_AMD64_YMM1H = 385, + CV_AMD64_YMM2H = 386, + CV_AMD64_YMM3H = 387, + CV_AMD64_YMM4H = 388, + CV_AMD64_YMM5H = 389, + CV_AMD64_YMM6H = 390, + CV_AMD64_YMM7H = 391, + CV_AMD64_YMM8H = 392, + CV_AMD64_YMM9H = 393, + CV_AMD64_YMM10H = 394, + CV_AMD64_YMM11H = 395, + CV_AMD64_YMM12H = 396, + CV_AMD64_YMM13H = 397, + CV_AMD64_YMM14H = 398, + CV_AMD64_YMM15H = 399, + + //Lower/upper 8 bytes of XMM registers. Unlike CV_AMD64_XMM, these + //values reprsesent the bit patterns of the registers as 64-bit integers, not + //the representation of these registers as a double. + CV_AMD64_XMM0IL = 400, + CV_AMD64_XMM1IL = 401, + CV_AMD64_XMM2IL = 402, + CV_AMD64_XMM3IL = 403, + CV_AMD64_XMM4IL = 404, + CV_AMD64_XMM5IL = 405, + CV_AMD64_XMM6IL = 406, + CV_AMD64_XMM7IL = 407, + CV_AMD64_XMM8IL = 408, + CV_AMD64_XMM9IL = 409, + CV_AMD64_XMM10IL = 410, + CV_AMD64_XMM11IL = 411, + CV_AMD64_XMM12IL = 412, + CV_AMD64_XMM13IL = 413, + CV_AMD64_XMM14IL = 414, + CV_AMD64_XMM15IL = 415, + + CV_AMD64_XMM0IH = 416, + CV_AMD64_XMM1IH = 417, + CV_AMD64_XMM2IH = 418, + CV_AMD64_XMM3IH = 419, + CV_AMD64_XMM4IH = 420, + CV_AMD64_XMM5IH = 421, + CV_AMD64_XMM6IH = 422, + CV_AMD64_XMM7IH = 423, + CV_AMD64_XMM8IH = 424, + CV_AMD64_XMM9IH = 425, + CV_AMD64_XMM10IH = 426, + CV_AMD64_XMM11IH = 427, + CV_AMD64_XMM12IH = 428, + CV_AMD64_XMM13IH = 429, + CV_AMD64_XMM14IH = 430, + CV_AMD64_XMM15IH = 431, + + CV_AMD64_YMM0I0 = 432, // AVX integer registers + CV_AMD64_YMM0I1 = 433, + CV_AMD64_YMM0I2 = 434, + CV_AMD64_YMM0I3 = 435, + CV_AMD64_YMM1I0 = 436, + CV_AMD64_YMM1I1 = 437, + CV_AMD64_YMM1I2 = 438, + CV_AMD64_YMM1I3 = 439, + CV_AMD64_YMM2I0 = 440, + CV_AMD64_YMM2I1 = 441, + CV_AMD64_YMM2I2 = 442, + CV_AMD64_YMM2I3 = 443, + CV_AMD64_YMM3I0 = 444, + CV_AMD64_YMM3I1 = 445, + CV_AMD64_YMM3I2 = 446, + CV_AMD64_YMM3I3 = 447, + CV_AMD64_YMM4I0 = 448, + CV_AMD64_YMM4I1 = 449, + CV_AMD64_YMM4I2 = 450, + CV_AMD64_YMM4I3 = 451, + CV_AMD64_YMM5I0 = 452, + CV_AMD64_YMM5I1 = 453, + CV_AMD64_YMM5I2 = 454, + CV_AMD64_YMM5I3 = 455, + CV_AMD64_YMM6I0 = 456, + CV_AMD64_YMM6I1 = 457, + CV_AMD64_YMM6I2 = 458, + CV_AMD64_YMM6I3 = 459, + CV_AMD64_YMM7I0 = 460, + CV_AMD64_YMM7I1 = 461, + CV_AMD64_YMM7I2 = 462, + CV_AMD64_YMM7I3 = 463, + CV_AMD64_YMM8I0 = 464, + CV_AMD64_YMM8I1 = 465, + CV_AMD64_YMM8I2 = 466, + CV_AMD64_YMM8I3 = 467, + CV_AMD64_YMM9I0 = 468, + CV_AMD64_YMM9I1 = 469, + CV_AMD64_YMM9I2 = 470, + CV_AMD64_YMM9I3 = 471, + CV_AMD64_YMM10I0 = 472, + CV_AMD64_YMM10I1 = 473, + CV_AMD64_YMM10I2 = 474, + CV_AMD64_YMM10I3 = 475, + CV_AMD64_YMM11I0 = 476, + CV_AMD64_YMM11I1 = 477, + CV_AMD64_YMM11I2 = 478, + CV_AMD64_YMM11I3 = 479, + CV_AMD64_YMM12I0 = 480, + CV_AMD64_YMM12I1 = 481, + CV_AMD64_YMM12I2 = 482, + CV_AMD64_YMM12I3 = 483, + CV_AMD64_YMM13I0 = 484, + CV_AMD64_YMM13I1 = 485, + CV_AMD64_YMM13I2 = 486, + CV_AMD64_YMM13I3 = 487, + CV_AMD64_YMM14I0 = 488, + CV_AMD64_YMM14I1 = 489, + CV_AMD64_YMM14I2 = 490, + CV_AMD64_YMM14I3 = 491, + CV_AMD64_YMM15I0 = 492, + CV_AMD64_YMM15I1 = 493, + CV_AMD64_YMM15I2 = 494, + CV_AMD64_YMM15I3 = 495, + + CV_AMD64_YMM0F0 = 496, // AVX floating-point single precise registers + CV_AMD64_YMM0F1 = 497, + CV_AMD64_YMM0F2 = 498, + CV_AMD64_YMM0F3 = 499, + CV_AMD64_YMM0F4 = 500, + CV_AMD64_YMM0F5 = 501, + CV_AMD64_YMM0F6 = 502, + CV_AMD64_YMM0F7 = 503, + CV_AMD64_YMM1F0 = 504, + CV_AMD64_YMM1F1 = 505, + CV_AMD64_YMM1F2 = 506, + CV_AMD64_YMM1F3 = 507, + CV_AMD64_YMM1F4 = 508, + CV_AMD64_YMM1F5 = 509, + CV_AMD64_YMM1F6 = 510, + CV_AMD64_YMM1F7 = 511, + CV_AMD64_YMM2F0 = 512, + CV_AMD64_YMM2F1 = 513, + CV_AMD64_YMM2F2 = 514, + CV_AMD64_YMM2F3 = 515, + CV_AMD64_YMM2F4 = 516, + CV_AMD64_YMM2F5 = 517, + CV_AMD64_YMM2F6 = 518, + CV_AMD64_YMM2F7 = 519, + CV_AMD64_YMM3F0 = 520, + CV_AMD64_YMM3F1 = 521, + CV_AMD64_YMM3F2 = 522, + CV_AMD64_YMM3F3 = 523, + CV_AMD64_YMM3F4 = 524, + CV_AMD64_YMM3F5 = 525, + CV_AMD64_YMM3F6 = 526, + CV_AMD64_YMM3F7 = 527, + CV_AMD64_YMM4F0 = 528, + CV_AMD64_YMM4F1 = 529, + CV_AMD64_YMM4F2 = 530, + CV_AMD64_YMM4F3 = 531, + CV_AMD64_YMM4F4 = 532, + CV_AMD64_YMM4F5 = 533, + CV_AMD64_YMM4F6 = 534, + CV_AMD64_YMM4F7 = 535, + CV_AMD64_YMM5F0 = 536, + CV_AMD64_YMM5F1 = 537, + CV_AMD64_YMM5F2 = 538, + CV_AMD64_YMM5F3 = 539, + CV_AMD64_YMM5F4 = 540, + CV_AMD64_YMM5F5 = 541, + CV_AMD64_YMM5F6 = 542, + CV_AMD64_YMM5F7 = 543, + CV_AMD64_YMM6F0 = 544, + CV_AMD64_YMM6F1 = 545, + CV_AMD64_YMM6F2 = 546, + CV_AMD64_YMM6F3 = 547, + CV_AMD64_YMM6F4 = 548, + CV_AMD64_YMM6F5 = 549, + CV_AMD64_YMM6F6 = 550, + CV_AMD64_YMM6F7 = 551, + CV_AMD64_YMM7F0 = 552, + CV_AMD64_YMM7F1 = 553, + CV_AMD64_YMM7F2 = 554, + CV_AMD64_YMM7F3 = 555, + CV_AMD64_YMM7F4 = 556, + CV_AMD64_YMM7F5 = 557, + CV_AMD64_YMM7F6 = 558, + CV_AMD64_YMM7F7 = 559, + CV_AMD64_YMM8F0 = 560, + CV_AMD64_YMM8F1 = 561, + CV_AMD64_YMM8F2 = 562, + CV_AMD64_YMM8F3 = 563, + CV_AMD64_YMM8F4 = 564, + CV_AMD64_YMM8F5 = 565, + CV_AMD64_YMM8F6 = 566, + CV_AMD64_YMM8F7 = 567, + CV_AMD64_YMM9F0 = 568, + CV_AMD64_YMM9F1 = 569, + CV_AMD64_YMM9F2 = 570, + CV_AMD64_YMM9F3 = 571, + CV_AMD64_YMM9F4 = 572, + CV_AMD64_YMM9F5 = 573, + CV_AMD64_YMM9F6 = 574, + CV_AMD64_YMM9F7 = 575, + CV_AMD64_YMM10F0 = 576, + CV_AMD64_YMM10F1 = 577, + CV_AMD64_YMM10F2 = 578, + CV_AMD64_YMM10F3 = 579, + CV_AMD64_YMM10F4 = 580, + CV_AMD64_YMM10F5 = 581, + CV_AMD64_YMM10F6 = 582, + CV_AMD64_YMM10F7 = 583, + CV_AMD64_YMM11F0 = 584, + CV_AMD64_YMM11F1 = 585, + CV_AMD64_YMM11F2 = 586, + CV_AMD64_YMM11F3 = 587, + CV_AMD64_YMM11F4 = 588, + CV_AMD64_YMM11F5 = 589, + CV_AMD64_YMM11F6 = 590, + CV_AMD64_YMM11F7 = 591, + CV_AMD64_YMM12F0 = 592, + CV_AMD64_YMM12F1 = 593, + CV_AMD64_YMM12F2 = 594, + CV_AMD64_YMM12F3 = 595, + CV_AMD64_YMM12F4 = 596, + CV_AMD64_YMM12F5 = 597, + CV_AMD64_YMM12F6 = 598, + CV_AMD64_YMM12F7 = 599, + CV_AMD64_YMM13F0 = 600, + CV_AMD64_YMM13F1 = 601, + CV_AMD64_YMM13F2 = 602, + CV_AMD64_YMM13F3 = 603, + CV_AMD64_YMM13F4 = 604, + CV_AMD64_YMM13F5 = 605, + CV_AMD64_YMM13F6 = 606, + CV_AMD64_YMM13F7 = 607, + CV_AMD64_YMM14F0 = 608, + CV_AMD64_YMM14F1 = 609, + CV_AMD64_YMM14F2 = 610, + CV_AMD64_YMM14F3 = 611, + CV_AMD64_YMM14F4 = 612, + CV_AMD64_YMM14F5 = 613, + CV_AMD64_YMM14F6 = 614, + CV_AMD64_YMM14F7 = 615, + CV_AMD64_YMM15F0 = 616, + CV_AMD64_YMM15F1 = 617, + CV_AMD64_YMM15F2 = 618, + CV_AMD64_YMM15F3 = 619, + CV_AMD64_YMM15F4 = 620, + CV_AMD64_YMM15F5 = 621, + CV_AMD64_YMM15F6 = 622, + CV_AMD64_YMM15F7 = 623, + + CV_AMD64_YMM0D0 = 624, // AVX floating-point double precise registers + CV_AMD64_YMM0D1 = 625, + CV_AMD64_YMM0D2 = 626, + CV_AMD64_YMM0D3 = 627, + CV_AMD64_YMM1D0 = 628, + CV_AMD64_YMM1D1 = 629, + CV_AMD64_YMM1D2 = 630, + CV_AMD64_YMM1D3 = 631, + CV_AMD64_YMM2D0 = 632, + CV_AMD64_YMM2D1 = 633, + CV_AMD64_YMM2D2 = 634, + CV_AMD64_YMM2D3 = 635, + CV_AMD64_YMM3D0 = 636, + CV_AMD64_YMM3D1 = 637, + CV_AMD64_YMM3D2 = 638, + CV_AMD64_YMM3D3 = 639, + CV_AMD64_YMM4D0 = 640, + CV_AMD64_YMM4D1 = 641, + CV_AMD64_YMM4D2 = 642, + CV_AMD64_YMM4D3 = 643, + CV_AMD64_YMM5D0 = 644, + CV_AMD64_YMM5D1 = 645, + CV_AMD64_YMM5D2 = 646, + CV_AMD64_YMM5D3 = 647, + CV_AMD64_YMM6D0 = 648, + CV_AMD64_YMM6D1 = 649, + CV_AMD64_YMM6D2 = 650, + CV_AMD64_YMM6D3 = 651, + CV_AMD64_YMM7D0 = 652, + CV_AMD64_YMM7D1 = 653, + CV_AMD64_YMM7D2 = 654, + CV_AMD64_YMM7D3 = 655, + CV_AMD64_YMM8D0 = 656, + CV_AMD64_YMM8D1 = 657, + CV_AMD64_YMM8D2 = 658, + CV_AMD64_YMM8D3 = 659, + CV_AMD64_YMM9D0 = 660, + CV_AMD64_YMM9D1 = 661, + CV_AMD64_YMM9D2 = 662, + CV_AMD64_YMM9D3 = 663, + CV_AMD64_YMM10D0 = 664, + CV_AMD64_YMM10D1 = 665, + CV_AMD64_YMM10D2 = 666, + CV_AMD64_YMM10D3 = 667, + CV_AMD64_YMM11D0 = 668, + CV_AMD64_YMM11D1 = 669, + CV_AMD64_YMM11D2 = 670, + CV_AMD64_YMM11D3 = 671, + CV_AMD64_YMM12D0 = 672, + CV_AMD64_YMM12D1 = 673, + CV_AMD64_YMM12D2 = 674, + CV_AMD64_YMM12D3 = 675, + CV_AMD64_YMM13D0 = 676, + CV_AMD64_YMM13D1 = 677, + CV_AMD64_YMM13D2 = 678, + CV_AMD64_YMM13D3 = 679, + CV_AMD64_YMM14D0 = 680, + CV_AMD64_YMM14D1 = 681, + CV_AMD64_YMM14D2 = 682, + CV_AMD64_YMM14D3 = 683, + CV_AMD64_YMM15D0 = 684, + CV_AMD64_YMM15D1 = 685, + CV_AMD64_YMM15D2 = 686, + CV_AMD64_YMM15D3 = 687 + + + // Note: Next set of platform registers need to go into a new enum... + // this one is above 44K now. + +} CV_HREG_e; + +typedef enum CV_HLSLREG_e { + CV_HLSLREG_TEMP = 0, + CV_HLSLREG_INPUT = 1, + CV_HLSLREG_OUTPUT = 2, + CV_HLSLREG_INDEXABLE_TEMP = 3, + CV_HLSLREG_IMMEDIATE32 = 4, + CV_HLSLREG_IMMEDIATE64 = 5, + CV_HLSLREG_SAMPLER = 6, + CV_HLSLREG_RESOURCE = 7, + CV_HLSLREG_CONSTANT_BUFFER = 8, + CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, + CV_HLSLREG_LABEL = 10, + CV_HLSLREG_INPUT_PRIMITIVEID = 11, + CV_HLSLREG_OUTPUT_DEPTH = 12, + CV_HLSLREG_NULL = 13, + CV_HLSLREG_RASTERIZER = 14, + CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, + CV_HLSLREG_STREAM = 16, + CV_HLSLREG_FUNCTION_BODY = 17, + CV_HLSLREG_FUNCTION_TABLE = 18, + CV_HLSLREG_INTERFACE = 19, + CV_HLSLREG_FUNCTION_INPUT = 20, + CV_HLSLREG_FUNCTION_OUTPUT = 21, + CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, + CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, + CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, + CV_HLSLREG_INPUT_CONTROL_POINT = 25, + CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, + CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, + CV_HLSLREG_INPUT_DOMAIN_POINT = 28, + CV_HLSLREG_THIS_POINTER = 29, + CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, + CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, + CV_HLSLREG_INPUT_THREAD_ID = 32, + CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, + CV_HLSLREG_INPUT_COVERAGE_MASK = 35, + CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, + CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, + CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, + CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, + CV_HLSLREG_CYCLE_COUNTER = 40, +} CV_HLSLREG_e; + +enum StackFrameTypeEnum +{ + FrameTypeFPO, // Frame pointer omitted, FPO info available + FrameTypeTrap, // Kernel Trap frame + FrameTypeTSS, // Kernel Trap frame + FrameTypeStandard, // Standard EBP stackframe + FrameTypeFrameData, // Frame pointer omitted, FrameData info available + + FrameTypeUnknown = -1, // Frame which does not have any debug info +}; + +enum MemoryTypeEnum +{ + MemTypeCode, // Read only code memory + MemTypeData, // Read only data/stack memory + MemTypeStack, // Read only stack memory + MemTypeCodeOnHeap, // Read only memory for code generated on heap by runtime + + MemTypeAny = -1, +}; + +typedef enum CV_HLSLMemorySpace_e +{ + // HLSL specific memory spaces + + CV_HLSL_MEMSPACE_DATA = 0x00, + CV_HLSL_MEMSPACE_SAMPLER = 0x01, + CV_HLSL_MEMSPACE_RESOURCE = 0x02, + CV_HLSL_MEMSPACE_RWRESOURCE = 0x03, + + CV_HLSL_MEMSPACE_MAX = 0x0F, +} CV_HLSLMemorySpace_e; + +#endif diff --git a/lib/coreclr/src/inc/cvinfo.h b/lib/coreclr/src/inc/cvinfo.h new file mode 100644 index 0000000000..c2e42e5d72 --- /dev/null +++ b/lib/coreclr/src/inc/cvinfo.h @@ -0,0 +1,4989 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*** cvinfo.h - Generic CodeView information definitions + * + * Structures, constants, etc. for accessing and interpreting + * CodeView information. + * + */ + + +/*** The master copy of this file resides in the langapi project. + * All Microsoft projects are required to use the master copy without + * modification. Modification of the master version or a copy + * without consultation with all parties concerned is extremely + * risky. + * + */ + +#pragma once + +#include "cvconst.h" + +#ifndef _CV_INFO_INCLUDED +#define _CV_INFO_INCLUDED + +#ifdef __cplusplus +#pragma warning ( disable: 4200 ) +#endif + +#ifndef __INLINE +#ifdef __cplusplus +#define __INLINE inline +#else +#define __INLINE __inline +#endif +#endif + +#pragma pack ( push, 1 ) +typedef unsigned long CV_uoff32_t; +typedef long CV_off32_t; +typedef unsigned short CV_uoff16_t; +typedef short CV_off16_t; +typedef unsigned short CV_typ16_t; +typedef unsigned long CV_typ_t; +typedef unsigned long CV_pubsymflag_t; // must be same as CV_typ_t. +typedef unsigned short _2BYTEPAD; +typedef unsigned long CV_tkn_t; + +#if !defined (CV_ZEROLEN) +#define CV_ZEROLEN +#endif + +#if !defined (FLOAT10) +#if defined(_M_I86) // 16 bit x86 supporting long double +typedef long double FLOAT10; +#else // 32 bit w/o long double support +typedef struct FLOAT10 +{ + char b[10]; +} FLOAT10; +#endif +#endif + + +#define CV_SIGNATURE_C6 0L // Actual signature is >64K +#define CV_SIGNATURE_C7 1L // First explicit signature +#define CV_SIGNATURE_C11 2L // C11 (vc5.x) 32-bit types +#define CV_SIGNATURE_C13 4L // C13 (vc7.x) zero terminated names +#define CV_SIGNATURE_RESERVED 5L // All signatures from 5 to 64K are reserved + +#define CV_MAXOFFSET 0xffffffff + +#ifndef GUID_DEFINED +#define GUID_DEFINED + +typedef struct _GUID { // size is 16 + unsigned long Data1; + unsigned short Data2; + unsigned short Data3; + unsigned char Data4[8]; +} GUID; + +#endif // !GUID_DEFINED + +typedef GUID SIG70; // new to 7.0 are 16-byte guid-like signatures +typedef SIG70 * PSIG70; +typedef const SIG70 * PCSIG70; + + + +/** CodeView Symbol and Type OMF type information is broken up into two + * ranges. Type indices less than 0x1000 describe type information + * that is frequently used. Type indices above 0x1000 are used to + * describe more complex features such as functions, arrays and + * structures. + */ + + + + +/** Primitive types have predefined meaning that is encoded in the + * values of the various bit fields in the value. + * + * A CodeView primitive type is defined as: + * + * 1 1 + * 1 089 7654 3 210 + * r mode type r sub + * + * Where + * mode is the pointer mode + * type is a type indicator + * sub is a subtype enumeration + * r is a reserved field + * + * See Microsoft Symbol and Type OMF (Version 4.0) for more + * information. + */ + + +#define CV_MMASK 0x700 // mode mask +#define CV_TMASK 0x0f0 // type mask + +// can we use the reserved bit ?? +#define CV_SMASK 0x00f // subtype mask + +#define CV_MSHIFT 8 // primitive mode right shift count +#define CV_TSHIFT 4 // primitive type right shift count +#define CV_SSHIFT 0 // primitive subtype right shift count + +// macros to extract primitive mode, type and size + +#define CV_MODE(typ) (((typ) & CV_MMASK) >> CV_MSHIFT) +#define CV_TYPE(typ) (((typ) & CV_TMASK) >> CV_TSHIFT) +#define CV_SUBT(typ) (((typ) & CV_SMASK) >> CV_SSHIFT) + +// macros to insert new primitive mode, type and size + +#define CV_NEWMODE(typ, nm) ((CV_typ_t)(((typ) & ~CV_MMASK) | ((nm) << CV_MSHIFT))) +#define CV_NEWTYPE(typ, nt) (((typ) & ~CV_TMASK) | ((nt) << CV_TSHIFT)) +#define CV_NEWSUBT(typ, ns) (((typ) & ~CV_SMASK) | ((ns) << CV_SSHIFT)) + + + +// pointer mode enumeration values + +typedef enum CV_prmode_e { + CV_TM_DIRECT = 0, // mode is not a pointer + CV_TM_NPTR = 1, // mode is a near pointer + CV_TM_FPTR = 2, // mode is a far pointer + CV_TM_HPTR = 3, // mode is a huge pointer + CV_TM_NPTR32 = 4, // mode is a 32 bit near pointer + CV_TM_FPTR32 = 5, // mode is a 32 bit far pointer + CV_TM_NPTR64 = 6, // mode is a 64 bit near pointer + CV_TM_NPTR128 = 7, // mode is a 128 bit near pointer +} CV_prmode_e; + + + + +// type enumeration values + + +typedef enum CV_type_e { + CV_SPECIAL = 0x00, // special type size values + CV_SIGNED = 0x01, // signed integral size values + CV_UNSIGNED = 0x02, // unsigned integral size values + CV_BOOLEAN = 0x03, // Boolean size values + CV_REAL = 0x04, // real number size values + CV_COMPLEX = 0x05, // complex number size values + CV_SPECIAL2 = 0x06, // second set of special types + CV_INT = 0x07, // integral (int) values + CV_CVRESERVED = 0x0f, +} CV_type_e; + + + + +// subtype enumeration values for CV_SPECIAL + + +typedef enum CV_special_e { + CV_SP_NOTYPE = 0x00, + CV_SP_ABS = 0x01, + CV_SP_SEGMENT = 0x02, + CV_SP_VOID = 0x03, + CV_SP_CURRENCY = 0x04, + CV_SP_NBASICSTR = 0x05, + CV_SP_FBASICSTR = 0x06, + CV_SP_NOTTRANS = 0x07, + CV_SP_HRESULT = 0x08, +} CV_special_e; + + + + +// subtype enumeration values for CV_SPECIAL2 + + +typedef enum CV_special2_e { + CV_S2_BIT = 0x00, + CV_S2_PASCHAR = 0x01, // Pascal CHAR + CV_S2_BOOL32FF = 0x02, // 32-bit BOOL where true is 0xffffffff +} CV_special2_e; + + + + + +// subtype enumeration values for CV_SIGNED, CV_UNSIGNED and CV_BOOLEAN + + +typedef enum CV_integral_e { + CV_IN_1BYTE = 0x00, + CV_IN_2BYTE = 0x01, + CV_IN_4BYTE = 0x02, + CV_IN_8BYTE = 0x03, + CV_IN_16BYTE = 0x04 +} CV_integral_e; + + + + + +// subtype enumeration values for CV_REAL and CV_COMPLEX + + +typedef enum CV_real_e { + CV_RC_REAL32 = 0x00, + CV_RC_REAL64 = 0x01, + CV_RC_REAL80 = 0x02, + CV_RC_REAL128 = 0x03, + CV_RC_REAL48 = 0x04, + CV_RC_REAL32PP = 0x05, // 32-bit partial precision real + CV_RC_REAL16 = 0x06, +} CV_real_e; + + + + +// subtype enumeration values for CV_INT (really int) + + +typedef enum CV_int_e { + CV_RI_CHAR = 0x00, + CV_RI_INT1 = 0x00, + CV_RI_WCHAR = 0x01, + CV_RI_UINT1 = 0x01, + CV_RI_INT2 = 0x02, + CV_RI_UINT2 = 0x03, + CV_RI_INT4 = 0x04, + CV_RI_UINT4 = 0x05, + CV_RI_INT8 = 0x06, + CV_RI_UINT8 = 0x07, + CV_RI_INT16 = 0x08, + CV_RI_UINT16 = 0x09, + CV_RI_CHAR16 = 0x0a, // char16_t + CV_RI_CHAR32 = 0x0b, // char32_t +} CV_int_e; + + + +// macros to check the type of a primitive + +#define CV_TYP_IS_DIRECT(typ) (CV_MODE(typ) == CV_TM_DIRECT) +#define CV_TYP_IS_PTR(typ) (CV_MODE(typ) != CV_TM_DIRECT) +#define CV_TYP_IS_NPTR(typ) (CV_MODE(typ) == CV_TM_NPTR) +#define CV_TYP_IS_FPTR(typ) (CV_MODE(typ) == CV_TM_FPTR) +#define CV_TYP_IS_HPTR(typ) (CV_MODE(typ) == CV_TM_HPTR) +#define CV_TYP_IS_NPTR32(typ) (CV_MODE(typ) == CV_TM_NPTR32) +#define CV_TYP_IS_FPTR32(typ) (CV_MODE(typ) == CV_TM_FPTR32) + +#define CV_TYP_IS_SIGNED(typ) (((CV_TYPE(typ) == CV_SIGNED) && CV_TYP_IS_DIRECT(typ)) || \ + (typ == T_INT1) || \ + (typ == T_INT2) || \ + (typ == T_INT4) || \ + (typ == T_INT8) || \ + (typ == T_INT16) || \ + (typ == T_RCHAR)) + +#define CV_TYP_IS_UNSIGNED(typ) (((CV_TYPE(typ) == CV_UNSIGNED) && CV_TYP_IS_DIRECT(typ)) || \ + (typ == T_UINT1) || \ + (typ == T_UINT2) || \ + (typ == T_UINT4) || \ + (typ == T_UINT8) || \ + (typ == T_UINT16)) + +#define CV_TYP_IS_REAL(typ) ((CV_TYPE(typ) == CV_REAL) && CV_TYP_IS_DIRECT(typ)) + +#define CV_FIRST_NONPRIM 0x1000 +#define CV_IS_PRIMITIVE(typ) ((typ) < CV_FIRST_NONPRIM) +#define CV_TYP_IS_COMPLEX(typ) ((CV_TYPE(typ) == CV_COMPLEX) && CV_TYP_IS_DIRECT(typ)) +#define CV_IS_INTERNAL_PTR(typ) (CV_IS_PRIMITIVE(typ) && \ + CV_TYPE(typ) == CV_CVRESERVED && \ + CV_TYP_IS_PTR(typ)) + + + + + + +// selected values for type_index - for a more complete definition, see +// Microsoft Symbol and Type OMF document + + + + +// Special Types + +typedef enum TYPE_ENUM_e { +// Special Types + + T_NOTYPE = 0x0000, // uncharacterized type (no type) + T_ABS = 0x0001, // absolute symbol + T_SEGMENT = 0x0002, // segment type + T_VOID = 0x0003, // void + T_HRESULT = 0x0008, // OLE/COM HRESULT + T_32PHRESULT = 0x0408, // OLE/COM HRESULT __ptr32 * + T_64PHRESULT = 0x0608, // OLE/COM HRESULT __ptr64 * + + T_PVOID = 0x0103, // near pointer to void + T_PFVOID = 0x0203, // far pointer to void + T_PHVOID = 0x0303, // huge pointer to void + T_32PVOID = 0x0403, // 32 bit pointer to void + T_32PFVOID = 0x0503, // 16:32 pointer to void + T_64PVOID = 0x0603, // 64 bit pointer to void + T_CURRENCY = 0x0004, // BASIC 8 byte currency value + T_NBASICSTR = 0x0005, // Near BASIC string + T_FBASICSTR = 0x0006, // Far BASIC string + T_NOTTRANS = 0x0007, // type not translated by cvpack + T_BIT = 0x0060, // bit + T_PASCHAR = 0x0061, // Pascal CHAR + T_BOOL32FF = 0x0062, // 32-bit BOOL where true is 0xffffffff + + +// Character types + + T_CHAR = 0x0010, // 8 bit signed + T_PCHAR = 0x0110, // 16 bit pointer to 8 bit signed + T_PFCHAR = 0x0210, // 16:16 far pointer to 8 bit signed + T_PHCHAR = 0x0310, // 16:16 huge pointer to 8 bit signed + T_32PCHAR = 0x0410, // 32 bit pointer to 8 bit signed + T_32PFCHAR = 0x0510, // 16:32 pointer to 8 bit signed + T_64PCHAR = 0x0610, // 64 bit pointer to 8 bit signed + + T_UCHAR = 0x0020, // 8 bit unsigned + T_PUCHAR = 0x0120, // 16 bit pointer to 8 bit unsigned + T_PFUCHAR = 0x0220, // 16:16 far pointer to 8 bit unsigned + T_PHUCHAR = 0x0320, // 16:16 huge pointer to 8 bit unsigned + T_32PUCHAR = 0x0420, // 32 bit pointer to 8 bit unsigned + T_32PFUCHAR = 0x0520, // 16:32 pointer to 8 bit unsigned + T_64PUCHAR = 0x0620, // 64 bit pointer to 8 bit unsigned + + +// really a character types + + T_RCHAR = 0x0070, // really a char + T_PRCHAR = 0x0170, // 16 bit pointer to a real char + T_PFRCHAR = 0x0270, // 16:16 far pointer to a real char + T_PHRCHAR = 0x0370, // 16:16 huge pointer to a real char + T_32PRCHAR = 0x0470, // 32 bit pointer to a real char + T_32PFRCHAR = 0x0570, // 16:32 pointer to a real char + T_64PRCHAR = 0x0670, // 64 bit pointer to a real char + + +// really a wide character types + + T_WCHAR = 0x0071, // wide char + T_PWCHAR = 0x0171, // 16 bit pointer to a wide char + T_PFWCHAR = 0x0271, // 16:16 far pointer to a wide char + T_PHWCHAR = 0x0371, // 16:16 huge pointer to a wide char + T_32PWCHAR = 0x0471, // 32 bit pointer to a wide char + T_32PFWCHAR = 0x0571, // 16:32 pointer to a wide char + T_64PWCHAR = 0x0671, // 64 bit pointer to a wide char + +// really a 16-bit unicode char + + T_CHAR16 = 0x007a, // 16-bit unicode char + T_PCHAR16 = 0x017a, // 16 bit pointer to a 16-bit unicode char + T_PFCHAR16 = 0x027a, // 16:16 far pointer to a 16-bit unicode char + T_PHCHAR16 = 0x037a, // 16:16 huge pointer to a 16-bit unicode char + T_32PCHAR16 = 0x047a, // 32 bit pointer to a 16-bit unicode char + T_32PFCHAR16 = 0x057a, // 16:32 pointer to a 16-bit unicode char + T_64PCHAR16 = 0x067a, // 64 bit pointer to a 16-bit unicode char + +// really a 32-bit unicode char + + T_CHAR32 = 0x007b, // 32-bit unicode char + T_PCHAR32 = 0x017b, // 16 bit pointer to a 32-bit unicode char + T_PFCHAR32 = 0x027b, // 16:16 far pointer to a 32-bit unicode char + T_PHCHAR32 = 0x037b, // 16:16 huge pointer to a 32-bit unicode char + T_32PCHAR32 = 0x047b, // 32 bit pointer to a 32-bit unicode char + T_32PFCHAR32 = 0x057b, // 16:32 pointer to a 32-bit unicode char + T_64PCHAR32 = 0x067b, // 64 bit pointer to a 32-bit unicode char + +// 8 bit int types + + T_INT1 = 0x0068, // 8 bit signed int + T_PINT1 = 0x0168, // 16 bit pointer to 8 bit signed int + T_PFINT1 = 0x0268, // 16:16 far pointer to 8 bit signed int + T_PHINT1 = 0x0368, // 16:16 huge pointer to 8 bit signed int + T_32PINT1 = 0x0468, // 32 bit pointer to 8 bit signed int + T_32PFINT1 = 0x0568, // 16:32 pointer to 8 bit signed int + T_64PINT1 = 0x0668, // 64 bit pointer to 8 bit signed int + + T_UINT1 = 0x0069, // 8 bit unsigned int + T_PUINT1 = 0x0169, // 16 bit pointer to 8 bit unsigned int + T_PFUINT1 = 0x0269, // 16:16 far pointer to 8 bit unsigned int + T_PHUINT1 = 0x0369, // 16:16 huge pointer to 8 bit unsigned int + T_32PUINT1 = 0x0469, // 32 bit pointer to 8 bit unsigned int + T_32PFUINT1 = 0x0569, // 16:32 pointer to 8 bit unsigned int + T_64PUINT1 = 0x0669, // 64 bit pointer to 8 bit unsigned int + + +// 16 bit short types + + T_SHORT = 0x0011, // 16 bit signed + T_PSHORT = 0x0111, // 16 bit pointer to 16 bit signed + T_PFSHORT = 0x0211, // 16:16 far pointer to 16 bit signed + T_PHSHORT = 0x0311, // 16:16 huge pointer to 16 bit signed + T_32PSHORT = 0x0411, // 32 bit pointer to 16 bit signed + T_32PFSHORT = 0x0511, // 16:32 pointer to 16 bit signed + T_64PSHORT = 0x0611, // 64 bit pointer to 16 bit signed + + T_USHORT = 0x0021, // 16 bit unsigned + T_PUSHORT = 0x0121, // 16 bit pointer to 16 bit unsigned + T_PFUSHORT = 0x0221, // 16:16 far pointer to 16 bit unsigned + T_PHUSHORT = 0x0321, // 16:16 huge pointer to 16 bit unsigned + T_32PUSHORT = 0x0421, // 32 bit pointer to 16 bit unsigned + T_32PFUSHORT = 0x0521, // 16:32 pointer to 16 bit unsigned + T_64PUSHORT = 0x0621, // 64 bit pointer to 16 bit unsigned + + +// 16 bit int types + + T_INT2 = 0x0072, // 16 bit signed int + T_PINT2 = 0x0172, // 16 bit pointer to 16 bit signed int + T_PFINT2 = 0x0272, // 16:16 far pointer to 16 bit signed int + T_PHINT2 = 0x0372, // 16:16 huge pointer to 16 bit signed int + T_32PINT2 = 0x0472, // 32 bit pointer to 16 bit signed int + T_32PFINT2 = 0x0572, // 16:32 pointer to 16 bit signed int + T_64PINT2 = 0x0672, // 64 bit pointer to 16 bit signed int + + T_UINT2 = 0x0073, // 16 bit unsigned int + T_PUINT2 = 0x0173, // 16 bit pointer to 16 bit unsigned int + T_PFUINT2 = 0x0273, // 16:16 far pointer to 16 bit unsigned int + T_PHUINT2 = 0x0373, // 16:16 huge pointer to 16 bit unsigned int + T_32PUINT2 = 0x0473, // 32 bit pointer to 16 bit unsigned int + T_32PFUINT2 = 0x0573, // 16:32 pointer to 16 bit unsigned int + T_64PUINT2 = 0x0673, // 64 bit pointer to 16 bit unsigned int + + +// 32 bit long types + + T_LONG = 0x0012, // 32 bit signed + T_ULONG = 0x0022, // 32 bit unsigned + T_PLONG = 0x0112, // 16 bit pointer to 32 bit signed + T_PULONG = 0x0122, // 16 bit pointer to 32 bit unsigned + T_PFLONG = 0x0212, // 16:16 far pointer to 32 bit signed + T_PFULONG = 0x0222, // 16:16 far pointer to 32 bit unsigned + T_PHLONG = 0x0312, // 16:16 huge pointer to 32 bit signed + T_PHULONG = 0x0322, // 16:16 huge pointer to 32 bit unsigned + + T_32PLONG = 0x0412, // 32 bit pointer to 32 bit signed + T_32PULONG = 0x0422, // 32 bit pointer to 32 bit unsigned + T_32PFLONG = 0x0512, // 16:32 pointer to 32 bit signed + T_32PFULONG = 0x0522, // 16:32 pointer to 32 bit unsigned + T_64PLONG = 0x0612, // 64 bit pointer to 32 bit signed + T_64PULONG = 0x0622, // 64 bit pointer to 32 bit unsigned + + +// 32 bit int types + + T_INT4 = 0x0074, // 32 bit signed int + T_PINT4 = 0x0174, // 16 bit pointer to 32 bit signed int + T_PFINT4 = 0x0274, // 16:16 far pointer to 32 bit signed int + T_PHINT4 = 0x0374, // 16:16 huge pointer to 32 bit signed int + T_32PINT4 = 0x0474, // 32 bit pointer to 32 bit signed int + T_32PFINT4 = 0x0574, // 16:32 pointer to 32 bit signed int + T_64PINT4 = 0x0674, // 64 bit pointer to 32 bit signed int + + T_UINT4 = 0x0075, // 32 bit unsigned int + T_PUINT4 = 0x0175, // 16 bit pointer to 32 bit unsigned int + T_PFUINT4 = 0x0275, // 16:16 far pointer to 32 bit unsigned int + T_PHUINT4 = 0x0375, // 16:16 huge pointer to 32 bit unsigned int + T_32PUINT4 = 0x0475, // 32 bit pointer to 32 bit unsigned int + T_32PFUINT4 = 0x0575, // 16:32 pointer to 32 bit unsigned int + T_64PUINT4 = 0x0675, // 64 bit pointer to 32 bit unsigned int + + +// 64 bit quad types + + T_QUAD = 0x0013, // 64 bit signed + T_PQUAD = 0x0113, // 16 bit pointer to 64 bit signed + T_PFQUAD = 0x0213, // 16:16 far pointer to 64 bit signed + T_PHQUAD = 0x0313, // 16:16 huge pointer to 64 bit signed + T_32PQUAD = 0x0413, // 32 bit pointer to 64 bit signed + T_32PFQUAD = 0x0513, // 16:32 pointer to 64 bit signed + T_64PQUAD = 0x0613, // 64 bit pointer to 64 bit signed + + T_UQUAD = 0x0023, // 64 bit unsigned + T_PUQUAD = 0x0123, // 16 bit pointer to 64 bit unsigned + T_PFUQUAD = 0x0223, // 16:16 far pointer to 64 bit unsigned + T_PHUQUAD = 0x0323, // 16:16 huge pointer to 64 bit unsigned + T_32PUQUAD = 0x0423, // 32 bit pointer to 64 bit unsigned + T_32PFUQUAD = 0x0523, // 16:32 pointer to 64 bit unsigned + T_64PUQUAD = 0x0623, // 64 bit pointer to 64 bit unsigned + + +// 64 bit int types + + T_INT8 = 0x0076, // 64 bit signed int + T_PINT8 = 0x0176, // 16 bit pointer to 64 bit signed int + T_PFINT8 = 0x0276, // 16:16 far pointer to 64 bit signed int + T_PHINT8 = 0x0376, // 16:16 huge pointer to 64 bit signed int + T_32PINT8 = 0x0476, // 32 bit pointer to 64 bit signed int + T_32PFINT8 = 0x0576, // 16:32 pointer to 64 bit signed int + T_64PINT8 = 0x0676, // 64 bit pointer to 64 bit signed int + + T_UINT8 = 0x0077, // 64 bit unsigned int + T_PUINT8 = 0x0177, // 16 bit pointer to 64 bit unsigned int + T_PFUINT8 = 0x0277, // 16:16 far pointer to 64 bit unsigned int + T_PHUINT8 = 0x0377, // 16:16 huge pointer to 64 bit unsigned int + T_32PUINT8 = 0x0477, // 32 bit pointer to 64 bit unsigned int + T_32PFUINT8 = 0x0577, // 16:32 pointer to 64 bit unsigned int + T_64PUINT8 = 0x0677, // 64 bit pointer to 64 bit unsigned int + + +// 128 bit octet types + + T_OCT = 0x0014, // 128 bit signed + T_POCT = 0x0114, // 16 bit pointer to 128 bit signed + T_PFOCT = 0x0214, // 16:16 far pointer to 128 bit signed + T_PHOCT = 0x0314, // 16:16 huge pointer to 128 bit signed + T_32POCT = 0x0414, // 32 bit pointer to 128 bit signed + T_32PFOCT = 0x0514, // 16:32 pointer to 128 bit signed + T_64POCT = 0x0614, // 64 bit pointer to 128 bit signed + + T_UOCT = 0x0024, // 128 bit unsigned + T_PUOCT = 0x0124, // 16 bit pointer to 128 bit unsigned + T_PFUOCT = 0x0224, // 16:16 far pointer to 128 bit unsigned + T_PHUOCT = 0x0324, // 16:16 huge pointer to 128 bit unsigned + T_32PUOCT = 0x0424, // 32 bit pointer to 128 bit unsigned + T_32PFUOCT = 0x0524, // 16:32 pointer to 128 bit unsigned + T_64PUOCT = 0x0624, // 64 bit pointer to 128 bit unsigned + + +// 128 bit int types + + T_INT16 = 0x0078, // 128 bit signed int + T_PINT16 = 0x0178, // 16 bit pointer to 128 bit signed int + T_PFINT16 = 0x0278, // 16:16 far pointer to 128 bit signed int + T_PHINT16 = 0x0378, // 16:16 huge pointer to 128 bit signed int + T_32PINT16 = 0x0478, // 32 bit pointer to 128 bit signed int + T_32PFINT16 = 0x0578, // 16:32 pointer to 128 bit signed int + T_64PINT16 = 0x0678, // 64 bit pointer to 128 bit signed int + + T_UINT16 = 0x0079, // 128 bit unsigned int + T_PUINT16 = 0x0179, // 16 bit pointer to 128 bit unsigned int + T_PFUINT16 = 0x0279, // 16:16 far pointer to 128 bit unsigned int + T_PHUINT16 = 0x0379, // 16:16 huge pointer to 128 bit unsigned int + T_32PUINT16 = 0x0479, // 32 bit pointer to 128 bit unsigned int + T_32PFUINT16 = 0x0579, // 16:32 pointer to 128 bit unsigned int + T_64PUINT16 = 0x0679, // 64 bit pointer to 128 bit unsigned int + + +// 16 bit real types + + T_REAL16 = 0x0046, // 16 bit real + T_PREAL16 = 0x0146, // 16 bit pointer to 16 bit real + T_PFREAL16 = 0x0246, // 16:16 far pointer to 16 bit real + T_PHREAL16 = 0x0346, // 16:16 huge pointer to 16 bit real + T_32PREAL16 = 0x0446, // 32 bit pointer to 16 bit real + T_32PFREAL16 = 0x0546, // 16:32 pointer to 16 bit real + T_64PREAL16 = 0x0646, // 64 bit pointer to 16 bit real + + +// 32 bit real types + + T_REAL32 = 0x0040, // 32 bit real + T_PREAL32 = 0x0140, // 16 bit pointer to 32 bit real + T_PFREAL32 = 0x0240, // 16:16 far pointer to 32 bit real + T_PHREAL32 = 0x0340, // 16:16 huge pointer to 32 bit real + T_32PREAL32 = 0x0440, // 32 bit pointer to 32 bit real + T_32PFREAL32 = 0x0540, // 16:32 pointer to 32 bit real + T_64PREAL32 = 0x0640, // 64 bit pointer to 32 bit real + + +// 32 bit partial-precision real types + + T_REAL32PP = 0x0045, // 32 bit PP real + T_PREAL32PP = 0x0145, // 16 bit pointer to 32 bit PP real + T_PFREAL32PP = 0x0245, // 16:16 far pointer to 32 bit PP real + T_PHREAL32PP = 0x0345, // 16:16 huge pointer to 32 bit PP real + T_32PREAL32PP = 0x0445, // 32 bit pointer to 32 bit PP real + T_32PFREAL32PP = 0x0545, // 16:32 pointer to 32 bit PP real + T_64PREAL32PP = 0x0645, // 64 bit pointer to 32 bit PP real + + +// 48 bit real types + + T_REAL48 = 0x0044, // 48 bit real + T_PREAL48 = 0x0144, // 16 bit pointer to 48 bit real + T_PFREAL48 = 0x0244, // 16:16 far pointer to 48 bit real + T_PHREAL48 = 0x0344, // 16:16 huge pointer to 48 bit real + T_32PREAL48 = 0x0444, // 32 bit pointer to 48 bit real + T_32PFREAL48 = 0x0544, // 16:32 pointer to 48 bit real + T_64PREAL48 = 0x0644, // 64 bit pointer to 48 bit real + + +// 64 bit real types + + T_REAL64 = 0x0041, // 64 bit real + T_PREAL64 = 0x0141, // 16 bit pointer to 64 bit real + T_PFREAL64 = 0x0241, // 16:16 far pointer to 64 bit real + T_PHREAL64 = 0x0341, // 16:16 huge pointer to 64 bit real + T_32PREAL64 = 0x0441, // 32 bit pointer to 64 bit real + T_32PFREAL64 = 0x0541, // 16:32 pointer to 64 bit real + T_64PREAL64 = 0x0641, // 64 bit pointer to 64 bit real + + +// 80 bit real types + + T_REAL80 = 0x0042, // 80 bit real + T_PREAL80 = 0x0142, // 16 bit pointer to 80 bit real + T_PFREAL80 = 0x0242, // 16:16 far pointer to 80 bit real + T_PHREAL80 = 0x0342, // 16:16 huge pointer to 80 bit real + T_32PREAL80 = 0x0442, // 32 bit pointer to 80 bit real + T_32PFREAL80 = 0x0542, // 16:32 pointer to 80 bit real + T_64PREAL80 = 0x0642, // 64 bit pointer to 80 bit real + + +// 128 bit real types + + T_REAL128 = 0x0043, // 128 bit real + T_PREAL128 = 0x0143, // 16 bit pointer to 128 bit real + T_PFREAL128 = 0x0243, // 16:16 far pointer to 128 bit real + T_PHREAL128 = 0x0343, // 16:16 huge pointer to 128 bit real + T_32PREAL128 = 0x0443, // 32 bit pointer to 128 bit real + T_32PFREAL128 = 0x0543, // 16:32 pointer to 128 bit real + T_64PREAL128 = 0x0643, // 64 bit pointer to 128 bit real + + +// 32 bit complex types + + T_CPLX32 = 0x0050, // 32 bit complex + T_PCPLX32 = 0x0150, // 16 bit pointer to 32 bit complex + T_PFCPLX32 = 0x0250, // 16:16 far pointer to 32 bit complex + T_PHCPLX32 = 0x0350, // 16:16 huge pointer to 32 bit complex + T_32PCPLX32 = 0x0450, // 32 bit pointer to 32 bit complex + T_32PFCPLX32 = 0x0550, // 16:32 pointer to 32 bit complex + T_64PCPLX32 = 0x0650, // 64 bit pointer to 32 bit complex + + +// 64 bit complex types + + T_CPLX64 = 0x0051, // 64 bit complex + T_PCPLX64 = 0x0151, // 16 bit pointer to 64 bit complex + T_PFCPLX64 = 0x0251, // 16:16 far pointer to 64 bit complex + T_PHCPLX64 = 0x0351, // 16:16 huge pointer to 64 bit complex + T_32PCPLX64 = 0x0451, // 32 bit pointer to 64 bit complex + T_32PFCPLX64 = 0x0551, // 16:32 pointer to 64 bit complex + T_64PCPLX64 = 0x0651, // 64 bit pointer to 64 bit complex + + +// 80 bit complex types + + T_CPLX80 = 0x0052, // 80 bit complex + T_PCPLX80 = 0x0152, // 16 bit pointer to 80 bit complex + T_PFCPLX80 = 0x0252, // 16:16 far pointer to 80 bit complex + T_PHCPLX80 = 0x0352, // 16:16 huge pointer to 80 bit complex + T_32PCPLX80 = 0x0452, // 32 bit pointer to 80 bit complex + T_32PFCPLX80 = 0x0552, // 16:32 pointer to 80 bit complex + T_64PCPLX80 = 0x0652, // 64 bit pointer to 80 bit complex + + +// 128 bit complex types + + T_CPLX128 = 0x0053, // 128 bit complex + T_PCPLX128 = 0x0153, // 16 bit pointer to 128 bit complex + T_PFCPLX128 = 0x0253, // 16:16 far pointer to 128 bit complex + T_PHCPLX128 = 0x0353, // 16:16 huge pointer to 128 bit real + T_32PCPLX128 = 0x0453, // 32 bit pointer to 128 bit complex + T_32PFCPLX128 = 0x0553, // 16:32 pointer to 128 bit complex + T_64PCPLX128 = 0x0653, // 64 bit pointer to 128 bit complex + + +// boolean types + + T_BOOL08 = 0x0030, // 8 bit boolean + T_PBOOL08 = 0x0130, // 16 bit pointer to 8 bit boolean + T_PFBOOL08 = 0x0230, // 16:16 far pointer to 8 bit boolean + T_PHBOOL08 = 0x0330, // 16:16 huge pointer to 8 bit boolean + T_32PBOOL08 = 0x0430, // 32 bit pointer to 8 bit boolean + T_32PFBOOL08 = 0x0530, // 16:32 pointer to 8 bit boolean + T_64PBOOL08 = 0x0630, // 64 bit pointer to 8 bit boolean + + T_BOOL16 = 0x0031, // 16 bit boolean + T_PBOOL16 = 0x0131, // 16 bit pointer to 16 bit boolean + T_PFBOOL16 = 0x0231, // 16:16 far pointer to 16 bit boolean + T_PHBOOL16 = 0x0331, // 16:16 huge pointer to 16 bit boolean + T_32PBOOL16 = 0x0431, // 32 bit pointer to 18 bit boolean + T_32PFBOOL16 = 0x0531, // 16:32 pointer to 16 bit boolean + T_64PBOOL16 = 0x0631, // 64 bit pointer to 18 bit boolean + + T_BOOL32 = 0x0032, // 32 bit boolean + T_PBOOL32 = 0x0132, // 16 bit pointer to 32 bit boolean + T_PFBOOL32 = 0x0232, // 16:16 far pointer to 32 bit boolean + T_PHBOOL32 = 0x0332, // 16:16 huge pointer to 32 bit boolean + T_32PBOOL32 = 0x0432, // 32 bit pointer to 32 bit boolean + T_32PFBOOL32 = 0x0532, // 16:32 pointer to 32 bit boolean + T_64PBOOL32 = 0x0632, // 64 bit pointer to 32 bit boolean + + T_BOOL64 = 0x0033, // 64 bit boolean + T_PBOOL64 = 0x0133, // 16 bit pointer to 64 bit boolean + T_PFBOOL64 = 0x0233, // 16:16 far pointer to 64 bit boolean + T_PHBOOL64 = 0x0333, // 16:16 huge pointer to 64 bit boolean + T_32PBOOL64 = 0x0433, // 32 bit pointer to 64 bit boolean + T_32PFBOOL64 = 0x0533, // 16:32 pointer to 64 bit boolean + T_64PBOOL64 = 0x0633, // 64 bit pointer to 64 bit boolean + + +// ??? + + T_NCVPTR = 0x01f0, // CV Internal type for created near pointers + T_FCVPTR = 0x02f0, // CV Internal type for created far pointers + T_HCVPTR = 0x03f0, // CV Internal type for created huge pointers + T_32NCVPTR = 0x04f0, // CV Internal type for created near 32-bit pointers + T_32FCVPTR = 0x05f0, // CV Internal type for created far 32-bit pointers + T_64NCVPTR = 0x06f0, // CV Internal type for created near 64-bit pointers + +} TYPE_ENUM_e; + +/** No leaf index can have a value of 0x0000. The leaf indices are + * separated into ranges depending upon the use of the type record. + * The second range is for the type records that are directly referenced + * in symbols. The first range is for type records that are not + * referenced by symbols but instead are referenced by other type + * records. All type records must have a starting leaf index in these + * first two ranges. The third range of leaf indices are used to build + * up complex lists such as the field list of a class type record. No + * type record can begin with one of the leaf indices. The fourth ranges + * of type indices are used to represent numeric data in a symbol or + * type record. These leaf indices are greater than 0x8000. At the + * point that type or symbol processor is expecting a numeric field, the + * next two bytes in the type record are examined. If the value is less + * than 0x8000, then the two bytes contain the numeric value. If the + * value is greater than 0x8000, then the data follows the leaf index in + * a format specified by the leaf index. The final range of leaf indices + * are used to force alignment of subfields within a complex type record.. + */ + + +typedef enum LEAF_ENUM_e { + // leaf indices starting records but referenced from symbol records + + LF_MODIFIER_16t = 0x0001, + LF_POINTER_16t = 0x0002, + LF_ARRAY_16t = 0x0003, + LF_CLASS_16t = 0x0004, + LF_STRUCTURE_16t = 0x0005, + LF_UNION_16t = 0x0006, + LF_ENUM_16t = 0x0007, + LF_PROCEDURE_16t = 0x0008, + LF_MFUNCTION_16t = 0x0009, + LF_VTSHAPE = 0x000a, + LF_COBOL0_16t = 0x000b, + LF_COBOL1 = 0x000c, + LF_BARRAY_16t = 0x000d, + LF_LABEL = 0x000e, + LF_NULL = 0x000f, + LF_NOTTRAN = 0x0010, + LF_DIMARRAY_16t = 0x0011, + LF_VFTPATH_16t = 0x0012, + LF_PRECOMP_16t = 0x0013, // not referenced from symbol + LF_ENDPRECOMP = 0x0014, // not referenced from symbol + LF_OEM_16t = 0x0015, // oem definable type string + LF_TYPESERVER_ST = 0x0016, // not referenced from symbol + + // leaf indices starting records but referenced only from type records + + LF_SKIP_16t = 0x0200, + LF_ARGLIST_16t = 0x0201, + LF_DEFARG_16t = 0x0202, + LF_LIST = 0x0203, + LF_FIELDLIST_16t = 0x0204, + LF_DERIVED_16t = 0x0205, + LF_BITFIELD_16t = 0x0206, + LF_METHODLIST_16t = 0x0207, + LF_DIMCONU_16t = 0x0208, + LF_DIMCONLU_16t = 0x0209, + LF_DIMVARU_16t = 0x020a, + LF_DIMVARLU_16t = 0x020b, + LF_REFSYM = 0x020c, + + LF_BCLASS_16t = 0x0400, + LF_VBCLASS_16t = 0x0401, + LF_IVBCLASS_16t = 0x0402, + LF_ENUMERATE_ST = 0x0403, + LF_FRIENDFCN_16t = 0x0404, + LF_INDEX_16t = 0x0405, + LF_MEMBER_16t = 0x0406, + LF_STMEMBER_16t = 0x0407, + LF_METHOD_16t = 0x0408, + LF_NESTTYPE_16t = 0x0409, + LF_VFUNCTAB_16t = 0x040a, + LF_FRIENDCLS_16t = 0x040b, + LF_ONEMETHOD_16t = 0x040c, + LF_VFUNCOFF_16t = 0x040d, + +// 32-bit type index versions of leaves, all have the 0x1000 bit set +// + LF_TI16_MAX = 0x1000, + + LF_MODIFIER = 0x1001, + LF_POINTER = 0x1002, + LF_ARRAY_ST = 0x1003, + LF_CLASS_ST = 0x1004, + LF_STRUCTURE_ST = 0x1005, + LF_UNION_ST = 0x1006, + LF_ENUM_ST = 0x1007, + LF_PROCEDURE = 0x1008, + LF_MFUNCTION = 0x1009, + LF_COBOL0 = 0x100a, + LF_BARRAY = 0x100b, + LF_DIMARRAY_ST = 0x100c, + LF_VFTPATH = 0x100d, + LF_PRECOMP_ST = 0x100e, // not referenced from symbol + LF_OEM = 0x100f, // oem definable type string + LF_ALIAS_ST = 0x1010, // alias (typedef) type + LF_OEM2 = 0x1011, // oem definable type string + + // leaf indices starting records but referenced only from type records + + LF_SKIP = 0x1200, + LF_ARGLIST = 0x1201, + LF_DEFARG_ST = 0x1202, + LF_FIELDLIST = 0x1203, + LF_DERIVED = 0x1204, + LF_BITFIELD = 0x1205, + LF_METHODLIST = 0x1206, + LF_DIMCONU = 0x1207, + LF_DIMCONLU = 0x1208, + LF_DIMVARU = 0x1209, + LF_DIMVARLU = 0x120a, + + LF_BCLASS = 0x1400, + LF_VBCLASS = 0x1401, + LF_IVBCLASS = 0x1402, + LF_FRIENDFCN_ST = 0x1403, + LF_INDEX = 0x1404, + LF_MEMBER_ST = 0x1405, + LF_STMEMBER_ST = 0x1406, + LF_METHOD_ST = 0x1407, + LF_NESTTYPE_ST = 0x1408, + LF_VFUNCTAB = 0x1409, + LF_FRIENDCLS = 0x140a, + LF_ONEMETHOD_ST = 0x140b, + LF_VFUNCOFF = 0x140c, + LF_NESTTYPEEX_ST = 0x140d, + LF_MEMBERMODIFY_ST = 0x140e, + LF_MANAGED_ST = 0x140f, + + // Types w/ SZ names + + LF_ST_MAX = 0x1500, + + LF_TYPESERVER = 0x1501, // not referenced from symbol + LF_ENUMERATE = 0x1502, + LF_ARRAY = 0x1503, + LF_CLASS = 0x1504, + LF_STRUCTURE = 0x1505, + LF_UNION = 0x1506, + LF_ENUM = 0x1507, + LF_DIMARRAY = 0x1508, + LF_PRECOMP = 0x1509, // not referenced from symbol + LF_ALIAS = 0x150a, // alias (typedef) type + LF_DEFARG = 0x150b, + LF_FRIENDFCN = 0x150c, + LF_MEMBER = 0x150d, + LF_STMEMBER = 0x150e, + LF_METHOD = 0x150f, + LF_NESTTYPE = 0x1510, + LF_ONEMETHOD = 0x1511, + LF_NESTTYPEEX = 0x1512, + LF_MEMBERMODIFY = 0x1513, + LF_MANAGED = 0x1514, + LF_TYPESERVER2 = 0x1515, + + LF_STRIDED_ARRAY = 0x1516, // same as LF_ARRAY, but with stride between adjacent elements + LF_HLSL = 0x1517, + LF_MODIFIER_EX = 0x1518, + LF_INTERFACE = 0x1519, + LF_BINTERFACE = 0x151a, + LF_VECTOR = 0x151b, + LF_MATRIX = 0x151c, + + LF_VFTABLE = 0x151d, // a virtual function table + LF_ENDOFLEAFRECORD = LF_VFTABLE, + + LF_TYPE_LAST, // one greater than the last type record + LF_TYPE_MAX = LF_TYPE_LAST - 1, + + LF_FUNC_ID = 0x1601, // global func ID + LF_MFUNC_ID = 0x1602, // member func ID + LF_BUILDINFO = 0x1603, // build info: tool, version, command line, src/pdb file + LF_SUBSTR_LIST = 0x1604, // similar to LF_ARGLIST, for list of sub strings + LF_STRING_ID = 0x1605, // string ID + + LF_UDT_SRC_LINE = 0x1606, // source and line on where an UDT is defined + // only generated by compiler + + LF_UDT_MOD_SRC_LINE = 0x1607, // module, source and line on where an UDT is defined + // only generated by linker + + LF_ID_LAST, // one greater than the last ID record + LF_ID_MAX = LF_ID_LAST - 1, + + LF_NUMERIC = 0x8000, + LF_CHAR = 0x8000, + LF_SHORT = 0x8001, + LF_USHORT = 0x8002, + LF_LONG = 0x8003, + LF_ULONG = 0x8004, + LF_REAL32 = 0x8005, + LF_REAL64 = 0x8006, + LF_REAL80 = 0x8007, + LF_REAL128 = 0x8008, + LF_QUADWORD = 0x8009, + LF_UQUADWORD = 0x800a, + LF_REAL48 = 0x800b, + LF_COMPLEX32 = 0x800c, + LF_COMPLEX64 = 0x800d, + LF_COMPLEX80 = 0x800e, + LF_COMPLEX128 = 0x800f, + LF_VARSTRING = 0x8010, + + LF_OCTWORD = 0x8017, + LF_UOCTWORD = 0x8018, + + LF_DECIMAL = 0x8019, + LF_DATE = 0x801a, + LF_UTF8STRING = 0x801b, + + LF_REAL16 = 0x801c, + + LF_PAD0 = 0xf0, + LF_PAD1 = 0xf1, + LF_PAD2 = 0xf2, + LF_PAD3 = 0xf3, + LF_PAD4 = 0xf4, + LF_PAD5 = 0xf5, + LF_PAD6 = 0xf6, + LF_PAD7 = 0xf7, + LF_PAD8 = 0xf8, + LF_PAD9 = 0xf9, + LF_PAD10 = 0xfa, + LF_PAD11 = 0xfb, + LF_PAD12 = 0xfc, + LF_PAD13 = 0xfd, + LF_PAD14 = 0xfe, + LF_PAD15 = 0xff, + +} LEAF_ENUM_e; + +// end of leaf indices + + + + +// Type enum for pointer records +// Pointers can be one of the following types + + +typedef enum CV_ptrtype_e { + CV_PTR_NEAR = 0x00, // 16 bit pointer + CV_PTR_FAR = 0x01, // 16:16 far pointer + CV_PTR_HUGE = 0x02, // 16:16 huge pointer + CV_PTR_BASE_SEG = 0x03, // based on segment + CV_PTR_BASE_VAL = 0x04, // based on value of base + CV_PTR_BASE_SEGVAL = 0x05, // based on segment value of base + CV_PTR_BASE_ADDR = 0x06, // based on address of base + CV_PTR_BASE_SEGADDR = 0x07, // based on segment address of base + CV_PTR_BASE_TYPE = 0x08, // based on type + CV_PTR_BASE_SELF = 0x09, // based on self + CV_PTR_NEAR32 = 0x0a, // 32 bit pointer + CV_PTR_FAR32 = 0x0b, // 16:32 pointer + CV_PTR_64 = 0x0c, // 64 bit pointer + CV_PTR_UNUSEDPTR = 0x0d // first unused pointer type +} CV_ptrtype_e; + + + + + +// Mode enum for pointers +// Pointers can have one of the following modes +// +// To support for l-value and r-value reference, we added CV_PTR_MODE_LVREF +// and CV_PTR_MODE_RVREF. CV_PTR_MODE_REF should be removed at some point. +// We keep it now so that old code that uses it won't be broken. +// + +typedef enum CV_ptrmode_e { + CV_PTR_MODE_PTR = 0x00, // "normal" pointer + CV_PTR_MODE_REF = 0x01, // "old" reference + CV_PTR_MODE_LVREF = 0x01, // l-value reference + CV_PTR_MODE_PMEM = 0x02, // pointer to data member + CV_PTR_MODE_PMFUNC = 0x03, // pointer to member function + CV_PTR_MODE_RVREF = 0x04, // r-value reference + CV_PTR_MODE_RESERVED= 0x05 // first unused pointer mode +} CV_ptrmode_e; + + +// enumeration for pointer-to-member types + +typedef enum CV_pmtype_e { + CV_PMTYPE_Undef = 0x00, // not specified (pre VC8) + CV_PMTYPE_D_Single = 0x01, // member data, single inheritance + CV_PMTYPE_D_Multiple= 0x02, // member data, multiple inheritance + CV_PMTYPE_D_Virtual = 0x03, // member data, virtual inheritance + CV_PMTYPE_D_General = 0x04, // member data, most general + CV_PMTYPE_F_Single = 0x05, // member function, single inheritance + CV_PMTYPE_F_Multiple= 0x06, // member function, multiple inheritance + CV_PMTYPE_F_Virtual = 0x07, // member function, virtual inheritance + CV_PMTYPE_F_General = 0x08, // member function, most general +} CV_pmtype_e; + +// enumeration for method properties + +typedef enum CV_methodprop_e { + CV_MTvanilla = 0x00, + CV_MTvirtual = 0x01, + CV_MTstatic = 0x02, + CV_MTfriend = 0x03, + CV_MTintro = 0x04, + CV_MTpurevirt = 0x05, + CV_MTpureintro = 0x06 +} CV_methodprop_e; + + + + +// enumeration for virtual shape table entries + +typedef enum CV_VTS_desc_e { + CV_VTS_near = 0x00, + CV_VTS_far = 0x01, + CV_VTS_thin = 0x02, + CV_VTS_outer = 0x03, + CV_VTS_meta = 0x04, + CV_VTS_near32 = 0x05, + CV_VTS_far32 = 0x06, + CV_VTS_unused = 0x07 +} CV_VTS_desc_e; + + + + +// enumeration for LF_LABEL address modes + +typedef enum CV_LABEL_TYPE_e { + CV_LABEL_NEAR = 0, // near return + CV_LABEL_FAR = 4 // far return +} CV_LABEL_TYPE_e; + + + +// enumeration for LF_MODIFIER values + + +typedef struct CV_modifier_t { + unsigned short MOD_const :1; + unsigned short MOD_volatile :1; + unsigned short MOD_unaligned :1; + unsigned short MOD_unused :13; +} CV_modifier_t; + + + + +// enumeration for HFA kinds + +typedef enum CV_HFA_e { + CV_HFA_none = 0, + CV_HFA_float = 1, + CV_HFA_double = 2, + CV_HFA_other = 3 +} CV_HFA_e; + +// enumeration for MoCOM UDT kinds + +typedef enum CV_MOCOM_UDT_e { + CV_MOCOM_UDT_none = 0, + CV_MOCOM_UDT_ref = 1, + CV_MOCOM_UDT_value = 2, + CV_MOCOM_UDT_interface = 3 +} CV_MOCOM_UDT_e; + +// bit field structure describing class/struct/union/enum properties + +typedef struct CV_prop_t { + unsigned short packed :1; // true if structure is packed + unsigned short ctor :1; // true if constructors or destructors present + unsigned short ovlops :1; // true if overloaded operators present + unsigned short isnested :1; // true if this is a nested class + unsigned short cnested :1; // true if this class contains nested types + unsigned short opassign :1; // true if overloaded assignment (=) + unsigned short opcast :1; // true if casting methods + unsigned short fwdref :1; // true if forward reference (incomplete defn) + unsigned short scoped :1; // scoped definition + unsigned short hasuniquename :1; // true if there is a decorated name following the regular name + unsigned short sealed :1; // true if class cannot be used as a base class + unsigned short hfa :2; // CV_HFA_e + unsigned short intrinsic :1; // true if class is an intrinsic type (e.g. __m128d) + unsigned short mocom :2; // CV_MOCOM_UDT_e +} CV_prop_t; + + + + +// class field attribute + +typedef struct CV_fldattr_t { + unsigned short access :2; // access protection CV_access_t + unsigned short mprop :3; // method properties CV_methodprop_t + unsigned short pseudo :1; // compiler generated fcn and does not exist + unsigned short noinherit :1; // true if class cannot be inherited + unsigned short noconstruct :1; // true if class cannot be constructed + unsigned short compgenx :1; // compiler generated fcn and does exist + unsigned short sealed :1; // true if method cannot be overridden + unsigned short unused :6; // unused +} CV_fldattr_t; + + +// function flags + +typedef struct CV_funcattr_t { + unsigned char cxxreturnudt :1; // true if C++ style ReturnUDT + unsigned char ctor :1; // true if func is an instance constructor + unsigned char ctorvbase :1; // true if func is an instance constructor of a class with virtual bases + unsigned char unused :5; // unused +} CV_funcattr_t; + + +// matrix flags + +typedef struct CV_matrixattr_t { + unsigned char row_major :1; // true if matrix has row-major layout (column-major is default) + unsigned char unused :7; // unused +} CV_matrixattr_t; + + +// Structures to access to the type records + + +typedef struct TYPTYPE { + unsigned short len; + unsigned short leaf; + unsigned char data[CV_ZEROLEN]; +} TYPTYPE; // general types record + +__INLINE char *NextType ( _In_ char * pType) { + return (pType + ((TYPTYPE *)pType)->len + sizeof(unsigned short)); +} + +typedef enum CV_PMEMBER { + CV_PDM16_NONVIRT = 0x00, // 16:16 data no virtual fcn or base + CV_PDM16_VFCN = 0x01, // 16:16 data with virtual functions + CV_PDM16_VBASE = 0x02, // 16:16 data with virtual bases + CV_PDM32_NVVFCN = 0x03, // 16:32 data w/wo virtual functions + CV_PDM32_VBASE = 0x04, // 16:32 data with virtual bases + + CV_PMF16_NEARNVSA = 0x05, // 16:16 near method nonvirtual single address point + CV_PMF16_NEARNVMA = 0x06, // 16:16 near method nonvirtual multiple address points + CV_PMF16_NEARVBASE = 0x07, // 16:16 near method virtual bases + CV_PMF16_FARNVSA = 0x08, // 16:16 far method nonvirtual single address point + CV_PMF16_FARNVMA = 0x09, // 16:16 far method nonvirtual multiple address points + CV_PMF16_FARVBASE = 0x0a, // 16:16 far method virtual bases + + CV_PMF32_NVSA = 0x0b, // 16:32 method nonvirtual single address point + CV_PMF32_NVMA = 0x0c, // 16:32 method nonvirtual multiple address point + CV_PMF32_VBASE = 0x0d // 16:32 method virtual bases +} CV_PMEMBER; + + + +// memory representation of pointer to member. These representations are +// indexed by the enumeration above in the LF_POINTER record + + + + +// representation of a 16:16 pointer to data for a class with no +// virtual functions or virtual bases + + +struct CV_PDMR16_NONVIRT { + CV_off16_t mdisp; // displacement to data (NULL = -1) +}; + + + + +// representation of a 16:16 pointer to data for a class with virtual +// functions + + +struct CV_PMDR16_VFCN { + CV_off16_t mdisp; // displacement to data ( NULL = 0) +}; + + + + +// representation of a 16:16 pointer to data for a class with +// virtual bases + + +struct CV_PDMR16_VBASE { + CV_off16_t mdisp; // displacement to data + CV_off16_t pdisp; // this pointer displacement to vbptr + CV_off16_t vdisp; // displacement within vbase table + // NULL = (,,0xffff) +}; + + + + +// representation of a 32 bit pointer to data for a class with +// or without virtual functions and no virtual bases + + +struct CV_PDMR32_NVVFCN { + CV_off32_t mdisp; // displacement to data (NULL = 0x80000000) +}; + + + + +// representation of a 32 bit pointer to data for a class +// with virtual bases + + +struct CV_PDMR32_VBASE { + CV_off32_t mdisp; // displacement to data + CV_off32_t pdisp; // this pointer displacement + CV_off32_t vdisp; // vbase table displacement + // NULL = (,,0xffffffff) +}; + + + + +// representation of a 16:16 pointer to near member function for a +// class with no virtual functions or bases and a single address point + + +struct CV_PMFR16_NEARNVSA { + CV_uoff16_t off; // near address of function (NULL = 0) +}; + + + +// representation of a 16 bit pointer to member functions of a +// class with no virtual bases and multiple address points + + +struct CV_PMFR16_NEARNVMA { + CV_uoff16_t off; // offset of function (NULL = 0,x) + signed short disp; +}; + + + + +// representation of a 16 bit pointer to member function of a +// class with virtual bases + + +struct CV_PMFR16_NEARVBASE { + CV_uoff16_t off; // offset of function (NULL = 0,x,x,x) + CV_off16_t mdisp; // displacement to data + CV_off16_t pdisp; // this pointer displacement + CV_off16_t vdisp; // vbase table displacement +}; + + + + +// representation of a 16:16 pointer to far member function for a +// class with no virtual bases and a single address point + + +struct CV_PMFR16_FARNVSA { + CV_uoff16_t off; // offset of function (NULL = 0:0) + unsigned short seg; // segment of function +}; + + + + +// representation of a 16:16 far pointer to member functions of a +// class with no virtual bases and multiple address points + + +struct CV_PMFR16_FARNVMA { + CV_uoff16_t off; // offset of function (NULL = 0:0,x) + unsigned short seg; + signed short disp; +}; + + + + +// representation of a 16:16 far pointer to member function of a +// class with virtual bases + + +struct CV_PMFR16_FARVBASE { + CV_uoff16_t off; // offset of function (NULL = 0:0,x,x,x) + unsigned short seg; + CV_off16_t mdisp; // displacement to data + CV_off16_t pdisp; // this pointer displacement + CV_off16_t vdisp; // vbase table displacement + +}; + + + + +// representation of a 32 bit pointer to member function for a +// class with no virtual bases and a single address point + + +struct CV_PMFR32_NVSA { + CV_uoff32_t off; // near address of function (NULL = 0L) +}; + + + + +// representation of a 32 bit pointer to member function for a +// class with no virtual bases and multiple address points + + +struct CV_PMFR32_NVMA { + CV_uoff32_t off; // near address of function (NULL = 0L,x) + CV_off32_t disp; +}; + + + + +// representation of a 32 bit pointer to member function for a +// class with virtual bases + + +struct CV_PMFR32_VBASE { + CV_uoff32_t off; // near address of function (NULL = 0L,x,x,x) + CV_off32_t mdisp; // displacement to data + CV_off32_t pdisp; // this pointer displacement + CV_off32_t vdisp; // vbase table displacement +}; + + + + + +// Easy leaf - used for generic casting to reference leaf field +// of a subfield of a complex list + +typedef struct lfEasy { + unsigned short leaf; // LF_... +} lfEasy; + + +/** The following type records are basically variant records of the + * above structure. The "unsigned short leaf" of the above structure and + * the "unsigned short leaf" of the following type definitions are the same + * symbol. When the OMF record is locked via the MHOMFLock API + * call, the address of the "unsigned short leaf" is returned + */ + +/** Notes on alignment + * Alignment of the fields in most of the type records is done on the + * basis of the TYPTYPE record base. That is why in most of the lf* + * records that the CV_typ_t (32-bit types) is located on what appears to + * be a offset mod 4 == 2 boundary. The exception to this rule are those + * records that are in a list (lfFieldList, lfMethodList), which are + * aligned to their own bases since they don't have the length field + */ + +/**** Change log for 16-bit to 32-bit type and symbol records + + Record type Change (f == field arrangement, p = padding added) + ---------------------------------------------------------------------- + lfModifer f + lfPointer fp + lfClass f + lfStructure f + lfUnion f + lfEnum f + lfVFTPath p + lfPreComp p + lfOEM p + lfArgList p + lfDerived p + mlMethod p (method list member) + lfBitField f + lfDimCon f + lfDimVar p + lfIndex p (field list member) + lfBClass f (field list member) + lfVBClass f (field list member) + lfFriendCls p (field list member) + lfFriendFcn p (field list member) + lfMember f (field list member) + lfSTMember f (field list member) + lfVFuncTab p (field list member) + lfVFuncOff p (field list member) + lfNestType p (field list member) + + DATASYM32 f + PROCSYM32 f + VPATHSYM32 f + REGREL32 f + THREADSYM32 f + PROCSYMMIPS f + + +*/ + +// Type record for LF_MODIFIER + +typedef struct lfModifier_16t { + unsigned short leaf; // LF_MODIFIER_16t + CV_modifier_t attr; // modifier attribute modifier_t + CV_typ16_t type; // modified type +} lfModifier_16t; + +typedef struct lfModifier { + unsigned short leaf; // LF_MODIFIER + CV_typ_t type; // modified type + CV_modifier_t attr; // modifier attribute modifier_t +} lfModifier; + + + + +// type record for LF_POINTER + +#ifndef __cplusplus +typedef struct lfPointer_16t { +#endif + struct lfPointerBody_16t { + unsigned short leaf; // LF_POINTER_16t + struct lfPointerAttr_16t { + unsigned char ptrtype :5; // ordinal specifying pointer type (CV_ptrtype_e) + unsigned char ptrmode :3; // ordinal specifying pointer mode (CV_ptrmode_e) + unsigned char isflat32 :1; // true if 0:32 pointer + unsigned char isvolatile :1; // TRUE if volatile pointer + unsigned char isconst :1; // TRUE if const pointer + unsigned char isunaligned :1; // TRUE if unaligned pointer + unsigned char unused :4; + } attr; + CV_typ16_t utype; // type index of the underlying type +#if (defined(__cplusplus) || defined(_MSC_VER)) // for C++ and MS compilers that support unnamed unions + }; +#else + } u; +#endif +#ifdef __cplusplus +typedef struct lfPointer_16t : public lfPointerBody_16t { +#endif + union { + struct { + CV_typ16_t pmclass; // index of containing class for pointer to member + unsigned short pmenum; // enumeration specifying pm format (CV_pmtype_e) + } pm; + unsigned short bseg; // base segment if PTR_BASE_SEG + unsigned char Sym[1]; // copy of base symbol record (including length) + struct { + CV_typ16_t index; // type index if CV_PTR_BASE_TYPE + unsigned char name[1]; // name of base type + } btype; + } pbase; +} lfPointer_16t; + +#ifndef __cplusplus +typedef struct lfPointer { +#endif + struct lfPointerBody { + unsigned short leaf; // LF_POINTER + CV_typ_t utype; // type index of the underlying type + struct lfPointerAttr { + unsigned long ptrtype :5; // ordinal specifying pointer type (CV_ptrtype_e) + unsigned long ptrmode :3; // ordinal specifying pointer mode (CV_ptrmode_e) + unsigned long isflat32 :1; // true if 0:32 pointer + unsigned long isvolatile :1; // TRUE if volatile pointer + unsigned long isconst :1; // TRUE if const pointer + unsigned long isunaligned :1; // TRUE if unaligned pointer + unsigned long isrestrict :1; // TRUE if restricted pointer (allow agressive opts) + unsigned long size :6; // size of pointer (in bytes) + unsigned long ismocom :1; // TRUE if it is a MoCOM pointer (^ or %) + unsigned long islref :1; // TRUE if it is this pointer of member function with & ref-qualifier + unsigned long isrref :1; // TRUE if it is this pointer of member function with && ref-qualifier + unsigned long unused :10;// pad out to 32-bits for following cv_typ_t's + } attr; +#if (defined(__cplusplus) || defined(_MSC_VER)) // for C++ and MS compilers that support unnamed unions + }; +#else + } u; +#endif +#ifdef __cplusplus +typedef struct lfPointer : public lfPointerBody { +#endif + union { + struct { + CV_typ_t pmclass; // index of containing class for pointer to member + unsigned short pmenum; // enumeration specifying pm format (CV_pmtype_e) + } pm; + unsigned short bseg; // base segment if PTR_BASE_SEG + unsigned char Sym[1]; // copy of base symbol record (including length) + struct { + CV_typ_t index; // type index if CV_PTR_BASE_TYPE + unsigned char name[1]; // name of base type + } btype; + } pbase; +} lfPointer; + + + + +// type record for LF_ARRAY + + +typedef struct lfArray_16t { + unsigned short leaf; // LF_ARRAY_16t + CV_typ16_t elemtype; // type index of element type + CV_typ16_t idxtype; // type index of indexing type + unsigned char data[CV_ZEROLEN]; // variable length data specifying + // size in bytes and name +} lfArray_16t; + +typedef struct lfArray { + unsigned short leaf; // LF_ARRAY + CV_typ_t elemtype; // type index of element type + CV_typ_t idxtype; // type index of indexing type + unsigned char data[CV_ZEROLEN]; // variable length data specifying + // size in bytes and name +} lfArray; + +typedef struct lfStridedArray { + unsigned short leaf; // LF_STRIDED_ARRAY + CV_typ_t elemtype; // type index of element type + CV_typ_t idxtype; // type index of indexing type + unsigned long stride; + unsigned char data[CV_ZEROLEN]; // variable length data specifying + // size in bytes and name +} lfStridedArray; + + + + +// type record for LF_VECTOR + + +typedef struct lfVector { + unsigned short leaf; // LF_VECTOR + CV_typ_t elemtype; // type index of element type + unsigned long count; // number of elements in the vector + unsigned char data[CV_ZEROLEN]; // variable length data specifying + // size in bytes and name +} lfVector; + + + + +// type record for LF_MATRIX + + +typedef struct lfMatrix { + unsigned short leaf; // LF_MATRIX + CV_typ_t elemtype; // type index of element type + unsigned long rows; // number of rows + unsigned long cols; // number of columns + unsigned long majorStride; + CV_matrixattr_t matattr; // attributes + unsigned char data[CV_ZEROLEN]; // variable length data specifying + // size in bytes and name +} lfMatrix; + + + + +// type record for LF_CLASS, LF_STRUCTURE + + +typedef struct lfClass_16t { + unsigned short leaf; // LF_CLASS_16t, LF_STRUCT_16t + unsigned short count; // count of number of elements in class + CV_typ16_t field; // type index of LF_FIELD descriptor list + CV_prop_t property; // property attribute field (prop_t) + CV_typ16_t derived; // type index of derived from list if not zero + CV_typ16_t vshape; // type index of vshape table for this class + unsigned char data[CV_ZEROLEN]; // data describing length of structure in + // bytes and name +} lfClass_16t; +typedef lfClass_16t lfStructure_16t; + + +typedef struct lfClass { + unsigned short leaf; // LF_CLASS, LF_STRUCT, LF_INTERFACE + unsigned short count; // count of number of elements in class + CV_prop_t property; // property attribute field (prop_t) + CV_typ_t field; // type index of LF_FIELD descriptor list + CV_typ_t derived; // type index of derived from list if not zero + CV_typ_t vshape; // type index of vshape table for this class + unsigned char data[CV_ZEROLEN]; // data describing length of structure in + // bytes and name +} lfClass; +typedef lfClass lfStructure; +typedef lfClass lfInterface; + +// type record for LF_UNION + + +typedef struct lfUnion_16t { + unsigned short leaf; // LF_UNION_16t + unsigned short count; // count of number of elements in class + CV_typ16_t field; // type index of LF_FIELD descriptor list + CV_prop_t property; // property attribute field + unsigned char data[CV_ZEROLEN]; // variable length data describing length of + // structure and name +} lfUnion_16t; + + +typedef struct lfUnion { + unsigned short leaf; // LF_UNION + unsigned short count; // count of number of elements in class + CV_prop_t property; // property attribute field + CV_typ_t field; // type index of LF_FIELD descriptor list + unsigned char data[CV_ZEROLEN]; // variable length data describing length of + // structure and name +} lfUnion; + + +// type record for LF_ALIAS + +typedef struct lfAlias { + unsigned short leaf; // LF_ALIAS + CV_typ_t utype; // underlying type + unsigned char Name[1]; // alias name +} lfAlias; + +// Item Id is a stricter typeindex which may referenced from symbol stream. +// The code item always had a name. + +typedef CV_typ_t CV_ItemId; + +typedef struct lfFuncId { + unsigned short leaf; // LF_FUNC_ID + CV_ItemId scopeId; // parent scope of the ID, 0 if global + CV_typ_t type; // function type + unsigned char name[CV_ZEROLEN]; +} lfFuncId; + +typedef struct lfMFuncId { + unsigned short leaf; // LF_MFUNC_ID + CV_typ_t parentType; // type index of parent + CV_typ_t type; // function type + unsigned char name[CV_ZEROLEN]; +} lfMFuncId; + +typedef struct lfStringId { + unsigned short leaf; // LF_STRING_ID + CV_ItemId id; // ID to list of sub string IDs + unsigned char name[CV_ZEROLEN]; +} lfStringId; + +typedef struct lfUdtSrcLine { + unsigned short leaf; // LF_UDT_SRC_LINE + CV_typ_t type; // UDT's type index + CV_ItemId src; // index to LF_STRING_ID record where source file name is saved + unsigned long line; // line number +} lfUdtSrcLine; + +typedef struct lfUdtModSrcLine { + unsigned short leaf; // LF_UDT_MOD_SRC_LINE + CV_typ_t type; // UDT's type index + CV_ItemId src; // index into string table where source file name is saved + unsigned long line; // line number + unsigned short imod; // module that contributes this UDT definition +} lfUdtModSrcLine; + +typedef enum CV_BuildInfo_e { + CV_BuildInfo_CurrentDirectory = 0, + CV_BuildInfo_BuildTool = 1, // Cl.exe + CV_BuildInfo_SourceFile = 2, // foo.cpp + CV_BuildInfo_ProgramDatabaseFile = 3, // foo.pdb + CV_BuildInfo_CommandArguments = 4, // -I etc + CV_BUILDINFO_KNOWN +} CV_BuildInfo_e; + +// type record for build information + +typedef struct lfBuildInfo { + unsigned short leaf; // LF_BUILDINFO + unsigned short count; // number of arguments + CV_ItemId arg[CV_BUILDINFO_KNOWN]; // arguments as CodeItemId +} lfBuildInfo; + +// type record for LF_MANAGED + +typedef struct lfManaged { + unsigned short leaf; // LF_MANAGED + unsigned char Name[1]; // utf8, zero terminated managed type name +} lfManaged; + + +// type record for LF_ENUM + + +typedef struct lfEnum_16t { + unsigned short leaf; // LF_ENUM_16t + unsigned short count; // count of number of elements in class + CV_typ16_t utype; // underlying type of the enum + CV_typ16_t field; // type index of LF_FIELD descriptor list + CV_prop_t property; // property attribute field + unsigned char Name[1]; // length prefixed name of enum +} lfEnum_16t; + +typedef struct lfEnum { + unsigned short leaf; // LF_ENUM + unsigned short count; // count of number of elements in class + CV_prop_t property; // property attribute field + CV_typ_t utype; // underlying type of the enum + CV_typ_t field; // type index of LF_FIELD descriptor list + unsigned char Name[1]; // length prefixed name of enum +} lfEnum; + + + +// Type record for LF_PROCEDURE + + +typedef struct lfProc_16t { + unsigned short leaf; // LF_PROCEDURE_16t + CV_typ16_t rvtype; // type index of return value + unsigned char calltype; // calling convention (CV_call_t) + CV_funcattr_t funcattr; // attributes + unsigned short parmcount; // number of parameters + CV_typ16_t arglist; // type index of argument list +} lfProc_16t; + +typedef struct lfProc { + unsigned short leaf; // LF_PROCEDURE + CV_typ_t rvtype; // type index of return value + unsigned char calltype; // calling convention (CV_call_t) + CV_funcattr_t funcattr; // attributes + unsigned short parmcount; // number of parameters + CV_typ_t arglist; // type index of argument list +} lfProc; + + + +// Type record for member function + + +typedef struct lfMFunc_16t { + unsigned short leaf; // LF_MFUNCTION_16t + CV_typ16_t rvtype; // type index of return value + CV_typ16_t classtype; // type index of containing class + CV_typ16_t thistype; // type index of this pointer (model specific) + unsigned char calltype; // calling convention (call_t) + CV_funcattr_t funcattr; // attributes + unsigned short parmcount; // number of parameters + CV_typ16_t arglist; // type index of argument list + long thisadjust; // this adjuster (long because pad required anyway) +} lfMFunc_16t; + +typedef struct lfMFunc { + unsigned short leaf; // LF_MFUNCTION + CV_typ_t rvtype; // type index of return value + CV_typ_t classtype; // type index of containing class + CV_typ_t thistype; // type index of this pointer (model specific) + unsigned char calltype; // calling convention (call_t) + CV_funcattr_t funcattr; // attributes + unsigned short parmcount; // number of parameters + CV_typ_t arglist; // type index of argument list + long thisadjust; // this adjuster (long because pad required anyway) +} lfMFunc; + + + + +// type record for virtual function table shape + + +typedef struct lfVTShape { + unsigned short leaf; // LF_VTSHAPE + unsigned short count; // number of entries in vfunctable + unsigned char desc[CV_ZEROLEN]; // 4 bit (CV_VTS_desc) descriptors +} lfVTShape; + +// type record for a virtual function table +typedef struct lfVftable { + unsigned short leaf; // LF_VFTABLE + CV_typ_t type; // class/structure that owns the vftable + CV_typ_t baseVftable; // vftable from which this vftable is derived + unsigned long offsetInObjectLayout; // offset of the vfptr to this table, relative to the start of the object layout. + unsigned long len; // length of the Names array below in bytes. + unsigned char Names[1]; // array of names. + // The first is the name of the vtable. + // The others are the names of the methods. + // TS-TODO: replace a name with a NamedCodeItem once Weiping is done, to + // avoid duplication of method names. +} lfVftable; + +// type record for cobol0 + + +typedef struct lfCobol0_16t { + unsigned short leaf; // LF_COBOL0_16t + CV_typ16_t type; // parent type record index + unsigned char data[CV_ZEROLEN]; +} lfCobol0_16t; + +typedef struct lfCobol0 { + unsigned short leaf; // LF_COBOL0 + CV_typ_t type; // parent type record index + unsigned char data[CV_ZEROLEN]; +} lfCobol0; + + + + +// type record for cobol1 + + +typedef struct lfCobol1 { + unsigned short leaf; // LF_COBOL1 + unsigned char data[CV_ZEROLEN]; +} lfCobol1; + + + + +// type record for basic array + + +typedef struct lfBArray_16t { + unsigned short leaf; // LF_BARRAY_16t + CV_typ16_t utype; // type index of underlying type +} lfBArray_16t; + +typedef struct lfBArray { + unsigned short leaf; // LF_BARRAY + CV_typ_t utype; // type index of underlying type +} lfBArray; + +// type record for assembler labels + + +typedef struct lfLabel { + unsigned short leaf; // LF_LABEL + unsigned short mode; // addressing mode of label +} lfLabel; + + + +// type record for dimensioned arrays + + +typedef struct lfDimArray_16t { + unsigned short leaf; // LF_DIMARRAY_16t + CV_typ16_t utype; // underlying type of the array + CV_typ16_t diminfo; // dimension information + unsigned char name[1]; // length prefixed name +} lfDimArray_16t; + +typedef struct lfDimArray { + unsigned short leaf; // LF_DIMARRAY + CV_typ_t utype; // underlying type of the array + CV_typ_t diminfo; // dimension information + unsigned char name[1]; // length prefixed name +} lfDimArray; + + + +// type record describing path to virtual function table + + +typedef struct lfVFTPath_16t { + unsigned short leaf; // LF_VFTPATH_16t + unsigned short count; // count of number of bases in path + CV_typ16_t base[1]; // bases from root to leaf +} lfVFTPath_16t; + +typedef struct lfVFTPath { + unsigned short leaf; // LF_VFTPATH + unsigned long count; // count of number of bases in path + CV_typ_t base[1]; // bases from root to leaf +} lfVFTPath; + + +// type record describing inclusion of precompiled types + + +typedef struct lfPreComp_16t { + unsigned short leaf; // LF_PRECOMP_16t + unsigned short start; // starting type index included + unsigned short count; // number of types in inclusion + unsigned long signature; // signature + unsigned char name[CV_ZEROLEN]; // length prefixed name of included type file +} lfPreComp_16t; + +typedef struct lfPreComp { + unsigned short leaf; // LF_PRECOMP + unsigned long start; // starting type index included + unsigned long count; // number of types in inclusion + unsigned long signature; // signature + unsigned char name[CV_ZEROLEN]; // length prefixed name of included type file +} lfPreComp; + + + +// type record describing end of precompiled types that can be +// included by another file + + +typedef struct lfEndPreComp { + unsigned short leaf; // LF_ENDPRECOMP + unsigned long signature; // signature +} lfEndPreComp; + + + + + +// type record for OEM definable type strings + + +typedef struct lfOEM_16t { + unsigned short leaf; // LF_OEM_16t + unsigned short cvOEM; // MS assigned OEM identified + unsigned short recOEM; // OEM assigned type identifier + unsigned short count; // count of type indices to follow + CV_typ16_t index[CV_ZEROLEN]; // array of type indices followed + // by OEM defined data +} lfOEM_16t; + +typedef struct lfOEM { + unsigned short leaf; // LF_OEM + unsigned short cvOEM; // MS assigned OEM identified + unsigned short recOEM; // OEM assigned type identifier + unsigned long count; // count of type indices to follow + CV_typ_t index[CV_ZEROLEN]; // array of type indices followed + // by OEM defined data +} lfOEM; + +#define OEM_MS_FORTRAN90 0xF090 +#define OEM_ODI 0x0010 +#define OEM_THOMSON_SOFTWARE 0x5453 +#define OEM_ODI_REC_BASELIST 0x0000 + +typedef struct lfOEM2 { + unsigned short leaf; // LF_OEM2 + unsigned char idOem[16]; // an oem ID (GUID) + unsigned long count; // count of type indices to follow + CV_typ_t index[CV_ZEROLEN]; // array of type indices followed + // by OEM defined data +} lfOEM2; + +// type record describing using of a type server + +typedef struct lfTypeServer { + unsigned short leaf; // LF_TYPESERVER + unsigned long signature; // signature + unsigned long age; // age of database used by this module + unsigned char name[CV_ZEROLEN]; // length prefixed name of PDB +} lfTypeServer; + +// type record describing using of a type server with v7 (GUID) signatures + +typedef struct lfTypeServer2 { + unsigned short leaf; // LF_TYPESERVER2 + SIG70 sig70; // guid signature + unsigned long age; // age of database used by this module + unsigned char name[CV_ZEROLEN]; // length prefixed name of PDB +} lfTypeServer2; + +// description of type records that can be referenced from +// type records referenced by symbols + + + +// type record for skip record + + +typedef struct lfSkip_16t { + unsigned short leaf; // LF_SKIP_16t + CV_typ16_t type; // next valid index + unsigned char data[CV_ZEROLEN]; // pad data +} lfSkip_16t; + +typedef struct lfSkip { + unsigned short leaf; // LF_SKIP + CV_typ_t type; // next valid index + unsigned char data[CV_ZEROLEN]; // pad data +} lfSkip; + + + +// argument list leaf + + +typedef struct lfArgList_16t { + unsigned short leaf; // LF_ARGLIST_16t + unsigned short count; // number of arguments + CV_typ16_t arg[CV_ZEROLEN]; // number of arguments +} lfArgList_16t; + +typedef struct lfArgList { + unsigned short leaf; // LF_ARGLIST, LF_SUBSTR_LIST + unsigned long count; // number of arguments + CV_typ_t arg[CV_ZEROLEN]; // number of arguments +} lfArgList; + + + + +// derived class list leaf + + +typedef struct lfDerived_16t { + unsigned short leaf; // LF_DERIVED_16t + unsigned short count; // number of arguments + CV_typ16_t drvdcls[CV_ZEROLEN]; // type indices of derived classes +} lfDerived_16t; + +typedef struct lfDerived { + unsigned short leaf; // LF_DERIVED + unsigned long count; // number of arguments + CV_typ_t drvdcls[CV_ZEROLEN]; // type indices of derived classes +} lfDerived; + + + + +// leaf for default arguments + + +typedef struct lfDefArg_16t { + unsigned short leaf; // LF_DEFARG_16t + CV_typ16_t type; // type of resulting expression + unsigned char expr[CV_ZEROLEN]; // length prefixed expression string +} lfDefArg_16t; + +typedef struct lfDefArg { + unsigned short leaf; // LF_DEFARG + CV_typ_t type; // type of resulting expression + unsigned char expr[CV_ZEROLEN]; // length prefixed expression string +} lfDefArg; + + + +// list leaf +// This list should no longer be used because the utilities cannot +// verify the contents of the list without knowing what type of list +// it is. New specific leaf indices should be used instead. + + +typedef struct lfList { + unsigned short leaf; // LF_LIST + char data[CV_ZEROLEN]; // data format specified by indexing type +} lfList; + + + + +// field list leaf +// This is the header leaf for a complex list of class and structure +// subfields. + + +typedef struct lfFieldList_16t { + unsigned short leaf; // LF_FIELDLIST_16t + char data[CV_ZEROLEN]; // field list sub lists +} lfFieldList_16t; + + +typedef struct lfFieldList { + unsigned short leaf; // LF_FIELDLIST + char data[CV_ZEROLEN]; // field list sub lists +} lfFieldList; + + + + + + + +// type record for non-static methods and friends in overloaded method list + +typedef struct mlMethod_16t { + CV_fldattr_t attr; // method attribute + CV_typ16_t index; // index to type record for procedure + unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if intro virtual +} mlMethod_16t; + +typedef struct mlMethod { + CV_fldattr_t attr; // method attribute + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t index; // index to type record for procedure + unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if intro virtual +} mlMethod; + + +typedef struct lfMethodList_16t { + unsigned short leaf; + unsigned char mList[CV_ZEROLEN]; // really a mlMethod_16t type +} lfMethodList_16t; + +typedef struct lfMethodList { + unsigned short leaf; + unsigned char mList[CV_ZEROLEN]; // really a mlMethod type +} lfMethodList; + + + + + +// type record for LF_BITFIELD + + +typedef struct lfBitfield_16t { + unsigned short leaf; // LF_BITFIELD_16t + unsigned char length; + unsigned char position; + CV_typ16_t type; // type of bitfield + +} lfBitfield_16t; + +typedef struct lfBitfield { + unsigned short leaf; // LF_BITFIELD + CV_typ_t type; // type of bitfield + unsigned char length; + unsigned char position; + +} lfBitfield; + + + + +// type record for dimensioned array with constant bounds + + +typedef struct lfDimCon_16t { + unsigned short leaf; // LF_DIMCONU_16t or LF_DIMCONLU_16t + unsigned short rank; // number of dimensions + CV_typ16_t typ; // type of index + unsigned char dim[CV_ZEROLEN]; // array of dimension information with + // either upper bounds or lower/upper bound +} lfDimCon_16t; + +typedef struct lfDimCon { + unsigned short leaf; // LF_DIMCONU or LF_DIMCONLU + CV_typ_t typ; // type of index + unsigned short rank; // number of dimensions + unsigned char dim[CV_ZEROLEN]; // array of dimension information with + // either upper bounds or lower/upper bound +} lfDimCon; + + + + +// type record for dimensioned array with variable bounds + + +typedef struct lfDimVar_16t { + unsigned short leaf; // LF_DIMVARU_16t or LF_DIMVARLU_16t + unsigned short rank; // number of dimensions + CV_typ16_t typ; // type of index + CV_typ16_t dim[CV_ZEROLEN]; // array of type indices for either + // variable upper bound or variable + // lower/upper bound. The referenced + // types must be LF_REFSYM or T_VOID +} lfDimVar_16t; + +typedef struct lfDimVar { + unsigned short leaf; // LF_DIMVARU or LF_DIMVARLU + unsigned long rank; // number of dimensions + CV_typ_t typ; // type of index + CV_typ_t dim[CV_ZEROLEN]; // array of type indices for either + // variable upper bound or variable + // lower/upper bound. The count of type + // indices is rank or rank*2 depending on + // whether it is LFDIMVARU or LF_DIMVARLU. + // The referenced types must be + // LF_REFSYM or T_VOID +} lfDimVar; + + + + +// type record for referenced symbol + + +typedef struct lfRefSym { + unsigned short leaf; // LF_REFSYM + unsigned char Sym[1]; // copy of referenced symbol record + // (including length) +} lfRefSym; + + + +// type record for generic HLSL type + + +typedef struct lfHLSL { + unsigned short leaf; // LF_HLSL + CV_typ_t subtype; // sub-type index, if any + unsigned short kind; // kind of built-in type from CV_builtin_e + unsigned short numprops : 4; // number of numeric properties + unsigned short unused : 12; // padding, must be 0 + unsigned char data[CV_ZEROLEN]; // variable-length array of numeric properties + // followed by byte size +} lfHLSL; + + + + +// type record for a generalized built-in type modifier + + +typedef struct lfModifierEx { + unsigned short leaf; // LF_MODIFIER_EX + CV_typ_t type; // type being modified + unsigned short count; // count of modifier values + unsigned short mods[CV_ZEROLEN]; // modifiers from CV_modifier_e +} lfModifierEx; + + + + +/** the following are numeric leaves. They are used to indicate the + * size of the following variable length data. When the numeric + * data is a single byte less than 0x8000, then the data is output + * directly. If the data is more the 0x8000 or is a negative value, + * then the data is preceeded by the proper index. + */ + + + +// signed character leaf + +typedef struct lfChar { + unsigned short leaf; // LF_CHAR + signed char val; // signed 8-bit value +} lfChar; + + + + +// signed short leaf + +typedef struct lfShort { + unsigned short leaf; // LF_SHORT + short val; // signed 16-bit value +} lfShort; + + + + +// unsigned short leaf + +typedef struct lfUShort { + unsigned short leaf; // LF_unsigned short + unsigned short val; // unsigned 16-bit value +} lfUShort; + + + + +// signed long leaf + +typedef struct lfLong { + unsigned short leaf; // LF_LONG + long val; // signed 32-bit value +} lfLong; + + + + +// unsigned long leaf + +typedef struct lfULong { + unsigned short leaf; // LF_ULONG + unsigned long val; // unsigned 32-bit value +} lfULong; + + + + +// signed quad leaf + +typedef struct lfQuad { + unsigned short leaf; // LF_QUAD + unsigned char val[8]; // signed 64-bit value +} lfQuad; + + + + +// unsigned quad leaf + +typedef struct lfUQuad { + unsigned short leaf; // LF_UQUAD + unsigned char val[8]; // unsigned 64-bit value +} lfUQuad; + + +// signed int128 leaf + +typedef struct lfOct { + unsigned short leaf; // LF_OCT + unsigned char val[16]; // signed 128-bit value +} lfOct; + +// unsigned int128 leaf + +typedef struct lfUOct { + unsigned short leaf; // LF_UOCT + unsigned char val[16]; // unsigned 128-bit value +} lfUOct; + + + + +// real 16-bit leaf + +typedef struct lfReal16 { + unsigned short leaf; // LF_REAL16 + unsigned short val; // 16-bit real value +} lfReal16; + + + + +// real 32-bit leaf + +typedef struct lfReal32 { + unsigned short leaf; // LF_REAL32 + float val; // 32-bit real value +} lfReal32; + + + + +// real 48-bit leaf + +typedef struct lfReal48 { + unsigned short leaf; // LF_REAL48 + unsigned char val[6]; // 48-bit real value +} lfReal48; + + + + +// real 64-bit leaf + +typedef struct lfReal64 { + unsigned short leaf; // LF_REAL64 + double val; // 64-bit real value +} lfReal64; + + + + +// real 80-bit leaf + +typedef struct lfReal80 { + unsigned short leaf; // LF_REAL80 + FLOAT10 val; // real 80-bit value +} lfReal80; + + + + +// real 128-bit leaf + +typedef struct lfReal128 { + unsigned short leaf; // LF_REAL128 + char val[16]; // real 128-bit value +} lfReal128; + + + + +// complex 32-bit leaf + +typedef struct lfCmplx32 { + unsigned short leaf; // LF_COMPLEX32 + float val_real; // real component + float val_imag; // imaginary component +} lfCmplx32; + + + + +// complex 64-bit leaf + +typedef struct lfCmplx64 { + unsigned short leaf; // LF_COMPLEX64 + double val_real; // real component + double val_imag; // imaginary component +} flCmplx64; + + + + +// complex 80-bit leaf + +typedef struct lfCmplx80 { + unsigned short leaf; // LF_COMPLEX80 + FLOAT10 val_real; // real component + FLOAT10 val_imag; // imaginary component +} lfCmplx80; + + + + +// complex 128-bit leaf + +typedef struct lfCmplx128 { + unsigned short leaf; // LF_COMPLEX128 + char val_real[16]; // real component + char val_imag[16]; // imaginary component +} lfCmplx128; + + + +// variable length numeric field + +typedef struct lfVarString { + unsigned short leaf; // LF_VARSTRING + unsigned short len; // length of value in bytes + unsigned char value[CV_ZEROLEN]; // value +} lfVarString; + +//*********************************************************************** + + +// index leaf - contains type index of another leaf +// a major use of this leaf is to allow the compilers to emit a +// long complex list (LF_FIELD) in smaller pieces. + +typedef struct lfIndex_16t { + unsigned short leaf; // LF_INDEX_16t + CV_typ16_t index; // type index of referenced leaf +} lfIndex_16t; + +typedef struct lfIndex { + unsigned short leaf; // LF_INDEX + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t index; // type index of referenced leaf +} lfIndex; + + +// subfield record for base class field + +typedef struct lfBClass_16t { + unsigned short leaf; // LF_BCLASS_16t + CV_typ16_t index; // type index of base class + CV_fldattr_t attr; // attribute + unsigned char offset[CV_ZEROLEN]; // variable length offset of base within class +} lfBClass_16t; + +typedef struct lfBClass { + unsigned short leaf; // LF_BCLASS, LF_BINTERFACE + CV_fldattr_t attr; // attribute + CV_typ_t index; // type index of base class + unsigned char offset[CV_ZEROLEN]; // variable length offset of base within class +} lfBClass; +typedef lfBClass lfBInterface; + + + + +// subfield record for direct and indirect virtual base class field + +typedef struct lfVBClass_16t { + unsigned short leaf; // LF_VBCLASS_16t | LV_IVBCLASS_16t + CV_typ16_t index; // type index of direct virtual base class + CV_typ16_t vbptr; // type index of virtual base pointer + CV_fldattr_t attr; // attribute + unsigned char vbpoff[CV_ZEROLEN]; // virtual base pointer offset from address point + // followed by virtual base offset from vbtable +} lfVBClass_16t; + +typedef struct lfVBClass { + unsigned short leaf; // LF_VBCLASS | LV_IVBCLASS + CV_fldattr_t attr; // attribute + CV_typ_t index; // type index of direct virtual base class + CV_typ_t vbptr; // type index of virtual base pointer + unsigned char vbpoff[CV_ZEROLEN]; // virtual base pointer offset from address point + // followed by virtual base offset from vbtable +} lfVBClass; + + + + + +// subfield record for friend class + + +typedef struct lfFriendCls_16t { + unsigned short leaf; // LF_FRIENDCLS_16t + CV_typ16_t index; // index to type record of friend class +} lfFriendCls_16t; + +typedef struct lfFriendCls { + unsigned short leaf; // LF_FRIENDCLS + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t index; // index to type record of friend class +} lfFriendCls; + + + + + +// subfield record for friend function + + +typedef struct lfFriendFcn_16t { + unsigned short leaf; // LF_FRIENDFCN_16t + CV_typ16_t index; // index to type record of friend function + unsigned char Name[1]; // name of friend function +} lfFriendFcn_16t; + +typedef struct lfFriendFcn { + unsigned short leaf; // LF_FRIENDFCN + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t index; // index to type record of friend function + unsigned char Name[1]; // name of friend function +} lfFriendFcn; + + + +// subfield record for non-static data members + +typedef struct lfMember_16t { + unsigned short leaf; // LF_MEMBER_16t + CV_typ16_t index; // index of type record for field + CV_fldattr_t attr; // attribute mask + unsigned char offset[CV_ZEROLEN]; // variable length offset of field followed + // by length prefixed name of field +} lfMember_16t; + +typedef struct lfMember { + unsigned short leaf; // LF_MEMBER + CV_fldattr_t attr; // attribute mask + CV_typ_t index; // index of type record for field + unsigned char offset[CV_ZEROLEN]; // variable length offset of field followed + // by length prefixed name of field +} lfMember; + + + +// type record for static data members + +typedef struct lfSTMember_16t { + unsigned short leaf; // LF_STMEMBER_16t + CV_typ16_t index; // index of type record for field + CV_fldattr_t attr; // attribute mask + unsigned char Name[1]; // length prefixed name of field +} lfSTMember_16t; + +typedef struct lfSTMember { + unsigned short leaf; // LF_STMEMBER + CV_fldattr_t attr; // attribute mask + CV_typ_t index; // index of type record for field + unsigned char Name[1]; // length prefixed name of field +} lfSTMember; + + + +// subfield record for virtual function table pointer + +typedef struct lfVFuncTab_16t { + unsigned short leaf; // LF_VFUNCTAB_16t + CV_typ16_t type; // type index of pointer +} lfVFuncTab_16t; + +typedef struct lfVFuncTab { + unsigned short leaf; // LF_VFUNCTAB + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t type; // type index of pointer +} lfVFuncTab; + + + +// subfield record for virtual function table pointer with offset + +typedef struct lfVFuncOff_16t { + unsigned short leaf; // LF_VFUNCOFF_16t + CV_typ16_t type; // type index of pointer + CV_off32_t offset; // offset of virtual function table pointer +} lfVFuncOff_16t; + +typedef struct lfVFuncOff { + unsigned short leaf; // LF_VFUNCOFF + _2BYTEPAD pad0; // internal padding, must be 0. + CV_typ_t type; // type index of pointer + CV_off32_t offset; // offset of virtual function table pointer +} lfVFuncOff; + + + +// subfield record for overloaded method list + + +typedef struct lfMethod_16t { + unsigned short leaf; // LF_METHOD_16t + unsigned short count; // number of occurrences of function + CV_typ16_t mList; // index to LF_METHODLIST record + unsigned char Name[1]; // length prefixed name of method +} lfMethod_16t; + +typedef struct lfMethod { + unsigned short leaf; // LF_METHOD + unsigned short count; // number of occurrences of function + CV_typ_t mList; // index to LF_METHODLIST record + unsigned char Name[1]; // length prefixed name of method +} lfMethod; + + + +// subfield record for nonoverloaded method + + +typedef struct lfOneMethod_16t { + unsigned short leaf; // LF_ONEMETHOD_16t + CV_fldattr_t attr; // method attribute + CV_typ16_t index; // index to type record for procedure + unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if + // intro virtual followed by + // length prefixed name of method +} lfOneMethod_16t; + +typedef struct lfOneMethod { + unsigned short leaf; // LF_ONEMETHOD + CV_fldattr_t attr; // method attribute + CV_typ_t index; // index to type record for procedure + unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if + // intro virtual followed by + // length prefixed name of method +} lfOneMethod; + + +// subfield record for enumerate + +typedef struct lfEnumerate { + unsigned short leaf; // LF_ENUMERATE + CV_fldattr_t attr; // access + unsigned char value[CV_ZEROLEN]; // variable length value field followed + // by length prefixed name +} lfEnumerate; + + +// type record for nested (scoped) type definition + +typedef struct lfNestType_16t { + unsigned short leaf; // LF_NESTTYPE_16t + CV_typ16_t index; // index of nested type definition + unsigned char Name[1]; // length prefixed type name +} lfNestType_16t; + +typedef struct lfNestType { + unsigned short leaf; // LF_NESTTYPE + _2BYTEPAD pad0; // internal padding, must be 0 + CV_typ_t index; // index of nested type definition + unsigned char Name[1]; // length prefixed type name +} lfNestType; + +// type record for nested (scoped) type definition, with attributes +// new records for vC v5.0, no need to have 16-bit ti versions. + +typedef struct lfNestTypeEx { + unsigned short leaf; // LF_NESTTYPEEX + CV_fldattr_t attr; // member access + CV_typ_t index; // index of nested type definition + unsigned char Name[1]; // length prefixed type name +} lfNestTypeEx; + +// type record for modifications to members + +typedef struct lfMemberModify { + unsigned short leaf; // LF_MEMBERMODIFY + CV_fldattr_t attr; // the new attributes + CV_typ_t index; // index of base class type definition + unsigned char Name[1]; // length prefixed member name +} lfMemberModify; + +// type record for pad leaf + +typedef struct lfPad { + unsigned char leaf; +} SYM_PAD; + + + +// Symbol definitions + +typedef enum SYM_ENUM_e { + S_COMPILE = 0x0001, // Compile flags symbol + S_REGISTER_16t = 0x0002, // Register variable + S_CONSTANT_16t = 0x0003, // constant symbol + S_UDT_16t = 0x0004, // User defined type + S_SSEARCH = 0x0005, // Start Search + S_END = 0x0006, // Block, procedure, "with" or thunk end + S_SKIP = 0x0007, // Reserve symbol space in $$Symbols table + S_CVRESERVE = 0x0008, // Reserved symbol for CV internal use + S_OBJNAME_ST = 0x0009, // path to object file name + S_ENDARG = 0x000a, // end of argument/return list + S_COBOLUDT_16t = 0x000b, // special UDT for cobol that does not symbol pack + S_MANYREG_16t = 0x000c, // multiple register variable + S_RETURN = 0x000d, // return description symbol + S_ENTRYTHIS = 0x000e, // description of this pointer on entry + + S_BPREL16 = 0x0100, // BP-relative + S_LDATA16 = 0x0101, // Module-local symbol + S_GDATA16 = 0x0102, // Global data symbol + S_PUB16 = 0x0103, // a public symbol + S_LPROC16 = 0x0104, // Local procedure start + S_GPROC16 = 0x0105, // Global procedure start + S_THUNK16 = 0x0106, // Thunk Start + S_BLOCK16 = 0x0107, // block start + S_WITH16 = 0x0108, // with start + S_LABEL16 = 0x0109, // code label + S_CEXMODEL16 = 0x010a, // change execution model + S_VFTABLE16 = 0x010b, // address of virtual function table + S_REGREL16 = 0x010c, // register relative address + + S_BPREL32_16t = 0x0200, // BP-relative + S_LDATA32_16t = 0x0201, // Module-local symbol + S_GDATA32_16t = 0x0202, // Global data symbol + S_PUB32_16t = 0x0203, // a public symbol (CV internal reserved) + S_LPROC32_16t = 0x0204, // Local procedure start + S_GPROC32_16t = 0x0205, // Global procedure start + S_THUNK32_ST = 0x0206, // Thunk Start + S_BLOCK32_ST = 0x0207, // block start + S_WITH32_ST = 0x0208, // with start + S_LABEL32_ST = 0x0209, // code label + S_CEXMODEL32 = 0x020a, // change execution model + S_VFTABLE32_16t = 0x020b, // address of virtual function table + S_REGREL32_16t = 0x020c, // register relative address + S_LTHREAD32_16t = 0x020d, // local thread storage + S_GTHREAD32_16t = 0x020e, // global thread storage + S_SLINK32 = 0x020f, // static link for MIPS EH implementation + + S_LPROCMIPS_16t = 0x0300, // Local procedure start + S_GPROCMIPS_16t = 0x0301, // Global procedure start + + // if these ref symbols have names following then the names are in ST format + S_PROCREF_ST = 0x0400, // Reference to a procedure + S_DATAREF_ST = 0x0401, // Reference to data + S_ALIGN = 0x0402, // Used for page alignment of symbols + + S_LPROCREF_ST = 0x0403, // Local Reference to a procedure + S_OEM = 0x0404, // OEM defined symbol + + // sym records with 32-bit types embedded instead of 16-bit + // all have 0x1000 bit set for easy identification + // only do the 32-bit target versions since we don't really + // care about 16-bit ones anymore. + S_TI16_MAX = 0x1000, + + S_REGISTER_ST = 0x1001, // Register variable + S_CONSTANT_ST = 0x1002, // constant symbol + S_UDT_ST = 0x1003, // User defined type + S_COBOLUDT_ST = 0x1004, // special UDT for cobol that does not symbol pack + S_MANYREG_ST = 0x1005, // multiple register variable + S_BPREL32_ST = 0x1006, // BP-relative + S_LDATA32_ST = 0x1007, // Module-local symbol + S_GDATA32_ST = 0x1008, // Global data symbol + S_PUB32_ST = 0x1009, // a public symbol (CV internal reserved) + S_LPROC32_ST = 0x100a, // Local procedure start + S_GPROC32_ST = 0x100b, // Global procedure start + S_VFTABLE32 = 0x100c, // address of virtual function table + S_REGREL32_ST = 0x100d, // register relative address + S_LTHREAD32_ST = 0x100e, // local thread storage + S_GTHREAD32_ST = 0x100f, // global thread storage + + S_LPROCMIPS_ST = 0x1010, // Local procedure start + S_GPROCMIPS_ST = 0x1011, // Global procedure start + + S_FRAMEPROC = 0x1012, // extra frame and proc information + S_COMPILE2_ST = 0x1013, // extended compile flags and info + + // new symbols necessary for 16-bit enumerates of IA64 registers + // and IA64 specific symbols + + S_MANYREG2_ST = 0x1014, // multiple register variable + S_LPROCIA64_ST = 0x1015, // Local procedure start (IA64) + S_GPROCIA64_ST = 0x1016, // Global procedure start (IA64) + + // Local symbols for IL + S_LOCALSLOT_ST = 0x1017, // local IL sym with field for local slot index + S_PARAMSLOT_ST = 0x1018, // local IL sym with field for parameter slot index + + S_ANNOTATION = 0x1019, // Annotation string literals + + // symbols to support managed code debugging + S_GMANPROC_ST = 0x101a, // Global proc + S_LMANPROC_ST = 0x101b, // Local proc + S_RESERVED1 = 0x101c, // reserved + S_RESERVED2 = 0x101d, // reserved + S_RESERVED3 = 0x101e, // reserved + S_RESERVED4 = 0x101f, // reserved + S_LMANDATA_ST = 0x1020, + S_GMANDATA_ST = 0x1021, + S_MANFRAMEREL_ST= 0x1022, + S_MANREGISTER_ST= 0x1023, + S_MANSLOT_ST = 0x1024, + S_MANMANYREG_ST = 0x1025, + S_MANREGREL_ST = 0x1026, + S_MANMANYREG2_ST= 0x1027, + S_MANTYPREF = 0x1028, // Index for type referenced by name from metadata + S_UNAMESPACE_ST = 0x1029, // Using namespace + + // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings. + S_ST_MAX = 0x1100, // starting point for SZ name symbols + + S_OBJNAME = 0x1101, // path to object file name + S_THUNK32 = 0x1102, // Thunk Start + S_BLOCK32 = 0x1103, // block start + S_WITH32 = 0x1104, // with start + S_LABEL32 = 0x1105, // code label + S_REGISTER = 0x1106, // Register variable + S_CONSTANT = 0x1107, // constant symbol + S_UDT = 0x1108, // User defined type + S_COBOLUDT = 0x1109, // special UDT for cobol that does not symbol pack + S_MANYREG = 0x110a, // multiple register variable + S_BPREL32 = 0x110b, // BP-relative + S_LDATA32 = 0x110c, // Module-local symbol + S_GDATA32 = 0x110d, // Global data symbol + S_PUB32 = 0x110e, // a public symbol (CV internal reserved) + S_LPROC32 = 0x110f, // Local procedure start + S_GPROC32 = 0x1110, // Global procedure start + S_REGREL32 = 0x1111, // register relative address + S_LTHREAD32 = 0x1112, // local thread storage + S_GTHREAD32 = 0x1113, // global thread storage + + S_LPROCMIPS = 0x1114, // Local procedure start + S_GPROCMIPS = 0x1115, // Global procedure start + S_COMPILE2 = 0x1116, // extended compile flags and info + S_MANYREG2 = 0x1117, // multiple register variable + S_LPROCIA64 = 0x1118, // Local procedure start (IA64) + S_GPROCIA64 = 0x1119, // Global procedure start (IA64) + S_LOCALSLOT = 0x111a, // local IL sym with field for local slot index + S_SLOT = S_LOCALSLOT, // alias for LOCALSLOT + S_PARAMSLOT = 0x111b, // local IL sym with field for parameter slot index + + // symbols to support managed code debugging + S_LMANDATA = 0x111c, + S_GMANDATA = 0x111d, + S_MANFRAMEREL = 0x111e, + S_MANREGISTER = 0x111f, + S_MANSLOT = 0x1120, + S_MANMANYREG = 0x1121, + S_MANREGREL = 0x1122, + S_MANMANYREG2 = 0x1123, + S_UNAMESPACE = 0x1124, // Using namespace + + // ref symbols with name fields + S_PROCREF = 0x1125, // Reference to a procedure + S_DATAREF = 0x1126, // Reference to data + S_LPROCREF = 0x1127, // Local Reference to a procedure + S_ANNOTATIONREF = 0x1128, // Reference to an S_ANNOTATION symbol + S_TOKENREF = 0x1129, // Reference to one of the many MANPROCSYM's + + // continuation of managed symbols + S_GMANPROC = 0x112a, // Global proc + S_LMANPROC = 0x112b, // Local proc + + // short, light-weight thunks + S_TRAMPOLINE = 0x112c, // trampoline thunks + S_MANCONSTANT = 0x112d, // constants with metadata type info + + // native attributed local/parms + S_ATTR_FRAMEREL = 0x112e, // relative to virtual frame ptr + S_ATTR_REGISTER = 0x112f, // stored in a register + S_ATTR_REGREL = 0x1130, // relative to register (alternate frame ptr) + S_ATTR_MANYREG = 0x1131, // stored in >1 register + + // Separated code (from the compiler) support + S_SEPCODE = 0x1132, + + S_LOCAL_2005 = 0x1133, // defines a local symbol in optimized code + S_DEFRANGE_2005 = 0x1134, // defines a single range of addresses in which symbol can be evaluated + S_DEFRANGE2_2005 = 0x1135, // defines ranges of addresses in which symbol can be evaluated + + S_SECTION = 0x1136, // A COFF section in a PE executable + S_COFFGROUP = 0x1137, // A COFF group + S_EXPORT = 0x1138, // A export + + S_CALLSITEINFO = 0x1139, // Indirect call site information + S_FRAMECOOKIE = 0x113a, // Security cookie information + + S_DISCARDED = 0x113b, // Discarded by LINK /OPT:REF (experimental, see richards) + + S_COMPILE3 = 0x113c, // Replacement for S_COMPILE2 + S_ENVBLOCK = 0x113d, // Environment block split off from S_COMPILE2 + + S_LOCAL = 0x113e, // defines a local symbol in optimized code + S_DEFRANGE = 0x113f, // defines a single range of addresses in which symbol can be evaluated + S_DEFRANGE_SUBFIELD = 0x1140, // ranges for a subfield + + S_DEFRANGE_REGISTER = 0x1141, // ranges for en-registered symbol + S_DEFRANGE_FRAMEPOINTER_REL = 0x1142, // range for stack symbol. + S_DEFRANGE_SUBFIELD_REGISTER = 0x1143, // ranges for en-registered field of symbol + S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, // range for stack symbol span valid full scope of function body, gap might apply. + S_DEFRANGE_REGISTER_REL = 0x1145, // range for symbol address as register + offset. + + // S_PROC symbols that reference ID instead of type + S_LPROC32_ID = 0x1146, + S_GPROC32_ID = 0x1147, + S_LPROCMIPS_ID = 0x1148, + S_GPROCMIPS_ID = 0x1149, + S_LPROCIA64_ID = 0x114a, + S_GPROCIA64_ID = 0x114b, + + S_BUILDINFO = 0x114c, // build information. + S_INLINESITE = 0x114d, // inlined function callsite. + S_INLINESITE_END = 0x114e, + S_PROC_ID_END = 0x114f, + + S_DEFRANGE_HLSL = 0x1150, + S_GDATA_HLSL = 0x1151, + S_LDATA_HLSL = 0x1152, + + S_FILESTATIC = 0x1153, + +#if defined(CC_DP_CXX) && CC_DP_CXX + + S_LOCAL_DPC_GROUPSHARED = 0x1154, // DPC groupshared variable + S_LPROC32_DPC = 0x1155, // DPC local procedure start + S_LPROC32_DPC_ID = 0x1156, + S_DEFRANGE_DPC_PTR_TAG = 0x1157, // DPC pointer tag definition range + S_DPC_SYM_TAG_MAP = 0x1158, // DPC pointer tag value to symbol record map + +#endif // CC_DP_CXX + + S_ARMSWITCHTABLE = 0x1159, + S_CALLEES = 0x115a, + S_CALLERS = 0x115b, + S_POGODATA = 0x115c, + S_INLINESITE2 = 0x115d, // extended inline site information + + S_HEAPALLOCSITE = 0x115e, // heap allocation site + + S_MOD_TYPEREF = 0x115f, // only generated at link time + + S_REF_MINIPDB = 0x1160, // only generated at link time for mini PDB + S_PDBMAP = 0x1161, // only generated at link time for mini PDB + + S_GDATA_HLSL32 = 0x1162, + S_LDATA_HLSL32 = 0x1163, + + S_GDATA_HLSL32_EX = 0x1164, + S_LDATA_HLSL32_EX = 0x1165, + + S_RECTYPE_MAX, // one greater than last + S_RECTYPE_LAST = S_RECTYPE_MAX - 1, + S_RECTYPE_PAD = S_RECTYPE_MAX + 0x100 // Used *only* to verify symbol record types so that current PDB code can potentially read + // future PDBs (assuming no format change, etc). + +} SYM_ENUM_e; + + +// enum describing compile flag ambient data model + + +typedef enum CV_CFL_DATA { + CV_CFL_DNEAR = 0x00, + CV_CFL_DFAR = 0x01, + CV_CFL_DHUGE = 0x02 +} CV_CFL_DATA; + + + + +// enum describing compile flag ambiant code model + + +typedef enum CV_CFL_CODE_e { + CV_CFL_CNEAR = 0x00, + CV_CFL_CFAR = 0x01, + CV_CFL_CHUGE = 0x02 +} CV_CFL_CODE_e; + + + + +// enum describing compile flag target floating point package + +typedef enum CV_CFL_FPKG_e { + CV_CFL_NDP = 0x00, + CV_CFL_EMU = 0x01, + CV_CFL_ALT = 0x02 +} CV_CFL_FPKG_e; + + +// enum describing function return method + + +typedef struct CV_PROCFLAGS { + union { + unsigned char bAll; + unsigned char grfAll; + struct { + unsigned char CV_PFLAG_NOFPO :1; // frame pointer present + unsigned char CV_PFLAG_INT :1; // interrupt return + unsigned char CV_PFLAG_FAR :1; // far return + unsigned char CV_PFLAG_NEVER :1; // function does not return + unsigned char CV_PFLAG_NOTREACHED:1; // label isn't fallen into + unsigned char CV_PFLAG_CUST_CALL :1; // custom calling convention + unsigned char CV_PFLAG_NOINLINE :1; // function marked as noinline + unsigned char CV_PFLAG_OPTDBGINFO:1; // function has debug information for optimized code + }; + }; +} CV_PROCFLAGS; + +// Extended proc flags +// +typedef struct CV_EXPROCFLAGS { + CV_PROCFLAGS cvpf; + union { + unsigned char grfAll; + struct { + unsigned char __reserved_byte :8; // must be zero + }; + }; +} CV_EXPROCFLAGS; + +// local variable flags +typedef struct CV_LVARFLAGS { + unsigned short fIsParam :1; // variable is a parameter + unsigned short fAddrTaken :1; // address is taken + unsigned short fCompGenx :1; // variable is compiler generated + unsigned short fIsAggregate :1; // the symbol is splitted in temporaries, + // which are treated by compiler as + // independent entities + unsigned short fIsAggregated :1; // Counterpart of fIsAggregate - tells + // that it is a part of a fIsAggregate symbol + unsigned short fIsAliased :1; // variable has multiple simultaneous lifetimes + unsigned short fIsAlias :1; // represents one of the multiple simultaneous lifetimes + unsigned short fIsRetValue :1; // represents a function return value + unsigned short fIsOptimizedOut :1; // variable has no lifetimes + unsigned short fIsEnregGlob :1; // variable is an enregistered global + unsigned short fIsEnregStat :1; // variable is an enregistered static + + unsigned short unused :5; // must be zero + +} CV_LVARFLAGS; + +// extended attributes common to all local variables +typedef struct CV_lvar_attr { + CV_uoff32_t off; // first code address where var is live + unsigned short seg; + CV_LVARFLAGS flags; // local var flags +} CV_lvar_attr; + +// This is max length of a lexical linear IP range. +// The upper number are reserved for seeded and flow based range + +#define CV_LEXICAL_RANGE_MAX 0xF000 + +// represents an address range, used for optimized code debug info + +typedef struct CV_LVAR_ADDR_RANGE { // defines a range of addresses + CV_uoff32_t offStart; + unsigned short isectStart; + unsigned short cbRange; +} CV_LVAR_ADDR_RANGE; + +// Represents the holes in overall address range, all address is pre-bbt. +// it is for compress and reduce the amount of relocations need. + +typedef struct CV_LVAR_ADDR_GAP { + unsigned short gapStartOffset; // relative offset from the beginning of the live range. + unsigned short cbRange; // length of this gap. +} CV_LVAR_ADDR_GAP; + +#if defined(CC_DP_CXX) && CC_DP_CXX + +// Represents a mapping from a DPC pointer tag value to the corresponding symbol record +typedef struct CV_DPC_SYM_TAG_MAP_ENTRY { + unsigned int tagValue; // address taken symbol's pointer tag value. + CV_off32_t symRecordOffset; // offset of the symbol record from the S_LPROC32_DPC record it is nested within +} CV_DPC_SYM_TAG_MAP_ENTRY; + +#endif // CC_DP_CXX + +// enum describing function data return method + +typedef enum CV_GENERIC_STYLE_e { + CV_GENERIC_VOID = 0x00, // void return type + CV_GENERIC_REG = 0x01, // return data is in registers + CV_GENERIC_ICAN = 0x02, // indirect caller allocated near + CV_GENERIC_ICAF = 0x03, // indirect caller allocated far + CV_GENERIC_IRAN = 0x04, // indirect returnee allocated near + CV_GENERIC_IRAF = 0x05, // indirect returnee allocated far + CV_GENERIC_UNUSED = 0x06 // first unused +} CV_GENERIC_STYLE_e; + + +typedef struct CV_GENERIC_FLAG { + unsigned short cstyle :1; // true push varargs right to left + unsigned short rsclean :1; // true if returnee stack cleanup + unsigned short unused :14; // unused +} CV_GENERIC_FLAG; + + +// flag bitfields for separated code attributes + +typedef struct CV_SEPCODEFLAGS { + unsigned long fIsLexicalScope : 1; // S_SEPCODE doubles as lexical scope + unsigned long fReturnsToParent : 1; // code frag returns to parent + unsigned long pad : 30; // must be zero +} CV_SEPCODEFLAGS; + +// Generic layout for symbol records + +typedef struct SYMTYPE { + unsigned short reclen; // Record length + unsigned short rectyp; // Record type + char data[CV_ZEROLEN]; +} SYMTYPE; + +__INLINE SYMTYPE *NextSym (SYMTYPE * pSym) { + return (SYMTYPE *) ((char *)pSym + pSym->reclen + sizeof(unsigned short)); +} + +// non-model specific symbol types + + + +typedef struct REGSYM_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REGISTER_16t + CV_typ16_t typind; // Type index + unsigned short reg; // register enumerate + unsigned char name[1]; // Length-prefixed name +} REGSYM_16t; + +typedef struct REGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REGISTER + CV_typ_t typind; // Type index or Metadata token + unsigned short reg; // register enumerate + unsigned char name[1]; // Length-prefixed name +} REGSYM; + +typedef struct ATTRREGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANREGISTER | S_ATTR_REGISTER + CV_typ_t typind; // Type index or Metadata token + CV_lvar_attr attr; // local var attributes + unsigned short reg; // register enumerate + unsigned char name[1]; // Length-prefixed name +} ATTRREGSYM; + +typedef struct MANYREGSYM_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANYREG_16t + CV_typ16_t typind; // Type index + unsigned char count; // count of number of registers + unsigned char reg[1]; // count register enumerates followed by + // length-prefixed name. Registers are + // most significant first. +} MANYREGSYM_16t; + +typedef struct MANYREGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANYREG + CV_typ_t typind; // Type index or metadata token + unsigned char count; // count of number of registers + unsigned char reg[1]; // count register enumerates followed by + // length-prefixed name. Registers are + // most significant first. +} MANYREGSYM; + +typedef struct MANYREGSYM2 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANYREG2 + CV_typ_t typind; // Type index or metadata token + unsigned short count; // count of number of registers + unsigned short reg[1]; // count register enumerates followed by + // length-prefixed name. Registers are + // most significant first. +} MANYREGSYM2; + +typedef struct ATTRMANYREGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANMANYREG + CV_typ_t typind; // Type index or metadata token + CV_lvar_attr attr; // local var attributes + unsigned char count; // count of number of registers + unsigned char reg[1]; // count register enumerates followed by + // length-prefixed name. Registers are + // most significant first. + unsigned char name[CV_ZEROLEN]; // utf-8 encoded zero terminate name +} ATTRMANYREGSYM; + +typedef struct ATTRMANYREGSYM2 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANMANYREG2 | S_ATTR_MANYREG + CV_typ_t typind; // Type index or metadata token + CV_lvar_attr attr; // local var attributes + unsigned short count; // count of number of registers + unsigned short reg[1]; // count register enumerates followed by + // length-prefixed name. Registers are + // most significant first. + unsigned char name[CV_ZEROLEN]; // utf-8 encoded zero terminate name +} ATTRMANYREGSYM2; + +typedef struct CONSTSYM_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CONSTANT_16t + CV_typ16_t typind; // Type index (containing enum if enumerate) + unsigned short value; // numeric leaf containing value + unsigned char name[CV_ZEROLEN]; // Length-prefixed name +} CONSTSYM_16t; + +typedef struct CONSTSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CONSTANT or S_MANCONSTANT + CV_typ_t typind; // Type index (containing enum if enumerate) or metadata token + unsigned short value; // numeric leaf containing value + unsigned char name[CV_ZEROLEN]; // Length-prefixed name +} CONSTSYM; + + +typedef struct UDTSYM_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_UDT_16t | S_COBOLUDT_16t + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} UDTSYM_16t; + + +typedef struct UDTSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_UDT | S_COBOLUDT + CV_typ_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} UDTSYM; + +typedef struct MANTYPREF { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANTYPREF + CV_typ_t typind; // Type index +} MANTYPREF; + +typedef struct SEARCHSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_SSEARCH + unsigned long startsym; // offset of the procedure + unsigned short seg; // segment of symbol +} SEARCHSYM; + + +typedef struct CFLAGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_COMPILE + unsigned char machine; // target processor + struct { + unsigned char language :8; // language index + unsigned char pcode :1; // true if pcode present + unsigned char floatprec :2; // floating precision + unsigned char floatpkg :2; // float package + unsigned char ambdata :3; // ambient data model + unsigned char ambcode :3; // ambient code model + unsigned char mode32 :1; // true if compiled 32 bit mode + unsigned char pad :4; // reserved + } flags; + unsigned char ver[1]; // Length-prefixed compiler version string +} CFLAGSYM; + + +typedef struct COMPILESYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_COMPILE2 + struct { + unsigned long iLanguage : 8; // language index + unsigned long fEC : 1; // compiled for E/C + unsigned long fNoDbgInfo : 1; // not compiled with debug info + unsigned long fLTCG : 1; // compiled with LTCG + unsigned long fNoDataAlign : 1; // compiled with -Bzalign + unsigned long fManagedPresent : 1; // managed code/data present + unsigned long fSecurityChecks : 1; // compiled with /GS + unsigned long fHotPatch : 1; // compiled with /hotpatch + unsigned long fCVTCIL : 1; // converted with CVTCIL + unsigned long fMSILModule : 1; // MSIL netmodule + unsigned long pad : 15; // reserved, must be 0 + } flags; + unsigned short machine; // target processor + unsigned short verFEMajor; // front end major version # + unsigned short verFEMinor; // front end minor version # + unsigned short verFEBuild; // front end build version # + unsigned short verMajor; // back end major version # + unsigned short verMinor; // back end minor version # + unsigned short verBuild; // back end build version # + unsigned char verSt[1]; // Length-prefixed compiler version string, followed + // by an optional block of zero terminated strings + // terminated with a double zero. +} COMPILESYM; + +typedef struct COMPILESYM3 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_COMPILE3 + struct { + unsigned long iLanguage : 8; // language index + unsigned long fEC : 1; // compiled for E/C + unsigned long fNoDbgInfo : 1; // not compiled with debug info + unsigned long fLTCG : 1; // compiled with LTCG + unsigned long fNoDataAlign : 1; // compiled with -Bzalign + unsigned long fManagedPresent : 1; // managed code/data present + unsigned long fSecurityChecks : 1; // compiled with /GS + unsigned long fHotPatch : 1; // compiled with /hotpatch + unsigned long fCVTCIL : 1; // converted with CVTCIL + unsigned long fMSILModule : 1; // MSIL netmodule + unsigned long fSdl : 1; // compiled with /sdl + unsigned long fPGO : 1; // compiled with /ltcg:pgo or pgu + unsigned long fExp : 1; // .exp module + unsigned long pad : 12; // reserved, must be 0 + } flags; + unsigned short machine; // target processor + unsigned short verFEMajor; // front end major version # + unsigned short verFEMinor; // front end minor version # + unsigned short verFEBuild; // front end build version # + unsigned short verFEQFE; // front end QFE version # + unsigned short verMajor; // back end major version # + unsigned short verMinor; // back end minor version # + unsigned short verBuild; // back end build version # + unsigned short verQFE; // back end QFE version # + char verSz[1]; // Zero terminated compiler version string +} COMPILESYM3; + +typedef struct ENVBLOCKSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ENVBLOCK + struct { + unsigned char rev : 1; // reserved + unsigned char pad : 7; // reserved, must be 0 + } flags; + unsigned char rgsz[1]; // Sequence of zero-terminated strings +} ENVBLOCKSYM; + +typedef struct OBJNAMESYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_OBJNAME + unsigned long signature; // signature + unsigned char name[1]; // Length-prefixed name +} OBJNAMESYM; + + +typedef struct ENDARGSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ENDARG +} ENDARGSYM; + + +typedef struct RETURNSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_RETURN + CV_GENERIC_FLAG flags; // flags + unsigned char style; // CV_GENERIC_STYLE_e return style + // followed by return method data +} RETURNSYM; + + +typedef struct ENTRYTHISSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ENTRYTHIS + unsigned char thissym; // symbol describing this pointer on entry +} ENTRYTHISSYM; + + +// symbol types for 16:16 memory model + + +typedef struct BPRELSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BPREL16 + CV_off16_t off; // BP-relative offset + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} BPRELSYM16; + + +typedef struct DATASYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LDATA or S_GDATA + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} DATASYM16; +typedef DATASYM16 PUBSYM16; + + +typedef struct PROCSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROC16 or S_LPROC16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned short len; // Proc length + unsigned short DbgStart; // Debug start offset + unsigned short DbgEnd; // Debug end offset + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + CV_typ16_t typind; // Type index + CV_PROCFLAGS flags; // Proc flags + unsigned char name[1]; // Length-prefixed name +} PROCSYM16; + + +typedef struct THUNKSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_THUNK + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + unsigned short len; // length of thunk + unsigned char ord; // THUNK_ORDINAL specifying type of thunk + unsigned char name[1]; // name of thunk + unsigned char variant[CV_ZEROLEN]; // variant portion of thunk +} THUNKSYM16; + +typedef struct LABELSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LABEL16 + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + CV_PROCFLAGS flags; // flags + unsigned char name[1]; // Length-prefixed name +} LABELSYM16; + + +typedef struct BLOCKSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BLOCK16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned short len; // Block length + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + unsigned char name[1]; // Length-prefixed name +} BLOCKSYM16; + + +typedef struct WITHSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_WITH16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned short len; // Block length + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + unsigned char expr[1]; // Length-prefixed expression +} WITHSYM16; + + +typedef enum CEXM_MODEL_e { + CEXM_MDL_table = 0x00, // not executable + CEXM_MDL_jumptable = 0x01, // Compiler generated jump table + CEXM_MDL_datapad = 0x02, // Data padding for alignment + CEXM_MDL_native = 0x20, // native (actually not-pcode) + CEXM_MDL_cobol = 0x21, // cobol + CEXM_MDL_codepad = 0x22, // Code padding for alignment + CEXM_MDL_code = 0x23, // code + CEXM_MDL_sql = 0x30, // sql + CEXM_MDL_pcode = 0x40, // pcode + CEXM_MDL_pcode32Mac = 0x41, // macintosh 32 bit pcode + CEXM_MDL_pcode32MacNep = 0x42, // macintosh 32 bit pcode native entry point + CEXM_MDL_javaInt = 0x50, + CEXM_MDL_unknown = 0xff +} CEXM_MODEL_e; + +// use the correct enumerate name +#define CEXM_MDL_SQL CEXM_MDL_sql + +typedef enum CV_COBOL_e { + CV_COBOL_dontstop, + CV_COBOL_pfm, + CV_COBOL_false, + CV_COBOL_extcall +} CV_COBOL_e; + +typedef struct CEXMSYM16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CEXMODEL16 + CV_uoff16_t off; // offset of symbol + unsigned short seg; // segment of symbol + unsigned short model; // execution model + union { + struct { + CV_uoff16_t pcdtable; // offset to pcode function table + CV_uoff16_t pcdspi; // offset to segment pcode information + } pcode; + struct { + unsigned short subtype; // see CV_COBOL_e above + unsigned short flag; + } cobol; + }; +} CEXMSYM16; + + +typedef struct VPATHSYM16 { + unsigned short reclen; // record length + unsigned short rectyp; // S_VFTPATH16 + CV_uoff16_t off; // offset of virtual function table + unsigned short seg; // segment of virtual function table + CV_typ16_t root; // type index of the root of path + CV_typ16_t path; // type index of the path record +} VPATHSYM16; + + +typedef struct REGREL16 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REGREL16 + CV_uoff16_t off; // offset of symbol + unsigned short reg; // register index + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} REGREL16; + + +typedef struct BPRELSYM32_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BPREL32_16t + CV_off32_t off; // BP-relative offset + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} BPRELSYM32_16t; + +typedef struct BPRELSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BPREL32 + CV_off32_t off; // BP-relative offset + CV_typ_t typind; // Type index or Metadata token + unsigned char name[1]; // Length-prefixed name +} BPRELSYM32; + +typedef struct FRAMERELSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANFRAMEREL | S_ATTR_FRAMEREL + CV_off32_t off; // Frame relative offset + CV_typ_t typind; // Type index or Metadata token + CV_lvar_attr attr; // local var attributes + unsigned char name[1]; // Length-prefixed name +} FRAMERELSYM; + +typedef FRAMERELSYM ATTRFRAMERELSYM; + + +typedef struct SLOTSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LOCALSLOT or S_PARAMSLOT + unsigned long iSlot; // slot index + CV_typ_t typind; // Type index or Metadata token + unsigned char name[1]; // Length-prefixed name +} SLOTSYM32; + +typedef struct ATTRSLOTSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANSLOT + unsigned long iSlot; // slot index + CV_typ_t typind; // Type index or Metadata token + CV_lvar_attr attr; // local var attributes + unsigned char name[1]; // Length-prefixed name +} ATTRSLOTSYM; + +typedef struct ANNOTATIONSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ANNOTATION + CV_uoff32_t off; + unsigned short seg; + unsigned short csz; // Count of zero terminated annotation strings + unsigned char rgsz[1]; // Sequence of zero terminated annotation strings +} ANNOTATIONSYM; + +typedef struct DATASYM32_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LDATA32_16t, S_GDATA32_16t or S_PUB32_16t + CV_uoff32_t off; + unsigned short seg; + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} DATASYM32_16t; +typedef DATASYM32_16t PUBSYM32_16t; + +typedef struct DATASYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA + CV_typ_t typind; // Type index, or Metadata token if a managed symbol + CV_uoff32_t off; + unsigned short seg; + unsigned char name[1]; // Length-prefixed name +} DATASYM32; + +typedef struct DATASYMHLSL { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GDATA_HLSL, S_LDATA_HLSL + CV_typ_t typind; // Type index + unsigned short regType; // register type from CV_HLSLREG_e + unsigned short dataslot; // Base data (cbuffer, groupshared, etc.) slot + unsigned short dataoff; // Base data byte offset start + unsigned short texslot; // Texture slot start + unsigned short sampslot; // Sampler slot start + unsigned short uavslot; // UAV slot start + unsigned char name[1]; // name +} DATASYMHLSL; + +typedef struct DATASYMHLSL32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GDATA_HLSL32, S_LDATA_HLSL32 + CV_typ_t typind; // Type index + unsigned long dataslot; // Base data (cbuffer, groupshared, etc.) slot + unsigned long dataoff; // Base data byte offset start + unsigned long texslot; // Texture slot start + unsigned long sampslot; // Sampler slot start + unsigned long uavslot; // UAV slot start + unsigned short regType; // register type from CV_HLSLREG_e + unsigned char name[1]; // name +} DATASYMHLSL32; + +typedef struct DATASYMHLSL32_EX { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GDATA_HLSL32_EX, S_LDATA_HLSL32_EX + CV_typ_t typind; // Type index + unsigned long regID; // Register index + unsigned long dataoff; // Base data byte offset start + unsigned long bindSpace; // Binding space + unsigned long bindSlot; // Lower bound in binding space + unsigned short regType; // register type from CV_HLSLREG_e + unsigned char name[1]; // name +} DATASYMHLSL32_EX; + +typedef enum CV_PUBSYMFLAGS_e + { + cvpsfNone = 0, + cvpsfCode = 0x00000001, + cvpsfFunction = 0x00000002, + cvpsfManaged = 0x00000004, + cvpsfMSIL = 0x00000008, +} CV_PUBSYMFLAGS_e; + +typedef union CV_PUBSYMFLAGS { + CV_pubsymflag_t grfFlags; + struct { + CV_pubsymflag_t fCode : 1; // set if public symbol refers to a code address + CV_pubsymflag_t fFunction : 1; // set if public symbol is a function + CV_pubsymflag_t fManaged : 1; // set if managed code (native or IL) + CV_pubsymflag_t fMSIL : 1; // set if managed IL code + CV_pubsymflag_t __unused : 28; // must be zero + }; +} CV_PUBSYMFLAGS; + +typedef struct PUBSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_PUB32 + CV_PUBSYMFLAGS pubsymflags; + CV_uoff32_t off; + unsigned short seg; + unsigned char name[1]; // Length-prefixed name +} PUBSYM32; + + +typedef struct PROCSYM32_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROC32_16t or S_LPROC32_16t + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + CV_uoff32_t off; + unsigned short seg; + CV_typ16_t typind; // Type index + CV_PROCFLAGS flags; // Proc flags + unsigned char name[1]; // Length-prefixed name +} PROCSYM32_16t; + +typedef struct PROCSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or S_LPROC32_DPC_ID + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + CV_typ_t typind; // Type index or ID + CV_uoff32_t off; + unsigned short seg; + CV_PROCFLAGS flags; // Proc flags + unsigned char name[1]; // Length-prefixed name +} PROCSYM32; + +typedef struct MANPROCSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GMANPROC, S_LMANPROC, S_GMANPROCIA64 or S_LMANPROCIA64 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + CV_tkn_t token; // COM+ metadata token for method + CV_uoff32_t off; + unsigned short seg; + CV_PROCFLAGS flags; // Proc flags + unsigned short retReg; // Register return value is in (may not be used for all archs) + unsigned char name[1]; // optional name field +} MANPROCSYM; + +typedef struct MANPROCSYMMIPS { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GMANPROCMIPS or S_LMANPROCMIPS + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + unsigned long regSave; // int register save mask + unsigned long fpSave; // fp register save mask + CV_uoff32_t intOff; // int register save offset + CV_uoff32_t fpOff; // fp register save offset + CV_tkn_t token; // COM+ token type + CV_uoff32_t off; + unsigned short seg; + unsigned char retReg; // Register return value is in + unsigned char frameReg; // Frame pointer register + unsigned char name[1]; // optional name field +} MANPROCSYMMIPS; + +typedef struct THUNKSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_THUNK32 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + CV_uoff32_t off; + unsigned short seg; + unsigned short len; // length of thunk + unsigned char ord; // THUNK_ORDINAL specifying type of thunk + unsigned char name[1]; // Length-prefixed name + unsigned char variant[CV_ZEROLEN]; // variant portion of thunk +} THUNKSYM32; + +typedef enum TRAMP_e { // Trampoline subtype + trampIncremental, // incremental thunks + trampBranchIsland, // Branch island thunks +} TRAMP_e; + +typedef struct TRAMPOLINESYM { // Trampoline thunk symbol + unsigned short reclen; // Record length + unsigned short rectyp; // S_TRAMPOLINE + unsigned short trampType; // trampoline sym subtype + unsigned short cbThunk; // size of the thunk + CV_uoff32_t offThunk; // offset of the thunk + CV_uoff32_t offTarget; // offset of the target of the thunk + unsigned short sectThunk; // section index of the thunk + unsigned short sectTarget; // section index of the target of the thunk +} TRAMPOLINE; + +typedef struct LABELSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LABEL32 + CV_uoff32_t off; + unsigned short seg; + CV_PROCFLAGS flags; // flags + unsigned char name[1]; // Length-prefixed name +} LABELSYM32; + + +typedef struct BLOCKSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BLOCK32 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long len; // Block length + CV_uoff32_t off; // Offset in code segment + unsigned short seg; // segment of label + unsigned char name[1]; // Length-prefixed name +} BLOCKSYM32; + + +typedef struct WITHSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_WITH32 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long len; // Block length + CV_uoff32_t off; // Offset in code segment + unsigned short seg; // segment of label + unsigned char expr[1]; // Length-prefixed expression string +} WITHSYM32; + + + +typedef struct CEXMSYM32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CEXMODEL32 + CV_uoff32_t off; // offset of symbol + unsigned short seg; // segment of symbol + unsigned short model; // execution model + union { + struct { + CV_uoff32_t pcdtable; // offset to pcode function table + CV_uoff32_t pcdspi; // offset to segment pcode information + } pcode; + struct { + unsigned short subtype; // see CV_COBOL_e above + unsigned short flag; + } cobol; + struct { + CV_uoff32_t calltableOff; // offset to function table + unsigned short calltableSeg; // segment of function table + } pcode32Mac; + }; +} CEXMSYM32; + + + +typedef struct VPATHSYM32_16t { + unsigned short reclen; // record length + unsigned short rectyp; // S_VFTABLE32_16t + CV_uoff32_t off; // offset of virtual function table + unsigned short seg; // segment of virtual function table + CV_typ16_t root; // type index of the root of path + CV_typ16_t path; // type index of the path record +} VPATHSYM32_16t; + +typedef struct VPATHSYM32 { + unsigned short reclen; // record length + unsigned short rectyp; // S_VFTABLE32 + CV_typ_t root; // type index of the root of path + CV_typ_t path; // type index of the path record + CV_uoff32_t off; // offset of virtual function table + unsigned short seg; // segment of virtual function table +} VPATHSYM32; + + + + + +typedef struct REGREL32_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REGREL32_16t + CV_uoff32_t off; // offset of symbol + unsigned short reg; // register index for symbol + CV_typ16_t typind; // Type index + unsigned char name[1]; // Length-prefixed name +} REGREL32_16t; + +typedef struct REGREL32 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REGREL32 + CV_uoff32_t off; // offset of symbol + CV_typ_t typind; // Type index or metadata token + unsigned short reg; // register index for symbol + unsigned char name[1]; // Length-prefixed name +} REGREL32; + +typedef struct ATTRREGREL { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MANREGREL | S_ATTR_REGREL + CV_uoff32_t off; // offset of symbol + CV_typ_t typind; // Type index or metadata token + unsigned short reg; // register index for symbol + CV_lvar_attr attr; // local var attributes + unsigned char name[1]; // Length-prefixed name +} ATTRREGREL; + +typedef ATTRREGREL ATTRREGRELSYM; + +typedef struct THREADSYM32_16t { + unsigned short reclen; // record length + unsigned short rectyp; // S_LTHREAD32_16t | S_GTHREAD32_16t + CV_uoff32_t off; // offset into thread storage + unsigned short seg; // segment of thread storage + CV_typ16_t typind; // type index + unsigned char name[1]; // length prefixed name +} THREADSYM32_16t; + +typedef struct THREADSYM32 { + unsigned short reclen; // record length + unsigned short rectyp; // S_LTHREAD32 | S_GTHREAD32 + CV_typ_t typind; // type index + CV_uoff32_t off; // offset into thread storage + unsigned short seg; // segment of thread storage + unsigned char name[1]; // length prefixed name +} THREADSYM32; + +typedef struct SLINK32 { + unsigned short reclen; // record length + unsigned short rectyp; // S_SLINK32 + unsigned long framesize; // frame size of parent procedure + CV_off32_t off; // signed offset where the static link was saved relative to the value of reg + unsigned short reg; +} SLINK32; + +typedef struct PROCSYMMIPS_16t { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROCMIPS_16t or S_LPROCMIPS_16t + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + unsigned long regSave; // int register save mask + unsigned long fpSave; // fp register save mask + CV_uoff32_t intOff; // int register save offset + CV_uoff32_t fpOff; // fp register save offset + CV_uoff32_t off; // Symbol offset + unsigned short seg; // Symbol segment + CV_typ16_t typind; // Type index + unsigned char retReg; // Register return value is in + unsigned char frameReg; // Frame pointer register + unsigned char name[1]; // Length-prefixed name +} PROCSYMMIPS_16t; + +typedef struct PROCSYMMIPS { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROCMIPS or S_LPROCMIPS + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + unsigned long regSave; // int register save mask + unsigned long fpSave; // fp register save mask + CV_uoff32_t intOff; // int register save offset + CV_uoff32_t fpOff; // fp register save offset + CV_typ_t typind; // Type index + CV_uoff32_t off; // Symbol offset + unsigned short seg; // Symbol segment + unsigned char retReg; // Register return value is in + unsigned char frameReg; // Frame pointer register + unsigned char name[1]; // Length-prefixed name +} PROCSYMMIPS; + +typedef struct PROCSYMIA64 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROCIA64 or S_LPROCIA64 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol + unsigned long len; // Proc length + unsigned long DbgStart; // Debug start offset + unsigned long DbgEnd; // Debug end offset + CV_typ_t typind; // Type index + CV_uoff32_t off; // Symbol offset + unsigned short seg; // Symbol segment + unsigned short retReg; // Register return value is in + CV_PROCFLAGS flags; // Proc flags + unsigned char name[1]; // Length-prefixed name +} PROCSYMIA64; + +typedef struct REFSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_PROCREF_ST, S_DATAREF_ST, or S_LPROCREF_ST + unsigned long sumName; // SUC of the name + unsigned long ibSym; // Offset of actual symbol in $$Symbols + unsigned short imod; // Module containing the actual symbol + unsigned short usFill; // align this record +} REFSYM; + +typedef struct REFSYM2 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_PROCREF, S_DATAREF, or S_LPROCREF + unsigned long sumName; // SUC of the name + unsigned long ibSym; // Offset of actual symbol in $$Symbols + unsigned short imod; // Module containing the actual symbol + unsigned char name[1]; // hidden name made a first class member +} REFSYM2; + +typedef struct ALIGNSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ALIGN +} ALIGNSYM; + +typedef struct OEMSYMBOL { + unsigned short reclen; // Record length + unsigned short rectyp; // S_OEM + unsigned char idOem[16]; // an oem ID (GUID) + CV_typ_t typind; // Type index + unsigned long rgl[]; // user data, force 4-byte alignment +} OEMSYMBOL; + +// generic block definition symbols +// these are similar to the equivalent 16:16 or 16:32 symbols but +// only define the length, type and linkage fields + +typedef struct PROCSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_GPROC16 or S_LPROC16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol +} PROCSYM; + + +typedef struct THUNKSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_THUNK + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end + unsigned long pNext; // pointer to next symbol +} THUNKSYM; + +typedef struct BLOCKSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BLOCK16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end +} BLOCKSYM; + + +typedef struct WITHSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_WITH16 + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this blocks end +} WITHSYM; + +typedef struct FRAMEPROCSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_FRAMEPROC + unsigned long cbFrame; // count of bytes of total frame of procedure + unsigned long cbPad; // count of bytes of padding in the frame + CV_uoff32_t offPad; // offset (relative to frame poniter) to where + // padding starts + unsigned long cbSaveRegs; // count of bytes of callee save registers + CV_uoff32_t offExHdlr; // offset of exception handler + unsigned short sectExHdlr; // section id of exception handler + + struct { + unsigned long fHasAlloca : 1; // function uses _alloca() + unsigned long fHasSetJmp : 1; // function uses setjmp() + unsigned long fHasLongJmp : 1; // function uses longjmp() + unsigned long fHasInlAsm : 1; // function uses inline asm + unsigned long fHasEH : 1; // function has EH states + unsigned long fInlSpec : 1; // function was speced as inline + unsigned long fHasSEH : 1; // function has SEH + unsigned long fNaked : 1; // function is __declspec(naked) + unsigned long fSecurityChecks : 1; // function has buffer security check introduced by /GS. + unsigned long fAsyncEH : 1; // function compiled with /EHa + unsigned long fGSNoStackOrdering : 1; // function has /GS buffer checks, but stack ordering couldn't be done + unsigned long fWasInlined : 1; // function was inlined within another function + unsigned long fGSCheck : 1; // function is __declspec(strict_gs_check) + unsigned long fSafeBuffers : 1; // function is __declspec(safebuffers) + unsigned long encodedLocalBasePointer : 2; // record function's local pointer explicitly. + unsigned long encodedParamBasePointer : 2; // record function's parameter pointer explicitly. + unsigned long fPogoOn : 1; // function was compiled with PGO/PGU + unsigned long fValidCounts : 1; // Do we have valid Pogo counts? + unsigned long fOptSpeed : 1; // Did we optimize for speed? + unsigned long fGuardCF : 1; // function contains CFG checks (and no write checks) + unsigned long fGuardCFW : 1; // function contains CFW checks and/or instrumentation + unsigned long pad : 9; // must be zero + } flags; +} FRAMEPROCSYM; + +#ifdef __cplusplus +namespace CodeViewInfo +{ +__inline unsigned short ExpandEncodedBasePointerReg(unsigned machineType, unsigned encodedFrameReg) +{ + static const unsigned short rgFramePointerRegX86[] = { + CV_REG_NONE, CV_ALLREG_VFRAME, CV_REG_EBP, CV_REG_EBX}; + static const unsigned short rgFramePointerRegX64[] = { + CV_REG_NONE, CV_AMD64_RSP, CV_AMD64_RBP, CV_AMD64_R13}; + static const unsigned short rgFramePointerRegArm[] = { + CV_REG_NONE, CV_ARM_SP, CV_ARM_R7, CV_REG_NONE}; + + if (encodedFrameReg >= 4) { + return CV_REG_NONE; + } + switch (machineType) { + case CV_CFL_8080 : + case CV_CFL_8086 : + case CV_CFL_80286 : + case CV_CFL_80386 : + case CV_CFL_80486 : + case CV_CFL_PENTIUM : + case CV_CFL_PENTIUMII : + case CV_CFL_PENTIUMIII : + return rgFramePointerRegX86[encodedFrameReg]; + case CV_CFL_AMD64 : + return rgFramePointerRegX64[encodedFrameReg]; + case CV_CFL_ARMNT : + return rgFramePointerRegArm[encodedFrameReg]; + default: + return CV_REG_NONE; + } +} +} +#endif + +typedef struct UNAMESPACE { + unsigned short reclen; // Record length + unsigned short rectyp; // S_UNAMESPACE + unsigned char name[1]; // name +} UNAMESPACE; + +typedef struct SEPCODESYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_SEPCODE + unsigned long pParent; // pointer to the parent + unsigned long pEnd; // pointer to this block's end + unsigned long length; // count of bytes of this block + CV_SEPCODEFLAGS scf; // flags + CV_uoff32_t off; // sect:off of the separated code + CV_uoff32_t offParent; // sectParent:offParent of the enclosing scope + unsigned short sect; // (proc, block, or sepcode) + unsigned short sectParent; +} SEPCODESYM; + +typedef struct BUILDINFOSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_BUILDINFO + CV_ItemId id; // CV_ItemId of Build Info. +} BUILDINFOSYM; + +typedef struct INLINESITESYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_INLINESITE + unsigned long pParent; // pointer to the inliner + unsigned long pEnd; // pointer to this block's end + CV_ItemId inlinee; // CV_ItemId of inlinee + unsigned char binaryAnnotations[CV_ZEROLEN]; // an array of compressed binary annotations. +} INLINESITESYM; + +typedef struct INLINESITESYM2 { + unsigned short reclen; // Record length + unsigned short rectyp; // S_INLINESITE2 + unsigned long pParent; // pointer to the inliner + unsigned long pEnd; // pointer to this block's end + CV_ItemId inlinee; // CV_ItemId of inlinee + unsigned long invocations; // entry count + unsigned char binaryAnnotations[CV_ZEROLEN]; // an array of compressed binary annotations. +} INLINESITESYM2; + + +// Defines a locals and it is live range, how to evaluate. +// S_DEFRANGE modifies previous local S_LOCAL, it has to consecutive. + +typedef struct LOCALSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LOCAL + CV_typ_t typind; // type index + CV_LVARFLAGS flags; // local var flags + + unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. +} LOCALSYM; + +typedef struct FILESTATICSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_FILESTATIC + CV_typ_t typind; // type index + CV_uoff32_t modOffset; // index of mod filename in stringtable + CV_LVARFLAGS flags; // local var flags + + unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters +} FILESTATICSYM; + +typedef struct DEFRANGESYM { // A live range of sub field of variable + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE + + CV_uoff32_t program; // DIA program to evaluate the value of the symbol + + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYM; + +typedef struct DEFRANGESYMSUBFIELD { // A live range of sub field of variable. like locala.i + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_SUBFIELD + + CV_uoff32_t program; // DIA program to evaluate the value of the symbol + + CV_uoff32_t offParent; // Offset in parent variable. + + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYMSUBFIELD; + +typedef struct CV_RANGEATTR { + unsigned short maybe : 1; // May have no user name on one of control flow path. + unsigned short padding : 15; // Padding for future use. +} CV_RANGEATTR; + +typedef struct DEFRANGESYMREGISTER { // A live range of en-registed variable + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_REGISTER + unsigned short reg; // Register to hold the value of the symbol + CV_RANGEATTR attr; // Attribute of the register range. + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYMREGISTER; + +typedef struct DEFRANGESYMFRAMEPOINTERREL { // A live range of frame variable + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_FRAMEPOINTER_REL + + CV_off32_t offFramePointer; // offset to frame pointer + + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYMFRAMEPOINTERREL; + +typedef struct DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE { // A frame variable valid in all function scope + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_FRAMEPOINTER_REL + + CV_off32_t offFramePointer; // offset to frame pointer +} DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE; + +#define CV_OFFSET_PARENT_LENGTH_LIMIT 12 + +// Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. +typedef struct DEFRANGESYMSUBFIELDREGISTER { // A live range of sub field of variable. like locala.i + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_SUBFIELD_REGISTER + + unsigned short reg; // Register to hold the value of the symbol + CV_RANGEATTR attr; // Attribute of the register range. + CV_uoff32_t offParent : CV_OFFSET_PARENT_LENGTH_LIMIT; // Offset in parent variable. + CV_uoff32_t padding : 20; // Padding for future use. + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYMSUBFIELDREGISTER; + +// Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. +// Used when /GS Copy parameter as local variable or other variable don't cover by FRAMERELATIVE. +typedef struct DEFRANGESYMREGISTERREL { // A live range of variable related to a register. + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_REGISTER_REL + + unsigned short baseReg; // Register to hold the base pointer of the symbol + unsigned short spilledUdtMember : 1; // Spilled member for s.i. + unsigned short padding : 3; // Padding for future use. + unsigned short offsetParent : CV_OFFSET_PARENT_LENGTH_LIMIT; // Offset in parent variable. + CV_off32_t offBasePointer; // offset to register + + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. +} DEFRANGESYMREGISTERREL; + +typedef struct DEFRANGESYMHLSL { // A live range of variable related to a symbol in HLSL code. + unsigned short reclen; // Record length + unsigned short rectyp; // S_DEFRANGE_HLSL or S_DEFRANGE_DPC_PTR_TAG + + unsigned short regType; // register type from CV_HLSLREG_e + + unsigned short regIndices : 2; // 0, 1 or 2, dimensionality of register space + unsigned short spilledUdtMember : 1; // this is a spilled member + unsigned short memorySpace : 4; // memory space + unsigned short padding : 9; // for future use + + unsigned short offsetParent; // Offset in parent variable. + unsigned short sizeInParent; // Size of enregistered portion + + CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid + unsigned char data[CV_ZEROLEN]; // variable length data specifying gaps where the value is not available + // followed by multi-dimensional offset of variable location in register + // space (see CV_DEFRANGESYMHLSL_* macros below) +} DEFRANGESYMHLSL; + +#define CV_DEFRANGESYM_GAPS_COUNT(x) \ + (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYM)) / sizeof(CV_LVAR_ADDR_GAP)) + +#define CV_DEFRANGESYMSUBFIELD_GAPS_COUNT(x) \ + (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMSUBFIELD)) / sizeof(CV_LVAR_ADDR_GAP)) + +#define CV_DEFRANGESYMHLSL_GAPS_COUNT(x) \ + (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMHLSL) - (x)->regIndices * sizeof(CV_uoff32_t)) / sizeof(CV_LVAR_ADDR_GAP)) + +#define CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, t) reinterpret_cast((x)->data) + +#define CV_DEFRANGESYMHLSL_GAPS_CONST_PTR(x) \ + CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, const CV_LVAR_ADDR_GAP*) + +#define CV_DEFRANGESYMHLSL_GAPS_PTR(x) \ + CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, CV_LVAR_ADDR_GAP*) + +#define CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, t) \ + reinterpret_cast(((CV_LVAR_ADDR_GAP*)(x)->data) + CV_DEFRANGESYMHLSL_GAPS_COUNT(x)) + +#define CV_DEFRANGESYMHLSL_OFFSET_CONST_PTR(x) \ + CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, const CV_uoff32_t*) + +#define CV_DEFRANGESYMHLSL_OFFSET_PTR(x) \ + CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, CV_uoff32_t*) + +#if defined(CC_DP_CXX) && CC_DP_CXX + +// Defines a local DPC group shared variable and its location. +typedef struct LOCALDPCGROUPSHAREDSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_LOCAL_DPC_GROUPSHARED + CV_typ_t typind; // type index + CV_LVARFLAGS flags; // local var flags + + unsigned short dataslot; // Base data (cbuffer, groupshared, etc.) slot + unsigned short dataoff; // Base data byte offset start + + unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. +} LOCALDPCGROUPSHAREDSYM; + +typedef struct DPCSYMTAGMAP { // A map for DPC pointer tag values to symbol records. + unsigned short reclen; // Record length + unsigned short rectyp; // S_DPC_SYM_TAG_MAP + + CV_DPC_SYM_TAG_MAP_ENTRY mapEntries[CV_ZEROLEN]; // Array of mappings from DPC pointer tag values to symbol record offsets +} DPCSYMTAGMAP; + +#define CV_DPCSYMTAGMAP_COUNT(x) \ + (((x)->reclen + sizeof((x)->reclen) - sizeof(DPCSYMTAGMAP)) / sizeof(CV_DPC_SYM_TAG_MAP_ENTRY)) + +#endif // CC_DP_CXX + +typedef enum CV_armswitchtype { + CV_SWT_INT1 = 0, + CV_SWT_UINT1 = 1, + CV_SWT_INT2 = 2, + CV_SWT_UINT2 = 3, + CV_SWT_INT4 = 4, + CV_SWT_UINT4 = 5, + CV_SWT_POINTER = 6, + CV_SWT_UINT1SHL1 = 7, + CV_SWT_UINT2SHL1 = 8, + CV_SWT_INT1SHL1 = 9, + CV_SWT_INT2SHL1 = 10, + CV_SWT_TBB = CV_SWT_UINT1SHL1, + CV_SWT_TBH = CV_SWT_UINT2SHL1, +} CV_armswitchtype; + +typedef struct FUNCTIONLIST { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CALLERS or S_CALLEES + + unsigned long count; // Number of functions + CV_typ_t funcs[CV_ZEROLEN]; // List of functions, dim == count + // unsigned long invocations[CV_ZEROLEN]; Followed by a parallel array of + // invocation counts. Counts > reclen are assumed to be zero +} FUNCTIONLIST; + +typedef struct POGOINFO { + unsigned short reclen; // Record length + unsigned short rectyp; // S_POGODATA + + unsigned long invocations; // Number of times function was called + __int64 dynCount; // Dynamic instruction count + unsigned long numInstrs; // Static instruction count + unsigned long staInstLive; // Final static instruction count (post inlining) +} POGOINFO; + +typedef struct ARMSWITCHTABLE { + unsigned short reclen; // Record length + unsigned short rectyp; // S_ARMSWITCHTABLE + + CV_uoff32_t offsetBase; // Section-relative offset to the base for switch offsets + unsigned short sectBase; // Section index of the base for switch offsets + unsigned short switchType; // type of each entry + CV_uoff32_t offsetBranch; // Section-relative offset to the table branch instruction + CV_uoff32_t offsetTable; // Section-relative offset to the start of the table + unsigned short sectBranch; // Section index of the table branch instruction + unsigned short sectTable; // Section index of the table + unsigned long cEntries; // number of switch table entries +} ARMSWITCHTABLE; + +typedef struct MODTYPEREF { + unsigned short reclen; // Record length + unsigned short rectyp; // S_MOD_TYPEREF + + unsigned long fNone : 1; // module doesn't reference any type + unsigned long fRefTMPCT : 1; // reference /Z7 PCH types + unsigned long fOwnTMPCT : 1; // module contains /Z7 PCH types + unsigned long fOwnTMR : 1; // module contains type info (/Z7) + unsigned long fOwnTM : 1; // module contains type info (/Zi or /ZI) + unsigned long fRefTM : 1; // module references type info owned by other module + unsigned long reserved : 9; + + unsigned short word0; // these two words contain SN or module index depending + unsigned short word1; // on above flags +} MODTYPEREF; + +typedef struct SECTIONSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_SECTION + + unsigned short isec; // Section number + unsigned char align; // Alignment of this section (power of 2) + unsigned char bReserved; // Reserved. Must be zero. + unsigned long rva; + unsigned long cb; + unsigned long characteristics; + unsigned char name[1]; // name +} SECTIONSYM; + +typedef struct COFFGROUPSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_COFFGROUP + + unsigned long cb; + unsigned long characteristics; + CV_uoff32_t off; // Symbol offset + unsigned short seg; // Symbol segment + unsigned char name[1]; // name +} COFFGROUPSYM; + +typedef struct EXPORTSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_EXPORT + + unsigned short ordinal; + unsigned short fConstant : 1; // CONSTANT + unsigned short fData : 1; // DATA + unsigned short fPrivate : 1; // PRIVATE + unsigned short fNoName : 1; // NONAME + unsigned short fOrdinal : 1; // Ordinal was explicitly assigned + unsigned short fForwarder : 1; // This is a forwarder + unsigned short reserved : 10; // Reserved. Must be zero. + unsigned char name[1]; // name of +} EXPORTSYM; + +// +// Symbol for describing indirect calls when they are using +// a function pointer cast on some other type or temporary. +// Typical content will be an LF_POINTER to an LF_PROCEDURE +// type record that should mimic an actual variable with the +// function pointer type in question. +// +// Since the compiler can sometimes tail-merge a function call +// through a function pointer, there may be more than one +// S_CALLSITEINFO record at an address. This is similar to what +// you could do in your own code by: +// +// if (expr) +// pfn = &function1; +// else +// pfn = &function2; +// +// (*pfn)(arg list); +// + +typedef struct CALLSITEINFO { + unsigned short reclen; // Record length + unsigned short rectyp; // S_CALLSITEINFO + CV_off32_t off; // offset of call site + unsigned short sect; // section index of call site + unsigned short __reserved_0; // alignment padding field, must be zero + CV_typ_t typind; // type index describing function signature +} CALLSITEINFO; + +typedef struct HEAPALLOCSITE { + unsigned short reclen; // Record length + unsigned short rectyp; // S_HEAPALLOCSITE + CV_off32_t off; // offset of call site + unsigned short sect; // section index of call site + unsigned short cbInstr; // length of heap allocation call instruction + CV_typ_t typind; // type index describing function signature +} HEAPALLOCSITE; + +// Frame cookie information + +typedef enum CV_cookietype_e +{ + CV_COOKIETYPE_COPY = 0, + CV_COOKIETYPE_XOR_SP, + CV_COOKIETYPE_XOR_BP, + CV_COOKIETYPE_XOR_R13, +} CV_cookietype_e; + +// Symbol for describing security cookie's position and type +// (raw, xor'd with esp, xor'd with ebp). + +typedef struct FRAMECOOKIE { + unsigned short reclen; // Record length + unsigned short rectyp; // S_FRAMECOOKIE + CV_off32_t off; // Frame relative offset + unsigned short reg; // Register index + CV_cookietype_e cookietype; // Type of the cookie + unsigned char flags; // Flags describing this cookie +} FRAMECOOKIE; + +typedef enum CV_DISCARDED_e +{ + CV_DISCARDED_UNKNOWN, + CV_DISCARDED_NOT_SELECTED, + CV_DISCARDED_NOT_REFERENCED, +} CV_DISCARDED_e; + +typedef struct DISCARDEDSYM { + unsigned short reclen; // Record length + unsigned short rectyp; // S_DISCARDED + unsigned long discarded : 8; // CV_DISCARDED_e + unsigned long reserved : 24; // Unused + unsigned long fileid; // First FILEID if line number info present + unsigned long linenum; // First line number + char data[CV_ZEROLEN]; // Original record(s) with invalid type indices +} DISCARDEDSYM; + +typedef struct REFMINIPDB { + unsigned short reclen; // Record length + unsigned short rectyp; // S_REF_MINIPDB + union { + unsigned long isectCoff; // coff section + CV_typ_t typind; // type index + }; + unsigned short imod; // mod index + unsigned short fLocal : 1; // reference to local (vs. global) func or data + unsigned short fData : 1; // reference to data (vs. func) + unsigned short fUDT : 1; // reference to UDT + unsigned short fLabel : 1; // reference to label + unsigned short fConst : 1; // reference to const + unsigned short reserved : 11; // reserved, must be zero + unsigned char name[1]; // zero terminated name string +} REFMINIPDB; + +typedef struct PDBMAP { + unsigned short reclen; // Record length + unsigned short rectyp; // S_PDBMAP + unsigned char name[CV_ZEROLEN]; // zero terminated source PDB filename followed by zero + // terminated destination PDB filename, both in wchar_t +} PDBMAP; + +// +// V7 line number data types +// + +enum DEBUG_S_SUBSECTION_TYPE { + DEBUG_S_IGNORE = 0x80000000, // if this bit is set in a subsection type then ignore the subsection contents + + DEBUG_S_SYMBOLS = 0xf1, + DEBUG_S_LINES, + DEBUG_S_STRINGTABLE, + DEBUG_S_FILECHKSMS, + DEBUG_S_FRAMEDATA, + DEBUG_S_INLINEELINES, + DEBUG_S_CROSSSCOPEIMPORTS, + DEBUG_S_CROSSSCOPEEXPORTS, + + DEBUG_S_IL_LINES, + DEBUG_S_FUNC_MDTOKEN_MAP, + DEBUG_S_TYPE_MDTOKEN_MAP, + DEBUG_S_MERGED_ASSEMBLYINPUT, + + DEBUG_S_COFF_SYMBOL_RVA, +}; + +struct CV_DebugSSubsectionHeader_t { + enum DEBUG_S_SUBSECTION_TYPE type; + CV_off32_t cbLen; +}; + +struct CV_DebugSLinesHeader_t { + CV_off32_t offCon; + unsigned short segCon; + unsigned short flags; + CV_off32_t cbCon; +}; + +struct CV_DebugSLinesFileBlockHeader_t { + CV_off32_t offFile; + CV_off32_t nLines; + CV_off32_t cbBlock; + // CV_Line_t lines[nLines]; + // CV_Column_t columns[nColumns]; +}; + +// +// Line flags (data present) +// +#define CV_LINES_HAVE_COLUMNS 0x0001 + +struct CV_Line_t { + unsigned long offset; // Offset to start of code bytes for line number + unsigned long linenumStart:24; // line where statement/expression starts + unsigned long deltaLineEnd:7; // delta to line where statement ends (optional) + unsigned long fStatement:1; // true if a statement linenumber, else an expression line num +}; + +typedef unsigned short CV_columnpos_t; // byte offset in a source line + +struct CV_Column_t { + CV_columnpos_t offColumnStart; + CV_columnpos_t offColumnEnd; +}; + +struct tagFRAMEDATA { + unsigned long ulRvaStart; + unsigned long cbBlock; + unsigned long cbLocals; + unsigned long cbParams; + unsigned long cbStkMax; + unsigned long frameFunc; + unsigned short cbProlog; + unsigned short cbSavedRegs; + unsigned long fHasSEH:1; + unsigned long fHasEH:1; + unsigned long fIsFunctionStart:1; + unsigned long reserved:29; +}; + +typedef struct tagFRAMEDATA FRAMEDATA, * PFRAMEDATA; + +typedef struct tagXFIXUP_DATA { + unsigned short wType; + unsigned short wExtra; + unsigned long rva; + unsigned long rvaTarget; +} XFIXUP_DATA; + +// Those cross scope IDs are private convention, +// it used to delay the ID merging for frontend and backend even linker. +// It is transparent for DIA client. +// Use those ID will let DIA run a litter slower and but +// avoid the copy type tree in some scenarios. + +#ifdef __cplusplus +namespace CodeViewInfo +{ + +typedef struct ComboID +{ + static const unsigned int IndexBitWidth = 20; + static const unsigned int ImodBitWidth = 12; + + ComboID(unsigned short imod, unsigned int index) + { + m_comboID = (((unsigned int) imod) << IndexBitWidth) | index; + } + + ComboID(unsigned int comboID) + { + m_comboID = comboID; + } + + operator unsigned int() + { + return m_comboID; + } + + unsigned short GetModIndex() + { + return (unsigned short) (m_comboID >> IndexBitWidth); + } + + unsigned int GetIndex() + { + return (m_comboID & ((1 << IndexBitWidth) - 1)); + } + +private: + + unsigned int m_comboID; +} ComboID; + + +typedef struct CrossScopeId +{ + static const unsigned int LocalIdBitWidth = 20; + static const unsigned int IdScopeBitWidth = 11; + static const unsigned int StartCrossScopeId = + (unsigned int) (1 << (LocalIdBitWidth + IdScopeBitWidth)); + static const unsigned int LocalIdMask = (1 << LocalIdBitWidth) - 1; + static const unsigned int ScopeIdMask = StartCrossScopeId - (1 << LocalIdBitWidth); + + // Compilation unit at most reference 1M constructed type. + static const unsigned int MaxLocalId = (1 << LocalIdBitWidth) - 1; + + // Compilation unit at most reference to another 2K compilation units. + static const unsigned int MaxScopeId = (1 << IdScopeBitWidth) - 1; + + CrossScopeId(unsigned short aIdScopeId, unsigned int aLocalId) + { + crossScopeId = StartCrossScopeId + | (aIdScopeId << LocalIdBitWidth) + | aLocalId; + } + + operator unsigned int() { + return crossScopeId; + } + + unsigned int GetLocalId() { + return crossScopeId & LocalIdMask; + } + + unsigned int GetIdScopeId() { + return (crossScopeId & ScopeIdMask) >> LocalIdBitWidth; + } + + static bool IsCrossScopeId(unsigned int i) + { + return (StartCrossScopeId & i) != 0; + } + + static CrossScopeId Decode(unsigned int i) + { + CrossScopeId retval; + retval.crossScopeId = i; + return retval; + } + +private: + + CrossScopeId() {} + + unsigned int crossScopeId; + +} CrossScopeId; + +// Combined encoding of TI or FuncId, In compiler implementation +// Id prefixed by 1 if it is function ID. + +typedef struct DecoratedItemId +{ + DecoratedItemId(bool isFuncId, CV_ItemId inputId) { + if (isFuncId) { + decoratedItemId = 0x80000000 | inputId; + } else { + decoratedItemId = inputId; + } + } + + DecoratedItemId(CV_ItemId encodedId) { + decoratedItemId = encodedId; + } + + operator unsigned int() { + return decoratedItemId; + } + + bool IsFuncId() + { + return (decoratedItemId & 0x80000000) == 0x80000000; + } + + CV_ItemId GetItemId() + { + return decoratedItemId & 0x7fffffff; + } + +private: + + unsigned int decoratedItemId; + +} DecoratedItemId; + +// Compilation Unit object file path include library name +// Or compile time PDB full path + +typedef struct tagPdbIdScope { + CV_off32_t offObjectFilePath; +} PdbIdScope; + +// An array of all imports by import module. +// List all cross reference for a specific ID scope. +// Format of DEBUG_S_CROSSSCOPEIMPORTS subsection is +typedef struct tagCrossScopeReferences { + PdbIdScope externalScope; // Module of definition Scope. + unsigned int countOfCrossReferences; // Count of following array. + CV_ItemId referenceIds[CV_ZEROLEN]; // CV_ItemId in another compilation unit. +} CrossScopeReferences; + +// An array of all exports in this module. +// Format of DEBUG_S_CROSSSCOPEEXPORTS subsection is +typedef struct tagLocalIdAndGlobalIdPair { + CV_ItemId localId; // local id inside the compile time PDB scope. 0 based + CV_ItemId globalId; // global id inside the link time PDB scope, if scope are different. +} LocalIdAndGlobalIdPair; + +// Format of DEBUG_S_INLINEELINEINFO subsection +// List start source file information for an inlined function. + +#define CV_INLINEE_SOURCE_LINE_SIGNATURE 0x0 +#define CV_INLINEE_SOURCE_LINE_SIGNATURE_EX 0x1 + +typedef struct tagInlineeSourceLine { + CV_ItemId inlinee; // function id. + CV_off32_t fileId; // offset into file table DEBUG_S_FILECHKSMS + CV_off32_t sourceLineNum; // definition start line number. +} InlineeSourceLine; + +typedef struct tagInlineeSourceLineEx { + CV_ItemId inlinee; // function id + CV_off32_t fileId; // offset into file table DEBUG_S_FILECHKSMS + CV_off32_t sourceLineNum; // definition start line number + unsigned int countOfExtraFiles; + CV_off32_t extraFileId[CV_ZEROLEN]; +} InlineeSourceLineEx; + +// BinaryAnnotations ::= BinaryAnnotationInstruction+ +// BinaryAnnotationInstruction ::= BinaryAnnotationOpcode Operand+ +// +// The binary annotation mechanism supports recording a list of annotations +// in an instruction stream. The X64 unwind code and the DWARF standard have +// similar design. +// +// One annotation contains opcode and a number of 32bits operands. +// +// The initial set of annotation instructions are for line number table +// encoding only. These annotations append to S_INLINESITE record, and +// operands are unsigned except for BA_OP_ChangeLineOffset. + +enum BinaryAnnotationOpcode +{ + BA_OP_Invalid, // link time pdb contains PADDINGs + BA_OP_CodeOffset, // param : start offset + BA_OP_ChangeCodeOffsetBase, // param : nth separated code chunk (main code chunk == 0) + BA_OP_ChangeCodeOffset, // param : delta of offset + BA_OP_ChangeCodeLength, // param : length of code, default next start + BA_OP_ChangeFile, // param : fileId + BA_OP_ChangeLineOffset, // param : line offset (signed) + BA_OP_ChangeLineEndDelta, // param : how many lines, default 1 + BA_OP_ChangeRangeKind, // param : either 1 (default, for statement) + // or 0 (for expression) + + BA_OP_ChangeColumnStart, // param : start column number, 0 means no column info + BA_OP_ChangeColumnEndDelta, // param : end column number delta (signed) + + // Combo opcodes for smaller encoding size. + + BA_OP_ChangeCodeOffsetAndLineOffset, // param : ((sourceDelta << 4) | CodeDelta) + BA_OP_ChangeCodeLengthAndCodeOffset, // param : codeLength, codeOffset + + BA_OP_ChangeColumnEnd, // param : end column number +}; + +inline int BinaryAnnotationInstructionOperandCount(BinaryAnnotationOpcode op) +{ + return (op == BA_OP_ChangeCodeLengthAndCodeOffset) ? 2 : 1; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// This routine a simplified variant from cor.h. +// +// Compress an unsigned integer (iLen) and store the result into pDataOut. +// +// Return value is the number of bytes that the compressed data occupies. It +// is caller's responsibilityt to ensure *pDataOut has at least 4 bytes to be +// written to. +// +// Note that this function returns -1 if iLen is too big to be compressed. +// We currently can only encode numbers no larger than 0x1FFFFFFF. +// +/////////////////////////////////////////////////////////////////////////////// + +typedef unsigned __int8 UInt8; +typedef unsigned __int32 UInt32; + +typedef UInt8 CompressedAnnotation; +typedef CompressedAnnotation* PCompressedAnnotation; + +inline UInt32 CVCompressData( + UInt32 iLen, // [IN] given uncompressed data + void * pDataOut) // [OUT] buffer for the compressed data +{ + UInt8 *pBytes = reinterpret_cast(pDataOut); + + if (iLen <= 0x7F) { + *pBytes = UInt8(iLen); + return 1; + } + + if (iLen <= 0x3FFF) { + *pBytes = UInt8((iLen >> 8) | 0x80); + *(pBytes+1) = UInt8(iLen & 0xff); + return 2; + } + + if (iLen <= 0x1FFFFFFF) { + *pBytes = UInt8((iLen >> 24) | 0xC0); + *(pBytes+1) = UInt8((iLen >> 16) & 0xff); + *(pBytes+2) = UInt8((iLen >> 8) & 0xff); + *(pBytes+3) = UInt8(iLen & 0xff); + return 4; + } + + return (UInt32) -1; +} + +/////////////////////////////////////////////////////////////////////////////// +// +// Uncompress the data in pData and store the result into pDataOut. +// +// Return value is the uncompressed unsigned integer. pData is incremented to +// point to the next piece of uncompressed data. +// +// Returns -1 if what is passed in is incorrectly compressed data, such as +// (*pBytes & 0xE0) == 0xE0. +// +/////////////////////////////////////////////////////////////////////////////// + +inline UInt32 CVUncompressData( + PCompressedAnnotation & pData) // [IN,OUT] compressed data +{ + UInt32 res = (UInt32)(-1); + + if ((*pData & 0x80) == 0x00) { + // 0??? ???? + + res = (UInt32)(*pData++); + } + else if ((*pData & 0xC0) == 0x80) { + // 10?? ???? + + res = (UInt32)((*pData++ & 0x3f) << 8); + res |= *pData++; + } + else if ((*pData & 0xE0) == 0xC0) { + // 110? ???? + + res = (*pData++ & 0x1f) << 24; + res |= *pData++ << 16; + res |= *pData++ << 8; + res |= *pData++; + } + + return res; +} + +// Encode smaller absolute numbers with smaller buffer. +// +// General compression only work for input < 0x1FFFFFFF +// algorithm will not work on 0x80000000 + +inline unsigned __int32 EncodeSignedInt32(__int32 input) +{ + unsigned __int32 rotatedInput; + + if (input >= 0) { + rotatedInput = input << 1; + } else { + rotatedInput = ((-input) << 1) | 1; + } + + return rotatedInput; +} + +inline __int32 DecodeSignedInt32(unsigned __int32 input) +{ + __int32 rotatedInput; + + if (input & 1) { + rotatedInput = - (int)(input >> 1); + } else { + rotatedInput = input >> 1; + } + + return rotatedInput; +} + +} +#endif +#pragma pack ( pop ) + +#endif /* CV_INFO_INCLUDED */ diff --git a/lib/coreclr/src/inc/cycletimer.h b/lib/coreclr/src/inc/cycletimer.h new file mode 100644 index 0000000000..229fddb33f --- /dev/null +++ b/lib/coreclr/src/inc/cycletimer.h @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// CycleTimer has methods related to getting cycle timer values. +// It uses an all-statics class as a namespace mechanism. +// + +#ifndef _CYCLETIMER_H_ +#define _CYCLETIMER_H_ + +#include "windef.h" + +class CycleTimer +{ + // This returns the value of the *non-thread-virtualized* cycle counter. + static unsigned __int64 GetCycleCount64(); + + + // This wraps GetCycleCount64 in the signature of QueryThreadCycleTime -- but note + // that it ignores the "thrd" argument. + static BOOL WINAPI DefaultQueryThreadCycleTime(__in HANDLE thrd, __out PULONG64 cyclesPtr); + + // The function pointer type for QueryThreadCycleTime. + typedef BOOL (WINAPI *QueryThreadCycleTimeSig)(__in HANDLE, __out PULONG64); + + // Returns a function pointer for QueryThreadCycleTime, or else BadFPtr. + static QueryThreadCycleTimeSig GetQueryThreadCycleTime(); + + // Initialized once from NULL to either BadFPtr or QueryThreadCycleTime. + static QueryThreadCycleTimeSig s_QueryThreadCycleTimeFPtr; + + public: + + // This method computes the number of cycles/sec for the current machine. The cycles are those counted + // by GetThreadCycleTime; we assume that these are of equal duration, though that is not necessarily true. + // If any OS interaction fails, returns 0.0. + static double CyclesPerSecond(); + + // Does a large number of queries, and returns the average of their overhead, so other measurements + // can adjust for this. + static unsigned __int64 QueryOverhead(); + + // There's no "native" atomic add for 64 bit, so we have this convenience function. + static void InterlockedAddU64(unsigned __int64* loc, unsigned __int64 amount); + + // Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets + // *cycles to the cycle counter value. Otherwise, returns false. Note that the value returned is (currently) + // virtualized to the current thread only on Windows; on non-windows x86/x64 platforms, directly reads + // the cycle counter and returns that value. + static bool GetThreadCyclesS(unsigned __int64* cycles); +}; + +#endif // _CYCLETIMER_H_ + diff --git a/lib/coreclr/src/inc/daccess.h b/lib/coreclr/src/inc/daccess.h new file mode 100644 index 0000000000..e4deab9207 --- /dev/null +++ b/lib/coreclr/src/inc/daccess.h @@ -0,0 +1,2462 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// File: daccess.h +// + +// +// Support for external access of runtime data structures. These +// macros and templates hide the details of pointer and data handling +// so that data structures and code can be compiled to work both +// in-process and through a special memory access layer. +// +// This code assumes the existence of two different pieces of code, +// the target, the runtime code that is going to be examined, and +// the host, the code that's doing the examining. Access to the +// target is abstracted so the target may be a live process on the +// same machine, a live process on a different machine, a dump file +// or whatever. No assumptions should be made about accessibility +// of the target. +// +// This code assumes that the data in the target is static. Any +// time the target's data changes the interfaces must be reset so +// that potentially stale data is discarded. +// +// This code is intended for read access and there is no +// way to write data back currently. +// +// DAC-ized code: +// - is read-only (non-invasive). So DACized codepaths can not trigger a GC. +// - has no Thread* object. In reality, DAC-ized codepaths are +// ReadProcessMemory calls from out-of-process. Conceptually, they +// are like a pure-native (preemptive) thread. +//// +// This means that in particular, you cannot DACize a GCTRIGGERS function. +// Neither can you DACize a function that throws if this will involve +// allocating a new exception object. There may be +// exceptions to these rules if you can guarantee that the DACized +// part of the code path cannot cause a garbage collection (see +// EditAndContinueModule::ResolveField for an example). +// If you need to DACize a function that may trigger +// a GC, it is probably best to refactor the function so that the DACized +// part of the code path is in a separate function. For instance, +// functions with GetOrCreate() semantics are hard to DAC-ize because +// they the Create portion is inherently invasive. Instead, consider refactoring +// into a GetOrFail() function that DAC can call; and then make GetOrCreate() +// a wrapper around that. + +// +// This code works by hiding the details of access to target memory. +// Access is divided into two types: +// 1. DPTR - access to a piece of data. +// 2. VPTR - access to a class with a vtable. The class can only have +// a single vtable pointer at the beginning of the class instance. +// Things only need to be declared as VPTRs when it is necessary to +// call virtual functions in the host. In that case the access layer +// must do extra work to provide a host vtable for the object when +// it is retrieved so that virtual functions can be called. +// +// When compiling with DACCESS_COMPILE the macros turn into templates +// which replace pointers with smart pointers that know how to fetch +// data from the target process and provide a host process version of it. +// Normal data structure access will transparently receive a host copy +// of the data and proceed, so code such as +// typedef DPTR(Class) PTR_Class; +// PTR_Class cls; +// int val = cls->m_Int; +// will work without modification. The appropriate operators are overloaded +// to provide transparent access, such as the -> operator in this case. +// Note that the convention is to create an appropriate typedef for +// each type that will be accessed. This hides the particular details +// of the type declaration and makes the usage look more like regular code. +// +// The ?PTR classes also have an implicit base type cast operator to +// produce a host-pointer instance of the given type. For example +// Class* cls = PTR_Class(addr); +// works by implicit conversion from the PTR_Class created by wrapping +// to a host-side Class instance. Again, this means that existing code +// can work without modification. +// +// Code Example: +// +// typedef struct _rangesection +// { +// PTR_IJitManager pjit; +// PTR_RangeSection pright; +// PTR_RangeSection pleft; +// ... Other fields omitted ... +// } RangeSection; +// +// RangeSection* pRS = m_RangeTree; +// +// while (pRS != NULL) +// { +// if (currentPC < pRS->LowAddress) +// pRS=pRS->pleft; +// else if (currentPC > pRS->HighAddress) +// pRS=pRS->pright; +// else +// { +// return pRS->pjit; +// } +// } +// +// This code does not require any modifications. The global reference +// provided by m_RangeTree will be a host version of the RangeSection +// instantiated by conversion. The references to pRS->pleft and +// pRS->pright will refer to DPTRs due to the modified declaration. +// In the assignment statement the compiler will automatically use +// the implicit conversion from PTR_RangeSection to RangeSection*, +// causing a host instance to be created. Finally, if an appropriate +// section is found the use of pRS->pjit will cause an implicit +// conversion from PTR_IJitManager to IJitManager. The VPTR code +// will look at target memory to determine the actual derived class +// for the JitManager and instantiate the right class in the host so +// that host virtual functions can be used just as they would in +// the target. +// +// There are situations where code modifications are required, though. +// +// 1. Any time the actual value of an address matters, such as using +// it as a search key in a tree, the target address must be used. +// +// An example of this is the RangeSection tree used to locate JIT +// managers. A portion of this code is shown above. Each +// RangeSection node in the tree describes a range of addresses +// managed by the JitMan. These addresses are just being used as +// values, not to dereference through, so there are not DPTRs. When +// searching the range tree for an address the address used in the +// search must be a target address as that's what values are kept in +// the RangeSections. In the code shown above, currentPC must be a +// target address as the RangeSections in the tree are all target +// addresses. Use dac_cast to retrieve the target address +// of a ?PTR, as well as to convert a host address to the +// target address used to retrieve that particular instance. Do not +// use dac_cast with any raw target pointer types (such as BYTE*). +// +// 2. Any time an address is modified, such as by address arithmetic, +// the arithmetic must be performed on the target address. +// +// When a host instance is created it is created for the type in use. +// There is no particular relation to any other instance, so address +// arithmetic cannot be used to get from one instance to any other +// part of memory. For example +// char* Func(Class* cls) +// { +// // String follows the basic Class data. +// return (char*)(cls + 1); +// } +// does not work with external access because the Class* used would +// have retrieved only a Class worth of data. There is no string +// following the host instance. Instead, this code should use +// dac_cast to get the target address of the Class +// instance, add sizeof(*cls) and then create a new ?PTR to access +// the desired data. Note that the newly retrieved data will not +// be contiguous with the Class instance, so address arithmetic +// will still not work. +// +// Previous Code: +// +// BOOL IsTarget(LPVOID ip) +// { +// StubCallInstrs* pStubCallInstrs = GetStubCallInstrs(); +// +// if (ip == (LPVOID) &(pStubCallInstrs->m_op)) +// { +// return TRUE; +// } +// +// Modified Code: +// +// BOOL IsTarget(LPVOID ip) +// { +// StubCallInstrs* pStubCallInstrs = GetStubCallInstrs(); +// +// if ((TADDR)ip == dac_cast(pStubCallInstrs) + +// (TADDR)offsetof(StubCallInstrs, m_op)) +// { +// return TRUE; +// } +// +// The parameter ip is a target address, so the host pStubCallInstrs +// cannot be used to derive an address from. The member & reference +// has to be replaced with a conversion from host to target address +// followed by explicit offsetting for the field. +// +// PTR_HOST_MEMBER_TADDR is a convenience macro that encapsulates +// these two operations, so the above code could also be: +// +// if ((TADDR)ip == +// PTR_HOST_MEMBER_TADDR(StubCallInstrs, pStubCallInstrs, m_op)) +// +// 3. Any time the amount of memory referenced through an address +// changes, such as by casting to a different type, a new ?PTR +// must be created. +// +// Host instances are created and stored based on both the target +// address and size of access. The access code has no way of knowing +// all possible ways that data will be retrieved for a given address +// so if code changes the way it accesses through an address a new +// ?PTR must be used, which may lead to a difference instance and +// different host address. This means that pointer identity does not hold +// across casts, so code like +// Class* cls = PTR_Class(addr); +// Class2* cls2 = PTR_Class2(addr); +// return cls == cls2; +// will fail because the host-side instances have no relation to each +// other. That isn't a problem, since by rule #1 you shouldn't be +// relying on specific host address values. +// +// Previous Code: +// +// return (ArrayClass *) m_pMethTab->GetClass(); +// +// Modified Code: +// +// return PTR_ArrayClass(m_pMethTab->GetClass()); +// +// The ?PTR templates have an implicit conversion from a host pointer +// to a target address, so the cast above constructs a new +// PTR_ArrayClass by implicitly converting the host pointer result +// from GetClass() to its target address and using that as the address +// of the new PTR_ArrayClass. As mentioned, the actual host-side +// pointer values may not be the same. +// +// Host pointer identity can be assumed as long as the type of access +// is the same. In the example above, if both accesses were of type +// Class then the host pointer will be the same, so it is safe to +// retrieve the target address of an instance and then later get +// a new host pointer for the target address using the same type as +// the host pointer in that case will be the same. This is enabled +// by caching all of the retrieved host instances. This cache is searched +// by the addr:size pair and when there's a match the existing instance +// is reused. This increases performance and also allows simple +// pointer identity to hold. It does mean that host memory grows +// in proportion to the amount of target memory being referenced, +// so retrieving extraneous data should be avoided. +// The host-side data cache grows until the Flush() method is called, +// at which point all host-side data is discarded. No host +// instance pointers should be held across a Flush(). +// +// Accessing into an object can lead to some unusual behavior. For +// example, the SList class relies on objects to contain an SLink +// instance that it uses for list maintenance. This SLink can be +// embedded anywhere in the larger object. The SList access is always +// purely to an SLink, so when using the access layer it will only +// retrieve an SLink's worth of data. The SList template will then +// do some address arithmetic to determine the start of the real +// object and cast the resulting pointer to the final object type. +// When using the access layer this results in a new ?PTR being +// created and used, so a new instance will result. The internal +// SLink instance will have no relation to the new object instance +// even though in target address terms one is embedded in the other. +// The assumption of data stability means that this won't cause +// a problem, but care must be taken with the address arithmetic, +// as layed out in rules #2 and #3. +// +// 4. Global address references cannot be used. Any reference to a +// global piece of code or data, such as a function address, global +// variable or class static variable, must be changed. +// +// The external access code may load at a different base address than +// the target process code. Global addresses are therefore not +// meaningful and must be replaced with something else. There isn't +// a single solution, so replacements must be done on a case-by-case +// basis. +// +// The simplest case is a global or class static variable. All +// declarations must be replaced with a special declaration that +// compiles into a modified accessor template value when compiled for +// external data access. Uses of the variable automatically are fixed +// up by the template instance. Note that assignment to the global +// must be independently ifdef'ed as the external access layer should +// not make any modifications. +// +// Macros allow for simple declaration of a class static and global +// values that compile into an appropriate templated value. +// +// Previous Code: +// +// static RangeSection* m_RangeTree; +// RangeSection* ExecutionManager::m_RangeTree; +// +// extern ThreadStore* g_pThreadStore; +// ThreadStore* g_pThreadStore = &StaticStore; +// class SystemDomain : public BaseDomain { +// ... +// ArrayListStatic m_appDomainIndexList; +// ... +// } +// +// SystemDomain::m_appDomainIndexList; +// +// extern DWORD gThreadTLSIndex; +// +// DWORD gThreadTLSIndex = TLS_OUT_OF_INDEXES; +// +// Modified Code: +// +// typedef DPTR(RangeSection) PTR_RangeSection; +// SPTR_DECL(RangeSection, m_RangeTree); +// SPTR_IMPL(RangeSection, ExecutionManager, m_RangeTree); +// +// typedef DPTR(ThreadStore) PTR_ThreadStore +// GPTR_DECL(ThreadStore, g_pThreadStore); +// GPTR_IMPL_INIT(ThreadStore, g_pThreadStore, &StaticStore); +// +// class SystemDomain : public BaseDomain { +// ... +// SVAL_DECL(ArrayListStatic; m_appDomainIndexList); +// ... +// } +// +// SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList); +// +// GVAL_DECL(DWORD, gThreadTLSIndex); +// +// GVAL_IMPL_INIT(DWORD, gThreadTLSIndex, TLS_OUT_OF_INDEXES); +// +// When declaring the variable, the first argument declares the +// variable's type and the second argument declares the variable's +// name. When defining the variable the arguments are similar, with +// an extra class name parameter for the static class variable case. +// If an initializer is needed the IMPL_INIT macro should be used. +// +// Things get slightly more complicated when declaring an embedded +// array. In this case the data element is not a single element and +// therefore cannot be represented by a ?PTR. In the case of a global +// array, you should use the GARY_DECL and GARY_IMPL macros. +// We durrently have no support for declaring static array data members +// or initialized arrays. Array data members that are dynamically allocated +// need to be treated as pointer members. To reference individual elements +// you must use pointer arithmetic (see rule 2 above). An array declared +// as a local variable within a function does not need to be DACized. +// +// +// All uses of ?VAL_DECL must have a corresponding entry given in the +// DacGlobals structure in src\inc\dacvars.h. For SVAL_DECL the entry +// is class__name. For GVAL_DECL the entry is dac__name. You must add +// these entries in dacvars.h using the DEFINE_DACVAR macro. Note that +// these entries also are used for dumping memory in mini dumps and +// heap dumps. If it's not appropriate to dump a variable, (e.g., +// it's an array or some other value that is not important to have +// in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow +// you to make the required entry in the DacGlobals structure without +// dumping its value. +// +// For convenience, here is a list of the various variable declaration and +// initialization macros: +// SVAL_DECL(type, name) static non-pointer data class MyClass +// member declared within { +// the class declaration // static int i; +// SVAL_DECL(int, i); +// } +// +// SVAL_IMPL(type, cls, name) static non-pointer data // int MyClass::i; +// member defined outside SVAL_IMPL(int, MyClass, i); +// the class declaration +// +// SVAL_IMPL_INIT(type, cls, static non-pointer data // int MyClass::i = 0; +// name, val) member defined and SVAL_IMPL_INIT(int, MyClass, i, 0); +// initialized outside the +// class declaration +// ------------------------------------------------------------------------------------------------ +// SPTR_DECL(type, name) static pointer data class MyClass +// member declared within { +// the class declaration // static int * pInt; +// SPTR_DECL(int, pInt); +// } +// +// SPTR_IMPL(type, cls, name) static pointer data // int * MyClass::pInt; +// member defined outside SPTR_IMPL(int, MyClass, pInt); +// the class declaration +// +// SPTR_IMPL_INIT(type, cls, static pointer data // int * MyClass::pInt = NULL; +// name, val) member defined and SPTR_IMPL_INIT(int, MyClass, pInt, NULL); +// initialized outside the +// class declaration +// ------------------------------------------------------------------------------------------------ +// GVAL_DECL(type, name) extern declaration of // extern int g_i +// global non-pointer GVAL_DECL(int, g_i); +// variable +// +// GVAL_IMPL(type, name) declaration of a // int g_i +// global non-pointer GVAL_IMPL(int, g_i); +// variable +// +// GVAL_IMPL_INIT (type, declaration and // int g_i = 0; +// name, initialization of a GVAL_IMPL_INIT(int, g_i, 0); +// val) global non-pointer +// variable +// ****Note**** +// If you use GVAL_? to declare a global variable of a structured type and you need to +// access a member of the type, you cannot use the dot operator. Instead, you must take the +// address of the variable and use the arrow operator. For example: +// struct +// { +// int x; +// char ch; +// } MyStruct; +// GVAL_IMPL(MyStruct, g_myStruct); +// int i = (&g_myStruct)->x; +// ------------------------------------------------------------------------------------------------ +// GPTR_DECL(type, name) extern declaration of // extern int * g_pInt +// global pointer GPTR_DECL(int, g_pInt); +// variable +// +// GPTR_IMPL(type, name) declaration of a // int * g_pInt +// global pointer GPTR_IMPL(int, g_pInt); +// variable +// +// GPTR_IMPL_INIT (type, declaration and // int * g_pInt = 0; +// name, initialization of a GPTR_IMPL_INIT(int, g_pInt, NULL); +// val) global pointer +// variable +// ------------------------------------------------------------------------------------------------ +// GARY_DECL(type, name) extern declaration of // extern int g_rgIntList[MAX_ELEMENTS]; +// a global array GPTR_DECL(int, g_rgIntList, MAX_ELEMENTS); +// variable +// +// GARY_IMPL(type, name) declaration of a // int g_rgIntList[MAX_ELEMENTS]; +// global pointer GPTR_IMPL(int, g_rgIntList, MAX_ELEMENTS); +// variable +// +// +// Certain pieces of code, such as the stack walker, rely on identifying +// an object from its vtable address. As the target vtable addresses +// do not necessarily correspond to the vtables used in the host, these +// references must be translated. The access layer maintains translation +// tables for all classes used with VPTR and can return the target +// vtable pointer for any host vtable in the known list of VPTR classes. +// +// ----- Errors: +// +// All errors in the access layer are reported via exceptions. The +// formal access layer methods catch all such exceptions and turn +// them into the appropriate error, so this generally isn't visible +// to users of the access layer. +// +// ----- DPTR Declaration: +// +// Create a typedef for the type with typedef DPTR(type) PTR_type; +// Replace type* with PTR_type. +// +// ----- VPTR Declaration: +// +// VPTR can only be used on classes that have a single vtable +// pointer at the beginning of the object. This should be true +// for a normal single-inheritance object. +// +// All of the classes that may be instantiated need to be identified +// and marked. In the base class declaration add either +// VPTR_BASE_VTABLE_CLASS if the class is abstract or +// VPTR_BASE_CONCRETE_VTABLE_CLASS if the class is concrete. In each +// derived class add VPTR_VTABLE_CLASS. If you end up with compile or +// link errors for an unresolved method called VPtrSize you missed a +// derived class declaration. +// +// As described above, dac can only handle classes with a single +// vtable. However, there's a special case for multiple inheritance +// situations when only one of the classes is needed for dac. If +// the base class needed is the first class in the derived class's +// layout then it can be used with dac via using the VPTR_MULTI_CLASS +// macros. Use with extreme care. +// +// All classes to be instantiated must be listed in src\inc\vptr_list.h. +// +// Create a typedef for the type with typedef VPTR(type) PTR_type; +// When using a VPTR, replace Class* with PTR_Class. +// +// ----- Specific Macros: +// +// PTR_TO_TADDR(ptr) +// Retrieves the raw target address for a ?PTR. +// See code:dac_cast for the preferred alternative +// +// PTR_HOST_TO_TADDR(host) +// Given a host address of an instance produced by a ?PTR reference, +// return the original target address. The host address must +// be an exact match for an instance. +// See code:dac_cast for the preferred alternative +// +// PTR_HOST_INT_TO_TADDR(host) +// Given a host address which resides somewhere within an instance +// produced by a ?PTR reference (a host interior pointer) return the +// corresponding target address. This is useful for evaluating +// relative pointers (e.g. RelativePointer) where calculating the +// target address requires knowledge of the target address of the +// relative pointer field itself. This lookup is slower than that for +// a non-interior host pointer so use it sparingly. +// +// VPTR_HOST_VTABLE_TO_TADDR(host) +// Given the host vtable pointer for a known VPTR class, return +// the target vtable pointer. +// +// PTR_HOST_MEMBER_TADDR(type, host, memb) +// Retrieves the target address of a host instance pointer and +// offsets it by the given member's offset within the type. +// +// PTR_HOST_INT_MEMBER_TADDR(type, host, memb) +// As above but will work for interior host pointers (see the +// description of PTR_HOST_INT_TO_TADDR for an explanation of host +// interior pointers). +// +// PTR_READ(addr, size) +// Reads a block of memory from the target and returns a host +// pointer for it. Useful for reading blocks of data from the target +// whose size is only known at runtime, such as raw code for a jitted +// method. If the data being read is actually an object, use SPTR +// instead to get better type semantics. +// +// DAC_EMPTY() +// DAC_EMPTY_ERR() +// DAC_EMPTY_RET(retVal) +// DAC_UNEXPECTED() +// Provides an empty method implementation when compiled +// for DACCESS_COMPILE. For example, use to stub out methods needed +// for vtable entries but otherwise unused. +// +// These macros are designed to turn into normal code when compiled +// without DACCESS_COMPILE. +// +//***************************************************************************** + + +#ifndef __daccess_h__ +#define __daccess_h__ + +#include + +#include "switches.h" +#include "safemath.h" +#include "corerror.h" + +#ifndef __in +#include +#endif + +#define DACCESS_TABLE_RESOURCE "COREXTERNALDATAACCESSRESOURCE" + +#ifdef PAL_STDCPP_COMPAT +#include +#else +#include "clr_std/type_traits" +#include "crosscomp.h" +#endif + +// Information stored in the DAC table of interest to the DAC implementation +// Note that this information is shared between all instantiations of ClrDataAccess, so initialize +// it just once in code:ClrDataAccess.GetDacGlobals (rather than use fields in ClrDataAccess); +struct DacTableInfo +{ + // On Windows, the first DWORD is the 32-bit timestamp read out of the runtime dll's debug directory. + // The remaining 3 DWORDS must all be 0. + // On Mac, this is the 16-byte UUID of the runtime dll. + // It is used to validate that mscorwks is the same version as mscordacwks + DWORD dwID0; + DWORD dwID1; + DWORD dwID2; + DWORD dwID3; +}; + +// The header of the DAC table. This includes the number of globals, the number of vptrs, and +// the DacTableInfo structure. We need the DacTableInfo and DacTableHeader structs outside +// of a DACCESS_COMPILE since soshost walks the Dac table headers to find the UUID of CoreCLR +// in the target process. +struct DacTableHeader +{ + ULONG numGlobals; + ULONG numVptrs; + DacTableInfo info; +}; + +// +// This version of things wraps pointer access in +// templates which understand how to retrieve data +// through an access layer. In this case no assumptions +// can be made that the current compilation processor or +// pointer types match the target's processor or pointer types. +// + +// Define TADDR as a non-pointer value so use of it as a pointer +// will not work properly. Define it as unsigned so +// pointer comparisons aren't affected by sign. +// This requires special casting to ULONG64 to sign-extend if necessary. +typedef ULONG_PTR TADDR; + +// TSIZE_T used for counts or ranges that need to span the size of a +// target pointer. For cross-plat, this may be different than SIZE_T +// which reflects the host pointer size. +typedef SIZE_T TSIZE_T; + + +// +// The following table contains all the global information that data access needs to begin +// operation. All of the values stored here are RVAs. DacGlobalBase() returns the current +// base address to combine with to get a full target address. +// + +typedef struct _DacGlobals +{ +#ifdef FEATURE_PAL + static void Initialize(); + void InitializeEntries(TADDR baseAddress); +#endif // FEATURE_PAL + +// These will define all of the dac related mscorwks static and global variables +#define DEFINE_DACVAR(id_type, size, id, var) id_type id; +#define DEFINE_DACVAR_NO_DUMP(id_type, size, id, var) id_type id; +#include "dacvars.h" + + // Global functions. + ULONG fn__ThreadpoolMgr__AsyncTimerCallbackCompletion; + ULONG fn__DACNotifyCompilationFinished; + ULONG fn__ThePreStub; + +#ifdef _TARGET_ARM_ + ULONG fn__ThePreStubCompactARM; +#endif // _TARGET_ARM_ + + ULONG fn__ThePreStubPatchLabel; + ULONG fn__PrecodeFixupThunk; +#ifdef FEATURE_PREJIT + ULONG fn__StubDispatchFixupStub; + ULONG fn__StubDispatchFixupPatchLabel; +#endif +#ifdef FEATURE_COMINTEROP + ULONG fn__Unknown_AddRef; + ULONG fn__Unknown_AddRefSpecial; + ULONG fn__Unknown_AddRefInner; +#endif + + // Vtable pointer values for all classes that must + // be instanted using vtable pointers as the identity. +#define VPTR_CLASS(name) ULONG name##__vtAddr; +#define VPTR_MULTI_CLASS(name, keyBase) ULONG name##__##keyBase##__mvtAddr; +#include +#undef VPTR_CLASS +#undef VPTR_MULTI_CLASS +} DacGlobals; + +#ifdef DACCESS_COMPILE + +extern DacTableInfo g_dacTableInfo; +extern DacGlobals g_dacGlobals; + +#ifdef __cplusplus +extern "C" { +#endif + +// These two functions are largely just for marking code +// that is not fully converted. DacWarning prints a debug +// message, while DacNotImpl throws a not-implemented exception. +void __cdecl DacWarning(__in __in_z char* format, ...); +void DacNotImpl(void); + +void DacError(HRESULT err); +void DECLSPEC_NORETURN DacError_NoRet(HRESULT err); +TADDR DacGlobalBase(void); +HRESULT DacReadAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx); +HRESULT DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx); +HRESULT DacAllocVirtual(TADDR addr, ULONG32 size, + ULONG32 typeFlags, ULONG32 protectFlags, + bool throwEx, TADDR* mem); +HRESULT DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags, + bool throwEx); +PVOID DacInstantiateTypeByAddress(TADDR addr, ULONG32 size, bool throwEx); +PVOID DacInstantiateTypeByAddressNoReport(TADDR addr, ULONG32 size, bool throwEx); +PVOID DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx); + +// Copy a null-terminated ascii or unicode string from the target to the host. +// Note that most of the work here is to find the null terminator. If you know the exact length, +// then you can also just call DacInstantiateTypebyAddress. +PSTR DacInstantiateStringA(TADDR addr, ULONG32 maxChars, bool throwEx); +PWSTR DacInstantiateStringW(TADDR addr, ULONG32 maxChars, bool throwEx); + +TADDR DacGetTargetAddrForHostAddr(LPCVOID ptr, bool throwEx); +TADDR DacGetTargetAddrForHostInteriorAddr(LPCVOID ptr, bool throwEx); +TADDR DacGetTargetVtForHostVt(LPCVOID vtHost, bool throwEx); +PWSTR DacGetVtNameW(TADDR targetVtable); + +// Report a region of memory to the debugger +bool DacEnumMemoryRegion(TADDR addr, TSIZE_T size, bool fExpectSuccess = true); + +// Report a region of memory to the debugger +bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer); + +HRESULT DacWriteHostInstance(PVOID host, bool throwEx); + +// This is meant to mimic the RethrowTerminalExceptions/ +// SwallowAllExceptions/RethrowTransientExceptions macros to allow minidump +// gathering cancelation for details see +// code:ClrDataAccess.EnumMemoryRegionsWrapper + +// This is usable in EX_TRY exactly how RethrowTerminalExceptions et cetera +#define RethrowCancelExceptions \ + if (GET_EXCEPTION()->GetHR() == COR_E_OPERATIONCANCELED) \ + { \ + EX_RETHROW; \ + } + +// Occasionally it's necessary to allocate some host memory for +// instance data that's created on the fly and so doesn't directly +// correspond to target memory. These are held and freed on flush +// like other instances but can't be looked up by address. +PVOID DacAllocHostOnlyInstance(ULONG32 size, bool throwEx); + +// Determines whether ASSERTs should be raised when inconsistencies in the target are detected +bool DacTargetConsistencyAssertsEnabled(); + +// Host instances can be marked as they are enumerated in +// order to break cycles. This function returns true if +// the instance is already marked, otherwise it marks the +// instance and returns false. +bool DacHostPtrHasEnumMark(LPCVOID host); + +// Determines if EnumMemoryRegions has been called on a method descriptor. +// This helps perf for minidumps of apps with large managed stacks. +bool DacHasMethodDescBeenEnumerated(LPCVOID pMD); + +// Sets a flag indicating that EnumMemoryRegions on a method desciptor +// has been successfully called. The function returns true if +// this flag had been previously set. +bool DacSetMethodDescEnumerated(LPCVOID pMD); + +// Determines if a method descriptor is valid +BOOL DacValidateMD(LPCVOID pMD); + +// Enumerate the instructions around a call site to help debugger stack walking heuristics +void DacEnumCodeForStackwalk(TADDR taCallEnd); + +// Given the address and the size of a memory range which is stored in the buffer, replace all the patches +// in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to +// disassemble the native instructions. +class MemoryRange; +HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); + +// +// Convenience macros for EnumMemoryRegions implementations. +// + +// Enumerate the given host instance and return +// true if the instance hasn't already been enumerated. +#define DacEnumHostDPtrMem(host) \ + (!DacHostPtrHasEnumMark(host) ? \ + (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), sizeof(*host)), \ + true) : false) +#define DacEnumHostSPtrMem(host, type) \ + (!DacHostPtrHasEnumMark(host) ? \ + (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), \ + type::DacSize(PTR_HOST_TO_TADDR(host))), \ + true) : false) +#define DacEnumHostVPtrMem(host) \ + (!DacHostPtrHasEnumMark(host) ? \ + (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), (host)->VPtrSize()), \ + true) : false) + +// Check enumeration of 'this' and return if this has already been +// enumerated. Making this the first line of an object's EnumMemoryRegions +// method will prevent cycles. +#define DAC_CHECK_ENUM_THIS() \ + if (DacHostPtrHasEnumMark(this)) return +#define DAC_ENUM_DTHIS() \ + if (!DacEnumHostDPtrMem(this)) return +#define DAC_ENUM_STHIS(type) \ + if (!DacEnumHostSPtrMem(this, type)) return +#define DAC_ENUM_VTHIS() \ + if (!DacEnumHostVPtrMem(this)) return + +#ifdef __cplusplus +} +class ReflectionModule; +interface IMDInternalImport* DacGetMDImport(const class PEFile* peFile, + bool throwEx); +interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule, + bool throwEx); + +int DacGetIlMethodSize(TADDR methAddr); +struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr); +#ifdef WIN64EXCEPTIONS +struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo); + +// virtually unwind a CONTEXT out-of-process +struct _KNONVOLATILE_CONTEXT_POINTERS; +BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers); +#endif // WIN64EXCEPTIONS + +#if defined(FEATURE_PAL) +// call back through data target to unwind out-of-process +HRESULT DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers); +#endif // FEATURE_PAL + +#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +class SString; +void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName); +bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName); +#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS + +// +// Computes (taBase + (dwIndex * dwElementSize()), with overflow checks. +// +// Arguments: +// taBase the base TADDR value +// dwIndex the index of the offset +// dwElementSize the size of each element (to multiply the offset by) +// +// Return value: +// The resulting TADDR, or throws CORDB_E_TARGET_INCONSISTENT on overlow. +// +// Notes: +// The idea here is that overflows during address arithmetic suggest that we're operating on corrupt +// pointers. It helps to improve reliability to detect the cases we can (like overflow) and fail. Note +// that this is just a heuristic, not a security measure. We can't trust target data regardless - +// failing on overflow is just one easy case of corruption to detect. There is no need to use checked +// arithmetic everywhere in the DAC infrastructure, this is intended just for the places most likely to +// help catch bugs (eg. __DPtr::operator[]). +// +inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSize ) +{ + ClrSafeInt t(taBase); + t += ClrSafeInt(dwIndex) * ClrSafeInt(dwElementSize); + if( t.IsOverflow() ) + { + // Pointer arithmetic overflow - probably due to corrupt target data + DacError(CORDBG_E_TARGET_INCONSISTENT); + } + return t.Value(); +} + + +// Base pointer wrapper which provides common behavior. +class __TPtrBase +{ +public: + __TPtrBase(void) + { + // Make uninitialized pointers obvious. + m_addr = (TADDR)-1; + } + __TPtrBase(TADDR addr) + { + m_addr = addr; + } + + bool operator!() const + { + return m_addr == 0; + } + // We'd like to have an implicit conversion to bool here since the C++ + // standard says all pointer types are implicitly converted to bool. + // Unfortunately, that would cause ambiguous overload errors for uses + // of operator== and operator!=. Instead callers will have to compare + // directly against NULL. + + bool operator==(TADDR addr) const + { + return m_addr == addr; + } + bool operator!=(TADDR addr) const + { + return m_addr != addr; + } + bool operator<(TADDR addr) const + { + return m_addr < addr; + } + bool operator>(TADDR addr) const + { + return m_addr > addr; + } + bool operator<=(TADDR addr) const + { + return m_addr <= addr; + } + bool operator>=(TADDR addr) const + { + return m_addr >= addr; + } + + TADDR GetAddr(void) const + { + return m_addr; + } + TADDR SetAddr(TADDR addr) + { + m_addr = addr; + return addr; + } + +protected: + TADDR m_addr; +}; + +// Pointer wrapper base class for various forms of normal data. +// This has the common functionality between __DPtr and __ArrayDPtr. +// The DPtrType type parameter is the actual derived type in use. This is necessary so that +// inhereted functions preserve exact return types. +template +class __DPtrBase : public __TPtrBase +{ +public: + typedef type _Type; + typedef type* _Ptr; + +protected: + // Constructors + // All protected - this type should not be used directly - use one of the derived types instead. + __DPtrBase< type, DPtrType >(void) : __TPtrBase() {} + __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {} + + explicit __DPtrBase< type, DPtrType >(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + explicit __DPtrBase< type, DPtrType >(type const * host) + { + m_addr = DacGetTargetAddrForHostAddr(host, true); + } + +public: + DPtrType& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return DPtrType(m_addr); + } + DPtrType& operator=(TADDR addr) + { + m_addr = addr; + return DPtrType(m_addr); + } + + type& operator*(void) const + { + return *(type*)DacInstantiateTypeByAddress(m_addr, sizeof(type), true); + } + + bool operator==(const DPtrType& ptr) const + { + return m_addr == ptr.GetAddr(); + } + bool operator==(TADDR addr) const + { + return m_addr == addr; + } + bool operator!=(const DPtrType& ptr) const + { + return !operator==(ptr); + } + bool operator!=(TADDR addr) const + { + return m_addr != addr; + } + bool operator<(const DPtrType& ptr) const + { + return m_addr < ptr.GetAddr(); + } + bool operator>(const DPtrType& ptr) const + { + return m_addr > ptr.GetAddr(); + } + bool operator<=(const DPtrType& ptr) const + { + return m_addr <= ptr.GetAddr(); + } + bool operator>=(const DPtrType& ptr) const + { + return m_addr >= ptr.GetAddr(); + } + + // Array index operator + // we want an operator[] for all possible numeric types (rather than rely on + // implicit numeric conversions on the argument) to prevent ambiguity with + // DPtr's implicit conversion to type* and the built-in operator[]. + // @dbgtodo : we could also use this technique to simplify other operators below. + template + type& operator[](indexType index) + { + // Compute the address of the element. + TADDR elementAddr; + if( index >= 0 ) + { + elementAddr = DacTAddrOffset(m_addr, index, sizeof(type)); + } + else + { + // Don't bother trying to do overflow checking for negative indexes - they are rare compared to + // positive ones. ClrSafeInt doesn't support signed datatypes yet (although we should be able to add it + // pretty easily). + elementAddr = m_addr + index * sizeof(type); + } + + // Marshal over a single instance and return a reference to it. + return *(type*) DacInstantiateTypeByAddress(elementAddr, sizeof(type), true); + } + + template + type const & operator[](indexType index) const + { + return (*const_cast<__DPtrBase*>(this))[index]; + } + + //------------------------------------------------------------------------- + // operator+ + + DPtrType operator+(unsigned short val) + { + return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); + } + DPtrType operator+(short val) + { + return DPtrType(m_addr + val * sizeof(type)); + } + // size_t is unsigned int on Win32, so we need + // to ifdef here to make sure the unsigned int + // and size_t overloads don't collide. size_t + // is marked __w64 so a simple unsigned int + // will not work on Win32, it has to be size_t. + DPtrType operator+(size_t val) + { + return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); + } +#if defined (_WIN64) + DPtrType operator+(unsigned int val) + { + return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); + } +#endif + DPtrType operator+(int val) + { + return DPtrType(m_addr + val * sizeof(type)); + } + // Because of the size difference between long and int on non MS compilers, + // we only need to define these operators on Windows. These provide compatible + // overloads for DWORD addition operations. +#ifdef _MSC_VER + DPtrType operator+(unsigned long val) + { + return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); + } + DPtrType operator+(long val) + { + return DPtrType(m_addr + val * sizeof(type)); + } +#endif + + //------------------------------------------------------------------------- + // operator- + + DPtrType operator-(unsigned short val) + { + return DPtrType(m_addr - val * sizeof(type)); + } + DPtrType operator-(short val) + { + return DPtrType(m_addr - val * sizeof(type)); + } + // size_t is unsigned int on Win32, so we need + // to ifdef here to make sure the unsigned int + // and size_t overloads don't collide. size_t + // is marked __w64 so a simple unsigned int + // will not work on Win32, it has to be size_t. + DPtrType operator-(size_t val) + { + return DPtrType(m_addr - val * sizeof(type)); + } +#ifdef _WIN64 + DPtrType operator-(unsigned int val) + { + return DPtrType(m_addr - val * sizeof(type)); + } +#endif + DPtrType operator-(int val) + { + return DPtrType(m_addr - val * sizeof(type)); + } + // Because of the size difference between long and int on non MS compilers, + // we only need to define these operators on Windows. These provide compatible + // overloads for DWORD addition operations. +#ifdef _MSC_VER // for now, everything else is 32 bit + DPtrType operator-(unsigned long val) + { + return DPtrType(m_addr - val * sizeof(type)); + } + DPtrType operator-(long val) + { + return DPtrType(m_addr - val * sizeof(type)); + } +#endif + size_t operator-(const DPtrType& val) + { + return (m_addr - val.m_addr) / sizeof(type); + } + + //------------------------------------------------------------------------- + + DPtrType& operator+=(size_t val) + { + m_addr += val * sizeof(type); + return static_cast(*this); + } + DPtrType& operator-=(size_t val) + { + m_addr -= val * sizeof(type); + return static_cast(*this); + } + + DPtrType& operator++() + { + m_addr += sizeof(type); + return static_cast(*this); + } + DPtrType& operator--() + { + m_addr -= sizeof(type); + return static_cast(*this); + } + DPtrType operator++(int postfix) + { + DPtrType orig = DPtrType(*this); + m_addr += sizeof(type); + return orig; + } + DPtrType operator--(int postfix) + { + DPtrType orig = DPtrType(*this); + m_addr -= sizeof(type); + return orig; + } + + bool IsValid(void) const + { + return m_addr && + DacInstantiateTypeByAddress(m_addr, sizeof(type), + false) != NULL; + } + void EnumMem(void) const + { + DacEnumMemoryRegion(m_addr, sizeof(type)); + } +}; + +// forward declaration +template +class __GlobalPtr; + +// Pointer wrapper for objects which are just plain data +// and need no special handling. +template +class __DPtr : public __DPtrBase > +{ +public: + // constructors - all chain to __DPtrBase constructors + __DPtr< type >(void) : __DPtrBase >() {} + __DPtr< type >(TADDR addr) : __DPtrBase >(addr) {} + + // construct const from non-const + typedef typename std::remove_const::type mutable_type; + __DPtr< type >(__DPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} + + // construct from GlobalPtr + explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) : + __DPtrBase >(globalPtr.GetAddr()) {} + + explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} + explicit __DPtr< type >(type const * host) : __DPtrBase >(host) {} + + operator type*() const + { + return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); + } + type* operator->() const + { + return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); + } +}; + +#define DPTR(type) __DPtr< type > + +// A restricted form of DPtr that doesn't have any conversions to pointer types. +// This is useful for pointer types that almost always represent arrays, as opposed +// to pointers to single instances (eg. PTR_BYTE). In these cases, allowing implicit +// conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer +// arithmetic and array indexing), since only a single instance has been marshalled to the host. +// If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now), +// then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code. +template +class __ArrayDPtr : public __DPtrBase > +{ +public: + // constructors - all chain to __DPtrBase constructors + __ArrayDPtr< type >(void) : __DPtrBase >() {} + __ArrayDPtr< type >(TADDR addr) : __DPtrBase >(addr) {} + + // construct const from non-const + typedef typename std::remove_const::type mutable_type; + __ArrayDPtr< type >(__ArrayDPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} + + explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} + + // Note that there is also no explicit constructor from host instances (type*). + // Going this direction is less problematic, but often still represents risky coding. +}; + +#define ArrayDPTR(type) __ArrayDPtr< type > + + +// Pointer wrapper for objects which are just plain data +// but whose size is not the same as the base type size. +// This can be used for prefetching data for arrays or +// for cases where an object has a variable size. +template +class __SPtr : public __TPtrBase +{ +public: + typedef type _Type; + typedef type* _Ptr; + + __SPtr< type >(void) : __TPtrBase() {} + __SPtr< type >(TADDR addr) : __TPtrBase(addr) {} + explicit __SPtr< type >(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + explicit __SPtr< type >(type* host) + { + m_addr = DacGetTargetAddrForHostAddr(host, true); + } + + __SPtr< type >& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return *this; + } + __SPtr< type >& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + operator type*() const + { + if (m_addr) + { + return (type*)DacInstantiateTypeByAddress(m_addr, + type::DacSize(m_addr), + true); + } + else + { + return (type*)NULL; + } + } + type* operator->() const + { + if (m_addr) + { + return (type*)DacInstantiateTypeByAddress(m_addr, + type::DacSize(m_addr), + true); + } + else + { + return (type*)NULL; + } + } + type& operator*(void) const + { + if (!m_addr) + { + DacError(E_INVALIDARG); + } + + return *(type*)DacInstantiateTypeByAddress(m_addr, + type::DacSize(m_addr), + true); + } + + bool IsValid(void) const + { + return m_addr && + DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), + false) != NULL; + } + void EnumMem(void) const + { + if (m_addr) + { + DacEnumMemoryRegion(m_addr, type::DacSize(m_addr)); + } + } +}; + +#define SPTR(type) __SPtr< type > + +// Pointer wrapper for objects which have a single leading +// vtable, such as objects in a single-inheritance tree. +// The base class of all such trees must have use +// VPTR_BASE_VTABLE_CLASS in their declaration and all +// instantiable members of the tree must be listed in vptr_list.h. +template +class __VPtr : public __TPtrBase +{ +public: + // VPtr::_Type has to be a pointer as + // often the type is an abstract class. + // This type is not expected to be used anyway. + typedef type* _Type; + typedef type* _Ptr; + + __VPtr< type >(void) : __TPtrBase() {} + __VPtr< type >(TADDR addr) : __TPtrBase(addr) {} + explicit __VPtr< type >(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + explicit __VPtr< type >(type* host) + { + m_addr = DacGetTargetAddrForHostAddr(host, true); + } + + __VPtr< type >& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return *this; + } + __VPtr< type >& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + operator type*() const + { + return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); + } + type* operator->() const + { + return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); + } + + bool operator==(const __VPtr< type >& ptr) const + { + return m_addr == ptr.m_addr; + } + bool operator==(TADDR addr) const + { + return m_addr == addr; + } + bool operator!=(const __VPtr< type >& ptr) const + { + return !operator==(ptr); + } + bool operator!=(TADDR addr) const + { + return m_addr != addr; + } + + bool IsValid(void) const + { + return m_addr && + DacInstantiateClassByVTable(m_addr, sizeof(type), false) != NULL; + } + void EnumMem(void) const + { + if (IsValid()) + { + DacEnumMemoryRegion(m_addr, (operator->())->VPtrSize()); + } + } +}; + +#define VPTR(type) __VPtr< type > + +// Pointer wrapper for 8-bit strings. +template +class __Str8Ptr : public __DPtr +{ +public: + typedef type _Type; + typedef type* _Ptr; + + __Str8Ptr< type, maxChars >(void) : __DPtr() {} + __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} + explicit __Str8Ptr< type, maxChars >(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + explicit __Str8Ptr< type, maxChars >(type* host) + { + m_addr = DacGetTargetAddrForHostAddr(host, true); + } + + __Str8Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return *this; + } + __Str8Ptr< type, maxChars >& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + operator type*() const + { + return (type*)DacInstantiateStringA(m_addr, maxChars, true); + } + + bool IsValid(void) const + { + return m_addr && + DacInstantiateStringA(m_addr, maxChars, false) != NULL; + } + void EnumMem(void) const + { + char* str = DacInstantiateStringA(m_addr, maxChars, false); + if (str) + { + DacEnumMemoryRegion(m_addr, strlen(str) + 1); + } + } +}; + +#define S8PTR(type) __Str8Ptr< type > +#define S8PTRMAX(type, maxChars) __Str8Ptr< type, maxChars > + +// Pointer wrapper for 16-bit strings. +template +class __Str16Ptr : public __DPtr +{ +public: + typedef type _Type; + typedef type* _Ptr; + + __Str16Ptr< type, maxChars >(void) : __DPtr() {} + __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} + explicit __Str16Ptr< type, maxChars >(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + explicit __Str16Ptr< type, maxChars >(type* host) + { + m_addr = DacGetTargetAddrForHostAddr(host, true); + } + + __Str16Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return *this; + } + __Str16Ptr< type, maxChars >& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + operator type*() const + { + return (type*)DacInstantiateStringW(m_addr, maxChars, true); + } + + bool IsValid(void) const + { + return m_addr && + DacInstantiateStringW(m_addr, maxChars, false) != NULL; + } + void EnumMem(void) const + { + char* str = DacInstantiateStringW(m_addr, maxChars, false); + if (str) + { + DacEnumMemoryRegion(m_addr, strlen(str) + 1); + } + } +}; + +#define S16PTR(type) __Str16Ptr< type > +#define S16PTRMAX(type, maxChars) __Str16Ptr< type, maxChars > + +template +class __GlobalVal +{ +public: + __GlobalVal< type >(PULONG rvaPtr) + { + m_rvaPtr = rvaPtr; + } + + operator type() const + { + return (type)*__DPtr< type >(DacGlobalBase() + *m_rvaPtr); + } + + __DPtr< type > operator&() const + { + return __DPtr< type >(DacGlobalBase() + *m_rvaPtr); + } + + // @dbgtodo dac support: This updates values in the host. This seems extremely dangerous + // to do silently. I'd prefer that a specific (searchable) write function + // was used. Try disabling this and see what fails... + __GlobalVal & operator=(const type & val) + { + type* ptr = __DPtr< type >(DacGlobalBase() + *m_rvaPtr); + // Update the host copy; + *ptr = val; + // Write back to the target. + DacWriteHostInstance(ptr, true); + return *this; + } + + bool IsValid(void) const + { + return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid(); + } + void EnumMem(void) const + { + TADDR p = DacGlobalBase() + *m_rvaPtr; + __DPtr< type >(p).EnumMem(); + } + +private: + PULONG m_rvaPtr; +}; + +template +class __GlobalArray +{ +public: + __GlobalArray< type, size >(PULONG rvaPtr) + { + m_rvaPtr = rvaPtr; + } + + __DPtr< type > operator&() const + { + return __DPtr< type >(DacGlobalBase() + *m_rvaPtr); + } + + type& operator[](unsigned int index) const + { + return __DPtr< type >(DacGlobalBase() + *m_rvaPtr)[index]; + } + + bool IsValid(void) const + { + // Only validates the base pointer, not the full array range. + return __DPtr< type >(DacGlobalBase() + *m_rvaPtr).IsValid(); + } + void EnumMem(void) const + { + DacEnumMemoryRegion(DacGlobalBase() + *m_rvaPtr, sizeof(type) * size); + } + +private: + PULONG m_rvaPtr; +}; + +template +class __GlobalPtr +{ +public: + __GlobalPtr< acc_type, store_type >(PULONG rvaPtr) + { + m_rvaPtr = rvaPtr; + } + + __DPtr< store_type > operator&() const + { + return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + } + + store_type & operator=(store_type & val) + { + store_type* ptr = __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + // Update the host copy; + *ptr = val; + // Write back to the target. + DacWriteHostInstance(ptr, true); + return val; + } + + acc_type operator->() const + { + return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + } + operator acc_type() const + { + return (acc_type)*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + } + operator store_type() const + { + return *__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + } + bool operator!() const + { + return !*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr); + } + + typename store_type::_Type& operator[](int index) + { + return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index]; + } + + typename store_type::_Type& operator[](unsigned int index) + { + return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr))[index]; + } + + TADDR GetAddr() const + { + return (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).GetAddr(); + } + + TADDR GetAddrRaw () const + { + return DacGlobalBase() + *m_rvaPtr; + } + + // This is only testing the the pointer memory is available but does not verify + // the memory that it points to. + // + bool IsValidPtr(void) const + { + return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid(); + } + + bool IsValid(void) const + { + return __DPtr< store_type >(DacGlobalBase() + *m_rvaPtr).IsValid() && + (*__DPtr< store_type >(DacGlobalBase() + *m_rvaPtr)).IsValid(); + } + void EnumMem(void) const + { + __DPtr< store_type > ptr(DacGlobalBase() + *m_rvaPtr); + ptr.EnumMem(); + if (ptr.IsValid()) + { + (*ptr).EnumMem(); + } + } + + PULONG m_rvaPtr; +}; + +template +inline bool operator==(const __GlobalPtr& gptr, + acc_type host) +{ + return DacGetTargetAddrForHostAddr(host, true) == + *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr); +} +template +inline bool operator!=(const __GlobalPtr& gptr, + acc_type host) +{ + return !operator==(gptr, host); +} + +template +inline bool operator==(acc_type host, + const __GlobalPtr& gptr) +{ + return DacGetTargetAddrForHostAddr(host, true) == + *__DPtr< TADDR >(DacGlobalBase() + *gptr.m_rvaPtr); +} +template +inline bool operator!=(acc_type host, + const __GlobalPtr& gptr) +{ + return !operator==(host, gptr); +} + + +// +// __VoidPtr is a type that behaves like void* but for target pointers. +// Behavior of PTR_VOID: +// * has void* semantics. Will compile to void* in non-DAC builds (just like +// other PTR types. Unlike TADDR, we want pointer semantics. +// * NOT assignable from host pointer types or convertible to host pointer +// types - ensures we can't confuse host and target pointers (we'll get +// compiler errors if we try and cast between them). +// * like void*, no pointer arithmetic or dereferencing is allowed +// * like TADDR, can be used to construct any __DPtr / __VPtr instance +// * representation is the same as a void* (for marshalling / casting) +// +// One way in which __VoidPtr is unlike void* is that it can't be cast to +// pointer or integer types. On the one hand, this is a good thing as it forces +// us to keep target pointers separate from other data types. On the other hand +// in practice this means we have to use dac_cast in places where we used +// to use a (TADDR) cast. Unfortunately C++ provides us no way to allow the +// explicit cast to primitive types without also allowing implicit conversions. +// +// This is very similar in spirit to TADDR. The primary difference is that +// PTR_VOID has pointer semantics, where TADDR has integer semantics. When +// dacizing uses of void* to TADDR, casts must be inserted everywhere back to +// pointer types. If we switch a use of TADDR to PTR_VOID, those casts in +// DACCESS_COMPILE regions no longer compile (see above). Also, TADDR supports +// pointer arithmetic, but that might not be necessary (could use PTR_BYTE +// instead etc.). Ideally we'd probably have just one type for this purpose +// (named TADDR but with the semantics of PTR_VOID), but outright conversion +// would require too much work. +// +class __VoidPtr : public __TPtrBase +{ +public: + __VoidPtr(void) : __TPtrBase() {} + __VoidPtr(TADDR addr) : __TPtrBase(addr) {} + + // Note, unlike __DPtr, this ctor form is not explicit. We allow implicit + // conversions from any pointer type (just like for void*). + __VoidPtr(__TPtrBase addr) + { + m_addr = addr.GetAddr(); + } + + // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs + template + __VoidPtr(__GlobalPtr globalPtr) + { + m_addr = globalPtr.GetAddr(); + } + + // Note, unlike __DPtr, there is no explicit conversion from host pointer + // types. Since void* cannot be marshalled, there is no such thing as + // a void* DAC instance in the host. + + // Also, we don't want an implicit conversion to TADDR because then the + // compiler will allow pointer arithmetic (which it wouldn't allow for + // void*). Instead, callers can use dac_cast if they want. + + // Note, unlike __DPtr, any pointer type can be assigned to a __VoidPtr + // This is to mirror the assignability of any pointer type to a void* + __VoidPtr& operator=(const __TPtrBase& ptr) + { + m_addr = ptr.GetAddr(); + return *this; + } + __VoidPtr& operator=(TADDR addr) + { + m_addr = addr; + return *this; + } + + // note, no marshalling operators (type* conversion, operator ->, operator*) + // A void* can't be marshalled because we don't know how much to copy + + // PTR_Void can be compared to any other pointer type (because conceptually, + // any other pointer type should be implicitly convertible to void*) + bool operator==(const __TPtrBase& ptr) const + { + return m_addr == ptr.GetAddr(); + } + bool operator==(TADDR addr) const + { + return m_addr == addr; + } + bool operator!=(const __TPtrBase& ptr) const + { + return !operator==(ptr); + } + bool operator!=(TADDR addr) const + { + return m_addr != addr; + } + bool operator<(const __TPtrBase& ptr) const + { + return m_addr < ptr.GetAddr(); + } + bool operator>(const __TPtrBase& ptr) const + { + return m_addr > ptr.GetAddr(); + } + bool operator<=(const __TPtrBase& ptr) const + { + return m_addr <= ptr.GetAddr(); + } + bool operator>=(const __TPtrBase& ptr) const + { + return m_addr >= ptr.GetAddr(); + } +}; + +typedef __VoidPtr PTR_VOID; +typedef DPTR(PTR_VOID) PTR_PTR_VOID; + +// For now we treat pointers to const and non-const void the same in DAC +// builds. In general, DAC is read-only anyway and so there isn't a danger of +// writing to these pointers. Also, the non-dac builds will ensure +// const-correctness. However, if we wanted to support true void* / const void* +// behavior, we could probably build the follow functionality by templating +// __VoidPtr: +// * A PTR_VOID would be implicitly convertable to PTR_CVOID +// * An explicit coercion (ideally const_cast) would be required to convert a +// PTR_CVOID to a PTR_VOID +// * Similarily, an explicit coercion would be required to convert a cost PTR +// type (eg. PTR_CBYTE) to a PTR_VOID. +typedef __VoidPtr PTR_CVOID; + + +// The special empty ctor declared here allows the whole +// class hierarchy to be instantiated easily by the +// external access code. The actual class body will be +// read externally so no members should be initialized. + +// +// VPTR_ANY_CLASS_METHODS - Defines the following methods for all VPTR classes +// +// VPtrSize +// Returns the size of the dynamic type of the object (as opposed to sizeof +// which is based only on the static type). +// +// VPtrHostVTable +// Returns the address of the vtable for this type. +// We create a temporary instance of this type in order to read it's vtable pointer +// (at offset 0). For this temporary instance, we do not want to initialize any fields, +// so we use the marshalling ctor. Since we didn't initialize any fields, we also don't +// wan't to run the dtor (marshaled data structures don't normally expect their destructor +// or non-DAC constructors to be called in DAC builds anyway). So, rather than create a +// normal stack object, or put the object on the heap, we create the temporary object +// on the stack using placement-new and alloca, and don't destruct it. +// +#define VPTR_ANY_CLASS_METHODS(name) \ + virtual ULONG32 VPtrSize(void) { SUPPORTS_DAC; return sizeof(name); } \ + static PVOID VPtrHostVTable() { \ + void * pBuf = _alloca(sizeof(name)); \ + name * dummy = new (pBuf) name((TADDR)0, (TADDR)0); \ + return *((PVOID*)dummy); } + +#define VPTR_CLASS_METHODS(name) \ + VPTR_ANY_CLASS_METHODS(name) \ + static TADDR VPtrTargetVTable() { \ + SUPPORTS_DAC; \ + return DacGlobalBase() + g_dacGlobals.name##__vtAddr; } + +#define VPTR_MULTI_CLASS_METHODS(name, keyBase) \ + VPTR_ANY_CLASS_METHODS(name) \ + static TADDR VPtrTargetVTable() { \ + SUPPORTS_DAC; \ + return DacGlobalBase() + g_dacGlobals.name##__##keyBase##__mvtAddr; } + +#define VPTR_VTABLE_CLASS(name, base) \ +public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \ + VPTR_CLASS_METHODS(name) + +#define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \ + VPTR_VTABLE_CLASS(name, base) + +#define VPTR_MULTI_VTABLE_CLASS(name, base) \ +public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \ + VPTR_MULTI_CLASS_METHODS(name, base) + +// Used for base classes that can be instantiated directly. +// The fake vfn is still used to force a vtable even when +// all the normal vfns are ifdef'ed out. +#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \ +public: name(TADDR addr, TADDR vtAddr) {} \ + VPTR_CLASS_METHODS(name) + +#define VPTR_BASE_CONCRETE_VTABLE_CLASS_NO_CTOR_BODY(name) \ +public: name(TADDR addr, TADDR vtAddr); \ + VPTR_CLASS_METHODS(name) + +// The pure virtual method forces all derivations to use +// VPTR_VTABLE_CLASS to compile. +#define VPTR_BASE_VTABLE_CLASS(name) \ +public: name(TADDR addr, TADDR vtAddr) {} \ + virtual ULONG32 VPtrSize(void) = 0; + +#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \ + VPTR_BASE_VTABLE_CLASS(name) + +#define VPTR_BASE_VTABLE_CLASS_NO_CTOR_BODY(name) \ +public: name(TADDR addr, TADDR vtAddr); \ + virtual ULONG32 VPtrSize(void) = 0; + +#define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ +public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} + +#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \ + VPTR_ABSTRACT_VTABLE_CLASS(name, base) + +#define VPTR_ABSTRACT_VTABLE_CLASS_NO_CTOR_BODY(name, base) \ +public: name(TADDR addr, TADDR vtAddr); + +// helper macro to make the vtables unique for DAC +#define VPTR_UNIQUE(unique) + +// Safe access for retrieving the target address of a PTR. +#define PTR_TO_TADDR(ptr) ((ptr).GetAddr()) + +#define GFN_TADDR(name) (DacGlobalBase() + g_dacGlobals.fn__ ## name) + +#define GVAL_ADDR(g) \ + ((g).operator&()) + +// +// References to class static and global data. +// These all need to be redirected through the global +// data table. +// + +#define _SPTR_DECL(acc_type, store_type, var) \ + static __GlobalPtr< acc_type, store_type > var +#define _SPTR_IMPL(acc_type, store_type, cls, var) \ + __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var) +#define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \ + __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.cls##__##var) +#define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \ + __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var) +#define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \ + __GlobalPtr< acc_type, store_type > cls::var(&g_dacGlobals.ns##__##cls##__##var) + +#define _GPTR_DECL(acc_type, store_type, var) \ + extern __GlobalPtr< acc_type, store_type > var +#define _GPTR_IMPL(acc_type, store_type, var) \ + __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var) +#define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \ + __GlobalPtr< acc_type, store_type > var(&g_dacGlobals.dac__##var) + +#define SVAL_DECL(type, var) \ + static __GlobalVal< type > var +#define SVAL_IMPL(type, cls, var) \ + __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var) +#define SVAL_IMPL_INIT(type, cls, var, init) \ + __GlobalVal< type > cls::var(&g_dacGlobals.cls##__##var) +#define SVAL_IMPL_NS(type, ns, cls, var) \ + __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var) +#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \ + __GlobalVal< type > cls::var(&g_dacGlobals.ns##__##cls##__##var) + +#define GVAL_DECL(type, var) \ + extern __GlobalVal< type > var +#define GVAL_IMPL(type, var) \ + __GlobalVal< type > var(&g_dacGlobals.dac__##var) +#define GVAL_IMPL_INIT(type, var, init) \ + __GlobalVal< type > var(&g_dacGlobals.dac__##var) + +#define GARY_DECL(type, var, size) \ + extern __GlobalArray< type, size > var +#define GARY_IMPL(type, var, size) \ + __GlobalArray< type, size > var(&g_dacGlobals.dac__##var) + +// Translation from a host pointer back to the target address +// that was used to retrieve the data for the host pointer. +#define PTR_HOST_TO_TADDR(host) DacGetTargetAddrForHostAddr(host, true) +// Translation from a host interior pointer back to the corresponding +// target address. The host address must reside within a previously +// retrieved instance. +#define PTR_HOST_INT_TO_TADDR(host) DacGetTargetAddrForHostInteriorAddr(host, true) +// Translation from a host vtable pointer to a target vtable pointer. +#define VPTR_HOST_VTABLE_TO_TADDR(host) DacGetTargetVtForHostVt(host, true) + +// Construct a pointer to a member of the given type. +#define PTR_HOST_MEMBER_TADDR(type, host, memb) \ + (PTR_HOST_TO_TADDR(host) + (TADDR)offsetof(type, memb)) + +// Construct a pointer to a member of the given type given an interior +// host address. +#define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) \ + (PTR_HOST_INT_TO_TADDR(host) + (TADDR)offsetof(type, memb)) + +#define PTR_TO_MEMBER_TADDR(type, ptr, memb) \ + (PTR_TO_TADDR(ptr) + (TADDR)offsetof(type, memb)) + +// Constructs an arbitrary data instance for a piece of +// memory in the target. +#define PTR_READ(addr, size) \ + DacInstantiateTypeByAddress(addr, size, true) + +// This value is used to intiailize target pointers to NULL. We want this to be TADDR type +// (as opposed to, say, __TPtrBase) so that it can be used in the non-explicit ctor overloads, +// eg. as an argument default value. +// We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer +// type (causing an ambiguous overload compiler error when used in explicit ctor forms). +#define PTR_NULL ((TADDR)0) + +// Provides an empty method implementation when compiled +// for DACCESS_COMPILE. For example, use to stub out methods needed +// for vtable entries but otherwise unused. +// Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a +// DacCop warning if any calls to them are detected. +// @dbgtodo : It's probably almost always wrong to call any such function, so +// we should probably throw a better error (DacNotImpl), and ideally mark the function +// DECLSPEC_NORETURN so we don't have to deal with fabricating return values and we can +// get compiler warnings (unreachable code) anytime functions marked this way are called. +#define DAC_EMPTY() { LIMITED_METHOD_CONTRACT; } +#define DAC_EMPTY_ERR() { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); } +#define DAC_EMPTY_RET(retVal) { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); return retVal; } +#define DAC_UNEXPECTED() { LIMITED_METHOD_CONTRACT; DacError_NoRet(E_UNEXPECTED); } + +#endif // #ifdef __cplusplus + +// Implementation details for dac_cast, should never be accessed directly. +// See code:dac_cast for details and discussion. +namespace dac_imp +{ + // Helper functions to get the target address of specific types + inline TADDR getTaddr(TADDR addr) { return addr; } + inline TADDR getTaddr(__TPtrBase const &tptr) { return PTR_TO_TADDR(tptr); } + inline TADDR getTaddr(void const * host) { return PTR_HOST_TO_TADDR((void *)host); } + template + inline TADDR getTaddr(__GlobalPtr const &gptr) { return PTR_TO_TADDR(gptr); } + + // It is an error to try dac_cast on a __GlobalVal or a __GlobalArray. Declare + // but do not define the methods so that a compile-time error results. + template + TADDR getTaddr(__GlobalVal const &gval); + template + TADDR getTaddr(__GlobalArray const &garr); + + // Helper class to instantiate DAC instances from a TADDR + // The default implementation assumes we want to create an instance of a PTR type + template struct makeDacInst + { + static inline T fromTaddr(TADDR addr) + { + static_assert((std::is_base_of<__TPtrBase, T>::value), "is_base_of constraint violation"); + return T(addr); + } + }; + + // Partial specialization for creating TADDRs + // This is the only other way to create a DAC type instance other than PTR types (above) + template<> struct makeDacInst + { + static inline TADDR fromTaddr(TADDR addr) { return addr; } + }; +} // namespace dac_imp + + +// DacCop in-line exclusion mechanism + +// Warnings - official home is DacCop\Shared\Warnings.cs, but we want a way for users to indicate +// warning codes in a way that is descriptive to readers (not just code numbers). The names here +// don't matter - DacCop just looks at the value +enum DacCopWarningCode +{ + // General Rules + FieldAccess = 1, + PointerArith = 2, + PointerComparison = 3, + InconsistentMarshalling = 4, + CastBetweenAddressSpaces = 5, + CastOfMarshalledType = 6, + VirtualCallToNonVPtr = 7, + UndacizedGlobalVariable = 8, + + // Function graph related + CallUnknown = 701, + CallNonDac = 702, + CallVirtualUnknown = 704, + CallVirtualNonDac = 705, +}; + +// DACCOP_IGNORE is a mechanism to suppress DacCop violations from within the source-code. +// See the DacCop wiki for guidance on how best to use this: http://mswikis/clr/dev/Pages/DacCop.aspx +// +// DACCOP_IGNORE will suppress a DacCop violation for the following (non-compound) statement. +// For example: +// // The "dual-mode DAC problem" occurs in a few places where a class is used both +// // in the host, and marshalled from the target ... +// DACCOP_IGNORE(CastBetweenAddressSpaces,"SBuffer has the dual-mode DAC problem"); +// TADDR bufAddr = (TADDR)m_buffer; +// +// A call to DACCOP_IGNORE must occur as it's own statement, and can apply only to following +// single-statements (not to compound statement blocks). Occasionally it is necessary to hoist +// violation-inducing code out to its own statement (e.g., if it occurs in the conditional of an +// if). +// +// Arguments: +// code: a literal value from DacCopWarningCode indicating which violation should be suppressed. +// szReasonString: a short description of why this exclusion is necessary. This is intended just +// to help readers of the code understand the source of the problem, and what would be required +// to fix it. More details can be provided in comments if desired. +// +inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString) +{ + // DacCop detects calls to this function. No implementation is necessary. +} + +#else // #ifdef DACCESS_COMPILE + +// +// This version of the macros turns into normal pointers +// for unmodified in-proc compilation. + +// ******************************************************* +// !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! +// +// Please search this file for the type name to find the +// DAC versions of these definitions +// +// !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! +// ******************************************************* + + +// Declare TADDR as a non-pointer type so that arithmetic +// can be done on it directly, as with the DACCESS_COMPILE definition. +// This also helps expose pointer usage that may need to be changed. +typedef ULONG_PTR TADDR; + +typedef void* PTR_VOID; +typedef LPVOID* PTR_PTR_VOID; +typedef const void* PTR_CVOID; + +#define DPTR(type) type* +#define ArrayDPTR(type) type* +#define SPTR(type) type* +#define VPTR(type) type* +#define S8PTR(type) type* +#define S8PTRMAX(type, maxChars) type* +#define S16PTR(type) type* +#define S16PTRMAX(type, maxChars) type* + +#if defined(FEATURE_PAL) + +#define VPTR_VTABLE_CLASS(name, base) \ + friend struct _DacGlobals; \ +public: name(int dummy) : base(dummy) {} + +#define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \ + VPTR_VTABLE_CLASS(name, base) \ + name() : base() {} + +#define VPTR_MULTI_VTABLE_CLASS(name, base) \ + friend struct _DacGlobals; \ +public: name(int dummy) : base(dummy) {} + +#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \ + friend struct _DacGlobals; \ +public: name(int dummy) {} + +#define VPTR_BASE_VTABLE_CLASS(name) \ + friend struct _DacGlobals; \ +public: name(int dummy) {} + +#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \ + VPTR_BASE_VTABLE_CLASS(name) \ + name() {} + +#define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ + friend struct _DacGlobals; \ +public: name(int dummy) : base(dummy) {} + +#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \ + VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ + name() : base() {} + +#else // FEATURE_PAL + +#define VPTR_VTABLE_CLASS(name, base) +#define VPTR_VTABLE_CLASS_AND_CTOR(name, base) +#define VPTR_MULTI_VTABLE_CLASS(name, base) +#define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) +#define VPTR_BASE_VTABLE_CLASS(name) +#define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) +#define VPTR_ABSTRACT_VTABLE_CLASS(name, base) +#define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) + +#endif // FEATURE_PAL + +// helper macro to make the vtables unique for DAC +#define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { return unique; } +#define VPTR_UNIQUE_BaseDomain (100000) +#define VPTR_UNIQUE_SystemDomain (VPTR_UNIQUE_BaseDomain + 1) +#define VPTR_UNIQUE_ComMethodFrame (VPTR_UNIQUE_SystemDomain + 1) +#define VPTR_UNIQUE_StubHelperFrame (VPTR_UNIQUE_ComMethodFrame + 1) +#define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_StubHelperFrame + 1) +#define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1) + +#define PTR_TO_TADDR(ptr) ((TADDR)(ptr)) +#define GFN_TADDR(name) ((TADDR)(name)) + +#define GVAL_ADDR(g) (&(g)) +#define _SPTR_DECL(acc_type, store_type, var) \ + static store_type var +#define _SPTR_IMPL(acc_type, store_type, cls, var) \ + store_type cls::var +#define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \ + store_type cls::var = init +#define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \ + store_type cls::var +#define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \ + store_type cls::var = init +#define _GPTR_DECL(acc_type, store_type, var) \ + extern store_type var +#define _GPTR_IMPL(acc_type, store_type, var) \ + store_type var +#define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \ + store_type var = init +#define SVAL_DECL(type, var) \ + static type var +#define SVAL_IMPL(type, cls, var) \ + type cls::var +#define SVAL_IMPL_INIT(type, cls, var, init) \ + type cls::var = init +#define SVAL_IMPL_NS(type, ns, cls, var) \ + type cls::var +#define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \ + type cls::var = init +#define GVAL_DECL(type, var) \ + extern type var +#define GVAL_IMPL(type, var) \ + type var +#define GVAL_IMPL_INIT(type, var, init) \ + type var = init +#define GARY_DECL(type, var, size) \ + extern type var[size] +#define GARY_IMPL(type, var, size) \ + type var[size] +#define PTR_HOST_TO_TADDR(host) ((TADDR)(host)) +#define PTR_HOST_INT_TO_TADDR(host) ((TADDR)(host)) +#define VPTR_HOST_VTABLE_TO_TADDR(host) ((TADDR)(host)) +#define PTR_HOST_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb) +#define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb) +#define PTR_TO_MEMBER_TADDR(type, ptr, memb) ((TADDR)&((ptr)->memb)) +#define PTR_READ(addr, size) ((PVOID)(addr)) + +#define PTR_NULL NULL + +#define DAC_EMPTY() +#define DAC_EMPTY_ERR() +#define DAC_EMPTY_RET(retVal) +#define DAC_UNEXPECTED() + +#define DACCOP_IGNORE(warningCode, reasonString) + +#endif // #ifdef DACCESS_COMPILE + +//---------------------------------------------------------------------------- +// dac_cast +// Casting utility, to be used for casting one class pointer type to another. +// Use as you would use static_cast +// +// dac_cast is designed to act just as static_cast does when +// dealing with pointers and their DAC abstractions. Specifically, +// it handles these coversions: +// +// dac_cast(SourceTypeVal) +// +// where TargetType <- SourceTypeVal are +// +// ?PTR(Tgt) <- TADDR - Create PTR type (DPtr etc.) from TADDR +// ?PTR(Tgt) <- ?PTR(Src) - Convert one PTR type to another +// ?PTR(Tgt) <- Src * - Create PTR type from dac host object instance +// TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.) +// TADDR <- Src * - Get TADDR of dac host object instance +// +// Note that there is no direct convertion to other host-pointer types (because we don't +// know if you want a DPTR or VPTR etc.). However, due to the implicit DAC conversions, +// you can just use dac_cast and assign that to a Foo*. +// +// The beauty of this syntax is that it is consistent regardless +// of source and target casting types. You just use dac_cast +// and the partial template specialization will do the right thing. +// +// One important thing to realise is that all "Foo *" types are +// assumed to be pointers to host instances that were marshalled by DAC. This should +// fail at runtime if it's not the case. +// +// Some examples would be: +// +// - Host pointer of one type to a related host pointer of another +// type, i.e., MethodDesc * <-> InstantiatedMethodDesc * +// Syntax: with MethodDesc *pMD, InstantiatedMethodDesc *pInstMD +// pInstMd = dac_cast(pMD) +// pMD = dac_cast(pInstMD) +// +// - (D|V)PTR of one encapsulated pointer type to a (D|V)PTR of +// another type, i.e., PTR_AppDomain <-> PTR_BaseDomain +// Syntax: with PTR_AppDomain pAD, PTR_BaseDomain pBD +// dac_cast(pBD) +// dac_cast(pAD) +// +// Example comparsions of some old and new syntax, where +// h is a host pointer, such as "Foo *h;" +// p is a DPTR, such as "PTR_Foo p;" +// +// PTR_HOST_TO_TADDR(h) ==> dac_cast(h) +// PTR_TO_TADDR(p) ==> dac_cast(p) +// PTR_Foo(PTR_HOST_TO_TADDR(h)) ==> dac_cast(h) +// +//---------------------------------------------------------------------------- +template +inline Tgt dac_cast(Src src) +{ +#ifdef DACCESS_COMPILE + // In DAC builds, first get a TADDR for the source, then create the + // appropriate destination instance. + TADDR addr = dac_imp::getTaddr(src); + return dac_imp::makeDacInst::fromTaddr(addr); +#else + // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support: + // - casting away const + // - conversions between pointers and TADDR + // Perhaps we should more precisely restrict it's usage, but we get the precise + // restrictions in DAC builds, so it wouldn't buy us much. + return (Tgt)(src); +#endif +} + +//---------------------------------------------------------------------------- +// +// Convenience macros which work for either mode. +// +//---------------------------------------------------------------------------- + +#define SPTR_DECL(type, var) _SPTR_DECL(type*, PTR_##type, var) +#define SPTR_IMPL(type, cls, var) _SPTR_IMPL(type*, PTR_##type, cls, var) +#define SPTR_IMPL_INIT(type, cls, var, init) _SPTR_IMPL_INIT(type*, PTR_##type, cls, var, init) +#define SPTR_IMPL_NS(type, ns, cls, var) _SPTR_IMPL_NS(type*, PTR_##type, ns, cls, var) +#define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) _SPTR_IMPL_NS_INIT(type*, PTR_##type, ns, cls, var, init) +#define GPTR_DECL(type, var) _GPTR_DECL(type*, PTR_##type, var) +#define GPTR_IMPL(type, var) _GPTR_IMPL(type*, PTR_##type, var) +#define GPTR_IMPL_INIT(type, var, init) _GPTR_IMPL_INIT(type*, PTR_##type, var, init) + + +// If you want to marshal a single instance of an ArrayDPtr over to the host and +// return a pointer to it, you can use this function. However, this is unsafe because +// users of value may assume they can do pointer arithmetic on it. This is exactly +// the bugs ArrayDPtr is designed to prevent. See code:__ArrayDPtr for details. +template +inline type* DacUnsafeMarshalSingleElement( ArrayDPTR(type) arrayPtr ) +{ + return (DPTR(type))(arrayPtr); +} + +//---------------------------------------------------------------------------- +// +// Forward typedefs for system types. This is a convenient place +// to declare things for system types, plus it gives us a central +// place to look at when deciding what types may cause issues for +// cross-platform compilation. +// +//---------------------------------------------------------------------------- + +typedef ArrayDPTR(BYTE) PTR_BYTE; +typedef ArrayDPTR(uint8_t) PTR_uint8_t; +typedef DPTR(PTR_BYTE) PTR_PTR_BYTE; +typedef DPTR(PTR_uint8_t) PTR_PTR_uint8_t; +typedef DPTR(PTR_PTR_BYTE) PTR_PTR_PTR_BYTE; +typedef ArrayDPTR(signed char) PTR_SBYTE; +typedef ArrayDPTR(const BYTE) PTR_CBYTE; +typedef DPTR(INT8) PTR_INT8; +typedef DPTR(INT16) PTR_INT16; +typedef DPTR(UINT16) PTR_UINT16; +typedef DPTR(WORD) PTR_WORD; +typedef DPTR(USHORT) PTR_USHORT; +typedef DPTR(DWORD) PTR_DWORD; +typedef DPTR(uint32_t) PTR_uint32_t; +typedef DPTR(LONG) PTR_LONG; +typedef DPTR(ULONG) PTR_ULONG; +typedef DPTR(INT32) PTR_INT32; +typedef DPTR(UINT32) PTR_UINT32; +typedef DPTR(ULONG64) PTR_ULONG64; +typedef DPTR(INT64) PTR_INT64; +typedef DPTR(UINT64) PTR_UINT64; +typedef DPTR(SIZE_T) PTR_SIZE_T; +typedef DPTR(size_t) PTR_size_t; +typedef DPTR(TADDR) PTR_TADDR; +typedef DPTR(int) PTR_int; +typedef DPTR(BOOL) PTR_BOOL; +typedef DPTR(unsigned) PTR_unsigned; + +typedef S8PTR(char) PTR_STR; +typedef S8PTR(const char) PTR_CSTR; +typedef S8PTR(char) PTR_UTF8; +typedef S8PTR(const char) PTR_CUTF8; +typedef S16PTR(WCHAR) PTR_WSTR; +typedef S16PTR(const WCHAR) PTR_CWSTR; + +typedef DPTR(T_CONTEXT) PTR_CONTEXT; +typedef DPTR(PTR_CONTEXT) PTR_PTR_CONTEXT; +typedef DPTR(struct _EXCEPTION_POINTERS) PTR_EXCEPTION_POINTERS; +typedef DPTR(struct _EXCEPTION_RECORD) PTR_EXCEPTION_RECORD; + +typedef DPTR(struct _EXCEPTION_REGISTRATION_RECORD) PTR_EXCEPTION_REGISTRATION_RECORD; + +typedef DPTR(struct IMAGE_COR_VTABLEFIXUP) PTR_IMAGE_COR_VTABLEFIXUP; +typedef DPTR(IMAGE_DATA_DIRECTORY) PTR_IMAGE_DATA_DIRECTORY; +typedef DPTR(IMAGE_DEBUG_DIRECTORY) PTR_IMAGE_DEBUG_DIRECTORY; +typedef DPTR(IMAGE_DOS_HEADER) PTR_IMAGE_DOS_HEADER; +typedef DPTR(IMAGE_NT_HEADERS) PTR_IMAGE_NT_HEADERS; +typedef DPTR(IMAGE_NT_HEADERS32) PTR_IMAGE_NT_HEADERS32; +typedef DPTR(IMAGE_NT_HEADERS64) PTR_IMAGE_NT_HEADERS64; +typedef DPTR(IMAGE_SECTION_HEADER) PTR_IMAGE_SECTION_HEADER; +typedef DPTR(IMAGE_TLS_DIRECTORY) PTR_IMAGE_TLS_DIRECTORY; + +#if defined(DACCESS_COMPILE) +#include +#include +#include +#endif + +#if defined(_TARGET_X86_) && defined(FEATURE_PAL) +typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; +#endif + +#ifdef _TARGET_64BIT_ +typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; +typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; +#if defined(_TARGET_AMD64_) +typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE; +#endif // _TARGET_AMD64_ +#endif // _TARGET_64BIT_ + +#ifdef _TARGET_ARM_ +typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; +#endif + +//---------------------------------------------------------------------------- +// +// A PCODE is a valid PC/IP value -- a pointer to an instruction, possibly including some processor mode bits. +// (On ARM, for example, a PCODE value should have the low-order THUMB_CODE bit set if the code should +// be executed in that mode.) +// +typedef TADDR PCODE; +typedef DPTR(PCODE) PTR_PCODE; +typedef DPTR(PTR_PCODE) PTR_PTR_PCODE; + +// There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off. +// Attempts to introduce this concept, and classify uses of PCODE as one or the other, +// turned out to be too hard: either name choice required *many* code changes, and decisions in unfamiliar code. So despite the +// the comment above, the PCODE is currently sometimes used for the PINSTR concept. + +// See PCODEToPINSTR in utilcode.h for conversion from PCODE to PINSTR. + +//---------------------------------------------------------------------------- +// +// The access code compile must compile data structures that exactly +// match the real structures for access to work. The access code +// doesn't want all of the debugging validation code, though, so +// distinguish between _DEBUG, for declaring general debugging data +// and always-on debug code, and _DEBUG_IMPL, for debugging code +// which will be disabled when compiling for external access. +// +//---------------------------------------------------------------------------- + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +// Helper macro for tracking EnumMemoryRegions progress. +#if 0 +#define EMEM_OUT(args) DacWarning args +#else +#define EMEM_OUT(args) +#endif + +// Macros like MAIN_CLR_MODULE_NAME* for the DAC module +#define MAIN_DAC_MODULE_NAME_W W("mscordaccore") +#define MAIN_DAC_MODULE_DLL_NAME_W W("mscordaccore.dll") + +// TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt. +// This is in contrast to ASSERTs in DAC infrastructure code which shouldn't fail regardless of the memory +// read from the target. At the moment we treat these the same, but in the future we will want a mechanism +// for disabling just the target consistency checks (eg. for tests that intentionally use corrupted targets). +// @dbgtodo : Separating asserts and target consistency checks is tracked by DevDiv Bugs 31674 +#define TARGET_CONSISTENCY_CHECK(expr,msg) _ASSERTE_MSG(expr,msg) + +#endif // #ifndef __daccess_h__ diff --git a/lib/coreclr/src/inc/dacprivate.h b/lib/coreclr/src/inc/dacprivate.h new file mode 100644 index 0000000000..7a12c642e4 --- /dev/null +++ b/lib/coreclr/src/inc/dacprivate.h @@ -0,0 +1,1069 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// +// Internal data access functionality. +// +//***************************************************************************** + +#ifndef _DACPRIVATE_H_ +#define _DACPRIVATE_H_ + +#include +#include +#include +#include + +#ifndef FEATURE_PAL +// It is unfortunate having to include this header just to get the definition of GenericModeBlock +#include +#endif // FEATURE_PAL + +// +// Whenever a structure is marshalled between different platforms, we need to ensure the +// layout is the same in both cases. We tell GCC to use the MSVC-style packing with +// the following attribute. The main thing this appears to control is whether +// 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default). +// This attribute affects only the immediate struct it is applied to, you must also apply +// it to any nested structs if you want their layout affected as well. You also must +// apply this to unions embedded in other structures, since it can influence the starting +// alignment. +// +// Note that there doesn't appear to be any disadvantage to applying this a little +// more agressively than necessary, so we generally use it on all classes / structures +// defined in a file that defines marshalled data types (eg. DacDbiStructures.h) +// The -mms-bitfields compiler option also does this for the whole file, but we don't +// want to go changing the layout of, for example, structures defined in OS header files +// so we explicitly opt-in with this attribute. +// +#ifdef __GNUC__ +#define MSLAYOUT __attribute__((__ms_struct__)) +#else +#define MSLAYOUT +#endif + +//---------------------------------------------------------------------------- +// +// Utility class to allow for zero initialization of our Dacp- structs. +// +//---------------------------------------------------------------------------- + +template +struct ZeroInit +{ + ZeroInit() + { memset(static_cast(this), 0, sizeof(T)); } +}; + + +#include + +//---------------------------------------------------------------------------- +// +// Internal CLRData requests. +// +//---------------------------------------------------------------------------- + + +// Private requests for DataModules +enum +{ + DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR = 0xf0000000, + DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA = 0xf0000001 +}; + + +// Private requests for stack walkers. +enum +{ + DACSTACKPRIV_REQUEST_FRAME_DATA = 0xf0000000 +}; + +enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER }; +struct MSLAYOUT DacpObjectData : ZeroInit +{ + CLRDATA_ADDRESS MethodTable; + DacpObjectType ObjectType; + ULONG64 Size; + CLRDATA_ADDRESS ElementTypeHandle; + CorElementType ElementType; + DWORD dwRank; + ULONG64 dwNumComponents; + ULONG64 dwComponentSize; + CLRDATA_ADDRESS ArrayDataPtr; + CLRDATA_ADDRESS ArrayBoundsPtr; + CLRDATA_ADDRESS ArrayLowerBoundsPtr; + + CLRDATA_ADDRESS RCW; + CLRDATA_ADDRESS CCW; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetObjectData(addr, this); + } +}; + +struct MSLAYOUT DacpExceptionObjectData : ZeroInit +{ + CLRDATA_ADDRESS Message; + CLRDATA_ADDRESS InnerException; + CLRDATA_ADDRESS StackTrace; + CLRDATA_ADDRESS WatsonBuckets; + CLRDATA_ADDRESS StackTraceString; + CLRDATA_ADDRESS RemoteStackTraceString; + INT32 HResult; + INT32 XCode; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + HRESULT hr; + ISOSDacInterface2 *psos2 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), (void**) &psos2))) + { + hr = psos2->GetObjectExceptionData(addr, this); + psos2->Release(); + } + return hr; + } +}; + +struct MSLAYOUT DacpUsefulGlobalsData : ZeroInit +{ + CLRDATA_ADDRESS ArrayMethodTable; + CLRDATA_ADDRESS StringMethodTable; + CLRDATA_ADDRESS ObjectMethodTable; + CLRDATA_ADDRESS ExceptionMethodTable; + CLRDATA_ADDRESS FreeMethodTable; +}; + +struct MSLAYOUT DacpFieldDescData : ZeroInit +{ + CorElementType Type; + CorElementType sigType; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case + CLRDATA_ADDRESS MTOfType; // NULL if Type is not loaded + + CLRDATA_ADDRESS ModuleOfType; + mdTypeDef TokenOfType; + + mdFieldDef mb; + CLRDATA_ADDRESS MTOfEnclosingClass; + DWORD dwOffset; + BOOL bIsThreadLocal; + BOOL bIsContextLocal; + BOOL bIsStatic; + CLRDATA_ADDRESS NextField; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetFieldDescData(addr, this); + } +}; + +struct MSLAYOUT DacpMethodTableFieldData : ZeroInit +{ + WORD wNumInstanceFields; + WORD wNumStaticFields; + WORD wNumThreadStaticFields; + + CLRDATA_ADDRESS FirstField; // If non-null, you can retrieve more + + WORD wContextStaticOffset; + WORD wContextStaticsSize; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetMethodTableFieldData(addr, this); + } +}; + +struct MSLAYOUT DacpMethodTableCollectibleData : ZeroInit +{ + CLRDATA_ADDRESS LoaderAllocatorObjectHandle; + BOOL bCollectible; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + HRESULT hr; + ISOSDacInterface6 *pSOS6 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface6), (void**)&pSOS6))) + { + hr = pSOS6->GetMethodTableCollectibleData(addr, this); + pSOS6->Release(); + } + + return hr; + } +}; + +struct MSLAYOUT DacpMethodTableTransparencyData : ZeroInit +{ + BOOL bHasCriticalTransparentInfo; + BOOL bIsCritical; + BOOL bIsTreatAsSafe; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetMethodTableTransparencyData(addr, this); + } +}; + +struct MSLAYOUT DacpDomainLocalModuleData : ZeroInit +{ + // These two parameters are used as input params when calling the + // no-argument form of Request below. + CLRDATA_ADDRESS appDomainAddr; + ULONG64 ModuleID; + + CLRDATA_ADDRESS pClassData; + CLRDATA_ADDRESS pDynamicClassTable; + CLRDATA_ADDRESS pGCStaticDataStart; + CLRDATA_ADDRESS pNonGCStaticDataStart; + + // Called when you have a pointer to the DomainLocalModule + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetDomainLocalModuleData(addr, this); + } +}; + + +struct MSLAYOUT DacpThreadLocalModuleData : ZeroInit +{ + // These two parameters are used as input params when calling the + // no-argument form of Request below. + CLRDATA_ADDRESS threadAddr; + ULONG64 ModuleIndex; + + CLRDATA_ADDRESS pClassData; + CLRDATA_ADDRESS pDynamicClassTable; + CLRDATA_ADDRESS pGCStaticDataStart; + CLRDATA_ADDRESS pNonGCStaticDataStart; +}; + + +struct MSLAYOUT DacpModuleData : ZeroInit +{ + CLRDATA_ADDRESS Address; + CLRDATA_ADDRESS File; // A PEFile addr + CLRDATA_ADDRESS ilBase; + CLRDATA_ADDRESS metadataStart; + ULONG64 metadataSize; + CLRDATA_ADDRESS Assembly; // Assembly pointer + BOOL bIsReflection; + BOOL bIsPEFile; + ULONG64 dwBaseClassIndex; + ULONG64 dwModuleID; + + DWORD dwTransientFlags; + + CLRDATA_ADDRESS TypeDefToMethodTableMap; + CLRDATA_ADDRESS TypeRefToMethodTableMap; + CLRDATA_ADDRESS MethodDefToDescMap; + CLRDATA_ADDRESS FieldDefToDescMap; + CLRDATA_ADDRESS MemberRefToDescMap; + CLRDATA_ADDRESS FileReferencesMap; + CLRDATA_ADDRESS ManifestModuleReferencesMap; + + CLRDATA_ADDRESS pLookupTableHeap; + CLRDATA_ADDRESS pThunkHeap; + + ULONG64 dwModuleIndex; + + DacpModuleData() + { + } + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetModuleData(addr, this); + } + +private: + // Ensure that this data structure is not copied. + DacpModuleData(const DacpModuleData&); + void operator=(const DacpModuleData&); +}; + +struct MSLAYOUT DacpMethodTableData : ZeroInit +{ + BOOL bIsFree; // everything else is NULL if this is true. + CLRDATA_ADDRESS Module; + CLRDATA_ADDRESS Class; + CLRDATA_ADDRESS ParentMethodTable; + WORD wNumInterfaces; + WORD wNumMethods; + WORD wNumVtableSlots; + WORD wNumVirtuals; + DWORD BaseSize; + DWORD ComponentSize; + mdTypeDef cl; // Metadata token + DWORD dwAttrClass; // cached metadata + BOOL bIsShared; // Always false, preserved for backward compatibility + BOOL bIsDynamic; + BOOL bContainsPointers; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetMethodTableData(addr, this); + } +}; + + +// Copied from util.hpp, for DacpThreadStoreData.fHostConfig below. +#define CLRMEMORYHOSTED 0x1 +#define CLRTASKHOSTED 0x2 +#define CLRSYNCHOSTED 0x4 +#define CLRTHREADPOOLHOSTED 0x8 +#define CLRIOCOMPLETIONHOSTED 0x10 +#define CLRASSEMBLYHOSTED 0x20 +#define CLRGCHOSTED 0x40 +#define CLRSECURITYHOSTED 0x80 +#define CLRHOSTED 0x80000000 + +struct MSLAYOUT DacpThreadStoreData : ZeroInit +{ + LONG threadCount; + LONG unstartedThreadCount; + LONG backgroundThreadCount; + LONG pendingThreadCount; + LONG deadThreadCount; + CLRDATA_ADDRESS firstThread; + CLRDATA_ADDRESS finalizerThread; + CLRDATA_ADDRESS gcThread; + DWORD fHostConfig; // Uses hosting flags defined above + + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetThreadStoreData(this); + } +}; + +struct MSLAYOUT DacpAppDomainStoreData : ZeroInit +{ + CLRDATA_ADDRESS sharedDomain; + CLRDATA_ADDRESS systemDomain; + LONG DomainCount; + + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetAppDomainStoreData(this); + } +}; + +struct MSLAYOUT DacpCOMInterfacePointerData : ZeroInit +{ + CLRDATA_ADDRESS methodTable; + CLRDATA_ADDRESS interfacePtr; + CLRDATA_ADDRESS comContext; +}; + +struct MSLAYOUT DacpRCWData : ZeroInit +{ + CLRDATA_ADDRESS identityPointer; + CLRDATA_ADDRESS unknownPointer; + CLRDATA_ADDRESS managedObject; + CLRDATA_ADDRESS jupiterObject; + CLRDATA_ADDRESS vtablePtr; + CLRDATA_ADDRESS creatorThread; + CLRDATA_ADDRESS ctxCookie; + + LONG refCount; + LONG interfaceCount; + + BOOL isJupiterObject; + BOOL supportsIInspectable; + BOOL isAggregated; + BOOL isContained; + BOOL isFreeThreaded; + BOOL isDisconnected; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw) + { + return sos->GetRCWData(rcw, this); + } + + HRESULT IsDCOMProxy(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw, BOOL* isDCOMProxy) + { + ISOSDacInterface2 *pSOS2 = nullptr; + HRESULT hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), reinterpret_cast(&pSOS2)); + if (SUCCEEDED(hr)) + { + hr = pSOS2->IsRCWDCOMProxy(rcw, isDCOMProxy); + pSOS2->Release(); + } + + return hr; + } +}; + +struct MSLAYOUT DacpCCWData : ZeroInit +{ + CLRDATA_ADDRESS outerIUnknown; + CLRDATA_ADDRESS managedObject; + CLRDATA_ADDRESS handle; + CLRDATA_ADDRESS ccwAddress; + + LONG refCount; + LONG interfaceCount; + BOOL isNeutered; + + LONG jupiterRefCount; + BOOL isPegged; + BOOL isGlobalPegged; + BOOL hasStrongRef; + BOOL isExtendsCOMObject; + BOOL isAggregated; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS ccw) + { + return sos->GetCCWData(ccw, this); + } +}; + +enum DacpAppDomainDataStage { + STAGE_CREATING, + STAGE_READYFORMANAGEDCODE, + STAGE_ACTIVE, + STAGE_OPEN, + STAGE_UNLOAD_REQUESTED, + STAGE_EXITING, + STAGE_EXITED, + STAGE_FINALIZING, + STAGE_FINALIZED, + STAGE_HANDLETABLE_NOACCESS, + STAGE_CLEARED, + STAGE_COLLECTED, + STAGE_CLOSED +}; + +// Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain). +// For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. +struct MSLAYOUT DacpAppDomainData : ZeroInit +{ + // The pointer to the BaseDomain (not necessarily an AppDomain). + // It's useful to keep this around in the structure + CLRDATA_ADDRESS AppDomainPtr; + CLRDATA_ADDRESS AppSecDesc; + CLRDATA_ADDRESS pLowFrequencyHeap; + CLRDATA_ADDRESS pHighFrequencyHeap; + CLRDATA_ADDRESS pStubHeap; + CLRDATA_ADDRESS DomainLocalBlock; + CLRDATA_ADDRESS pDomainLocalModules; + // The creation sequence number of this app domain (starting from 1) + DWORD dwId; + LONG AssemblyCount; + LONG FailedAssemblyCount; + DacpAppDomainDataStage appDomainStage; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetAppDomainData(addr, this); + } +}; + +struct MSLAYOUT DacpAssemblyData : ZeroInit +{ + CLRDATA_ADDRESS AssemblyPtr; //useful to have + CLRDATA_ADDRESS ClassLoader; + CLRDATA_ADDRESS ParentDomain; + CLRDATA_ADDRESS BaseDomainPtr; + CLRDATA_ADDRESS AssemblySecDesc; + BOOL isDynamic; + UINT ModuleCount; + UINT LoadContext; + BOOL isDomainNeutral; // Always false, preserved for backward compatibility + DWORD dwLocationFlags; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr) + { + return sos->GetAssemblyData(baseDomainPtr, addr, this); + } + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return Request(sos, addr, NULL); + } +}; + + +struct MSLAYOUT DacpThreadData : ZeroInit +{ + DWORD corThreadId; + DWORD osThreadId; + int state; + ULONG preemptiveGCDisabled; + CLRDATA_ADDRESS allocContextPtr; + CLRDATA_ADDRESS allocContextLimit; + CLRDATA_ADDRESS context; + CLRDATA_ADDRESS domain; + CLRDATA_ADDRESS pFrame; + DWORD lockCount; + CLRDATA_ADDRESS firstNestedException; // Pass this pointer to DacpNestedExceptionInfo + CLRDATA_ADDRESS teb; + CLRDATA_ADDRESS fiberData; + CLRDATA_ADDRESS lastThrownObjectHandle; + CLRDATA_ADDRESS nextThread; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetThreadData(addr, this); + } +}; + + +struct MSLAYOUT DacpReJitData : ZeroInit +{ + enum Flags + { + kUnknown, + kRequested, + kActive, + kReverted, + }; + + CLRDATA_ADDRESS rejitID; + Flags flags; + CLRDATA_ADDRESS NativeCodeAddr; +}; + + +struct MSLAYOUT DacpMethodDescData : ZeroInit +{ + BOOL bHasNativeCode; + BOOL bIsDynamic; + WORD wSlotNumber; + CLRDATA_ADDRESS NativeCodeAddr; + // Useful for breaking when a method is jitted. + CLRDATA_ADDRESS AddressOfNativeCodeSlot; + + CLRDATA_ADDRESS MethodDescPtr; + CLRDATA_ADDRESS MethodTablePtr; + CLRDATA_ADDRESS ModulePtr; + + mdToken MDToken; + CLRDATA_ADDRESS GCInfo; + CLRDATA_ADDRESS GCStressCodeCopy; + + // This is only valid if bIsDynamic is true + CLRDATA_ADDRESS managedDynamicMethodObject; + + CLRDATA_ADDRESS requestedIP; + + // Gives info for the single currently active version of a method + DacpReJitData rejitDataCurrent; + + // Gives info corresponding to requestedIP (for !ip2md) + DacpReJitData rejitDataRequested; + + // Total number of rejit versions that have been jitted + ULONG cJittedRejitVersions; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetMethodDescData( + addr, + NULL, // IP address + this, + 0, // cRejitData + NULL, // rejitData[] + NULL // pcNeededRejitData + ); + } +}; + + +struct MSLAYOUT DacpMethodDescTransparencyData : ZeroInit +{ + BOOL bHasCriticalTransparentInfo; + BOOL bIsCritical; + BOOL bIsTreatAsSafe; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetMethodDescTransparencyData(addr, this); + } +}; + +struct MSLAYOUT DacpTieredVersionData +{ + enum OptimizationTier + { + OptimizationTier_Unknown, + OptimizationTier_MinOptJitted, + OptimizationTier_Optimized, + OptimizationTier_QuickJitted, + OptimizationTier_OptimizedTier1, + OptimizationTier_ReadyToRun, + }; + + CLRDATA_ADDRESS NativeCodeAddr; + OptimizationTier OptimizationTier; + CLRDATA_ADDRESS NativeCodeVersionNodePtr; +}; + +// for JITType +enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT}; + +struct MSLAYOUT DacpCodeHeaderData : ZeroInit +{ + CLRDATA_ADDRESS GCInfo; + JITTypes JITType; + CLRDATA_ADDRESS MethodDescPtr; + CLRDATA_ADDRESS MethodStart; + DWORD MethodSize; + CLRDATA_ADDRESS ColdRegionStart; + DWORD ColdRegionSize; + DWORD HotRegionSize; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS IPAddr) + { + return sos->GetCodeHeaderData(IPAddr, this); + } +}; + +struct MSLAYOUT DacpWorkRequestData : ZeroInit +{ + CLRDATA_ADDRESS Function; + CLRDATA_ADDRESS Context; + CLRDATA_ADDRESS NextWorkRequest; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetWorkRequestData(addr, this); + } +}; + +struct MSLAYOUT DacpHillClimbingLogEntry : ZeroInit +{ + DWORD TickCount; + int Transition; + int NewControlSetting; + int LastHistoryCount; + double LastHistoryMean; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS entry) + { + return sos->GetHillClimbingLogEntry(entry, this); + } +}; + + +// Used for CLR versions >= 4.0 +struct MSLAYOUT DacpThreadpoolData : ZeroInit +{ + LONG cpuUtilization; + int NumIdleWorkerThreads; + int NumWorkingWorkerThreads; + int NumRetiredWorkerThreads; + LONG MinLimitTotalWorkerThreads; + LONG MaxLimitTotalWorkerThreads; + + CLRDATA_ADDRESS FirstUnmanagedWorkRequest; + + CLRDATA_ADDRESS HillClimbingLog; + int HillClimbingLogFirstIndex; + int HillClimbingLogSize; + + DWORD NumTimers; + // TODO: Add support to enumerate timers too. + + LONG NumCPThreads; + LONG NumFreeCPThreads; + LONG MaxFreeCPThreads; + LONG NumRetiredCPThreads; + LONG MaxLimitTotalCPThreads; + LONG CurrentLimitTotalCPThreads; + LONG MinLimitTotalCPThreads; + + CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr; + + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetThreadpoolData(this); + } +}; + +struct MSLAYOUT DacpGenerationData : ZeroInit +{ + CLRDATA_ADDRESS start_segment; + CLRDATA_ADDRESS allocation_start; + + // These are examined only for generation 0, otherwise NULL + CLRDATA_ADDRESS allocContextPtr; + CLRDATA_ADDRESS allocContextLimit; +}; + +#define DAC_NUMBERGENERATIONS 4 + + +struct MSLAYOUT DacpAllocData : ZeroInit +{ + CLRDATA_ADDRESS allocBytes; + CLRDATA_ADDRESS allocBytesLoh; +}; + +struct MSLAYOUT DacpGenerationAllocData : ZeroInit +{ + DacpAllocData allocData[DAC_NUMBERGENERATIONS]; +}; + +struct MSLAYOUT DacpGcHeapDetails : ZeroInit +{ + CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL + CLRDATA_ADDRESS alloc_allocated; + + CLRDATA_ADDRESS mark_array; + CLRDATA_ADDRESS current_c_gc_state; + CLRDATA_ADDRESS next_sweep_obj; + CLRDATA_ADDRESS saved_sweep_ephemeral_seg; + CLRDATA_ADDRESS saved_sweep_ephemeral_start; + CLRDATA_ADDRESS background_saved_lowest_address; + CLRDATA_ADDRESS background_saved_highest_address; + + DacpGenerationData generation_table [DAC_NUMBERGENERATIONS]; + CLRDATA_ADDRESS ephemeral_heap_segment; + CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3]; + CLRDATA_ADDRESS lowest_address; + CLRDATA_ADDRESS highest_address; + CLRDATA_ADDRESS card_table; + + // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetGCHeapStaticData(this); + } + + // Use this for Server mode, as there are multiple heaps, + // and you need to pass a heap address in addr. + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetGCHeapDetails(addr, this); + } +}; + +struct MSLAYOUT DacpGcHeapData + : ZeroInit +{ + BOOL bServerMode; + BOOL bGcStructuresValid; + UINT HeapCount; + UINT g_max_generation; + + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetGCHeapData(this); + } +}; + +struct MSLAYOUT DacpHeapSegmentData + : ZeroInit +{ + CLRDATA_ADDRESS segmentAddr; + CLRDATA_ADDRESS allocated; + CLRDATA_ADDRESS committed; + CLRDATA_ADDRESS reserved; + CLRDATA_ADDRESS used; + CLRDATA_ADDRESS mem; + // pass this to request if non-null to get the next segments. + CLRDATA_ADDRESS next; + CLRDATA_ADDRESS gc_heap; // only filled in in server mode, otherwise NULL + // computed field: if this is the ephemeral segment highMark includes the ephemeral generation + CLRDATA_ADDRESS highAllocMark; + + size_t flags; + CLRDATA_ADDRESS background_allocated; + + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, const DacpGcHeapDetails& heap) + { + HRESULT hr = sos->GetHeapSegmentData(addr, this); + + // if this is the start segment, set highAllocMark too. + if (SUCCEEDED(hr)) + { + // TODO: This needs to be put on the Dac side. + if (this->segmentAddr == heap.generation_table[0].start_segment) + highAllocMark = heap.alloc_allocated; + else + highAllocMark = allocated; + } + return hr; + } +}; + +struct MSLAYOUT DacpOomData : ZeroInit +{ + int reason; + ULONG64 alloc_size; + ULONG64 available_pagefile_mb; + ULONG64 gc_index; + int fgm; + ULONG64 size; + BOOL loh_p; + + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetOOMStaticData(this); + } + + // Use this for Server mode, as there are multiple heaps, + // and you need to pass a heap address in addr. + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetOOMData(addr, this); + } +}; + +#define DAC_NUM_GC_DATA_POINTS 9 +#define DAC_MAX_COMPACT_REASONS_COUNT 11 +#define DAC_MAX_EXPAND_MECHANISMS_COUNT 6 +#define DAC_MAX_GC_MECHANISM_BITS_COUNT 2 +#define DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT 6 +struct MSLAYOUT DacpGCInterestingInfoData : ZeroInit +{ + size_t interestingDataPoints[DAC_NUM_GC_DATA_POINTS]; + size_t compactReasons[DAC_MAX_COMPACT_REASONS_COUNT]; + size_t expandMechanisms[DAC_MAX_EXPAND_MECHANISMS_COUNT]; + size_t bitMechanisms[DAC_MAX_GC_MECHANISM_BITS_COUNT]; + size_t globalMechanisms[DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT]; + + HRESULT RequestGlobal(ISOSDacInterface *sos) + { + HRESULT hr; + ISOSDacInterface3 *psos3 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) + { + hr = psos3->GetGCGlobalMechanisms(globalMechanisms); + psos3->Release(); + } + return hr; + } + + HRESULT Request(ISOSDacInterface *sos) + { + HRESULT hr; + ISOSDacInterface3 *psos3 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) + { + hr = psos3->GetGCInterestingInfoStaticData(this); + psos3->Release(); + } + return hr; + } + + // Use this for Server mode, as there are multiple heaps, + // and you need to pass a heap address in addr. + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + HRESULT hr; + ISOSDacInterface3 *psos3 = NULL; + if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) + { + hr = psos3->GetGCInterestingInfoData(addr, this); + psos3->Release(); + } + return hr; + } +}; + +struct MSLAYOUT DacpGcHeapAnalyzeData + : ZeroInit +{ + CLRDATA_ADDRESS heapAddr; // Only filled in in server mode, otherwise NULL + + CLRDATA_ADDRESS internal_root_array; + ULONG64 internal_root_array_index; + BOOL heap_analyze_success; + + // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). + HRESULT Request(ISOSDacInterface *sos) + { + return sos->GetHeapAnalyzeStaticData(this); + } + + // Use this for Server mode, as there are multiple heaps, + // and you need to pass a heap address in addr. + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) + { + return sos->GetHeapAnalyzeData(addr, this); + } +}; + + +#define SYNCBLOCKDATA_COMFLAGS_CCW 1 +#define SYNCBLOCKDATA_COMFLAGS_RCW 2 +#define SYNCBLOCKDATA_COMFLAGS_CF 4 + +struct MSLAYOUT DacpSyncBlockData : ZeroInit +{ + CLRDATA_ADDRESS Object; + BOOL bFree; // if set, no other fields are useful + + // fields below provide data from this, so it's just for display + CLRDATA_ADDRESS SyncBlockPointer; + DWORD COMFlags; + UINT MonitorHeld; + UINT Recursion; + CLRDATA_ADDRESS HoldingThread; + UINT AdditionalThreadCount; + CLRDATA_ADDRESS appDomainPtr; + + // SyncBlockCount will always be filled in with the number of SyncBlocks. + // SyncBlocks may be requested from [1,SyncBlockCount] + UINT SyncBlockCount; + + // SyncBlockNumber must be from [1,SyncBlockCount] + // If there are no SyncBlocks, a call to Request with SyncBlockCount = 1 + // will return E_FAIL. + HRESULT Request(ISOSDacInterface *sos, UINT SyncBlockNumber) + { + return sos->GetSyncBlockData(SyncBlockNumber, this); + } +}; + +struct MSLAYOUT DacpSyncBlockCleanupData : ZeroInit +{ + CLRDATA_ADDRESS SyncBlockPointer; + + CLRDATA_ADDRESS nextSyncBlock; + CLRDATA_ADDRESS blockRCW; + CLRDATA_ADDRESS blockClassFactory; + CLRDATA_ADDRESS blockCCW; + + // Pass NULL on the first request to start a traversal. + HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS psyncBlock) + { + return sos->GetSyncBlockCleanupData(psyncBlock, this); + } +}; + +/////////////////////////////////////////////////////////////////////////// + +enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown}; + +struct MSLAYOUT DACEHInfo : ZeroInit +{ + EHClauseType clauseType; + CLRDATA_ADDRESS tryStartOffset; + CLRDATA_ADDRESS tryEndOffset; + CLRDATA_ADDRESS handlerStartOffset; + CLRDATA_ADDRESS handlerEndOffset; + BOOL isDuplicateClause; + CLRDATA_ADDRESS filterOffset; // valid when clauseType is EHFilter + BOOL isCatchAllHandler; // valid when clauseType is EHTyped + CLRDATA_ADDRESS moduleAddr; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token + CLRDATA_ADDRESS mtCatch; // the method table of the TYPED clause type + mdToken tokCatch; // the type token of the TYPED clause type +}; + +struct MSLAYOUT DacpGetModuleAddress : ZeroInit +{ + CLRDATA_ADDRESS ModulePtr; + HRESULT Request(IXCLRDataModule* pDataModule) + { + return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR, 0, NULL, sizeof(*this), (PBYTE) this); + } +}; + +struct MSLAYOUT DacpGetModuleData : ZeroInit +{ + BOOL IsDynamic; + BOOL IsInMemory; + BOOL IsFileLayout; + CLRDATA_ADDRESS PEFile; + CLRDATA_ADDRESS LoadedPEAddress; + ULONG64 LoadedPESize; + CLRDATA_ADDRESS InMemoryPdbAddress; + ULONG64 InMemoryPdbSize; + + HRESULT Request(IXCLRDataModule* pDataModule) + { + return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA, 0, NULL, sizeof(*this), (PBYTE) this); + } +}; + +struct MSLAYOUT DacpFrameData : ZeroInit +{ + CLRDATA_ADDRESS frameAddr; + + // Could also be implemented for IXCLRDataFrame if desired. + HRESULT Request(IXCLRDataStackWalk* dac) + { + return dac->Request(DACSTACKPRIV_REQUEST_FRAME_DATA, + 0, NULL, + sizeof(*this), (PBYTE)this); + } +}; + +struct MSLAYOUT DacpJitManagerInfo : ZeroInit +{ + CLRDATA_ADDRESS managerAddr; + DWORD codeType; // for union below + CLRDATA_ADDRESS ptrHeapList; // A HeapList * if IsMiIL(codeType) +}; + +enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN}; + +struct MSLAYOUT DacpJitCodeHeapInfo : ZeroInit +{ + DWORD codeHeapType; // for union below + + union + { + CLRDATA_ADDRESS LoaderHeap; // if CODEHEAP_LOADER + struct MSLAYOUT + { + CLRDATA_ADDRESS baseAddr; // if CODEHEAP_HOST + CLRDATA_ADDRESS currentAddr; + } HostData; + }; +}; + +#include "static_assert.h" + +/* DAC datastructures are frozen as of dev11 shipping. Do NOT add fields, remove fields, or change the fields of + * these structs in any way. The correct way to get new data out of the runtime is to create a new struct and + * add a new function to the latest Dac<-->SOS interface to produce this data. + */ +static_assert(sizeof(DacpAllocData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGenerationAllocData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpSyncBlockCleanupData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpThreadStoreData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpAppDomainStoreData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpAppDomainData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpAssemblyData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpThreadData) == 0x68, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodDescData) == 0x98, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpCodeHeaderData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpThreadpoolData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpObjectData) == 0x60, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodTableData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpWorkRequestData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpFieldDescData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpModuleData) == 0xa0, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGcHeapData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpJitManagerInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpHeapSegmentData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpDomainLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpUsefulGlobalsData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DACEHInfo) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpRCWData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpCCWData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodTableFieldData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodTableTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpThreadLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpCOMInterfacePointerData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodDescTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpHillClimbingLogEntry) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGenerationData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGcHeapDetails) == 0x120, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpOomData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGcHeapAnalyzeData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpSyncBlockData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); +static_assert(sizeof(DacpMethodTableCollectibleData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); + +#endif // _DACPRIVATE_H_ diff --git a/lib/coreclr/src/inc/dacvars.h b/lib/coreclr/src/inc/dacvars.h new file mode 100644 index 0000000000..78b1c10a4f --- /dev/null +++ b/lib/coreclr/src/inc/dacvars.h @@ -0,0 +1,263 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// This file contains the globals and statics that are visible to DAC. +// It is used for the following: +// 1. in daccess.h to build the table of DAC globals +// 2. in enummem.cpp to dump out the related memory of static and globals +// in a mini dump or heap dump +// 3. in DacUpdateDll and toolbox\DacTablenGen\main.cs +// +// To use this functionality for other tools or purposes, define the +// DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or +// daccess.h for examples): +// +// #define DEFINE_DACVAR(type, size, id, var) type id; //this defn. discards +// //the size +// #include "dacvars.h" +// +// @dbgtodo: +// Ideally we may be able to build a tool that generates this automatically. +// At the least, we should automatically verify that the contents of this file +// are consistent with the uses of all the macros like SVAL_DECL and GARY_DECL. +// +//================================================= +// INSTRUCTIONS FOR ADDING VARIABLES TO THIS FILE +//================================================= +// You need to add a global or static declared with DAC macros, such as SPTR_* +// GPTR_*, SVAL_*, GVAL_*, or GARY_*, only if the global or static is actually used +// in a DACized code path. If you have declared a static or global that way just +// because you were pattern-matching or because you anticipate that the variable +// may eventually be used in a DACized code path, you don't need to add it here, +// although in that case, you should not really use the DAC macro when you declare +// the global or static. +// * * * +// The FIRST ARGUMENT should always be specified as ULONG. This is the type of +// the offsets for the corresponding id in the _DacGlobals table. +// @dbgtodo: +// We should get rid of the ULONG argument since it's always the same. We would +// also need to modify DacTablenGen\main.cs. +// * * * +// The SECOND ARGUMENT, "true_type," is used to calculate the true size of the +// static/global variable. It is currently used only in enummem.cpp to write out +// theproper size of memory for dumps. +// * * * +// The THIRD ARGUMENT should be a qualified name. If the variable is a static data +// member, the name should be __. If the variable is a +// global, the name should be __. +// * * * +// The FOURTH ARGUMENT should be the actual name of the static/global variable. If +// static data the should be [::]::. If global, +// it should look like . +// * * * +// If you need to add an entry to this file, your type may not be visible when +// this file is compiled. In that case, you need to do one of two things: +// - If the type is a pointer type, you can simply use UNKNOWN_POINTER_TYPE as the +// "true type." It may be useful to specify the non-visible type in a comment. +// - If the type is a composite/user-defined type, you must #include the header +// file that defines the type in enummem.cpp. Do NOT #include it in daccess.h +// Array types may be dumped via an explicit call to enumMem, so they should +// be declared with DEFINE_DACVAR_NO_DUMP. The size in this case is immaterial, since +// nothing will be dumped. + +#ifndef DEFINE_DACVAR +#define DEFINE_DACVAR(type, true_type, id, var) +#endif + +// Use this macro to define a static var that is known to DAC, but not captured in a dump. +#ifndef DEFINE_DACVAR_NO_DUMP +#define DEFINE_DACVAR_NO_DUMP(type, true_type, id, var) +#endif + +#define UNKNOWN_POINTER_TYPE SIZE_T + +DEFINE_DACVAR(ULONG, PTR_RangeSection, ExecutionManager__m_CodeRangeList, ExecutionManager::m_CodeRangeList) +DEFINE_DACVAR(ULONG, PTR_EECodeManager, ExecutionManager__m_pDefaultCodeMan, ExecutionManager::m_pDefaultCodeMan) +DEFINE_DACVAR(ULONG, LONG, ExecutionManager__m_dwReaderCount, ExecutionManager::m_dwReaderCount) +DEFINE_DACVAR(ULONG, LONG, ExecutionManager__m_dwWriterLock, ExecutionManager::m_dwWriterLock) + +DEFINE_DACVAR(ULONG, PTR_EEJitManager, ExecutionManager__m_pEEJitManager, ExecutionManager::m_pEEJitManager) +#ifdef FEATURE_PREJIT +DEFINE_DACVAR(ULONG, PTR_NativeImageJitManager, ExecutionManager__m_pNativeImageJitManager, ExecutionManager::m_pNativeImageJitManager) +#endif +#ifdef FEATURE_READYTORUN +DEFINE_DACVAR(ULONG, PTR_ReadyToRunJitManager, ExecutionManager__m_pReadyToRunJitManager, ExecutionManager::m_pReadyToRunJitManager) +#endif + +DEFINE_DACVAR_NO_DUMP(ULONG, VMHELPDEF *, dac__hlpFuncTable, ::hlpFuncTable) +DEFINE_DACVAR(ULONG, VMHELPDEF *, dac__hlpDynamicFuncTable, ::hlpDynamicFuncTable) + +DEFINE_DACVAR(ULONG, PTR_StubManager, StubManager__g_pFirstManager, StubManager::g_pFirstManager) +DEFINE_DACVAR(ULONG, PTR_PrecodeStubManager, PrecodeStubManager__g_pManager, PrecodeStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_StubLinkStubManager, StubLinkStubManager__g_pManager, StubLinkStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_ThunkHeapStubManager, ThunkHeapStubManager__g_pManager, ThunkHeapStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_JumpStubStubManager, JumpStubStubManager__g_pManager, JumpStubStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_RangeSectionStubManager, RangeSectionStubManager__g_pManager, RangeSectionStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_DelegateInvokeStubManager, DelegateInvokeStubManager__g_pManager, DelegateInvokeStubManager::g_pManager) +DEFINE_DACVAR(ULONG, PTR_VirtualCallStubManagerManager, VirtualCallStubManagerManager__g_pManager, VirtualCallStubManagerManager::g_pManager) + +DEFINE_DACVAR(ULONG, PTR_ThreadStore, ThreadStore__s_pThreadStore, ThreadStore::s_pThreadStore) + +DEFINE_DACVAR(ULONG, int, ThreadpoolMgr__cpuUtilization, ThreadpoolMgr::cpuUtilization) +DEFINE_DACVAR(ULONG, ThreadpoolMgr::ThreadCounter, ThreadpoolMgr__WorkerCounter, ThreadpoolMgr::WorkerCounter) +DEFINE_DACVAR(ULONG, int, ThreadpoolMgr__MinLimitTotalWorkerThreads, ThreadpoolMgr::MinLimitTotalWorkerThreads) +DEFINE_DACVAR(ULONG, DWORD, ThreadpoolMgr__MaxLimitTotalWorkerThreads, ThreadpoolMgr::MaxLimitTotalWorkerThreads) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_WorkRequest*/, ThreadpoolMgr__WorkRequestHead, ThreadpoolMgr::WorkRequestHead) // PTR_WorkRequest is not defined. So use a pointer type +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE /*PTR_WorkRequest*/, ThreadpoolMgr__WorkRequestTail, ThreadpoolMgr::WorkRequestTail) // +DEFINE_DACVAR(ULONG, ThreadpoolMgr::ThreadCounter, ThreadpoolMgr__CPThreadCounter, ThreadpoolMgr::CPThreadCounter) +DEFINE_DACVAR(ULONG, LONG, ThreadpoolMgr__MaxFreeCPThreads, ThreadpoolMgr::MaxFreeCPThreads) +DEFINE_DACVAR(ULONG, LONG, ThreadpoolMgr__MaxLimitTotalCPThreads, ThreadpoolMgr::MaxLimitTotalCPThreads) +DEFINE_DACVAR(ULONG, LONG, ThreadpoolMgr__MinLimitTotalCPThreads, ThreadpoolMgr::MinLimitTotalCPThreads) +DEFINE_DACVAR(ULONG, LIST_ENTRY, ThreadpoolMgr__TimerQueue, ThreadpoolMgr::TimerQueue) +DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__HillClimbingLog, ::HillClimbingLog) +DEFINE_DACVAR(ULONG, int, dac__HillClimbingLogFirstIndex, ::HillClimbingLogFirstIndex) +DEFINE_DACVAR(ULONG, int, dac__HillClimbingLogSize, ::HillClimbingLogSize) + +DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pFinalizerThread, ::g_pFinalizerThread) +DEFINE_DACVAR(ULONG, PTR_Thread, dac__g_pSuspensionThread, ::g_pSuspensionThread) + +DEFINE_DACVAR(ULONG, DWORD, dac__g_heap_type, g_heap_type) +DEFINE_DACVAR(ULONG, PTR_GcDacVars, dac__g_gcDacGlobals, g_gcDacGlobals) + +DEFINE_DACVAR(ULONG, PTR_AppDomain, AppDomain__m_pTheAppDomain, AppDomain::m_pTheAppDomain) +DEFINE_DACVAR(ULONG, PTR_SystemDomain, SystemDomain__m_pSystemDomain, SystemDomain::m_pSystemDomain) +#ifdef FEATURE_PREJIT +DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceDebug, SystemDomain::s_fForceDebug) +DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceProfiling, SystemDomain::s_fForceProfiling) +DEFINE_DACVAR(ULONG, BOOL, SystemDomain__s_fForceInstrument, SystemDomain::s_fForceInstrument) +#endif + +#ifdef FEATURE_INTEROP_DEBUGGING +DEFINE_DACVAR(ULONG, DWORD, dac__g_debuggerWordTLSIndex, g_debuggerWordTLSIndex) +#endif +DEFINE_DACVAR(ULONG, DWORD, dac__g_TlsIndex, g_TlsIndex) + +DEFINE_DACVAR(ULONG, PTR_SString, SString__s_Empty, SString::s_Empty) + +#ifdef FEATURE_APPX +DEFINE_DACVAR(ULONG, BOOL, dac__g_fAppX, ::g_fAppX) +#endif // FEATURE_APPX + +DEFINE_DACVAR(ULONG, INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero) + +DEFINE_DACVAR(ULONG, BOOL, StackwalkCache__s_Enabled, StackwalkCache::s_Enabled) + +DEFINE_DACVAR(ULONG, PTR_JITNotification, dac__g_pNotificationTable, ::g_pNotificationTable) +DEFINE_DACVAR(ULONG, ULONG32, dac__g_dacNotificationFlags, ::g_dacNotificationFlags) +DEFINE_DACVAR(ULONG, PTR_GcNotification, dac__g_pGcNotificationTable, ::g_pGcNotificationTable) + +DEFINE_DACVAR(ULONG, PTR_EEConfig, dac__g_pConfig, ::g_pConfig) + +DEFINE_DACVAR(ULONG, MscorlibBinder, dac__g_Mscorlib, ::g_Mscorlib) + +#if defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) +DEFINE_DACVAR(ULONG, ProfControlBlock, dac__g_profControlBlock, ::g_profControlBlock) +#endif // defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) + +DEFINE_DACVAR(ULONG, PTR_DWORD, dac__g_card_table, ::g_card_table) +DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_lowest_address, ::g_lowest_address) +DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address) + +DEFINE_DACVAR(ULONG, IGCHeap, dac__g_pGCHeap, ::g_pGCHeap) + +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pModuleIndexDispenser, ::g_pModuleIndexDispenser) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectClass, ::g_pObjectClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pRuntimeTypeClass, ::g_pRuntimeTypeClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pCanonMethodTableClass, ::g_pCanonMethodTableClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pStringClass, ::g_pStringClass) +#ifdef FEATURE_UTF8STRING +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pUtf8StringClass, ::g_pUtf8StringClass) +#endif // FEATURE_UTF8STRING +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pArrayClass, ::g_pArrayClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pSZArrayHelperClass, ::g_pSZArrayHelperClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pNullableClass, ::g_pNullableClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByReferenceClass, ::g_pByReferenceClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExceptionClass, ::g_pExceptionClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadAbortExceptionClass, ::g_pThreadAbortExceptionClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pOutOfMemoryExceptionClass, ::g_pOutOfMemoryExceptionClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pStackOverflowExceptionClass, ::g_pStackOverflowExceptionClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExecutionEngineExceptionClass, ::g_pExecutionEngineExceptionClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pDelegateClass, ::g_pDelegateClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pMulticastDelegateClass, ::g_pMulticastDelegateClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pFreeObjectMethodTable, ::g_pFreeObjectMethodTable) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pOverlappedDataClass, ::g_pOverlappedDataClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pValueTypeClass, ::g_pValueTypeClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEnumClass, ::g_pEnumClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThreadClass, ::g_pThreadClass) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPredefinedArrayTypes) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pByteArrayMT, ::g_pByteArrayMT) + +#ifdef FEATURE_COMINTEROP +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pBaseRuntimeClass, ::g_pBaseRuntimeClass) +#endif + +#ifdef FEATURE_ICASTABLE +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface) +#endif // FEATURE_ICASTABLE + +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pExecuteBackoutCodeHelperMethod, ::g_pExecuteBackoutCodeHelperMethod) + +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectFinalizerMD, ::g_pObjectFinalizerMD) + +DEFINE_DACVAR(ULONG, bool, dac__g_fProcessDetach, ::g_fProcessDetach) +DEFINE_DACVAR(ULONG, DWORD, dac__g_fEEShutDown, ::g_fEEShutDown) +DEFINE_DACVAR(ULONG, DWORD, dac__g_fHostConfig, ::g_fHostConfig) + +DEFINE_DACVAR(ULONG, ULONG, dac__g_CORDebuggerControlFlags, ::g_CORDebuggerControlFlags) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pDebugger, ::g_pDebugger) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pDebugInterface, ::g_pDebugInterface) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEEDbgInterfaceImpl, ::g_pEEDbgInterfaceImpl) +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pEEInterface, ::g_pEEInterface) +DEFINE_DACVAR(ULONG, ULONG, dac__CLRJitAttachState, ::CLRJitAttachState) + +DEFINE_DACVAR(ULONG, BOOL, Debugger__s_fCanChangeNgenFlags, Debugger::s_fCanChangeNgenFlags) + +DEFINE_DACVAR(ULONG, PTR_DebuggerPatchTable, DebuggerController__g_patches, DebuggerController::g_patches) +DEFINE_DACVAR(ULONG, BOOL, DebuggerController__g_patchTableValid, DebuggerController::g_patchTableValid) + +DEFINE_DACVAR(ULONG, SIZE_T, dac__gLowestFCall, ::gLowestFCall) +DEFINE_DACVAR(ULONG, SIZE_T, dac__gHighestFCall, ::gHighestFCall) +DEFINE_DACVAR(ULONG, SIZE_T, dac__gFCallMethods, ::gFCallMethods) + +DEFINE_DACVAR(ULONG, PTR_SyncTableEntry, dac__g_pSyncTable, ::g_pSyncTable) +#ifdef FEATURE_COMINTEROP +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pRCWCleanupList, ::g_pRCWCleanupList) +DEFINE_DACVAR(ULONG, BOOL, RCWWalker__s_bIsGlobalPeggingOn, RCWWalker::s_bIsGlobalPeggingOn) +#endif // FEATURE_COMINTEROP + +#ifndef FEATURE_PAL +DEFINE_DACVAR(ULONG, SIZE_T, dac__g_runtimeLoadedBaseAddress, ::g_runtimeLoadedBaseAddress) +DEFINE_DACVAR(ULONG, SIZE_T, dac__g_runtimeVirtualSize, ::g_runtimeVirtualSize) +#endif // !FEATURE_PAL + +DEFINE_DACVAR(ULONG, SyncBlockCache *, SyncBlockCache__s_pSyncBlockCache, SyncBlockCache::s_pSyncBlockCache) + +DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pStressLog, ::g_pStressLog) + +DEFINE_DACVAR(ULONG, SIZE_T, dac__s_gsCookie, ::s_gsCookie) + +DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__g_FCDynamicallyAssignedImplementations, ::g_FCDynamicallyAssignedImplementations) + +#ifndef FEATURE_PAL +DEFINE_DACVAR(ULONG, HANDLE, dac__g_hContinueStartupEvent, ::g_hContinueStartupEvent) +#endif // !FEATURE_PAL +DEFINE_DACVAR(ULONG, DWORD, CorHost2__m_dwStartupFlags, CorHost2::m_dwStartupFlags) + +DEFINE_DACVAR(ULONG, HRESULT, dac__g_hrFatalError, ::g_hrFatalError) + +#if defined(DEBUGGING_SUPPORTED) && defined (FEATURE_PREJIT) + DEFINE_DACVAR(ULONG, DWORD, PEFile__s_NGENDebugFlags, PEFile::s_NGENDebugFlags) +#endif //defined(DEBUGGING_SUPPORTED) && defined (FEATURE_PREJIT) + +#ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS +DEFINE_DACVAR(ULONG, DWORD, dac__g_MiniMetaDataBuffMaxSize, ::g_MiniMetaDataBuffMaxSize) +DEFINE_DACVAR(ULONG, TADDR, dac__g_MiniMetaDataBuffAddress, ::g_MiniMetaDataBuffAddress) +#endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS + +DEFINE_DACVAR(ULONG, SIZE_T, dac__g_clrNotificationArguments, ::g_clrNotificationArguments) + +#undef DEFINE_DACVAR +#undef DEFINE_DACVAR_NO_DUMP diff --git a/lib/coreclr/src/inc/dbgconfigstrings.h b/lib/coreclr/src/inc/dbgconfigstrings.h new file mode 100644 index 0000000000..acbb7eb0ac --- /dev/null +++ b/lib/coreclr/src/inc/dbgconfigstrings.h @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// This header lists the names of the string resources used by the Windows portion of Mac CoreCLR debugging +// configuration. It's designed to be included multiple times with different definitions of CORECLR_STRING_DEF +// to build either enumerated integer values for each key or a table mapping enum values to key names. +// + +CORECLR_STRING_DEF(CreateFile) +CORECLR_STRING_DEF(WriteFile) +CORECLR_STRING_DEF(CreateDir) +CORECLR_STRING_DEF(InternalError) +CORECLR_STRING_DEF(DecryptFailure) +CORECLR_STRING_DEF(OutOfMemory) +CORECLR_STRING_DEF(Success) +CORECLR_STRING_DEF(DialogTitleMain) +CORECLR_STRING_DEF(DialogTitleInfo) +CORECLR_STRING_DEF(DialogTitleError) +CORECLR_STRING_DEF(OKButton) +CORECLR_STRING_DEF(CancelButton) +CORECLR_STRING_DEF(HeaderText) diff --git a/lib/coreclr/src/inc/dbgenginemetrics.h b/lib/coreclr/src/inc/dbgenginemetrics.h new file mode 100644 index 0000000000..174888565e --- /dev/null +++ b/lib/coreclr/src/inc/dbgenginemetrics.h @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// DbgEngineMetrics.h +// +// This file contains the defintion of CLR_ENGINE_METRICS. This struct is used for Silverlight debugging. +// +// ====================================================================================== + + + +#ifndef __DbgEngineMetrics_h__ +#define __DbgEngineMetrics_h__ + +//--------------------------------------------------------------------------------------- +// +// This struct contains information necessary for Silverlight debugging. coreclr.dll has a static struct +// of this type. It is read by dbgshim.dll to help synchronize the debugger and coreclr.dll in launch +// and early attach scenarios. +// + +typedef struct tagCLR_ENGINE_METRICS +{ + DWORD cbSize; // the size of the struct; also identifies the format of the struct + DWORD dwDbiVersion; // the version of the debugging interface expected by this CoreCLR + LPVOID phContinueStartupEvent; // pointer to the continue startup event handle +} CLR_ENGINE_METRICS; + +#endif // __DbgEngineMetrics_h__ diff --git a/lib/coreclr/src/inc/dbgmeta.h b/lib/coreclr/src/inc/dbgmeta.h new file mode 100644 index 0000000000..ce7a3bbdf3 --- /dev/null +++ b/lib/coreclr/src/inc/dbgmeta.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* ------------------------------------------------------------------------- * + * DbgMeta.h - header file for debugger metadata routines + * ------------------------------------------------------------------------- */ + +#ifndef _DbgMeta_h_ +#define _DbgMeta_h_ + +#include + +/* ------------------------------------------------------------------------- * + * Structs to support line numbers and variables + * ------------------------------------------------------------------------- */ + +class DebuggerLexicalScope; + +// +// DebuggerVarInfo +// +// Holds basic information about local variables, method arguments, +// and class static and instance variables. +// +struct DebuggerVarInfo +{ + LPCSTR name; + PCCOR_SIGNATURE sig; + unsigned int varNumber; // placement info for IL code + DebuggerLexicalScope* scope; // containing scope + + DebuggerVarInfo() : name(NULL), sig(NULL), varNumber(0), + scope(NULL) {} +}; + +#endif /* _DbgMeta_h_ */ + diff --git a/lib/coreclr/src/inc/dbgportable.h b/lib/coreclr/src/inc/dbgportable.h new file mode 100644 index 0000000000..4a035642c2 --- /dev/null +++ b/lib/coreclr/src/inc/dbgportable.h @@ -0,0 +1,141 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __DBG_PORTABLE_INCLUDED +#define __DBG_PORTABLE_INCLUDED + +// +// This header defines the template class Portable which is designed to wrap primitive types in such a way +// that their physical representation is in a canonical format that can be safely transferred between hosts on +// different platforms. +// +// This is achieved by storing the wrapped datum in little-endian format (since most of our platforms are +// little-endian this makes the most sense from a performance perspective). On little-endian platforms the +// wrapper code will become a no-op and get optimized away by the compiler. On big-endian platforms +// assignments to a Portable value will reverse the order of the bytes in the T value and reverse them back +// again on a read. +// +// Portable is typically used to wrap the fields of structures sent directly over a network channel. In +// this fashion many of the values that would otherwise require manual endian-ness fixups are now marshalled +// and unmarshalled transparent right at the network transition. +// +// Care must be taken to identify any code that takes the address of a Portable, since this is not +// generally safe (it could expose naive code to the network encoded form of the datum). In such situations +// the code is normally re-written to create a temporary instance of T on the stack, initialized to the +// correct host value by reading from the Portable field. The address of this variable can now be taken +// safely (assuming its value is required only for some lexically scoped operation). Once the value is no +// longer being used, and if there is a possibility that the value may have been updated, the new value can be +// copied back into the Portable field. +// +// Note that this header uses very basic data types only as it is included from both Win32/PAL code and native +// Mac code. +// + +#if BIGENDIAN || __BIG_ENDIAN__ +#define DBG_BYTE_SWAP_REQUIRED +#endif + +#if defined(_ASSERTE) +#define _PASSERT(_expr) _ASSERTE(_expr) +#elif defined(assert) +#define _PASSERT(_expr) assert(_expr) +#else +#define _PASSERT(_expr) +#endif + +// Lowest level helper used to reverse the order of a sequence of bytes, either as an in-place operation or as +// part of a copy. +inline void ByteSwapPrimitive(const void *pSrc, void *pDst, unsigned int cbSize) +{ + _PASSERT(cbSize == 2 || cbSize == 4 || cbSize == 8); + + unsigned char *pbSrc = (unsigned char*)pSrc; + unsigned char *pbDst = (unsigned char*)pDst; + + for (unsigned int i = 0; i < (cbSize / 2); i++) + { + unsigned int j = cbSize - i - 1; + unsigned char bTemp = pbSrc[i]; + pbDst[i] = pbSrc[j]; + pbDst[j] = bTemp; + } +} + +template +class Portable +{ + T m_data; + +public: + // No constructors -- this will be used in unions. + + // Convert data to portable format on assignment. + T operator = (T value) + { + _PASSERT(sizeof(value) <= sizeof(double)); +#ifdef DBG_BYTE_SWAP_REQUIRED + m_data = ByteSwap(value); +#else // DBG_BYTE_SWAP_REQUIRED + m_data = value; +#endif // DBG_BYTE_SWAP_REQUIRED + return value; + } + + // Return data in native format on access. + operator T () const + { +#ifdef DBG_BYTE_SWAP_REQUIRED + return ByteSwap(m_data); +#else // DBG_BYTE_SWAP_REQUIRED + return m_data; +#endif // DBG_BYTE_SWAP_REQUIRED + } + + bool operator == (T other) const + { +#ifdef DBG_BYTE_SWAP_REQUIRED + return ByteSwap(m_data) == other; +#else // DBG_BYTE_SWAP_REQUIRED + return m_data == other; +#endif // DBG_BYTE_SWAP_REQUIRED + } + + bool operator != (T other) const + { +#ifdef DBG_BYTE_SWAP_REQUIRED + return ByteSwap(m_data) != other; +#else // DBG_BYTE_SWAP_REQUIRED + return m_data != other; +#endif // DBG_BYTE_SWAP_REQUIRED + } + + T Unwrap() + { +#ifdef DBG_BYTE_SWAP_REQUIRED + return ByteSwap(m_data); +#else // DBG_BYTE_SWAP_REQUIRED + return m_data; +#endif // DBG_BYTE_SWAP_REQUIRED + } + +private: +#ifdef DBG_BYTE_SWAP_REQUIRED + // Big endian helper routine to swap the order of bytes of an arbitrary sized type + // (though obviously this type must be an integral primitive for this to make any + // sense). + static T ByteSwap(T inval) + { + if (sizeof(T) > 1) + { + T outval; + ByteSwapPrimitive(&inval, &outval, sizeof(T)); + return outval; + } + else + return inval; + } +#endif // DBG_BYTE_SWAP_REQUIRED +}; + +#endif // !__DBG_PORTABLE_INCLUDED diff --git a/lib/coreclr/src/inc/debugmacros.h b/lib/coreclr/src/inc/debugmacros.h new file mode 100644 index 0000000000..540be99c74 --- /dev/null +++ b/lib/coreclr/src/inc/debugmacros.h @@ -0,0 +1,269 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// DebugMacros.h +// +// Wrappers for Debugging purposes. +// +//***************************************************************************** + +#ifndef __DebugMacros_h__ +#define __DebugMacros_h__ + +#include "stacktrace.h" +#include "debugmacrosext.h" +#include "palclr.h" + +#undef _ASSERTE +#undef VERIFY + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#if defined(_DEBUG) + +class SString; +bool GetStackTraceAtContext(SString & s, struct _CONTEXT * pContext); + +void _cdecl DbgWriteEx(LPCTSTR szFmt, ...); +bool _DbgBreakCheck(LPCSTR szFile, int iLine, LPCSTR szExpr, BOOL fConstrained = FALSE); + +extern VOID ANALYZER_NORETURN DbgAssertDialog(const char *szFile, int iLine, const char *szExpr); + +#define TRACE_BUFF_SIZE (cchMaxAssertStackLevelStringLen * cfrMaxAssertStackLevels + cchMaxAssertExprLen + 1) +extern char g_szExprWithStack[TRACE_BUFF_SIZE]; + +extern int _DbgBreakCount; + +#define PRE_ASSERTE /* if you need to change modes before doing asserts override */ +#define POST_ASSERTE /* put it back */ + +#if !defined(_ASSERTE_MSG) + #define _ASSERTE_MSG(expr, msg) \ + do { \ + if (!(expr)) { \ + PRE_ASSERTE \ + DbgAssertDialog(__FILE__, __LINE__, msg); \ + POST_ASSERTE \ + } \ + } while (0) +#endif // _ASSERTE_MSG + +#if !defined(_ASSERTE) + #define _ASSERTE(expr) _ASSERTE_MSG(expr, #expr) +#endif // !_ASSERTE + + +#define VERIFY(stmt) _ASSERTE((stmt)) + +#define _ASSERTE_ALL_BUILDS(file, expr) _ASSERTE((expr)) + +#define FreeBuildDebugBreak() DebugBreak() + +#else // !_DEBUG + +#define _DbgBreakCount 0 + +#define _ASSERTE(expr) ((void)0) +#define _ASSERTE_MSG(expr, msg) ((void)0) +#define VERIFY(stmt) (void)(stmt) + +void __FreeBuildDebugBreak(); +void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr); + +#define FreeBuildDebugBreak() __FreeBuildDebugBreak() + +// At this point, EEPOLICY_HANDLE_FATAL_ERROR may or may not be defined. It will be defined +// if we are building the VM folder, but outside VM, its not necessarily defined. +// +// Thus, if EEPOLICY_HANDLE_FATAL_ERROR is not defined, we will call into __FreeBuildAssertFail, +// but if it is defined, we will use it. +// +// Failing here implies an error in the runtime - hence we use COR_E_EXECUTIONENGINE. + +#ifdef EEPOLICY_HANDLE_FATAL_ERROR +#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); +#else // !EEPOLICY_HANDLE_FATAL_ERROR +#define _ASSERTE_ALL_BUILDS(file, expr) if (!(expr)) __FreeBuildAssertFail(file, __LINE__, #expr); +#endif // EEPOLICY_HANDLE_FATAL_ERROR + +#endif + + +#define ASSERT_AND_CHECK(x) { \ + BOOL bResult = x; \ + if (!bResult) \ + { \ + _ASSERTE(x); \ + return FALSE; \ + } \ +} + + +#ifdef _DEBUG_IMPL + +// A macro to execute a statement only in _DEBUG_IMPL. +#define DEBUG_IMPL_STMT(stmt) stmt + +#define _ASSERTE_IMPL(expr) _ASSERTE((expr)) + +#if defined(_M_IX86) +#if defined(_MSC_VER) +#define _DbgBreak() __asm { int 3 } +#elif defined(__GNUC__) +#define _DbgBreak() __asm__ ("int $3"); +#else +#error Unknown compiler +#endif +#else +#define _DbgBreak() DebugBreak() +#endif + +extern VOID DebBreak(); +extern VOID DebBreakHr(HRESULT hr); + +#ifndef IfFailGoto +#define IfFailGoto(EXPR, LABEL) \ +do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); goto LABEL; } } while (0) +#endif + +#ifndef IfFailRet +#define IfFailRet(EXPR) \ +do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); return (hr); } } while (0) +#endif + +#ifndef IfFailWin32Ret +#define IfFailWin32Ret(EXPR) \ +do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); return hr;} } while (0) +#endif + +#ifndef IfFailWin32Goto +#define IfFailWin32Goto(EXPR, LABEL) \ +do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); goto LABEL; } } while (0) +#endif + +#ifndef IfFailGo +#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) +#endif + +#ifndef IfFailWin32Go +#define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit) +#endif + +#else // _DEBUG_IMPL + +#define _DbgBreak() {} + +#define DEBUG_IMPL_STMT(stmt) + +#define _ASSERTE_IMPL(expr) + +#define IfFailGoto(EXPR, LABEL) \ +do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0) + +#define IfFailRet(EXPR) \ +do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0) + +#define IfFailWin32Ret(EXPR) \ +do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); return hr;} } while (0) + +#define IfFailWin32Goto(EXPR, LABEL) \ +do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); goto LABEL; } } while (0) + +#define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) + +#define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit) + +#endif // _DEBUG_IMPL + + +#define IfNullGoto(EXPR, LABEL) \ + do { if ((EXPR) == NULL) { OutOfMemory(); IfFailGoto(E_OUTOFMEMORY, LABEL); } } while (false) + +#ifndef IfNullRet +#define IfNullRet(EXPR) \ + do { if ((EXPR) == NULL) { OutOfMemory(); return E_OUTOFMEMORY; } } while (false) +#endif //!IfNullRet + +#define IfNullGo(EXPR) IfNullGoto(EXPR, ErrExit) + +#ifdef __cplusplus +} + +#endif // __cplusplus + + +#undef assert +#define assert _ASSERTE +#undef _ASSERT +#define _ASSERT _ASSERTE + + +#if defined(_DEBUG) && !defined(FEATURE_PAL) + +// This function returns the EXE time stamp (effectively a random number) +// Under retail it always returns 0. This is meant to be used in the +// RandomOnExe macro +unsigned DbgGetEXETimeStamp(); + +// returns true 'fractionOn' amount of the time using the EXE timestamp +// as the random number seed. For example DbgRandomOnExe(.1) returns true 1/10 +// of the time. We use the line number so that different uses of DbgRandomOnExe +// will not be coorelated with each other (9973 is prime). Returns false on a retail build +#define DbgRandomOnHashAndExe(hash, fractionOn) \ + (((DbgGetEXETimeStamp() * __LINE__ * ((hash) ? (hash) : 1)) % 9973) < \ + unsigned(fractionOn * 9973)) +#define DbgRandomOnExe(fractionOn) DbgRandomOnHashAndExe(0, fractionOn) +#define DbgRandomOnStringAndExe(string, fractionOn) DbgRandomOnHashAndExe(HashStringA(string), fractionOn) + +#else + +#define DbgGetEXETimeStamp() 0 +#define DbgRandomOnHashAndExe(hash, fractionOn) 0 +#define DbgRandomOnExe(fractionOn) 0 +#define DbgRandomOnStringAndExe(fractionOn) 0 + +#endif // _DEBUG && !FEATUREPAL + +#ifdef _DEBUG +namespace clr +{ + namespace dbg + { + // In debug builds, this can be used to write known bad values into + // memory. One example is in ComUtil::IUnknownCommon::~IUnknownCommon, + // which overwrites its instance memory with a known bad value after + // completing its destructor. + template < typename T > + void PoisonMem(T &val) + { + ZeroMemory((void*)&val, sizeof(T)); + } + + template < typename T > + void PoisonMem(T* ptr, size_t len) + { + ZeroMemory((void*)ptr, sizeof(T)* len); + } + } +} +#else + +// Empty versions of the functions in retail that will be inlined +// and completely elided. +namespace clr +{ + namespace dbg + { + template < typename T > + inline void PoisonMem(T &) {} + + template < typename T > + void PoisonMem(T* ptr, size_t len){} + } +} +#endif + +#endif diff --git a/lib/coreclr/src/inc/debugmacrosext.h b/lib/coreclr/src/inc/debugmacrosext.h new file mode 100644 index 0000000000..e1aade65b5 --- /dev/null +++ b/lib/coreclr/src/inc/debugmacrosext.h @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// DebugMacrosExt.h +// +// Simple debugging macros that take no dependencies on CLR headers. +// This header can be used from outside the CLR. +// +//***************************************************************************** + +#ifndef __DebugMacrosExt_h__ +#define __DebugMacrosExt_h__ + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +#ifdef _DEBUG +// A macro to execute a statement only in _DEBUG. +#define DEBUG_STMT(stmt) stmt +#define INDEBUG(x) x +#define INDEBUG_COMMA(x) x, +#define COMMA_INDEBUG(x) ,x +#define NOT_DEBUG(x) +#else +#define DEBUG_STMT(stmt) +#define INDEBUG(x) +#define INDEBUG_COMMA(x) +#define COMMA_INDEBUG(x) +#define NOT_DEBUG(x) x +#endif + + +#ifdef _DEBUG_IMPL +#define INDEBUGIMPL(x) x +#define INDEBUGIMPL_COMMA(x) x, +#define COMMA_INDEBUGIMPL(x) ,x +#else +#define INDEBUGIMPL(x) +#define INDEBUGIMPL_COMMA(x) +#define COMMA_INDEBUGIMPL(x) +#endif + + +#endif diff --git a/lib/coreclr/src/inc/debugreturn.h b/lib/coreclr/src/inc/debugreturn.h new file mode 100644 index 0000000000..73edd010ef --- /dev/null +++ b/lib/coreclr/src/inc/debugreturn.h @@ -0,0 +1,125 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _DEBUGRETURN_H_ +#define _DEBUGRETURN_H_ + +// Note that with OACR Prefast is run over checked (_DEBUG is defined) sources +// so we have to first check the _PREFAST_ define followed by the _DEBUG define +// +#ifdef _PREFAST_ + +// Use prefast to detect gotos out of no-return blocks. The gotos out of no-return blocks +// should be reported as memory leaks by prefast. The (nothrow) is because PREfix sees the +// throw from the new statement, and doesn't like these macros used in a destructor (and +// the NULL returned by failure works just fine in delete[]) + +#define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { char* __noReturnInThisBlock_##arg = ::new (nothrow) char[1]; +#define DEBUG_ASSURE_NO_RETURN_END(arg) ::delete[] __noReturnInThisBlock_##arg; } + +#define DEBUG_OK_TO_RETURN_BEGIN(arg) { ::delete[] __noReturnInThisBlock_##arg; +#define DEBUG_OK_TO_RETURN_END(arg) __noReturnInThisBlock_##arg = ::new (nothrow) char[1]; } + +#define DEBUG_ASSURE_SAFE_TO_RETURN TRUE +#define return return + +#else // !_PREFAST_ + +// This is disabled in build 190024315 (a pre-release build after VS 2015 Update 3) and +// earlier because those builds only support C++11 constexpr, which doesn't allow the +// use of 'if' statements within the body of a constexpr function. Later builds support +// C++14 constexpr. +#if defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) + +// Code to generate a compile-time error if return statements appear where they +// shouldn't. +// +// Here's the way it works... +// +// We create two classes with a safe_to_return() method. The method is static, +// returns void, and does nothing. One class has the method as public, the other +// as private. We introduce a global scope typedef for __ReturnOK that refers to +// the class with the public method. So, by default, the expression +// +// __ReturnOK::safe_to_return() +// +// quietly compiles and does nothing. When we enter a block in which we want to +// inhibit returns, we introduce a new typedef that defines __ReturnOK as the +// class with the private method. Inside this scope, +// +// __ReturnOK::safe_to_return() +// +// generates a compile-time error. +// +// To cause the method to be called, we have to #define the return keyword. +// The simplest working version would be +// +// #define return if (0) __ReturnOK::safe_to_return(); else return +// +// but we've used +// +// #define return for (;1;__ReturnOK::safe_to_return()) return +// +// because it happens to generate somewhat faster code in a checked build. (They +// both introduce no overhead in a fastchecked build.) +// +class __SafeToReturn { +public: + static int safe_to_return() {return 0;}; + static int used() {return 0;}; +}; + +class __YouCannotUseAReturnStatementHere { +private: + // If you got here, and you're wondering what you did wrong -- you're using + // a return statement where it's not allowed. Likely, it's inside one of: + // GCPROTECT_BEGIN ... GCPROTECT_END + // HELPER_METHOD_FRAME_BEGIN ... HELPER_METHOD_FRAME_END + // + static int safe_to_return() {return 0;}; +public: + // Some compilers warn if all member functions in a class are private + // or if a typedef is unused. Rather than disable the warning, we'll work + // around it here. + static int used() {return 0;}; +}; + +typedef __SafeToReturn __ReturnOK; + +// Use this to ensure that it is safe to return from a given scope +#define DEBUG_ASSURE_SAFE_TO_RETURN __ReturnOK::safe_to_return() + +// Unfortunately, the only way to make this work is to #define all return statements -- +// even the ones at global scope. This actually generates better code that appears. +// The call is dead, and does not appear in the generated code, even in a checked +// build. (And, in fastchecked, there is no penalty at all.) +// +#ifdef _MSC_VER +#define return if (0 && __ReturnOK::safe_to_return()) { } else return +#else // _MSC_VER +#define return for (;1;__ReturnOK::safe_to_return()) return +#endif // _MSC_VER + +#define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { typedef __YouCannotUseAReturnStatementHere __ReturnOK; if (0 && __ReturnOK::used()) { } else { +#define DEBUG_ASSURE_NO_RETURN_END(arg) } } + +#define DEBUG_OK_TO_RETURN_BEGIN(arg) { typedef __SafeToReturn __ReturnOK; if (0 && __ReturnOK::used()) { } else { +#define DEBUG_OK_TO_RETURN_END(arg) } } + +#else // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) + +#define DEBUG_ASSURE_SAFE_TO_RETURN TRUE + +#define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { +#define DEBUG_ASSURE_NO_RETURN_END(arg) } + +#define DEBUG_OK_TO_RETURN_BEGIN(arg) { +#define DEBUG_OK_TO_RETURN_END(arg) } + +#endif // defined(_DEBUG) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) + +#endif // !_PREFAST_ + +#endif // _DEBUGRETURN_H_ diff --git a/lib/coreclr/src/inc/defaultallocator.h b/lib/coreclr/src/inc/defaultallocator.h new file mode 100644 index 0000000000..ee342dff8b --- /dev/null +++ b/lib/coreclr/src/inc/defaultallocator.h @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _DEFAULTALLOCATOR_H_ +#define _DEFAULTALLOCATOR_H_ + +// The "DefaultAllocator" class may be used by classes that wish to +// provide the flexibility of using an "IAllocator" may avoid writing +// conditionals at allocation sites about whether a non-default +// "IAllocator" has been provided: if none is, they can simply set the +// allocator to DefaultAllocator::Singleton(). +class DefaultAllocator: public IAllocator +{ + static DefaultAllocator s_singleton; + +public: + void* Alloc(size_t sz) + { + return ::operator new(sz); + } + + void* ArrayAlloc(size_t elemSize, size_t numElems) + { + ClrSafeInt safeElemSize(elemSize); + ClrSafeInt safeNumElems(numElems); + ClrSafeInt sz = safeElemSize * safeNumElems; + if (sz.IsOverflow()) + { + return NULL; + } + else + { + return ::operator new(sz.Value()); + } + } + + virtual void Free(void * p) + { + ::operator delete(p); + } + + static DefaultAllocator* Singleton() + { + return &s_singleton; + } +}; + +#endif // _DEFAULTALLOCATOR_H_ diff --git a/lib/coreclr/src/inc/delayloadhelpers.h b/lib/coreclr/src/inc/delayloadhelpers.h new file mode 100644 index 0000000000..2a62a8d95c --- /dev/null +++ b/lib/coreclr/src/inc/delayloadhelpers.h @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// Contains convenience functionality for lazily loading modules +// and getting entrypoints within them. +// + +#ifndef DelayLoadHelpers_h +#define DelayLoadHelpers_h + +#include "volatile.h" + +namespace DelayLoad +{ + //================================================================================================================= + // Contains information needed to load and cache a module. Use through + // the DELAY_LOADED_MODULE macro defined below. + struct Module + { + LPCWSTR const m_wzDllName; + HMODULE m_hMod; + HRESULT m_hr; + Volatile m_fInitialized; + + // Returns a non-ref-counted HMODULE; will load the module if necessary. + // Do not FreeLibrary the returned value. + HRESULT GetValue(HMODULE *pHMODULE); + }; +} + +//===================================================================================================================== +// Use at global scope to declare a delay loaded module represented as a +// DelayLoad::Module instance. The module may then be accessed as +// 'DelayLoad::Modules::DLL_NAME'. +// +// Parameters: +// DLL_NAME - the simple name (without extension) of the DLL. +// +// Example: +// DELAY_LOADED_MODULE(Kernel32); +// void Foo() { +// HMODULE hModKernel32 = nullptr; +// IfFailThrow(DelayLoad::Modules::Kernel32.GetValue(&hModKernel32)); +// // Use hModKernel32 as needed. Do not FreeLibrary the value! +// } + +#define DELAY_LOADED_MODULE(DLL_NAME) \ + namespace DelayLoad { \ + namespace Modules { \ + SELECTANY Module DLL_NAME = { L#DLL_NAME W(".dll"), nullptr, S_OK, false }; \ + } \ + } + +namespace DelayLoad +{ + //================================================================================================================= + // Contains information needed to load a function pointer from a DLL. Builds + // on the DelayLoad::Module functionality, and should be used through + // the DELAY_LOADED_FUNCTION macro defined below. + struct Function + { + Module * const m_pModule; + LPCSTR const m_szFunctionName; + PVOID m_pvFunction; + HRESULT m_hr; + Volatile m_fInitialized; + + // On success, ppvFunc is set to point to the entrypoint corresponding to + // m_szFunctionName as exported from m_pModule. + HRESULT GetValue(LPVOID * ppvFunc); + + // Convenience function that does the necessary casting for you. + template inline + HRESULT GetValue(FnT ** ppFunc) + { + return GetValue(reinterpret_cast(ppFunc)); + } + }; +} + +//===================================================================================================================== +// Use at global scope to declare a delay loaded function and its associated module, +// represented as DelayLoad::Function and DelayLoad::Module instances, respectively. +// The function may then be accessed as 'DelayLoad::DLL_NAME::FUNC_NAME', and the +// module may be access as described in DELAY_LOADED_MODULE's comment. +// +// Parameters: +// DLL_NAME - unquoted simple name (without extension) of the DLL containing +// the function. +// FUNC_NAME - unquoted entrypoint name exported from the DLL. +// +// Example: +// DELAY_LOADED_FUNCTION(MyDll, MyFunction); +// HRESULT Foo(...) { +// typedef HRESULT MyFunction_t(); +// MyFunction_t * pFunc = nullptr; +// IfFailRet(DelayLoad::WinTypes::RoResolveNamespace.GetValue(&pFunc)); +// return (*pFunc)(...); +// } + +#define DELAY_LOADED_FUNCTION(DLL_NAME, FUNC_NAME) \ + DELAY_LOADED_MODULE(DLL_NAME) \ + namespace DelayLoad { \ + namespace DLL_NAME { \ + SELECTANY Function FUNC_NAME = { &Modules::##DLL_NAME, #FUNC_NAME, nullptr, S_OK, false }; \ + } \ + } + +#endif // DelayLoadHelpers_h + diff --git a/lib/coreclr/src/inc/dlwrap.h b/lib/coreclr/src/inc/dlwrap.h new file mode 100644 index 0000000000..853bc58d7f --- /dev/null +++ b/lib/coreclr/src/inc/dlwrap.h @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +// + +#ifndef _DLWRAP_H +#define _DLWRAP_H + +//include this file if you get contract violation because of delayload + +//nothrow implementations + +#if defined(VER_H) && !defined (GetFileVersionInfoSizeW_NoThrow) +DWORD +GetFileVersionInfoSizeW_NoThrow( + LPCWSTR lptstrFilename, /* Filename of version stamped file */ + LPDWORD lpdwHandle + ); +#endif + +#if defined(VER_H) && !defined (GetFileVersionInfoW_NoThrow) +BOOL +GetFileVersionInfoW_NoThrow( + LPCWSTR lptstrFilename, /* Filename of version stamped file */ + DWORD dwHandle, /* Information from GetFileVersionSize */ + DWORD dwLen, /* Length of buffer for info */ + LPVOID lpData + ); +#endif + +#if defined(VER_H) && !defined (VerQueryValueW_NoThrow) +BOOL +VerQueryValueW_NoThrow( + const LPVOID pBlock, + LPCWSTR lpSubBlock, + LPVOID * lplpBuffer, + PUINT puLen + ); +#endif + +#if defined(_WININET_) && !defined (CreateUrlCacheEntryW_NoThrow) +__success(return) +BOOL +CreateUrlCacheEntryW_NoThrow( + IN LPCWSTR lpszUrlName, + IN DWORD dwExpectedFileSize, + IN LPCWSTR lpszFileExtension, + __out_ecount(MAX_LONGPATH+1) LPWSTR lpszFileName, + IN DWORD dwReserved + ); +#endif + +#if defined(_WININET_) && !defined (CommitUrlCacheEntryW_NoThrow) +BOOL +CommitUrlCacheEntryW_NoThrow( + IN LPCWSTR lpszUrlName, + IN LPCWSTR lpszLocalFileName, + IN FILETIME ExpireTime, + IN FILETIME LastModifiedTime, + IN DWORD CacheEntryType, + IN LPCWSTR lpHeaderInfo, + IN DWORD dwHeaderSize, + IN LPCWSTR lpszFileExtension, + IN LPCWSTR lpszOriginalUrl + ); +#endif + +#if defined(_WININET_) && !defined (InternetTimeToSystemTimeA_NoThrow) +BOOL +InternetTimeToSystemTimeA_NoThrow( + IN LPCSTR lpszTime, // NULL terminated string + OUT SYSTEMTIME *pst, // output in GMT time + IN DWORD dwReserved + ); +#endif + +#if defined(__urlmon_h__) && !defined(CoInternetCreateSecurityManager_NoThrow) +HRESULT +CoInternetCreateSecurityManager_NoThrow( + IServiceProvider *pSP, + IInternetSecurityManager **ppSM, + DWORD dwReserved + ); +#endif + +#if defined(__urlmon_h__) && !defined(URLDownloadToCacheFileW_NoThrow) +HRESULT +URLDownloadToCacheFileW_NoThrow( + LPUNKNOWN lpUnkcaller, + LPCWSTR szURL, + __out_ecount(dwBufLength) LPWSTR szFileName, + DWORD dwBufLength, + DWORD dwReserved, + IBindStatusCallback *pBSC + ); +#endif + +#if defined(__urlmon_h__) && !defined(CoInternetGetSession_NoThrow) +HRESULT +CoInternetGetSession_NoThrow( + WORD dwSessionMode, + IInternetSession **ppIInternetSession, + DWORD dwReserved + ); +#endif + +#if defined(__urlmon_h__) && !defined(CopyBindInfo_NoThrow) +HRESULT +CopyBindInfo_NoThrow( + const BINDINFO * pcbiSrc, BINDINFO * pbiDest + ); +#endif + + + +//overrides +#undef InternetTimeToSystemTimeA +#undef CommitUrlCacheEntryW +#undef HttpQueryInfoA +#undef InternetCloseHandle +#undef HttpSendRequestA +#undef HttpOpenRequestA +#undef InternetConnectA +#undef InternetOpenA +#undef InternetReadFile +#undef CreateUrlCacheEntryW +#undef CoInternetGetSession +#undef CopyBindInfo +#undef CoInternetCreateSecurityManager +#undef URLDownloadToCacheFileW +#undef FDICreate +#undef FDIIsCabinet +#undef FDICopy +#undef FDIDestroy +#undef VerQueryValueW +#undef GetFileVersionInfoW +#undef GetFileVersionInfoSizeW +#undef VerQueryValueA +#undef GetFileVersionInfoA +#undef GetFileVersionInfoSizeA + + +#define InternetTimeToSystemTimeA InternetTimeToSystemTimeA_NoThrow +#define CommitUrlCacheEntryW CommitUrlCacheEntryW_NoThrow +#define CreateUrlCacheEntryW CreateUrlCacheEntryW_NoThrow +#define CoInternetGetSession CoInternetGetSession_NoThrow +#define CopyBindInfo CopyBindInfo_NoThrow +#define CoInternetCreateSecurityManager CoInternetCreateSecurityManager_NoThrow +#define URLDownloadToCacheFileW URLDownloadToCacheFileW_NoThrow +#define VerQueryValueW VerQueryValueW_NoThrow +#define GetFileVersionInfoW GetFileVersionInfoW_NoThrow +#define GetFileVersionInfoSizeW GetFileVersionInfoSizeW_NoThrow +#define VerQueryValueA Use_VerQueryValueW +#define GetFileVersionInfoA Use_GetFileVersionInfoW +#define GetFileVersionInfoSizeA Use_GetFileVersionInfoSizeW + +#if defined(_WININET_) + inline + HRESULT HrCreateUrlCacheEntryW( + IN LPCWSTR lpszUrlName, + IN DWORD dwExpectedFileSize, + IN LPCWSTR lpszFileExtension, + __out_ecount(MAX_LONGPATH+1) LPWSTR lpszFileName, + IN DWORD dwReserved + ) + { + if (!CreateUrlCacheEntryW(lpszUrlName, dwExpectedFileSize, lpszFileExtension, lpszFileName, dwReserved)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + else + { + return S_OK; + } + } + + inline + HRESULT HrCommitUrlCacheEntryW( + IN LPCWSTR lpszUrlName, + IN LPCWSTR lpszLocalFileName, + IN FILETIME ExpireTime, + IN FILETIME LastModifiedTime, + IN DWORD CacheEntryType, + IN LPCWSTR lpHeaderInfo, + IN DWORD dwHeaderSize, + IN LPCWSTR lpszFileExtension, + IN LPCWSTR lpszOriginalUrl + ) + { + if (!CommitUrlCacheEntryW(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime, CacheEntryType, + lpHeaderInfo, dwHeaderSize, lpszFileExtension, lpszOriginalUrl)) + { + return HRESULT_FROM_WIN32(GetLastError()); + } + else + { + return S_OK; + } + } +#endif // defined(_WININET_) + +#endif + diff --git a/lib/coreclr/src/inc/eetwain.h b/lib/coreclr/src/inc/eetwain.h new file mode 100644 index 0000000000..9597e30e44 --- /dev/null +++ b/lib/coreclr/src/inc/eetwain.h @@ -0,0 +1,799 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// +// EETwain.h +// +// This file has the definition of ICodeManager and EECodeManager. +// +// ICorJitCompiler compiles the IL of a method to native code, and stores +// auxilliary data called as GCInfo (via ICorJitInfo::allocGCInfo()). +// The data is used by the EE to manage the method's garbage collection, +// exception handling, stack-walking etc. +// This data can be parsed by an ICodeManager corresponding to that +// ICorJitCompiler. +// +// EECodeManager is an implementation of ICodeManager for a default format +// of GCInfo. Various ICorJitCompiler's are free to share this format so that +// they do not need to provide their own implementation of ICodeManager +// (though they are permitted to, if they want). +// +//***************************************************************************** + +#ifndef _EETWAIN_H +#define _EETWAIN_H +//***************************************************************************** + +#include +#include "regdisp.h" +#include "corjit.h" // For NativeVarInfo +#include "stackwalktypes.h" +#include "bitvector.h" +#include "gcinfotypes.h" + +#if !defined(_TARGET_X86_) +#define USE_GC_INFO_DECODER +#endif + +#if (defined(_TARGET_X86_) && !defined(FEATURE_PAL)) || defined(_TARGET_AMD64_) +#define HAS_QUICKUNWIND +#endif + +#define CHECK_APP_DOMAIN 0 + +#define NO_OVERRIDE_OFFSET (DWORD)-1 + +struct EHContext; + +#ifdef DACCESS_COMPILE +typedef struct _DAC_SLOT_LOCATION +{ + int reg; + int regOffset; + bool targetPtr; + + _DAC_SLOT_LOCATION(int _reg, int _regOffset, bool _targetPtr) + : reg(_reg), regOffset(_regOffset), targetPtr(_targetPtr) + { + } +} DacSlotLocation; +#endif + +typedef void (*GCEnumCallback)( + LPVOID hCallback, // callback data + OBJECTREF* pObject, // address of obect-reference we are reporting + uint32_t flags // is this a pinned and/or interior pointer + DAC_ARG(DacSlotLocation loc) // where the reference came from +); + +/****************************************************************************** + The stackwalker maintains some state on behalf of ICodeManager. +*/ + +const int CODEMAN_STATE_SIZE = 512; + +struct CodeManState +{ + DWORD dwIsSet; // Is set to 0 by the stackwalk as appropriate + BYTE stateBuf[CODEMAN_STATE_SIZE]; +}; + +/****************************************************************************** + These flags are used by some functions, although not all combinations might + make sense for all functions. +*/ + +enum ICodeManagerFlags +{ + ActiveStackFrame = 0x0001, // this is the currently active function + ExecutionAborted = 0x0002, // execution of this function has been aborted + // (i.e. it will not continue execution at the + // current location) + AbortingCall = 0x0004, // The current call will never return + UpdateAllRegs = 0x0008, // update full register set + CodeAltered = 0x0010, // code of that function might be altered + // (e.g. by debugger), need to call EE + // for original code + SpeculativeStackwalk + = 0x0020, // we're in the middle of a stackwalk seeded + // by an untrusted source (e.g., sampling profiler) + + ParentOfFuncletStackFrame + = 0x0040, // A funclet for this frame was previously reported + NoReportUntracked + = 0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include + // any untracked slots +}; + +//***************************************************************************** +// +// EECodeInfo is used by ICodeManager to get information about the +// method whose GCInfo is being processed. +// It is useful so that some information which is available elsewhere does +// not need to be cached in the GCInfo. +// + +class EECodeInfo; + +enum GenericParamContextType +{ + GENERIC_PARAM_CONTEXT_NONE = 0, + GENERIC_PARAM_CONTEXT_THIS = 1, + GENERIC_PARAM_CONTEXT_METHODDESC = 2, + GENERIC_PARAM_CONTEXT_METHODTABLE = 3 +}; + +//***************************************************************************** +// +// ICodeManager is the abstract class that all CodeManagers +// must inherit from. This will probably need to move into +// cor.h and become a real com interface. +// +//***************************************************************************** + +class ICodeManager +{ + VPTR_BASE_VTABLE_CLASS_AND_CTOR(ICodeManager) + +public: + +/* + Last chance for the runtime support to do fixups in the context + before execution continues inside a filter, catch handler, or fault/finally +*/ + +enum ContextType +{ + FILTER_CONTEXT, + CATCH_CONTEXT, + FINALLY_CONTEXT +}; + +/* Type of funclet corresponding to a shadow stack-pointer */ + +enum +{ + SHADOW_SP_IN_FILTER = 0x1, + SHADOW_SP_FILTER_DONE = 0x2, + SHADOW_SP_BITS = 0x3 +}; + +#ifndef DACCESS_COMPILE +#ifndef WIN64EXCEPTIONS +virtual void FixContext(ContextType ctxType, + EHContext *ctx, + EECodeInfo *pCodeInfo, + DWORD dwRelOffset, + DWORD nestingLevel, + OBJECTREF thrownObject, + CodeManState *pState, + size_t ** ppShadowSP, // OUT + size_t ** ppEndRegion) = 0; // OUT +#endif // !WIN64EXCEPTIONS +#endif // #ifndef DACCESS_COMPILE + +#ifdef _TARGET_X86_ +/* + Gets the ambient stack pointer value at the given nesting level within + the method. +*/ +virtual TADDR GetAmbientSP(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + DWORD dwRelOffset, + DWORD nestingLevel, + CodeManState *pState) = 0; +#endif // _TARGET_X86_ + +/* + Get the number of bytes used for stack parameters. + This is currently only used on x86. +*/ +virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo) = 0; + +#ifndef CROSSGEN_COMPILE +/* + Unwind the current stack frame, i.e. update the virtual register + set in pContext. This will be similar to the state after the function + returns back to caller (IP points to after the call, Frame and Stack + pointer has been reset, callee-saved registers restored + (if UpdateAllRegs), callee-UNsaved registers are trashed) + Returns success of operation. +*/ +virtual bool UnwindStackFrame(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + unsigned flags, + CodeManState *pState, + StackwalkCacheUnwindInfo *pUnwindInfo) = 0; +#endif // CROSSGEN_COMPILE + +/* + Is the function currently at a "GC safe point" ? + Can call EnumGcRefs() successfully +*/ +virtual bool IsGcSafe(EECodeInfo *pCodeInfo, + DWORD dwRelOffset) = 0; + +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +virtual bool HasTailCalls(EECodeInfo *pCodeInfo) = 0; +#endif // _TARGET_ARM_ || _TARGET_ARM64_ + +#if defined(_TARGET_AMD64_) && defined(_DEBUG) +/* + Locates the end of the last interruptible region in the given code range. + Returns 0 if the entire range is uninterruptible. Returns the end point + if the entire range is interruptible. +*/ +virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, + unsigned endOffset, + GCInfoToken gcInfoToken) = 0; +#endif // _TARGET_AMD64_ && _DEBUG + +#ifndef CROSSGEN_COMPILE +/* + Enumerate all live object references in that function using + the virtual register set. Same reference location cannot be enumerated + multiple times (but all differenct references pointing to the same + object have to be individually enumerated). + Returns success of operation. +*/ +virtual bool EnumGcRefs(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + unsigned flags, + GCEnumCallback pCallback, + LPVOID hCallBack, + DWORD relOffsetOverride = NO_OVERRIDE_OFFSET) = 0; +#endif // !CROSSGEN_COMPILE + +#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) +/* + Return the address of the local security object reference + (if available). +*/ +virtual OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) = 0; +#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE + +#ifndef CROSSGEN_COMPILE +/* + For a non-static method, "this" pointer is passed in as argument 0. + However, if there is a "ldarga 0" or "starg 0" in the IL, + JIT will create a copy of arg0 and redirect all "ldarg(a) 0" and "starg 0" to this copy. + (See Compiler::lvaArg0Var for more details.) + + The following method returns the original "this" argument, i.e. the one that is passed in, + if it is a non-static method AND the object is still alive. + Returns NULL in all other cases. +*/ +virtual OBJECTREF GetInstance(PREGDISPLAY pContext, + EECodeInfo* pCodeInfo) = 0; +#endif // !CROSSGEN_COMPILE + +#ifndef CROSSGEN_COMPILE +/* + Returns the extra argument passed to to shared generic code if it is still alive. + Returns NULL in all other cases. +*/ +virtual PTR_VOID GetParamTypeArg(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo) = 0; +#endif // !CROSSGEN_COMPILE + +// Returns the type of the context parameter (this, methodtable, methoddesc, or none) +virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo) = 0; + +#ifndef CROSSGEN_COMPILE +/* + Returns the offset of the GuardStack cookie if it exists. + Returns NULL if there is no cookie. +*/ +virtual void * GetGSCookieAddr(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo, + CodeManState * pState) = 0; +#endif + +#ifndef USE_GC_INFO_DECODER +/* + Returns true if the given IP is in the given method's prolog or an epilog. +*/ +virtual bool IsInPrologOrEpilog(DWORD relPCOffset, + GCInfoToken gcInfoToken, + size_t* prologSize) = 0; + +/* + Returns true if the given IP is in the synchronized region of the method (valid for synchronized methods only) +*/ +virtual bool IsInSynchronizedRegion( + DWORD relOffset, + GCInfoToken gcInfoToken, + unsigned flags) = 0; +#endif // !USE_GC_INFO_DECODER + +/* + Returns the size of a given function as reported in the GC info (does + not take procedure splitting into account). For the actual size of + the hot region call IJitManager::JitTokenToMethodHotSize. +*/ +virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0; + +/* +Returns the ReturnKind of a given function as reported in the GC info. +*/ + +virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken) = 0; + +#ifndef USE_GC_INFO_DECODER +/* + Returns the size of the frame (barring localloc) +*/ +virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken) = 0; +#endif // USE_GC_INFO_DECODER + +#ifndef DACCESS_COMPILE + +/* Debugger API */ + +#ifndef WIN64EXCEPTIONS +virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0; + +virtual BOOL IsInFilter(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx, + DWORD curNestLevel) = 0; + +virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx) = 0; + +virtual void LeaveCatch(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx)=0; +#endif // WIN64EXCEPTIONS + +#ifdef EnC_SUPPORTED + +/* + Last chance for the runtime support to do fixups in the context + before execution continues inside an EnC updated function. +*/ + +virtual HRESULT FixContextForEnC(PCONTEXT pCtx, + EECodeInfo * pOldCodeInfo, + const ICorDebugInfo::NativeVarInfo * oldMethodVars, + SIZE_T oldMethodVarsCount, + EECodeInfo * pNewCodeInfo, + const ICorDebugInfo::NativeVarInfo * newMethodVars, + SIZE_T newMethodVarsCount) = 0; + +#endif // EnC_SUPPORTED + +#endif // #ifndef DACCESS_COMPILE + + +#ifdef DACCESS_COMPILE + virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0; +#endif +}; + +//***************************************************************************** +// +// EECodeManager is the EE's implementation of the ICodeManager which +// supports the default format of GCInfo. +// +//***************************************************************************** + +struct hdrInfo; + +class EECodeManager : public ICodeManager { + + VPTR_VTABLE_CLASS_AND_CTOR(EECodeManager, ICodeManager) + +public: + + +#ifndef DACCESS_COMPILE +#ifndef WIN64EXCEPTIONS +/* + Last chance for the runtime support to do fixups in the context + before execution continues inside a filter, catch handler, or finally +*/ +virtual +void FixContext(ContextType ctxType, + EHContext *ctx, + EECodeInfo *pCodeInfo, + DWORD dwRelOffset, + DWORD nestingLevel, + OBJECTREF thrownObject, + CodeManState *pState, + size_t ** ppShadowSP, // OUT + size_t ** ppEndRegion); // OUT +#endif // !WIN64EXCEPTIONS +#endif // #ifndef DACCESS_COMPILE + +#ifdef _TARGET_X86_ +/* + Gets the ambient stack pointer value at the given nesting level within + the method. +*/ +virtual +TADDR GetAmbientSP(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + DWORD dwRelOffset, + DWORD nestingLevel, + CodeManState *pState); +#endif // _TARGET_X86_ + +/* + Get the number of bytes used for stack parameters. + This is currently only used on x86. +*/ +virtual +ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo); + +#ifndef CROSSGEN_COMPILE +/* + Unwind the current stack frame, i.e. update the virtual register + set in pContext. This will be similar to the state after the function + returns back to caller (IP points to after the call, Frame and Stack + pointer has been reset, callee-saved registers restored + (if UpdateAllRegs), callee-UNsaved registers are trashed) + Returns success of operation. +*/ +virtual +bool UnwindStackFrame( + PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + unsigned flags, + CodeManState *pState, + StackwalkCacheUnwindInfo *pUnwindInfo); +#endif // CROSSGEN_COMPILE + +#ifdef HAS_QUICKUNWIND +enum QuickUnwindFlag +{ + UnwindCurrentStackFrame, + EnsureCallerStackFrameIsValid +}; + +/* + * Light unwind the current stack frame, using provided cache entry. + * only pPC and Esp of pContext are updated. And pEbp if necessary. + */ + +static +void QuickUnwindStackFrame( + PREGDISPLAY pRD, + StackwalkCacheEntry *pCacheEntry, + QuickUnwindFlag flag); +#endif // HAS_QUICKUNWIND + +/* + Is the function currently at a "GC safe point" ? + Can call EnumGcRefs() successfully +*/ +virtual +bool IsGcSafe( EECodeInfo *pCodeInfo, + DWORD dwRelOffset); + +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) +virtual +bool HasTailCalls(EECodeInfo *pCodeInfo); +#endif // _TARGET_ARM_ || _TARGET_ARM64_ + +#if defined(_TARGET_AMD64_) && defined(_DEBUG) +/* + Locates the end of the last interruptible region in the given code range. + Returns 0 if the entire range is uninterruptible. Returns the end point + if the entire range is interruptible. +*/ +virtual +unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, + unsigned endOffset, + GCInfoToken gcInfoToken); +#endif // _TARGET_AMD64_ && _DEBUG + +#ifndef CROSSGEN_COMPILE +/* + Enumerate all live object references in that function using + the virtual register set. Same reference location cannot be enumerated + multiple times (but all differenct references pointing to the same + object have to be individually enumerated). + Returns success of operation. +*/ +virtual +bool EnumGcRefs(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + unsigned flags, + GCEnumCallback pCallback, + LPVOID hCallBack, + DWORD relOffsetOverride = NO_OVERRIDE_OFFSET); +#endif // !CROSSGEN_COMPILE + +#ifdef FEATURE_CONSERVATIVE_GC +// Temporary conservative collection, for testing purposes, until we have +// accurate gc info from the JIT. +bool EnumGcRefsConservative(PREGDISPLAY pRD, + EECodeInfo *pCodeInfo, + unsigned flags, + GCEnumCallback pCallBack, + LPVOID hCallBack); +#endif // FEATURE_CONSERVATIVE_GC + +#ifdef _TARGET_X86_ +/* + Return the address of the local security object reference + using data that was previously cached before in UnwindStackFrame + using StackwalkCacheUnwindInfo +*/ +static OBJECTREF* GetAddrOfSecurityObjectFromCachedInfo( + PREGDISPLAY pRD, + StackwalkCacheUnwindInfo * stackwalkCacheUnwindInfo); +#endif // _TARGET_X86_ + +#if !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE) +virtual +OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) DAC_UNEXPECTED(); +#endif // !DACCESS_COMPILE && !CROSSGEN_COMPILE + +#ifndef CROSSGEN_COMPILE +virtual +OBJECTREF GetInstance( + PREGDISPLAY pContext, + EECodeInfo * pCodeInfo); +#endif // !CROSSGEN_COMPILE + +#ifndef CROSSGEN_COMPILE +/* + Returns the extra argument passed to to shared generic code if it is still alive. + Returns NULL in all other cases. +*/ +virtual +PTR_VOID GetParamTypeArg(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo); +#endif // !CROSSGEN_COMPILE + +// Returns the type of the context parameter (this, methodtable, methoddesc, or none) +virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo); + +#if defined(WIN64EXCEPTIONS) && defined(USE_GC_INFO_DECODER) && !defined(CROSSGEN_COMPILE) +/* + Returns the generics token. This is used by GetInstance() and GetParamTypeArg() on WIN64. +*/ +static +PTR_VOID GetExactGenericsToken(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo); + +static +PTR_VOID GetExactGenericsToken(SIZE_T baseStackSlot, + EECodeInfo * pCodeInfo); + + +#endif // WIN64EXCEPTIONS && USE_GC_INFO_DECODER && !CROSSGEN_COMPILE + +#ifndef CROSSGEN_COMPILE +/* + Returns the offset of the GuardStack cookie if it exists. + Returns NULL if there is no cookie. +*/ +virtual +void * GetGSCookieAddr(PREGDISPLAY pContext, + EECodeInfo * pCodeInfo, + CodeManState * pState); +#endif + + +#ifndef USE_GC_INFO_DECODER +/* + Returns true if the given IP is in the given method's prolog or an epilog. +*/ +virtual +bool IsInPrologOrEpilog( + DWORD relOffset, + GCInfoToken gcInfoToken, + size_t* prologSize); + +/* + Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only) +*/ +virtual +bool IsInSynchronizedRegion( + DWORD relOffset, + GCInfoToken gcInfoToken, + unsigned flags); +#endif // !USE_GC_INFO_DECODER + +/* + Returns the size of a given function. +*/ +virtual +size_t GetFunctionSize(GCInfoToken gcInfoToken); + +/* +Returns the ReturnKind of a given function. +*/ +virtual ReturnKind GetReturnKind(GCInfoToken gcInfotoken); + +#ifndef USE_GC_INFO_DECODER +/* + Returns the size of the frame (barring localloc) +*/ +virtual +unsigned int GetFrameSize(GCInfoToken gcInfoToken); +#endif // USE_GC_INFO_DECODER + +#ifndef DACCESS_COMPILE + +#ifndef WIN64EXCEPTIONS +virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg); +virtual BOOL IsInFilter(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx, + DWORD curNestLevel); +virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx); +virtual void LeaveCatch(GCInfoToken gcInfoToken, + unsigned offset, + PCONTEXT pCtx); +#endif // WIN64EXCEPTIONS + +#ifdef EnC_SUPPORTED +/* + Last chance for the runtime support to do fixups in the context + before execution continues inside an EnC updated function. +*/ +virtual +HRESULT FixContextForEnC(PCONTEXT pCtx, + EECodeInfo * pOldCodeInfo, + const ICorDebugInfo::NativeVarInfo * oldMethodVars, + SIZE_T oldMethodVarsCount, + EECodeInfo * pNewCodeInfo, + const ICorDebugInfo::NativeVarInfo * newMethodVars, + SIZE_T newMethodVarsCount); +#endif // EnC_SUPPORTED + +#endif // #ifndef DACCESS_COMPILE + +#ifdef WIN64EXCEPTIONS + static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL ); + static size_t GetCallerSp( PREGDISPLAY pRD ); +#ifdef _TARGET_X86_ + static size_t GetResumeSp( PCONTEXT pContext ); +#endif // _TARGET_X86_ +#endif // WIN64EXCEPTIONS + +#ifdef DACCESS_COMPILE + virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); +#endif + +}; + +#ifdef _TARGET_X86_ +bool UnwindStackFrame(PREGDISPLAY pContext, + EECodeInfo *pCodeInfo, + unsigned flags, + CodeManState *pState, + StackwalkCacheUnwindInfo *pUnwindInfo); +#endif + +/***************************************************************************** + ToDo: Do we want to include JIT/IL/target.h? + */ + +enum regNum +{ + REGI_EAX, REGI_ECX, REGI_EDX, REGI_EBX, + REGI_ESP, REGI_EBP, REGI_ESI, REGI_EDI, + REGI_COUNT, + REGI_NA = REGI_COUNT +}; + +/***************************************************************************** + Register masks + */ + +enum RegMask +{ + RM_EAX = 0x01, + RM_ECX = 0x02, + RM_EDX = 0x04, + RM_EBX = 0x08, + RM_ESP = 0x10, + RM_EBP = 0x20, + RM_ESI = 0x40, + RM_EDI = 0x80, + + RM_NONE = 0x00, + RM_ALL = (RM_EAX|RM_ECX|RM_EDX|RM_EBX|RM_ESP|RM_EBP|RM_ESI|RM_EDI), + RM_CALLEE_SAVED = (RM_EBP|RM_EBX|RM_ESI|RM_EDI), + RM_CALLEE_TRASHED = (RM_ALL & ~RM_CALLEE_SAVED), +}; + +/***************************************************************************** + * + * Helper to extract basic info from a method info block. + */ + +struct hdrInfo +{ + unsigned int methodSize; // native code bytes + unsigned int argSize; // in bytes + unsigned int stackSize; // including callee saved registers + unsigned int rawStkSize; // excluding callee saved registers + ReturnKind returnKind; // The ReturnKind for this method. + + unsigned int prologSize; + + // Size of the epilogs in the method. + // For methods which use CEE_JMP, some epilogs may end with a "ret" instruction + // and some may end with a "jmp". The epilogSize reported should be for the + // epilog with the smallest size. + unsigned int epilogSize; + + unsigned char epilogCnt; + bool epilogEnd; // is the epilog at the end of the method + + bool ebpFrame; // locals and arguments addressed relative to EBP + bool doubleAlign; // is the stack double-aligned? locals addressed relative to ESP, and arguments relative to EBP + bool interruptible; // intr. at all times (excluding prolog/epilog), not just call sites + + bool securityCheck; // has a slot for security object + bool handlers; // has callable handlers + bool localloc; // uses localloc + bool editNcontinue; // has been compiled in EnC mode + bool varargs; // is this a varargs routine + bool profCallbacks; // does the method have Enter-Leave callbacks + bool genericsContext;// has a reported generic context paramter + bool genericsContextIsMethodDesc;// reported generic context parameter is methoddesc + bool isSpeculativeStackWalk; // is the stackwalk seeded by an untrusted source (e.g., sampling profiler)? + + // These always includes EBP for EBP-frames and double-aligned-frames + RegMask savedRegMask:8; // which callee-saved regs are saved on stack + + // Count of the callee-saved registers, excluding the frame pointer. + // This does not include EBP for EBP-frames and double-aligned-frames. + unsigned int savedRegsCountExclFP; + + unsigned int untrackedCnt; + unsigned int varPtrTableSize; + unsigned int argTabOffset; // INVALID_ARGTAB_OFFSET if argtab must be reached by stepping through ptr tables + unsigned int gsCookieOffset; // INVALID_GS_COOKIE_OFFSET if there is no GuardStack cookie + + unsigned int syncStartOffset; // start/end code offset of the protected region in synchronized methods. + unsigned int syncEndOffset; // INVALID_SYNC_OFFSET if there not synchronized method + unsigned int syncEpilogStart; // The start of the epilog. Synchronized methods are guaranteed to have no more than one epilog. + unsigned int revPInvokeOffset; // INVALID_REV_PINVOKE_OFFSET if there is no Reverse PInvoke frame + + enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 }; + + int prologOffs; // NOT_IN_PROLOG if not in prolog + int epilogOffs; // NOT_IN_EPILOG if not in epilog. It is never 0 + + // + // Results passed back from scanArgRegTable + // + regNum thisPtrResult; // register holding "this" + RegMask regMaskResult; // registers currently holding GC ptrs + RegMask iregMaskResult; // iptr qualifier for regMaskResult + unsigned argHnumResult; + PTR_CBYTE argTabResult; // Table of encoded offsets of pending ptr args + unsigned argTabBytes; // Number of bytes in argTabResult[] + + // These next two are now large structs (i.e 132 bytes each) + + ptrArgTP argMaskResult; // pending arguments mask + ptrArgTP iargMaskResult; // iptr qualifier for argMaskResult +}; + +/***************************************************************************** + How the stackwalkers buffer will be interpreted +*/ + +struct CodeManStateBuf +{ + DWORD hdrInfoSize; + hdrInfo hdrInfoBody; +}; +//***************************************************************************** +#endif // _EETWAIN_H +//***************************************************************************** diff --git a/lib/coreclr/src/inc/eexcp.h b/lib/coreclr/src/inc/eexcp.h new file mode 100644 index 0000000000..b91522b4d8 --- /dev/null +++ b/lib/coreclr/src/inc/eexcp.h @@ -0,0 +1,156 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ==++== +// + +// +// + +// +// ==--== + + +#ifndef __eexcp_h__ +#define __eexcp_h__ + +#include "corhlpr.h" +#include "daccess.h" + +struct EE_ILEXCEPTION_CLAUSE; +typedef DPTR(EE_ILEXCEPTION_CLAUSE) PTR_EE_ILEXCEPTION_CLAUSE; + +// The exception handling sub-system needs to keep track of EH clause that is handling given exception. +// PTR_EXCEPTION_CLAUSE_TOKEN is opaque pointer that uniquely identifies +// exception handling clause. It abstracts away encoding differences of EH clauses between JIT and NGen. +typedef PTR_VOID PTR_EXCEPTION_CLAUSE_TOKEN; + +struct EE_ILEXCEPTION_CLAUSE { + //Flags is not marked as volatile since it is always accessed + // from within a critical section + CorExceptionFlag Flags; + DWORD TryStartPC; + DWORD TryEndPC; + DWORD HandlerStartPC; + DWORD HandlerEndPC; + union { + void* TypeHandle; + mdToken ClassToken; + DWORD FilterOffset; + }; +}; + +struct EE_ILEXCEPTION; +typedef DPTR(EE_ILEXCEPTION) PTR_EE_ILEXCEPTION; + +struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT +{ + EE_ILEXCEPTION_CLAUSE Clauses[1]; // actually variable size + + void Init(unsigned ehCount) + { + LIMITED_METHOD_CONTRACT; + + SetKind(CorILMethod_Sect_FatFormat); + SetDataSize((unsigned)sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); + } + + unsigned EHCount() const + { + LIMITED_METHOD_CONTRACT; + + return GetDataSize() / (DWORD) sizeof(EE_ILEXCEPTION_CLAUSE); + } + + static unsigned Size(unsigned ehCount) + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(ehCount > 0); + + return (offsetof(EE_ILEXCEPTION, Clauses) + sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); + } + EE_ILEXCEPTION_CLAUSE *EHClause(unsigned i) + { + LIMITED_METHOD_DAC_CONTRACT; + return &(PTR_EE_ILEXCEPTION_CLAUSE(PTR_HOST_MEMBER_TADDR(EE_ILEXCEPTION,this,Clauses))[i]); + } +}; + +#define COR_ILEXCEPTION_CLAUSE_CACHED_CLASS 0x10000000 + +inline BOOL HasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + _ASSERTE(sizeof(EHClause->Flags) == sizeof(DWORD)); + return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); +} + +inline void SetHasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + _ASSERTE(! HasCachedTypeHandle(EHClause)); + EHClause->Flags = (CorExceptionFlag)(EHClause->Flags | COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); +} + +inline BOOL IsFinally(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + LIMITED_METHOD_CONTRACT; + + return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FINALLY); +} + +inline BOOL IsFault(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + LIMITED_METHOD_CONTRACT; + + return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FAULT); +} + +inline BOOL IsFaultOrFinally(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + return IsFault(EHClause) || IsFinally(EHClause); +} + +inline BOOL IsFilterHandler(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + LIMITED_METHOD_CONTRACT; + + return EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER; +} + +inline BOOL IsTypedHandler(EE_ILEXCEPTION_CLAUSE *EHClause) +{ + return ! (IsFilterHandler(EHClause) || IsFaultOrFinally(EHClause)); +} + +inline BOOL IsDuplicateClause(EE_ILEXCEPTION_CLAUSE* pEHClause) +{ + return pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED; +} + +#if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) +// Finally is the only EH construct that can be part of the execution as being fall-through. +// +// "Cloned" finally is a contruct that represents a finally block that is used as +// fall through for normal try-block execution. Such a "cloned" finally will: +// +// 1) Have its try-clause's Start and End PC the same as its handler's start PC (i.e. will have +// zero length try block), AND +// 2) Is marked duplicate +// +// Because of their fall-through nature, JIT guarantees that only finally constructs can be cloned, +// and not catch or fault (since they cannot be fallen through but are invoked as funclets). +// +// The cloned finally construct is also used to mark "call to finally" thunks that are not within +// the EH region protected by the finally, and also not within the enclosing region. This is done +// to prevent ThreadAbortException from creating an infinite loop of calling the same finally. +inline BOOL IsClonedFinally(EE_ILEXCEPTION_CLAUSE* pEHClause) +{ + return ((pEHClause->TryStartPC == pEHClause->TryEndPC) && + (pEHClause->TryStartPC == pEHClause->HandlerStartPC) && + IsFinally(pEHClause) && IsDuplicateClause(pEHClause)); +} +#endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + +#endif // __eexcp_h__ + diff --git a/lib/coreclr/src/inc/entrypoints.h b/lib/coreclr/src/inc/entrypoints.h new file mode 100644 index 0000000000..c552b664c3 --- /dev/null +++ b/lib/coreclr/src/inc/entrypoints.h @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- +// Entrypoint markers +// Used to identify all external entrypoints into the CLR (via COM, exports, etc) +// and perform various tasks on all of them +//----------------------------------------------------------------------------- + + +#ifndef __ENTRYPOINTS_h__ +#define __ENTRYPOINTS_h__ + +#define BEGIN_ENTRYPOINT_THROWS +#define END_ENTRYPOINT_THROWS +#define BEGIN_ENTRYPOINT_THROWS_WITH_THREAD(____thread) +#define END_ENTRYPOINT_THROWS_WITH_THREAD +#define BEGIN_ENTRYPOINT_NOTHROW_WITH_THREAD(___thread) +#define END_ENTRYPOINT_NOTHROW_WITH_THREAD +#define BEGIN_ENTRYPOINT_NOTHROW +#define END_ENTRYPOINT_NOTHROW +#define BEGIN_ENTRYPOINT_VOIDRET +#define END_ENTRYPOINT_VOIDRET +#define BEGIN_CLEANUP_ENTRYPOINT +#define END_CLEANUP_ENTRYPOINT + +#endif // __ENTRYPOINTS_h__ + + diff --git a/lib/coreclr/src/inc/eventtrace.h b/lib/coreclr/src/inc/eventtrace.h new file mode 100644 index 0000000000..1564c944b8 --- /dev/null +++ b/lib/coreclr/src/inc/eventtrace.h @@ -0,0 +1,361 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: eventtrace.h +// Abstract: This module implements Event Tracing support. This includes +// eventtracebase.h, and adds VM-specific ETW helpers to support features like type +// logging, allocation logging, and gc heap walk logging. +// + +// + +// +// +// #EventTracing +// Windows +// ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable +// tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are +// four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. +// An event provider is a logical entity that writes events to ETW sessions. The event provider must register +// a provider ID with ETW through the registration API. A provider first registers with ETW and writes events +// from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by +// the ETW controller application, calls to the logging API sends events to a specific trace session +// designated by the controller. Each event sent by the event provider to the trace session consists of a +// fixed header that includes event metadata and additional variable user-context data. CLR is an event +// provider. + +// Mac +// DTrace is similar to ETW and has been made to look like ETW at most of the places. +// For convenience, it is called ETM (Event Tracing for Mac) and exists only on the Mac Leopard OS +// ============================================================================ + +#ifndef _VMEVENTTRACE_H_ +#define _VMEVENTTRACE_H_ + +#include "eventtracebase.h" +#include "gcinterface.h" + +#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) +struct ProfilingScanContext : ScanContext +{ + BOOL fProfilerPinned; + void * pvEtwContext; + void *pHeapId; + + ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() + { + LIMITED_METHOD_CONTRACT; + + pHeapId = NULL; + fProfilerPinned = fProfilerPinnedParam; + pvEtwContext = NULL; +#ifdef FEATURE_CONSERVATIVE_GC + // To not confuse GCScan::GcScanRoots + promotion = g_pConfig->GetGCConservative(); +#endif + } +}; +#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) + +#ifndef FEATURE_REDHAWK + +namespace ETW +{ + class LoggedTypesFromModule; + + // We keep a hash of these to keep track of: + // * Which types have been logged through ETW (so we can avoid logging dupe Type + // events), and + // * GCSampledObjectAllocation stats to help with "smart sampling" which + // dynamically adjusts sampling rate of objects by type. + // See code:LoggedTypesFromModuleTraits + struct TypeLoggingInfo + { + public: + TypeLoggingInfo(TypeHandle thParam) + { + Init(thParam); + } + + TypeLoggingInfo() + { + Init(TypeHandle()); + } + + void Init(TypeHandle thParam) + { + th = thParam; + dwTickOfCurrentTimeBucket = 0; + dwAllocCountInCurrentBucket = 0; + flAllocPerMSec = 0; + + dwAllocsToSkipPerSample = 0; + dwAllocsSkippedForSample = 0; + cbIgnoredSizeForSample = 0; + }; + + // The type this TypeLoggingInfo represents + TypeHandle th; + + // Smart sampling + + // These bucket values remember stats of a particular time slice that are used to + // help adjust the sampling rate + DWORD dwTickOfCurrentTimeBucket; + DWORD dwAllocCountInCurrentBucket; + float flAllocPerMSec; + + // The number of data points to ignore before taking a "sample" (i.e., logging a + // GCSampledObjectAllocation ETW event for this type) + DWORD dwAllocsToSkipPerSample; + + // The current number of data points actually ignored for the current sample + DWORD dwAllocsSkippedForSample; + + // The current count of bytes of objects of this type actually allocated (and + // ignored) for the current sample + SIZE_T cbIgnoredSizeForSample; + }; + + // Class to wrap all type system logic for ETW + class TypeSystemLog + { + private: + // Global type hash + static AllLoggedTypes *s_pAllLoggedTypes; + + // An unsigned value that gets incremented whenever a global change is made. + // When this occurs, threads must synchronize themselves with the global state. + // Examples include unloading of modules and disabling of allocation sampling. + static unsigned int s_nEpoch; + + // See code:ETW::TypeSystemLog::PostRegistrationInit + static BOOL s_fHeapAllocEventEnabledOnStartup; + static BOOL s_fHeapAllocHighEventEnabledNow; + static BOOL s_fHeapAllocLowEventEnabledNow; + + // If COMPLUS_UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec is set, then + // this is used to determine the event frequency, overriding + // s_nDefaultMsBetweenEvents above (regardless of which + // GCSampledObjectAllocation*Keyword was used) + static int s_nCustomMsBetweenEvents; + + public: + // This customizes the type logging behavior in LogTypeAndParametersIfNecessary + enum TypeLogBehavior + { + // Take lock, and consult hash table to see if this is the first time we've + // encountered the type, in which case, log it + kTypeLogBehaviorTakeLockAndLogIfFirstTime, + + // Don't take lock, don't consult hash table. Just log the type. (This is + // used in cases when checking for dupe type logging isn't worth it, such as + // when logging the finalization of an object.) + kTypeLogBehaviorAlwaysLog, + + // When logging the type for GCSampledObjectAllocation events, + // we already know we need to log the type (since we already + // looked it up in the hash). But we would still need to consult the hash + // for any type parameters, so kTypeLogBehaviorAlwaysLog isn't appropriate, + // and this is used instead. + kTypeLogBehaviorAlwaysLogTopLevelType, + }; + + static HRESULT PreRegistrationInit(); + static void PostRegistrationInit(); + static BOOL IsHeapAllocEventEnabled(); + static void SendObjectAllocatedEvent(Object * pObject); + static CrstBase * GetHashCrst(); + static VOID LogTypeAndParametersIfNecessary(BulkTypeEventLogger * pBulkTypeEventLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior); + static VOID OnModuleUnload(Module * pModule); + static void OnKeywordsChanged(); + static void Cleanup(); + static VOID DeleteTypeHashNoLock(AllLoggedTypes **ppAllLoggedTypes); + static VOID FlushObjectAllocationEvents(); + + private: + static BOOL ShouldLogType(TypeHandle th); + static TypeLoggingInfo LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL * pfCreatedNew, LoggedTypesFromModule ** ppLoggedTypesFromModule = NULL); + static BOOL AddTypeToGlobalCacheIfNotExists(TypeHandle th, BOOL * pfCreatedNew); + static BOOL AddOrReplaceTypeLoggingInfo(ETW::LoggedTypesFromModule * pLoggedTypesFromModule, const ETW::TypeLoggingInfo * pTypeLoggingInfo); + static int GetDefaultMsBetweenEvents(); + static VOID OnTypesKeywordTurnedOff(); + }; + +#endif // FEATURE_REDHAWK + + + // Class to wrap all GC logic for ETW + class GCLog + { + private: + // When WPA triggers a GC, it gives us this unique number to append to our + // GCStart event so WPA can correlate the CLR's GC with the JScript GC they + // triggered at the same time. + // + // We set this value when the GC is triggered, and then retrieve the value on the + // first subsequent FireGcStart() method call for a full, induced GC, assuming + // that that's the GC that WPA triggered. This is imperfect, and if we were in + // the act of beginning another full, induced GC (for some other reason), then + // we'll attach this sequence number to that GC instead of to the WPA-induced GC, + // but who cares? When parsing ETW logs later on, it's indistinguishable if both + // GCs really were induced at around the same time. +#ifdef FEATURE_REDHAWK + static volatile LONGLONG s_l64LastClientSequenceNumber; +#else // FEATURE_REDHAWK + static Volatile s_l64LastClientSequenceNumber; +#endif // FEATURE_REDHAWK + + public: + typedef union st_GCEventInfo { + typedef struct _GenerationInfo { + ULONGLONG GenerationSize; + ULONGLONG TotalPromotedSize; + } GenerationInfo; + + struct { + GenerationInfo GenInfo[4]; // the heap info on gen0, gen1, gen2 and the large object heap. + ULONGLONG FinalizationPromotedSize; //not available per generation + ULONGLONG FinalizationPromotedCount; //not available per generation + ULONG PinnedObjectCount; + ULONG SinkBlockCount; + ULONG GCHandleCount; + } HeapStats; + + typedef enum _HeapType { + SMALL_OBJECT_HEAP, LARGE_OBJECT_HEAP, READ_ONLY_HEAP + } HeapType; + struct { + ULONGLONG Address; + ULONGLONG Size; + HeapType Type; + } GCCreateSegment; + + struct { + ULONGLONG Address; + } GCFreeSegment; + struct { + ULONG Count; + ULONG Depth; + } GCEnd; + + typedef enum _AllocationKind { + AllocationSmall = 0, + AllocationLarge + }AllocationKind; + struct { + ULONG Allocation; + AllocationKind Kind; + } AllocationTick; + + // These values are gotten from the gc_reason + // in gcimpl.h + typedef enum _GC_REASON { + GC_ALLOC_SOH = 0, + GC_INDUCED = 1, + GC_LOWMEMORY = 2, + GC_EMPTY = 3, + GC_ALLOC_LOH = 4, + GC_OOS_SOH = 5, + GC_OOS_LOH = 6, + GC_INDUCED_NOFORCE = 7, + GC_GCSTRESS = 8, + GC_LOWMEMORY_BLOCKING = 9, + GC_INDUCED_COMPACTING = 10, + GC_LOWMEMORY_HOST = 11 + } GC_REASON; + typedef enum _GC_TYPE { + GC_NGC = 0, + GC_BGC = 1, + GC_FGC = 2 + } GC_TYPE; + typedef enum _GC_ROOT_KIND { + GC_ROOT_STACK = 0, + GC_ROOT_FQ = 1, + GC_ROOT_HANDLES = 2, + GC_ROOT_OLDER = 3, + GC_ROOT_SIZEDREF = 4, + GC_ROOT_OVERFLOW = 5 + } GC_ROOT_KIND; + struct { + ULONG Count; + ULONG Depth; + GC_REASON Reason; + GC_TYPE Type; + } GCStart; + + struct { + ULONG Count; // how many finalizers we called. + } GCFinalizers; + + struct { + ULONG Reason; + // This is only valid when SuspendEE is called by GC (ie, Reason is either + // SUSPEND_FOR_GC or SUSPEND_FOR_GC_PREP. + ULONG GcCount; + } SuspendEE; + + struct { + ULONG HeapNum; + } GCMark; + + struct { + ULONGLONG SegmentSize; + ULONGLONG LargeObjectSegmentSize; + BOOL ServerGC; // TRUE means it's server GC; FALSE means it's workstation. + } GCSettings; + + struct { + // The generation that triggered this notification. + ULONG Count; + // 1 means the notification was due to allocation; 0 means it was due to other factors. + ULONG Alloc; + } GCFullNotify; + } ETW_GC_INFO, *PETW_GC_INFO; + +#ifdef FEATURE_EVENT_TRACE + static VOID GCSettingsEvent(); +#else + static VOID GCSettingsEvent() {}; +#endif // FEATURE_EVENT_TRACE + + static BOOL ShouldWalkHeapObjectsForEtw(); + static BOOL ShouldWalkHeapRootsForEtw(); + static BOOL ShouldTrackMovementForEtw(); + static HRESULT ForceGCForDiagnostics(); + static VOID ForceGC(LONGLONG l64ClientSequenceNumber); + static VOID FireGcStart(ETW_GC_INFO * pGcInfo); + static VOID RootReference( + LPVOID pvHandle, + Object * pRootedNode, + Object * pSecondaryNodeForDependentHandle, + BOOL fDependentHandle, + ProfilingScanContext * profilingScanContext, + DWORD dwGCFlags, + DWORD rootFlags); + static VOID ObjectReference( + ProfilerWalkHeapContext * profilerWalkHeapContext, + Object * pObjReferenceSource, + ULONGLONG typeID, + ULONGLONG cRefs, + Object ** rgObjReferenceTargets); + static BOOL ShouldWalkStaticsAndCOMForEtw(); + static VOID WalkStaticsAndCOMForETW(); + static VOID EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext); +#ifdef FEATURE_EVENT_TRACE + static VOID BeginMovedReferences(size_t * pProfilingContext); + static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE); + static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE); +#else + // TODO: Need to be implemented for PROFILING_SUPPORTED. + static VOID BeginMovedReferences(size_t * pProfilingContext) {}; + static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE) {}; + static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE) {}; +#endif // FEATURE_EVENT_TRACE + static VOID SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj); + }; +}; + + +#endif //_VMEVENTTRACE_H_ diff --git a/lib/coreclr/src/inc/eventtracebase.h b/lib/coreclr/src/inc/eventtracebase.h new file mode 100644 index 0000000000..43147f5a6f --- /dev/null +++ b/lib/coreclr/src/inc/eventtracebase.h @@ -0,0 +1,1473 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// File: eventtracebase.h +// Abstract: This module implements base Event Tracing support (excluding some of the +// CLR VM-specific ETW helpers). +// + +// + +// +// +// #EventTracing +// Windows +// ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable +// tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are +// four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. +// An event provider is a logical entity that writes events to ETW sessions. The event provider must register +// a provider ID with ETW through the registration API. A provider first registers with ETW and writes events +// from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by +// the ETW controller application, calls to the logging API sends events to a specific trace session +// designated by the controller. Each event sent by the event provider to the trace session consists of a +// fixed header that includes event metadata and additional variable user-context data. CLR is an event +// provider. +// ============================================================================ + +#ifndef _ETWTRACER_HXX_ +#define _ETWTRACER_HXX_ + +struct EventStructTypeData; +void InitializeEventTracing(); + +class PrepareCodeConfig; + +// !!!!!!! NOTE !!!!!!!! +// The flags must match those in the ETW manifest exactly +// !!!!!!! NOTE !!!!!!!! + +// These flags need to be defined either when FEATURE_EVENT_TRACE is enabled or the +// PROFILING_SUPPORTED is set, since they are used both by event tracing and profiling. + +enum EtwTypeFlags +{ + kEtwTypeFlagsDelegate = 0x1, + kEtwTypeFlagsFinalizable = 0x2, + kEtwTypeFlagsExternallyImplementedCOMObject = 0x4, + kEtwTypeFlagsArray = 0x8, +}; + +enum EtwThreadFlags +{ + kEtwThreadFlagGCSpecial = 0x00000001, + kEtwThreadFlagFinalizer = 0x00000002, + kEtwThreadFlagThreadPoolWorker = 0x00000004, +}; + +#ifndef FEATURE_REDHAWK + +#if defined(FEATURE_EVENT_TRACE) + +#if defined(FEATURE_PERFTRACING) +#define EVENT_PIPE_ENABLED() (EventPipeHelper::Enabled()) +#else +#define EVENT_PIPE_ENABLED() (FALSE) +#endif + +#if !defined(FEATURE_PAL) + +// +// Use this macro at the least before calling the Event Macros +// + +#define ETW_TRACING_INITIALIZED(RegHandle) \ + ((g_pEtwTracer && RegHandle) || EVENT_PIPE_ENABLED()) + +// +// Use this macro to check if an event is enabled +// if the fields in the event are not cheap to calculate +// +#define ETW_EVENT_ENABLED(Context, EventDescriptor) \ + ((Context.EtwProvider->IsEnabled && McGenEventXplatEnabled(Context.EtwProvider, &EventDescriptor)) || EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword)) + +// +// Use this macro to check if a category of events is enabled +// + +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) \ + ((Context.EtwProvider->IsEnabled && McGenEventProviderEnabled(Context.EtwProvider, Level, Keyword)) || EventPipeHelper::IsEnabled(Context, Level, Keyword)) + + +// This macro only checks if a provider is enabled +// It does not check the flags and keywords for which it is enabled +#define ETW_PROVIDER_ENABLED(ProviderSymbol) \ + ((ProviderSymbol##_Context.IsEnabled) || EVENT_PIPE_ENABLED()) + + +#else //!defined(FEATURE_PAL) +#if defined(FEATURE_PERFTRACING) +#define ETW_INLINE +#define ETWOnStartup(StartEventName, EndEventName) +#define ETWFireEvent(EventName) + +#define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword) || \ + (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword))) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ + (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ + (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) +#else //defined(FEATURE_PERFTRACING) +#define ETW_INLINE +#define ETWOnStartup(StartEventName, EndEventName) +#define ETWFireEvent(EventName) + +#define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword)) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.KeywordsBitmask)) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (ETW_EVENT_ENABLED(Context, EventDescriptor) && EventEnabled##EventDescriptor()) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (ETW_CATEGORY_ENABLED(Context, Level, Keyword)) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (XplatEventLogger::IsProviderEnabled(Context)) +#endif // defined(FEATURE_PERFTRACING) +#endif // !defined(FEATURE_PAL) + +#else // FEATURE_EVENT_TRACE + +#define ETWOnStartup(StartEventName, EndEventName) +#define ETWFireEvent(EventName) + +#define ETW_TRACING_INITIALIZED(RegHandle) (FALSE) +#define ETW_EVENT_ENABLED(Context, EventDescriptor) (FALSE) +#define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) +#define ETW_TRACING_ENABLED(Context, EventDescriptor) (FALSE) +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) +#define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) + +#endif // FEATURE_EVENT_TRACE + +#endif // FEATURE_REDHAWK + +// During a heap walk, this is the storage for keeping track of all the nodes and edges +// being batched up by ETW, and for remembering whether we're also supposed to call into +// a profapi profiler. This is allocated toward the end of a GC and passed to us by the +// GC heap walker. +struct ProfilerWalkHeapContext +{ +public: + ProfilerWalkHeapContext(BOOL fProfilerPinnedParam, LPVOID pvEtwContextParam) + { + fProfilerPinned = fProfilerPinnedParam; + pvEtwContext = pvEtwContextParam; + } + + BOOL fProfilerPinned; + LPVOID pvEtwContext; +}; + +#ifdef FEATURE_EVENT_TRACE + +class Object; +#if !defined(FEATURE_PAL) + +/***************************************/ +/* Tracing levels supported by CLR ETW */ +/***************************************/ +#define ETWMAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported +#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination +#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging +#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure +#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit +#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps + +struct ProfilingScanContext; + +// +// Use this macro to check if ETW is initialized and the event is enabled +// +#define ETW_TRACING_ENABLED(Context, EventDescriptor) \ + ((Context.EtwProvider->IsEnabled && ETW_TRACING_INITIALIZED(Context.EtwProvider->RegistrationHandle) && ETW_EVENT_ENABLED(Context, EventDescriptor))|| \ + EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword)) + +// +// Using KEYWORDZERO means when checking the events category ignore the keyword +// +#define KEYWORDZERO 0x0 + +// +// Use this macro to check if ETW is initialized and the category is enabled +// +#define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) \ + (ETW_TRACING_INITIALIZED(Context.EtwProvider->RegistrationHandle) && ETW_CATEGORY_ENABLED(Context, Level, Keyword)) + +#define ETWOnStartup(StartEventName, EndEventName) \ + ETWTraceStartup trace##StartEventName##(Microsoft_Windows_DotNETRuntimePrivateHandle, &StartEventName, &StartupId, &EndEventName, &StartupId); +#define ETWFireEvent(EventName) \ + ETWTraceStartup::StartupTraceEvent(Microsoft_Windows_DotNETRuntimePrivateHandle, &EventName, &StartupId); + +#ifndef FEATURE_REDHAWK +// Headers +#include +#include +#include +#include +#endif //!FEATURE_REDHAWK +#endif //!defined(FEATURE_PAL) + + +#else // FEATURE_EVENT_TRACE + +#include "etmdummy.h" +#endif // FEATURE_EVENT_TRACE + +#ifndef FEATURE_REDHAWK + +#include "corprof.h" + +// g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. +// This enables both the VM and Utilcode to raise ETW events. +extern UINT32 g_nClrInstanceId; + +#define GetClrInstanceId() (static_cast(g_nClrInstanceId)) +#if defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) +#define KEYWORDZERO 0x0 + +/***************************************/ +/* Tracing levels supported by CLR ETW */ +/***************************************/ +#define MAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported +#define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination +#define TRACE_LEVEL_ERROR 2 // Severe errors that need logging +#define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure +#define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit +#define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps + +#define DEF_LTTNG_KEYWORD_ENABLED 1 +#include "clrproviders.h" +#include "clrconfig.h" + +class XplatEventLoggerConfiguration +{ +public: + XplatEventLoggerConfiguration() = default; + + XplatEventLoggerConfiguration(XplatEventLoggerConfiguration const & other) = delete; + XplatEventLoggerConfiguration(XplatEventLoggerConfiguration && other) + { + _provider = std::move(other._provider); + _isValid = other._isValid; + _enabledKeywords = other._enabledKeywords; + _level = other._level; + } + + ~XplatEventLoggerConfiguration() + { + _provider = nullptr; + } + + void Parse(LPWSTR configString) + { + auto providerComponent = GetNextComponentString(configString); + _provider = ParseProviderName(providerComponent); + if (_provider == nullptr) + { + _isValid = false; + return; + } + + auto keywordsComponent = GetNextComponentString(providerComponent.End + 1); + _enabledKeywords = ParseEnabledKeywordsMask(keywordsComponent); + + auto levelComponent = GetNextComponentString(keywordsComponent.End + 1); + _level = ParseEnabledKeywordsMask(levelComponent); + _isValid = true; + } + + bool IsValid() const + { + return _isValid; + } + + LPCWSTR GetProviderName() const + { + return _provider; + } + + ULONGLONG GetEnabledKeywordsMask() const + { + return _enabledKeywords; + } + + UINT GetLevel() const + { + return _level; + } + +private: + struct ComponentSpan + { + public: + ComponentSpan(LPCWSTR start, LPCWSTR end) + : Start(start), End(end) + { + } + + LPCWSTR Start; + LPCWSTR End; + }; + + ComponentSpan GetNextComponentString(LPCWSTR start) const + { + static WCHAR ComponentDelimiter = W(':'); + + auto end = wcschr(start, ComponentDelimiter); + if (end == nullptr) + { + end = start + wcslen(start); + } + + return ComponentSpan(start, end); + } + + LPCWSTR ParseProviderName(ComponentSpan const & component) const + { + auto providerName = (WCHAR*)nullptr; + if ((component.End - component.Start) != 0) + { + auto const length = component.End - component.Start; + providerName = new WCHAR[length + 1]; + memset(providerName, '\0', (length + 1) * sizeof(WCHAR)); + wcsncpy(providerName, component.Start, length); + } + return providerName; + } + + ULONGLONG ParseEnabledKeywordsMask(ComponentSpan const & component) const + { + auto enabledKeywordsMask = (ULONGLONG)(-1); + if ((component.End - component.Start) != 0) + { + enabledKeywordsMask = _wcstoui64(component.Start, nullptr, 16); + } + return enabledKeywordsMask; + } + + UINT ParseLevel(ComponentSpan const & component) const + { + auto level = TRACE_LEVEL_VERBOSE; + if ((component.End - component.Start) != 0) + { + level = _wtoi(component.Start); + } + return level; + } + + LPCWSTR _provider; + ULONGLONG _enabledKeywords; + UINT _level; + bool _isValid; +}; + +class XplatEventLoggerController +{ +public: + + static void UpdateProviderContext(XplatEventLoggerConfiguration const &config) + { + if (!config.IsValid()) + { + return; + } + + auto providerName = config.GetProviderName(); + auto enabledKeywordsMask = config.GetEnabledKeywordsMask(); + auto level = config.GetLevel(); + if (_wcsicmp(providerName, W("*")) == 0 && enabledKeywordsMask == (ULONGLONG)(-1) && level == TRACE_LEVEL_VERBOSE) + { + ActivateAllKeywordsOfAllProviders(); + } + else + { + auto provider = GetProvider(providerName); + if (provider == nullptr) + { + return; + } + provider->EnabledKeywordsBitmask = enabledKeywordsMask; + provider->Level = level; + provider->IsEnabled = true; + } + } + + static void ActivateAllKeywordsOfAllProviders() + { + for (LTTNG_TRACE_CONTEXT * const provider : ALL_LTTNG_PROVIDERS_CONTEXT) + { + provider->EnabledKeywordsBitmask = (ULONGLONG)(-1); + provider->Level = TRACE_LEVEL_VERBOSE; + provider->IsEnabled = true; + } + } + +private: + + static LTTNG_TRACE_CONTEXT * const GetProvider(LPCWSTR providerName) + { + auto length = wcslen(providerName); + for (auto provider : ALL_LTTNG_PROVIDERS_CONTEXT) + { + if (_wcsicmp(provider->Name, providerName) == 0) + { + return provider; + } + } + return nullptr; + } +}; + +class XplatEventLogger +{ +public: + + inline static BOOL IsEventLoggingEnabled() + { + static ConfigDWORD configEventLogging; + return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); + } + + inline static bool IsProviderEnabled(DOTNET_TRACE_CONTEXT providerCtx) + { + return providerCtx.LttngProvider->IsEnabled; + } + + inline static bool IsKeywordEnabled(DOTNET_TRACE_CONTEXT providerCtx, UCHAR level, ULONGLONG keyword) + { + if (!providerCtx.LttngProvider->IsEnabled) + { + return false; + } + + if ((level <= providerCtx.LttngProvider->Level) || (providerCtx.LttngProvider->Level == 0)) + { + if ((keyword == 0) || ((keyword & providerCtx.LttngProvider->EnabledKeywordsBitmask) != 0)) + { + return true; + } + } + return false; + } + + + /* + This method is where COMPlus_LTTngConfig environment variable is parsed and is registered with the runtime provider + context structs generated by src/scripts/genEventing.py. + It expects the environment variable to look like: + provider:keywords:level,provider:keywords:level + (Notice the "arguments" part is missing compared to EventPipe configuration) + + Ex) + Microsoft-Windows-DotNETRuntime:deadbeefdeadbeef:4,Microsoft-Windows-DotNETRuntimePrivate:deafbeefdeadbeef:5 + */ + static void InitializeLogger() + { + if (!IsEventLoggingEnabled()) + { + return; + } + + LPWSTR xplatEventConfig = NULL; + CLRConfig::GetConfigValue(CLRConfig::INTERNAL_LTTngConfig, &xplatEventConfig); + auto configuration = XplatEventLoggerConfiguration(); + auto configToParse = xplatEventConfig; + + if (configToParse == nullptr || *configToParse == L'\0') + { + XplatEventLoggerController::ActivateAllKeywordsOfAllProviders(); + return; + } + while (configToParse != nullptr) + { + static WCHAR comma = W(','); + auto end = wcschr(configToParse, comma); + configuration.Parse(configToParse); + XplatEventLoggerController::UpdateProviderContext(configuration); + if (end == nullptr) + { + break; + } + configToParse = end + 1; + } + } +}; + + +#endif // defined(FEATURE_PAL) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) + +#if defined(FEATURE_EVENT_TRACE) + +struct EventFilterDescriptor; + +VOID EventPipeEtwCallbackDotNETRuntimeStress( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ EventFilterDescriptor* FilterData, + _Inout_opt_ PVOID CallbackContext); + +VOID EventPipeEtwCallbackDotNETRuntime( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ EventFilterDescriptor* FilterData, + _Inout_opt_ PVOID CallbackContext); + +VOID EventPipeEtwCallbackDotNETRuntimeRundown( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ EventFilterDescriptor* FilterData, + _Inout_opt_ PVOID CallbackContext); + +VOID EventPipeEtwCallbackDotNETRuntimePrivate( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ EventFilterDescriptor* FilterData, + _Inout_opt_ PVOID CallbackContext); + +#ifndef FEATURE_PAL +// Callback and stack support +#if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) +extern "C" { + /* ETW control callback + * Desc: This function handles the ETW control + * callback. + * Ret: success or failure + ***********************************************/ + VOID EtwCallback( + _In_ LPCGUID SourceId, + _In_ ULONG ControlCode, + _In_ UCHAR Level, + _In_ ULONGLONG MatchAnyKeyword, + _In_ ULONGLONG MatchAllKeyword, + _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, + _Inout_opt_ PVOID CallbackContext); +} + +// +// User defined callback +// +#define MCGEN_PRIVATE_ENABLE_CALLBACK(RequestCode, Context, InOutBufferSize, Buffer) \ + EtwCallback(NULL /* SourceId */, (RequestCode==WMI_ENABLE_EVENTS) ? EVENT_CONTROL_CODE_ENABLE_PROVIDER : EVENT_CONTROL_CODE_DISABLE_PROVIDER, 0 /* Level */, 0 /* MatchAnyKeyword */, 0 /* MatchAllKeyword */, NULL /* FilterData */, Context) + +// +// User defined callback2 +// +#define MCGEN_PRIVATE_ENABLE_CALLBACK_V2(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) \ + EtwCallback(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) + +extern "C" { + /* ETW callout + * Desc: This function handles the ETW callout + * Ret: success or failure + ***********************************************/ + VOID EtwCallout( + REGHANDLE RegHandle, + PCEVENT_DESCRIPTOR Descriptor, + ULONG ArgumentCount, + PEVENT_DATA_DESCRIPTOR EventData); +} + +// +// Call user defined callout +// +#define MCGEN_CALLOUT(RegHandle, Descriptor, NumberOfArguments, EventData) \ + EtwCallout(RegHandle, Descriptor, NumberOfArguments, EventData) +#endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE + +#endif //!FEATURE_PAL +#include "clretwallmain.h" + +#if defined(FEATURE_PERFTRACING) +class EventPipeHelper +{ +public: + static bool Enabled(); + static bool IsEnabled(DOTNET_TRACE_CONTEXT Context, UCHAR Level, ULONGLONG Keyword); +}; +#endif // defined(FEATURE_PERFTRACING) + +#endif // FEATURE_EVENT_TRACE + +/**************************/ +/* CLR ETW infrastructure */ +/**************************/ +// #CEtwTracer +// On Windows Vista, ETW has gone through a major upgrade, and one of the most significant changes is the +// introduction of the unified event provider model and APIs. The older architecture used the classic ETW +// events. The new ETW architecture uses the manifest based events. To support both types of events at the +// same time, we use the manpp tool for generating event macros that can be directly used to fire ETW events +// from various components within the CLR. +// (http://diagnostics/sites/etw/Lists/Announcements/DispForm.aspx?ID=10&Source=http%3A%2F%2Fdiagnostics%2Fsites%2Fetw%2Fdefault%2Easpx) +// Every ETW provider has to Register itself to the system, so that when enabled, it is capable of firing +// ETW events. file:../VM/eventtrace.cpp#Registration is where the actual Provider Registration takes place. +// At process shutdown, a registered provider need to be unregistered. +// file:../VM/eventtrace.cpp#Unregistration. Since ETW can also be enabled at any instant after the process +// has started, one may want to do something useful when that happens (e.g enumerate all the loaded modules +// in the system). To enable this, we have to implement a callback routine. +// file:../VM/eventtrace.cpp#EtwCallback is CLR's implementation of the callback. +// + +#include "daccess.h" +class Module; +class Assembly; +class MethodDesc; +class MethodTable; +class BaseDomain; +class AppDomain; +class SString; +class CrawlFrame; +class LoaderAllocator; +class AssemblyLoaderAllocator; +struct AllLoggedTypes; +class CrstBase; +class BulkTypeEventLogger; +class TypeHandle; +class Thread; + + +// All ETW helpers must be a part of this namespace +// We have auto-generated macros to directly fire the events +// but in some cases, gathering the event payload information involves some work +// and it can be done in a relevant helper class like the one's in this namespace +namespace ETW +{ + // Class to wrap the ETW infrastructure logic +#if !defined(FEATURE_PAL) + class CEtwTracer + { +#if defined(FEATURE_EVENT_TRACE) + ULONG RegGuids(LPCGUID ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle); +#endif + + public: +#ifdef FEATURE_EVENT_TRACE + // Registers all the Event Tracing providers + HRESULT Register(); + + // Unregisters all the Event Tracing providers + HRESULT UnRegister(); +#else + HRESULT Register() + { + return S_OK; + } + HRESULT UnRegister() + { + return S_OK; + } +#endif // FEATURE_EVENT_TRACE + }; +#endif // !defined(FEATURE_PAL) + + class LoaderLog; + class MethodLog; + // Class to wrap all the enumeration logic for ETW + class EnumerationLog + { + friend class ETW::LoaderLog; + friend class ETW::MethodLog; +#ifdef FEATURE_EVENT_TRACE + static VOID SendThreadRundownEvent(); + static VOID IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions); + static VOID IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions); + static VOID IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions); + static VOID IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions); + static VOID IterateModule(Module *pModule, DWORD enumerationOptions); + static VOID EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions); + static DWORD GetEnumerationOptionsFromRuntimeKeywords(); + public: + typedef union _EnumerationStructs + { + typedef enum _EnumerationOptions + { + None= 0x00000000, + DomainAssemblyModuleLoad= 0x00000001, + DomainAssemblyModuleUnload= 0x00000002, + DomainAssemblyModuleDCStart= 0x00000004, + DomainAssemblyModuleDCEnd= 0x00000008, + JitMethodLoad= 0x00000010, + JitMethodUnload= 0x00000020, + JitMethodDCStart= 0x00000040, + JitMethodDCEnd= 0x00000080, + NgenMethodLoad= 0x00000100, + NgenMethodUnload= 0x00000200, + NgenMethodDCStart= 0x00000400, + NgenMethodDCEnd= 0x00000800, + ModuleRangeLoad= 0x00001000, + ModuleRangeDCStart= 0x00002000, + ModuleRangeDCEnd= 0x00004000, + ModuleRangeLoadPrivate= 0x00008000, + MethodDCStartILToNativeMap= 0x00010000, + MethodDCEndILToNativeMap= 0x00020000, + JitMethodILToNativeMap= 0x00040000, + TypeUnload= 0x00080000, + + // Helpers + ModuleRangeEnabledAny = ModuleRangeLoad | ModuleRangeDCStart | ModuleRangeDCEnd | ModuleRangeLoadPrivate, + JitMethodLoadOrDCStartAny = JitMethodLoad | JitMethodDCStart | MethodDCStartILToNativeMap, + JitMethodUnloadOrDCEndAny = JitMethodUnload | JitMethodDCEnd | MethodDCEndILToNativeMap, + }EnumerationOptions; + }EnumerationStructs; + + static VOID ProcessShutdown(); + static VOID ModuleRangeRundown(); + static VOID SendOneTimeRundownEvents(); + static VOID StartRundown(); + static VOID EndRundown(); + static VOID EnumerateForCaptureState(); +#else + public: + static VOID ProcessShutdown() {}; + static VOID StartRundown() {}; + static VOID EndRundown() {}; +#endif // FEATURE_EVENT_TRACE + }; + + + // Class to wrap all the sampling logic for ETW + + class SamplingLog + { +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) + public: + typedef enum _EtwStackWalkStatus + { + Completed = 0, + UnInitialized = 1, + InProgress = 2 + } EtwStackWalkStatus; + private: + static const UINT8 s_MaxStackSize=100; + UINT32 m_FrameCount; + SIZE_T m_EBPStack[SamplingLog::s_MaxStackSize]; + VOID Append(SIZE_T currentFrame); + EtwStackWalkStatus SaveCurrentStack(int skipTopNFrames=1); + public: + static ULONG SendStackTrace(MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid); + EtwStackWalkStatus GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack); +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) + }; + + // Class to wrap all Loader logic for ETW + class LoaderLog + { + friend class ETW::EnumerationLog; +#if defined(FEATURE_EVENT_TRACE) + static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE); + static ULONG SendModuleRange(__in Module *pModule, __in DWORD dwEventOptions); + static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions); + static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); + public: + typedef union _LoaderStructs + { + typedef enum _AppDomainFlags + { + DefaultDomain=0x1, + ExecutableDomain=0x2, + SharedDomain=0x4 + }AppDomainFlags; + + typedef enum _AssemblyFlags + { + DomainNeutralAssembly=0x1, + DynamicAssembly=0x2, + NativeAssembly=0x4, + CollectibleAssembly=0x8, + ReadyToRunAssembly=0x10, + }AssemblyFlags; + + typedef enum _ModuleFlags + { + DomainNeutralModule=0x1, + NativeModule=0x2, + DynamicModule=0x4, + ManifestModule=0x8, + IbcOptimized=0x10, + ReadyToRunModule=0x20, + PartialReadyToRunModule=0x40, + }ModuleFlags; + + typedef enum _RangeFlags + { + HotRange=0x0 + }RangeFlags; + + }LoaderStructs; + + static VOID DomainLoadReal(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL); + + static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName = NULL) + { + if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) + { + DomainLoadReal(pDomain, wszFriendlyName); + } + } + + static VOID DomainUnload(AppDomain *pDomain); + static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator); + static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule); +#else + public: + static VOID DomainLoad(BaseDomain *pDomain, __in_opt LPWSTR wszFriendlyName=NULL) {}; + static VOID DomainUnload(AppDomain *pDomain) {}; + static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) {}; + static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Method logic for ETW + class MethodLog + { + friend class ETW::EnumerationLog; +#ifdef FEATURE_EVENT_TRACE + static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); + static VOID SendEventsForJitMethodsHelper( + LoaderAllocator *pLoaderAllocatorFilter, + DWORD dwEventOptions, + BOOL fLoadOrDCStart, + BOOL fUnloadOrDCEnd, + BOOL fSendMethodEvent, + BOOL fSendILToNativeMapEvent, + BOOL fGetCodeIds); + static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); + static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); + static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, ReJITID ilCodeId); + static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL); + static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); + public: + typedef union _MethodStructs + { + typedef enum _MethodFlags + { + DynamicMethod=0x1, + GenericMethod=0x2, + SharedGenericCode=0x4, + JittedMethod=0x8, + JitHelperMethod=0x10, + ProfilerRejectedPrecompiledCode=0x20, + ReadyToRunRejectedPrecompiledCode=0x40, + // 0x80 to 0x200 are used for the optimization tier + }MethodFlags; + + typedef enum _MethodExtent + { + HotSection=0x00000000, + ColdSection=0x10000000 + }MethodExtent; + + }MethodStructs; + + static const UINT8 MethodFlagsJitOptimizationTierShift = 7; + static const unsigned int MethodFlagsJitOptimizationTierLowMask = 0x7; + + static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint); + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); + static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); + static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers); + static VOID MethodRestored(MethodDesc * pMethodDesc); + static VOID MethodTableRestored(MethodTable * pMethodTable); + static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc); +#else // FEATURE_EVENT_TRACE + public: + static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {}; + static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); + static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); + static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; + static VOID StubsInitialized(PVOID *pHelperStartAddresss, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; + static VOID MethodRestored(MethodDesc * pMethodDesc) {}; + static VOID MethodTableRestored(MethodTable * pMethodTable) {}; + static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Security logic for ETW + class SecurityLog + { +#ifdef FEATURE_EVENT_TRACE + public: + static VOID StrongNameVerificationStart(DWORD dwInFlags, __in LPWSTR strFullyQualifiedAssemblyName); + static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, __in LPWSTR strFullyQualifiedAssemblyName); + + static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain); + static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet); + + static void FireTokenTransparencyComputationStart(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireTokenTransparencyComputationEnd(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); + + static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain); + static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe); +#else + public: + static VOID StrongNameVerificationStart(DWORD dwInFlags, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; + static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; + + static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain) {}; + static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsTreatAsSafe, + BOOL fIsOpportunisticallyCritical, + DWORD dwSecurityRuleSet) {}; + + static void FireTokenTransparencyComputationStart(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireTokenTransparencyComputationEnd(DWORD dwToken, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; + + static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain) {}; + static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, + LPCWSTR wszModuleName, + DWORD dwAppDomain, + BOOL fIsAllCritical, + BOOL fIsAllTransparent, + BOOL fIsCritical, + BOOL fIsTreatAsSafe) {}; +#endif // FEATURE_EVENT_TRACE + }; + + // Class to wrap all Binder logic for ETW + class BinderLog + { + public: + typedef union _BinderStructs { + typedef enum _NGENBINDREJECT_REASON { + NGEN_BIND_START_BIND = 0, + NGEN_BIND_NO_INDEX = 1, + NGEN_BIND_SYSTEM_ASSEMBLY_NOT_AVAILABLE = 2, + NGEN_BIND_NO_NATIVE_IMAGE = 3, + NGEN_BIND_REJECT_CONFIG_MASK = 4, + NGEN_BIND_FAIL = 5, + NGEN_BIND_INDEX_CORRUPTION = 6, + NGEN_BIND_REJECT_TIMESTAMP = 7, + NGEN_BIND_REJECT_NATIVEIMAGE_NOT_FOUND = 8, + NGEN_BIND_REJECT_IL_SIG = 9, + NGEN_BIND_REJECT_LOADER_EVAL_FAIL = 10, + NGEN_BIND_MISSING_FOUND = 11, + NGEN_BIND_REJECT_HOSTASM = 12, + NGEN_BIND_REJECT_IL_NOT_FOUND = 13, + NGEN_BIND_REJECT_APPBASE_NOT_FILE = 14, + NGEN_BIND_BIND_DEPEND_REJECT_REF_DEF_MISMATCH = 15, + NGEN_BIND_BIND_DEPEND_REJECT_NGEN_SIG = 16, + NGEN_BIND_APPLY_EXTERNAL_RELOCS_FAILED = 17, + NGEN_BIND_SYSTEM_ASSEMBLY_NATIVEIMAGE_NOT_AVAILABLE = 18, + NGEN_BIND_ASSEMBLY_HAS_DIFFERENT_GRANT = 19, + NGEN_BIND_ASSEMBLY_NOT_DOMAIN_NEUTRAL = 20, + NGEN_BIND_NATIVEIMAGE_VERSION_MISMATCH = 21, + NGEN_BIND_LOADFROM_NOT_ALLOWED = 22, + NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY = 23 + } NGENBINDREJECT_REASON; + } BinderStructs; + }; + + // Class to wrap all Exception logic for ETW + class ExceptionLog + { + public: +#ifdef FEATURE_EVENT_TRACE + static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException); + static VOID ExceptionThrownEnd(); + static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionCatchEnd(); + static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionFinallyEnd(); + static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); + static VOID ExceptionFilterEnd(); + +#else + static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) {}; + static VOID ExceptionThrownEnd() {}; + static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionCatchEnd() {}; + static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionFinallyEnd() {}; + static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; + static VOID ExceptionFilterEnd() {}; +#endif // FEATURE_EVENT_TRACE + typedef union _ExceptionStructs + { + typedef enum _ExceptionThrownFlags + { + HasInnerException=0x1, + IsNestedException=0x2, + IsReThrownException=0x4, + IsCSE=0x8, + IsCLSCompliant=0x10 + }ExceptionThrownFlags; + }ExceptionStructs; + }; + // Class to wrap all Contention logic for ETW + class ContentionLog + { + public: + typedef union _ContentionStructs + { + typedef enum _ContentionFlags { + ManagedContention=0, + NativeContention=1 + } ContentionFlags; + } ContentionStructs; + }; + // Class to wrap all Interop logic for ETW + class InteropLog + { + public: + }; + + // Class to wrap all Information logic for ETW + class InfoLog + { + public: + typedef union _InfoStructs + { + typedef enum _StartupMode + { + ManagedExe=0x1, + HostedCLR=0x2, + IJW=0x4, + COMActivated=0x8, + Other=0x10 + }StartupMode; + + typedef enum _Sku + { + DesktopCLR=0x1, + CoreCLR=0x2 + }Sku; + + typedef enum _EtwMode + { + Normal=0x0, + Callback=0x1 + }EtwMode; + }InfoStructs; + +#ifdef FEATURE_EVENT_TRACE + static VOID RuntimeInformation(INT32 type); +#else + static VOID RuntimeInformation(INT32 type) {}; +#endif // FEATURE_EVENT_TRACE + }; + + class CodeSymbolLog + { + public: +#ifdef FEATURE_EVENT_TRACE + static VOID EmitCodeSymbols(Module* pModule); + static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes); + static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, + DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead); +#else + static VOID EmitCodeSymbols(Module* pModule) {} + static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes) { return S_OK; } + static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, + DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead) { return S_OK; } +#endif // FEATURE_EVENT_TRACE + }; + +#define DISABLE_CONSTRUCT_COPY(T) \ + T() = delete; \ + T(const T &) = delete; \ + T &operator =(const T &) = delete + + // Class to wrap all Compilation logic for ETW + class CompilationLog + { + public: + class Runtime + { + public: +#ifdef FEATURE_EVENT_TRACE + static bool IsEnabled(); +#else + static bool IsEnabled() { return false; } +#endif + + DISABLE_CONSTRUCT_COPY(Runtime); + }; + + class Rundown + { + public: +#ifdef FEATURE_EVENT_TRACE + static bool IsEnabled(); +#else + static bool IsEnabled() { return false; } +#endif + + DISABLE_CONSTRUCT_COPY(Rundown); + }; + + // Class to wrap all TieredCompilation logic for ETW + class TieredCompilation + { + private: + static void GetSettings(UINT32 *flagsRef); + + public: + class Runtime + { + public: +#ifdef FEATURE_EVENT_TRACE + static bool IsEnabled(); + static void SendSettings(); + static void SendPause(); + static void SendResume(UINT32 newMethodCount); + static void SendBackgroundJitStart(UINT32 pendingMethodCount); + static void SendBackgroundJitStop(UINT32 pendingMethodCount, UINT32 jittedMethodCount); +#else + static bool IsEnabled() { return false; } + static void SendSettings() {} +#endif + + DISABLE_CONSTRUCT_COPY(Runtime); + }; + + class Rundown + { + public: +#ifdef FEATURE_EVENT_TRACE + static bool IsEnabled(); + static void SendSettings(); +#else + static bool IsEnabled() { return false; } + static void SendSettings() {} +#endif + + DISABLE_CONSTRUCT_COPY(Rundown); + }; + + DISABLE_CONSTRUCT_COPY(TieredCompilation); + }; + + DISABLE_CONSTRUCT_COPY(CompilationLog); + }; + +#undef DISABLE_CONSTRUCT_COPY +}; + + +#define ETW_IS_TRACE_ON(level) ( FALSE ) // for fusion which is eventually going to get removed +#define ETW_IS_FLAG_ON(flag) ( FALSE ) // for fusion which is eventually going to get removed + +// Commonly used constats for ETW Assembly Loader and Assembly Binder events. +#define ETWLoadContextNotAvailable (LOADCTX_TYPE_HOSTED + 1) +#define ETWAppDomainIdNotAvailable 0 // Valid AppDomain IDs start from 1 + +#define ETWFieldUnused 0 // Indicates that a particular field in the ETW event payload template is currently unused. + +#define ETWLoaderLoadTypeNotAvailable 0 // Static or Dynamic Load is only valid at LoaderPhaseStart and LoaderPhaseEnd events - for other events, 0 indicates "not available" +#define ETWLoaderStaticLoad 0 // Static reference load +#define ETWLoaderDynamicLoad 1 // Dynamic assembly load + +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +// +// The ONE and only ONE global instantiation of this class +// +extern ETW::CEtwTracer * g_pEtwTracer; + +// +// Special Handling of Startup events +// + +// "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; +// on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so +// we manually place it here. +ETW_INLINE +ULONG +CoMofTemplate_h( + __in REGHANDLE RegHandle, + __in PCEVENT_DESCRIPTOR Descriptor, + __in_opt LPCGUID EventGuid, + __in const unsigned short ClrInstanceID + ) +{ +#define ARGUMENT_COUNT_h 1 + ULONG Error = ERROR_SUCCESS; +typedef struct _MCGEN_TRACE_BUFFER { + EVENT_TRACE_HEADER Header; + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_h]; +} MCGEN_TRACE_BUFFER; + + MCGEN_TRACE_BUFFER TraceBuf; + PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; + + EventDataDescCreate(&EventData[0], &ClrInstanceID, sizeof(const unsigned short) ); + + + { + Error = EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_h, EventData); + + } + +#ifdef MCGEN_CALLOUT +MCGEN_CALLOUT(RegHandle, + Descriptor, + ARGUMENT_COUNT_h, + EventData); +#endif + + return Error; +} + +class ETWTraceStartup { + REGHANDLE TraceHandle; + PCEVENT_DESCRIPTOR EventStartDescriptor; + LPCGUID EventStartGuid; + PCEVENT_DESCRIPTOR EventEndDescriptor; + LPCGUID EventEndGuid; +public: + ETWTraceStartup(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventStartDescriptor, LPCGUID _EventStartGuid, PCEVENT_DESCRIPTOR _EventEndDescriptor, LPCGUID _EventEndGuid) { + TraceHandle = _TraceHandle; + EventStartDescriptor = _EventStartDescriptor; + EventEndDescriptor = _EventEndDescriptor; + EventStartGuid = _EventStartGuid; + EventEndGuid = _EventEndGuid; + StartupTraceEvent(TraceHandle, EventStartDescriptor, EventStartGuid); + } + ~ETWTraceStartup() { + StartupTraceEvent(TraceHandle, EventEndDescriptor, EventEndGuid); + } + static void StartupTraceEvent(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventDescriptor, LPCGUID _EventGuid) { + EVENT_DESCRIPTOR desc = *_EventDescriptor; + if(ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context, desc)) + { + CoMofTemplate_h(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context.RegistrationHandle, _EventDescriptor, _EventGuid, GetClrInstanceId()); + } + } +}; +// "mc.exe -MOF" already generates this block for XP-suported builds inside ClrEtwAll.h; +// on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so +// we manually place it here. +FORCEINLINE +BOOLEAN __stdcall +McGenEventTracingEnabled( + __in PMCGEN_TRACE_CONTEXT EnableInfo, + __in PCEVENT_DESCRIPTOR EventDescriptor + ) +{ + + if(!EnableInfo){ + return FALSE; + } + + + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((EventDescriptor->Level <= EnableInfo->Level) || // This also covers the case of Level == 0. + (EnableInfo->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((EventDescriptor->Keyword == (ULONGLONG)0) || + ((EventDescriptor->Keyword & EnableInfo->MatchAnyKeyword) && + ((EventDescriptor->Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { + return TRUE; + } + } + + return FALSE; +} + + +ETW_INLINE +ULONG +ETW::SamplingLog::SendStackTrace( + MCGEN_TRACE_CONTEXT TraceContext, + PCEVENT_DESCRIPTOR Descriptor, + LPCGUID EventGuid) +{ +#define ARGUMENT_COUNT_CLRStackWalk 5 + ULONG Result = ERROR_SUCCESS; +typedef struct _MCGEN_TRACE_BUFFER { + EVENT_TRACE_HEADER Header; + EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_CLRStackWalk]; +} MCGEN_TRACE_BUFFER; + + REGHANDLE RegHandle = TraceContext.RegistrationHandle; + if(!TraceContext.IsEnabled || !McGenEventTracingEnabled(&TraceContext, Descriptor)) + { + return Result; + } + + PVOID *Stack = NULL; + UINT32 FrameCount = 0; + ETW::SamplingLog stackObj; + if(stackObj.GetCurrentThreadsCallStack(&FrameCount, &Stack) == ETW::SamplingLog::Completed) + { + UCHAR Reserved1=0, Reserved2=0; + UINT16 ClrInstanceId = GetClrInstanceId(); + MCGEN_TRACE_BUFFER TraceBuf; + PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; + + EventDataDescCreate(&EventData[0], &ClrInstanceId, sizeof(const UINT16) ); + + EventDataDescCreate(&EventData[1], &Reserved1, sizeof(const UCHAR) ); + + EventDataDescCreate(&EventData[2], &Reserved2, sizeof(const UCHAR) ); + + EventDataDescCreate(&EventData[3], &FrameCount, sizeof(const unsigned int) ); + + EventDataDescCreate(&EventData[4], Stack, sizeof(PVOID) * FrameCount ); + + return EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_CLRStackWalk, EventData); + } + return Result; +}; + +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) +#ifdef FEATURE_EVENT_TRACE +#ifdef _TARGET_X86_ +struct CallStackFrame +{ + struct CallStackFrame* m_Next; + SIZE_T m_ReturnAddress; +}; +#endif // _TARGET_X86_ +#endif // FEATURE_EVENT_TRACE + +#if defined(FEATURE_EVENT_TRACE) && !defined(FEATURE_PAL) +FORCEINLINE +BOOLEAN __stdcall +McGenEventProviderEnabled( + __in PMCGEN_TRACE_CONTEXT Context, + __in UCHAR Level, + __in ULONGLONG Keyword + ) +{ + if(!Context) { + return FALSE; + } + + // + // Check if the event Level is lower than the level at which + // the channel is enabled. + // If the event Level is 0 or the channel is enabled at level 0, + // all levels are enabled. + // + + if ((Level <= Context->Level) || // This also covers the case of Level == 0. + (Context->Level == 0)) { + + // + // Check if Keyword is enabled + // + + if ((Keyword == (ULONGLONG)0) || + ((Keyword & Context->MatchAnyKeyword) && + ((Keyword & Context->MatchAllKeyword) == Context->MatchAllKeyword))) { + return TRUE; + } + } + return FALSE; +} +#endif // FEATURE_EVENT_TRACE && !defined(FEATURE_PAL) + + +#endif // !FEATURE_REDHAWK + +// These parts of the ETW namespace are common for both FEATURE_REDHAWK and +// !FEATURE_REDHAWK builds. + + +struct ProfilingScanContext; +class Object; + +namespace ETW +{ + // Class to wrap the logging of threads (runtime and rundown providers) + class ThreadLog + { + private: + static DWORD GetEtwThreadFlags(Thread * pThread); + + public: + static VOID FireThreadCreated(Thread * pThread); + static VOID FireThreadDC(Thread * pThread); + }; +}; + + +#endif //_ETWTRACER_HXX_ diff --git a/lib/coreclr/src/inc/ex.h b/lib/coreclr/src/inc/ex.h new file mode 100644 index 0000000000..ac40cbacdf --- /dev/null +++ b/lib/coreclr/src/inc/ex.h @@ -0,0 +1,1423 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#if !defined(_EX_H_) +#define _EX_H_ + +#ifdef FEATURE_PAL +#define EX_TRY_HOLDER \ + HardwareExceptionHolder \ + NativeExceptionHolderCatchAll __exceptionHolder; \ + __exceptionHolder.Push(); \ + +#else // FEATURE_PAL +#define EX_TRY_HOLDER +#endif // FEATURE_PAL + +#include "sstring.h" +#include "crtwrap.h" +#include "winwrap.h" +#include "corerror.h" +#include "stresslog.h" +#include "staticcontract.h" +#include "entrypoints.h" + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + + +//=========================================================================================== +// These abstractions hide the difference between legacy desktop CLR's (that don't support +// side-by-side-inproc and rely on a fixed SEH code to identify managed exceptions) and +// new CLR's that support side-by-side inproc. +// +// The new CLR's use a different set of SEH codes to avoid conflicting with the legacy CLR's. +// In addition, to distinguish between EH's raised by different inproc instances of the CLR, +// the module handle of the owning CLR is stored in ExceptionRecord.ExceptionInformation[4]. +// +// (Note: all existing SEH's use either only slot [0] or no slots at all. We are leaving +// slots [1] thru [3] open for future expansion.) +//=========================================================================================== + +// Is this exception code one of the special CLR-specific SEH codes that participate in the +// instance-tagging scheme? +BOOL IsInstanceTaggedSEHCode(DWORD dwExceptionCode); + + +// This set of overloads generates the NumberParameters and ExceptionInformation[] array to +// pass to RaiseException(). +// +// Parameters: +// exceptionArgs: a fixed-size array of size INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE. +// This will get filled in by this function. (The module handle goes +// in the last slot if this is a side-by-side-inproc enabled build.) +// +// exceptionArg1... up to four arguments that go in slots [0]..[3]. These depends +// the specific requirements of your exception code. +// +// Returns: +// The NumberParameters to pass to RaiseException(). +// +// Basically, this is either INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE or the count of your +// fixed arguments depending on whether this tagged-SEH-enabled build. +// +// This function is not permitted to fail. + +#define INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE 5 +DWORD MarkAsThrownByUs(/*out*/ ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE]); +DWORD MarkAsThrownByUs(/*out*/ ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE], ULONG_PTR arg0); +// (the existing system can support more overloads up to 4 fixed arguments but we don't need them at this time.) + + +// Given an exception record, checks if it's exception code matches a specific exception code +// *and* whether it was tagged by the calling instance of the CLR. +// +// If this is a non-tagged-SEH-enabled build, it is blindly assumed to be tagged by the +// calling instance of the CLR. +BOOL WasThrownByUs(const EXCEPTION_RECORD *pcER, DWORD dwExceptionCode); + + +//----------------------------------------------------------------------------------- +// The following group wraps the basic abstracts specifically for EXCEPTION_COMPLUS. +//----------------------------------------------------------------------------------- +BOOL IsComPlusException(const EXCEPTION_RECORD *pcER); +VOID RaiseComPlusException(); + + +//=========================================================================================== +//=========================================================================================== + + +//------------------------------------------------------------------------------------------- +// This routine will generate the most descriptive possible error message for an hresult. +// It will generate at minimum the hex value. It will also try to generate the symbolic name +// (E_POINTER) and the friendly description (from the message tables.) +// +// bNoGeekStuff suppresses hex HR codes. Use this sparingly as most error strings generated by the +// CLR are aimed at developers, not end-users. +//------------------------------------------------------------------------------------------- +void GetHRMsg(HRESULT hresult, SString &result, BOOL bNoGeekStuff = FALSE); + + +//------------------------------------------------------------------------------------------- +// Similar to GetHRMsg but phrased for top-level exception message. +//------------------------------------------------------------------------------------------- +void GenerateTopLevelHRExceptionMessage(HRESULT hresult, SString &result); + + +// --------------------------------------------------------------------------- +// We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid +// duing exception handling. GetCurrentExceptionPointers returns the saved data. +// --------------------------------------------------------------------------- +void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo); + +// --------------------------------------------------------------------------- +// We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid +// duing exception handling. GetCurrentExceptionCode returns the current exception code. +// --------------------------------------------------------------------------- +DWORD GetCurrentExceptionCode(); + +// --------------------------------------------------------------------------- +// Standard exception hierarchy & infrastructure for library code & EE +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// Exception class. Abstract root exception of our hierarchy. +// --------------------------------------------------------------------------- + +class Exception; +class SEHException; + + +// Exception hierarchy: +/* GetInstanceType +Exception + | + |-> HRException Y + | | + | |-> HRMsgException + | |-> COMException + | + |-> SEHException Y + | + |-> DelegatingException Y + | + |-> OutOfMemoryException Y + | + |-> CLRException Y + | + |-> EEException Y + | | + | |-> EEMessageException + | | + | |-> EEResourceException + | | + | |-> EECOMException + | | + | |-> EEFieldException + | | + | |-> EEMethodException + | | + | |-> EEArgumentException + | | + | |-> EETypeLoadException + | | + | |-> EEFileLoadException + | + |-> ObjrefException Y + | + |-> CLRLastThrownObjectException Y +*/ + +class Exception +{ + friend bool DebugIsEECxxExceptionPointer(void* pv); + + private: + static const int c_type = 0x524f4f54; // 'ROOT' + static Exception * g_OOMException; + static Exception * g_SOException; + + protected: + Exception *m_innerException; + + public: + Exception() {LIMITED_METHOD_DAC_CONTRACT; m_innerException = NULL;} + virtual ~Exception() {LIMITED_METHOD_DAC_CONTRACT; if (m_innerException != NULL) Exception::Delete(m_innerException); } + virtual BOOL IsDomainBound() {return m_innerException!=NULL && m_innerException->IsDomainBound();} ; + virtual HRESULT GetHR() = 0; + virtual void GetMessage(SString &s); + virtual IErrorInfo *GetErrorInfo() { LIMITED_METHOD_CONTRACT; return NULL; } + virtual HRESULT SetErrorInfo() { LIMITED_METHOD_CONTRACT; return S_OK; } + void SetInnerException(Exception * pInnerException) { LIMITED_METHOD_CONTRACT; m_innerException = pInnerException; } + + // Dynamic type query for catchers + static int GetType() { LIMITED_METHOD_CONTRACT; return c_type; } + // !!! If GetInstanceType is implemented, IsSameInstanceType should be implemented + virtual int GetInstanceType() = 0; + virtual BOOL IsType(int type) {LIMITED_METHOD_CONTRACT; return type == c_type; } + + // This is used in CLRException::GetThrowable to detect if we are in a recursive situation. + virtual BOOL IsSameInstanceType(Exception *pException) = 0; + + // Will create a new instance of the Exception. Note that this will + // be free of app domain or thread affinity. Not every type of exception + // can be cloned with full fidelity. + virtual Exception *Clone(); + + // DomainBoundClone is a specialized form of cloning which is guaranteed + // to provide full fidelity. However, the result is bound to the current + // app domain and should not be leaked. + Exception *DomainBoundClone(); + + class HandlerState + { + enum CaughtFlags + { + Caught = 1, + CaughtSO = 2, + CaughtCxx = 4, + }; + + DWORD m_dwFlags; + public: + Exception* m_pExceptionPtr; + + HandlerState(); + + void CleanupTry(); + void SetupCatch(INDEBUG_COMMA(__in_z const char * szFile) int lineNum); + void SucceedCatch(); + + BOOL DidCatch() { return (m_dwFlags & Caught); } + void SetCaught() { m_dwFlags |= Caught; } + + BOOL DidCatchCxx() { return (m_dwFlags & CaughtCxx); } + void SetCaughtCxx() { m_dwFlags |= CaughtCxx; } + }; + + // Is this exception type considered "uncatchable"? + BOOL IsTerminal(); + + // Is this exception type considered "transient" (would a retry possibly succeed)? + BOOL IsTransient(); + static BOOL IsTransient(HRESULT hr); + + // Get an HRESULT's source representation, if known + static LPCSTR GetHRSymbolicName(HRESULT hr); + + static Exception* GetOOMException(); + + // Preallocated exceptions: If there is a preallocated instance of some + // subclass of Exception, override this function and return a correct + // value. The default implementation returns constant FALSE + virtual BOOL IsPreallocatedException(); + BOOL IsPreallocatedOOMException(); + + static void Delete(Exception* pvMemory); + +protected: + + // This virtual method must be implemented by any non abstract Exception + // derived class. It must allocate a NEW exception of the identical type and + // copy all the relevant fields from the current exception to the new one. + // It is NOT responsible however for copying the inner exception. This + // will be handled by the base Exception class. + virtual Exception *CloneHelper(); + + // This virtual method must be implemented by Exception subclasses whose + // DomainBoundClone behavior is different than their normal clone behavior. + // It must allocate a NEW exception of the identical type and + // copy all the relevant fields from the current exception to the new one. + // It is NOT responsible however for copying the inner exception. This + // will be handled by the base Exception class. + virtual Exception *DomainBoundCloneHelper() { return CloneHelper(); } +}; + +#if 1 +template +inline void Exception__Delete(T* pvMemory); + +template <> +inline void Exception__Delete(Exception* pvMemory) +{ + Exception::Delete(pvMemory); +} + +NEW_WRAPPER_TEMPLATE1(ExceptionHolderTemplate, Exception__Delete<_TYPE>); +typedef ExceptionHolderTemplate ExceptionHolder; +#else + +//------------------------------------------------------------------------------ +// class ExceptionHolder +// +// This is a very lightweight holder class for use inside the EX_TRY family +// of macros. It is based on the standard Holder classes, but has been +// highly specialized for this one function, so that extra code can be +// removed, and the resulting code can be simple enough for all of the +// non-exceptional-case code to be inlined. +class ExceptionHolder +{ +private: + Exception *m_value; + BOOL m_acquired; + +public: + FORCEINLINE ExceptionHolder(Exception *pException = NULL, BOOL take = TRUE) + : m_value(pException) + { + m_acquired = pException && take; + } + + FORCEINLINE ~ExceptionHolder() + { + if (m_acquired) + { + Exception::Delete(m_value); + } + } + + Exception* operator->() { return m_value; } + + void operator=(Exception *p) + { + Release(); + m_value = p; + Acquire(); + } + + BOOL IsNull() { return m_value == NULL; } + + operator Exception*() { return m_value; } + + Exception* GetValue() { return m_value; } + + void SuppressRelease() { m_acquired = FALSE; } + +private: + void Acquire() + { + _ASSERTE(!m_acquired); + + if (!IsNull()) + { + m_acquired = TRUE; + } + } + void Release() + { + if (m_acquired) + { + _ASSERTE(!IsNull()); + Exception::Delete(m_value); + m_acquired = FALSE; + } + } + +}; + +#endif + +// --------------------------------------------------------------------------- +// HRException class. Implements exception API for exceptions generated from HRESULTs +// --------------------------------------------------------------------------- + +class HRException : public Exception +{ + friend bool DebugIsEECxxExceptionPointer(void* pv); + + protected: + HRESULT m_hr; + + public: + HRException(); + HRException(HRESULT hr); + + static const int c_type = 0x48522020; // 'HR ' + + // Dynamic type query for catchers + static int GetType() {LIMITED_METHOD_DAC_CONTRACT; return c_type; } + virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } + virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } + // Virtual overrides + HRESULT GetHR(); + + BOOL IsSameInstanceType(Exception *pException) + { + WRAPPER_NO_CONTRACT; + return pException->GetInstanceType() == GetType() && pException->GetHR() == m_hr; + } + + protected: + virtual Exception *CloneHelper() + { + WRAPPER_NO_CONTRACT; + return new HRException(m_hr); + } +}; + +// --------------------------------------------------------------------------- +// HRMessageException class. Implements exception API for exceptions +// generated from HRESULTs, and includes in info message. +// --------------------------------------------------------------------------- + +class HRMsgException : public HRException +{ + friend bool DebugIsEECxxExceptionPointer(void* pv); + + protected: + SString m_msg; + + public: + HRMsgException(); + HRMsgException(HRESULT hr, SString const &msg); + + // Virtual overrides + void GetMessage(SString &s); + + protected: + virtual Exception *CloneHelper() + { + WRAPPER_NO_CONTRACT; + return new HRMsgException(m_hr, m_msg); + } +}; + +// --------------------------------------------------------------------------- +// COMException class. Implements exception API for standard COM-based error info +// --------------------------------------------------------------------------- + +class COMException : public HRException +{ + friend bool DebugIsEECxxExceptionPointer(void* pv); + + private: + IErrorInfo *m_pErrorInfo; + + public: + COMException(); + COMException(HRESULT hr) ; + COMException(HRESULT hr, IErrorInfo *pErrorInfo); + ~COMException(); + + // Virtual overrides + IErrorInfo *GetErrorInfo(); + void GetMessage(SString &result); + + protected: + virtual Exception *CloneHelper() + { + WRAPPER_NO_CONTRACT; + return new COMException(m_hr, m_pErrorInfo); + } +}; + +// --------------------------------------------------------------------------- +// SEHException class. Implements exception API for SEH exception info +// --------------------------------------------------------------------------- + +class SEHException : public Exception +{ + friend bool DebugIsEECxxExceptionPointer(void* pv); + + public: + EXCEPTION_RECORD m_exception; + + SEHException(); + SEHException(EXCEPTION_RECORD *pRecord, T_CONTEXT *pContext = NULL); + + static const int c_type = 0x53454820; // 'SEH ' + + // Dynamic type query for catchers + static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } + virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } + virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } + + BOOL IsSameInstanceType(Exception *pException) + { + WRAPPER_NO_CONTRACT; + return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); + } + + // Virtual overrides + HRESULT GetHR(); + IErrorInfo *GetErrorInfo(); + void GetMessage(SString &result); + + protected: + virtual Exception *CloneHelper() + { + WRAPPER_NO_CONTRACT; + return new SEHException(&m_exception); + } +}; + +// --------------------------------------------------------------------------- +// DelegatingException class. Implements exception API for "foreign" exceptions. +// --------------------------------------------------------------------------- + +class DelegatingException : public Exception +{ + Exception *m_delegatedException; + Exception* GetDelegate(); + + enum {DELEGATE_NOT_YET_SET = -1}; + bool IsDelegateSet() {LIMITED_METHOD_DAC_CONTRACT; return m_delegatedException != (Exception*)DELEGATE_NOT_YET_SET; } + bool IsDelegateValid() {LIMITED_METHOD_DAC_CONTRACT; return IsDelegateSet() && m_delegatedException != NULL; } + + public: + + DelegatingException(); + ~DelegatingException(); + + static const int c_type = 0x44454C20; // 'DEL ' + + // Dynamic type query for catchers + static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } + virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } + virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } + + BOOL IsSameInstanceType(Exception *pException) + { + WRAPPER_NO_CONTRACT; + return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); + } + + // Virtual overrides + virtual BOOL IsDomainBound() {return Exception::IsDomainBound() ||(m_delegatedException!=NULL && m_delegatedException->IsDomainBound());} ; + HRESULT GetHR(); + IErrorInfo *GetErrorInfo(); + void GetMessage(SString &result); + virtual Exception *Clone(); + + protected: + virtual Exception *CloneHelper() + { + WRAPPER_NO_CONTRACT; + return new DelegatingException(); + } +}; + +//------------------------------------------------------------------------------ +// class OutOfMemoryException +// +// While there could be any number of instances of this class, there is one +// special instance, the pre-allocated OOM exception. Storage for that +// instance is allocated in the image, so we can always obtain it, even +// in low memory situations. +// Note that, in fact, there is only one instance. +//------------------------------------------------------------------------------ +class OutOfMemoryException : public Exception +{ + private: + static const int c_type = 0x4F4F4D20; // 'OOM ' + BOOL bIsPreallocated; + + public: + OutOfMemoryException() : bIsPreallocated(FALSE) {} + OutOfMemoryException(BOOL b) : bIsPreallocated(b) {} + + // Dynamic type query for catchers + static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } + virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } + BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } + + BOOL IsSameInstanceType(Exception *pException) + { + WRAPPER_NO_CONTRACT; + return pException->GetInstanceType() == GetType(); + } + + HRESULT GetHR() {LIMITED_METHOD_DAC_CONTRACT; return E_OUTOFMEMORY; } + void GetMessage(SString &result) { WRAPPER_NO_CONTRACT; result.SetASCII("Out Of Memory"); } + + virtual Exception *Clone(); + + virtual BOOL IsPreallocatedException() { return bIsPreallocated; } +}; + +template +class CAutoTryCleanup +{ +public: + DEBUG_NOINLINE CAutoTryCleanup(STATETYPE& refState) : + m_refState(refState) + { + SCAN_SCOPE_BEGIN; + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_SUPPORTS_DAC; + +#ifdef ENABLE_CONTRACTS_IMPL + // This is similar to ClrTryMarkerHolder. We're marking that its okay to throw on this thread now because + // we're within a try block. We fold this into here strictly for performance reasons... we have one + // stack-allocated object do the work. + m_pClrDebugState = GetClrDebugState(); + m_oldOkayToThrowValue = m_pClrDebugState->IsOkToThrow(); + m_pClrDebugState->SetOkToThrow(); +#endif + } + + DEBUG_NOINLINE ~CAutoTryCleanup() + { + SCAN_SCOPE_END; + WRAPPER_NO_CONTRACT; + + m_refState.CleanupTry(); + +#ifdef ENABLE_CONTRACTS_IMPL + // Restore the original OkayToThrow value since we're leaving the try block. + + m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue ); +#endif // ENABLE_CONTRACTS_IMPL + } + +protected: + STATETYPE& m_refState; + +#ifdef ENABLE_CONTRACTS_DATA +private: + BOOL m_oldOkayToThrowValue; + ClrDebugState *m_pClrDebugState; +#endif +}; + +// --------------------------------------------------------------------------- +// Throw/Catch macros +// +// Usage: +// +// EX_TRY +// { +// EX_THROW(HRException, (E_FAIL)); +// } +// EX_CATCH +// { +// Exception *e = GET_EXCEPTION(); +// EX_RETHROW; +// } +// EX_END_CATCH(RethrowTerminalExceptions, RethrowTransientExceptions or SwallowAllExceptions) +// +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// #NO_HOST_CPP_EH_ONLY +// +// The EX_CATCH* macros defined below can work one of two ways: +// 1. They catch all exceptions, both C++ and SEH exceptions. +// 2. They catch only C++ exceptions. +// +// Which way they are defined depends on what sort of handling of SEH +// exceptions, like AV's, you wish to have in your DLL. In general we +// do not typically want to catch and swallow AV's. +// +// By default, the macros catch all exceptions. This is how they work when +// compiled into the primary runtime DLL (clr.dll). This is reasonable for +// the CLR becuase it needs to also catch managed exceptions, which are SEH +// exceptions, and because that DLL also includes a vectored exception +// handler that will take down the process on any AV within clr.dll. +// +// But for uses of these macros outside of the CLR DLL there are other +// possibilities. If a DLL only uses facilities in Utilcode that throw the +// C++ exceptions defined above, and never needs to catch a managed exception, +// then that DLL should setup the macros to only catch C++ exceptions. That +// way, AV's are not accidentally swallowed and hidden. +// +// On the other hand, if a DLL needs to catch managed exceptions, then it has +// no choice but to also catch all SEH exceptions, including AV's. In that case +// the DLL should also include a vectored handler, like CLR.dll, to take the +// process down on an AV. +// +// The behavior difference is controled by NO_HOST_CPP_EH_ONLY. When defined, +// the EX_CATCH* macros only catch C++ exceptions. When not defined, they catch +// C++ and SEH exceptions. +// +// Note: use of NO_HOST_CPP_EH_ONLY is only valid outside the primary CLR DLLs. +// Thus it is an error to attempt to define it without also defining SELF_NO_HOST. +// --------------------------------------------------------------------------- + +#if defined(NO_HOST_CPP_EH_ONLY) && !defined(SELF_NO_HOST) +#error It is incorrect to attempt to have C++-only EH macros when hosted. This is only valid for components outside the runtime DLLs. +#endif + +//----------------------------------------------------------------------- +// EX_END_CATCH has a mandatory argument which is one of "RethrowTerminalExceptions", +// "RethrowTransientExceptions", or "SwallowAllExceptions". +// +// If an exception is considered "terminal" (e->IsTerminal()), it should normally +// be allowed to proceed. Hence, most of the time, you should use RethrowTerminalExceptions. +// +// In some cases you will want transient exceptions (terminal plus things like +// resource exhaustion) to proceed as well. Use RethrowTransientExceptions for this cas. +// +// If you have a good reason to use SwallowAllExceptions, (e.g. a hard COM interop boundary) +// use one of the higher level macros for this if available, or consider developing one. +// Otherwise, clearly document why you're swallowing terminal exceptions. Raw uses of +// SwallowAllExceptions will cause the cleanup police to come knocking on your door +// at some point. +// +// A lot of existing TRY's swallow terminals right now simply because there is +// backout code following the END_CATCH that has to be executed. The solution is +// to replace that backout code with holder objects. + +//----------------------------------------------------------------------- + +#define RethrowTransientExceptions \ + if (GET_EXCEPTION()->IsTransient()) \ + { \ + EX_RETHROW; \ + } \ + +// Don't use this - use RethrowCorruptingExceptions (see below) instead. +#define SwallowAllExceptions ; + +////////////////////////////////////////////////////////////////////// +// +// Corrupted State Exception Support +// +///////////////////////////////////////////////////////////////////// + +#ifdef FEATURE_CORRUPTING_EXCEPTIONS + +#define CORRUPTING_EXCEPTIONS_ONLY(expr) expr +#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr) ,expr + +// EX_END_CATCH has been modified to not swallow Corrupting Exceptions (CE) when one of the +// following arguments are passed to it: +// +// 1) RethrowTerminalExceptions - rethrows both terminal and corrupting exceptions +// 2) RethrowCorruptingExceptions - swallows all exceptions exception corrupting exceptions. This SHOULD BE USED instead of SwallowAllExceptions. +// 3) RethrowTerminalExceptionsEx - same as (1) but rethrow of CE can be controlled via a condition. +// 4) RethrowCorruptingExceptionsEx - same as (2) but rethrow of CE can be controlled via a condition. +// +// By default, if a CE is encountered when one of the above policies are applied, the runtime will +// ensure that the CE propagates up the stack and not get swallowed unless the developer chooses to override the behaviour. +// This can be done by using the "Ex" versions above that take a conditional which evaluates to a BOOL. In such a case, +// the CE will *only* be rethrown if the conditional evalutes to TRUE. For examples, refer to COMToCLRWorker or +// DispatchInfo::InvokeMember implementations. +// +// SET_CE_RETHROW_FLAG_FOR_EX_CATCH macros helps evaluate if the CE is to be rethrown or not. This has been redefined in +// Clrex.h to add the condition of evaluating the throwable as well (which is not available outside the VM folder). +// +// Passing FALSE as the second argument to IsProcessCorruptedStateException implies that SET_CE_RETHROW_FLAG_FOR_EX_CATCH +// will ensure that we dont rethrow SO and allow EX_ENDTRY to SO specific processing. If none is done, then EX_ENDTRY will +// rethrow SO. By that time stack has been reclaimed and thus, throwing SO will be safe. +// +// We also check the global override flag incase it has been set to force pre-V4 beahviour. "0" implies it has not +// been overriden. +#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) (((expr == TRUE) && \ + (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_legacyCorruptedStateExceptionsPolicy) == 0) && \ + IsProcessCorruptedStateException(GetCurrentExceptionCode(), FALSE))) + +// This rethrow policy can be used in EX_END_CATCH to swallow all exceptions except the corrupting ones. +// This macro can be used to rethrow the CE based upon a BOOL condition. +#define RethrowCorruptingExceptionsEx(expr) \ + if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \ + { \ + STATIC_CONTRACT_THROWS_TERMINAL; \ + EX_RETHROW; \ + } + +#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) \ + if (SET_CE_RETHROW_FLAG_FOR_EX_CATCH(shouldRethrowExpr)) \ + { \ + STATIC_CONTRACT_THROWS_TERMINAL; \ + aboutToRethrowExpr; \ + EX_RETHROW; \ + } + +#else // !FEATURE_CORRUPTING_EXCEPTIONS + +#define CORRUPTING_EXCEPTIONS_ONLY(expr) +#define COMMA_CORRUPTING_EXCEPTIONS_ONLY(expr) + +// When we dont have support for CE, just map it to SwallowAllExceptions +#define RethrowCorruptingExceptionsEx(expr) SwallowAllExceptions +#define RethrowCorruptingExceptionsExAndHookRethrow(shouldRethrowExpr, aboutToRethrowExpr) SwallowAllExceptions +#define SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr) !TRUE +#endif // FEATURE_CORRUPTING_EXCEPTIONS + +// Map to RethrowCorruptingExceptionsEx so that it does the "right" thing +#define RethrowCorruptingExceptions RethrowCorruptingExceptionsEx(TRUE) + +// This macro can be used to rethrow the CE based upon a BOOL condition. It will continue to rethrow terminal +// exceptions unconditionally. +#define RethrowTerminalExceptionsEx(expr) \ + if (GET_EXCEPTION()->IsTerminal() || \ + SET_CE_RETHROW_FLAG_FOR_EX_CATCH(expr)) \ + { \ + STATIC_CONTRACT_THROWS_TERMINAL; \ + EX_RETHROW; \ + } \ + + +// When applied to EX_END_CATCH, this policy will always rethrow Terminal and Corrupting exceptions if they are +// encountered. +#define RethrowTerminalExceptions RethrowTerminalExceptionsEx(TRUE) + +// Special define to be used in EEStartup that will also check for VM initialization before +// commencing on a path that may use the managed thread object. +#define RethrowTerminalExceptionsWithInitCheck \ + if ((g_fEEStarted == TRUE) && (GetThread() != NULL)) \ + { \ + RethrowTerminalExceptions \ + } + +#ifdef _DEBUG + +void ExThrowTrap(const char *fcn, const char *file, int line, const char *szType, HRESULT hr, const char *args); + +#define EX_THROW_DEBUG_TRAP(fcn, file, line, szType, hr, args) ExThrowTrap(fcn, file, line, szType, hr, args) + +#else + +#define EX_THROW_DEBUG_TRAP(fcn, file, line, szType, hr, args) + +#endif + +#define EX_THROW(_type, _args) \ + { \ + FAULT_NOT_FATAL(); \ + \ + _type * ___pExForExThrow = new _type _args ; \ + /* don't embed file names in retail to save space and avoid IP */ \ + /* a findstr /n will allow you to locate it in a pinch */ \ + STRESS_LOG3(LF_EH, LL_INFO100, "EX_THROW Type = 0x%x HR = 0x%x, " \ + INDEBUG(__FILE__) " line %d\n", _type::GetType(), \ + ___pExForExThrow->GetHR(), __LINE__); \ + EX_THROW_DEBUG_TRAP(__FUNCTION__, __FILE__, __LINE__, #_type, ___pExForExThrow->GetHR(), #_args); \ + PAL_CPP_THROW(_type *, ___pExForExThrow); \ + } + +//-------------------------------------------------------------------------------- +// Clones an exception into the current domain. Also handles special cases for +// OOM and other stuff. Making this a function so we don't inline all this logic +// every place we call EX_THROW_WITH_INNER. +//-------------------------------------------------------------------------------- +Exception *ExThrowWithInnerHelper(Exception *inner); + +// This macro will set the m_innerException into the newly created exception +// The passed in _type has to be derived from CLRException. You cannot put OOM +// as the inner exception. If we are throwing in OOM case, allocate more memory (this macro will clone) +// does not make any sense. +// +#define EX_THROW_WITH_INNER(_type, _args, _inner) \ + { \ + FAULT_NOT_FATAL(); \ + \ + Exception *_inner2 = ExThrowWithInnerHelper(_inner); \ + _type *___pExForExThrow = new _type _args ; \ + ___pExForExThrow->SetInnerException(_inner2); \ + STRESS_LOG3(LF_EH, LL_INFO100, "EX_THROW_WITH_INNER Type = 0x%x HR = 0x%x, " \ + INDEBUG(__FILE__) " line %d\n", _type::GetType(), \ + ___pExForExThrow->GetHR(), __LINE__); \ + EX_THROW_DEBUG_TRAP(__FUNCTION__, __FILE__, __LINE__, #_type, ___pExForExThrow->GetHR(), #_args); \ + PAL_CPP_THROW(_type *, ___pExForExThrow); \ + } + +//#define IsCLRException(ex) ((ex !=NULL) && ex->IsType(CLRException::GetType()) + +#define EX_TRY_IMPL EX_TRY_CUSTOM(Exception::HandlerState, , DelegatingException /* was SEHException*/) + +#define EX_TRY_CPP_ONLY EX_TRY_CUSTOM_CPP_ONLY(Exception::HandlerState, , DelegatingException /* was SEHException*/) + +#ifndef INCONTRACT +#ifdef ENABLE_CONTRACTS +#define INCONTRACT(x) x +#else +#define INCONTRACT(x) +#endif +#endif + +#define EX_TRY_CUSTOM(STATETYPE, STATEARG, DEFAULT_EXCEPTION_TYPE) \ + { \ + STATETYPE __state STATEARG; \ + typedef DEFAULT_EXCEPTION_TYPE __defaultException_t; \ + SCAN_EHMARKER(); \ + PAL_CPP_TRY \ + { \ + SCAN_EHMARKER_TRY(); \ + SCAN_EHMARKER(); \ + PAL_CPP_TRY \ + { \ + SCAN_EHMARKER_TRY(); \ + CAutoTryCleanup __autoCleanupTry(__state); \ + /* prevent annotations from being dropped by optimizations in debug */ \ + INDEBUG(static bool __alwayszero;) \ + INDEBUG(VolatileLoad(&__alwayszero);) \ + { \ + /* Disallow returns to make exception handling work. */ \ + /* Some work is done after the catch, see EX_ENDTRY. */ \ + DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ + EX_TRY_HOLDER \ + + +#define EX_CATCH_IMPL_EX(DerivedExceptionClass) \ + DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ + } \ + SCAN_EHMARKER_END_TRY(); \ + } \ + PAL_CPP_CATCH_DERIVED (DerivedExceptionClass, __pExceptionRaw) \ + { \ + SCAN_EHMARKER_CATCH(); \ + __state.SetCaughtCxx(); \ + __state.m_pExceptionPtr = __pExceptionRaw; \ + SCAN_EHMARKER_END_CATCH(); \ + SCAN_IGNORE_THROW_MARKER; \ + PAL_CPP_RETHROW; \ + } \ + PAL_CPP_ENDTRY \ + SCAN_EHMARKER_END_TRY(); \ + } \ + PAL_CPP_CATCH_ALL \ + { \ + SCAN_EHMARKER_CATCH(); \ + __defaultException_t __defaultException; \ + CHECK::ResetAssert(); \ + ExceptionHolder __pException(__state.m_pExceptionPtr); \ + /* work around unreachable code warning */ \ + if (true) { \ + DEBUG_ASSURE_NO_RETURN_BEGIN(EX_CATCH) \ + /* don't embed file names in retail to save space and avoid IP */ \ + /* a findstr /n will allow you to locate it in a pinch */ \ + __state.SetupCatch(INDEBUG_COMMA(__FILE__) __LINE__); \ + +#define EX_CATCH_IMPL EX_CATCH_IMPL_EX(Exception) + +#define EX_TRY_CUSTOM_CPP_ONLY(STATETYPE, STATEARG, DEFAULT_EXCEPTION_TYPE) \ + { \ + STATETYPE __state STATEARG; \ + typedef DEFAULT_EXCEPTION_TYPE __defaultException_t; \ + SCAN_EHMARKER(); \ + PAL_CPP_TRY \ + { \ + SCAN_EHMARKER_TRY(); \ + CAutoTryCleanup __autoCleanupTry(__state); \ + /* prevent annotations from being dropped by optimizations in debug */ \ + INDEBUG(static bool __alwayszero;) \ + INDEBUG(VolatileLoad(&__alwayszero);) \ + { \ + /* Disallow returns to make exception handling work. */ \ + /* Some work is done after the catch, see EX_ENDTRY. */ \ + DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ + +#define EX_CATCH_IMPL_CPP_ONLY \ + DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ + } \ + SCAN_EHMARKER_END_TRY(); \ + } \ + PAL_CPP_CATCH_DERIVED (Exception, __pExceptionRaw) \ + { \ + SCAN_EHMARKER_CATCH(); \ + __state.SetCaughtCxx(); \ + __state.m_pExceptionPtr = __pExceptionRaw; \ + SCAN_EHMARKER_END_CATCH(); \ + SCAN_IGNORE_THROW_MARKER; \ + __defaultException_t __defaultException; \ + CHECK::ResetAssert(); \ + ExceptionHolder __pException(__state.m_pExceptionPtr); \ + /* work around unreachable code warning */ \ + if (true) { \ + DEBUG_ASSURE_NO_RETURN_BEGIN(EX_CATCH) \ + /* don't embed file names in retail to save space and avoid IP */ \ + /* a findstr /n will allow you to locate it in a pinch */ \ + __state.SetupCatch(INDEBUG_COMMA(__FILE__) __LINE__); \ + + +// Here we finally define the EX_CATCH* macros that will be used throughout the system. +// These can catch C++ and SEH exceptions, or just C++ exceptions. +// See code:NO_HOST_CPP_EH_ONLY for more details. +// +// Note: we make it illegal to use forms that are redundant with the basic EX_CATCH +// version. I.e., in the C++ & SEH version, EX_CATCH_CPP_AND_SEH is the same as EX_CATCH. +// Likewise, in the C++ only version, EX_CATCH_CPP_ONLY is redundant with EX_CATCH. + +#ifndef NO_HOST_CPP_EH_ONLY +#define EX_TRY EX_TRY_IMPL +#define EX_CATCH EX_CATCH_IMPL +#define EX_CATCH_EX EX_CATCH_IMPL_EX +#define EX_CATCH_CPP_ONLY EX_CATCH_IMPL_CPP_ONLY +#define EX_CATCH_CPP_AND_SEH Dont_Use_EX_CATCH_CPP_AND_SEH +#else +#define EX_TRY EX_TRY_CPP_ONLY +#define EX_CATCH EX_CATCH_IMPL_CPP_ONLY +#define EX_CATCH_CPP_ONLY Dont_Use_EX_CATCH_CPP_ONLY +#define EX_CATCH_CPP_AND_SEH EX_CATCH_IMPL + +// Note: at this time we don't have a use case for EX_CATCH_EX, and we do not have +// the C++-only version of the implementation available. Thus we disallow its use at this time. +// If a real use case arises then we should go ahead and enable this. +#define EX_CATCH_EX Dont_Use_EX_CATCH_EX +#endif + +#define EX_END_CATCH_UNREACHABLE \ + DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ + } \ + SCAN_EHMARKER_END_CATCH(); \ + UNREACHABLE(); \ + } \ + PAL_CPP_ENDTRY \ + } \ + + +// "terminalexceptionpolicy" must be one of "RethrowTerminalExceptions", +// "RethrowTransientExceptions", or "SwallowAllExceptions" + +#define EX_END_CATCH(terminalexceptionpolicy) \ + terminalexceptionpolicy; \ + __state.SucceedCatch(); \ + DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ + } \ + SCAN_EHMARKER_END_CATCH(); \ + } \ + EX_ENDTRY \ + } \ + + +#define EX_END_CATCH_FOR_HOOK \ + __state.SucceedCatch(); \ + DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ + ANNOTATION_HANDLER_END; \ + } \ + SCAN_EHMARKER_END_CATCH(); \ + } \ + EX_ENDTRY + +#define EX_ENDTRY \ + PAL_CPP_ENDTRY + +#define EX_RETHROW \ + { \ + __pException.SuppressRelease(); \ + PAL_CPP_RETHROW; \ + } \ + + // Define a copy of GET_EXCEPTION() that will not be redefined by clrex.h +#define GET_EXCEPTION() (__pException == NULL ? &__defaultException : __pException.GetValue()) +#define EXTRACT_EXCEPTION() (__pException.Extract()) + + +//============================================================================== +// High-level macros for common uses of EX_TRY. Try using these rather +// than the raw EX_TRY constructs. +//============================================================================== + +//=================================================================================== +// Macro for converting exceptions into HR internally. Unlike EX_CATCH_HRESULT, +// it does not set up IErrorInfo on the current thread. +// +// Usage: +// +// HRESULT hr = S_OK; +// EX_TRY +// +// EX_CATCH_HRESULT_NO_ERRORINFO(hr); +// return hr; +// +// Comments: +// Since IErrorInfo is not set up, this does not require COM interop to be started. +//=================================================================================== + +#define EX_CATCH_HRESULT_NO_ERRORINFO(_hr) \ + EX_CATCH \ + { \ + (_hr) = GET_EXCEPTION()->GetHR(); \ + _ASSERTE(FAILED(_hr)); \ + } \ + EX_END_CATCH(SwallowAllExceptions) + + +//=================================================================================== +// Macro for catching managed exception object. +// +// Usage: +// +// OBJECTREF pThrowable = NULL; +// EX_TRY +// +// EX_CATCH_THROWABLE(&pThrowable); +// +//=================================================================================== + +#define EX_CATCH_THROWABLE(ppThrowable) \ + EX_CATCH \ + { \ + *ppThrowable = GET_THROWABLE(); \ + } \ + EX_END_CATCH(SwallowAllExceptions) + + +#ifdef FEATURE_COMINTEROP + +//=================================================================================== +// Macro for defining external entrypoints such as COM interop boundaries. +// The boundary will catch all exceptions (including terminals) and convert +// them into HR/IErrorInfo pairs as appropriate. +// +// Usage: +// +// HRESULT hr = S_OK; +// EX_TRY +// +// EX_CATCH_HRESULT(hr); +// return hr; +// +// Comments: +// Note that IErrorInfo will automatically be set up on the thread if appropriate. +//=================================================================================== + +#define EX_CATCH_HRESULT(_hr) \ + EX_CATCH \ + { \ + (_hr) = GET_EXCEPTION()->GetHR(); \ + _ASSERTE(FAILED(_hr)); \ + IErrorInfo *pErr = GET_EXCEPTION()->GetErrorInfo(); \ + if (pErr != NULL) \ + { \ + SetErrorInfo(0, pErr); \ + pErr->Release(); \ + } \ + } \ + EX_END_CATCH(SwallowAllExceptions) + +//=================================================================================== +// Macro to make conditional catching more succinct. +// +// Usage: +// +// EX_TRY +// ... +// EX_CATCH_HRESULT_IF(IsHRESULTForExceptionKind(GET_EXCEPTION()->GetHR(), kFileNotFoundException)); +//=================================================================================== + +#define EX_CATCH_HRESULT_IF(HR, ...) \ + EX_CATCH \ + { \ + (HR) = GET_EXCEPTION()->GetHR(); \ + \ + /* Rethrow if condition is false. */ \ + if (!(__VA_ARGS__)) \ + EX_RETHROW; \ + \ + _ASSERTE(FAILED(HR)); \ + IErrorInfo *pErr = GET_EXCEPTION()->GetErrorInfo(); \ + if (pErr != NULL) \ + { \ + SetErrorInfo(0, pErr); \ + pErr->Release(); \ + } \ + } \ + EX_END_CATCH(SwallowAllExceptions) + +#else // FEATURE_COMINTEROP + +#define EX_CATCH_HRESULT(_hr) EX_CATCH_HRESULT_NO_ERRORINFO(_hr) + +#endif // FEATURE_COMINTEROP + +//=================================================================================== +// Macro for containing normal exceptions but letting terminal exceptions continue to propagate. +// +// Usage: +// +// EX_TRY +// { +// ...your stuff... +// } +// EX_SWALLOW_NONTERMINAL +// +// Remember, terminal exceptions (such as ThreadAbort) will still throw out of this +// block. So don't use this as a substitute for exception-safe cleanup! +//=================================================================================== + +#define EX_SWALLOW_NONTERMINAL \ + EX_CATCH \ + { \ + } \ + EX_END_CATCH(RethrowTerminalExceptions) \ + + +//=================================================================================== +// Macro for containing normal exceptions but letting transient exceptions continue to propagate. +// +// Usage: +// +// EX_TRY +// { +// ...your stuff... +// } +// EX_SWALLOW_NONTRANSIENT +// +// Terminal exceptions (such as ThreadAbort and OutOfMemory) will still throw out of this +// block. So don't use this as a substitute for exception-safe cleanup! +//=================================================================================== + +#define EX_SWALLOW_NONTRANSIENT \ + EX_CATCH \ + { \ + } \ + EX_END_CATCH(RethrowTransientExceptions) \ + + +//=================================================================================== +// Macro for observing or wrapping exceptions in flight. +// +// Usage: +// +// EX_TRY +// { +// ... your stuff ... +// } +// EX_HOOK +// { +// ... your stuff ... +// } +// EX_END_HOOK +// ... control will never get here ... +// +// +// EX_HOOK is like EX_CATCH except that you can't prevent the +// exception from being rethrown. You can throw a new exception inside the hook +// (for example, if you want to wrap the exception in flight with your own). +// But if control reaches the end of the hook, the original exception gets rethrown. +// +// Avoid using EX_HOOK for conditional backout if a destructor-based holder +// will suffice. Because these macros are implemented on top of SEH, using them will +// prevent the use of holders anywhere else inside the same function. That is, instead +// of saying this: +// +// EX_TRY // DON'T DO THIS +// { +// thing = new Thing(); +// blah +// } +// EX_HOOK +// { +// delete thing; // if it failed, we don't want to keep the Thing. +// } +// EX_END_HOOK +// +// do this: +// +// Holder thing = new Thing(); //DO THIS INSTEAD +// blah +// // If we got here, we succeeded. So tell holder we want to keep the thing. +// thing.SuppressRelease(); +// +// We won't rethrow the exception if it is a Stack Overflow exception. Instead, we'll throw a new +// exception. This will allow the stack to unwind point, and so we won't be jeopardizing a +// second stack overflow. +//=================================================================================== +#define EX_HOOK \ + EX_CATCH \ + { \ + +#define EX_END_HOOK \ + } \ + ANNOTATION_HANDLER_END; \ + EX_RETHROW; \ + EX_END_CATCH_FOR_HOOK; \ + } + +// --------------------------------------------------------------------------- +// Inline implementations. Pay no attention to that man behind the curtain. +// --------------------------------------------------------------------------- + +inline Exception::HandlerState::HandlerState() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SUPPORTS_DAC; + + m_dwFlags = 0; + m_pExceptionPtr = NULL; + +#if defined(STACK_GUARDS_DEBUG) && defined(ENABLE_CONTRACTS_IMPL) + // If we have a debug state, use its setting for SO tolerance. The default + // is SO-tolerant if we have no debug state. Can't probe w/o debug state and + // can't enter SO-interolant mode w/o probing. + GetClrDebugState(); +#endif +} + +inline void Exception::HandlerState::CleanupTry() +{ + LIMITED_METHOD_DAC_CONTRACT; +} + +inline void Exception::HandlerState::SetupCatch(INDEBUG_COMMA(__in_z const char * szFile) int lineNum) +{ + WRAPPER_NO_CONTRACT; + + /* don't embed file names in retail to save space and avoid IP */ + /* a findstr /n will allow you to locate it in a pinch */ +#ifdef _DEBUG + STRESS_LOG2(LF_EH, LL_INFO100, "EX_CATCH %s line %d\n", szFile, lineNum); +#else + STRESS_LOG1(LF_EH, LL_INFO100, "EX_CATCH line %d\n", lineNum); +#endif + + SetCaught(); +} + +inline void Exception::HandlerState::SucceedCatch() +{ + LIMITED_METHOD_DAC_CONTRACT; +} + +inline HRException::HRException() + : m_hr(E_UNEXPECTED) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; +} + +inline HRException::HRException(HRESULT hr) + : m_hr(hr) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + // Catchers assume only failing hresults + _ASSERTE(FAILED(hr)); +} + +inline HRMsgException::HRMsgException() + : HRException() +{ + LIMITED_METHOD_CONTRACT; +} + +inline HRMsgException::HRMsgException(HRESULT hr, SString const &s) + : HRException(hr), m_msg(s) +{ + WRAPPER_NO_CONTRACT; +} + +inline COMException::COMException() + : HRException(), + m_pErrorInfo(NULL) +{ + WRAPPER_NO_CONTRACT; +} + +inline COMException::COMException(HRESULT hr) + : HRException(hr), + m_pErrorInfo(NULL) +{ + LIMITED_METHOD_CONTRACT; +} + +inline COMException::COMException(HRESULT hr, IErrorInfo *pErrorInfo) + : HRException(hr), + m_pErrorInfo(pErrorInfo) +{ + LIMITED_METHOD_CONTRACT; +} + +inline SEHException::SEHException() +{ + LIMITED_METHOD_CONTRACT; + memset(&m_exception, 0, sizeof(EXCEPTION_RECORD)); +} + +inline SEHException::SEHException(EXCEPTION_RECORD *pointers, T_CONTEXT *pContext) +{ + LIMITED_METHOD_CONTRACT; + memcpy(&m_exception, pointers, sizeof(EXCEPTION_RECORD)); +} + +// The exception throwing helpers are intentionally not inlined +// Exception throwing is a rare slow codepath that should be optimized for code size + +void DECLSPEC_NORETURN ThrowHR(HRESULT hr); +void DECLSPEC_NORETURN ThrowHR(HRESULT hr, SString const &msg); +void DECLSPEC_NORETURN ThrowHR(HRESULT hr, UINT uText); +void DECLSPEC_NORETURN ThrowWin32(DWORD err); +void DECLSPEC_NORETURN ThrowLastError(); +void DECLSPEC_NORETURN ThrowOutOfMemory(); +void DECLSPEC_NORETURN ThrowStackOverflow(); + +#undef IfFailThrow +inline HRESULT IfFailThrow(HRESULT hr) +{ + WRAPPER_NO_CONTRACT; + + if (FAILED(hr)) + { + ThrowHR(hr); + } + + return hr; +} + +inline HRESULT IfFailThrow(HRESULT hr, SString &msg) +{ + WRAPPER_NO_CONTRACT; + + if (FAILED(hr)) + { + ThrowHR(hr, msg); + } + + return hr; +} + +inline HRESULT IfTransientFailThrow(HRESULT hr) +{ + WRAPPER_NO_CONTRACT; + + if (FAILED(hr) && Exception::IsTransient(hr)) + { + ThrowHR(hr); + } + + return hr; +} + +// Set if fatal error (like stack overflow or out of memory) occurred in this process. +GVAL_DECL(HRESULT, g_hrFatalError); + +#endif // _EX_H_ diff --git a/lib/coreclr/src/inc/factory.h b/lib/coreclr/src/inc/factory.h new file mode 100644 index 0000000000..ae618fe2dd --- /dev/null +++ b/lib/coreclr/src/inc/factory.h @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _FACTORY_H_ +#define _FACTORY_H_ + +template +class Factory +{ +public: + virtual PRODUCT* Create() = 0; + virtual ~Factory() {} +}; + +template +class InlineFactory : public Factory +{ +public: + InlineFactory() : m_next(NULL), m_cProduct(0) { WRAPPER_NO_CONTRACT; } + ~InlineFactory() { WRAPPER_NO_CONTRACT; if (m_next) delete m_next; } + PRODUCT* Create(); + +private: + InlineFactory* GetNext() + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + if (m_next == NULL) + { + m_next = new (nothrow) InlineFactory(); + } + + return m_next; + } + + InlineFactory* m_next; + PRODUCT m_product[MAX_FACTORY_PRODUCT]; + INT32 m_cProduct; +}; + +#include "factory.inl" + +#endif + diff --git a/lib/coreclr/src/inc/factory.inl b/lib/coreclr/src/inc/factory.inl new file mode 100644 index 0000000000..b49b90a749 --- /dev/null +++ b/lib/coreclr/src/inc/factory.inl @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _FACTORY_INL_ +#define _FACTORY_INL_ + +#include "factory.h" + +template +PRODUCT* InlineFactory::Create() +{ + WRAPPER_NO_CONTRACT; + + if (m_cProduct == MAX_FACTORY_PRODUCT) + { + InlineFactory* pNext = GetNext(); + if (pNext) + { + return pNext->Create(); + } + else + { + return NULL; + } + } + + return &m_product[m_cProduct++]; +} + +#endif + diff --git a/lib/coreclr/src/inc/fixuppointer.h b/lib/coreclr/src/inc/fixuppointer.h new file mode 100644 index 0000000000..18886c0f54 --- /dev/null +++ b/lib/coreclr/src/inc/fixuppointer.h @@ -0,0 +1,1090 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/*****************************************************************************\ +* * +* FixupPointer.h - Fixup pointer holder types * +* * +\*****************************************************************************/ + +#ifndef _FIXUPPOINTER_H +#define _FIXUPPOINTER_H + +#include "daccess.h" + +#ifdef FEATURE_PREJIT + +//---------------------------------------------------------------------------- +// RelativePointer is pointer encoded as relative offset. It is used to reduce size of +// relocation section in NGen images. Conversion from/to RelativePointer needs +// address of the pointer ("this") converted to TADDR passed in from outside. +// Converting "this" to TADDR is not possible in the DAC transparently because +// DAC is based on exact pointers, not ranges. +// There are several flavors of conversions from/to RelativePointer: +// - GetValue/SetValue: The most common version. Assumes that the pointer is not NULL. +// - GetValueMaybeNull/SetValueMaybeNull: Pointer can be NULL. +// - GetValueAtPtr: Static version of GetValue. It is +// meant to simplify access to arrays of RelativePointers. +// - GetValueMaybeNullAtPtr +template +class RelativePointer +{ +public: + + static constexpr bool isRelative = true; + typedef PTR_TYPE type; + +#ifndef DACCESS_COMPILE + RelativePointer() + { + m_delta = (TADDR)NULL; + + _ASSERTE (IsNull()); + } +#else // DACCESS_COMPILE + RelativePointer() =delete; +#endif // DACCESS_COMPILE + + // Implicit copy/move is not allowed + // Bitwise copy is implemented by BitwiseCopyTo method + RelativePointer(const RelativePointer &) =delete; + RelativePointer(RelativePointer &&) =delete; + RelativePointer& operator = (const RelativePointer &) =delete; + RelativePointer& operator = (RelativePointer &&) =delete; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + // Pointer pointing to itself is treated as NULL + return m_delta == (TADDR)NULL; + } + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + PTR_TYPE GetValue(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + return dac_cast(base + m_delta); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValue() const + { + LIMITED_METHOD_CONTRACT; + return GetValue((TADDR)this); + } +#endif + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValue(base); + } + + // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + // Cache local copy of delta to avoid races when the value is changing under us. + TADDR delta = m_delta; + + if (delta == 0) + return NULL; + + return dac_cast(base + delta); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. The pointer can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return GetValueMaybeNull((TADDR)this); + } +#endif + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueMaybeNull(base); + } + +#ifndef DACCESS_COMPILE + // Set encoded value of the pointer. Assumes that the value is not NULL. + FORCEINLINE void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + PRECONDITION(addr != NULL); + m_delta = (TADDR)addr - (TADDR)this; + } + + // Set encoded value of the pointer. The value can be NULL. + void SetValueMaybeNull(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + if (addr == NULL) + m_delta = NULL; + else + m_delta = (TADDR)addr - (TADDR)base; + } + + // Set encoded value of the pointer. The value can be NULL. + FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValueMaybeNull((TADDR)this, addr); + } + + FORCEINLINE void SetValueVolatile(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } +#endif + +#ifndef DACCESS_COMPILE + void BitwiseCopyTo(RelativePointer &dest) const + { + dest.m_delta = m_delta; + } +#endif // DACCESS_COMPILE + + static TADDR GetRelativeMaybeNull(TADDR base, TADDR addr) + { + LIMITED_METHOD_DAC_CONTRACT; + if (addr == NULL) + { + return NULL; + } + else + { + return addr - base; + } + } + + static TADDR GetRelative(TADDR base, TADDR addr) + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(addr != NULL); + return addr - base; + } + +private: +#ifndef DACCESS_COMPILE + Volatile m_delta; +#else + TADDR m_delta; +#endif +}; + +//---------------------------------------------------------------------------- +// FixupPointer is pointer with optional indirection. It is used to reduce number +// of private pages in NGen images - cross-module pointers that written to at runtime +// are packed together and accessed via indirection. +// +// The direct flavor (lowest bit of m_addr is cleared) is user for intra-module pointers +// in NGen images, and in datastructuters allocated at runtime. +// +// The indirect mode (lowest bit of m_addr is set) is used for cross-module pointers +// in NGen images. +// + +// Friendly name for lowest bit that marks the indirection +#define FIXUP_POINTER_INDIRECTION 1 + +template +class FixupPointer +{ +public: + + static constexpr bool isRelative = false; + typedef PTR_TYPE type; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_addr == 0; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + FORCEINLINE BOOL IsTagged() const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0; + return FALSE; + } + + // Returns value of the encoded pointer. + FORCEINLINE PTR_TYPE GetValue() const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION); + return dac_cast(addr); + } + + // Returns value of the encoded pointer. + FORCEINLINE PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValue(); + } + +#ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. + PTR_TYPE * GetValuePtr() const + { + LIMITED_METHOD_CONTRACT; + TADDR addr = m_addr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); + return (PTR_TYPE *)&m_addr; + } +#endif // !DACCESS_COMPILE + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValue(); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueMaybeNull(); + } + + // Returns value of the encoded pointer. + // Allows the value to be tagged. + FORCEINLINE TADDR GetValueMaybeTagged() const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION); + return addr; + } + +#ifndef DACCESS_COMPILE + void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_addr = dac_cast(addr); + } + + void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } +#endif // !DACCESS_COMPILE + +private: + TADDR m_addr; +}; + +//---------------------------------------------------------------------------- +// RelativeFixupPointer is combination of RelativePointer and FixupPointer +template +class RelativeFixupPointer +{ +public: + + static constexpr bool isRelative = true; + typedef PTR_TYPE type; + +#ifndef DACCESS_COMPILE + RelativeFixupPointer() + { + SetValueMaybeNull(NULL); + } +#else // DACCESS_COMPILE + RelativeFixupPointer() =delete; +#endif // DACCESS_COMPILE + + // Implicit copy/move is not allowed + RelativeFixupPointer(const RelativeFixupPointer &) =delete; + RelativeFixupPointer(RelativeFixupPointer &&) =delete; + RelativeFixupPointer& operator = (const RelativeFixupPointer &) =delete; + RelativeFixupPointer& operator = (RelativeFixupPointer &&) =delete; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + // Pointer pointing to itself is treated as NULL + return m_delta == (TADDR)NULL; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + FORCEINLINE BOOL IsTagged(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = base + m_delta; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + return (*PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION) & 1) != 0; + return FALSE; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Ignores isIndirect and offset values. + FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsTagged(base); + } + +#ifndef DACCESS_COMPILE + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE BOOL IsTagged() const + { + LIMITED_METHOD_CONTRACT; + return IsTagged((TADDR)this); + } +#endif // !DACCESS_COMPILE + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + FORCEINLINE PTR_TYPE GetValue(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + PRECONDITION(!IsTagged(base)); + TADDR addr = base + m_delta; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION); + return dac_cast(addr); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValue() const + { + LIMITED_METHOD_CONTRACT; + return GetValue((TADDR)this); + } +#endif + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValue(base); + } + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + // Ignores isIndirect and offset values. + FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueAtPtr(base); + } + + // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsTagged(base)); + + // Cache local copy of delta to avoid races when the value is changing under us. + TADDR delta = m_delta; + + if (delta == 0) + return NULL; + + TADDR addr = base + delta; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION); + return dac_cast(addr); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. The pointer can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return GetValueMaybeNull((TADDR)this); + } +#endif + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueMaybeNull(base); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + // Ignores isIndirect and offset values. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueMaybeNullAtPtr(base); + } + +#ifndef DACCESS_COMPILE + // Set encoded value of the pointer. Assumes that the value is not NULL. + FORCEINLINE void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + PRECONDITION(addr != NULL); + m_delta = dac_cast(addr) - (TADDR)this; + } + + // Set encoded value of the pointer. The value can be NULL. + void SetValueMaybeNull(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + if (addr == NULL) + m_delta = NULL; + else + m_delta = dac_cast(addr) - (TADDR)base; + } + + // Set encoded value of the pointer. The value can be NULL. + FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValueMaybeNull((TADDR)this, addr); + } +#endif + +#ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. + PTR_TYPE * GetValuePtr() const + { + LIMITED_METHOD_CONTRACT; + TADDR addr = ((TADDR)this) + m_delta; + _ASSERTE((addr & FIXUP_POINTER_INDIRECTION) != 0); + return (PTR_TYPE *)(addr - FIXUP_POINTER_INDIRECTION); + } + + // Returns the pointer to the indirection cell. + // Ignores isIndirect and offset values. + PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + return GetValuePtr(); + } +#endif // !DACCESS_COMPILE + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Allows the value to be tagged. + FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + TADDR addr = base + m_delta; + if ((addr & FIXUP_POINTER_INDIRECTION) != 0) + addr = *PTR_TADDR(addr - FIXUP_POINTER_INDIRECTION); + return addr; + } + + // Returns whether pointer is indirect. Assumes that the value is not NULL. + bool IsIndirectPtr(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + + TADDR addr = base + m_delta; + + return (addr & FIXUP_POINTER_INDIRECTION) != 0; + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtr() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtr((TADDR)this); + } + + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Ignores isIndirect and offset values. + bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsIndirectPtr(); + } +#endif + + // Returns whether pointer is indirect. The value can be NULL. + bool IsIndirectPtrMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + if (m_delta == 0) + return false; + + return IsIndirectPtr(base); + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. The value can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtrMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtrMaybeNull((TADDR)this); + } + + // Returns whether pointer is indirect. The value can be NULL. + // Ignores isIndirect and offset values. + bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + return IsIndirectPtrMaybeNull(); + } +#endif + +private: +#ifndef DACCESS_COMPILE + Volatile m_delta; +#else + TADDR m_delta; +#endif +}; + +// Fixup used for RelativePointer +#define IMAGE_REL_BASED_RelativePointer IMAGE_REL_BASED_RELPTR + +#endif // FEATURE_PREJIT + +//---------------------------------------------------------------------------- +// PlainPointer is simple pointer wrapper to support compilation without indirections +// This is useful for building size-constrained runtime without NGen support. +template +class PlainPointer +{ +public: + + static constexpr bool isRelative = false; + typedef PTR_TYPE type; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_ptr == NULL; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + BOOL IsTagged(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return FALSE; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + BOOL IsTagged() const + { + LIMITED_METHOD_DAC_CONTRACT; + return FALSE; + } + + // Returns value of the encoded pointer. + PTR_TYPE GetValue() const + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast(m_ptr); + } + +#ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. + PTR_TYPE * GetValuePtr() const + { + LIMITED_METHOD_CONTRACT; + return (PTR_TYPE *)&m_ptr; + } +#endif // !DACCESS_COMPILE + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + PTR_TYPE GetValue(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast(m_ptr); + } + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValue(base); + } + + // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast(m_ptr); + } + + // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast(m_ptr); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueMaybeNull(base); + } + + // Returns value of the encoded pointer. + // Allows the value to be tagged. + FORCEINLINE TADDR GetValueMaybeTagged() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_ptr; + } + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Allows the value to be tagged. + FORCEINLINE TADDR GetValueMaybeTagged(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_ptr; + } + + // Returns whether pointer is indirect. Assumes that the value is not NULL. + bool IsIndirectPtr(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return FALSE; + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtr() const + { + LIMITED_METHOD_CONTRACT; + return FALSE; + } +#endif + + // Returns whether pointer is indirect. The value can be NULL. + bool IsIndirectPtrMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + return FALSE; + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. The value can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + bool IsIndirectPtrMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return FALSE; + } +#endif + +#ifndef DACCESS_COMPILE + void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_ptr = dac_cast(addr); + } + + // Set encoded value of the pointer. Assumes that the value is not NULL. + void SetValue(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_ptr = dac_cast(addr); + } + + // Static version of SetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static void SetValueAtPtr(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + dac_cast)>(base)->SetValue(base, addr); + } + + // Set encoded value of the pointer. The value can be NULL. + void SetValueMaybeNull(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_ptr = dac_cast(addr); + } + + // Set encoded value of the pointer. The value can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + return SetValueMaybeNull((TADDR)this, addr); + } + + // Static version of SetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static void SetValueMaybeNullAtPtr(TADDR base, PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + dac_cast)>(base)->SetValueMaybeNull(base, addr); + } + + FORCEINLINE void SetValueVolatile(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + VolatileStore((PTR_TYPE *)(&m_ptr), addr); + } +#endif + + static TADDR GetRelativeMaybeNull(TADDR base, TADDR addr) + { + LIMITED_METHOD_DAC_CONTRACT; + return addr; + } + + static TADDR GetRelative(TADDR base, TADDR addr) + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(addr != NULL); + return addr; + } + +private: + TADDR m_ptr; +}; + +#ifndef FEATURE_PREJIT + +#define FixupPointer PlainPointer +#define RelativePointer PlainPointer +#define RelativeFixupPointer PlainPointer + +#endif // !FEATURE_PREJIT + +//---------------------------------------------------------------------------- +// RelativePointer32 is pointer encoded as relative 32-bit offset. It is used +// to reduce both the size of the pointer itself as well as size of relocation +// section for pointers that live exlusively in NGen images. +template +class RelativePointer32 +{ +public: + + static constexpr bool isRelative = true; + typedef PTR_TYPE type; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + // Pointer pointing to itself is treated as NULL + return m_delta == 0; + } + + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + PTR_TYPE GetValue(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + PRECONDITION(!IsNull()); + return dac_cast(base + m_delta); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. Assumes that the pointer is not NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValue() const + { + LIMITED_METHOD_CONTRACT; + return GetValue((TADDR)this); + } +#endif + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValue(base); + } + + // Returns value of the encoded pointer. The pointer can be NULL. + PTR_TYPE GetValueMaybeNull(TADDR base) const + { + LIMITED_METHOD_DAC_CONTRACT; + + // Cache local copy of delta to avoid races when the value is changing under us. + TADDR delta = m_delta; + + if (delta == 0) + return NULL; + + return dac_cast(base + delta); + } + +#ifndef DACCESS_COMPILE + // Returns value of the encoded pointer. The pointer can be NULL. + // Does not need explicit base and thus can be used in non-DAC builds only. + FORCEINLINE PTR_TYPE GetValueMaybeNull() const + { + LIMITED_METHOD_CONTRACT; + return GetValueMaybeNull((TADDR)this); + } +#endif + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtr(TADDR base) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueMaybeNull(base); + } + +private: + INT32 m_delta; +}; + +//---------------------------------------------------------------------------- +// IndirectPointer is pointer with optional indirection, similar to FixupPointer and RelativeFixupPointer. +// +// In comparison to FixupPointer, IndirectPointer's indirection is handled from outside by isIndirect flag. +// In comparison to RelativeFixupPointer, IndirectPointer's offset is a constant, +// while RelativeFixupPointer's offset is an address. +// +// IndirectPointer can contain NULL only if it is not indirect. +// +template +class IndirectPointer +{ +public: + + static constexpr bool isRelative = false; + typedef PTR_TYPE type; + + // Returns whether the encoded pointer is NULL. + BOOL IsNull() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_addr == (TADDR)NULL; + } + + // Returns whether the indirection cell contain fixup that has not been converted to real pointer yet. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE BOOL IsTaggedIndirect(TADDR base, bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + return (*PTR_TADDR(addr + offset) & 1) != 0; + } + return FALSE; + } + + // Returns value of the encoded pointer. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE PTR_TYPE GetValueIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_DAC_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + addr = *PTR_TADDR(addr + offset); + } + return dac_cast(addr); + } + +#ifndef DACCESS_COMPILE + // Returns the pointer to the indirection cell. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + PTR_TYPE * GetValuePtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + TADDR addr = m_addr; + if (isIndirect) + { + _ASSERTE(!IsNull()); + return (PTR_TYPE *)(addr + offset); + } + return (PTR_TYPE *)&m_addr; + } +#endif // !DACCESS_COMPILE + + // Static version of GetValue. It is meant to simplify access to arrays of pointers. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE static PTR_TYPE GetValueAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return dac_cast)>(base)->GetValueIndirect(isIndirect, offset); + } + + // Static version of GetValueMaybeNull. It is meant to simplify access to arrays of pointers. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + FORCEINLINE static PTR_TYPE GetValueMaybeNullAtPtrIndirect(TADDR base, bool isIndirect, intptr_t offset) + { + LIMITED_METHOD_DAC_CONTRACT; + return GetValueAtPtrIndirect(base, isIndirect, offset); + } + +#ifndef DACCESS_COMPILE + // Returns whether pointer is indirect. Assumes that the value is not NULL. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + bool IsIndirectPtrIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + if (isIndirect) + _ASSERTE(!IsNull()); + return isIndirect; + } + + // Returns whether pointer is indirect. The value can be NULL. + // Uses isIndirect to identify, whether pointer is indirect or not. If it is, uses offset. + bool IsIndirectPtrMaybeNullIndirect(bool isIndirect, intptr_t offset) const + { + LIMITED_METHOD_CONTRACT; + return IsIndirectPtrIndirect(isIndirect, offset); + } +#endif // !DACCESS_COMPILE + +#ifndef DACCESS_COMPILE + // Set encoded value of the pointer. Assumes that the value is not NULL. + void SetValue(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + m_addr = dac_cast(addr); + } + + // Set encoded value of the pointer. The value can be NULL. + void SetValueMaybeNull(PTR_TYPE addr) + { + LIMITED_METHOD_CONTRACT; + SetValue(addr); + } +#endif // !DACCESS_COMPILE + +private: + TADDR m_addr; +}; + +template +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base; + + if (isMaybeNull) + { + return PT::GetValueMaybeNullAtPtr(dac_cast(base) + offset); + } + else + { + return PT::GetValueAtPtr(dac_cast(base) + offset); + } +} + +template +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + uintptr_t offset = (uintptr_t) &(base->*pPointerFieldMember) - (uintptr_t) base; + + if (isMaybeNull) + { + return PT::GetValueMaybeNullAtPtrIndirect(dac_cast(base) + offset, isIndirect, offset); + } + else + { + return PT::GetValueAtPtrIndirect(dac_cast(base) + offset, isIndirect, offset); + } +} + +template +typename PT::type +ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember); +} + +template +typename PT::type +ReadPointerMaybeNull(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember, isIndirect); +} + +template +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember); +} + +template +typename PT::type +ReadPointer(const T *base, const PT T::* pPointerFieldMember, bool isIndirect) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pPointerFieldMember, isIndirect); +} + +template +typename PT::type +ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + const PT *ptr = &(base->*pFirstPointerFieldMember.*pSecondPointerFieldMember); + uintptr_t offset = (uintptr_t) ptr - (uintptr_t) base; + + if (isMaybeNull) + { + return PT::GetValueMaybeNullAtPtr(dac_cast(base) + offset); + } + else + { + return PT::GetValueAtPtr(dac_cast(base) + offset); + } +} + +template +typename PT::type +ReadPointerMaybeNull(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pFirstPointerFieldMember, pSecondPointerFieldMember); +} + +template +typename PT::type +ReadPointer(const T *base, const C T::* pFirstPointerFieldMember, const PT C::* pSecondPointerFieldMember) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ReadPointer(base, pFirstPointerFieldMember, pSecondPointerFieldMember); +} + +#endif //_FIXUPPOINTER_H diff --git a/lib/coreclr/src/inc/formattype.cpp b/lib/coreclr/src/inc/formattype.cpp new file mode 100644 index 0000000000..fcbfadf6ae --- /dev/null +++ b/lib/coreclr/src/inc/formattype.cpp @@ -0,0 +1,1570 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +/******************************************************************************/ +/* formatType.cpp */ +/******************************************************************************/ +#include "formattype.h" + +/******************************************************************************/ +char* asString(CQuickBytes *out) { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + SIZE_T oldSize = out->Size(); + out->ReSizeThrows(oldSize + 1); + char* cur = &((char*) out->Ptr())[oldSize]; + *cur = 0; + out->ReSizeThrows(oldSize); // Don't count the null character + return((char*) out->Ptr()); +} + +void appendStr(CQuickBytes *out, const char* str, unsigned len) { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if(len == (unsigned)(-1)) len = (unsigned)strlen(str); + SIZE_T oldSize = out->Size(); + out->ReSizeThrows(oldSize + len); + char* cur = &((char*) out->Ptr())[oldSize]; + memcpy(cur, str, len); + // Note no trailing null! +} + +void appendChar(CQuickBytes *out, char chr) { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + SIZE_T oldSize = out->Size(); + out->ReSizeThrows(oldSize + 1); + ((char*) out->Ptr())[oldSize] = chr; + // Note no trailing null! +} + +void insertStr(CQuickBytes *out, const char* str) { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + unsigned len = (unsigned)strlen(str); + SIZE_T oldSize = out->Size(); + out->ReSizeThrows(oldSize + len); + char* cur = &((char*) out->Ptr())[len]; + memmove(cur,out->Ptr(),oldSize); + memcpy(out->Ptr(), str, len); + // Note no trailing null! +} + +static void appendStrNum(CQuickBytes *out, int num) { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + char buff[16]; + sprintf_s(buff, COUNTOF(buff), "%d", num); + appendStr(out, buff); +} + +PCCOR_SIGNATURE PrettyPrintSignature( + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig + _In_opt_z_ const char* inlabel, // prefix for names (NULL if no names required) + BOOL printTyArity=FALSE); + + +PCCOR_SIGNATURE PrettyPrintTypeOrDef( + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig + +//***************************************************************************** +// Parse a length, return the length, size of the length. +//***************************************************************************** +ULONG GetLength( // Length or -1 on error. + void const *pData, // First byte of length. + int *pSizeLen) // Put size of length here, if not 0. +{ + LIMITED_METHOD_CONTRACT; + + BYTE const *pBytes = reinterpret_cast(pData); + + if(pBytes) + { + if ((*pBytes & 0x80) == 0x00) // 0??? ???? + { + if (pSizeLen) *pSizeLen = 1; + return (*pBytes & 0x7f); + } + + if ((*pBytes & 0xC0) == 0x80) // 10?? ???? + { + if (pSizeLen) *pSizeLen = 2; + return ((*pBytes & 0x3f) << 8 | *(pBytes+1)); + } + + if ((*pBytes & 0xE0) == 0xC0) // 110? ???? + { + if (pSizeLen) *pSizeLen = 4; + return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3)); + } + } + if(pSizeLen) *pSizeLen = 0; + return 0; +} + + +/******************************************************************************/ +const char* PrettyPrintSig( + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the length of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig + const char* inlabel, // prefix for names (NULL if no names required) + BOOL printTyArity) +{ + STATIC_CONTRACT_THROWS; + + // This had a _try/__except handler earlier that would swallow exceptions like + // SO and breakpoint. Obviously, swallowing any of them is not the right thing to do. + // + // Thus, we replace it with EX_TRY/EX_CATCH that automatically kicks in with SO + // handling if it sees any SO going past it. Also, C++ catch will not swallow + // the breakpoint exception (which is what we want). + EX_TRY + { + PrettyPrintSignature(typePtr, + typeLen, + name, + out, + pIMDI, + inlabel, + printTyArity); + } + EX_CATCH + { + out->Shrink(0); + appendStr(out,"ERROR PARSING THE SIGNATURE"); + } +#if defined(__ILDASM__) + // Dont allow ildasm to swallow bad SEH exceptions + EX_END_CATCH(RethrowCorruptingExceptions); +#else // __ILDASM__ + EX_END_CATCH(SwallowAllExceptions); +#endif // __ILDASM__ + + return(asString(out)); +} + +/********************************************************************************/ +// Converts a com signature to a printable signature. +// Note that return value is pointing at the CQuickBytes buffer, + +PCCOR_SIGNATURE PrettyPrintSignature( + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig + const char* inlabel, // prefix for names (NULL if no names required) + BOOL printTyArity) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + unsigned numArgs; + unsigned numTyArgs = 0; + PCCOR_SIGNATURE typeEnd = typePtr + typeLen; + unsigned ixArg= 0; //arg index + char argname[1024]; + char label[MAX_PREFIX_SIZE]; + const char* openpar = "("; + const char* closepar = ")"; + ParamDescriptor* pszArgName = NULL; // ptr to array of names (if provided by debug info) + + if(inlabel && *inlabel) // check for *inlabel is totally unnecessary, added to pacify the PREFIX + { + strcpy_s(label,MAX_PREFIX_SIZE,inlabel); + ixArg = label[strlen(label)-1] - '0'; + label[strlen(label)-1] = 0; + if(label[0] == '@') // it's pointer! + { +#ifdef _WIN64 + pszArgName = (ParamDescriptor*)_atoi64(&label[1]); +#else // !_WIN64 + pszArgName = (ParamDescriptor*)(size_t)atoi(&label[1]); +#endif // _WIN64 + } + } + + // 0 means a local var sig + if (name != 0) + { + // get the calling convention out + unsigned callConv = CorSigUncompressData(typePtr); + + // should not be a local var sig + _ASSERTE(!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)); + + if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD)) + { + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + if (*name) + { + appendChar(out, ' '); + appendStr(out, name); + } + return(typePtr); + } + + if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) + appendStr(out, KEYWORD("explicit ")); + + if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) + appendStr(out, KEYWORD("instance ")); + + if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) + { + openpar = LTN(); + closepar = GTN(); + } + else + { + static const char* const callConvNames[8] = { + "", + "unmanaged cdecl ", + "unmanaged stdcall ", + "unmanaged thiscall ", + "unmanaged fastcall ", + "vararg ", + " ", + " " + }; + appendStr(out, KEYWORD(callConvNames[callConv & 7])); + } + + if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC) + { + numTyArgs = CorSigUncompressData(typePtr); + } + numArgs = CorSigUncompressData(typePtr); + if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) + { + // do return type + if(pszArgName) + { + argname[0] = 0; + DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg+numArgs].attr); + appendStr(out,argname); + } + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + if(pszArgName) + { + argname[0] = ' '; argname[1] = 0; + DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg+numArgs].tok); + appendStr(out,argname); + } + if(*name != 0) + { + appendChar(out, ' '); + appendStr(out, name); + } + if((numTyArgs != 0)&&printTyArity) + { + appendStr(out,LTN()); + appendChar(out,'['); + appendStrNum(out,numTyArgs); + appendChar(out,']'); + appendStr(out,GTN()); + } + } + } + else + { + // get the calling convention out +#ifdef _DEBUG + unsigned callConv = +#endif + CorSigUncompressData(typePtr); +#ifdef _DEBUG + (void)callConv; //prevent "unused variable" warning from GCC + // should be a local var sig + _ASSERTE(callConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG); +#endif + + numArgs = CorSigUncompressData(typePtr); + } + + appendStr(out, openpar); + + bool needComma = false; + while(typePtr < typeEnd) + { + if(name) // printing the arguments + { + PREFIX_ASSUME(typePtr != NULL); + if (*typePtr == ELEMENT_TYPE_SENTINEL) + { + if (needComma) + appendChar(out, ','); + appendStr(out, "..."); + typePtr++; + } + else + { + if (numArgs <= 0) + break; + if (needComma) + appendChar(out, ','); + if(pszArgName) + { + argname[0] = 0; + DumpParamAttr(argname,COUNTOF(argname),pszArgName[ixArg].attr); + appendStr(out,argname); + } + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + if(inlabel) + { + if(pszArgName) + { + argname[0] = ' '; argname[1] = 0; + DumpMarshaling(pIMDI,argname,COUNTOF(argname),pszArgName[ixArg].tok); + strcat_s(argname, COUNTOF(argname), ProperName(pszArgName[ixArg++].name)); + } + else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++); + appendStr(out,argname); + } + --numArgs; + } + } + else // printing local vars + { + if (numArgs <= 0) + break; + if(pszArgName) + { + if(pszArgName[ixArg].attr == 0xFFFFFFFF) + { + CQuickBytes fake_out; + typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI); + ixArg++; + numArgs--; + continue; + } + } + if (needComma) + appendChar(out, ','); + if(pszArgName) + { + sprintf_s(argname,COUNTOF(argname),"[%d] ",pszArgName[ixArg].attr); + appendStr(out,argname); + } + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + if(inlabel) + { + if(pszArgName) + { + sprintf_s(argname,COUNTOF(argname)," %s",ProperLocalName(pszArgName[ixArg++].name)); + } + else sprintf_s(argname,COUNTOF(argname)," %s_%d",label,ixArg++); + appendStr(out,argname); + } + --numArgs; + } + needComma = true; + } + // Have we finished printing all the arguments? + if (numArgs > 0) { + appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]")); + } + + appendStr(out, closepar); + return(typePtr); +} + + +/******************************************************************************/ +// pretty prints 'type' or its 'typedef' to the buffer 'out' returns a pointer to the next type, +// or 0 on a format failure; outside ILDASM -- simple wrapper for PrettyPrintType + +PCCOR_SIGNATURE PrettyPrintTypeOrDef( + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PCCOR_SIGNATURE pBegin, pEnd=NULL; + +#ifdef __ILDASM__ + ULONG L = (ULONG)(out->Size()); +#endif + pBegin = typePtr; + pEnd = PrettyPrintType(typePtr,out,pIMDI); +#ifdef __ILDASM__ + if(pEnd > pBegin) // PrettyPrintType can return NULL + { + DWORD i; + ULONG l = (ULONG)(pEnd - pBegin); + for(i=0; i < g_NumTypedefs; i++) + { + if(((*g_typedefs)[i].cb == l) + && (memcmp((*g_typedefs)[i].psig,pBegin,l)==0)) + { + out->Shrink(L); // discard output of PrettyPrintType + appendStr(out, JUMPPT(ProperName((*g_typedefs)[i].szName),(*g_typedefs)[i].tkSelf)); + break; + } + } + } +#endif + return pEnd; +} + +/******************************************************************************/ +// pretty prints 'type' to the buffer 'out' returns a pointer to the next type, +// or 0 on a format failure + +PCCOR_SIGNATURE PrettyPrintType( + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + mdToken tk; + const char* str; + int typ; + CQuickBytes tmp; + CQuickBytes Appendix; + BOOL Reiterate; + int n; + + do { + Reiterate = FALSE; + switch(typ = *typePtr++) { + case ELEMENT_TYPE_VOID : + str = "void"; goto APPEND; + case ELEMENT_TYPE_BOOLEAN : + str = "bool"; goto APPEND; + case ELEMENT_TYPE_CHAR : + str = "char"; goto APPEND; + case ELEMENT_TYPE_I1 : + str = "int8"; goto APPEND; + case ELEMENT_TYPE_U1 : + str = "uint8"; goto APPEND; + case ELEMENT_TYPE_I2 : + str = "int16"; goto APPEND; + case ELEMENT_TYPE_U2 : + str = "uint16"; goto APPEND; + case ELEMENT_TYPE_I4 : + str = "int32"; goto APPEND; + case ELEMENT_TYPE_U4 : + str = "uint32"; goto APPEND; + case ELEMENT_TYPE_I8 : + str = "int64"; goto APPEND; + case ELEMENT_TYPE_U8 : + str = "uint64"; goto APPEND; + case ELEMENT_TYPE_R4 : + str = "float32"; goto APPEND; + case ELEMENT_TYPE_R8 : + str = "float64"; goto APPEND; + case ELEMENT_TYPE_U : + str = "native uint"; goto APPEND; + case ELEMENT_TYPE_I : + str = "native int"; goto APPEND; + case ELEMENT_TYPE_OBJECT : + str = "object"; goto APPEND; + case ELEMENT_TYPE_STRING : + str = "string"; goto APPEND; + case ELEMENT_TYPE_TYPEDBYREF : + str = "typedref"; goto APPEND; + APPEND: + appendStr(out, KEYWORD((char*)str)); + break; + + case ELEMENT_TYPE_VALUETYPE : + str = "valuetype "; + goto DO_CLASS; + case ELEMENT_TYPE_CLASS : + str = "class "; + goto DO_CLASS; + + DO_CLASS: + appendStr(out, KEYWORD((char*)str)); + typePtr += CorSigUncompressToken(typePtr, &tk); + if(IsNilToken(tk)) + { + appendStr(out, "[ERROR! NIL TOKEN]"); + } + else PrettyPrintClass(out, tk, pIMDI); + REGISTER_REF(g_tkRefUser,tk) + break; + + case ELEMENT_TYPE_SZARRAY : + insertStr(&Appendix,"[]"); + Reiterate = TRUE; + break; + + case ELEMENT_TYPE_ARRAY : + { + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + PREFIX_ASSUME(typePtr != NULL); + unsigned rank = CorSigUncompressData(typePtr); + // what is the syntax for the rank 0 case? + if (rank == 0) { + appendStr(out, ERRORMSG("[BAD: RANK == 0!]")); + } + else { + _ASSERTE(rank != 0); + +#ifdef _PREFAST_ +#pragma prefast(push) +#pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow") +#endif + int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); + int* sizes = &lowerBounds[rank]; + memset(lowerBounds, 0, sizeof(int)*2*rank); + + unsigned numSizes = CorSigUncompressData(typePtr); + _ASSERTE(numSizes <= rank); + unsigned i; + for(i =0; i < numSizes; i++) + sizes[i] = CorSigUncompressData(typePtr); + + unsigned numLowBounds = CorSigUncompressData(typePtr); + _ASSERTE(numLowBounds <= rank); + for(i = 0; i < numLowBounds; i++) + typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); + + appendChar(out, '['); + if (rank == 1 && numSizes == 0 && numLowBounds == 0) + appendStr(out, "..."); + else { + for(i = 0; i < rank; i++) + { + //if (sizes[i] != 0 || lowerBounds[i] != 0) + { + if (lowerBounds[i] == 0 && i < numSizes) + appendStrNum(out, sizes[i]); + else + { + if(i < numLowBounds) + { + appendStrNum(out, lowerBounds[i]); + appendStr(out, "..."); + if (/*sizes[i] != 0 && */i < numSizes) + appendStrNum(out, lowerBounds[i] + sizes[i] - 1); + } + } + } + if (i < rank-1) + appendChar(out, ','); + } + } + appendChar(out, ']'); +#ifdef _PREFAST_ +#pragma prefast(pop) +#endif + } + } break; + + case ELEMENT_TYPE_VAR : + appendChar(out, '!'); + n = CorSigUncompressData(typePtr); +#ifdef __ILDASM__ + if(!PrettyPrintGP(g_tkVarOwner,out,n)) +#endif + appendStrNum(out, n); + break; + + case ELEMENT_TYPE_MVAR : + appendChar(out, '!'); + appendChar(out, '!'); + n = CorSigUncompressData(typePtr); +#ifdef __ILDASM__ + if(!PrettyPrintGP(g_tkMVarOwner,out,n)) +#endif + appendStrNum(out, n); + break; + + case ELEMENT_TYPE_FNPTR : + appendStr(out, KEYWORD("method ")); + typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL); + break; + + case ELEMENT_TYPE_GENERICINST : + { + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + appendStr(out, LTN()); + unsigned numArgs = CorSigUncompressData(typePtr); + bool needComma = false; + while(numArgs--) + { + if (needComma) + appendChar(out, ','); + typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); + needComma = true; + } + appendStr(out, GTN()); + break; + } + +#ifndef __ILDASM__ + case ELEMENT_TYPE_INTERNAL : + { + // ELEMENT_TYPE_INTERNAL + _ASSERTE(sizeof(TypeHandle) == sizeof(void *)); + TypeHandle typeHandle; + typePtr += CorSigUncompressPointer(typePtr, (void **)&typeHandle); + + MethodTable *pMT = NULL; + if (typeHandle.IsTypeDesc()) + { + pMT = typeHandle.AsTypeDesc()->GetMethodTable(); + if (pMT) + { + PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); + + // It could be a "native version" of the managed type used in interop + if (typeHandle.AsTypeDesc()->IsNativeValueType()) + appendStr(out, "_NativeValueType"); + } + else + appendStr(out, "(null)"); + } + else + { + pMT = typeHandle.AsMethodTable(); + if (pMT) + PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); + else + appendStr(out, "(null)"); + } + + char sz[32]; + if(IsCompilationProcess()) + { + sprintf_s(sz, COUNTOF(sz), " /* TOKEN: 0x%x */", pMT != NULL ? pMT->GetCl() : 0); + } + else + { + sprintf_s(sz, COUNTOF(sz), " /* MT: 0x%p */", pMT); + } + appendStr(out, sz); + break; + } +#endif + + + // Modifiers or depedent types + case ELEMENT_TYPE_CMOD_OPT : + str = " modopt("; goto ADDCLASSTOCMOD; + case ELEMENT_TYPE_CMOD_REQD : + str = " modreq("; + ADDCLASSTOCMOD: + typePtr += CorSigUncompressToken(typePtr, &tk); + if (IsNilToken(tk)) + { + Debug_ReportError("Nil token in custom modifier"); + } + tmp.Shrink(0); + appendStr(&tmp, KEYWORD((char*)str)); + PrettyPrintClass(&tmp, tk, pIMDI); + appendChar(&tmp,')'); + str = (const char *) asString(&tmp); + goto MODIFIER; + case ELEMENT_TYPE_PINNED : + str = " pinned"; goto MODIFIER; + case ELEMENT_TYPE_PTR : + str = "*"; goto MODIFIER; + case ELEMENT_TYPE_BYREF : + str = AMP(); goto MODIFIER; + MODIFIER: + insertStr(&Appendix, str); + Reiterate = TRUE; + break; + + default: + case ELEMENT_TYPE_SENTINEL : + case ELEMENT_TYPE_END : + //_ASSERTE(!"Unknown Type"); + if(typ) + { + char sz[64]; + sprintf_s(sz,COUNTOF(sz),"/* UNKNOWN TYPE (0x%X)*/",typ); + appendStr(out, ERRORMSG(sz)); + } + break; + } // end switch + } while(Reiterate); + appendStr(out,asString(&Appendix)); + return(typePtr); +} + +/******************************************************************/ +const char* PrettyPrintClass( + CQuickBytes *out, // where to put the pretty printed string + mdToken tk, // The class token to look up + IMDInternalImport *pIMDI) // ptr to IMDInternalImport class with ComSig +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if(tk == mdTokenNil) // Zero resolution scope for "somewhere here" TypeRefs + { + appendStr(out,"[*]"); + return(asString(out)); + } + if(!pIMDI->IsValidToken(tk)) + { + char str[1024]; + sprintf_s(str,COUNTOF(str)," [ERROR: INVALID TOKEN 0x%8.8X] ",tk); + appendStr(out,ERRORMSG(str)); + return(asString(out)); + } + switch(TypeFromToken(tk)) + { + case mdtTypeRef: + case mdtTypeDef: +#ifdef __ILDASM__ + DWORD ix; + for(ix = 0; ix < g_NumTypedefs; ix++) + { + if((*g_typedefs)[ix].tkTypeSpec == tk) break; + } + if(ix < g_NumTypedefs) + { + appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf)); + } + else +#endif + { + const char *nameSpace = 0; + const char *name = 0; + mdToken tkEncloser; + + if (TypeFromToken(tk) == mdtTypeRef) + { + if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkEncloser))) + { + tkEncloser = mdTypeDefNil; + } + if (FAILED(pIMDI->GetNameOfTypeRef(tk, &nameSpace, &name))) + { + nameSpace = name = "Invalid TypeRef record"; + } + } + else + { + if (FAILED(pIMDI->GetNestedClassProps(tk,&tkEncloser))) + { + tkEncloser = mdTypeDefNil; + } + if (FAILED(pIMDI->GetNameOfTypeDef(tk, &name, &nameSpace))) + { + nameSpace = name = "Invalid TypeDef record"; + } + } + MAKE_NAME_IF_NONE(name,tk); + if((tkEncloser == mdTokenNil) || RidFromToken(tkEncloser)) + { + PrettyPrintClass(out,tkEncloser,pIMDI); + if (TypeFromToken(tkEncloser) == mdtTypeRef || TypeFromToken(tkEncloser) == mdtTypeDef) + { + appendChar(out, '/'); + //nameSpace = ""; //don't print namespaces for nested classes! + } + } + if(TypeFromToken(tk)==mdtTypeDef) + { + unsigned L = (unsigned)strlen(ProperName(name))+1; + char* szFN = NULL; + if(nameSpace && *nameSpace) + { + const char* sz = ProperName(nameSpace); + L+= (unsigned)strlen(sz)+1; + szFN = new char[L]; + sprintf_s(szFN,L,"%s.",sz); + } + else + { + szFN = new char[L]; + *szFN = 0; + } + strcat_s(szFN,L, ProperName(name)); + appendStr(out,JUMPPT(szFN,tk)); + VDELETE(szFN); + } + else + { + if (nameSpace && *nameSpace) { + appendStr(out, ProperName(nameSpace)); + appendChar(out, '.'); + } + + appendStr(out, ProperName(name)); + } + if(g_fDumpTokens) + { + char tmp[16]; + sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); + appendStr(out,COMMENT(tmp)); + } + } + break; + + case mdtAssemblyRef: + { + LPCSTR szName = NULL; +#ifdef __ILDASM__ + if (rAsmRefName && (RidFromToken(tk) <= ulNumAsmRefs)) + { + szName = rAsmRefName[RidFromToken(tk)-1]; + } + else +#endif + { + if (FAILED(pIMDI->GetAssemblyRefProps(tk,NULL,NULL,&szName,NULL,NULL,NULL,NULL))) + { + szName = NULL; + } + } + if ((szName != NULL) && ((*szName) != 0 )) + { + appendChar(out, '['); + appendStr(out,JUMPPT(ProperName(szName),tk)); + if(g_fDumpTokens) + { + char tmp[16]; + sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); + appendStr(out,COMMENT(tmp)); + } + appendChar(out, ']'); + } + } + break; + case mdtAssembly: + { + LPCSTR szName; + if (FAILED(pIMDI->GetAssemblyProps(tk,NULL,NULL,NULL,&szName,NULL,NULL))) + { + szName = NULL; + } + if ((szName != NULL) && ((*szName) != 0)) + { + appendChar(out, '['); + appendStr(out,JUMPPT(ProperName(szName),tk)); + if(g_fDumpTokens) + { + char tmp[16]; + sprintf_s(tmp,COUNTOF(tmp),"/* %08X */",tk); + appendStr(out,COMMENT(tmp)); + } + appendChar(out, ']'); + } + } + break; + case mdtModuleRef: + { + LPCSTR szName; + if (FAILED(pIMDI->GetModuleRefProps(tk, &szName))) + { + szName = NULL; + } + if ((szName != NULL) && ((*szName) != 0)) + { + appendChar(out, '['); + appendStr(out,KEYWORD(".module ")); + appendStr(out,JUMPPT(ProperName(szName),tk)); + if(g_fDumpTokens) + { + char tmp[16]; + sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); + appendStr(out,COMMENT(tmp)); + } + appendChar(out, ']'); + } + } + break; + + case mdtTypeSpec: + { +#ifdef __ILDASM__ + DWORD ix; + for(ix = 0; ix < g_NumTypedefs; ix++) + { + if((*g_typedefs)[ix].tkTypeSpec == tk) break; + } + if(ix < g_NumTypedefs) + { + appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf)); + } + else +#endif + { + ULONG cSig; + PCCOR_SIGNATURE sig; + if (FAILED(pIMDI->GetSigFromToken(tk, &cSig, &sig))) + { + char tmp[64]; + sprintf_s(tmp, COUNTOF(tmp), "/*Invalid %08X record*/", tk); + appendStr(out, COMMENT(tmp)); + } + else + { + PrettyPrintType(sig, out, pIMDI); + } + } + if(g_fDumpTokens) + { + char tmp[16]; + sprintf_s(tmp,COUNTOF(tmp),"/*%08X*/",tk); + appendStr(out,COMMENT(tmp)); + } + } + break; + + case mdtModule: + break; + + default: + { + char str[128]; + sprintf_s(str,COUNTOF(str)," [ERROR: INVALID TOKEN TYPE 0x%8.8X] ",tk); + appendStr(out,ERRORMSG(str)); + } + } + return(asString(out)); +} + +const char* TrySigUncompressAndDumpSimpleNativeType( + PCCOR_SIGNATURE pData, // [IN] compressed data + ULONG *pDataOut, // [OUT] the expanded *pData + ULONG &cbCur, + SString &buf) +{ + const char* sz = NULL; + ULONG ulSize = CorSigUncompressData(pData, pDataOut); + if (ulSize != (ULONG)-1) + { + switch (*pDataOut) + { + case NATIVE_TYPE_VOID: sz = " void"; break; + case NATIVE_TYPE_BOOLEAN: sz = " bool"; break; + case NATIVE_TYPE_I1: sz = " int8"; break; + case NATIVE_TYPE_U1: sz = " unsigned int8"; break; + case NATIVE_TYPE_I2: sz = " int16"; break; + case NATIVE_TYPE_U2: sz = " unsigned int16"; break; + case NATIVE_TYPE_I4: sz = " int32"; break; + case NATIVE_TYPE_U4: sz = " unsigned int32"; break; + case NATIVE_TYPE_I8: sz = " int64"; break; + case NATIVE_TYPE_U8: sz = " unsigned int64"; break; + case NATIVE_TYPE_R4: sz = " float32"; break; + case NATIVE_TYPE_R8: sz = " float64"; break; + case NATIVE_TYPE_SYSCHAR: sz = " syschar"; break; + case NATIVE_TYPE_VARIANT: sz = " variant"; break; + case NATIVE_TYPE_CURRENCY: sz = " currency"; break; + case NATIVE_TYPE_DECIMAL: sz = " decimal"; break; + case NATIVE_TYPE_DATE: sz = " date"; break; + case NATIVE_TYPE_BSTR: sz = " bstr"; break; + case NATIVE_TYPE_LPSTR: sz = " lpstr"; break; + case NATIVE_TYPE_LPWSTR: sz = " lpwstr"; break; + case NATIVE_TYPE_LPTSTR: sz = " lptstr"; break; + case NATIVE_TYPE_OBJECTREF: sz = " objectref"; break; + case NATIVE_TYPE_STRUCT: sz = " struct"; break; + case NATIVE_TYPE_ERROR: sz = " error"; break; + case NATIVE_TYPE_INT: sz = " int"; break; + case NATIVE_TYPE_UINT: sz = " uint"; break; + case NATIVE_TYPE_NESTEDSTRUCT: sz = " nested struct"; break; + case NATIVE_TYPE_BYVALSTR: sz = " byvalstr"; break; + case NATIVE_TYPE_ANSIBSTR: sz = " ansi bstr"; break; + case NATIVE_TYPE_TBSTR: sz = " tbstr"; break; + case NATIVE_TYPE_VARIANTBOOL: sz = " variant bool"; break; + case NATIVE_TYPE_FUNC: sz = " method"; break; + case NATIVE_TYPE_ASANY: sz = " as any"; break; + case NATIVE_TYPE_LPSTRUCT: sz = " lpstruct"; break; + case NATIVE_TYPE_PTR: + case NATIVE_TYPE_SAFEARRAY: + case NATIVE_TYPE_ARRAY: + case NATIVE_TYPE_FIXEDSYSSTRING: + case NATIVE_TYPE_FIXEDARRAY: + case NATIVE_TYPE_INTF: + case NATIVE_TYPE_IUNKNOWN: + case NATIVE_TYPE_IDISPATCH: + case NATIVE_TYPE_CUSTOMMARSHALER: + case NATIVE_TYPE_END: + case NATIVE_TYPE_MAX: + sz = ""; break; + default: sz = NULL; + } + } + if (sz) + cbCur += ulSize; + else + buf.Clear(); + + return sz; +} + +bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data + ULONG *pDataOut, // [OUT] the expanded *pData + ULONG &cbCur, + SString &buf) +{ + ULONG ulSize = CorSigUncompressData(pData, pDataOut); + if (ulSize == (ULONG)-1) + { + buf.Clear(); + return false; + } else + { + cbCur += ulSize; + return true; + } +} + + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:21000) // Suppress PREFast warning about overly large function +#endif +char* DumpMarshaling(IMDInternalImport* pImport, + __inout_ecount(cchszString) char* szString, + DWORD cchszString, + mdToken tok) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PCCOR_SIGNATURE pSigNativeType = NULL; + ULONG cbNativeType = 0; + SString buf; + if (RidFromToken(tok) && + SUCCEEDED(pImport->GetFieldMarshal( // return error if no native type associate with the token + tok, // [IN] given fielddef + &pSigNativeType, // [OUT] the native type signature + &cbNativeType))) // [OUT] the count of bytes of *ppvNativeType + { + ULONG cbCur = 0; + ULONG ulData; + const char *sz = NULL; + BOOL fAddAsterisk = FALSE, fAddBrackets = FALSE; + buf.AppendPrintf(" %s(", KEYWORD("marshal")); + while (cbCur < cbNativeType) + { + ulData = NATIVE_TYPE_MAX; + sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf); + if (!sz) + goto error; + if(*sz == 0) + { + switch (ulData) + { + case NATIVE_TYPE_PTR: + sz = ""; + fAddAsterisk = TRUE; + break; + case NATIVE_TYPE_SAFEARRAY: + sz = ""; + buf.AppendASCII(KEYWORD(" safearray")); + ulData = VT_EMPTY; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + } + switch(ulData & VT_TYPEMASK) + { + case VT_EMPTY: sz=""; break; + case VT_NULL: sz=" null"; break; + case VT_VARIANT: sz=" variant"; break; + case VT_CY: sz=" currency"; break; + case VT_VOID: sz=" void"; break; + case VT_BOOL: sz=" bool"; break; + case VT_I1: sz=" int8"; break; + case VT_I2: sz=" int16"; break; + case VT_I4: sz=" int32"; break; + case VT_I8: sz=" int64"; break; + case VT_R4: sz=" float32"; break; + case VT_R8: sz=" float64"; break; + case VT_UI1: sz=" unsigned int8"; break; + case VT_UI2: sz=" unsigned int16"; break; + case VT_UI4: sz=" unsigned int32"; break; + case VT_UI8: sz=" unsigned int64"; break; + case VT_PTR: sz=" *"; break; + case VT_DECIMAL: sz=" decimal"; break; + case VT_DATE: sz=" date"; break; + case VT_BSTR: sz=" bstr"; break; + case VT_LPSTR: sz=" lpstr"; break; + case VT_LPWSTR: sz=" lpwstr"; break; + case VT_UNKNOWN: sz=" iunknown"; break; + case VT_DISPATCH: sz=" idispatch"; break; + case VT_SAFEARRAY: sz=" safearray"; break; + case VT_INT: sz=" int"; break; + case VT_UINT: sz=" unsigned int"; break; + case VT_ERROR: sz=" error"; break; + case VT_HRESULT: sz=" hresult"; break; + case VT_CARRAY: sz=" carray"; break; + case VT_USERDEFINED: sz=" userdefined"; break; + case VT_RECORD: sz=" record"; break; + case VT_FILETIME: sz=" filetime"; break; + case VT_BLOB: sz=" blob"; break; + case VT_STREAM: sz=" stream"; break; + case VT_STORAGE: sz=" storage"; break; + case VT_STREAMED_OBJECT: sz=" streamed_object"; break; + case VT_STORED_OBJECT: sz=" stored_object"; break; + case VT_BLOB_OBJECT: sz=" blob_object"; break; + case VT_CF: sz=" cf"; break; + case VT_CLSID: sz=" clsid"; break; + default: sz=NULL; break; + } + if(sz) buf.AppendASCII(KEYWORD(sz)); + else + { + // buf.AppendPrintf(ERRORMSG(" [ILLEGAL VARIANT TYPE 0x%X]"),ulData & VT_TYPEMASK); + buf.Clear(); + goto error; + } + sz=""; + switch(ulData & (~VT_TYPEMASK)) + { + case VT_ARRAY: sz = "[]"; break; + case VT_VECTOR: sz = " vector"; break; + case VT_BYREF: sz = "&"; break; + case VT_BYREF|VT_ARRAY: sz = "&[]"; break; + case VT_BYREF|VT_VECTOR: sz = "& vector"; break; + case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break; + case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break; + } + buf.AppendASCII(KEYWORD(sz)); + sz=""; + + // Extract the user defined sub type name. + if (cbCur < cbNativeType) + { + LPUTF8 strTemp = NULL; + int strLen = 0; + int ByteCountLength = 0; + strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); + cbCur += ByteCountLength; + if(strLen) + { +#ifdef _PREFAST_ +#pragma prefast(push) +#pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow") +#endif + strTemp = (LPUTF8)_alloca(strLen + 1); + memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); + strTemp[strLen] = 0; + buf.AppendPrintf(", \"%s\"", UnquotedProperName(strTemp)); + cbCur += strLen; +#ifdef _PREFAST_ +#pragma prefast(pop) +#endif + } + } + break; + + case NATIVE_TYPE_ARRAY: + sz = ""; + fAddBrackets = TRUE; + break; + case NATIVE_TYPE_FIXEDSYSSTRING: + { + sz = ""; + buf.AppendASCII(KEYWORD(" fixed sysstring")); + buf.AppendASCII(" ["); + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + buf.AppendPrintf("%d",ulData); + } + buf.AppendASCII("]"); + } + break; + case NATIVE_TYPE_FIXEDARRAY: + { + sz = ""; + buf.AppendASCII(KEYWORD(" fixed array")); + buf.AppendASCII(" ["); + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + buf.AppendPrintf("%d",ulData); + } + buf.AppendASCII("]"); + if (cbCur < cbNativeType) + { + sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf); + if (!sz) + goto error; + } + } + break; + + case NATIVE_TYPE_INTF: + buf.AppendASCII(KEYWORD(" interface")); + goto DumpIidParamIndex; + case NATIVE_TYPE_IUNKNOWN: + buf.AppendASCII(KEYWORD(" iunknown")); + goto DumpIidParamIndex; + case NATIVE_TYPE_IDISPATCH: + buf.AppendASCII(KEYWORD(" idispatch")); + DumpIidParamIndex: + sz = " "; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + buf.AppendPrintf("(%s = %d)",KEYWORD("iidparam"),ulData); + } + break; + + case NATIVE_TYPE_CUSTOMMARSHALER: + { + LPUTF8 strTemp = NULL; + int strLen = 0; + int ByteCountLength = 0; + BOOL fFourStrings = FALSE; + + sz = ""; + buf.AppendASCII(KEYWORD(" custom")); + buf.AppendASCII(" ("); + // Extract the typelib GUID. + strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); + cbCur += ByteCountLength; + if(strLen) + { + fFourStrings = TRUE; + strTemp = (LPUTF8)(new char[strLen + 1]); + if(strTemp) + { + memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); + strTemp[strLen] = 0; + buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); + cbCur += strLen; + VDELETE(strTemp); + } + } + if(cbCur >= cbNativeType) + { + // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + buf.Clear(); + goto error; + } + else + { + //_ASSERTE(cbCur < cbNativeType); + + // Extract the name of the native type. + strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); + cbCur += ByteCountLength; + if(fFourStrings) + { + if(strLen) + { + strTemp = (LPUTF8)(new char[strLen + 1]); + if(strTemp) + { + memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); + strTemp[strLen] = 0; + buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); + cbCur += strLen; + VDELETE(strTemp); + } + } + else buf.AppendASCII("\"\","); + } + if(cbCur >= cbNativeType) + { + // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + buf.Clear(); + goto error; + } + else + { + //_ASSERTE(cbCur < cbNativeType); + + // Extract the name of the custom marshaler. + strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); + cbCur += ByteCountLength; + if(strLen) + { + strTemp = (LPUTF8)(new char[strLen + 1]); + if(strTemp) + { + memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); + strTemp[strLen] = 0; + buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); + cbCur += strLen; + VDELETE(strTemp); + } + } + else buf.AppendASCII("\"\","); + if(cbCur >= cbNativeType) + { + // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + buf.Clear(); + goto error; + } + else + { + // Extract the cookie string. + strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); + cbCur += ByteCountLength; + + if(cbCur+strLen > cbNativeType) + { + // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); + buf.Clear(); + goto error; + } + else + { + if(strLen) + { + strTemp = (LPUTF8)(new (nothrow) char[strLen + 1]); + if(strTemp) + { + memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); + strTemp[strLen] = 0; + + buf.AppendASCII("\""); + // Copy the cookie string and transform the embedded nulls into \0's. + for (int i = 0; i < strLen - 1; i++, cbCur++) + { + if (strTemp[i] == 0) + buf.AppendASCII("\\0"); + else + { + buf.AppendPrintf("%c", strTemp[i]); + } + } + buf.AppendPrintf("%c\"", strTemp[strLen - 1]); + cbCur++; + VDELETE(strTemp); + } + } + else + buf.AppendASCII("\"\""); + //_ASSERTE(cbCur <= cbNativeType); + } + } + } + } + buf.AppendASCII(")"); + } + break; + default: + { + sz = ""; + } + } // end switch + } + if(*sz) + { + buf.AppendASCII(KEYWORD(sz)); + if(fAddAsterisk) + { + buf.AppendASCII("*"); + fAddAsterisk = FALSE; + } + if(fAddBrackets) + { + ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; + buf.AppendASCII("["); + fAddBrackets = FALSE; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + ulSizeParam = ulData; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + ulSizeConst = ulData; + if (cbCur < cbNativeType) + { + // retrieve flags + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + if((ulData & 1) == 0) ulSizeParam = 0xFFFFFFFF; + } + } + } + if(ulSizeConst != 0xFFFFFFFF) + { + buf.AppendPrintf("%d",ulSizeConst); + // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0 + } + if(ulSizeParam != 0xFFFFFFFF) + { + buf.AppendPrintf(" + %d",ulSizeParam); + } + buf.AppendASCII("]"); + } + + } + + if (ulData >= NATIVE_TYPE_MAX) + break; + } // end while (cbCur < cbNativeType) + // still can have outstanding asterisk or brackets + if(fAddAsterisk) + { + buf.AppendASCII("*"); + fAddAsterisk = FALSE; + } + if(fAddBrackets) + { + ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; + buf.AppendASCII("["); + fAddBrackets = FALSE; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + ulSizeParam = ulData; + if (cbCur < cbNativeType) + { + if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) + goto error; + ulSizeConst = ulData; + } + } + if(ulSizeConst != 0xFFFFFFFF) + { + buf.AppendPrintf("%d",ulSizeConst); + // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0 + } + if(ulSizeParam != 0xFFFFFFFF) + { + buf.AppendPrintf(" + %d",ulSizeParam); + } + buf.AppendASCII("]"); + } + buf.AppendASCII(") "); + }// end if(SUCCEEDED +error: + if (buf.IsEmpty() && cbNativeType != 0) + { + // There was something that we didn't grok in the signature. + // Just dump out the blob as hex + buf.AppendPrintf(" %s({", KEYWORD("marshal")); + while (cbNativeType--) + buf.AppendPrintf(" %2.2X", *pSigNativeType++); + buf.AppendASCII(" }) "); + + char * tgt = szString + strlen(szString); + int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode()); + if (sprintf_ret == -1) + { + // Hit an error. Oh well, nothing to do... + return tgt; + } + else + { + return tgt + sprintf_ret; + } + } + else + { + char * tgt = szString + strlen(szString); + int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%S", buf.GetUnicode()); + if (sprintf_ret == -1) + { + // There was an error, possibly with converting the Unicode characters. + buf.Clear(); + if (cbNativeType != 0) + goto error; + return tgt; // Oh well, nothing to do... + } + else + { + return tgt + sprintf_ret; + } + } +} +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +char* DumpParamAttr(__inout_ecount(cchszString) char* szString, DWORD cchszString, DWORD dwAttr) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + char *szptr = &szString[strlen(szString)]; + char *was_szptr = szptr; + if(IsPdIn(dwAttr)) + { + szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr), KEYWORD("[in]")); + } + if(IsPdOut(dwAttr)) + { + szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[out]")); + } + if(IsPdOptional(dwAttr)) + { + szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[opt]")); + } + if(szptr != was_szptr) + { + szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr)," "); + } + return szptr; +} diff --git a/lib/coreclr/src/inc/formattype.h b/lib/coreclr/src/inc/formattype.h new file mode 100644 index 0000000000..31a17e06f2 --- /dev/null +++ b/lib/coreclr/src/inc/formattype.h @@ -0,0 +1,181 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _formatType_h +#define _formatType_h + +#include "corpriv.h" // for IMDInternalImport + +// ILDASM code doesn't memcpy on gc pointers, so it prefers the real +// memcpy rather than GCSafeMemCpy. +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) +#ifdef memcpy +#undef memcpy +#endif +#endif + +#define MAX_PREFIX_SIZE 32 + +struct ParamDescriptor +{ + char* name; + mdToken tok; + DWORD attr; +}; + +char* DumpMarshaling(IMDInternalImport* pImport, + __inout_ecount(cchszString) char* szString, + DWORD cchszString, + mdToken tok); +char* DumpParamAttr(__inout_ecount(cchszString) char* szString, + DWORD cchszString, + DWORD dwAttr); + +void appendStr(CQuickBytes *out, const char* str, unsigned len=(unsigned)-1); +void insertStr(CQuickBytes *out, const char* str); +char* asString(CQuickBytes *out); + +const char* PrettyPrintSig( + PCCOR_SIGNATURE typePtr, // type to convert, + unsigned typeLen, // the lenght of 'typePtr' + const char* name, // can be "", the name of the method for this sig 0 means local var sig + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig + __in_opt const char* inlabel, // prefix for names (NULL if no names required) + BOOL printTyArity=FALSE); // flag to print Type Param number (MemberRefs only) + +PCCOR_SIGNATURE PrettyPrintType( + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig + +PCCOR_SIGNATURE PrettyPrintTypeOrDef( // outside ILDASM - simple wrapper of PrettyPrintType + PCCOR_SIGNATURE typePtr, // type to convert, + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig + + +const char* PrettyPrintClass( + CQuickBytes *out, // where to put the pretty printed string + mdToken tk, // The class token to look up + IMDInternalImport *pIMDI); // ptr to IMDInternalImport class with ComSig + +//================= ILDASM-specific ================================================================== + +#ifdef __ILDASM__ + +#include "../ildasm/dynamicarray.h" + +bool IsNameToQuote(const char *name); +bool IsLocalToQuote(const char *name); +const char* UnquotedProperName(__in __nullterminated const char* name, unsigned len=(unsigned)-1); +const char* ProperName(__in __nullterminated const char* name, bool isLocalName = false); +#define ProperLocalName(x) ProperName(x, true) +const char* KEYWORD(__in_opt __nullterminated const char* szOrig); +const char* COMMENT(__in_opt __nullterminated const char* szOrig); +const char* ERRORMSG(__in_opt __nullterminated const char* szOrig); +const char* ANCHORPT(__in __nullterminated const char* szOrig, mdToken tk); +const char* JUMPPT(__in __nullterminated const char* szOrig, mdToken tk); +const char* SCOPE(void); +const char* UNSCOPE(void); +const char* LTN(void); +const char* GTN(void); +const char* AMP(void); + +extern BOOL g_fDumpRTF,g_fDumpHTML; // declared in FormatType.cpp +//------------------------------------------------------------------------------- +// Protection against null names +extern const char* const szStdNamePrefix[]; //declared in formatType.cpp + +extern DynamicArray *g_dups; +extern DWORD g_NumDups; +inline BOOL IsDup(mdToken tk) +{ + if(g_NumDups) + { + mdToken tktype = TypeFromToken(tk); + if((tktype==mdtTypeDef)||(tktype==mdtMethodDef)||(tktype==mdtFieldDef)) + { + for (unsigned i=0; i>24],tk&0x00FFFFFF); psz = sz; } } + + +struct TypeDefDescr +{ + char* szName; + mdToken tkTypeSpec; + mdToken tkSelf; + PCCOR_SIGNATURE psig; + ULONG cb; +}; +extern DynamicArray *g_typedefs; +extern DWORD g_NumTypedefs; + + +//------------------------------------------------------------------------------- +// Reference analysis (ILDASM) +struct TokPair +{ + mdToken tkUser; + mdToken tkRef; + TokPair() { tkUser = tkRef = 0; }; +}; +extern DynamicArray *g_refs; +extern DWORD g_NumRefs; +extern mdToken g_tkRefUser; // for PrettyPrintSig +#define REGISTER_REF(x,y) if(g_refs && (x)){ (*g_refs)[g_NumRefs].tkUser = x; (*g_refs)[g_NumRefs++].tkRef = y;} + +//-------------------------------------------------------------------------------- +// No-throw deallocators + +#define SDELETE(x) {PAL_CPP_TRY{ delete (x); } PAL_CPP_CATCH_ALL { _ASSERTE(!"AV in scalar deallocator");} PAL_CPP_ENDTRY; (x)=NULL; } +#define VDELETE(x) {PAL_CPP_TRY{ delete [] (x); } PAL_CPP_CATCH_ALL { _ASSERTE(!"AV in vector deallocator");}; PAL_CPP_ENDTRY; (x)=NULL; } + +//-------------------------------------------------------------------------------- +// Generic param names +extern mdToken g_tkVarOwner; +extern mdToken g_tkMVarOwner; +//void SetVarOwner(mdToken tk) { g_tkVarOwner = tk; } +//void SetMVarOwner(mdToken tk) { g_tkMVarOwner = tk; } +BOOL PrettyPrintGP( // defined in dasm.cpp + mdToken tkOwner, // Class, method or 0 + CQuickBytes *out, // where to put the pretty printed generic param + int n); // Index of generic param + +//============== End of ILDASM-specific ================================================================ + +#else + +#define IsNameToQuote(x) false +#define IsLocalToQuote(x) false +#define UnquotedProperName(x) x +#define ProperName(x) x +#define ProperLocalName(x) x +#define KEYWORD(x) x +#define COMMENT(x) x +#define ERRORMSG(x) x +#define ANCHORPT(x,y) x +#define JUMPPT(x,y) x +#define SCOPE() "{" +#define UNSCOPE() "}" +#define LTN() "<" +#define GTN() ">" +#define AMP() "&" +#define REGISTER_REF(x,y) {} +#define MAKE_NAME_IF_NONE(x,y) { } +#define g_fDumpTokens false +#define SDELETE(x) delete (x) +#define VDELETE(x) delete [] (x) + +#endif + +#endif diff --git a/lib/coreclr/src/inc/fstream.h b/lib/coreclr/src/inc/fstream.h new file mode 100644 index 0000000000..aa81ec8cfd --- /dev/null +++ b/lib/coreclr/src/inc/fstream.h @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef __FSTREAM_H_INCLUDED__ +#define __FSTREAM_H_INCLUDED__ + +#include + +class CFileStream : public IStream +{ + public: + CFileStream(); + virtual ~CFileStream(); + + HRESULT OpenForRead(LPCWSTR wzFilePath); + HRESULT OpenForWrite(LPCWSTR wzFilePath); + + // IUnknown methods: + STDMETHODIMP_(ULONG) AddRef(); + STDMETHODIMP_(ULONG) Release(); + STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj); + + // ISequentialStream methods: + STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead); + STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten); + + // IStream methods: + STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); + STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize); + STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); + STDMETHODIMP Commit(DWORD grfCommitFlags); + STDMETHODIMP Revert(); + STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); + STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); + STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag); + STDMETHODIMP Clone(IStream **ppIStream); + + private: + BOOL Close(); + + private: + LONG _cRef; + HANDLE _hFile; + +}; + +#endif + diff --git a/lib/coreclr/src/inc/fstring.h b/lib/coreclr/src/inc/fstring.h new file mode 100644 index 0000000000..9245885896 --- /dev/null +++ b/lib/coreclr/src/inc/fstring.h @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// FString.h (Fast String) +// + +// --------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------ +// FString is fast string handling namespace + + +// 1) Simple +// 2) No C++ exception +// 3) Optimized for speed + + +#ifndef _FSTRING_H_ +#define _FSTRING_H_ + +namespace FString +{ + // Note: All "length" parameters do not count the space for the null terminator. + // Caller of Unicode_Utf8 and Utf8_Unicode must pass in a buffer of size at least length + 1. + + // Scan for ASCII only string, calculate result UTF8 string length + HRESULT Unicode_Utf8_Length(__in_z LPCWSTR pString, __out bool * pAllAscii, __out DWORD * pLength); + + // Convert UNICODE string to UTF8 string. Direct/fast conversion if ASCII + HRESULT Unicode_Utf8(__in_z LPCWSTR pString, bool allAscii, __out_z LPSTR pBuffer, DWORD length); + + // Scan for ASCII string, calculate result UNICODE string length + HRESULT Utf8_Unicode_Length(__in_z LPCSTR pString, __out bool * pAllAscii, __out DWORD * pLength); + + // Convert UTF8 string to UNICODE. Direct/fast conversion if ASCII + HRESULT Utf8_Unicode(__in_z LPCSTR pString, bool allAscii, __out_z LPWSTR pBuffer, DWORD length); + + HRESULT ConvertUnicode_Utf8(__in_z LPCWSTR pString, __out_z LPSTR * pBuffer); + + HRESULT ConvertUtf8_Unicode(__in_z LPCSTR pString, __out_z LPWSTR * pBuffer); + +} // namespace FString + +#endif // _FSTRING_H_ diff --git a/lib/coreclr/src/inc/fusion.idl b/lib/coreclr/src/inc/fusion.idl new file mode 100644 index 0000000000..4056d168ba --- /dev/null +++ b/lib/coreclr/src/inc/fusion.idl @@ -0,0 +1,242 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// File: fusion.idl +// +// Contents: Fusion Interfaces +// +// Classes: +// +// Functions: +// +// +//---------------------------------------------------------------------------- + +cpp_quote("") +cpp_quote("#ifdef _MSC_VER") +cpp_quote("#pragma comment(lib,\"uuid.lib\")") +cpp_quote("#endif") +cpp_quote("") +cpp_quote("//---------------------------------------------------------------------------=") +cpp_quote("// Fusion Interfaces.") +cpp_quote("") + +import "objidl.idl"; + +cpp_quote("#ifdef _MSC_VER") +cpp_quote("#pragma once") +cpp_quote("#endif") + + +interface IAssemblyCache; +interface IAssemblyCacheItem; +interface IAssemblyName; +interface IAssemblyEnum; + + +cpp_quote("#ifndef PEKIND_ENUM_DEFINED") +cpp_quote("#define PEKIND_ENUM_DEFINED") +// This must match the definition of pekind in peinformation.h +typedef enum _tagPEKIND +{ + peNone = 0x00000000, + peMSIL = 0x00000001, + peI386 = 0x00000002, + peIA64 = 0x00000003, + peAMD64 = 0x00000004, + peARM = 0x00000005, + peARM64 = 0x00000006, + peInvalid = 0xffffffff +} PEKIND; +cpp_quote("#endif") + +typedef enum _tagAssemblyContentType +{ + AssemblyContentType_Default = 0x00000000, + AssemblyContentType_WindowsRuntime = 0x00000001, + AssemblyContentType_Invalid = 0xffffffff +} AssemblyContentType; + + +/////////////////////////////////////////////////////////////////////////////// +// +// IAssemblyName +// +/////////////////////////////////////////////////////////////////////////////// + +cpp_quote("// {CD193BC0-B4BC-11d2-9833-00C04FC31D2E}") +cpp_quote("EXTERN_GUID(IID_IAssemblyName, 0xCD193BC0, 0xB4BC, 0x11d2, 0x98, 0x33, 0x00, 0xC0, 0x4F, 0xC3, 0x1D, 0x2E);") + + +[ + local, + object, + uuid(CD193BC0-B4BC-11d2-9833-00C04FC31D2E), + pointer_default(unique) +] +interface IAssemblyName: IUnknown +{ + typedef [unique] IAssemblyName *LPASSEMBLYNAME; + + typedef enum { + CANOF_PARSE_DISPLAY_NAME = 0x1, + CANOF_SET_DEFAULT_VALUES = 0x2, + CANOF_VERIFY_FRIEND_ASSEMBLYNAME = 0x4, + CANOF_PARSE_FRIEND_DISPLAY_NAME = CANOF_PARSE_DISPLAY_NAME | CANOF_VERIFY_FRIEND_ASSEMBLYNAME + } CREATE_ASM_NAME_OBJ_FLAGS; + + typedef enum + { + ASM_NAME_PUBLIC_KEY = 0, // 0 + ASM_NAME_PUBLIC_KEY_TOKEN, // 1 + ASM_NAME_HASH_VALUE, // 2 + ASM_NAME_NAME, // 3 + ASM_NAME_MAJOR_VERSION, // 4 + ASM_NAME_MINOR_VERSION, // 5 + ASM_NAME_BUILD_NUMBER, // 6 + ASM_NAME_REVISION_NUMBER, // 7 + ASM_NAME_CULTURE, // 8 + ASM_NAME_PROCESSOR_ID_ARRAY, // 9 + ASM_NAME_OSINFO_ARRAY, // 10 ... 0x0a + ASM_NAME_HASH_ALGID, // 11 ... 0x0b + ASM_NAME_ALIAS, // 12 ... 0x0c + ASM_NAME_CODEBASE_URL, // 13 ... 0x0d + ASM_NAME_CODEBASE_LASTMOD, // 14 ... 0x0e + ASM_NAME_NULL_PUBLIC_KEY, // 15 ... 0x0f + ASM_NAME_NULL_PUBLIC_KEY_TOKEN, // 16 ... 0x10 + ASM_NAME_CUSTOM, // 17 ... 0x11 + ASM_NAME_NULL_CUSTOM, // 18 ... 0x12 + ASM_NAME_MVID, // 19 ... 0x13 + ASM_NAME_FILE_MAJOR_VERSION, // 20 ... 0x14 + ASM_NAME_FILE_MINOR_VERSION, // 21 ... 0x15 + ASM_NAME_FILE_BUILD_NUMBER, // 22 ... 0x16 + ASM_NAME_FILE_REVISION_NUMBER, // 23 ... 0x17 + ASM_NAME_RETARGET, // 24 ... 0x18 + ASM_NAME_SIGNATURE_BLOB, // 25 ... 0x19 + ASM_NAME_CONFIG_MASK, // 26 ... 0x1a + ASM_NAME_ARCHITECTURE, // 27 ... 0x1b + ASM_NAME_CONTENT_TYPE, // 28 ... 0x1c + ASM_NAME_MAX_PARAMS // 29 ... 0x1d + } ASM_NAME; + + typedef enum + { + ASM_DISPLAYF_VERSION = 0x1, + ASM_DISPLAYF_CULTURE = 0x2, + ASM_DISPLAYF_PUBLIC_KEY_TOKEN = 0x4, + ASM_DISPLAYF_PUBLIC_KEY = 0x8, + ASM_DISPLAYF_CUSTOM = 0x10, + ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20, + ASM_DISPLAYF_LANGUAGEID = 0x40, + ASM_DISPLAYF_RETARGET = 0x80, + ASM_DISPLAYF_CONFIG_MASK = 0x100, + ASM_DISPLAYF_MVID = 0x200, + ASM_DISPLAYF_CONTENT_TYPE = 0x400, + + + // ASM_DISPLAYF_FULL shows the full identity of the assembly. + // It should be used when you are working with APIs taking + // assembly full identity, such as GAC APIs. + // + // WARNING!!! ASM_DISPLAYF_FULL will change in the future, + // when we introduce new attributes. This means the identity returned + // will change from CLR version to version. Don't ever assume + // the identity will not change. !!! + ASM_DISPLAYF_FULL = ASM_DISPLAYF_VERSION + | ASM_DISPLAYF_CULTURE + | ASM_DISPLAYF_PUBLIC_KEY_TOKEN + | ASM_DISPLAYF_RETARGET + | ASM_DISPLAYF_PROCESSORARCHITECTURE + | ASM_DISPLAYF_CONTENT_TYPE, + } ASM_DISPLAY_FLAGS; + + typedef enum + { + ASM_CMPF_NAME = 0x1, + + ASM_CMPF_MAJOR_VERSION = 0x2, + ASM_CMPF_MINOR_VERSION = 0x4, + ASM_CMPF_BUILD_NUMBER = 0x8, + ASM_CMPF_REVISION_NUMBER = 0x10, + + ASM_CMPF_VERSION = ASM_CMPF_MAJOR_VERSION + |ASM_CMPF_MINOR_VERSION + |ASM_CMPF_BUILD_NUMBER + |ASM_CMPF_REVISION_NUMBER, + + ASM_CMPF_PUBLIC_KEY_TOKEN = 0x20, + ASM_CMPF_CULTURE = 0x40, + ASM_CMPF_CUSTOM = 0x80, + + ASM_CMPF_DEFAULT = 0x100, + + ASM_CMPF_RETARGET = 0x200, + ASM_CMPF_ARCHITECTURE = 0x400, + ASM_CMPF_CONFIG_MASK = 0x800, + ASM_CMPF_MVID = 0x1000, + ASM_CMPF_SIGNATURE = 0x2000, + ASM_CMPF_CONTENT_TYPE = 0x4000, + + ASM_CMPF_IL_ALL = ASM_CMPF_NAME + | ASM_CMPF_VERSION + | ASM_CMPF_PUBLIC_KEY_TOKEN + | ASM_CMPF_CULTURE, + + ASM_CMPF_IL_NO_VERSION = ASM_CMPF_NAME + | ASM_CMPF_PUBLIC_KEY_TOKEN + | ASM_CMPF_CULTURE + } ASM_CMP_FLAGS; + + HRESULT SetProperty( + [in] DWORD PropertyId, + [in] void const * pvProperty, + [in] DWORD cbProperty); + + HRESULT GetProperty( + [in] DWORD PropertyId, + [out] LPVOID pvProperty, + [in, out] LPDWORD pcbProperty); + + HRESULT Finalize(); + + HRESULT GetDisplayName( + [out, annotation("_Out_writes_opt_(*pccDisplayName)")] + LPOLESTR szDisplayName, + [in, out] LPDWORD pccDisplayName, + [in] DWORD dwDisplayFlags); + + HRESULT Reserved( + [in] REFIID refIID, + [in] IUnknown *pUnkReserved1, + [in] IUnknown *pUnkReserved2, + [in] LPCOLESTR szReserved, + [in] LONGLONG llReserved, + [in] LPVOID pvReserved, + [in] DWORD cbReserved, + [out] LPVOID *ppReserved); + + + HRESULT GetName( + [in, out, annotation("_Inout_")] LPDWORD lpcwBuffer, + [out, annotation("_Out_writes_opt_(*lpcwBuffer)")] WCHAR *pwzName); + + HRESULT GetVersion( + [out] LPDWORD pdwVersionHi, + [out] LPDWORD pdwVersionLow); + + HRESULT IsEqual( + [in] IAssemblyName *pName, + [in] DWORD dwCmpFlags); + + HRESULT Clone( + [out] IAssemblyName **pName); + +} + + +#pragma midl_echo("STDAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj, LPCWSTR szAssemblyName, DWORD dwFlags, LPVOID pvReserved); ") + diff --git a/lib/coreclr/src/inc/gcdecoder.cpp b/lib/coreclr/src/inc/gcdecoder.cpp new file mode 100644 index 0000000000..ed3f1f34d7 --- /dev/null +++ b/lib/coreclr/src/inc/gcdecoder.cpp @@ -0,0 +1,624 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XX XX +XX GCDecode XX +XX XX +XX Logic to decode the JIT method header and GC pointer tables XX +XX XX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +*/ + +// ****************************************************************************** +// WARNING!!!: This code is also used by SOS in the diagnostics repo. Should be +// updated in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcdecoder.cpp +// ****************************************************************************** + +#ifdef _TARGET_X86_ + +/* This file is shared between the VM and JIT/IL and SOS/Strike directories */ + +#include "gcinfotypes.h" + +/*****************************************************************************/ +/* + * This entire file depends upon GC2_ENCODING being set to 1 + * + *****************************************************************************/ + +size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* val) +{ + LIMITED_METHOD_CONTRACT; + + size_t size = 1; + BYTE byte = *src++; + unsigned value = byte & 0x7f; + while (byte & 0x80) { + size++; + byte = *src++; + value <<= 7; + value += byte & 0x7f; + } + *val = value; + return size; +} + +size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + unsigned delta; + size_t size = decodeUnsigned(src, &delta); + *value = lastValue + delta; + return size; +} + +size_t FASTCALL decodeSigned(PTR_CBYTE src, int* val) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + } CONTRACTL_END; + + size_t size = 1; + BYTE byte = *src++; + BYTE first = byte; + int value = byte & 0x3f; + while (byte & 0x80) + { + size++; + byte = *src++; + value <<= 7; + value += byte & 0x7f; + } + if (first & 0x40) + value = -value; + *val = value; + return size; +} + +/*****************************************************************************/ + +#if defined(_MSC_VER) +#pragma optimize("tgy", on) +#endif + +PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header) +{ + LIMITED_METHOD_DAC_CONTRACT; + + BYTE nextByte = *table++; + BYTE encoding = nextByte & 0x7f; + GetInfoHdr(encoding, header); + while (nextByte & MORE_BYTES_TO_FOLLOW) + { + nextByte = *table++; + encoding = nextByte & ADJ_ENCODING_MAX; + // encoding here always corresponds to codes in InfoHdrAdjust set + + if (encoding < NEXT_FOUR_START) + { + if (encoding < SET_ARGCOUNT) + { + header->frameSize = encoding - SET_FRAMESIZE; + } + else if (encoding < SET_PROLOGSIZE) + { + header->argCount = encoding - SET_ARGCOUNT; + } + else if (encoding < SET_EPILOGSIZE) + { + header->prologSize = encoding - SET_PROLOGSIZE; + } + else if (encoding < SET_EPILOGCNT) + { + header->epilogSize = encoding - SET_EPILOGSIZE; + } + else if (encoding < SET_UNTRACKED) + { + header->epilogCount = (encoding - SET_EPILOGCNT) / 2; + header->epilogAtEnd = ((encoding - SET_EPILOGCNT) & 1) == 1; + assert(!header->epilogAtEnd || (header->epilogCount == 1)); + } + else if (encoding < FIRST_FLIP) + { + header->untrackedCnt = encoding - SET_UNTRACKED; + _ASSERTE(header->untrackedCnt != HAS_UNTRACKED); + } + else switch (encoding) + { + default: + assert(!"Unexpected encoding"); + break; + case FLIP_EDI_SAVED: + header->ediSaved ^= 1; + break; + case FLIP_ESI_SAVED: + header->esiSaved ^= 1; + break; + case FLIP_EBX_SAVED: + header->ebxSaved ^= 1; + break; + case FLIP_EBP_SAVED: + header->ebpSaved ^= 1; + break; + case FLIP_EBP_FRAME: + header->ebpFrame ^= 1; + break; + case FLIP_INTERRUPTIBLE: + header->interruptible ^= 1; + break; + case FLIP_DOUBLE_ALIGN: + header->doubleAlign ^= 1; + break; + case FLIP_SECURITY: + header->security ^= 1; + break; + case FLIP_HANDLERS: + header->handlers ^= 1; + break; + case FLIP_LOCALLOC: + header->localloc ^= 1; + break; + case FLIP_EDITnCONTINUE: + header->editNcontinue ^= 1; + break; + case FLIP_VAR_PTR_TABLE_SZ: + header->varPtrTableSize ^= HAS_VARPTR; + break; + case FFFF_UNTRACKED_CNT: + header->untrackedCnt = HAS_UNTRACKED; + break; + case FLIP_VARARGS: + header->varargs ^= 1; + break; + case FLIP_PROF_CALLBACKS: + header->profCallbacks ^= 1; + break; + case FLIP_HAS_GENERICS_CONTEXT: + header->genericsContext ^= 1; + break; + case FLIP_GENERICS_CONTEXT_IS_METHODDESC: + header->genericsContextIsMethodDesc ^= 1; + break; + case FLIP_HAS_GS_COOKIE: + header->gsCookieOffset ^= HAS_GS_COOKIE_OFFSET; + break; + case FLIP_SYNC: + header->syncStartOffset ^= HAS_SYNC_OFFSET; + break; + case FLIP_REV_PINVOKE_FRAME: + _ASSERTE(GCInfoEncodesRevPInvokeFrame(version)); + header->revPInvokeOffset ^= HAS_REV_PINVOKE_FRAME_OFFSET; + break; + + case NEXT_OPCODE: + _ASSERTE((nextByte & MORE_BYTES_TO_FOLLOW) && "Must have another code"); + nextByte = *table++; + encoding = nextByte & ADJ_ENCODING_MAX; + // encoding here always corresponds to codes in InfoHdrAdjust2 set + + if (encoding < SET_RET_KIND_MAX) + { + _ASSERTE(GCInfoEncodesReturnKind(version)); + header->returnKind = (ReturnKind)encoding; + } + else + { + assert(!"Unexpected encoding"); + } + break; + } + } + else + { + unsigned char lowBits; + switch (encoding >> 4) + { + default: + assert(!"Unexpected encoding"); + break; + case 5: + assert(NEXT_FOUR_FRAMESIZE == 0x50); + lowBits = encoding & 0xf; + header->frameSize <<= 4; + header->frameSize += lowBits; + break; + case 6: + assert(NEXT_FOUR_ARGCOUNT == 0x60); + lowBits = encoding & 0xf; + header->argCount <<= 4; + header->argCount += lowBits; + break; + case 7: + if ((encoding & 0x8) == 0) + { + assert(NEXT_THREE_PROLOGSIZE == 0x70); + lowBits = encoding & 0x7; + header->prologSize <<= 3; + header->prologSize += lowBits; + } + else + { + assert(NEXT_THREE_EPILOGSIZE == 0x78); + lowBits = encoding & 0x7; + header->epilogSize <<= 3; + header->epilogSize += lowBits; + } + break; + } + } + } + return table; +} + +void FASTCALL decodeCallPattern(int pattern, + unsigned * argCnt, + unsigned * regMask, + unsigned * argMask, + unsigned * codeDelta) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } CONTRACTL_END; + + assert((pattern>=0) && (pattern<80)); + CallPattern pat; + pat.val = callPatternTable[pattern]; + *argCnt = pat.fld.argCnt; + *regMask = pat.fld.regMask; // EBP,EBX,ESI,EDI + *argMask = pat.fld.argMask; + *codeDelta = pat.fld.codeDelta; +} + +#define YES HAS_VARPTR + +const InfoHdrSmall infoHdrShortcut[128] = { +// Prolog size +// | +// | Epilog size +// | | +// | | Epilog count +// | | | +// | | | Epilog at end +// | | | | +// | | | | EDI saved +// | | | | | +// | | | | | ESI saved +// | | | | | | +// | | | | | | EBX saved +// | | | | | | | +// | | | | | | | EBP saved +// | | | | | | | | +// | | | | | | | | EBP-frame +// | | | | | | | | | +// | | | | | | | | | Interruptible method +// | | | | | | | | | | +// | | | | | | | | | | doubleAlign +// | | | | | | | | | | | +// | | | | | | | | | | | security flag +// | | | | | | | | | | | | +// | | | | | | | | | | | | handlers +// | | | | | | | | | | | | | +// | | | | | | | | | | | | | localloc +// | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | edit and continue +// | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | varargs +// | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | ProfCallbacks +// | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | genericsContext +// | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | genericsContextIsMethodDesc +// | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | returnKind +// | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | Arg count +// | | | | | | | | | | | | | | | | | | | | | Counted occurences +// | | | | | | | | | | | | | | | | | | | | | Frame size | +// | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | untrackedCnt | Header encoding +// | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | varPtrTable | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | gsCookieOffs | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | syncOffs | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +// v v v v v v v v v v v v v v v v v v v v v v v v v v v v v + { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1139 00 + { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 128738 01 + { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3696 02 + { 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 402 03 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 4259 04 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 3379 05 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 2058 06 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 728 07 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 984 08 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, // 606 09 + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0 }, // 1110 0a + { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0 }, // 414 0b + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1553 0c + { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 584 0d + { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 2182 0e + { 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3445 0f + { 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1369 10 + { 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 515 11 + { 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 21127 12 + { 1, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3517 13 + { 1, 2, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 750 14 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1876 15 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1665 16 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 729 17 + { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 484 18 + { 1, 4, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 331 19 + { 2, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 1a + { 2, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 964 1b + { 2, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3713 1c + { 2, 3, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 466 1d + { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1325 1e + { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 712 1f + { 2, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 588 20 + { 2, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 20542 21 + { 2, 3, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3802 22 + { 2, 3, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 798 23 + { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1900 24 + { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 385 25 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1617 26 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1743 27 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 909 28 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 602 29 + { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 352 2a + { 2, 6, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 657 2b + { 2, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1283 2c + { 2, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1286 2d + { 3, 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1495 2e + { 3, 4, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1989 2f + { 3, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1154 30 + { 3, 4, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 9300 31 + { 3, 4, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 392 32 + { 3, 4, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1720 33 + { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1246 34 + { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 800 35 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1179 36 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1368 37 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 349 38 + { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 505 39 + { 3, 6, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 629 3a + { 3, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, YES }, // 365 3b + { 4, 5, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 487 3c + { 4, 5, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1752 3d + { 4, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1959 3e + { 4, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2436 3f + { 4, 5, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 861 40 + { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1459 41 + { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 950 42 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1491 43 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 879 44 + { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 408 45 + { 5, 4, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4870 46 + { 5, 6, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 359 47 + { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 915 48 + { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 412 49 + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1288 4a + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1591 4b + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 361 4c + { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0 }, // 623 4d + { 5, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 1239 4e + { 6, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 457 4f + { 6, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 606 50 + { 6, 4, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1073 51 + { 6, 4, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 508 52 + { 6, 6, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 330 53 + { 6, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1709 54 + { 6, 7, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1164 55 + { 7, 4, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 556 56 + { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 529 57 + { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 1423 58 + { 7, 8, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 2455 59 + { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 956 5a + { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1399 5b + { 7, 8, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 587 5c + { 7, 10, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 743 5d + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // 1004 5e + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, YES }, // 487 5f + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0 }, // 337 60 + { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, YES }, // 361 61 + { 8, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 560 62 + { 8, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1377 63 + { 9, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 877 64 + { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 3041 65 + { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 349 66 + { 10, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 2061 67 + { 10, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 577 68 + { 11, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 1195 69 + { 12, 5, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 491 6a + { 13, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, YES }, // 627 6b + { 13, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0 }, // 1099 6c + { 13, 10, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 488 6d + { 14, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 574 6e + { 16, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 1281 6f + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1881 70 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 339 71 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, // 2594 72 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 339 73 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 2107 74 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 2372 75 + { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, YES }, // 1078 76 + { 16, 7, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 384 77 + { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, YES }, // 1541 78 + { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, YES }, // 975 79 + { 19, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 546 7a + { 24, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 675 7b + { 45, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 902 7c + { 51, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, YES }, // 432 7d + { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 7e + { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0 }, // 703 7f +}; + +bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const +{ +#ifdef _ASSERTE + // target cannot have place-holder values. + _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && + target.varPtrTableSize != HAS_VARPTR && + target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && + target.syncStartOffset != HAS_SYNC_OFFSET && + target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); +#endif + + // compare two InfoHdr's up to but not including the untrackCnt field + if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0) + return false; + + if (untrackedCnt != target.untrackedCnt) { + if (target.untrackedCnt <= SET_UNTRACKED_MAX) + return false; + else if (untrackedCnt != HAS_UNTRACKED) + return false; + } + + if (varPtrTableSize != target.varPtrTableSize) { + if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0)) + return false; + } + + if (target.gsCookieOffset != INVALID_GS_COOKIE_OFFSET) + return false; + + if (target.syncStartOffset != INVALID_SYNC_OFFSET) + return false; + + if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET) + return false; + + return true; +} + + +const unsigned callCommonDelta[4] = { 6,8,10,12 }; + +/* + * In the callPatternTable each 32-bit unsigned value represents four bytes: + * + * byte0,byte1,byte2,byte3 => codeDelta,argMask,regMask,argCnt + * for example 0x0c000301 => codeDelta of 12, argMask of 0, + * regMask of 0x3, argCnt of 1 + * + * Furthermore within the table the following maximum values are in place: + * + * codeDelta <= CP_MAX_CODE_DELTA // (0x23) + * argCnt <= CP_MAX_ARG_CNT // (0x02) + * argMask <= CP_MAX_ARG_MASK // (0x00) + * + * Note that ARG_CNT is the count of pushed args for a nested call site. + * And since the first two arguments are always passed in registers + * an ARG_CNT of 1 would mean that the nested call site had three arguments + * + * Note that ARG_MASK is the mask of pushed args that contain GC pointers + * since the first two arguments are always passed in registers it is + * a fairly rare occurance to push a GC pointer as an argument, since it + * only occurs for nested calls, when the third or later argument for the + * outer call contains a GC ref. + * + * Additionally the encoding of the regMask uses the following bits: + * EDI = 0x1, ESI = 0x2, EBX = 0x4, EBP = 0x8 + * + */ +const unsigned callPatternTable[80] = { // # of occurences + 0x0a000200, // 30109 + 0x0c000200, // 22970 + 0x0c000201, // 19005 + 0x0a000300, // 12193 + 0x0c000300, // 10614 + 0x0e000200, // 10253 + 0x10000200, // 9746 + 0x0b000200, // 9698 + 0x0d000200, // 9625 + 0x08000200, // 8909 + 0x0c000301, // 8522 + 0x11000200, // 7382 + 0x0e000300, // 7357 + 0x12000200, // 7139 + 0x10000300, // 7062 + 0x11000300, // 6970 + 0x0a000201, // 6842 + 0x0a000100, // 6803 + 0x0f000200, // 6795 + 0x13000200, // 6559 + 0x08000300, // 6079 + 0x15000200, // 5874 + 0x0d000201, // 5492 + 0x0c000100, // 5193 + 0x0d000300, // 5165 + 0x23000200, // 5143 + 0x1b000200, // 5035 + 0x14000200, // 4872 + 0x0f000300, // 4850 + 0x0a000700, // 4781 + 0x09000200, // 4560 + 0x12000300, // 4496 + 0x16000200, // 4180 + 0x07000200, // 4021 + 0x09000300, // 4012 + 0x0c000700, // 3988 + 0x0c000600, // 3946 + 0x0e000100, // 3823 + 0x1a000200, // 3764 + 0x18000200, // 3744 + 0x17000200, // 3736 + 0x1f000200, // 3671 + 0x13000300, // 3559 + 0x0a000600, // 3214 + 0x0e000600, // 3109 + 0x08000201, // 2984 + 0x0b000300, // 2928 + 0x0a000301, // 2859 + 0x07000100, // 2826 + 0x13000100, // 2782 + 0x09000301, // 2644 + 0x19000200, // 2638 + 0x11000700, // 2618 + 0x21000200, // 2518 + 0x0d000202, // 2484 + 0x10000100, // 2480 + 0x0f000600, // 2413 + 0x14000300, // 2363 + 0x0c000500, // 2362 + 0x08000301, // 2285 + 0x20000200, // 2245 + 0x10000700, // 2240 + 0x0f000100, // 2236 + 0x1e000200, // 2214 + 0x0c000400, // 2193 + 0x16000300, // 2171 + 0x12000600, // 2132 + 0x22000200, // 2011 + 0x1d000200, // 2011 + 0x0c000f00, // 1996 + 0x0e000700, // 1971 + 0x0a000400, // 1970 + 0x09000201, // 1932 + 0x10000600, // 1903 + 0x15000300, // 1847 + 0x0a000101, // 1814 + 0x0a000b00, // 1771 + 0x0c000601, // 1737 + 0x09000700, // 1737 + 0x07000300, // 1684 +}; + +#endif // _TARGET_X86_ diff --git a/lib/coreclr/src/inc/gcdump.h b/lib/coreclr/src/inc/gcdump.h new file mode 100644 index 0000000000..3271ca1d6b --- /dev/null +++ b/lib/coreclr/src/inc/gcdump.h @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + * GCDump.h + * + * Defines functions to display the GCInfo as defined by the GC-encoding + * spec. The GC information may be either dynamically created by a + * Just-In-Time compiler conforming to the standard code-manager spec, + * or may be persisted by a managed native code compiler conforming + * to the standard code-manager spec. + */ + +/*****************************************************************************/ +#ifndef __GCDUMP_H__ +#define __GCDUMP_H__ +/*****************************************************************************/ + +#include "gcinfotypes.h" // For InfoHdr + +#ifndef FASTCALL +#ifndef FEATURE_PAL +#define FASTCALL __fastcall +#else +#define FASTCALL +#endif +#endif + + +class GCDump +{ +public: + + GCDump (UINT32 gcInfoVersion, + bool encBytes = true, + unsigned maxEncBytes = 5, + bool dumpCodeOffs = true); + +#ifdef _TARGET_X86_ + /*------------------------------------------------------------------------- + * Dumps the InfoHdr to 'stdout' + * table : Start of the GC info block + * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES + * Return value : Size in bytes of the header encoding + */ + + unsigned FASTCALL DumpInfoHdr (PTR_CBYTE gcInfoBlock, + InfoHdr * header, /* OUT */ + unsigned * methodSize, /* OUT */ + bool verifyGCTables = false); +#endif + + /*------------------------------------------------------------------------- + * Dumps the GC tables to 'stdout' + * gcInfoBlock : Start of the GC info block + * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES + * Return value : Size in bytes of the GC table encodings + */ + + size_t FASTCALL DumpGCTable (PTR_CBYTE gcInfoBlock, +#ifdef _TARGET_X86_ + const InfoHdr& header, +#endif + unsigned methodSize, + bool verifyGCTables = false); + + /*------------------------------------------------------------------------- + * Dumps the location of ptrs for the given code offset + * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES + */ + + void FASTCALL DumpPtrsInFrame(PTR_CBYTE gcInfoBlock, + PTR_CBYTE codeBlock, + unsigned offs, + bool verifyGCTables = false); + + +public: + typedef void (*printfFtn)(const char* fmt, ...); + printfFtn gcPrintf; + UINT32 gcInfoVersion; + //------------------------------------------------------------------------- +protected: + + bool fDumpEncBytes; + unsigned cMaxEncBytes; + + bool fDumpCodeOffsets; + + /* Helper methods */ + + PTR_CBYTE DumpEncoding(PTR_CBYTE gcInfoBlock, + int cDumpBytes); + void DumpOffset (unsigned o); + void DumpOffsetEx(unsigned o); + +}; + +/*****************************************************************************/ +#endif // __GC_DUMP_H__ +/*****************************************************************************/ diff --git a/lib/coreclr/src/inc/gcinfo.h b/lib/coreclr/src/inc/gcinfo.h new file mode 100644 index 0000000000..acdfe6589a --- /dev/null +++ b/lib/coreclr/src/inc/gcinfo.h @@ -0,0 +1,95 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ****************************************************************************** +// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should +// added or removed in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfo.h +// ****************************************************************************** + +/*****************************************************************************/ +#ifndef _GCINFO_H_ +#define _GCINFO_H_ +/*****************************************************************************/ + +#include "daccess.h" +#include "windef.h" // For BYTE + +// Some declarations in this file are used on non-x86 platforms, but most are x86-specific. + +// Use the lower 2 bits of the offsets stored in the tables +// to encode properties + +const unsigned OFFSET_MASK = 0x3; // mask to access the low 2 bits + +// +// Note for untracked locals the flags allowed are "pinned" and "byref" +// and for tracked locals the flags allowed are "this" and "byref" +// Note that these definitions should also match the definitions of +// GC_CALL_INTERIOR and GC_CALL_PINNED in VM/gc.h +// +const unsigned byref_OFFSET_FLAG = 0x1; // the offset is an interior ptr +const unsigned pinned_OFFSET_FLAG = 0x2; // the offset is a pinned ptr +#if !defined(_TARGET_X86_) || !defined(WIN64EXCEPTIONS) +const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" +#endif + +//----------------------------------------------------------------------------- +// The current GCInfo Version +//----------------------------------------------------------------------------- + +#define GCINFO_VERSION 2 + +#define MIN_GCINFO_VERSION_WITH_RETURN_KIND 2 +#define MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME 2 + +inline BOOL GCInfoEncodesReturnKind(UINT32 version=GCINFO_VERSION) +{ + return version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND; +} + +inline BOOL GCInfoEncodesRevPInvokeFrame(UINT32 version=GCINFO_VERSION) +{ + return version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME; +} + +//----------------------------------------------------------------------------- +// GCInfoToken: A wrapper that contains the GcInfo data and version number. +// +// The version# is not stored in the GcInfo structure -- because it is +// wasteful to store the version once for every method. +// Instead, the version# istracked per range-section of generated/loaded methods. +// +// The GCInfo version is computed as : +// 1) The current GCINFO_VERSION for JITted and Ngened images +// 2) A function of the Ready - to - run major version stored in READYTORUN_HEADER +// for ready - to - run images.ReadyToRunJitManager::JitTokenToGCInfoVersion() +// provides the GcInfo version for any Method. +//----------------------------------------------------------------------------- + +struct GCInfoToken +{ + PTR_VOID Info; + UINT32 Version; + + BOOL IsReturnKindAvailable() + { + return GCInfoEncodesReturnKind(Version); + } + BOOL IsReversePInvokeFrameAvailable() + { + return GCInfoEncodesRevPInvokeFrame(Version); + } + + static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion) + { + // GcInfo version is 1 up to ReadyTorun version 1.x + // GcInfo version is current from ReadyToRun version 2.0 + return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION; + } +}; + +/*****************************************************************************/ +#endif //_GCINFO_H_ +/*****************************************************************************/ diff --git a/lib/coreclr/src/inc/gcinfoarraylist.h b/lib/coreclr/src/inc/gcinfoarraylist.h new file mode 100644 index 0000000000..c19f00d42f --- /dev/null +++ b/lib/coreclr/src/inc/gcinfoarraylist.h @@ -0,0 +1,114 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _GCINFOARRAYLIST_H_ +#define _GCINFOARRAYLIST_H_ + +// GCInfoArrayList is basically a more efficient linked list--it's useful for accumulating +// lots of small fixed-size allocations into larger chunks which in a typical linked list +// would incur an unnecessarily high amount of overhead. + +class GcInfoArrayListBase +{ +private: + static const size_t GrowthFactor = 2; + +protected: + friend class IteratorBase; + + struct ChunkBase + { + ChunkBase* m_next; // actually GcInfoArrayListChunk* + }; + + class IteratorBase + { + protected: + IteratorBase(GcInfoArrayListBase* list, size_t firstChunkCapacity); + ChunkBase* GetNextChunk(size_t& elementCount); + + private: + GcInfoArrayListBase* m_list; + ChunkBase* m_currentChunk; + size_t m_currentChunkCount; + }; + + GcInfoArrayListBase(IAllocator* allocator); + virtual ~GcInfoArrayListBase(); + + void AppendNewChunk(size_t firstChunkCapacity, size_t elementSize, size_t chunkAlignment); + +public: + size_t Count() + { + return m_itemCount; + } + +protected: + IAllocator* m_allocator; + ChunkBase* m_firstChunk; // actually GcInfoArrayListChunk* + ChunkBase* m_lastChunk; // actually GcInfoArrayListChunk* + size_t m_lastChunkCount; + size_t m_lastChunkCapacity; + size_t m_itemCount; +}; + +template +class GcInfoArrayList : public GcInfoArrayListBase +{ +private: + struct Chunk : public ChunkBase + { + ElementType m_items[]; + }; + +public: + friend class Iterator; + + struct Iterator : IteratorBase + { + Iterator(GcInfoArrayList* list) + : IteratorBase(list, FirstChunkCapacity) + { + } + + ElementType* GetNext(size_t* elementCount) + { + Chunk* chunk = reinterpret_cast(GetNextChunk(*elementCount)); + return chunk == nullptr ? nullptr : &chunk->m_items[0]; + } + }; + + GcInfoArrayList(IAllocator* allocator) + : GcInfoArrayListBase(allocator) + { + } + + ElementType* Append() + { + if (m_lastChunk == nullptr || m_lastChunkCount == m_lastChunkCapacity) + { + AppendNewChunk(FirstChunkCapacity, sizeof(ElementType), __alignof(ElementType)); + } + + m_itemCount++; + m_lastChunkCount++; + return &reinterpret_cast(m_lastChunk)->m_items[m_lastChunkCount - 1]; + } + + void CopyTo(ElementType* dest) + { + Iterator iter(this); + ElementType* source; + size_t elementCount; + + while (source = iter.GetNext(&elementCount), source != nullptr) + { + memcpy(dest, source, elementCount * sizeof(ElementType)); + dest += elementCount; + } + } +}; + +#endif diff --git a/lib/coreclr/src/inc/gcinfodecoder.h b/lib/coreclr/src/inc/gcinfodecoder.h new file mode 100644 index 0000000000..dfaa3b16ae --- /dev/null +++ b/lib/coreclr/src/inc/gcinfodecoder.h @@ -0,0 +1,706 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************** + * + * GC Information Decoding API + * + *****************************************************************/ + +// ****************************************************************************** +// WARNING!!!: These values are used by SOS in the diagnostics repo. Values should +// added or removed in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfodecoder.h +// ****************************************************************************** + +#ifndef _GC_INFO_DECODER_ +#define _GC_INFO_DECODER_ + +#define _max(a, b) (((a) > (b)) ? (a) : (b)) +#define _min(a, b) (((a) < (b)) ? (a) : (b)) + +#if !defined(_TARGET_X86_) +#define USE_GC_INFO_DECODER +#endif + +#if !defined(GCINFODECODER_NO_EE) + +#include "eetwain.h" + +#else + +#ifdef FEATURE_REDHAWK + +typedef ArrayDPTR(const uint8_t) PTR_CBYTE; + +#define LIMITED_METHOD_CONTRACT +#define SUPPORTS_DAC + +#define LOG(x) +#define LOG_PIPTR(pObjRef, gcFlags, hCallBack) +#define DAC_ARG(x) + +#define VALIDATE_ROOT(isInterior, hCallBack, pObjRef) + +#define _ASSERTE(x) assert(x) + +#define UINT32 UInt32 +#define INT32 Int32 +#define UINT16 UInt16 +#define UINT UInt32 +#define SIZE_T UIntNative +#define SSIZE_T IntNative +#define LPVOID void* + +typedef void * OBJECTREF; + +#define GET_CALLER_SP(pREGDISPLAY) ((TADDR)0) + +#else // FEATURE_REDHAWK + +// Stuff from cgencpu.h: + +#ifndef __cgencpu_h__ + +inline void SetIP(T_CONTEXT* context, PCODE rip) +{ + _ASSERTE(!"don't call this"); +} + +inline TADDR GetSP(T_CONTEXT* context) +{ +#ifdef _TARGET_AMD64_ + return (TADDR)context->Rsp; +#elif defined(_TARGET_ARM_) + return (TADDR)context->Sp; +#elif defined(_TARGET_ARM64_) + return (TADDR)context->Sp; +#else + _ASSERTE(!"nyi for platform"); +#endif +} + +inline PCODE GetIP(T_CONTEXT* context) +{ +#ifdef _TARGET_AMD64_ + return (PCODE) context->Rip; +#elif defined(_TARGET_ARM_) + return (PCODE)context->Pc; +#elif defined(_TARGET_ARM64_) + return (PCODE)context->Pc; +#else + _ASSERTE(!"nyi for platform"); +#endif +} + +#endif // !__cgencpu_h__ + +// Misc. VM types: + +#ifndef DEFINE_OBJECTREF +#define DEFINE_OBJECTREF +class Object; +typedef Object *OBJECTREF; +#endif +typedef SIZE_T TADDR; + +// Stuff from gc.h: + +#ifndef __GC_H + +#define GC_CALL_INTERIOR 0x1 +#define GC_CALL_PINNED 0x2 + +#endif // !__GC_H + +// Stuff from stdmacros.h (can't include because it includes contract.h, which uses #pragma once) + +#ifndef _stdmacros_h_ + +inline BOOL IS_ALIGNED( size_t val, size_t alignment ) +{ + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE( 0 == (alignment & (alignment - 1)) ); + return 0 == (val & (alignment - 1)); +} +inline BOOL IS_ALIGNED( void* val, size_t alignment ) +{ + return IS_ALIGNED( (size_t) val, alignment ); +} + +#define FMT_REG "r%d " +#define FMT_STK "sp%s0x%02x " + +#define DBG_STK(off) \ + (off >= 0) ? "+" : "-", \ + (off >= 0) ? off : -off + +#endif + +// Stuff from check.h: + +#ifndef UNREACHABLE +#define UNREACHABLE() __assume(0) +#endif + +// Stuff from eetwain.h: + +#ifndef _EETWAIN_H + +typedef void (*GCEnumCallback)( + void * hCallback, // callback data + OBJECTREF* pObject, // address of obect-reference we are reporting + uint32_t flags // is this a pinned and/or interior pointer +); + +#endif // !_EETWAIN_H + +#include "regdisp.h" + +#endif // FEATURE_REDHAWK + +#ifndef _strike_h + +enum ICodeManagerFlags +{ + ActiveStackFrame = 0x0001, // this is the currently active function + ExecutionAborted = 0x0002, // execution of this function has been aborted + // (i.e. it will not continue execution at the + // current location) + ParentOfFuncletStackFrame + = 0x0040, // A funclet for this frame was previously reported + + NoReportUntracked + = 0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include + // any untracked slots +}; + +#endif // !_strike_h + +#endif // GCINFODECODER_NO_EE + + +#include "gcinfotypes.h" + +#ifdef _DEBUG + #define MAX_PREDECODED_SLOTS 4 +#else + #define MAX_PREDECODED_SLOTS 64 +#endif + + + +enum GcInfoDecoderFlags +{ + DECODE_EVERYTHING = 0x0, + DECODE_SECURITY_OBJECT = 0x01, // stack location of security object + DECODE_CODE_LENGTH = 0x02, + DECODE_VARARG = 0x04, + DECODE_INTERRUPTIBILITY = 0x08, + DECODE_GC_LIFETIMES = 0x10, + DECODE_NO_VALIDATION = 0x20, + DECODE_PSP_SYM = 0x40, + DECODE_GENERICS_INST_CONTEXT = 0x80, // stack location of instantiation context for generics + // (this may be either the 'this' ptr or the instantiation secret param) + DECODE_GS_COOKIE = 0x100, // stack location of the GS cookie + DECODE_FOR_RANGES_CALLBACK = 0x200, + DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context) + DECODE_EDIT_AND_CONTINUE = 0x800, + DECODE_REVERSE_PINVOKE_VAR = 0x1000, + DECODE_RETURN_KIND = 0x2000, +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + DECODE_HAS_TAILCALLS = 0x4000, +#endif // _TARGET_ARM_ || _TARGET_ARM64_ +}; + +enum GcInfoHeaderFlags +{ + GC_INFO_IS_VARARG = 0x1, + GC_INFO_HAS_SECURITY_OBJECT = 0x2, + GC_INFO_HAS_GS_COOKIE = 0x4, + GC_INFO_HAS_PSP_SYM = 0x8, + GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK = 0x30, + GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE = 0x00, + GC_INFO_HAS_GENERICS_INST_CONTEXT_MT = 0x10, + GC_INFO_HAS_GENERICS_INST_CONTEXT_MD = 0x20, + GC_INFO_HAS_GENERICS_INST_CONTEXT_THIS = 0x30, + GC_INFO_HAS_STACK_BASE_REGISTER = 0x40, +#ifdef _TARGET_AMD64_ + GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80, +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + GC_INFO_HAS_TAILCALLS = 0x80, +#endif // _TARGET_AMD64_ + GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS = 0x100, + GC_INFO_REVERSE_PINVOKE_FRAME = 0x200, + + GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9, + GC_INFO_FLAGS_BIT_SIZE = 10, +}; + +class BitStreamReader +{ +public: + BitStreamReader() + { + SUPPORTS_DAC; + } + + BitStreamReader( PTR_CBYTE pBuffer ) + { + SUPPORTS_DAC; + + _ASSERTE( pBuffer != NULL ); + + m_pCurrent = m_pBuffer = dac_cast((size_t)dac_cast(pBuffer) & ~((size_t)sizeof(size_t)-1)); + m_RelPos = m_InitialRelPos = (int)((size_t)dac_cast(pBuffer) % sizeof(size_t)) * 8/*BITS_PER_BYTE*/; + } + + BitStreamReader(const BitStreamReader& other) + { + SUPPORTS_DAC; + + m_pBuffer = other.m_pBuffer; + m_InitialRelPos = other.m_InitialRelPos; + m_pCurrent = other.m_pCurrent; + m_RelPos = other.m_RelPos; + } + + const BitStreamReader& operator=(const BitStreamReader& other) + { + SUPPORTS_DAC; + + m_pBuffer = other.m_pBuffer; + m_InitialRelPos = other.m_InitialRelPos; + m_pCurrent = other.m_pCurrent; + m_RelPos = other.m_RelPos; + return *this; + } + + // NOTE: This routine is perf-critical + __forceinline size_t Read( int numBits ) + { + SUPPORTS_DAC; + + _ASSERTE(numBits > 0 && numBits <= BITS_PER_SIZE_T); + + size_t result = (*m_pCurrent) >> m_RelPos; + int newRelPos = m_RelPos + numBits; + if(newRelPos >= BITS_PER_SIZE_T) + { + m_pCurrent++; + newRelPos -= BITS_PER_SIZE_T; + if(newRelPos > 0) + { + size_t extraBits = (*m_pCurrent) << (numBits - newRelPos); + result ^= extraBits; + } + } + m_RelPos = newRelPos; + result &= SAFE_SHIFT_LEFT(1, numBits) - 1; + return result; + } + + // This version reads one bit, returning zero/non-zero (not 0/1) + // NOTE: This routine is perf-critical + __forceinline size_t ReadOneFast() + { + SUPPORTS_DAC; + + size_t result = (*m_pCurrent) & (((size_t)1) << m_RelPos); + if(++m_RelPos == BITS_PER_SIZE_T) + { + m_pCurrent++; + m_RelPos = 0; + } + return result; + } + + + __forceinline size_t GetCurrentPos() + { + SUPPORTS_DAC; + return (size_t) ((m_pCurrent - m_pBuffer) * BITS_PER_SIZE_T + m_RelPos - m_InitialRelPos); + } + + __forceinline void SetCurrentPos( size_t pos ) + { + size_t adjPos = pos + m_InitialRelPos; + m_pCurrent = m_pBuffer + adjPos / BITS_PER_SIZE_T; + m_RelPos = (int)(adjPos % BITS_PER_SIZE_T); + _ASSERTE(GetCurrentPos() == pos); + } + + __forceinline void Skip( SSIZE_T numBitsToSkip ) + { + SUPPORTS_DAC; + + SetCurrentPos(GetCurrentPos() + numBitsToSkip); + } + + __forceinline void AlignUpToByte() + { + if(m_RelPos <= BITS_PER_SIZE_T - 8) + { + m_RelPos = (m_RelPos + 7) & ~7; + } + else + { + m_RelPos = 0; + m_pCurrent++; + } + } + + __forceinline size_t ReadBitAtPos( size_t pos ) + { + size_t adjPos = pos + m_InitialRelPos; + size_t* ptr = m_pBuffer + adjPos / BITS_PER_SIZE_T; + int relPos = (int)(adjPos % BITS_PER_SIZE_T); + return (*ptr) & (((size_t)1) << relPos); + } + + + //-------------------------------------------------------------------------- + // Decode variable length numbers + // See the corresponding methods on BitStreamWriter for more information on the format + //-------------------------------------------------------------------------- + + inline size_t DecodeVarLengthUnsigned( int base ) + { + _ASSERTE((base > 0) && (base < (int)BITS_PER_SIZE_T)); + size_t numEncodings = size_t{ 1 } << base; + size_t result = 0; + for(int shift=0; ; shift+=base) + { + _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); + + size_t currentChunk = Read(base+1); + result |= (currentChunk & (numEncodings-1)) << shift; + if(!(currentChunk & numEncodings)) + { + // Extension bit is not set, we're done. + return result; + } + } + } + + inline SSIZE_T DecodeVarLengthSigned( int base ) + { + _ASSERTE((base > 0) && (base < (int)BITS_PER_SIZE_T)); + size_t numEncodings = size_t{ 1 } << base; + SSIZE_T result = 0; + for(int shift=0; ; shift+=base) + { + _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); + + size_t currentChunk = Read(base+1); + result |= (currentChunk & (numEncodings-1)) << shift; + if(!(currentChunk & numEncodings)) + { + // Extension bit is not set, sign-extend and we're done. + int sbits = BITS_PER_SIZE_T - (shift+base); + result <<= sbits; + result >>= sbits; // This provides the sign extension + return result; + } + } + } + +private: + PTR_size_t m_pBuffer; + int m_InitialRelPos; + PTR_size_t m_pCurrent; + int m_RelPos; +}; + +struct GcSlotDesc +{ + union + { + UINT32 RegisterNumber; + GcStackSlot Stack; + } Slot; + GcSlotFlags Flags; +}; + +class GcSlotDecoder +{ +public: + GcSlotDecoder() + {} + + void DecodeSlotTable(BitStreamReader& reader); + + UINT32 GetNumSlots() + { + return m_NumSlots; + } + + UINT32 GetNumUntracked() + { + return m_NumUntracked; + } + + UINT32 GetNumTracked() + { + return m_NumSlots - m_NumUntracked; + } + + UINT32 GetNumRegisters() + { + return m_NumRegisters; + } + + const GcSlotDesc* GetSlotDesc(UINT32 slotIndex); + +private: + GcSlotDesc m_SlotArray[MAX_PREDECODED_SLOTS]; + BitStreamReader m_SlotReader; + UINT32 m_NumSlots; + UINT32 m_NumRegisters; + UINT32 m_NumUntracked; + + UINT32 m_NumDecodedSlots; + GcSlotDesc* m_pLastSlot; +}; + +#ifdef USE_GC_INFO_DECODER +class GcInfoDecoder +{ +public: + + // If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset + GcInfoDecoder( + GCInfoToken gcInfoToken, + GcInfoDecoderFlags flags = DECODE_EVERYTHING, + UINT32 instructionOffset = 0 + ); + + //------------------------------------------------------------------------ + // Interruptibility + //------------------------------------------------------------------------ + + bool IsInterruptible(); + +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + // This is used for gccoverage + bool IsSafePoint(UINT32 codeOffset); + + typedef void EnumerateSafePointsCallback (UINT32 offset, void * hCallback); + void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); + +#endif + // Returns true to stop enumerating. + typedef bool EnumerateInterruptibleRangesCallback (UINT32 startOffset, UINT32 stopOffset, void * hCallback); + + void EnumerateInterruptibleRanges ( + EnumerateInterruptibleRangesCallback *pCallback, + void * hCallback); + + //------------------------------------------------------------------------ + // GC lifetime information + //------------------------------------------------------------------------ + + bool EnumerateLiveSlots( + PREGDISPLAY pRD, + bool reportScratchSlots, + unsigned flags, + GCEnumCallback pCallBack, + void * hCallBack + ); + + // Public for the gc info dumper + void EnumerateUntrackedSlots( + PREGDISPLAY pRD, + unsigned flags, + GCEnumCallback pCallBack, + void * hCallBack + ); + + //------------------------------------------------------------------------ + // Miscellaneous method information + //------------------------------------------------------------------------ + + INT32 GetSecurityObjectStackSlot(); + INT32 GetGSCookieStackSlot(); + UINT32 GetGSCookieValidRangeStart(); + UINT32 GetGSCookieValidRangeEnd(); + UINT32 GetPrologSize(); + INT32 GetPSPSymStackSlot(); + INT32 GetGenericsInstContextStackSlot(); + INT32 GetReversePInvokeFrameStackSlot(); + bool HasMethodDescGenericsInstContext(); + bool HasMethodTableGenericsInstContext(); + bool GetIsVarArg(); + bool WantsReportOnlyLeaf(); +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + bool HasTailCalls(); +#endif // _TARGET_ARM_ || _TARGET_ARM64_ + ReturnKind GetReturnKind(); + UINT32 GetCodeLength(); + UINT32 GetStackBaseRegister(); + UINT32 GetSizeOfEditAndContinuePreservedArea(); + size_t GetNumBytesRead(); + +#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA + UINT32 GetSizeOfStackParameterArea(); +#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA + + +private: + BitStreamReader m_Reader; + UINT32 m_InstructionOffset; + + // Pre-decoded information + bool m_IsInterruptible; + bool m_IsVarArg; + bool m_GenericSecretParamIsMD; + bool m_GenericSecretParamIsMT; +#ifdef _TARGET_AMD64_ + bool m_WantsReportOnlyLeaf; +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + bool m_HasTailCalls; +#endif // _TARGET_AMD64_ + INT32 m_SecurityObjectStackSlot; + INT32 m_GSCookieStackSlot; + INT32 m_ReversePInvokeFrameStackSlot; + UINT32 m_ValidRangeStart; + UINT32 m_ValidRangeEnd; + INT32 m_PSPSymStackSlot; + INT32 m_GenericsInstContextStackSlot; + UINT32 m_CodeLength; + UINT32 m_StackBaseRegister; + UINT32 m_SizeOfEditAndContinuePreservedArea; + ReturnKind m_ReturnKind; +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + UINT32 m_NumSafePoints; + UINT32 m_SafePointIndex; + UINT32 FindSafePoint(UINT32 codeOffset); +#endif + UINT32 m_NumInterruptibleRanges; + +#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA + UINT32 m_SizeOfStackOutgoingAndScratchArea; +#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA + +#ifdef _DEBUG + GcInfoDecoderFlags m_Flags; + PTR_CBYTE m_GcInfoAddress; +#endif + UINT32 m_Version; + + static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback); + + OBJECTREF* GetRegisterSlot( + int regNum, + PREGDISPLAY pRD + ); + +#ifdef FEATURE_PAL + OBJECTREF* GetCapturedRegister( + int regNum, + PREGDISPLAY pRD + ); +#endif // FEATURE_PAL + + OBJECTREF* GetStackSlot( + INT32 spOffset, + GcStackSlotBase spBase, + PREGDISPLAY pRD + ); + +#ifdef DACCESS_COMPILE + int GetStackReg(int spBase); +#endif // DACCESS_COMPILE + + bool IsScratchRegister(int regNum, PREGDISPLAY pRD); + bool IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD); + + void ReportUntrackedSlots( + GcSlotDecoder& slotDecoder, + PREGDISPLAY pRD, + unsigned flags, + GCEnumCallback pCallBack, + void * hCallBack + ); + + void ReportRegisterToGC( + int regNum, + unsigned gcFlags, + PREGDISPLAY pRD, + unsigned flags, + GCEnumCallback pCallBack, + void * hCallBack + ); + + void ReportStackSlotToGC( + INT32 spOffset, + GcStackSlotBase spBase, + unsigned gcFlags, + PREGDISPLAY pRD, + unsigned flags, + GCEnumCallback pCallBack, + void * hCallBack + ); + + + inline void ReportSlotToGC( + GcSlotDecoder& slotDecoder, + UINT32 slotIndex, + PREGDISPLAY pRD, + bool reportScratchSlots, + unsigned inputFlags, + GCEnumCallback pCallBack, + void * hCallBack + ) + { + _ASSERTE(slotIndex < slotDecoder.GetNumSlots()); + const GcSlotDesc* pSlot = slotDecoder.GetSlotDesc(slotIndex); + + if(slotIndex < slotDecoder.GetNumRegisters()) + { + UINT32 regNum = pSlot->Slot.RegisterNumber; + if( reportScratchSlots || !IsScratchRegister( regNum, pRD ) ) + { + ReportRegisterToGC( + regNum, + pSlot->Flags, + pRD, + inputFlags, + pCallBack, + hCallBack + ); + } + else + { + LOG((LF_GCROOTS, LL_INFO1000, "\"Live\" scratch register " FMT_REG " not reported\n", regNum)); + } + } + else + { + INT32 spOffset = pSlot->Slot.Stack.SpOffset; + GcStackSlotBase spBase = pSlot->Slot.Stack.Base; + if( reportScratchSlots || !IsScratchStackSlot(spOffset, spBase, pRD) ) + { + ReportStackSlotToGC( + spOffset, + spBase, + pSlot->Flags, + pRD, + inputFlags, + pCallBack, + hCallBack + ); + } + else + { + LOG((LF_GCROOTS, LL_INFO1000, "\"Live\" scratch stack slot " FMT_STK " not reported\n", DBG_STK(spOffset))); + } + } + } +}; +#endif // USE_GC_INFO_DECODER + + +#endif // _GC_INFO_DECODER_ + diff --git a/lib/coreclr/src/inc/gcinfodumper.h b/lib/coreclr/src/inc/gcinfodumper.h new file mode 100644 index 0000000000..cd939c1340 --- /dev/null +++ b/lib/coreclr/src/inc/gcinfodumper.h @@ -0,0 +1,122 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __GCINFODUMPER_H__ +#define __GCINFODUMPER_H__ + +#include "gcinfotypes.h" +#include "gcinfodecoder.h" + +// ***************************************************************************** +// WARNING!!!: These values and code are also used by SOS in the diagnostics +// repo. Should updated in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfodumper.h +// ***************************************************************************** + +// +// This class dumps the contents of the gc encodings, providing outputs +// similar to the inputs to GcInfoEncoder. This uses the same GcInfoDecoder +// functions that the EE uses (vs. decoding the bits directly). +// +class GcInfoDumper +{ +public: + + GcInfoDumper (GCInfoToken gcInfoToken); + ~GcInfoDumper (); + + // Returns TRUE to stop decoding. + typedef BOOL InterruptibleStateChangeProc ( + UINT32 CodeOffset, + BOOL fInterruptible, + PVOID pvData); + + // Returns TRUE to stop decoding. + typedef BOOL OnSafePointProc ( + UINT32 CodeOffset, + PVOID pvData); + + // Returns TRUE to stop decoding. + typedef BOOL RegisterStateChangeProc ( + UINT32 CodeOffset, + UINT32 RegisterNumber, + GcSlotFlags Flags, + GcSlotState NewState, + PVOID pvData); + + // Returns TRUE to stop decoding. + typedef BOOL StackSlotStateChangeProc ( + UINT32 CodeOffset, + GcSlotFlags flags, + GcStackSlotBase BaseRegister, + SSIZE_T StackOffset, + GcSlotState NewState, + PVOID pvData); + + enum EnumerateStateChangesResults + { + SUCCESS = 0, + OUT_OF_MEMORY, + REPORTED_REGISTER_IN_CALLERS_FRAME, + REPORTED_FRAME_POINTER, + REPORTED_INVALID_BASE_REGISTER, + REPORTED_INVALID_POINTER, + DECODER_FAILED, + }; + + // Returns TRUE if successful. FALSE if out of memory, invalid data, etc. + EnumerateStateChangesResults EnumerateStateChanges ( + InterruptibleStateChangeProc *pfnInterruptibleStateChange, + RegisterStateChangeProc *pfnRegisterStateChange, + StackSlotStateChangeProc *pfnStackSlotStateChange, + OnSafePointProc *pfnSafePointFunc, + PVOID pvData); + + size_t GetGCInfoSize(); + +private: + + struct LivePointerRecord + { + OBJECTREF *ppObject; + DWORD flags; + LivePointerRecord *pNext; + UINT marked; + }; + + GCInfoToken m_gcTable; + UINT32 m_StackBaseRegister; + UINT32 m_SizeOfEditAndContinuePreservedArea; + LivePointerRecord *m_pRecords; + RegisterStateChangeProc *m_pfnRegisterStateChange; + StackSlotStateChangeProc *m_pfnStackSlotStateChange; + PVOID m_pvCallbackData; + EnumerateStateChangesResults m_Error; + size_t m_gcInfoSize; + + static void LivePointerCallback ( + LPVOID hCallback, // callback data + OBJECTREF* pObject, // address of obect-reference we are reporting + uint32_t flags // is this a pinned and/or interior pointer + DAC_ARG(DacSlotLocation loc)); // the location the pointer came from + + static void FreePointerRecords (LivePointerRecord *pRecords); + + // Return TRUE if callback requested to stop decoding. + BOOL ReportPointerRecord ( + UINT32 CodeOffset, + BOOL fLive, + REGDISPLAY *pRD, + LivePointerRecord *pRecord); + + // Return TRUE if callback requested to stop decoding. + BOOL ReportPointerDifferences ( + UINT32 offset, + REGDISPLAY *pRD, + LivePointerRecord *pPrevState); +}; + + +#endif // !__GCINFODUMPER_H__ + diff --git a/lib/coreclr/src/inc/gcinfoencoder.h b/lib/coreclr/src/inc/gcinfoencoder.h new file mode 100644 index 0000000000..18dfa8cfd0 --- /dev/null +++ b/lib/coreclr/src/inc/gcinfoencoder.h @@ -0,0 +1,567 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/***************************************************************** + * + * GC Information Encoding API + * + *****************************************************************/ + +/***************************************************************** + + ENCODING LAYOUT + + 1. Header + + Slim Header for simple and common cases: + - EncodingType[Slim] + - ReturnKind (Fat: 2 bits) + - CodeLength + - NumCallSites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) + + Fat Header for other cases: + - EncodingType[Fat] + - Flag: isVarArg, + hasSecurityObject, + hasGSCookie, + hasPSPSymStackSlot, + hasGenericsInstContextStackSlot, + hasStackBaseregister, + wantsReportOnlyLeaf (AMD64 use only), + hasTailCalls (ARM/ARM64 only) + hasSizeOfEditAndContinuePreservedArea + hasReversePInvokeFrame, + - ReturnKind (Fat: 4 bits) + - CodeLength + - Prolog (if hasSecurityObject || hasGenericsInstContextStackSlot || hasGSCookie) + - Epilog (if hasGSCookie) + - SecurityObjectStackSlot (if any) + - GSCookieStackSlot (if any) + - PSPSymStackSlot (if any) + - GenericsInstContextStackSlot (if any) + - StackBaseRegister (if any) + - SizeOfEditAndContinuePreservedArea (if any) + - ReversePInvokeFrameSlot (if any) + - SizeOfStackOutgoingAndScratchArea (#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA) + - NumCallSites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) + - NumInterruptibleRanges + + 2. Call sites offsets (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) + 3. Fully-interruptible ranges + 4. Slot table + 5. GC state at call sites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) + 6. GC state at try clauses (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) + 7. Chunk pointers + 8. Chunk encodings + + + STANDALONE_BUILD + + The STANDALONE_BUILD switch can be used to build the GcInfoEncoder library + independently by clients outside the CoreClr tree. + + The GcInfo library uses some custom data-structures (ex: ArrayList, SimplerHashTable) + and includes some utility libraries (ex: UtilCode) which pull in several other + headers with considerable unrelated content. Rather than porting all the + utility code to suite other clients, the STANDALONE_BUILD switch can be used + to include only the minimal set of headers specific to GcInfo encodings. + + Clients of STANDALONE_BUILD will likely use standard library + implementations of data-structures like ArrayList, HashMap etc., in place + of the custom implementation currently used by GcInfoEncoder. + + Rather than spew the GcInfoEnoder code with + #ifdef STANDALONE_BUILD ... #else .. #endif blocks, we include a special + header GcInfoUtil.h in STANDALONE_BUILD mode. GcInfoUtil.h is expected to + supply the interface/implementation for the data-structures and utilities + used by GcInfoEncoder. This header should be provided by the clients doing + the standalone build in their source tree. + +*****************************************************************/ + + +#ifndef __GCINFOENCODER_H__ +#define __GCINFOENCODER_H__ + +#ifdef STANDALONE_BUILD +#include +#include +#include "GcInfoUtil.h" +#include "corjit.h" +#else +#include +#include +#include +#include "corjit.h" +#include "iallocator.h" +#include "gcinfoarraylist.h" +#include "stdmacros.h" +#include "eexcp.h" +#endif + +#include "gcinfotypes.h" + +// As stated in issue #6008, GcInfoSize should be incorporated into debug builds. +#ifdef _DEBUG +#define MEASURE_GCINFO +#endif + +#ifdef MEASURE_GCINFO +struct GcInfoSize +{ + size_t TotalSize; + + size_t NumMethods; + size_t NumCallSites; + size_t NumRanges; + size_t NumRegs; + size_t NumStack; + size_t NumUntracked; + size_t NumTransitions; + size_t SizeOfCode; + size_t EncPreservedSlots; + + size_t UntrackedSlotSize; + size_t NumUntrackedSize; + size_t FlagsSize; + size_t RetKindSize; + size_t CodeLengthSize; + size_t ProEpilogSize; + size_t SecObjSize; + size_t GsCookieSize; + size_t PspSymSize; + size_t GenericsCtxSize; + size_t StackBaseSize; + size_t ReversePInvokeFrameSize; + size_t FixedAreaSize; + size_t NumCallSitesSize; + size_t NumRangesSize; + size_t CallSitePosSize; + size_t RangeSize; + size_t NumRegsSize; + size_t NumStackSize; + size_t RegSlotSize; + size_t StackSlotSize; + size_t CallSiteStateSize; + size_t EhPosSize; + size_t EhStateSize; + size_t ChunkPtrSize; + size_t ChunkMaskSize; + size_t ChunkFinalStateSize; + size_t ChunkTransitionSize; + + GcInfoSize(); + GcInfoSize& operator+=(const GcInfoSize& other); + void Log(DWORD level, const char * header); +}; +#endif + +struct GcSlotDesc +{ + union + { + UINT32 RegisterNumber; + GcStackSlot Stack; + } Slot; + GcSlotFlags Flags; + + BOOL IsRegister() const + { + return (Flags & GC_SLOT_IS_REGISTER); + } + BOOL IsInterior() const + { + return (Flags & GC_SLOT_INTERIOR); + } + BOOL IsPinned() const + { + return (Flags & GC_SLOT_PINNED); + } + BOOL IsUntracked() const + { + return (Flags & GC_SLOT_UNTRACKED); + } + BOOL IsDeleted() const + { + return (Flags & GC_SLOT_IS_DELETED); + } + void MarkDeleted() + { + Flags = (GcSlotFlags) (Flags | GC_SLOT_IS_DELETED); + } +}; + +class BitArray; +class BitStreamWriter +{ +public: + BitStreamWriter( IAllocator* pAllocator ); + + // bit 0 is the least significative bit + void Write( size_t data, UINT32 count ); + + inline size_t GetBitCount() + { + return m_BitCount; + } + + inline size_t GetByteCount() + { + return ( m_BitCount + 7 ) / 8; + } + + + void CopyTo( BYTE* buffer ); + void Dispose(); + + //-------------------------------------------------------- + // Compute the number of bits used to encode variable length numbers + // Uses base+1 bits at minimum + // Bits 0..(base-1) represent the encoded quantity + // If it doesn't fit, set bit #base to 1 and use base+1 more bits + //-------------------------------------------------------- + static int SizeofVarLengthUnsigned( size_t n, UINT32 base ); + + //-------------------------------------------------------- + // Encode variable length numbers + // Uses base+1 bits at minimum + // Bits 0..(base-1) represent the encoded quantity + // If it doesn't fit, set bit #base to 1 and use base+1 more bits + //-------------------------------------------------------- + int EncodeVarLengthUnsigned( size_t n, UINT32 base ); + + //-------------------------------------------------------- + // Signed quantities are encoded the same as unsigned + // The most relevant difference is that a number is considered + // to fit in base bits if the topmost bit of a base-long chunk + // matches the sign of the whole number + //-------------------------------------------------------- + int EncodeVarLengthSigned( SSIZE_T n, UINT32 base ); + +private: + class MemoryBlockList; + class MemoryBlock + { + friend class MemoryBlockList; + MemoryBlock* m_next; + + public: + size_t Contents[]; + + inline MemoryBlock* Next() + { + return m_next; + } + }; + + class MemoryBlockList + { + MemoryBlock* m_head; + MemoryBlock* m_tail; + + public: + MemoryBlockList(); + + inline MemoryBlock* Head() + { + return m_head; + } + + MemoryBlock* AppendNew(IAllocator* allocator, size_t bytes); + void Dispose(IAllocator* allocator); + }; + + IAllocator* m_pAllocator; + size_t m_BitCount; + UINT32 m_FreeBitsInCurrentSlot; + MemoryBlockList m_MemoryBlocks; + const static int m_MemoryBlockSize = 128; // must be a multiple of the pointer size + size_t* m_pCurrentSlot; // bits are written through this pointer + size_t* m_OutOfBlockSlot; // sentinel value to determine when the block is full +#ifdef _DEBUG + int m_MemoryBlocksCount; +#endif + +private: + // Writes bits knowing that they will all fit in the current memory slot + inline void WriteInCurrentSlot( size_t data, UINT32 count ) + { + data &= SAFE_SHIFT_LEFT(1, count) - 1; + data <<= (BITS_PER_SIZE_T - m_FreeBitsInCurrentSlot); + *m_pCurrentSlot |= data; + } + + inline void AllocMemoryBlock() + { + _ASSERTE( IS_ALIGNED( m_MemoryBlockSize, sizeof( size_t ) ) ); + MemoryBlock* pMemBlock = m_MemoryBlocks.AppendNew(m_pAllocator, m_MemoryBlockSize); + + m_pCurrentSlot = pMemBlock->Contents; + m_OutOfBlockSlot = m_pCurrentSlot + m_MemoryBlockSize / sizeof( size_t ); + +#ifdef _DEBUG + m_MemoryBlocksCount++; +#endif + + } + + inline void InitCurrentSlot() + { + m_FreeBitsInCurrentSlot = BITS_PER_SIZE_T; + *m_pCurrentSlot = 0; + } +}; + + +typedef UINT32 GcSlotId; + + +inline UINT32 GetNormCodeOffsetChunk(UINT32 normCodeOffset) +{ + return normCodeOffset / NUM_NORM_CODE_OFFSETS_PER_CHUNK; +} + +inline UINT32 GetCodeOffsetChunk(UINT32 codeOffset) +{ + return (NORMALIZE_CODE_OFFSET(codeOffset)) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; +} + +enum GENERIC_CONTEXTPARAM_TYPE +{ + GENERIC_CONTEXTPARAM_NONE = 0, + GENERIC_CONTEXTPARAM_MT = 1, + GENERIC_CONTEXTPARAM_MD = 2, + GENERIC_CONTEXTPARAM_THIS = 3, +}; + +extern void DECLSPEC_NORETURN ThrowOutOfMemory(); + +class GcInfoEncoder +{ +public: + typedef void (*NoMemoryFunction)(void); + + GcInfoEncoder( + ICorJitInfo* pCorJitInfo, + CORINFO_METHOD_INFO* pMethodInfo, + IAllocator* pJitAllocator, + NoMemoryFunction pNoMem = ::ThrowOutOfMemory + ); + + struct LifetimeTransition + { + UINT32 CodeOffset; + GcSlotId SlotId; + BYTE BecomesLive; + BYTE IsDeleted; + }; + + +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + void DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites); +#endif + + //------------------------------------------------------------------------ + // Interruptibility + //------------------------------------------------------------------------ + + // An instruction at offset x will be interruptible + // if-and-only-if startInstructionOffset <= x < startInstructionOffset+length + void DefineInterruptibleRange( UINT32 startInstructionOffset, UINT32 length ); + + + //------------------------------------------------------------------------ + // Slot information + //------------------------------------------------------------------------ + + // + // If spOffset is relative to the current SP, spOffset must be non-negative. + // If spOffset is relative to the SP of the caller (same as SP at the method entry and exit) + // Negative offsets describe GC refs in the local and outgoing areas. + // Positive offsets describe GC refs in the scratch area + // Note that if the dynamic allocation area is resized, the outgoing area will not be valid anymore + // Old slots must be declared dead and new ones can be defined. + // It's up to the JIT to do the right thing. We don't enforce this. + + GcSlotId GetRegisterSlotId( UINT32 regNum, GcSlotFlags flags ); + GcSlotId GetStackSlotId( INT32 spOffset, GcSlotFlags flags, GcStackSlotBase spBase = GC_CALLER_SP_REL ); + + // + // After a FinalizeSlotIds is called, no more slot definitions can be made. + // FinalizeSlotIds must be called once and only once before calling Build() + // + void FinalizeSlotIds(); + + + //------------------------------------------------------------------------ + // Fully-interruptible information + //------------------------------------------------------------------------ + + // + // For inputs, pass zero as offset + // + + // Indicates that the GC state of slot "slotId" becomes (and remains, until another transition) + // "slotState" after the instruction preceding "instructionOffset" (so it is first in this state when + // the IP of a suspended thread is at this instruction offset). + + void SetSlotState( UINT32 instructionOffset, + GcSlotId slotId, + GcSlotState slotState + ); + + + //------------------------------------------------------------------------ + // ReturnKind + //------------------------------------------------------------------------ + + void SetReturnKind(ReturnKind returnKind); + + //------------------------------------------------------------------------ + // Miscellaneous method information + //------------------------------------------------------------------------ + + void SetSecurityObjectStackSlot( INT32 spOffset ); + void SetPrologSize( UINT32 prologSize ); + void SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRangeStart, UINT32 validRangeEnd ); + void SetPSPSymStackSlot( INT32 spOffsetPSPSym ); + void SetGenericsInstContextStackSlot( INT32 spOffsetGenericsContext, GENERIC_CONTEXTPARAM_TYPE type); + void SetReversePInvokeFrameSlot(INT32 spOffset); + void SetIsVarArg(); + void SetCodeLength( UINT32 length ); + + // Optional in the general case. Required if the method uses GC_FRAMEREG_REL stack slots + void SetStackBaseRegister( UINT32 registerNumber ); + + // Number of slots preserved during EnC remap + void SetSizeOfEditAndContinuePreservedArea( UINT32 size ); + +#ifdef _TARGET_AMD64_ + // Used to only report a frame once for the leaf function/funclet + // instead of once for each live function/funclet on the stack. + // Called only by RyuJIT (not JIT64) + void SetWantsReportOnlyLeaf(); +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + void SetHasTailCalls(); +#endif // _TARGET_AMD64_ + +#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA + void SetSizeOfStackOutgoingAndScratchArea( UINT32 size ); +#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA + + + //------------------------------------------------------------------------ + // Encoding + //------------------------------------------------------------------------ + + // + // Build() encodes GC information into temporary buffers. + // The method description cannot change after Build is called + // + void Build(); + + // + // Write encoded information to its final destination and frees temporary buffers. + // The encoder shouldn't be used anymore after calling this method. + // It returns a pointer to the destination buffer, which address is byte-aligned + // + BYTE* Emit(); + +private: + + friend int __cdecl CompareLifetimeTransitionsByOffsetThenSlot(const void*, const void*); + friend int CompareLifetimeTransitionsByChunk(const void*, const void*); + + + struct InterruptibleRange + { + UINT32 NormStartOffset; + UINT32 NormStopOffset; + }; + + ICorJitInfo* m_pCorJitInfo; + CORINFO_METHOD_INFO* m_pMethodInfo; + IAllocator* m_pAllocator; + NoMemoryFunction m_pNoMem; + +#ifdef _DEBUG + const char *m_MethodName, *m_ModuleName; +#endif + + BitStreamWriter m_Info1; // Used for everything except for chunk encodings + BitStreamWriter m_Info2; // Used for chunk encodings + + GcInfoArrayList m_InterruptibleRanges; + GcInfoArrayList m_LifetimeTransitions; + + bool m_IsVarArg; +#if defined(_TARGET_AMD64_) + bool m_WantsReportOnlyLeaf; +#elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) + bool m_HasTailCalls; +#endif // _TARGET_AMD64_ + INT32 m_SecurityObjectStackSlot; + INT32 m_GSCookieStackSlot; + UINT32 m_GSCookieValidRangeStart; + UINT32 m_GSCookieValidRangeEnd; + INT32 m_PSPSymStackSlot; + INT32 m_GenericsInstContextStackSlot; + GENERIC_CONTEXTPARAM_TYPE m_contextParamType; + ReturnKind m_ReturnKind; + UINT32 m_CodeLength; + UINT32 m_StackBaseRegister; + UINT32 m_SizeOfEditAndContinuePreservedArea; + INT32 m_ReversePInvokeFrameSlot; + InterruptibleRange* m_pLastInterruptibleRange; + +#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA + UINT32 m_SizeOfStackOutgoingAndScratchArea; +#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA + + void * eeAllocGCInfo (size_t blockSize); + +private: + + friend class EncoderCheckState; + + static const UINT32 m_SlotTableInitialSize = 32; + UINT32 m_SlotTableSize; + UINT32 m_NumSlots; + GcSlotDesc *m_SlotTable; + +#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + UINT32* m_pCallSites; + BYTE* m_pCallSiteSizes; + UINT32 m_NumCallSites; +#endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + + void GrowSlotTable(); + + void WriteSlotStateVector(BitStreamWriter &writer, const BitArray& vector); + + UINT32 SizeofSlotStateVarLengthVector(const BitArray& vector, UINT32 baseSkip, UINT32 baseRun); + void SizeofSlotStateVarLengthVector(const BitArray& vector, UINT32 baseSkip, UINT32 baseRun, UINT32 * pSizeofSimple, UINT32 * pSizeofRLE, UINT32 * pSizeofRLENeg); + UINT32 WriteSlotStateVarLengthVector(BitStreamWriter &writer, const BitArray& vector, UINT32 baseSkip, UINT32 baseRun); + + bool IsAlwaysScratch(GcSlotDesc &slot); + + // Assumes that "*ppTransitions" is has size "numTransitions", is sorted by CodeOffset then by SlotId, + // and that "*ppEndTransitions" points one beyond the end of the array. If "*ppTransitions" contains + // any dead/live transitions pairs for the same CodeOffset and SlotID, removes those, by allocating a + // new array, and copying the non-removed elements into it. If it does this, sets "*ppTransitions" to + // point to the new array, "*pNumTransitions" to its shorted length, and "*ppEndTransitions" to + // point one beyond the used portion of this array. + void EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, + size_t* pNumTransitions, + LifetimeTransition** ppEndTransitions); + +#ifdef _DEBUG + bool m_IsSlotTableFrozen; +#endif + +#ifdef MEASURE_GCINFO + GcInfoSize m_CurrentMethodSize; +#endif +}; + +#endif // !__GCINFOENCODER_H__ diff --git a/lib/coreclr/src/inc/gcinfotypes.h b/lib/coreclr/src/inc/gcinfotypes.h new file mode 100644 index 0000000000..d45b9a6292 --- /dev/null +++ b/lib/coreclr/src/inc/gcinfotypes.h @@ -0,0 +1,839 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef __GCINFOTYPES_H__ +#define __GCINFOTYPES_H__ + +#ifndef FEATURE_REDHAWK +#include "gcinfo.h" +#endif + +// ***************************************************************************** +// WARNING!!!: These values and code are also used by SOS in the diagnostics +// repo. Should updated in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/gcinfotypes.h +// ***************************************************************************** + +#define PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED + +#define FIXED_STACK_PARAMETER_SCRATCH_AREA + + +#define BITS_PER_SIZE_T ((int)sizeof(size_t)*8) + + +//-------------------------------------------------------------------------------- +// It turns out, that ((size_t)x) << y == x, when y is not a literal +// and its value is BITS_PER_SIZE_T +// I guess the processor only shifts of the right operand modulo BITS_PER_SIZE_T +// In many cases, we want the above operation to yield 0, +// hence the following macros +//-------------------------------------------------------------------------------- +__forceinline size_t SAFE_SHIFT_LEFT(size_t x, size_t count) +{ + _ASSERTE(count <= BITS_PER_SIZE_T); + return (x << 1) << (count - 1); +} +__forceinline size_t SAFE_SHIFT_RIGHT(size_t x, size_t count) +{ + _ASSERTE(count <= BITS_PER_SIZE_T); + return (x >> 1) >> (count - 1); +} + +inline UINT32 CeilOfLog2(size_t x) +{ + _ASSERTE(x > 0); + UINT32 result = (x & (x - 1)) ? 1 : 0; + while (x != 1) + { + result++; + x >>= 1; + } + return result; +} + +enum GcSlotFlags +{ + GC_SLOT_BASE = 0x0, + GC_SLOT_INTERIOR = 0x1, + GC_SLOT_PINNED = 0x2, + GC_SLOT_UNTRACKED = 0x4, + + // For internal use by the encoder/decoder + GC_SLOT_IS_REGISTER = 0x8, + GC_SLOT_IS_DELETED = 0x10, +}; + +enum GcStackSlotBase +{ + GC_CALLER_SP_REL = 0x0, + GC_SP_REL = 0x1, + GC_FRAMEREG_REL = 0x2, + + GC_SPBASE_FIRST = GC_CALLER_SP_REL, + GC_SPBASE_LAST = GC_FRAMEREG_REL, +}; + +#ifdef _DEBUG +const char* const GcStackSlotBaseNames[] = +{ + "caller.sp", + "sp", + "frame", +}; +#endif + +enum GcSlotState +{ + GC_SLOT_DEAD = 0x0, + GC_SLOT_LIVE = 0x1, +}; + +struct GcStackSlot +{ + INT32 SpOffset; + GcStackSlotBase Base; + + bool operator==(const GcStackSlot& other) + { + return ((SpOffset == other.SpOffset) && (Base == other.Base)); + } + bool operator!=(const GcStackSlot& other) + { + return ((SpOffset != other.SpOffset) || (Base != other.Base)); + } +}; + +//-------------------------------------------------------------------------------- +// ReturnKind -- encoding return type information in GcInfo +// +// When a method is stopped at a call - site for GC (ex: via return-address +// hijacking) the runtime needs to know whether the value is a GC - value +// (gc - pointer or gc - pointers stored in an aggregate). +// It needs this information so that mark - phase can preserve the gc-pointers +// being returned. +// +// The Runtime doesn't need the precise return-type of a method. +// It only needs to find the GC-pointers in the return value. +// The only scenarios currently supported by CoreCLR are: +// 1. Object references +// 2. ByRef pointers +// 3. ARM64/X64 only : Structs returned in two registers +// 4. X86 only : Floating point returns to perform the correct save/restore +// of the return value around return-hijacking. +// +// Based on these cases, the legal set of ReturnKind enumerations are specified +// for each architecture/encoding. +// A value of this enumeration is stored in the GcInfo header. +// +//-------------------------------------------------------------------------------- + +// RT_Unset: An intermediate step for staged bringup. +// When ReturnKind is RT_Unset, it means that the JIT did not set +// the ReturnKind in the GCInfo, and therefore the VM cannot rely on it, +// and must use other mechanisms (similar to GcInfo ver 1) to determine +// the Return type's GC information. +// +// RT_Unset is only used in the following situations: +// X64: Used by JIT64 until updated to use GcInfo v2 API +// ARM: Used by JIT32 until updated to use GcInfo v2 API +// +// RT_Unset should have a valid encoding, whose bits are actually stored in the image. +// For X86, there are no free bits, and there's no RT_Unused enumeration. + +#if defined(_TARGET_X86_) + +// 00 RT_Scalar +// 01 RT_Object +// 10 RT_ByRef +// 11 RT_Float + +#elif defined(_TARGET_ARM_) + +// 00 RT_Scalar +// 01 RT_Object +// 10 RT_ByRef +// 11 RT_Unset + +#elif defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) + +// Slim Header: + +// 00 RT_Scalar +// 01 RT_Object +// 10 RT_ByRef +// 11 RT_Unset + +// Fat Header: + +// 0000 RT_Scalar +// 0001 RT_Object +// 0010 RT_ByRef +// 0011 RT_Unset +// 0100 RT_Scalar_Obj +// 1000 RT_Scalar_ByRef +// 0101 RT_Obj_Obj +// 1001 RT_Obj_ByRef +// 0110 RT_ByRef_Obj +// 1010 RT_ByRef_ByRef + +#else +#ifdef PORTABILITY_WARNING +PORTABILITY_WARNING("Need ReturnKind for new Platform") +#endif // PORTABILITY_WARNING +#endif // Target checks + +enum ReturnKind { + + // Cases for Return in one register + + RT_Scalar = 0, + RT_Object = 1, + RT_ByRef = 2, + +#ifdef _TARGET_X86_ + RT_Float = 3, // Encoding 3 means RT_Float on X86 +#else + RT_Unset = 3, // RT_Unset on other platforms +#endif // _TARGET_X86_ + + // Cases for Struct Return in two registers + // + // We have the following equivalencies, because the VM's behavior is the same + // for both cases: + // RT_Scalar_Scalar == RT_Scalar + // RT_Obj_Scalar == RT_Object + // RT_ByRef_Scalar == RT_Byref + // The encoding for these equivalencies will play out well because + // RT_Scalar is zero. + // + // Naming: RT_firstReg_secondReg + // Encoding: + // + // This encoding with exclusive bits for each register is chosen for ease of use, + // and because it doesn't cost any more bits. + // It can be changed (ex: to a linear sequence) if necessary. + // For example, we can encode the GC-information for the two registers in 3 bits (instead of 4) + // if we approximate RT_Obj_ByRef and RT_ByRef_Obj as RT_ByRef_ByRef. + + // RT_Scalar_Scalar = RT_Scalar + RT_Scalar_Obj = RT_Object << 2 | RT_Scalar, + RT_Scalar_ByRef = RT_ByRef << 2 | RT_Scalar, + + // RT_Obj_Scalar = RT_Object + RT_Obj_Obj = RT_Object << 2 | RT_Object, + RT_Obj_ByRef = RT_ByRef << 2 | RT_Object, + + // RT_ByRef_Scalar = RT_Byref + RT_ByRef_Obj = RT_Object << 2 | RT_ByRef, + RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef, + + // Illegal or uninitialized value, + // Not a valid encoding, never written to image. + RT_Illegal = 0xFF +}; + +// Identify ReturnKinds containing useful information +inline bool IsValidReturnKind(ReturnKind returnKind) +{ + return (returnKind != RT_Illegal) +#ifndef _TARGET_X86_ + && (returnKind != RT_Unset) +#endif // _TARGET_X86_ + ; +} + +// Identify ReturnKinds that can be a part of a multi-reg struct return +inline bool IsValidFieldReturnKind(ReturnKind returnKind) +{ + return (returnKind == RT_Scalar || returnKind == RT_Object || returnKind == RT_ByRef); +} + +inline bool IsPointerFieldReturnKind(ReturnKind returnKind) +{ + _ASSERTE(IsValidFieldReturnKind(returnKind)); + return (returnKind == RT_Object || returnKind == RT_ByRef); +} + +inline bool IsValidReturnRegister(size_t regNo) +{ + return (regNo == 0) +#ifdef FEATURE_MULTIREG_RETURN + || (regNo == 1) +#endif // FEATURE_MULTIREG_RETURN + ; +} + +inline bool IsStructReturnKind(ReturnKind returnKind) +{ + // Two bits encode integer/ref/float return-kinds. + // Encodings needing more than two bits are (non-scalar) struct-returns. + return returnKind > 3; +} + +inline bool IsScalarReturnKind(ReturnKind returnKind) +{ + return (returnKind == RT_Scalar) +#ifdef _TARGET_X86_ + || (returnKind == RT_Float) +#endif // _TARGET_X86_ + ; +} + +inline bool IsPointerReturnKind(ReturnKind returnKind) +{ + return IsValidReturnKind(returnKind) && !IsScalarReturnKind(returnKind); +} + +// Helpers for combining/extracting individual ReturnKinds from/to Struct ReturnKinds. +// Encoding is two bits per register + +inline ReturnKind GetStructReturnKind(ReturnKind reg0, ReturnKind reg1) +{ + _ASSERTE(IsValidFieldReturnKind(reg0) && IsValidFieldReturnKind(reg1)); + + ReturnKind structReturnKind = (ReturnKind)(reg1 << 2 | reg0); + + _ASSERTE(IsValidReturnKind(structReturnKind)); + + return structReturnKind; +} + +// Extract returnKind for the specified return register. +// Also determines if higher ordinal return registers contain object references +inline ReturnKind ExtractRegReturnKind(ReturnKind returnKind, size_t returnRegOrdinal, bool& moreRegs) +{ + _ASSERTE(IsValidReturnKind(returnKind)); + _ASSERTE(IsValidReturnRegister(returnRegOrdinal)); + + // Return kind of each return register is encoded in two bits at returnRegOrdinal*2 position from LSB + ReturnKind regReturnKind = (ReturnKind)((returnKind >> (returnRegOrdinal * 2)) & 3); + + // Check if any other higher ordinal return registers have object references. + // ReturnKind of higher ordinal return registers are encoded at (returnRegOrdinal+1)*2) position from LSB + // If all of the remaining bits are 0 then there isn't any more RT_Object or RT_ByRef encoded in returnKind. + moreRegs = (returnKind >> ((returnRegOrdinal+1) * 2)) != 0; + + _ASSERTE(IsValidReturnKind(regReturnKind)); + _ASSERTE((returnRegOrdinal == 0) || IsValidFieldReturnKind(regReturnKind)); + + return regReturnKind; +} + +inline const char *ReturnKindToString(ReturnKind returnKind) +{ + switch (returnKind) { + case RT_Scalar: return "Scalar"; + case RT_Object: return "Object"; + case RT_ByRef: return "ByRef"; +#ifdef _TARGET_X86_ + case RT_Float: return "Float"; +#else + case RT_Unset: return "UNSET"; +#endif // _TARGET_X86_ + case RT_Scalar_Obj: return "{Scalar, Object}"; + case RT_Scalar_ByRef: return "{Scalar, ByRef}"; + case RT_Obj_Obj: return "{Object, Object}"; + case RT_Obj_ByRef: return "{Object, ByRef}"; + case RT_ByRef_Obj: return "{ByRef, Object}"; + case RT_ByRef_ByRef: return "{ByRef, ByRef}"; + + case RT_Illegal: return ""; + default: return "!Impossible!"; + } +} + +#ifdef _TARGET_X86_ + +#include // For memcmp() +#include "bitvector.h" // for ptrArgTP + +#ifndef FASTCALL +#define FASTCALL __fastcall +#endif + +// we use offsetof to get the offset of a field +#include // offsetof + +enum infoHdrAdjustConstants { + // Constants + SET_FRAMESIZE_MAX = 7, + SET_ARGCOUNT_MAX = 8, // Change to 6 + SET_PROLOGSIZE_MAX = 16, + SET_EPILOGSIZE_MAX = 10, // Change to 6 + SET_EPILOGCNT_MAX = 4, + SET_UNTRACKED_MAX = 3, + SET_RET_KIND_MAX = 4, // 2 bits for ReturnKind + ADJ_ENCODING_MAX = 0x7f, // Maximum valid encoding in a byte + // Also used to mask off next bit from each encoding byte. + MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte + // is set, then there are more adjustments to follow. +}; + +// +// Enum to define codes that are used to incrementally adjust the InfoHdr structure. +// First set of opcodes +enum infoHdrAdjust { + + SET_FRAMESIZE = 0, // 0x00 + SET_ARGCOUNT = SET_FRAMESIZE + SET_FRAMESIZE_MAX + 1, // 0x08 + SET_PROLOGSIZE = SET_ARGCOUNT + SET_ARGCOUNT_MAX + 1, // 0x11 + SET_EPILOGSIZE = SET_PROLOGSIZE + SET_PROLOGSIZE_MAX + 1, // 0x22 + SET_EPILOGCNT = SET_EPILOGSIZE + SET_EPILOGSIZE_MAX + 1, // 0x2d + SET_UNTRACKED = SET_EPILOGCNT + (SET_EPILOGCNT_MAX + 1) * 2, // 0x37 + + FIRST_FLIP = SET_UNTRACKED + SET_UNTRACKED_MAX + 1, + + FLIP_EDI_SAVED = FIRST_FLIP, // 0x3b + FLIP_ESI_SAVED, // 0x3c + FLIP_EBX_SAVED, // 0x3d + FLIP_EBP_SAVED, // 0x3e + FLIP_EBP_FRAME, // 0x3f + FLIP_INTERRUPTIBLE, // 0x40 + FLIP_DOUBLE_ALIGN, // 0x41 + FLIP_SECURITY, // 0x42 + FLIP_HANDLERS, // 0x43 + FLIP_LOCALLOC, // 0x44 + FLIP_EDITnCONTINUE, // 0x45 + FLIP_VAR_PTR_TABLE_SZ, // 0x46 Flip whether a table-size exits after the header encoding + FFFF_UNTRACKED_CNT, // 0x47 There is a count (>SET_UNTRACKED_MAX) after the header encoding + FLIP_VARARGS, // 0x48 + FLIP_PROF_CALLBACKS, // 0x49 + FLIP_HAS_GS_COOKIE, // 0x4A - The offset of the GuardStack cookie follows after the header encoding + FLIP_SYNC, // 0x4B + FLIP_HAS_GENERICS_CONTEXT,// 0x4C + FLIP_GENERICS_CONTEXT_IS_METHODDESC,// 0x4D + FLIP_REV_PINVOKE_FRAME, // 0x4E + NEXT_OPCODE, // 0x4F -- see next Adjustment enumeration + NEXT_FOUR_START = 0x50, + NEXT_FOUR_FRAMESIZE = 0x50, + NEXT_FOUR_ARGCOUNT = 0x60, + NEXT_THREE_PROLOGSIZE = 0x70, + NEXT_THREE_EPILOGSIZE = 0x78 +}; + +// Second set of opcodes, when first code is 0x4F +enum infoHdrAdjust2 { + SET_RETURNKIND = 0, // 0x00-SET_RET_KIND_MAX Set ReturnKind to value +}; + +#define HAS_UNTRACKED ((unsigned int) -1) +#define HAS_VARPTR ((unsigned int) -1) + +#define INVALID_REV_PINVOKE_OFFSET 0 +#define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -1) +// 0 is not a valid offset for EBP-frames as all locals are at a negative offset +// For ESP frames, the cookie is above (at a higher address than) the buffers, +// and so cannot be at offset 0. +#define INVALID_GS_COOKIE_OFFSET 0 +// Temporary value to indicate that the offset needs to be read after the header +#define HAS_GS_COOKIE_OFFSET ((unsigned int) -1) + +// 0 is not a valid sync offset +#define INVALID_SYNC_OFFSET 0 +// Temporary value to indicate that the offset needs to be read after the header +#define HAS_SYNC_OFFSET ((unsigned int) -1) + +#define INVALID_ARGTAB_OFFSET 0 + +#include + +// Working set optimization: saving 12 * 128 = 1536 bytes in infoHdrShortcut +struct InfoHdr; + +struct InfoHdrSmall { + unsigned char prologSize; // 0 + unsigned char epilogSize; // 1 + unsigned char epilogCount : 3; // 2 [0:2] + unsigned char epilogAtEnd : 1; // 2 [3] + unsigned char ediSaved : 1; // 2 [4] which callee-saved regs are pushed onto stack + unsigned char esiSaved : 1; // 2 [5] + unsigned char ebxSaved : 1; // 2 [6] + unsigned char ebpSaved : 1; // 2 [7] + unsigned char ebpFrame : 1; // 3 [0] locals accessed relative to ebp + unsigned char interruptible : 1; // 3 [1] is intr. at all points (except prolog/epilog), not just call-sites + unsigned char doubleAlign : 1; // 3 [2] uses double-aligned stack (ebpFrame will be false) + unsigned char security : 1; // 3 [3] has slot for security object + unsigned char handlers : 1; // 3 [4] has callable handlers + unsigned char localloc : 1; // 3 [5] uses localloc + unsigned char editNcontinue : 1; // 3 [6] was JITed in EnC mode + unsigned char varargs : 1; // 3 [7] function uses varargs calling convention + unsigned char profCallbacks : 1; // 4 [0] + unsigned char genericsContext : 1;//4 [1] function reports a generics context parameter is present + unsigned char genericsContextIsMethodDesc : 1;//4[2] + unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined + unsigned short argCount; // 5,6 in bytes + unsigned int frameSize; // 7,8,9,10 in bytes + unsigned int untrackedCnt; // 11,12,13,14 + unsigned int varPtrTableSize; // 15.16,17,18 + + // Checks whether "this" is compatible with "target". + // It is not an exact bit match as "this" could have some + // marker/place-holder values, which will have to be written out + // after the header. + + bool isHeaderMatch(const InfoHdr& target) const; +}; + + +struct InfoHdr : public InfoHdrSmall { + // 0 (zero) means that there is no GuardStack cookie + // The cookie is either at ESP+gsCookieOffset or EBP-gsCookieOffset + unsigned int gsCookieOffset; // 19,20,21,22 + unsigned int syncStartOffset; // 23,24,25,26 + unsigned int syncEndOffset; // 27,28,29,30 + unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined + // 35 bytes total + + // Checks whether "this" is compatible with "target". + // It is not an exact bit match as "this" could have some + // marker/place-holder values, which will have to be written out + // after the header. + + bool isHeaderMatch(const InfoHdr& target) const + { +#ifdef _ASSERTE + // target cannot have place-holder values. + _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && + target.varPtrTableSize != HAS_VARPTR && + target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && + target.syncStartOffset != HAS_SYNC_OFFSET && + target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); +#endif + + // compare two InfoHdr's up to but not including the untrackCnt field + if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0) + return false; + + if (untrackedCnt != target.untrackedCnt) { + if (target.untrackedCnt <= SET_UNTRACKED_MAX) + return false; + else if (untrackedCnt != HAS_UNTRACKED) + return false; + } + + if (varPtrTableSize != target.varPtrTableSize) { + if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0)) + return false; + } + + if ((gsCookieOffset == INVALID_GS_COOKIE_OFFSET) != + (target.gsCookieOffset == INVALID_GS_COOKIE_OFFSET)) + return false; + + if ((syncStartOffset == INVALID_SYNC_OFFSET) != + (target.syncStartOffset == INVALID_SYNC_OFFSET)) + return false; + + if ((revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) != + (target.revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET)) + return false; + + return true; + } +}; + + +union CallPattern { + struct { + unsigned char argCnt; + unsigned char regMask; // EBP=0x8, EBX=0x4, ESI=0x2, EDI=0x1 + unsigned char argMask; + unsigned char codeDelta; + } fld; + unsigned val; +}; + +#include + +#define IH_MAX_PROLOG_SIZE (51) + +extern const InfoHdrSmall infoHdrShortcut[]; +extern int infoHdrLookup[]; + +inline void GetInfoHdr(int index, InfoHdr * header) +{ + *((InfoHdrSmall *)header) = infoHdrShortcut[index]; + + header->gsCookieOffset = INVALID_GS_COOKIE_OFFSET; + header->syncStartOffset = INVALID_SYNC_OFFSET; + header->syncEndOffset = INVALID_SYNC_OFFSET; + header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; +} + +PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header); + +BYTE FASTCALL encodeHeaderFirst(const InfoHdr& header, InfoHdr* state, int* more, int *pCached); +BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state, BYTE &codeSet); + +size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* value); +size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue); +size_t FASTCALL decodeSigned(PTR_CBYTE src, int * value); + +#define CP_MAX_CODE_DELTA (0x23) +#define CP_MAX_ARG_CNT (0x02) +#define CP_MAX_ARG_MASK (0x00) + +extern const unsigned callPatternTable[]; +extern const unsigned callCommonDelta[]; + + +int FASTCALL lookupCallPattern(unsigned argCnt, + unsigned regMask, + unsigned argMask, + unsigned codeDelta); + +void FASTCALL decodeCallPattern(int pattern, + unsigned * argCnt, + unsigned * regMask, + unsigned * argMask, + unsigned * codeDelta); + +#endif // _TARGET_86_ + +// Stack offsets must be 8-byte aligned, so we use this unaligned +// offset to represent that the method doesn't have a security object +#define NO_SECURITY_OBJECT (-1) +#define NO_GS_COOKIE (-1) +#define NO_STACK_BASE_REGISTER (0xffffffff) +#define NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA (0xffffffff) +#define NO_GENERICS_INST_CONTEXT (-1) +#define NO_REVERSE_PINVOKE_FRAME (-1) +#define NO_PSP_SYM (-1) + +#if defined(_TARGET_AMD64_) + +#ifndef TARGET_POINTER_SIZE +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#endif +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) +#define NORMALIZE_STACK_SLOT(x) ((x)>>3) +#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) +#define NORMALIZE_CODE_LENGTH(x) (x) +#define DENORMALIZE_CODE_LENGTH(x) (x) +// Encode RBP as 0 +#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) +#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) +#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) +#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) +#define CODE_OFFSETS_NEED_NORMALIZATION 0 +#define NORMALIZE_CODE_OFFSET(x) (x) +#define DENORMALIZE_CODE_OFFSET(x) (x) +#define NORMALIZE_REGISTER(x) (x) +#define DENORMALIZE_REGISTER(x) (x) +#define NORMALIZE_NUM_SAFE_POINTS(x) (x) +#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) +#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) +#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) + +#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 +#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 +#define GS_COOKIE_STACK_SLOT_ENCBASE 6 +#define CODE_LENGTH_ENCBASE 8 +#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 +#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 +#define STACK_BASE_REGISTER_ENCBASE 3 +#define SIZE_OF_STACK_AREA_ENCBASE 3 +#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 +#define REVERSE_PINVOKE_FRAME_ENCBASE 6 +#define NUM_REGISTERS_ENCBASE 2 +#define NUM_STACK_SLOTS_ENCBASE 2 +#define NUM_UNTRACKED_SLOTS_ENCBASE 1 +#define NORM_PROLOG_SIZE_ENCBASE 5 +#define NORM_EPILOG_SIZE_ENCBASE 3 +#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 +#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 +#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 +#define REGISTER_ENCBASE 3 +#define REGISTER_DELTA_ENCBASE 2 +#define STACK_SLOT_ENCBASE 6 +#define STACK_SLOT_DELTA_ENCBASE 4 +#define NUM_SAFE_POINTS_ENCBASE 2 +#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 +#define NUM_EH_CLAUSES_ENCBASE 2 +#define POINTER_SIZE_ENCBASE 3 +#define LIVESTATE_RLE_RUN_ENCBASE 2 +#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#elif defined(_TARGET_ARM_) + +#ifndef TARGET_POINTER_SIZE +#define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#endif +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) +#define NORMALIZE_STACK_SLOT(x) ((x)>>2) +#define DENORMALIZE_STACK_SLOT(x) ((x)<<2) +#define NORMALIZE_CODE_LENGTH(x) ((x)>>1) +#define DENORMALIZE_CODE_LENGTH(x) ((x)<<1) +// Encode R11 as zero +#define NORMALIZE_STACK_BASE_REGISTER(x) ((((x) - 4) & 7) ^ 7) +#define DENORMALIZE_STACK_BASE_REGISTER(x) (((x) ^ 7) + 4) +#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2) +#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2) +#define CODE_OFFSETS_NEED_NORMALIZATION 1 +#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states, +#define DENORMALIZE_CODE_OFFSET(x) (x) // but the safe-point offsets are encoded with a -1 adjustment. +#define NORMALIZE_REGISTER(x) (x) +#define DENORMALIZE_REGISTER(x) (x) +#define NORMALIZE_NUM_SAFE_POINTS(x) (x) +#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) +#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) +#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) + +// The choices of these encoding bases only affects space overhead +// and performance, not semantics/correctness. +#define PSP_SYM_STACK_SLOT_ENCBASE 5 +#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5 +#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5 +#define GS_COOKIE_STACK_SLOT_ENCBASE 5 +#define CODE_LENGTH_ENCBASE 7 +#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 +#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 +#define STACK_BASE_REGISTER_ENCBASE 1 +#define SIZE_OF_STACK_AREA_ENCBASE 3 +#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 +#define REVERSE_PINVOKE_FRAME_ENCBASE 5 +#define NUM_REGISTERS_ENCBASE 2 +#define NUM_STACK_SLOTS_ENCBASE 3 +#define NUM_UNTRACKED_SLOTS_ENCBASE 3 +#define NORM_PROLOG_SIZE_ENCBASE 5 +#define NORM_EPILOG_SIZE_ENCBASE 3 +#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 +#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 4 +#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 +#define REGISTER_ENCBASE 2 +#define REGISTER_DELTA_ENCBASE 1 +#define STACK_SLOT_ENCBASE 6 +#define STACK_SLOT_DELTA_ENCBASE 4 +#define NUM_SAFE_POINTS_ENCBASE 3 +#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 2 +#define NUM_EH_CLAUSES_ENCBASE 3 +#define POINTER_SIZE_ENCBASE 3 +#define LIVESTATE_RLE_RUN_ENCBASE 2 +#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#elif defined(_TARGET_ARM64_) + +#ifndef TARGET_POINTER_SIZE +#define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#endif +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) +#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned +#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) +#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long +#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) +#define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero +#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) +#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) +#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) +#define CODE_OFFSETS_NEED_NORMALIZATION 0 +#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point +#define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. +#define NORMALIZE_REGISTER(x) (x) +#define DENORMALIZE_REGISTER(x) (x) +#define NORMALIZE_NUM_SAFE_POINTS(x) (x) +#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) +#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) +#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) + +#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 +#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 +#define GS_COOKIE_STACK_SLOT_ENCBASE 6 +#define CODE_LENGTH_ENCBASE 8 +#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 +#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 +#define STACK_BASE_REGISTER_ENCBASE 2 // FP encoded as 0, SP as 2. +#define SIZE_OF_STACK_AREA_ENCBASE 3 +#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 +#define REVERSE_PINVOKE_FRAME_ENCBASE 6 +#define NUM_REGISTERS_ENCBASE 3 +#define NUM_STACK_SLOTS_ENCBASE 2 +#define NUM_UNTRACKED_SLOTS_ENCBASE 1 +#define NORM_PROLOG_SIZE_ENCBASE 5 +#define NORM_EPILOG_SIZE_ENCBASE 3 +#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 +#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 +#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 +#define REGISTER_ENCBASE 3 +#define REGISTER_DELTA_ENCBASE 2 +#define STACK_SLOT_ENCBASE 6 +#define STACK_SLOT_DELTA_ENCBASE 4 +#define NUM_SAFE_POINTS_ENCBASE 3 +#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 +#define NUM_EH_CLAUSES_ENCBASE 2 +#define POINTER_SIZE_ENCBASE 3 +#define LIVESTATE_RLE_RUN_ENCBASE 2 +#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#else + +#ifndef _TARGET_X86_ +#ifdef PORTABILITY_WARNING +PORTABILITY_WARNING("Please specialize these definitions for your platform!") +#endif +#endif + +#ifndef TARGET_POINTER_SIZE +#define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target +#endif +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) +#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) +#define NORMALIZE_STACK_SLOT(x) (x) +#define DENORMALIZE_STACK_SLOT(x) (x) +#define NORMALIZE_CODE_LENGTH(x) (x) +#define DENORMALIZE_CODE_LENGTH(x) (x) +#define NORMALIZE_STACK_BASE_REGISTER(x) (x) +#define DENORMALIZE_STACK_BASE_REGISTER(x) (x) +#define NORMALIZE_SIZE_OF_STACK_AREA(x) (x) +#define DENORMALIZE_SIZE_OF_STACK_AREA(x) (x) +#define CODE_OFFSETS_NEED_NORMALIZATION 0 +#define NORMALIZE_CODE_OFFSET(x) (x) +#define DENORMALIZE_CODE_OFFSET(x) (x) +#define NORMALIZE_REGISTER(x) (x) +#define DENORMALIZE_REGISTER(x) (x) +#define NORMALIZE_NUM_SAFE_POINTS(x) (x) +#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) +#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) +#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) + +#define PSP_SYM_STACK_SLOT_ENCBASE 6 +#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 +#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 +#define GS_COOKIE_STACK_SLOT_ENCBASE 6 +#define CODE_LENGTH_ENCBASE 6 +#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 +#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 +#define STACK_BASE_REGISTER_ENCBASE 3 +#define SIZE_OF_STACK_AREA_ENCBASE 6 +#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 +#define REVERSE_PINVOKE_FRAME_ENCBASE 6 +#define NUM_REGISTERS_ENCBASE 3 +#define NUM_STACK_SLOTS_ENCBASE 5 +#define NUM_UNTRACKED_SLOTS_ENCBASE 5 +#define NORM_PROLOG_SIZE_ENCBASE 4 +#define NORM_EPILOG_SIZE_ENCBASE 3 +#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 +#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 5 +#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 5 +#define REGISTER_ENCBASE 3 +#define REGISTER_DELTA_ENCBASE REGISTER_ENCBASE +#define STACK_SLOT_ENCBASE 6 +#define STACK_SLOT_DELTA_ENCBASE 4 +#define NUM_SAFE_POINTS_ENCBASE 4 +#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 +#define NUM_EH_CLAUSES_ENCBASE 2 +#define POINTER_SIZE_ENCBASE 3 +#define LIVESTATE_RLE_RUN_ENCBASE 2 +#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#endif + +#endif // !__GCINFOTYPES_H__ + diff --git a/lib/coreclr/src/inc/gcrefmap.h b/lib/coreclr/src/inc/gcrefmap.h new file mode 100644 index 0000000000..0e07074cda --- /dev/null +++ b/lib/coreclr/src/inc/gcrefmap.h @@ -0,0 +1,247 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _GCREFMAP_H_ +#define _GCREFMAP_H_ + +#include "sigbuilder.h" + +// +// The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is +// position of the reference in the stack frame and token is type of GC reference (one of GCREFMAP_XXX values). +// +// - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding +// stream. The last byte has the high order bit zero. It means that there are 7 useful bits in each byte. +// - "pos" is always encoded as delta from previous pos. +// - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior +// pointer). Value 3 means that extended encoding follows. +// - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is +// used to signal the end. +// - For x86, the encoding starts by size of the callee poped stack. The size is encoded using the same mechanism as above (two bit +// basic encoding, with extended encoding for large values). + +///////////////////////////////////////////////////////////////////////////////////// +// A utility class to encode sequence of GC summaries for a callsite + +class GCRefMapBuilder +{ + int m_PendingByte; // Pending value, not yet written out + + int m_Bits; // Number of bits in pending byte. Note that the trailing zero bits are not written out, + // so this can be more than 7. + + int m_Pos; // Current position + + SigBuilder m_SigBuilder; + + // Append single bit to the stream + void AppendBit(int bit) + { + if (bit != 0) + { + while (m_Bits >= 7) + { + m_SigBuilder.AppendByte((BYTE)(m_PendingByte | 0x80)); + m_PendingByte = 0; + m_Bits -= 7; + } + + m_PendingByte |= (1 << m_Bits); + } + + m_Bits++; + } + + void AppendTwoBit(int bits) + { + AppendBit(bits & 1); + AppendBit(bits >> 1); + } + + void AppendInt(int val) + { + do { + AppendBit(val & 1); + AppendBit((val >> 1) & 1); + AppendBit((val >> 2) & 1); + + val >>= 3; + + AppendBit((val != 0) ? 1 : 0); + } + while (val != 0); + } + +public: + GCRefMapBuilder() + : m_PendingByte(0), m_Bits(0), m_Pos(0) + { + } + +#ifdef _TARGET_X86_ + void WriteStackPop(int stackPop) + { + if (stackPop < 3) + { + AppendTwoBit(stackPop); + } + else + { + AppendTwoBit(3); + AppendInt(stackPop - 3); + } + } +#endif + + void WriteToken(int pos, int gcRefMapToken) + { + int posDelta = pos - m_Pos; + m_Pos = pos + 1; + + if (posDelta != 0) + { + if (posDelta < 4) + { + // Skipping by one slot at a time for small deltas produces smaller encoding. + while (posDelta > 0) + { + AppendTwoBit(0); + posDelta--; + } + } + else + { + AppendTwoBit(3); + AppendInt((posDelta - 4) << 1); + } + } + + if (gcRefMapToken < 3) + { + AppendTwoBit(gcRefMapToken); + } + else + { + AppendTwoBit(3); + AppendInt(((gcRefMapToken - 3) << 1) | 1); + } + } + + void Flush() + { + if ((m_PendingByte & 0x7F) != 0 || m_Pos == 0) + m_SigBuilder.AppendByte((BYTE)(m_PendingByte & 0x7F)); + + m_PendingByte = 0; + m_Bits = 0; + + m_Pos = 0; + } + + PVOID GetBlob(DWORD * pdwLength) + { + return m_SigBuilder.GetSignature(pdwLength); + } + + DWORD GetBlobLength() + { + return m_SigBuilder.GetSignatureLength(); + } +}; + +///////////////////////////////////////////////////////////////////////////////////// +// A utility class to decode a GC summary for a callsite + +class GCRefMapDecoder +{ + PTR_BYTE m_pCurrentByte; + int m_PendingByte; + int m_Pos; + + FORCEINLINE int GetBit() + { + int x = m_PendingByte; + if (x & 0x80) + { + x = *m_pCurrentByte++; + x |= ((x & 0x80) << 7); + } + m_PendingByte = x >> 1; + return x & 1; + } + + FORCEINLINE int GetTwoBit() + { + int result = GetBit(); + result |= GetBit() << 1; + return result; + } + + int GetInt() + { + int result = 0; + + int bit = 0; + do { + result |= GetBit() << (bit++); + result |= GetBit() << (bit++); + result |= GetBit() << (bit++); + } + while (GetBit() != 0); + + return result; + } + +public: + GCRefMapDecoder(PTR_BYTE pBlob) + : m_pCurrentByte(pBlob), m_PendingByte(0x80), m_Pos(0) + { + } + + BOOL AtEnd() + { + return m_PendingByte == 0; + } + +#ifdef _TARGET_X86_ + UINT ReadStackPop() + { + int x = GetTwoBit(); + + if (x == 3) + x = GetInt() + 3; + + return x; + } +#endif + + int CurrentPos() + { + return m_Pos; + } + + int ReadToken() + { + int val = GetTwoBit(); + if (val == 3) + { + int ext = GetInt(); + if ((ext & 1) == 0) + { + m_Pos += (ext >> 1) + 4; + return GCREFMAP_SKIP; + } + else + { + m_Pos++; + return (ext >> 1) + 3; + } + } + m_Pos++; + return val; + } +}; + +#endif // _GCREFMAP_H_ diff --git a/lib/coreclr/src/inc/genheaders.cs b/lib/coreclr/src/inc/genheaders.cs new file mode 100644 index 0000000000..6a55cd85ee --- /dev/null +++ b/lib/coreclr/src/inc/genheaders.cs @@ -0,0 +1,233 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Xml; +using System.Xml.Schema; +using System.IO; + +public class GenerateHeaders { + + public static void Main(string[] args) { + + if (args.Length != 3) { + Console.WriteLine("Usage:genheaders XML-file header-file resorce-file"); + return; + } + + ValidateXML(args[0]); + String Message=null; + String SymbolicName=null; + String NumericValue=null; + String tempheaderfile = "temp.h"; + String temprcfile = "temp.rc"; + + StreamWriter HSW=File.CreateText(tempheaderfile); + StreamWriter RSW=File.CreateText(temprcfile); + + int FaciltyUrt=0x13; + int SeveritySuccess=0; + int SeverityError=1; + + int minSR = MakeHresult(SeveritySuccess,FaciltyUrt,0); + int maxSR = MakeHresult(SeveritySuccess,FaciltyUrt,0xffff); + int minHR = MakeHresult(SeverityError,FaciltyUrt,0); + int maxHR = MakeHresult(SeverityError,FaciltyUrt,0xffff); + + PrintLicenseHeader(HSW); + PrintHeader(HSW); + PrintLicenseHeader(RSW); + PrintResourceHeader(RSW); + + XmlTextReader rdr = new XmlTextReader(args[0]); + rdr.WhitespaceHandling = WhitespaceHandling.None; + + while (rdr.Read()) { + + switch (rdr.NodeType) { + + case XmlNodeType.Element: + + if (rdr.Name.ToString() == "HRESULT") { + NumericValue=rdr.GetAttribute("NumericValue"); + } + if (rdr.Name.ToString() == "Message") { + Message = rdr.ReadString(); + } + if (rdr.Name.ToString() == "SymbolicName") { + SymbolicName = rdr.ReadString(); + } + + break; + + case XmlNodeType.EndElement: + if(rdr.Name.ToString() == "HRESULT"){ + + // For CLR Hresult's we take the last 4 digits as the resource strings. + + if ( (NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X")) ) { + + String HexResult = NumericValue.Substring(2); + int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); + + if ((num>minSR) && (num <= maxSR)) { + num = num & 0xffff; + HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); + } else if ((num>minHR) && (num <= maxHR)) { + num = num & 0xffff; + HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); + } else { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); + } + + + + } else { + HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); + } + + if (Message != null) { + RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); + RSW.WriteLine(Message); + } + + SymbolicName = null; + NumericValue = null; + Message = null; + } + break; + + } + } + + PrintFooter(HSW); + PrintResourceFooter(RSW); + + HSW.Close(); + RSW.Close(); + + bool AreFilesEqual = false; + + if (File.Exists(args[1])) { + StreamReader sr1 = new StreamReader(tempheaderfile); + StreamReader sr2 = new StreamReader(args[1]); + AreFilesEqual = CompareFiles(sr1, sr2); + sr1.Close(); + sr2.Close(); + } + + if (!AreFilesEqual) { + File.Copy(tempheaderfile, args[1], true); + File.Copy(temprcfile, args[2], true); + } + + if (!File.Exists(args[2])) { + File.Copy(temprcfile, args[2], true); + } + + File.Delete(tempheaderfile); + File.Delete(temprcfile); + } + + private static void ValidateXML (String XMLFile) { + + // Set the validation settings on the XmlReaderSettings object. + XmlReaderSettings settings = new XmlReaderSettings(); + + settings.ValidationType = ValidationType.Schema; + settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; + + settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); + + // Create the XmlReader object. + XmlReader reader = XmlReader.Create(XMLFile, settings); + + // Parse the file. + + while (reader.Read()) { + } + } + + // Display any validation errors. + private static void ValidationCallBack(object sender, ValidationEventArgs e) { + Console.WriteLine("Validation Error: {0}", e.Message); + Environment.Exit(-1); + } + + private static void PrintLicenseHeader(StreamWriter SW) { + SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); + SW.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); + SW.WriteLine("// See the LICENSE file in the project root for more information."); + SW.WriteLine(); + } + + private static void PrintHeader(StreamWriter SW) { + + SW.WriteLine("#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); + SW.WriteLine("#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); + SW.WriteLine(); + SW.WriteLine("#include "); + SW.WriteLine(); + SW.WriteLine(); + SW.WriteLine("//"); + SW.WriteLine("//This file is AutoGenerated -- Do Not Edit by hand!!!"); + SW.WriteLine("//"); + SW.WriteLine("//Add new HRESULTS along with their corresponding error messages to"); + SW.WriteLine("//corerror.xml"); + SW.WriteLine("//"); + SW.WriteLine(); + SW.WriteLine("#ifndef FACILITY_URT"); + SW.WriteLine("#define FACILITY_URT 0x13"); + SW.WriteLine("#endif"); + SW.WriteLine("#ifndef EMAKEHR"); + SW.WriteLine("#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)"); + SW.WriteLine("#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)"); + SW.WriteLine("#endif"); + SW.WriteLine(); + } + + private static void PrintFooter(StreamWriter SW) { + SW.WriteLine(); + SW.WriteLine(); + SW.WriteLine("#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); + } + + private static void PrintResourceHeader(StreamWriter SW) { + SW.WriteLine("STRINGTABLE DISCARDABLE"); + SW.WriteLine("BEGIN"); + } + + private static void PrintResourceFooter(StreamWriter SW) { + SW.WriteLine("END"); + } + + private static bool CompareFiles(StreamReader sr1, StreamReader sr2) { + String line1,line2; + + while (true) { + line1 = sr1.ReadLine(); + line2 = sr2.ReadLine(); + + if ( (line1 == null) && (line2 == null) ) { + return true; + } + + if (line1 != line2) { + return false; + } + + } + + } + + private static int MakeHresult(int sev, int fac, int code) { + return ((sev<<31) | (fac<<16) | (code)); + } +} + + + + + + diff --git a/lib/coreclr/src/inc/genrops.pl b/lib/coreclr/src/inc/genrops.pl new file mode 100644 index 0000000000..415eea731a --- /dev/null +++ b/lib/coreclr/src/inc/genrops.pl @@ -0,0 +1,91 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# See the LICENSE file in the project root for more information. +# +# GENREFOPS.PL +# +# PERL script used to generate the numbering of the reference opcodes +# +#use strict 'vars'; +#use strict 'subs'; +#use strict 'refs'; + +print "Reference opcodes\n"; +print "This file is presently only for human consumption\n"; +print "This file is generated from opcode.def using the genrops.pl script\n\n"; +print "Name String Name refop encode\n"; +print "-----------------------------------------------------------------\n"; + +my $ret = 0; +my %oneByte; +my %twoByte; +$count = 0; +while (<>) +{ + # Process only OPDEF(....) lines + if (/OPDEF\(\s*/) + { + chop; # Strip off trailing CR + s/^OPDEF\(\s*//; # Strip off "OP(" + s/\)$//; # Strip off ")" at end + s/,\s*/,/g; # Remove whitespace + + # Split the line up into its basic parts + ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/); + $s1 =~ s/0x//; + $s1 = hex($s1); + $s2 =~ s/0x//; + $s2 = hex($s2); + + + my $line = sprintf("%-24s %-24s 0x%03x", + $enumname, $stringname, $count); + if ($size == 1) { + $line .= sprintf(" 0x%02x\n", $s2); + if ($oneByte{$s2}) { + printf("Error opcode 0x%x already defined!\n", $s2); + print " Old = $oneByte{$s2}"; + print " New = $line"; + $ret = -1; + } + $oneByte{$s2} = $line; + } + elsif ($size == 2) { + if ($twoByte{$s2}) { + printf("Error opcode 0x%x 0x%x already defined!\n", $s1, $s2); + print " Old = $twoByte{$s2}"; + print " New = $line"; + $ret = -1; + } + $line .= sprintf(" 0x%02x 0x%02x\n", $s1, $s2); + $twoByte{$s2 + 256 * $s1} = $line; + } + else { + $line .= "\n"; + push(@deprecated, $line); + } + $count++; + } +} + +my $opcode; +my $lastOp = -1; +foreach $opcode (sort {$a <=> $b} keys(%oneByte)) { + printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); + print $oneByte{$opcode}; + $lastOp = $opcode; +} + +$lastOp = -1; +foreach $opcode (sort {$a <=> $b} keys(%twoByte)) { + printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); + print $twoByte{$opcode}; + $lastOp = $opcode; +} + +print @deprecated; + +exit($ret); + + + diff --git a/lib/coreclr/src/inc/getproductversionnumber.h b/lib/coreclr/src/inc/getproductversionnumber.h new file mode 100644 index 0000000000..81367fa3e5 --- /dev/null +++ b/lib/coreclr/src/inc/getproductversionnumber.h @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// GetProductVersionNumber.h +// +// Helper function to retrieve the file version number of a file. +// +// ====================================================================================== + + + +#ifndef __GetProductVersionNumber_h__ +#define __GetProductVersionNumber_h__ + +#include "contract.h" +#include "sstring.h" +#include "holder.h" +#include "ex.h" + +//--------------------------------------------------------------------------------------- +// +// Given the full path to an image, return the product version number. +// +// Arguments: +// szFullPath - full path to the image +// pdwVersionMS - out parameter; return the most significant 4 bytes of the version number according to +// the VS_FIXEDFILEINFO convention +// pdwVersionLS - out parameter; return the least significant 4 bytes of the version number according to +// the VS_FIXEDFILEINFO convention +// +// Notes: +// Throws on error + +void inline GetProductVersionNumber(SString &szFullPath, DWORD * pdwVersionMS, DWORD * pdwVersionLS) +{ + WRAPPER_NO_CONTRACT; +#ifndef FEATURE_PAL + + DWORD dwDummy = 0; + DWORD dwFileInfoSize = 0; + + // Get the size of all of the file version information. + dwFileInfoSize = GetFileVersionInfoSize(szFullPath, &dwDummy); + if (dwFileInfoSize == 0) + { + ThrowLastError(); + } + + // Create the buffer to store the file information. + NewHolder pbFileInfo(new BYTE[dwFileInfoSize]); + + // Actually retrieve the file version information. + if (!GetFileVersionInfo(szFullPath, NULL, dwFileInfoSize, pbFileInfo)) + { + ThrowLastError(); + } + + // Now retrieve only the relevant version information, which will be returned in a VS_FIXEDFILEINFO. + UINT uVersionInfoSize = 0; + VS_FIXEDFILEINFO * pVersionInfo = NULL; + + if (!VerQueryValue(pbFileInfo, W("\\"), reinterpret_cast(&pVersionInfo), &uVersionInfoSize)) + { + ThrowLastError(); + } + _ASSERTE(uVersionInfoSize == sizeof(VS_FIXEDFILEINFO)); + + *pdwVersionMS = pVersionInfo->dwProductVersionMS; + *pdwVersionLS = pVersionInfo->dwProductVersionLS; +#else + *pdwVersionMS = 0; + *pdwVersionLS = 0; +#endif // FEATURE_PAL +} + +#endif // __GetProductVersionNumber_h__ diff --git a/lib/coreclr/src/inc/guidfromname.h b/lib/coreclr/src/inc/guidfromname.h new file mode 100644 index 0000000000..2974de44aa --- /dev/null +++ b/lib/coreclr/src/inc/guidfromname.h @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef GUIDFROMNAME_H_ +#define GUIDFROMNAME_H_ + +// GuidFromName.h - function prototype + +void CorGuidFromNameW +( + GUID * pGuidResult, // resulting GUID + LPCWSTR wzName, // the unicode name from which to generate a GUID + SIZE_T cchName // name length in count of unicode character. + // -1 if lstrlen(wzName)+1 should be used +); + +#endif // GUIDFROMNAME_H_ diff --git a/lib/coreclr/src/inc/holder.h b/lib/coreclr/src/inc/holder.h new file mode 100644 index 0000000000..204f807a08 --- /dev/null +++ b/lib/coreclr/src/inc/holder.h @@ -0,0 +1,1399 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef __HOLDER_H_ +#define __HOLDER_H_ + +#include +#include "cor.h" +#include "staticcontract.h" +#include "volatile.h" +#include "palclr.h" + +#ifdef PAL_STDCPP_COMPAT +#include +#include +#else +#include "clr_std/utility" +#include "clr_std/type_traits" +#endif + +#if defined(FEATURE_COMINTEROP) && !defined(STRIKE) +#include +#include +#endif + +// Note: you can't use CONTRACT's in this file. You can't use dynamic contracts because the impl of dynamic +// contracts depends on holders. You can't use static contracts because they include the function name as a string, +// and the template names in this file are just too long, so you get a compiler error. +// +// All the functions in this file are pretty basic, so the lack of CONTRACT's isn't a big loss. + +#ifdef _MSC_VER +// Make sure we can recurse deep enough for FORCEINLINE +#pragma inline_recursion(on) +#pragma inline_depth(16) +#pragma warning(disable:4714) +#endif // _MSC_VER + +//------------------------------------------------------------------------------------------------ +// Declare but do not define methods that would normally be automatically generated by the +// compiler. This will produce a link-time error if they are used. This is involved in object +// initialization and operator eliding; see +// http://groups.google.com/group/comp.lang.c++/msg/3cd673ab749bed83?dmode=source +// for the intricate details. + +#ifdef __GNUC__ +// GCC checks accessibility of the copy ctor before performing elision optimization, so +// it must be declared as public. VC does not, so we can declare it private to give an +// earlier error message. +#define HIDE_GENERATED_METHODS(_NAME) \ + public: \ + _NAME(_NAME const &); \ + private: \ + _NAME & operator=(_NAME const &); +#else +#define HIDE_GENERATED_METHODS(_NAME) \ + private: \ + _NAME(_NAME const &); \ + _NAME & operator=(_NAME const &); +#endif + +#ifdef _DEBUG + +//------------------------------------------------------------------------------------------------ +// This is used to make Visual Studio autoexp.dat work sensibly with holders again. +// The problem is that certain codebases (particulary Fusion) implement key data structures +// using a class but refer to it using a holder to an interface type. This combination prevents +// autoexp rules from working as desired. +// +// Example: Take this useful autoexp rule for CAssemblyName. +// +// CAssemblyName=<_rProp._rProp[3].asStr> +// +// To get the same rule to fire when your assemblyname is wrapped in a ReleaseHolder, +// add these companion rules. +// +// HolderBase=_rProp._rProp[3].asStr> +// HolderBase=_asCAssemblyName->_rProp._rProp[3].asStr> +// +//------------------------------------------------------------------------------------------------ +struct AutoExpVisibleValue +{ + private: + union + { + // Only include a class name here if it is customarily referred to through an abstract interface. + +#if defined(FEATURE_APPX) + const class AppXBindResultImpl *_asAppXBindResultImpl; +#endif + + const void *_pPreventEmptyUnion; + }; +}; +#endif //_DEBUG + +//----------------------------------------------------------------------------- +// Holder is the base class of all holder objects. Any backout object should derive from it. +// (Eventually some additional bookeeping and exception handling code will be placed in this +// base class.) +// +// There are several ways to use this class: +// 1. Derive from HolderBase, and instantiate a Holder or Wrapper around your base. This is necessary +// if you need to add more state to your holder. +// 2. Instantiate the Holder template with your type and functions. +// 3. Instantiate the Wrapper template with your type and functions. The Wrapper adds some additional +// operator overloads to provide "smart pointer" like behavior +// 4. Use a prebaked Holder. This is ALWAYS the preferable strategy. It is expected that +// the general design patter is that Holders will be provided as part of a typical data abstraction. +// (See Crst for an example of this.) +//----------------------------------------------------------------------------- + + + +//----------------------------------------------------------------------------- +// HolderBase defines the base holder functionality. You can subtype and plug in +// a different base if you need to add more members for access during +// acquire & release +//----------------------------------------------------------------------------- +template +class HolderBase +{ + protected: + TYPE m_value; + + HolderBase(TYPE value) + : m_value(value) + { +#ifdef _DEBUG + m_pAutoExpVisibleValue = (const AutoExpVisibleValue *)(&m_value); +#endif //_DEBUG + } + + void DoAcquire() + { + // Insert any global or thread bookeeping here + } + + void DoRelease() + { + // Insert any global or thread bookeeping here + } + +#ifdef _DEBUG + private: + // NOT DEAD CODE: This field is not referenced in the source code but it is not a dead field. See comments above "class AutoExpVisibleValue" for why this field exists. + // Note: What we really want is for m_value and m_pAutoExpVisibleValue to be members of a union. But the compiler won't let you build that + // since it can't prove that "TYPE" doesn't have a non-trivial constructor. + const AutoExpVisibleValue *m_pAutoExpVisibleValue; // This field is to be referenced from individual autoexp.dat files, NOT from the CLR source code. +#endif //_DEBUG + +}; // class HolderBase<> + +#ifndef _PREFAST_ // Work around an ICE error in EspX.dll + +template +BOOL CompareDefault(TYPE value, TYPE defaultValue) +{ + STATIC_CONTRACT_SUPPORTS_DAC; + return value == defaultValue; +} + +#else + +template +BOOL CompareDefault(TYPE value, TYPE defaultValue) +{ + return FALSE; +} + +#endif + + +template +BOOL NoNull(TYPE value, TYPE defaultValue) +{ + return FALSE; +} + +// Used e.g. for retail version of code:SyncAccessHolder +template +class NoOpBaseHolder +{ + public: + FORCEINLINE NoOpBaseHolder() + { + } + FORCEINLINE NoOpBaseHolder(TYPE value, BOOL take = TRUE) + { + } + FORCEINLINE ~NoOpBaseHolder() + { + } + FORCEINLINE void Assign(TYPE value, BOOL fTake = TRUE) + { + } + FORCEINLINE void Acquire() + { + } + FORCEINLINE void Release() + { + } + FORCEINLINE void Clear() + { + } + FORCEINLINE void SuppressRelease() + { + } + FORCEINLINE TYPE Extract() + { + } + FORCEINLINE TYPE GetValue() + { + } + FORCEINLINE BOOL IsNull() const + { + return FALSE; + } + + private: + NoOpBaseHolder& operator=(NoOpBaseHolder const &); + NoOpBaseHolder(NoOpBaseHolder const &); +}; // NoOpBaseHolder<> + + +template + < + typename TYPE, + typename BASE, + UINT_PTR DEFAULTVALUE = 0, + BOOL IS_NULL(TYPE, TYPE) = CompareDefault + > +class BaseHolder : protected BASE +{ + protected: + BOOL m_acquired; // Have we acquired the resource? + + static_assert(!std::is_pointer::value || DEFAULTVALUE == 0 || DEFAULTVALUE == UINT_PTR(-1 /*INVALID_HANDLE_VALUE*/), + "DEFAULTVALUE must be NULL for pointer holders and wrappers."); + + public: + FORCEINLINE BaseHolder() + : BASE(TYPE(DEFAULTVALUE)), + m_acquired(FALSE) + { + } + FORCEINLINE BaseHolder(TYPE value) + : BASE(value), + m_acquired(FALSE) + { + if (!IsNull()) + Acquire(); + } + FORCEINLINE BaseHolder(TYPE value, BOOL takeOwnership) + : BASE(value), + m_acquired(FALSE) + { + if (takeOwnership) + Acquire(); + } + FORCEINLINE ~BaseHolder() + { + Release(); + } + // Sets the value to 'value'. Doesn't call Acquire if value is DEFAULTVALUE. + FORCEINLINE void Assign(TYPE value) + { + Assign(value, !IS_NULL(value, TYPE(DEFAULTVALUE))); + } + // Sets the value to 'value'. Doesn't call Acquire if fTake is FALSE. + FORCEINLINE void Assign(TYPE value, BOOL takeOwnership) + { + Release(); + this->m_value = value; + if (takeOwnership) + Acquire(); + } + FORCEINLINE void Acquire() + { + STATIC_CONTRACT_WRAPPER; + _ASSERTE(!m_acquired); + + if (!IsNull()) + { + this->DoAcquire(); + m_acquired = TRUE; + } + } + FORCEINLINE void Release() + { + STATIC_CONTRACT_WRAPPER; + if (m_acquired) + { + _ASSERTE(!IsNull()); + this->DoRelease(); + m_acquired = FALSE; + } + } + + FORCEINLINE void Clear() + { + STATIC_CONTRACT_WRAPPER; + Assign(TYPE(DEFAULTVALUE), FALSE); + } + FORCEINLINE void SuppressRelease() + { + STATIC_CONTRACT_LEAF; + m_acquired = FALSE; + } + FORCEINLINE TYPE Extract() + { + STATIC_CONTRACT_WRAPPER; + SuppressRelease(); + return GetValue(); + } + FORCEINLINE TYPE GetValue() + { + STATIC_CONTRACT_LEAF; + return this->m_value; + } + FORCEINLINE BOOL IsNull() const + { + STATIC_CONTRACT_WRAPPER; + return IS_NULL(this->m_value, TYPE(DEFAULTVALUE)); + } + + HIDE_GENERATED_METHODS(BaseHolder) +}; // BaseHolder<> + +template +class StateHolder +{ + private: + BOOL m_acquired; // Have we acquired the state? + + public: + FORCEINLINE StateHolder(BOOL take = TRUE) + : m_acquired(FALSE) + { + STATIC_CONTRACT_WRAPPER; + if (take) + Acquire(); + } + FORCEINLINE ~StateHolder() + { + STATIC_CONTRACT_WRAPPER; + Release(); + } + FORCEINLINE void Acquire() + { + STATIC_CONTRACT_WRAPPER; + // Insert any global or thread bookeeping here + + _ASSERTE(!m_acquired); + + ACQUIRE(); + m_acquired = TRUE; + } + FORCEINLINE void Release() + { + STATIC_CONTRACT_WRAPPER; + // Insert any global or thread bookeeping here + + if (m_acquired) + { + RELEASEF(); + m_acquired = FALSE; + } + } + FORCEINLINE void Clear() + { + STATIC_CONTRACT_WRAPPER; + if (m_acquired) + { + RELEASEF(); + } + + m_acquired = FALSE; + } + FORCEINLINE void SuppressRelease() + { + STATIC_CONTRACT_LEAF; + m_acquired = FALSE; + } + + HIDE_GENERATED_METHODS(StateHolder) +}; // class StateHolder<> + +// Holder for the case where the acquire function can fail. +template +class ConditionalStateHolder +{ + private: + VALUE m_value; + BOOL m_acquired; // Have we acquired the state? + + public: + FORCEINLINE ConditionalStateHolder(VALUE value, BOOL take = TRUE) + : m_value(value), m_acquired(FALSE) + { + STATIC_CONTRACT_WRAPPER; + if (take) + Acquire(); + } + FORCEINLINE ~ConditionalStateHolder() + { + STATIC_CONTRACT_WRAPPER; + Release(); + } + FORCEINLINE BOOL Acquire() + { + STATIC_CONTRACT_WRAPPER; + // Insert any global or thread bookeeping here + + _ASSERTE(!m_acquired); + + m_acquired = ACQUIRE(m_value); + + return m_acquired; + } + FORCEINLINE void Release() + { + STATIC_CONTRACT_WRAPPER; + // Insert any global or thread bookeeping here + + if (m_acquired) + { + RELEASEF(m_value); + m_acquired = FALSE; + } + } + FORCEINLINE void Clear() + { + STATIC_CONTRACT_WRAPPER; + if (m_acquired) + { + RELEASEF(m_value); + } + + m_acquired = FALSE; + } + FORCEINLINE void SuppressRelease() + { + STATIC_CONTRACT_LEAF; + m_acquired = FALSE; + } + FORCEINLINE BOOL Acquired() + { + STATIC_CONTRACT_LEAF; + + return m_acquired; + } + + HIDE_GENERATED_METHODS(ConditionalStateHolder) +}; // class ConditionalStateHolder<> + + +// Making the copy constructor private produces a warning about "can't generate copy +// constructor" on all holders (duh, that's the point.) +#ifdef _MSC_VER +#pragma warning(disable:4511) +#endif // _MSC_VER + +//----------------------------------------------------------------------------- +// BaseWrapper is just Base like a Holder, but it "transparently" proxies the type it contains, +// using operator overloads. Use this when you want a holder to expose the functionality of +// the value it contains. +//----------------------------------------------------------------------------- +template > +class BaseWrapper : public BaseHolder +{ + typedef BaseHolder BaseT; + + +#ifdef __GNUC__ +//#pragma GCC visibility push(hidden) +#endif // __GNUC__ + // This temporary object takes care of the case where we are initializing + // a holder's contents by passing it as an out parameter. The object is + // guaranteed to live longer than the call it is passed to, hence we should + // properly acquire the object on return + friend class AddressInitHolder; + class AddressInitHolder + { + protected: + BaseWrapper &m_holder; + + public: + FORCEINLINE AddressInitHolder(BaseWrapper &holder) + : m_holder(holder) + { + // + // We must clear the value, to avoid the following scenario: + // + // ReleaseHolder pMyType; + // hr = MyFunction(&pMyType, ...); + // + // hr = MyFunction(&pMyType, ...); <- calls Release before call and Acquire on return. + // + // If the second call to MyFunction were to fail and return without updating the + // out parameter, then ~AddressInitHolder will all Acquire, which is a no-op on + // the underlying pointer but sets m_acquired to TRUE. Thus, when pMyType goes + // out of scope, ReleaseHolder will cause a double-release of pMyType. + // + // By calling Clear, then the call to Acquire in the dtor will not set m_acquired + // to true since IsNull(m_holder.m_value) will return true. + // + m_holder.Clear(); + } + FORCEINLINE ~AddressInitHolder() + { + m_holder.Acquire(); + } + + // It's not optimal to have to declare these casting operators. But if we don't, + // people cannot cast the result of &holder to these values. (The C++ compiler won't + // automatically use the TYPE * cast as an intermediate value.) So we put them here, + // rather than forcing callers to double cast in these common cases. + + FORCEINLINE operator IUnknown **() + { + IUnknown *unknown; + // Typesafe check. This will fail at compile time if + // m_holder.m_value can't be converted to an IUnknown *. + unknown = static_cast(m_holder.m_value); + // do the cast with an unsafe cast + return (IUnknown **)(&m_holder.m_value); + } + +#if defined(FEATURE_COMINTEROP) && !defined(STRIKE) + FORCEINLINE operator IInspectable **() + { + IInspectable *inspectable; + // Typesafe check. This will fail at compile time if + // m_holder.m_value can't be converted to an IInspectable *. + inspectable = static_cast(m_holder.m_value); + return (IInspectable **)(&m_holder.m_value); + + } +#endif // FEATURE_COMINTEROP + + FORCEINLINE operator void **() + { + return (void **)(&m_holder.m_value); + } + FORCEINLINE operator void *() + { + return (void *)(&m_holder.m_value); + } + }; + + // Separate out method with TYPE * cast operator, since it may clash with IUnknown ** or + // void ** cast operator. + friend class TypedAddressInitHolder; + class TypedAddressInitHolder : public AddressInitHolder + { + public: + FORCEINLINE TypedAddressInitHolder(BaseWrapper & holder) + : AddressInitHolder(holder) + { + } + + FORCEINLINE operator TYPE *() + { + return static_cast(&this->m_holder.m_value); + } + }; +#ifdef __GNUC__ +//#pragma GCC visibility pop +#endif // __GNUC__ + + public: + FORCEINLINE BaseWrapper() + : BaseT(TYPE(DEFAULTVALUE), FALSE) + { + } + FORCEINLINE BaseWrapper(TYPE value) + : BaseT(value) + { + } + FORCEINLINE BaseWrapper(TYPE value, BOOL take) + : BaseT(value, take) + { + } + FORCEINLINE BaseWrapper& operator=(TYPE value) + { + BaseT::Assign(value); + return *this; + } + FORCEINLINE operator TYPE() const + { + return this->m_value; + } + FORCEINLINE TypedAddressInitHolder operator&() + { + return TypedAddressInitHolder(*this); + } + template + FORCEINLINE bool operator==(T const & value) const + { + return !!(this->m_value == TYPE(value)); + } + template + FORCEINLINE bool operator!=(T const & value) const + { + return !!(this->m_value != TYPE(value)); + } +#ifdef __GNUC__ + // This handles the NULL value that is an int and clang + // doesn't want to convert int to a pointer + FORCEINLINE bool operator==(int value) const + { + return !!(this->m_value == TYPE((void*)(SIZE_T)value)); + } + FORCEINLINE bool operator!=(int value) const + { + return !!(this->m_value != TYPE((void*)(SIZE_T)value)); + } +#endif // __GNUC__ + FORCEINLINE const TYPE &operator->() const + { + return this->m_value; + } + FORCEINLINE int operator!() const + { + return this->IsNull(); + } + + private: + HIDE_GENERATED_METHODS(BaseWrapper) +}; // class BaseWrapper<> + +//----------------------------------------------------------------------------- +// Generic templates to use to wrap up acquire/release functionality for Holder +//----------------------------------------------------------------------------- + +template +FORCEINLINE void DoNothing(TYPE value) +{ + // @TODO: Due to prefast template problems, implementations of the DoNothing macro have been changed + // Search by prefast, and remove them when prefast is ready +} + +FORCEINLINE void DoNothing() +{ +} + +// Prefast stuff.We should have DoNothing in the holder declaration, but currently +// prefast doesnt support, it, so im stuffing all these here so if we need to change the template you can change +// everything here. When prefast works, remove the following functions +struct ConnectionCookie; +FORCEINLINE void ConnectionCookieDoNothing(ConnectionCookie* p) +{ +} + +class ComCallWrapper; +FORCEINLINE void CCWHolderDoNothing(ComCallWrapper* p) +{ +} + + +FORCEINLINE void DispParamHolderDoNothing(VARIANT* p) +{ +} + +FORCEINLINE void VariantPtrDoNothing(VARIANT* p) +{ +} + +FORCEINLINE void VariantDoNothing(VARIANT) +{ +} + +FORCEINLINE void ZeroDoNothing(VOID* p) +{ +} + +class CtxEntry; +FORCEINLINE void CtxEntryDoNothing(CtxEntry* p) +{ +} + +struct RCW; +FORCEINLINE void NewRCWHolderDoNothing(RCW*) +{ +} + +// Prefast stuff.We should have DoNothing in the holder declaration +FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p) +{ +} + + +//----------------------------------------------------------------------------- +// Holder/Wrapper are the simplest way to define holders - they synthesizes a base class out of +// function pointers +//----------------------------------------------------------------------------- + +template +class FunctionBase : protected HolderBase +{ + protected: + + FORCEINLINE FunctionBase(TYPE value) + : HolderBase(value) + { + } + + FORCEINLINE void DoAcquire() + { + ACQUIREF(this->m_value); + } + + void DoRelease() + { + RELEASEF(this->m_value); + } +}; // class Function<> + +template + < + typename TYPE, + void (*ACQUIREF)(TYPE), + void (*RELEASEF)(TYPE), + UINT_PTR DEFAULTVALUE = 0, + BOOL IS_NULL(TYPE, TYPE) = CompareDefault, + // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor + // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and + // operates on static or global value instead. + bool DEFAULT_CTOR_ACQUIRE = true + > +class Holder : public BaseHolder, + DEFAULTVALUE, IS_NULL> +{ + typedef BaseHolder, + DEFAULTVALUE, IS_NULL> BaseT; + + public: + FORCEINLINE Holder() + : BaseT(TYPE(DEFAULTVALUE), DEFAULT_CTOR_ACQUIRE) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Holder(TYPE value) + : BaseT(value) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Holder(TYPE value, BOOL takeOwnership) + : BaseT(value, takeOwnership) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Holder& operator=(TYPE p) + { + STATIC_CONTRACT_WRAPPER; + BaseT::operator=(p); + return *this; + } + + HIDE_GENERATED_METHODS(Holder) +}; + +//--------------------------------------------------------------------------------------- +// +template + < + typename TYPE, + void (*ACQUIREF)(TYPE), + void (*RELEASEF)(TYPE), + UINT_PTR DEFAULTVALUE = 0, + BOOL IS_NULL(TYPE, TYPE) = CompareDefault, + // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor + // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and + // operates on static or global value instead. + bool DEFAULT_CTOR_ACQUIRE = true + > +class Wrapper : public BaseWrapper, + DEFAULTVALUE, IS_NULL> +{ + typedef BaseWrapper, + DEFAULTVALUE, IS_NULL> BaseT; + + public: + FORCEINLINE Wrapper() + : BaseT(TYPE(DEFAULTVALUE), DEFAULT_CTOR_ACQUIRE) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Wrapper(TYPE value) + : BaseT(value) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Wrapper(TYPE value, BOOL takeOwnership) + : BaseT(value, takeOwnership) + { + STATIC_CONTRACT_WRAPPER; + } + + FORCEINLINE Wrapper& operator=(TYPE const & value) + { + STATIC_CONTRACT_WRAPPER; + BaseT::operator=(value); + return *this; + } + + HIDE_GENERATED_METHODS(Wrapper) +}; // Wrapper<> + +//--------------------------------------------------------------------------------------- +// - Cannot use the standard INDEBUG macro: holder.h is used in places where INDEBUG is defined in the nonstandard way +#if defined(_DEBUG) +#define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) x +#else +#define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) +#endif + +//--------------------------------------------------------------------------------------- +// +// New template wrapper type macros. These save some effort when specializing +// existing holder templates. (We would rather use a construct like: +// +// template +// typedef Holder<...> NewHolder; +// +// But this construct doesn't exist in C++. These macros ease some of the cruft necessary +// to get similar functionality out of class templates. +//----------------------------------------------------------------------------- + +// Dev10 VC++ has some of the new C++0x language extensions. Of particular interest here: +// rvalue references, which enables differentiation between named (lvalue) and +// temporary (rvalue) object references, enabling move semantics and perfect forwarding. +// See http://msdn.microsoft.com/en-us/library/dd293668.aspx for more information. + +// Enable copy construction and assignment from temporary objects. This permits Wrapper objects +// to be returned from methods, and for move assignment. +#define NEW_WRAPPER_TEMPLATE_RVALREF_METHODS(_NAME) \ + public: \ + FORCEINLINE _NAME(_NAME && other) \ + : BaseT(NULL, FALSE) \ + { \ + STATIC_CONTRACT_WRAPPER; \ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ + *this = std::move(other); \ + } \ + FORCEINLINE _NAME& operator=(_NAME && other) \ + { \ + std::swap(BaseT::m_value, other.BaseT::m_value); \ + std::swap(BaseT::m_acquired, other.BaseT::m_acquired); \ + return *this; \ + } + +#define NEW_WRAPPER_TEMPLATE1(_NAME, _RELEASEF) \ + template \ + class _NAME : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> \ + { \ + typedef Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> BaseT; \ + public: \ + FORCEINLINE _NAME() : BaseT(NULL, FALSE) \ + { \ + STATIC_CONTRACT_WRAPPER; \ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ + } \ + FORCEINLINE _NAME(_TYPE* value) : BaseT(value) \ + { \ + STATIC_CONTRACT_WRAPPER; \ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ + } \ + FORCEINLINE _NAME(_TYPE* value, BOOL takeOwnership) : BaseT(value, takeOwnership) \ + { \ + STATIC_CONTRACT_WRAPPER; \ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) \ + } \ + FORCEINLINE ~_NAME() \ + { \ + } \ + FORCEINLINE _NAME& operator=(_TYPE * value) \ + { \ + STATIC_CONTRACT_WRAPPER; \ + BaseT::operator=(value); \ + return *this; \ + } \ + /* Since operator& is overloaded we need a way to get a type safe this pointer. */ \ + FORCEINLINE _NAME* GetAddr() \ + { \ + STATIC_CONTRACT_LEAF; \ + return this; \ + } \ + NEW_WRAPPER_TEMPLATE_RVALREF_METHODS(_NAME) \ + HIDE_GENERATED_METHODS(_NAME) \ + private: \ + /* m_ppValue: Do not use from source code: Only for convenient use from debugger */ \ + /* watch windows - saves five mouseclicks when inspecting holders. */ \ + INDEBUG_AND_WINDOWS_FOR_HOLDERS(_TYPE ** m_pvalue;) \ + }; + +//----------------------------------------------------------------------------- +// NOTE: THIS IS UNSAFE TO USE IN THE VM for interop COM objects!! +// WE DO NOT CORRECTLY CHANGE TO PREEMPTIVE MODE BEFORE CALLING RELEASE!! +// USE SafeComHolder +// +// ReleaseHolder : COM Interface holder for use outside the VM (or on well known instances +// which do not need preemptive Relesae) +// +// Usage example: +// +// { +// ReleaseHolder foo; +// hr = FunctionToGetRefOfFoo(&foo); +// // Note ComHolder doesn't call AddRef - it assumes you already have a ref (if non-0). +// } // foo->Release() on out of scope (WITHOUT RESPECT FOR GC MODE!!) +// +//----------------------------------------------------------------------------- + +template +FORCEINLINE void DoTheRelease(TYPE *value) +{ + if (value) + { + value->Release(); + } +} + +NEW_WRAPPER_TEMPLATE1(DoNothingHolder, DoNothing<_TYPE*>); + +NEW_WRAPPER_TEMPLATE1(ReleaseHolder, DoTheRelease<_TYPE>); + +NEW_WRAPPER_TEMPLATE1(NonVMComHolder, DoTheRelease<_TYPE>); + + +//----------------------------------------------------------------------------- +// StubHolder : holder for stubs +// +// Usage example: +// +// { +// StubHolder foo; +// foo = new Stub(); +// foo->AddRef(); +// // Note StubHolder doesn't call AddRef for you. +// } // foo->DecRef() on out of scope +// +//----------------------------------------------------------------------------- +template +FORCEINLINE void StubRelease(TYPE* value) +{ + if (value) + value->DecRef(); +} + +NEW_WRAPPER_TEMPLATE1(StubHolder, StubRelease<_TYPE>); + +//----------------------------------------------------------------------------- +// CoTaskMemHolder : CoTaskMemAlloc allocated memory holder +// +// { +// CoTaskMemHolder foo = (Foo*) CoTaskMemAlloc(sizeof(Foo)); +// } // delete foo on out of scope +//----------------------------------------------------------------------------- + +template +FORCEINLINE void DeleteCoTaskMem(TYPE *value) +{ + if (value) + CoTaskMemFree(value); +} + +NEW_WRAPPER_TEMPLATE1(CoTaskMemHolder, DeleteCoTaskMem<_TYPE>); + +//----------------------------------------------------------------------------- +// NewHolder : New'ed memory holder +// +// { +// NewHolder foo = new Foo (); +// } // delete foo on out of scope +//----------------------------------------------------------------------------- + +template +FORCEINLINE void Delete(TYPE *value) +{ + STATIC_CONTRACT_LEAF; + + static_assert(!std::is_same::type, WCHAR>::value, + "Must use NewArrayHolder (not NewHolder) for strings."); + static_assert(!std::is_same::type, CHAR>::value, + "Must use NewArrayHolder (not NewHolder) for strings."); + + delete value; +} + +NEW_WRAPPER_TEMPLATE1(NewHolder, Delete<_TYPE>); + + //----------------------------------------------------------------------------- +// NewExecutableHolder : New'ed memory holder for executable memory. +// +// { +// NewExecutableHolder foo = (Foo*) new (executable) Byte[num]; +// } // delete foo on out of scope +//----------------------------------------------------------------------------- +// IJW +template void DeleteExecutable(T *p); + +NEW_WRAPPER_TEMPLATE1(NewExecutableHolder, DeleteExecutable<_TYPE>); + +//----------------------------------------------------------------------------- +// NewArrayHolder : New []'ed pointer holder +// { +// NewArrayHolder foo = new Foo [30]; +// } // delete [] foo on out of scope +//----------------------------------------------------------------------------- + +template +FORCEINLINE void DeleteArray(TYPE *value) +{ + STATIC_CONTRACT_WRAPPER; + delete [] value; + value = NULL; +} + +NEW_WRAPPER_TEMPLATE1(NewArrayHolder, DeleteArray<_TYPE>); +typedef NewArrayHolder AStringHolder; +typedef NewArrayHolder WStringHolder; + +//----------------------------------------------------------------------------- +// A special array holder that expects its contents are interface pointers, +// and will call Release() on them. +// +// NOTE: You may ONLY use this if you've determined that it is SAFE to call +// Release() on the contained interface pointers (e.g., as opposed to SafeRelease) +// +template +class NewInterfaceArrayHolder : public NewArrayHolder +{ +public: + NewInterfaceArrayHolder() : + NewArrayHolder(), + m_cElements(0) + { + STATIC_CONTRACT_WRAPPER; + } + + NewInterfaceArrayHolder& operator=(INTERFACE ** value) + { + STATIC_CONTRACT_WRAPPER; + NewArrayHolder::operator=(value); + return *this; + } + + void SetElementCount(ULONG32 cElements) + { + STATIC_CONTRACT_LEAF; + m_cElements = cElements; + } + + ~NewInterfaceArrayHolder() + { + STATIC_CONTRACT_LEAF; + for (ULONG32 i=0; i < m_cElements; i++) + { + if (this->m_value[i] != NULL) + this->m_value[i]->Release(); + } + } + +protected: + ULONG32 m_cElements; +}; + + +//----------------------------------------------------------------------------- +// ResetPointerHolder : pointer which needs to be set to NULL +// { +// ResetPointerHolder holder = &pFoo; +// } // "*pFoo=NULL" on out of scope +//----------------------------------------------------------------------------- +#ifdef __GNUC__ +// With -fvisibility-inlines-hidden, the Invoke methods below +// get hidden, which causes warnings when visible classes expose them. +#define VISIBLE __attribute__ ((visibility("default"))) +#else +#define VISIBLE +#endif // __GNUC__ + +namespace detail +{ + template + struct ZeroMem + { + static VISIBLE void Invoke(T * pVal) + { + ZeroMemory(pVal, sizeof(T)); + } + }; + + template + struct ZeroMem + { + static VISIBLE void Invoke(T ** pVal) + { + *pVal = NULL; + } + }; + +} +#undef VISIBLE + +NEW_WRAPPER_TEMPLATE1(ResetPointerHolder, detail::ZeroMem<_TYPE>::Invoke); +NEW_WRAPPER_TEMPLATE1(FieldNuller, detail::ZeroMem<_TYPE>::Invoke); + +//----------------------------------------------------------------------------- +// Wrap win32 functions using HANDLE +//----------------------------------------------------------------------------- + +FORCEINLINE void VoidCloseHandle(HANDLE h) { if (h != NULL) CloseHandle(h); } +// (UINT_PTR) -1 is INVALID_HANDLE_VALUE +FORCEINLINE void VoidCloseFileHandle(HANDLE h) { if (h != ((HANDLE)((LONG_PTR) -1))) CloseHandle(h); } +FORCEINLINE void VoidFindClose(HANDLE h) { FindClose(h); } +FORCEINLINE void VoidUnmapViewOfFile(void *ptr) { UnmapViewOfFile(ptr); } + +template +FORCEINLINE void TypeUnmapViewOfFile(TYPE *ptr) { UnmapViewOfFile(ptr); } + +// (UINT_PTR) -1 is INVALID_HANDLE_VALUE +//@TODO: Dangerous default value. Some Win32 functions return INVALID_HANDLE_VALUE, some return NULL (such as CreatEvent). +typedef Wrapper, VoidCloseHandle, (UINT_PTR) -1> HandleHolder; +typedef Wrapper, VoidCloseFileHandle, (UINT_PTR) -1> FileHandleHolder; +typedef Wrapper, VoidFindClose, (UINT_PTR) -1> FindHandleHolder; + +typedef Wrapper MapViewHolder; + +#ifdef WszDeleteFile +// Deletes a file with the specified path. Do not use if you care about failures +// deleting the file, as failures are ignored by VoidDeleteFile. +FORCEINLINE void VoidDeleteFile(LPCWSTR wszFilePath) { WszDeleteFile(wszFilePath); } +typedef Wrapper, VoidDeleteFile, NULL> DeleteFileHolder; +#endif // WszDeleteFile + + +//----------------------------------------------------------------------------- +// Misc holders +//----------------------------------------------------------------------------- + +// A holder for HMODULE. +FORCEINLINE void HolderFreeLibrary(HMODULE h) { FreeLibrary(h); } + +typedef Wrapper, HolderFreeLibrary, NULL> HModuleHolder; + +template FORCEINLINE +void DoLocalFree(T* pMem) { (LocalFree)((HLOCAL)pMem); } + +NEW_WRAPPER_TEMPLATE1(LocalAllocHolder, DoLocalFree<_TYPE>); + +inline void BoolSet( _Out_ bool * val ) { *val = true; } +inline void BoolUnset( _Out_ bool * val ) { *val = false; } + +typedef Wrapper< bool *, BoolSet, BoolUnset > BoolFlagStateHolder; + +// +// We need the following methods to have volatile arguments, so that they can accept +// raw pointers in addition to the results of the & operator on Volatile. +// + +FORCEINLINE void CounterIncrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedIncrement(p);}; +FORCEINLINE void CounterDecrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedDecrement(p);}; + +typedef Wrapper> CounterHolder; + + +#ifndef FEATURE_PAL +FORCEINLINE void RegKeyRelease(HKEY k) {RegCloseKey(k);}; +typedef Wrapper RegKeyHolder; +#endif // !FEATURE_PAL + +class ErrorModeHolder +{ + UINT m_oldMode; +public: + ErrorModeHolder(UINT newMode){m_oldMode=SetErrorMode(newMode);}; + ~ErrorModeHolder(){SetErrorMode(m_oldMode);}; + UINT OldMode() {return m_oldMode;}; +}; + +#ifndef FEATURE_PAL +//----------------------------------------------------------------------------- +// HKEYHolder : HKEY holder, Calls RegCloseKey on scope exit. +// +// { +// HKEYHolder hFoo = NULL; +// WszRegOpenKeyEx(HKEY_CLASSES_ROOT, L"Interface",0, KEY_READ, hFoo); +// +// } // close key on out of scope via RegCloseKey. +//----------------------------------------------------------------------------- + +class HKEYHolder +{ +public: + HKEYHolder() + { + STATIC_CONTRACT_LEAF; + m_value = 0; + } + + ~HKEYHolder() + { + STATIC_CONTRACT_WRAPPER; + if (m_value != NULL) + ::RegCloseKey(m_value); + } + + FORCEINLINE void operator=(HKEY p) + { + STATIC_CONTRACT_LEAF; + if (p != 0) + m_value = p; + } + + FORCEINLINE operator HKEY() + { + STATIC_CONTRACT_LEAF; + return m_value; + } + + FORCEINLINE operator HKEY*() + { + STATIC_CONTRACT_LEAF; + return &m_value; + } + + FORCEINLINE HKEY* operator&() + { + STATIC_CONTRACT_LEAF; + return &m_value; + } + +private: + HKEY m_value; +}; +#endif // !FEATURE_PAL + +//---------------------------------------------------------------------------- +// +// External data access does not want certain holder implementations +// to be active as locks should not be taken and so on. Provide +// a no-op in that case. +// +//---------------------------------------------------------------------------- + +#ifndef DACCESS_COMPILE + +#define DacHolder Holder + +#else + +template , BOOL VALIDATE_BACKOUT_STACK = TRUE> +class DacHolder +{ + protected: + TYPE m_value; + + private: + BOOL m_acquired; // Have we acquired the resource? + + public: + FORCEINLINE DacHolder() + : m_value(TYPE(DEFAULTVALUE)), + m_acquired(FALSE) + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + + // construct a new instance of DacHolder + // Arguments: + // input: value - the resource held + // take - indicates whether the lock should be taken--the default is true. See Notes: + // Note: In DAC builds, the Acquire function does not actually take the lock, instead + // it determines whether the lock is held (by the LS). If it is, the locked data + // is assumed to be inconsistent and the Acquire function will throw. + FORCEINLINE DacHolder(TYPE value, BOOL take = TRUE) + : m_value(value), + m_acquired(FALSE) + { + STATIC_CONTRACT_SUPPORTS_DAC; + if (take) + Acquire(); + + } + FORCEINLINE ~DacHolder() + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + // Sets the value to 'value'. Doesn't call Acquire/Release if fTake is FALSE. + FORCEINLINE void Assign(TYPE value, BOOL fTake = TRUE) + { + m_value = value; + } + FORCEINLINE void Acquire() + { + STATIC_CONTRACT_SUPPORTS_DAC; + + if (!IsNull()) + { + m_acquired = TRUE; + // because ACQUIRE is a template argument, if the line m_acquired = TRUE is placed after the call + // where it logically belongs, the compiler flags it as "unreachable code." + ACQUIRE(this->m_value); + } + } + FORCEINLINE void Release() + { + // Insert any global or thread bookeeping here + + if (m_acquired) + { + m_acquired = FALSE; + } + } + FORCEINLINE void Clear() + { + m_value = TYPE(DEFAULTVALUE); + m_acquired = FALSE; + } + FORCEINLINE void SuppressRelease() + { + m_acquired = FALSE; + } + FORCEINLINE TYPE GetValue() + { + return m_value; + } + FORCEINLINE BOOL IsNull() const + { + return IS_NULL(m_value, TYPE(DEFAULTVALUE)); + } + + private: + FORCEINLINE DacHolder& operator=(const Holder &holder) + { + } + + FORCEINLINE DacHolder(const Holder &holder) + { + } +}; + +#endif // #ifndef DACCESS_COMPILE + +// Holder-specific clr::SafeAddRef and clr::SafeRelease helper functions. +namespace clr +{ + // Copied from utilcode.h. We can't include the header directly because there + // is circular reference. + // Forward declare the overload which is used by 'SafeAddRef' below. + template + static inline + typename std::enable_if< std::is_pointer::value, ItfT >::type + SafeAddRef(ItfT pItf); + + template < typename ItfT > __checkReturn + ItfT * + SafeAddRef(ReleaseHolder & pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + //@TODO: Would be good to add runtime validation that the return value is used. + return SafeAddRef(pItf.GetValue()); + } + + namespace detail + { + template + char IsHolderHelper(HolderBase*); + int IsHolderHelper(...); + + template + struct IsHolder : public std::conditional< + sizeof(IsHolderHelper(reinterpret_cast(NULL))) == sizeof(char), + std::true_type, + std::false_type>::type + {}; + } + + template < typename T > + typename std::enable_if::value, ULONG>::type + SafeRelease(T& arg) + { + STATIC_CONTRACT_LIMITED_METHOD; + return arg.Release(); + } +} + +#endif // __HOLDER_H_ diff --git a/lib/coreclr/src/inc/holderinst.h b/lib/coreclr/src/inc/holderinst.h new file mode 100644 index 0000000000..ee59da0842 --- /dev/null +++ b/lib/coreclr/src/inc/holderinst.h @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef __HOLDERINST_H_ +#define __HOLDERINST_H_ + +// This file contains holder instantiations which we can't put in holder.h because +// the instantiations require _ASSERTE to be defined, which is not always the case +// for placed that include holder.h. + +FORCEINLINE void SafeArrayRelease(SAFEARRAY* p) +{ + SafeArrayDestroy(p); +} + + +class SafeArrayHolder : public Wrapper +{ +public: + SafeArrayHolder(SAFEARRAY* p = NULL) + : Wrapper(p) + { + } + + FORCEINLINE void operator=(SAFEARRAY* p) + { + Wrapper::operator=(p); + } +}; + +#endif // __HOLDERINST_H_ diff --git a/lib/coreclr/src/inc/iallocator.h b/lib/coreclr/src/inc/iallocator.h new file mode 100644 index 0000000000..b4c1b71120 --- /dev/null +++ b/lib/coreclr/src/inc/iallocator.h @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// We would like to allow "util" collection classes to be usable both +// from the VM and from the JIT. The latter case presents a +// difficulty, because in the (x86, soon to be cross-platform) JIT +// compiler, we require allocation to be done using a "no-release" +// (aka, arena-style) allocator that is provided as methods of the +// JIT's Compiler type. + +// To allow utilcode collection classes to deal with this, they may be +// written to do allocation and freeing via an instance of the +// "IAllocator" class defined in this file. +// +#ifndef _IALLOCATOR_DEFINED_ +#define _IALLOCATOR_DEFINED_ + +#include "contract.h" +#include "safemath.h" + +class IAllocator +{ + public: + virtual void* Alloc(size_t sz) = 0; + + // Allocate space for an array of "elems" elements, each of size "elemSize". + virtual void* ArrayAlloc(size_t elems, size_t elemSize) = 0; + + virtual void Free(void* p) = 0; +}; + +// This class wraps an allocator that does not allow zero-length allocations, +// producing one that does (every zero-length allocation produces a pointer to the same +// statically-allocated memory, and freeing that pointer is a no-op). +class AllowZeroAllocator: public IAllocator +{ + int m_zeroLenAllocTarg; + IAllocator* m_alloc; + +public: + AllowZeroAllocator(IAllocator* alloc) : m_alloc(alloc) {} + + void* Alloc(size_t sz) + { + if (sz == 0) + { + return (void*)(&m_zeroLenAllocTarg); + } + else + { + return m_alloc->Alloc(sz); + } + } + + void* ArrayAlloc(size_t elemSize, size_t numElems) + { + if (elemSize == 0 || numElems == 0) + { + return (void*)(&m_zeroLenAllocTarg); + } + else + { + return m_alloc->ArrayAlloc(elemSize, numElems); + } + } + + virtual void Free(void * p) + { + if (p != (void*)(&m_zeroLenAllocTarg)) + { + m_alloc->Free(p); + } + } +}; + +#endif // _IALLOCATOR_DEFINED_ diff --git a/lib/coreclr/src/inc/iceefilegen.h b/lib/coreclr/src/inc/iceefilegen.h new file mode 100644 index 0000000000..65289f4f93 --- /dev/null +++ b/lib/coreclr/src/inc/iceefilegen.h @@ -0,0 +1,237 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** ICeeFileGen.h - code generator interface. ** + ** ** + ** This interface provides functionality to create a CLR PE executable. ** + ** This will typically be used by compilers to generate their compiled ** + ** output executable. ** + ** ** + *****************************************************************************/ + +/* + This is how this is typically used: + + // Step #1 ... Get CLR hosting API: + #include + #include + + ICLRMetaHost * pMetaHost; + CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, &pMetaHost); // defined in mscoree.h + + ICLRRuntimeInfo * pCLRRuntimeInfo; + pMetaHost->GetRuntime(wszClrVersion, IID_ICLRRuntimeInfo, &pCLRRuntimeInfo); + + // Step #2 ... use mscorpe APIs to create a file generator + CreateICeeFileGen(...); // Get a ICeeFileGen + + CreateCeeFile(...); // Get a HCEEFILE (called for every output file needed) + SetOutputFileName(...); // Set the name for the output file + pEmit = IMetaDataEmit object; // Get a metadata emitter + GetSectionBlock(...);, AddSectionReloc(...); ... // Get blocks, write non-metadata information, and add necessary relocation + EmitMetaDataEx(pEmit); // Write out the metadata + GenerateCeeFile(...); // Write out the file. Implicitly calls LinkCeeFile and FixupCeeFile + + DestroyICeeFileGen(...); // Release the ICeeFileGen object +*/ + + +#ifndef _ICEEFILEGEN_H_ +#define _ICEEFILEGEN_H_ + +#include +#include "cor.h" + +class ICeeFileGen; + +typedef void *HCEEFILE; + +EXTERN_C HRESULT __stdcall CreateICeeFileGen(ICeeFileGen** pCeeFileGen); +EXTERN_C HRESULT __stdcall DestroyICeeFileGen(ICeeFileGen ** ppCeeFileGen); + +typedef HRESULT (__stdcall * PFN_CreateICeeFileGen)(ICeeFileGen ** ceeFileGen); // call this to instantiate an ICeeFileGen interface +typedef HRESULT (__stdcall * PFN_DestroyICeeFileGen)(ICeeFileGen ** ceeFileGen); // call this to delete an ICeeFileGen + +#define ICEE_CREATE_FILE_PE32 0x00000001 // Create a PE (32-bit) +#define ICEE_CREATE_FILE_PE64 0x00000002 // Create a PE+ (64-bit) +#define ICEE_CREATE_FILE_CORMAIN_STUB 0x00000004 // add a mscoree!_Cor___Main call stub +#define ICEE_CREATE_FILE_STRIP_RELOCS 0x00000008 // strip the .reloc section +#define ICEE_CREATE_FILE_EMIT_FIXUPS 0x00000010 // emit fixups for use by Vulcan + +#define ICEE_CREATE_MACHINE_MASK 0x0000FF00 // space for up to 256 machine targets (note: most users just do a bit check, not an equality compare after applying the mask) +#define ICEE_CREATE_MACHINE_ILLEGAL 0x00000000 // An illegal machine name +#define ICEE_CREATE_MACHINE_I386 0x00000100 // Create a IMAGE_FILE_MACHINE_I386 +#define ICEE_CREATE_MACHINE_IA64 0x00000200 // Create a IMAGE_FILE_MACHINE_IA64 +#define ICEE_CREATE_MACHINE_AMD64 0x00000400 // Create a IMAGE_FILE_MACHINE_AMD64 +#define ICEE_CREATE_MACHINE_ARM 0x00000800 // Create a IMAGE_FILE_MACHINE_ARMNT +#define ICEE_CREATE_MACHINE_ARM64 0x00001000 // Create a IMAGE_FILE_MACHINE_ARM64 + + // Pass this to CreateCeeFileEx to create a pure IL Exe or DLL +#define ICEE_CREATE_FILE_PURE_IL ICEE_CREATE_FILE_PE32 | \ + ICEE_CREATE_FILE_CORMAIN_STUB | \ + ICEE_CREATE_MACHINE_I386 + +class ICeeFileGen { + public: + virtual ~ICeeFileGen() = default; + + virtual HRESULT CreateCeeFile(HCEEFILE *ceeFile); // call this to instantiate a file handle + + // @FUTURE: remove this function. We no longer support mdScope. + virtual HRESULT EmitMetaData (HCEEFILE ceeFile, IMetaDataEmit *emitter, mdScope scope); + virtual HRESULT EmitLibraryName (HCEEFILE ceeFile, IMetaDataEmit *emitter, mdScope scope); + virtual HRESULT EmitMethod (); // @FUTURE: remove + virtual HRESULT GetMethodRVA (HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA); + virtual HRESULT EmitSignature (); // @FUTURE: remove + + virtual HRESULT EmitString (HCEEFILE ceeFile,_In_ LPWSTR strValue, ULONG *strRef); + virtual HRESULT GenerateCeeFile (HCEEFILE ceeFile); + + virtual HRESULT SetOutputFileName (HCEEFILE ceeFile, _In_ LPWSTR outputFileName); + _Return_type_success_(return == S_OK) + virtual HRESULT GetOutputFileName (HCEEFILE ceeFile, _Out_ LPWSTR *outputFileName); + + virtual HRESULT SetResourceFileName (HCEEFILE ceeFile, _In_ LPWSTR resourceFileName); + + _Return_type_success_(return == S_OK) + virtual HRESULT GetResourceFileName (HCEEFILE ceeFile, _Out_ LPWSTR *resourceFileName); + + virtual HRESULT SetImageBase(HCEEFILE ceeFile, size_t imageBase); + + virtual HRESULT SetSubsystem(HCEEFILE ceeFile, DWORD subsystem, DWORD major, DWORD minor); + + virtual HRESULT SetEntryClassToken (); //@FUTURE: remove + virtual HRESULT GetEntryClassToken (); //@FUTURE: remove + + virtual HRESULT SetEntryPointDescr (); //@FUTURE: remove + virtual HRESULT GetEntryPointDescr (); //@FUTURE: remove + + virtual HRESULT SetEntryPointFlags (); //@FUTURE: remove + virtual HRESULT GetEntryPointFlags (); //@FUTURE: remove + + virtual HRESULT SetDllSwitch (HCEEFILE ceeFile, BOOL dllSwitch); + virtual HRESULT GetDllSwitch (HCEEFILE ceeFile, BOOL *dllSwitch); + + virtual HRESULT SetLibraryName (HCEEFILE ceeFile, _In_ LPWSTR LibraryName); + _Return_type_success_( return == S_OK ) + virtual HRESULT GetLibraryName (HCEEFILE ceeFile, _Out_ LPWSTR *LibraryName); + + virtual HRESULT SetLibraryGuid (HCEEFILE ceeFile, _In_ LPWSTR LibraryGuid); + + virtual HRESULT DestroyCeeFile(HCEEFILE *ceeFile); // call this to delete a file handle + + virtual HRESULT GetSectionCreate (HCEEFILE ceeFile, const char *name, DWORD flags, HCEESECTION *section); + virtual HRESULT GetIlSection (HCEEFILE ceeFile, HCEESECTION *section); + virtual HRESULT GetRdataSection (HCEEFILE ceeFile, HCEESECTION *section); + + virtual HRESULT GetSectionDataLen (HCEESECTION section, ULONG *dataLen); + virtual HRESULT GetSectionBlock (HCEESECTION section, ULONG len, ULONG align=1, void **ppBytes=0); + virtual HRESULT TruncateSection (HCEESECTION section, ULONG len); + virtual HRESULT AddSectionReloc (HCEESECTION section, ULONG offset, HCEESECTION relativeTo, CeeSectionRelocType relocType); + + // deprecated: use SetDirectoryEntry instead + virtual HRESULT SetSectionDirectoryEntry (HCEESECTION section, ULONG num); + + virtual HRESULT CreateSig (); //@FUTURE: Remove + virtual HRESULT AddSigArg (); //@FUTURE: Remove + virtual HRESULT SetSigReturnType (); //@FUTURE: Remove + virtual HRESULT SetSigCallingConvention (); //@FUTURE: Remove + virtual HRESULT DeleteSig (); //@FUTURE: Remove + + virtual HRESULT SetEntryPoint (HCEEFILE ceeFile, mdMethodDef method); + virtual HRESULT GetEntryPoint (HCEEFILE ceeFile, mdMethodDef *method); + + virtual HRESULT SetComImageFlags (HCEEFILE ceeFile, DWORD mask); + virtual HRESULT GetComImageFlags (HCEEFILE ceeFile, DWORD *mask); + + // get IMapToken interface for tracking mapped tokens + virtual HRESULT GetIMapTokenIface(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); + virtual HRESULT SetDirectoryEntry (HCEEFILE ceeFile, HCEESECTION section, ULONG num, ULONG size, ULONG offset = 0); + + // Write out the metadata in "emitter" to the metadata section in "ceeFile" + // Use EmitMetaDataAt() for more control + virtual HRESULT EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); + + virtual HRESULT EmitLibraryNameEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); + virtual HRESULT GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); + + virtual HRESULT EmitMacroDefinitions(HCEEFILE ceeFile, void *pData, DWORD cData); + virtual HRESULT CreateCeeFileFromICeeGen( + ICeeGen *pFromICeeGen, HCEEFILE *ceeFile, DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); // call this to instantiate a file handle + + virtual HRESULT SetManifestEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); + + virtual HRESULT SetEnCRVABase(HCEEFILE ceeFile, ULONG dataBase, ULONG rdataBase); + virtual HRESULT GenerateCeeMemoryImage (HCEEFILE ceeFile, void **ppImage); + + virtual HRESULT ComputeSectionOffset(HCEESECTION section, _In_ char *ptr, + unsigned *offset); + + virtual HRESULT ComputeOffset(HCEEFILE file, _In_ char *ptr, + HCEESECTION *pSection, unsigned *offset); + + virtual HRESULT GetCorHeader(HCEEFILE ceeFile, + IMAGE_COR20_HEADER **header); + + // Layout the sections and assign their starting addresses + virtual HRESULT LinkCeeFile (HCEEFILE ceeFile); + + // Apply relocations to any pointer data. Also generate PE base relocs + virtual HRESULT FixupCeeFile (HCEEFILE ceeFile); + + // Base RVA assinged to the section. To be called only after LinkCeeFile() + virtual HRESULT GetSectionRVA (HCEESECTION section, ULONG *rva); + + _Return_type_success_(return == S_OK) + virtual HRESULT ComputeSectionPointer(HCEESECTION section, ULONG offset, + _Out_ char **ptr); + + virtual HRESULT SetObjSwitch (HCEEFILE ceeFile, BOOL objSwitch); + virtual HRESULT GetObjSwitch (HCEEFILE ceeFile, BOOL *objSwitch); + virtual HRESULT SetVTableEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); + // See the end of interface for another overload of AetVTableEntry + + virtual HRESULT SetStrongNameEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); + + // Emit the metadata from "emitter". + // If 'section != 0, it will put the data in 'buffer'. This + // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' + // (should use GetSaveSize to insure that buffer is big enough + virtual HRESULT EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, + HCEESECTION section, DWORD offset, + BYTE* buffer, unsigned buffLen); + + virtual HRESULT GetFileTimeStamp (HCEEFILE ceeFile, DWORD *pTimeStamp); + + // Add a notification handler. If it implements an interface that + // the ICeeFileGen understands, S_OK is returned. Otherwise, + // E_NOINTERFACE. + virtual HRESULT AddNotificationHandler(HCEEFILE ceeFile, + IUnknown *pHandler); + + virtual HRESULT SetFileAlignment(HCEEFILE ceeFile, ULONG fileAlignment); + + virtual HRESULT ClearComImageFlags (HCEEFILE ceeFile, DWORD mask); + + // call this to instantiate a PE+ (64-bit PE file) + virtual HRESULT CreateCeeFileEx(HCEEFILE *ceeFile, ULONG createFlags); + virtual HRESULT SetImageBase64(HCEEFILE ceeFile, ULONGLONG imageBase); + + virtual HRESULT GetHeaderInfo (HCEEFILE ceeFile, PIMAGE_NT_HEADERS *ppNtHeaders, + PIMAGE_SECTION_HEADER *ppSections, + ULONG *pNumSections); + + // Seed file is a base file which is copied over into the output file + // Note that there are restrictions on the seed file (the sections + // cannot be relocated), and that the copy is not complete as the new + // headers overwrite the seed file headers. + virtual HRESULT CreateCeeFileEx2(HCEEFILE *ceeFile, ULONG createFlags, + LPCWSTR seedFileName = NULL); + + virtual HRESULT SetVTableEntry64(HCEEFILE ceeFile, ULONG size, void* ptr); +}; + +#endif diff --git a/lib/coreclr/src/inc/il_kywd.h b/lib/coreclr/src/inc/il_kywd.h new file mode 100644 index 0000000000..826906854b --- /dev/null +++ b/lib/coreclr/src/inc/il_kywd.h @@ -0,0 +1,304 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// +// COM+ IL keywords, symbols and values +// +// This is the master table used in ILASM (asmparse.y) +// and ILDASM (dis.cpp) +// symbols and values are defined in asmparse.y +// and not used in dis.cpp +// + +#ifndef __IL_KYWD_H_ +#define __IL_KYWD_H_ + + KYWD( "void", VOID_, NO_VALUE ) + KYWD( "bool", BOOL_, NO_VALUE ) + KYWD( "char", CHAR_, NO_VALUE ) + KYWD( "wchar", CHAR_, NO_VALUE ) + KYWD( "int", INT_, NO_VALUE ) + KYWD( "int8", INT8_, NO_VALUE ) + KYWD( "int16", INT16_, NO_VALUE ) + KYWD( "int32", INT32_, NO_VALUE ) + KYWD( "int64", INT64_, NO_VALUE ) + KYWD( "uint", UINT_, NO_VALUE ) + KYWD( "uint8", UINT8_, NO_VALUE ) + KYWD( "uint16", UINT16_, NO_VALUE ) + KYWD( "uint32", UINT32_, NO_VALUE ) + KYWD( "uint64", UINT64_, NO_VALUE ) + KYWD( "float", FLOAT_, NO_VALUE ) + KYWD( "float32", FLOAT32_, NO_VALUE ) + KYWD( "float64", FLOAT64_, NO_VALUE ) + KYWD( "refany", TYPEDREF_, NO_VALUE ) + KYWD( "typedref", TYPEDREF_, NO_VALUE ) + KYWD( "object", OBJECT_, NO_VALUE ) + KYWD( "string", STRING_, NO_VALUE ) + KYWD( "native", NATIVE_, NO_VALUE ) + KYWD( "unsigned", UNSIGNED_, NO_VALUE ) + KYWD( "value", VALUE_, NO_VALUE ) + KYWD( "valuetype", VALUETYPE_, NO_VALUE ) + KYWD( "class", CLASS_, NO_VALUE ) + KYWD( "vararg", VARARG_, NO_VALUE ) + KYWD( "default", DEFAULT_, NO_VALUE ) + KYWD( "stdcall", STDCALL_, NO_VALUE ) + KYWD( "thiscall", THISCALL_, NO_VALUE ) + KYWD( "fastcall", FASTCALL_, NO_VALUE ) + KYWD( "unmanaged", UNMANAGED_, NO_VALUE ) + KYWD( "beforefieldinit",BEFOREFIELDINIT_, NO_VALUE ) + KYWD( "instance", INSTANCE_, NO_VALUE ) + KYWD( "filter", FILTER_, NO_VALUE ) + KYWD( "catch", CATCH_, NO_VALUE ) + KYWD( "static", STATIC_ , NO_VALUE ) + KYWD( "public", PUBLIC_, NO_VALUE ) + KYWD( "private", PRIVATE_, NO_VALUE ) + KYWD( "forwarder", FORWARDER_, NO_VALUE ) + KYWD( "synchronized", SYNCHRONIZED_, NO_VALUE ) + KYWD( "interface", INTERFACE_, NO_VALUE ) + KYWD( "extends", EXTENDS_, NO_VALUE ) + KYWD( "implements", IMPLEMENTS_, NO_VALUE ) + KYWD( "handler", HANDLER_, NO_VALUE ) + KYWD( "finally", FINALLY_, NO_VALUE ) + KYWD( "fault", FAULT_, NO_VALUE ) + KYWD( "to", TO_, NO_VALUE ) + KYWD( "abstract", ABSTRACT_, NO_VALUE ) + KYWD( "auto", AUTO_, NO_VALUE ) + KYWD( "sequential", SEQUENTIAL_, NO_VALUE ) + KYWD( "explicit", EXPLICIT_, NO_VALUE ) + KYWD( "ansi", ANSI_, NO_VALUE ) + KYWD( "unicode", UNICODE_, NO_VALUE ) + KYWD( "autochar", AUTOCHAR_, NO_VALUE ) + KYWD( "import", IMPORT_, NO_VALUE ) + KYWD( "enum", ENUM_, NO_VALUE ) + KYWD( "virtual", VIRTUAL_, NO_VALUE ) + KYWD( "strict", STRICT_, NO_VALUE ) + KYWD( "il", CIL_, NO_VALUE ) + KYWD( "cil", CIL_, NO_VALUE ) + KYWD( "optil", OPTIL_, NO_VALUE ) + KYWD( "managed", MANAGED_, NO_VALUE ) + KYWD( "preservesig", PRESERVESIG_, NO_VALUE ) + KYWD( "runtime", RUNTIME_, NO_VALUE ) + KYWD( "method", METHOD_, NO_VALUE ) + KYWD( "field", FIELD_, NO_VALUE ) + KYWD( "property", PROPERTY_, NO_VALUE ) + KYWD( "bytearray", BYTEARRAY_, NO_VALUE ) + KYWD( "final", FINAL_, NO_VALUE ) + KYWD( "sealed", SEALED_, NO_VALUE ) + KYWD( "specialname", SPECIALNAME_, NO_VALUE ) + KYWD( "family", FAMILY_, NO_VALUE ) + KYWD( "assembly", ASSEMBLY_, NO_VALUE ) + KYWD( "famandassem", FAMANDASSEM_, NO_VALUE ) + KYWD( "famorassem", FAMORASSEM_, NO_VALUE ) + KYWD( "privatescope", PRIVATESCOPE_, NO_VALUE ) + KYWD( "nested", NESTED_, NO_VALUE ) + KYWD( "hidebysig", HIDEBYSIG_, NO_VALUE ) + KYWD( "newslot", NEWSLOT_, NO_VALUE ) + KYWD( "aggressiveinlining",AGGRESSIVEINLINING_,NO_VALUE ) + KYWD( "rtspecialname", RTSPECIALNAME_, NO_VALUE ) + KYWD( "pinvokeimpl", PINVOKEIMPL_, NO_VALUE ) + KYWD( "unmanagedexp", UNMANAGEDEXP_, NO_VALUE ) + KYWD( "reqsecobj", REQSECOBJ_, NO_VALUE ) + KYWD( ".ctor", _CTOR, NO_VALUE ) + KYWD( ".cctor", _CCTOR, NO_VALUE ) + KYWD( "initonly", INITONLY_, NO_VALUE ) + KYWD( "literal", LITERAL_, NO_VALUE ) + KYWD( "notserialized", NOTSERIALIZED_, NO_VALUE ) + KYWD( "forwardref", FORWARDREF_, NO_VALUE ) + KYWD( "internalcall", INTERNALCALL_, NO_VALUE ) + KYWD( "noinlining", NOINLINING_, NO_VALUE ) + KYWD( "nooptimization", NOOPTIMIZATION_, NO_VALUE ) + KYWD( "aggressiveoptimization", AGGRESSIVEOPTIMIZATION_, NO_VALUE ) + KYWD( "nomangle", NOMANGLE_, NO_VALUE ) + KYWD( "lasterr", LASTERR_, NO_VALUE ) + KYWD( "winapi", WINAPI_, NO_VALUE ) + KYWD( "cdecl", CDECL_, NO_VALUE ) + KYWD( "as", AS_, NO_VALUE ) + KYWD( "pinned", PINNED_, NO_VALUE ) + KYWD( "modreq", MODREQ_, NO_VALUE ) + KYWD( "modopt", MODOPT_, NO_VALUE ) + KYWD( "serializable", SERIALIZABLE_, NO_VALUE ) + KYWD( "at", AT_, NO_VALUE ) + KYWD( "tls", TLS_, NO_VALUE ) + KYWD( "true", TRUE_, NO_VALUE ) + KYWD( "false", FALSE_, NO_VALUE ) + KYWD( "on", ON_, NO_VALUE ) + KYWD( "off", OFF_, NO_VALUE ) + KYWD( "bestfit", BESTFIT_, NO_VALUE ) + KYWD( "charmaperror", CHARMAPERROR_, NO_VALUE ) + + /* assembler directives */ + KYWD( ".class", _CLASS, NO_VALUE ) + KYWD( ".this", _THIS, NO_VALUE ) + KYWD( ".base", _BASE, NO_VALUE ) + KYWD( ".nester", _NESTER, NO_VALUE ) + KYWD( ".namespace", _NAMESPACE, NO_VALUE ) + KYWD( ".method", _METHOD, NO_VALUE ) + KYWD( ".field", _FIELD, NO_VALUE ) + KYWD( ".emitbyte", _EMITBYTE, NO_VALUE ) + KYWD( ".try", _TRY, NO_VALUE ) + KYWD( ".maxstack", _MAXSTACK, NO_VALUE ) + KYWD( ".locals", _LOCALS, NO_VALUE ) + KYWD( ".entrypoint", _ENTRYPOINT, NO_VALUE ) + KYWD( ".zeroinit", _ZEROINIT, NO_VALUE ) + KYWD( ".data", _DATA, NO_VALUE ) + + KYWD( ".event", _EVENT, NO_VALUE ) + KYWD( ".addon", _ADDON, NO_VALUE ) + KYWD( ".removeon", _REMOVEON, NO_VALUE ) + KYWD( ".fire", _FIRE, NO_VALUE ) + KYWD( ".other", _OTHER, NO_VALUE ) + + KYWD( ".property", _PROPERTY, NO_VALUE ) + KYWD( ".set", _SET, NO_VALUE ) + KYWD( ".get", _GET, NO_VALUE ) + + KYWD( ".permission", _PERMISSION, NO_VALUE ) + KYWD( ".permissionset", _PERMISSIONSET, NO_VALUE ) + + /* security actions */ + KYWD( "request", REQUEST_, NO_VALUE ) + KYWD( "demand", DEMAND_, NO_VALUE ) + KYWD( "assert", ASSERT_, NO_VALUE ) + KYWD( "deny", DENY_, NO_VALUE ) + KYWD( "permitonly", PERMITONLY_, NO_VALUE ) + KYWD( "linkcheck", LINKCHECK_, NO_VALUE ) + KYWD( "inheritcheck", INHERITCHECK_, NO_VALUE ) + KYWD( "reqmin", REQMIN_, NO_VALUE ) + KYWD( "reqopt", REQOPT_, NO_VALUE ) + KYWD( "reqrefuse", REQREFUSE_, NO_VALUE ) + KYWD( "prejitgrant", PREJITGRANT_, NO_VALUE ) + KYWD( "prejitdeny", PREJITDENY_, NO_VALUE ) + KYWD( "noncasdemand", NONCASDEMAND_, NO_VALUE ) + KYWD( "noncaslinkdemand",NONCASLINKDEMAND_, NO_VALUE ) + KYWD( "noncasinheritance",NONCASINHERITANCE_,NO_VALUE ) + + /* extern debug data specifier */ + KYWD( ".line", _LINE, NO_VALUE ) + KYWD( ".language", _LANGUAGE, NO_VALUE ) + KYWD( "#line", P_LINE, NO_VALUE ) + /* custom value specifier */ + KYWD( ".custom", _CUSTOM, NO_VALUE ) + /* IL method attribute */ + KYWD( "init", INIT_, NO_VALUE ) + /* Class layout directives */ + KYWD( ".size", _SIZE, NO_VALUE ) + KYWD( ".pack", _PACK, NO_VALUE ) + /* Manifest-related keywords */ + KYWD( ".file", _FILE, NO_VALUE ) + KYWD( "nometadata", NOMETADATA_, NO_VALUE ) + KYWD( ".hash", _HASH, NO_VALUE ) + KYWD( ".assembly", _ASSEMBLY, NO_VALUE ) + KYWD( "retargetable", RETARGETABLE_, NO_VALUE ) + KYWD( "windowsruntime", WINDOWSRUNTIME_, NO_VALUE ) + KYWD( "noplatform", NOPLATFORM_, NO_VALUE ) + KYWD( "legacy", LEGACY_, NO_VALUE ) + KYWD( "library", LIBRARY_, NO_VALUE ) + KYWD( "x86", X86_, NO_VALUE ) + KYWD( "amd64", AMD64_, NO_VALUE ) + KYWD( "arm", ARM_, NO_VALUE ) + KYWD( "arm64", ARM64_, NO_VALUE ) + KYWD( ".publickey", _PUBLICKEY, NO_VALUE ) + KYWD( ".publickeytoken",_PUBLICKEYTOKEN, NO_VALUE ) + KYWD( "algorithm", ALGORITHM_, NO_VALUE ) + KYWD( ".ver", _VER, NO_VALUE ) + KYWD( ".locale", _LOCALE, NO_VALUE ) + KYWD( "extern", EXTERN_, NO_VALUE ) + KYWD( ".export", _EXPORT, NO_VALUE ) + KYWD( ".manifestres", _MRESOURCE, NO_VALUE ) + KYWD( ".mresource", _MRESOURCE, NO_VALUE ) + KYWD( ".module", _MODULE, NO_VALUE ) + /* Field marshaling keywords */ + KYWD( "marshal", MARSHAL_, NO_VALUE ) + KYWD( "custom", CUSTOM_, NO_VALUE ) + KYWD( "sysstring", SYSSTRING_, NO_VALUE ) + KYWD( "fixed", FIXED_, NO_VALUE ) + KYWD( "variant", VARIANT_, NO_VALUE ) + KYWD( "currency", CURRENCY_, NO_VALUE ) + KYWD( "syschar", SYSCHAR_, NO_VALUE ) + KYWD( "decimal", DECIMAL_, NO_VALUE ) + KYWD( "date", DATE_, NO_VALUE ) + KYWD( "bstr", BSTR_, NO_VALUE ) + KYWD( "tbstr", TBSTR_, NO_VALUE ) + KYWD( "lpstr", LPSTR_, NO_VALUE ) + KYWD( "lpwstr", LPWSTR_, NO_VALUE ) + KYWD( "lptstr", LPTSTR_, NO_VALUE ) + KYWD( "objectref", OBJECTREF_, NO_VALUE ) + KYWD( "iunknown", IUNKNOWN_, NO_VALUE ) + KYWD( "idispatch", IDISPATCH_, NO_VALUE ) + KYWD( "iidparam", IIDPARAM_, NO_VALUE ) + KYWD( "struct", STRUCT_, NO_VALUE ) + KYWD( "safearray", SAFEARRAY_, NO_VALUE ) + KYWD( "byvalstr", BYVALSTR_, NO_VALUE ) + KYWD( "lpvoid", LPVOID_, NO_VALUE ) + KYWD( "any", ANY_, NO_VALUE ) + KYWD( "array", ARRAY_, NO_VALUE ) + KYWD( "lpstruct", LPSTRUCT_, NO_VALUE ) + /* VTable fixup keywords */ + KYWD( ".vtfixup", _VTFIXUP, NO_VALUE ) + KYWD( "fromunmanaged", FROMUNMANAGED_, NO_VALUE ) + KYWD( "retainappdomain",RETAINAPPDOMAIN_, NO_VALUE ) + KYWD( "callmostderived",CALLMOSTDERIVED_, NO_VALUE ) + KYWD( ".vtentry", _VTENTRY, NO_VALUE ) + /* Parameter attributes */ + KYWD( "in", IN_, NO_VALUE ) + KYWD( "out", OUT_, NO_VALUE ) + KYWD( "opt", OPT_, NO_VALUE ) + KYWD( ".param", PARAM_, NO_VALUE ) + /* Method implementations */ + KYWD( ".override", _OVERRIDE, NO_VALUE ) + KYWD( "with", WITH_, NO_VALUE ) + /* VariantType keywords */ + KYWD( "null", NULL_, NO_VALUE ) + KYWD( "error", ERROR_, NO_VALUE ) + KYWD( "hresult", HRESULT_, NO_VALUE ) + KYWD( "carray", CARRAY_, NO_VALUE ) + KYWD( "userdefined", USERDEFINED_, NO_VALUE ) + KYWD( "record", RECORD_, NO_VALUE ) + KYWD( "filetime", FILETIME_, NO_VALUE ) + KYWD( "blob", BLOB_, NO_VALUE ) + KYWD( "stream", STREAM_, NO_VALUE ) + KYWD( "storage", STORAGE_, NO_VALUE ) + KYWD( "streamed_object",STREAMED_OBJECT_, NO_VALUE ) + KYWD( "stored_object", STORED_OBJECT_, NO_VALUE ) + KYWD( "blob_object", BLOB_OBJECT_, NO_VALUE ) + KYWD( "cf", CF_, NO_VALUE ) + KYWD( "clsid", CLSID_, NO_VALUE ) + KYWD( "vector", VECTOR_, NO_VALUE ) + /* Null reference keyword for InitOpt */ + KYWD( "nullref", NULLREF_, NO_VALUE ) + KYWD( "type", TYPE_, NO_VALUE ) + KYWD( ".interfaceimpl", _INTERFACEIMPL, NO_VALUE ) + /* Header flags keywords */ + KYWD( ".subsystem", _SUBSYSTEM, NO_VALUE ) + KYWD( ".corflags", _CORFLAGS, NO_VALUE ) + KYWD( "alignment", ALIGNMENT_, NO_VALUE ) + KYWD( ".imagebase", _IMAGEBASE, NO_VALUE ) + KYWD( ".stackreserve", _STACKRESERVE, NO_VALUE ) + /* Explicit binary flag specification keywords */ + KYWD( "flags", FLAGS_, NO_VALUE ) + KYWD( "callconv", CALLCONV_, NO_VALUE ) + KYWD( "mdtoken", MDTOKEN_, NO_VALUE ) + + /* Some ILASM-specific syntactic sugar */ + KYWD( ".typedef", _TYPEDEF, NO_VALUE ) + KYWD( ".template", _TEMPLATE, NO_VALUE ) + KYWD( ".typelist", _TYPELIST, NO_VALUE ) + KYWD( ".mscorlib", _MSCORLIB, NO_VALUE ) + + /* Compilation control keywords */ + KYWD( "#define", P_DEFINE, NO_VALUE ) + KYWD( "#undef", P_UNDEF, NO_VALUE ) + KYWD( "#ifdef", P_IFDEF, NO_VALUE ) + KYWD( "#ifndef", P_IFNDEF, NO_VALUE ) + KYWD( "#else", P_ELSE, NO_VALUE ) + KYWD( "#endif", P_ENDIF, NO_VALUE ) + KYWD( "#include", P_INCLUDE, NO_VALUE ) + + + /* Deprecated keywords */ + KYWD( ".vtable", _VTABLE, NO_VALUE ) + + + KYWD( "^THE_END^", 0, NO_VALUE ) +#endif diff --git a/lib/coreclr/src/inc/ildbsymlib.h b/lib/coreclr/src/inc/ildbsymlib.h new file mode 100644 index 0000000000..6c2d4d0edf --- /dev/null +++ b/lib/coreclr/src/inc/ildbsymlib.h @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// IldbSymLib.h +// +// ILDB debug symbols functions implemented in IldbSymLib.lib +// Provides support for ILDB-format debug symbols using the same interfaces +// that diasymreader.dll exposes for PDB symbols. +// +//***************************************************************************** +#ifndef __IldbSymLib_h__ +#define __IldbSymLib_h__ + +// Get the IClassFactory for one of the ILDB symbols CLSIDs +STDAPI IldbSymbolsGetClassObject(REFCLSID rclsid, REFIID riid, void** ppvObject); + +// Create an inststance of an ILDB ISymUnmanagedReader, ISymUnmanagedWriter or ISymUnmanagedBinder +STDAPI IldbSymbolsCreateInstance(REFCLSID rclsid, REFIID riid, void** ppvIUnknown); + +#endif // __IldbSymLib_h__ diff --git a/lib/coreclr/src/inc/ilformatter.h b/lib/coreclr/src/inc/ilformatter.h new file mode 100644 index 0000000000..7593aa65bc --- /dev/null +++ b/lib/coreclr/src/inc/ilformatter.h @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/***************************************************************************/ +/* ILFormatter.h */ +/***************************************************************************/ + +#ifndef ILFormatter_h +#define ILFormatter_h + +#include "opinfo.h" +#include "outstring.h" + +struct IMetaDataImport; + +#define INVALID_IL_OFFSET 0x80000000 + +/***************************************************************************/ +class ILFormatter { +public: + ILFormatter() : start(0), targetStart(0), stackStart(0) {} + + ILFormatter(IMetaDataImport* aMeta, const BYTE* aStart, + const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh) + : targetStart(0), stackStart(0) { + init(aMeta, aStart, aLimit, maxStack, eh); + } + ~ILFormatter() { delete [] stackStart; delete [] targetStart; } + + void init(IMetaDataImport* aMeta, const BYTE* aStart, + const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh); + const BYTE* formatStatement(const BYTE* stmtIL, OutString* out); + const BYTE* formatInstr(const BYTE* instrIL, OutString* out); +private: + + void formatInstrArgs(OpInfo op, OpArgsVal arg, OutString* out, size_t curIP=INVALID_IL_OFFSET); + void formatArgs(unsigned numArgs, OutString* out); + void spillStack(OutString* out); + void setStackAsTarget(size_t ilOffset); + void setTarget(size_t ilOffset, size_t depth); + +private: + const BYTE* start; // keeps us sane + const BYTE* limit; + IMetaDataImport* meta; // used to parse tokens etc + + struct StackEntry { + OutString val; + int prec; + }; + + struct Target { + size_t ilOffset; + size_t stackDepth; + }; + + Target* targetStart; + Target* targetEnd; + Target* targetCur; + + size_t stackDepth(); + void pushAndClear(OutString* val, int prec); + OutString* pop(int prec = 0); + OutString* top(); + void popN(size_t num); + + StackEntry* stackStart; + StackEntry* stackEnd; + StackEntry* stackCur; // points at the next slot to fill + +}; + +#endif + diff --git a/lib/coreclr/src/inc/internalunknownimpl.h b/lib/coreclr/src/inc/internalunknownimpl.h new file mode 100644 index 0000000000..9b561fad64 --- /dev/null +++ b/lib/coreclr/src/inc/internalunknownimpl.h @@ -0,0 +1,494 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// +// InternalUnknownImpl.h +// +// Defines utility class ComUtil::IUnknownCommon, which provides default +// implementations for IUnknown's AddRef, Release, and QueryInterface methods. +// +// Use: a class that implements one or more interfaces should derive from +// ComUtil::IUnknownCommon with a template parameter list consisting of the +// list of implemented interfaces. +// +// Example: +// class MyInterfacesImpl : +// public IUnknownCommon +// { ... }; +// +// IUnknownCommon will provide base AddRef and Release semantics, and will +// also provide an implementation of QueryInterface that will evaluate the +// arguments against the set of supported interfaces and return the +// appropriate result. +// +// If you need to specify multiple interfaces where one is a base interface +// of another and implementing all of them would result in a compiler error, +// you can use the NoDerive wrapper to tell IUnknownCommon to not derive from +// this interface but just use it for QueryInterface calls. +// +// Example: +// interface A +// { ... }; +// interface B : public A +// { ... }; +// class MyInterfacesImpl : public IUnknownCommon > +// { ... }; +// +// If a base type also implements IUnknownCommon, then you must override +// QueryInterface with a method that delegates to your type's +// IUnknownCommon::QueryInterface and then to BaseType::QueryInterface. +// + + +// +//***************************************************************************** + +#ifndef __InternalUnknownImpl_h__ +#define __InternalUnknownImpl_h__ + +#include +#include "winwrap.h" +#include "contract.h" +#include "ex.h" +#include "volatile.h" +#include "mpl/type_list" +#include "debugmacros.h" + +#define COMUTIL_IIDOF(x) __uuidof(x) + +namespace ComUtil +{ + //--------------------------------------------------------------------------------------------- + template + struct TypeWrapper + { typedef T wrapped_type; }; + + namespace detail + { + typedef char (&_Yes)[1]; + typedef char (&_No)[2]; + + static inline _No _IsTypeWrapper(...); + + template + static _Yes _IsTypeWrapper(T *, typename T::wrapped_type * = nullptr); + } + + //--------------------------------------------------------------------------------------------- + template + struct IsTypeWrapper + { + static const bool value = std::integral_constant< + bool, + sizeof(detail::_IsTypeWrapper((T*)0)) == sizeof(detail::_Yes)>::value; + }; + + //----------------------------------------------------------------------------------------- + // Utility to remove marker type wrappers. + template ::value> + struct UnwrapOne + { typedef T type; }; + + template + struct UnwrapOne + { typedef typename T::wrapped_type type; }; + + template ::value> + struct Unwrap + { typedef T type; }; + + template + struct Unwrap + { typedef typename Unwrap< typename UnwrapOne::type >::type type; }; + + //--------------------------------------------------------------------------------------------- + // Used as a flag to indicate that an interface should not be used as a base class. + // See DeriveTypeList below. + template + struct NoDerive : public TypeWrapper + { }; + + //--------------------------------------------------------------------------------------------- + // Used to indicate that a base class contributes implemented interfaces. + template + struct ItfBase : public TypeWrapper + { }; + + namespace detail + { + using namespace mpl; + + //----------------------------------------------------------------------------------------- + // Exposes a type that derives every type in the given type list, except for those marked + // with NoDerive. + template + struct DeriveTypeList; + + // Common case. Derive from list head and recursively on list tail. + template + struct DeriveTypeList< type_list > : + public Unwrap::type, + public DeriveTypeList + {}; + + // Non-derived case. Skip this type, continue with tail. + template + struct DeriveTypeList< type_list< NoDerive< HeadT >, TailT> > : + public DeriveTypeList + {}; + + // Termination case. + template <> + struct DeriveTypeList + {}; + + //----------------------------------------------------------------------------------------- + template + struct GetFirstInterface; + + template + struct GetFirstInterface< type_list > + { typedef HeadT type; }; + + template + struct GetFirstInterface< type_list< ItfBase< HeadT >, TailT> > + { typedef typename GetFirstInterface::type type; }; + + template <> + struct GetFirstInterface< null_type > + { typedef IUnknown type; }; + + //----------------------------------------------------------------------------------------- + // Uses type lists to implement the helper. Type lists are implemented + // through templates, and can be best understood if compared to Scheme + // cdr and cons: each list type has a head type and a tail type. The + // head type is typically a concrete type, and the tail type is + // typically another list containing the remainder of the list. Type + // lists are terminated with a head type of null_type. + // + // QueryInterface is implemented using QIHelper, which uses type_lists + // and partial specialization to recursively walk the type list and + // look to see if the requested interface is supported. If not, then + // the termination case is reached and a final test against IUknown + // is made before returning a failure. + //----------------------------------------------------------------------------------------- + template + struct QIHelper; + + template + struct QIHelper< type_list< HeadT, TailT > > + { + template + static inline HRESULT QI( + REFIID riid, + void **ppvObject, + IUnknownCommonT *pThis) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_ENTRY_POINT; + + HRESULT hr = S_OK; + + typedef typename Unwrap::type ItfT; + + // If the interface type matches that of the head of the list, + // then cast to it and return success. + if (riid == COMUTIL_IIDOF(ItfT)) + { + ItfT *pItf = static_cast(pThis); + pItf->AddRef(); + *ppvObject = pItf; + } + // If not, recurse on the tail of the list. + else + hr = QIHelper::QI(riid, ppvObject, pThis); + + return hr; + } + }; + + template + struct QIHelper< type_list< ItfBase< HeadT >, TailT> > + { + template + static inline HRESULT QI( + REFIID riid, + void **ppvObject, + IUnknownCommonT *pThis) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_ENTRY_POINT; + + HRESULT hr = S_OK; + + hr = pThis->HeadT::QueryInterface(riid, ppvObject); + + if (hr == E_NOINTERFACE) + hr = QIHelper::QI(riid, ppvObject, pThis); + + return hr; + } + }; + + // This is the termination case. In this case, we check if the + // requested interface is IUnknown (which is common to all interfaces). + template <> + struct QIHelper< null_type > + { + template + static inline HRESULT QI( + REFIID riid, + void **ppvObject, + IUnknownCommonT *pThis) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_ENTRY_POINT; + + HRESULT hr = S_OK; + + // If the request was for IUnknown, cast and return success. + if (riid == COMUTIL_IIDOF(IUnknown)) + { + typedef typename detail::GetFirstInterface< + typename IUnknownCommonT::InterfaceListT>::type IUnknownCastHelper; + + // Cast to first interface type to then cast to IUnknown unambiguously. + IUnknown *pItf = static_cast( + static_cast(pThis)); + pItf->AddRef(); + *ppvObject = pItf; + } + // Otherwise none of the interfaces match the requested IID, + // so return E_NOINTERFACE. + else + { + *ppvObject = nullptr; + hr = E_NOINTERFACE; + } + + return hr; + } + }; + + //----------------------------------------------------------------------------------------- + // Is used as a virtual base to ensure that there is a single reference count field. + struct IUnknownCommonRef + { + inline + IUnknownCommonRef() + : m_cRef(0) + {} + + Volatile m_cRef; + }; + } + + //--------------------------------------------------------------------------------------------- + // IUnknownCommon + // + // T0-T9 - the list of interfaces to implement. + template + < + typename T0 = mpl::null_type, + typename T1 = mpl::null_type, + typename T2 = mpl::null_type, + typename T3 = mpl::null_type, + typename T4 = mpl::null_type, + typename T5 = mpl::null_type, + typename T6 = mpl::null_type, + typename T7 = mpl::null_type, + typename T8 = mpl::null_type, + typename T9 = mpl::null_type + > + class IUnknownCommon : + virtual protected detail::IUnknownCommonRef, + public detail::DeriveTypeList< typename mpl::make_type_list< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type > + { + public: + typedef typename mpl::make_type_list< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type InterfaceListT; + + // Add a virtual destructor to force derived types to also have virtual destructors. + virtual ~IUnknownCommon() + { + WRAPPER_NO_CONTRACT; + clr::dbg::PoisonMem(*this); + } + + // Standard AddRef implementation + STDMETHOD_(ULONG, AddRef()) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + return InterlockedIncrement(&m_cRef); + } + + // Standard Release implementation. + STDMETHOD_(ULONG, Release()) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + _ASSERTE(m_cRef > 0); + + ULONG cRef = InterlockedDecrement(&m_cRef); + + if (cRef == 0) + delete this; // Relies on virtual dtor to work properly. + + return cRef; + } + + // Uses detail::QIHelper for implementation. + STDMETHOD(QueryInterface(REFIID riid, void **ppvObject)) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + if (ppvObject == nullptr) + return E_INVALIDARG; + + *ppvObject = nullptr; + + return detail::QIHelper::QI( + riid, ppvObject, this); + } + + template + HRESULT QueryInterface(ItfT **ppItf) + { + return QueryInterface(__uuidof(ItfT), reinterpret_cast(ppItf)); + } + + protected: + // May only be constructed as a base type. + inline IUnknownCommon() : + IUnknownCommonRef() + { WRAPPER_NO_CONTRACT; } + }; + + //--------------------------------------------------------------------------------------------- + // IUnknownCommonExternal + // + // T0-T9 - the list of interfaces to implement. + template + < + typename T0 = mpl::null_type, + typename T1 = mpl::null_type, + typename T2 = mpl::null_type, + typename T3 = mpl::null_type, + typename T4 = mpl::null_type, + typename T5 = mpl::null_type, + typename T6 = mpl::null_type, + typename T7 = mpl::null_type, + typename T8 = mpl::null_type, + typename T9 = mpl::null_type + > + class IUnknownCommonExternal : + virtual protected detail::IUnknownCommonRef, + public detail::DeriveTypeList< typename mpl::make_type_list< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type > + { + public: + typedef typename mpl::make_type_list< + T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type InterfaceListT; + + // Standard AddRef implementation + STDMETHOD_(ULONG, AddRef()) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + return InterlockedIncrement(&m_cRef); + } + + // Standard Release implementation. + // Should be called outside VM only + STDMETHOD_(ULONG, Release()) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + _ASSERTE(m_cRef > 0); + + ULONG cRef = InterlockedDecrement(&m_cRef); + + if (cRef == 0) + { + Cleanup(); // Cleans up the object + delete this; + } + + return cRef; + } + + // Internal release + // Should be called inside VM only + STDMETHOD_(ULONG, InternalRelease()) + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(m_cRef > 0); + + ULONG cRef = InterlockedDecrement(&m_cRef); + + if (cRef == 0) + { + InternalCleanup(); // Cleans up the object, internal version + delete this; + } + + return cRef; + } + + // Uses detail::QIHelper for implementation. + STDMETHOD(QueryInterface(REFIID riid, void **ppvObject)) + { + STATIC_CONTRACT_LIMITED_METHOD; + STATIC_CONTRACT_ENTRY_POINT; + + if (ppvObject == nullptr) + return E_INVALIDARG; + + *ppvObject = nullptr; + + return detail::QIHelper::QI( + riid, ppvObject, this); + } + + template + HRESULT QueryInterface(ItfT **ppItf) + { + return QueryInterface(__uuidof(ItfT), reinterpret_cast(ppItf)); + } + + protected: + // May only be constructed as a base type. + inline IUnknownCommonExternal() : + IUnknownCommonRef() + { WRAPPER_NO_CONTRACT; } + + // Internal version of cleanup + virtual void InternalCleanup() = 0; + + // External version of cleanup + // Not surprisingly, this should call InternalCleanup to avoid duplicate code + // Not implemented here to avoid bringing too much into this header file + virtual void Cleanup() = 0; + }; +} + +#undef COMUTIL_IIDOF + +using ComUtil::NoDerive; +using ComUtil::ItfBase; +using ComUtil::IUnknownCommon; +using ComUtil::IUnknownCommonExternal; + +#endif // __InternalUnknownImpl_h__ diff --git a/lib/coreclr/src/inc/intrinsic.h b/lib/coreclr/src/inc/intrinsic.h new file mode 100644 index 0000000000..50bcd52b28 --- /dev/null +++ b/lib/coreclr/src/inc/intrinsic.h @@ -0,0 +1,25 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// Intrinsic.h +// +// Force several very useful functions to be intrinsic, which means that the +// compiler will generate code inline for the functions instead of generating +// a call to the function. +// +//***************************************************************************** + +#ifndef __intrinsic_h__ +#define __intrinsic_h__ + +#ifdef _MSC_VER +#pragma intrinsic(memcmp) +#pragma intrinsic(memcpy) +#pragma intrinsic(memset) +#pragma intrinsic(strcmp) +#pragma intrinsic(strcpy) +#pragma intrinsic(strlen) +#endif // defined(_MSC_VER) + +#endif // __intrinsic_h__ diff --git a/lib/coreclr/src/inc/iterator.h b/lib/coreclr/src/inc/iterator.h new file mode 100644 index 0000000000..7616c2c044 --- /dev/null +++ b/lib/coreclr/src/inc/iterator.h @@ -0,0 +1,641 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// Iterator.h +// --------------------------------------------------------------------------- + +// ================================================================================ +// Iterator pattern: +// +// This pattern is similar to the STL iterator pattern. It basically consists of +// wrapping an "iteration variable" in an object, and providing pointer-like operators +// on the iterator. Example usage: +// +// for (Iterator start = foo->Begin(), end = foo->End(); start != end; start++) +// { +// // use foo, start +// } +// +// There are 3 levels of iterator functionality +// 1. Enumerator (STL forward) - only go forward one at a time +// Enumerators have the following operations: +// operator * : access current element as ref +// operator -> : access current element as ptr +// operator++ : go to the next element +// operator==, operator!= : compare to another enumerator +// +// +// 2. Scanner (STL bidirectional) - backward or forward one at a time +// Scanners have all the functionality of enumerators, plus: +// operator-- : go backward one element +// +// 3. Indexer (STL random access) - skip around arbitrarily +// Indexers have all the functionality of scanners, plus: +// operator[] : access the element at index from iterator as ref +// operator+= : advance iterator by index +// operator+ : return new iterator at index from iterator +// operator-= : rewind iterator by index +// operator- : return new iterator at index back from iterator +// operator <, operator <=, operator >, operator>= : +// range comparison on two indexers +// +// The object being iterated should define the following methods: +// Begin() return an iterator starting at the first element +// End() return an iterator just past the last element +// +// Iterator types are normally defined as member types named "Iterator", no matter +// what their functionality level is. +// ================================================================================ + + +#ifndef ITERATOR_H_ +#define ITERATOR_H_ + +#include "contract.h" + +namespace HIDDEN { +// These prototypes are not for direct use - they are only here to illustrate the +// iterator pattern + +template +class ScannerPrototype +{ + public: + + typedef ScannerPrototype Iterator; + + ELEMENT &operator*(); + ELEMENT *operator->(); + + Iterator &operator++(); + Iterator operator++(int); + Iterator &operator--(); + Iterator operator--(int); + + bool operator==(const Iterator &i); + bool operator!=(const Iterator &i); +}; + +template +class EnumeratorPrototype +{ + public: + + typedef EnumeratorPrototype Iterator; + + ELEMENT &operator*(); + ELEMENT *operator->(); + + Iterator &operator++(); + Iterator operator++(int); + + bool operator==(const Iterator &i); + bool operator!=(const Iterator &i); +}; + +template +class IndexerPrototype +{ + public: + typedef IndexerPrototype Iterator; + + ELEMENT &operator*(); + ELEMENT *operator->(); + ELEMENT &operator[](int index); + + Iterator &operator++(); + Iterator operator++(int); + Iterator &operator--(); + Iterator operator--(int); + + Iterator &operator+=(SCOUNT_T index); + Iterator &operator-=(SCOUNT_T index); + + Iterator operator+(SCOUNT_T index); + Iterator operator-(SCOUNT_T index); + + SCOUNT_T operator-(Iterator &i); + + bool operator==(const Iterator &i); + bool operator!=(const Iterator &i); + bool operator<(const Iterator &i); + bool operator<=(const Iterator &i); + bool operator>(const Iterator &i); + bool operator>=(const Iterator &i); +}; + +template +class EnumerablePrototype +{ + typedef EnumeratorPrototype Iterator; + + Iterator Begin(); + Iterator End(); +}; + +template +class ScannablePrototype +{ + typedef ScannerPrototype Iterator; + + Iterator Begin(); + Iterator End(); +}; + +template +class IndexablePrototype +{ + typedef IndexerPrototype Iterator; + + Iterator Begin(); + Iterator End(); +}; + +}; + +// -------------------------------------------------------------------------------- +// EnumeratorBase, ScannerBase, and IndexerBase are abstract classes +// describing basic operations for iterator functionality at the different levels. +// +// You +// 1. Use the classes as a pattern (don't derive from them), and plug in your own +// class into the Enumerator/Scanner/Indexer templates below. +// 2. Subclass the AbstractEnumerator/AbstractScanner/AbstractIndexer classes +// -------------------------------------------------------------------------------- + +namespace HIDDEN +{ +// These prototypes are not for direct use - they are only here to illustrate the +// pattern of the BASE class for the Iterator templates + +template +class EnumeratorBasePrototype +{ + protected: + EnumeratorBasePrototype(CONTAINER *container, BOOL begin); + ELEMENT &Get() const; + void Next(); + BOOL Equal(const EnumeratorBasePrototype &i) const; + CHECK DoCheck() const; +}; + +template +class ScannerBasePrototype +{ + protected: + ScannerBasePrototype(CONTAINER *container, BOOL begin); + ELEMENT &Get() const; + void Next(); + void Previous(); + BOOL Equal(const ScannerBasePrototype &i) const; + CHECK DoCheck() const; +}; + +template +class IndexerBasePrototype +{ + protected: + IndexerBasePrototype(CONTAINER *container, SCOUNT_T delta); + ELEMENT &GetAt(SCOUNT_T delta) const; + void Skip(SCOUNT_T delta); + SCOUNT_T Subtract(const IndexerBasePrototype &i) const; + CHECK DoCheck(SCOUNT_T delta) const; +}; + +}; + + +template +class CheckedIteratorBase +{ + protected: +#if defined(_DEBUG) + const CONTAINER *m_container; + int m_revision; +#endif + + CHECK CheckRevision() const + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; +#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__llvm__)) + __if_exists(CONTAINER::m_revision) + { + CHECK_MSG(m_revision == m_container->m_revision, + "Use of Iterator after container has been modified"); + } +#endif + CHECK_OK; + } + + CheckedIteratorBase() + { + LIMITED_METHOD_DAC_CONTRACT; +#if defined(_DEBUG) + m_container = NULL; +#endif + } + + CheckedIteratorBase(const CONTAINER *container) + { + LIMITED_METHOD_CONTRACT; +#if defined(_DEBUG) + m_container = container; +#if defined(_MSC_VER) || defined(__llvm__) + __if_exists(CONTAINER::m_revision) + { + m_revision = m_container->m_revision; + } +#endif +#endif + } + + void Resync(const CONTAINER *container) + { + LIMITED_METHOD_DAC_CONTRACT; + +#if defined(_DEBUG) && (defined(_MSC_VER) || defined(__llvm__)) + __if_exists(CONTAINER::m_revision) + { + m_revision = m_container->m_revision; + } +#endif + } + +#if defined(_DEBUG) + const CONTAINER *GetContainerDebug() const + { + LIMITED_METHOD_CONTRACT; + return m_container; + } +#endif + + public: + CHECK Check() const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckRevision()); + CHECK_OK; + } + + CHECK CheckContainer(const CONTAINER *container) const + { + WRAPPER_NO_CONTRACT; +#if defined(_DEBUG) + CHECK(container == m_container); +#endif + CHECK_OK; + } + +}; + + +// -------------------------------------------------------------------------------- +// Enumerator, Scanner, and Indexer provide a template to produce an iterator +// on an existing class with a single iteration variable. +// +// The template takes 3 type parameters: +// CONTAINER - type of object being interated on +// ELEMENT - type of iteration +// BASE - base type of the iteration. This type must follow the pattern described +// by the above Prototypes +// -------------------------------------------------------------------------------- + +template +class Enumerator +{ + private: + const SUBTYPE *This() const + { + return (const SUBTYPE *) this; + } + + SUBTYPE *This() + { + return (SUBTYPE *)this; + } + + public: + + Enumerator() + { + } + + CHECK CheckIndex() const + { +#if defined(_DEBUG) + CHECK(This()->DoCheck()); +#endif + CHECK_OK; + } + + ELEMENT &operator*() const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex()); + + return This()->Get(); + } + ELEMENT *operator->() const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex()); + + return &(This()->Get()); + } + SUBTYPE &operator++() + { + PRECONDITION(CheckPointer(This())); + + This()->Next(); + return *This(); + } + SUBTYPE operator++(int) + { + PRECONDITION(CheckPointer(This())); + + SUBTYPE i = *This(); + This()->Next(); + return i; + } + bool operator==(const SUBTYPE &i) const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return This()->Equal(i); + } + bool operator!=(const SUBTYPE &i) const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return !This()->Equal(i); + } +}; + +template +class Scanner +{ + private: + const SUBTYPE *This() const + { + return (const SUBTYPE *)this; + } + + SUBTYPE *This() + { + return (SUBTYPE *)this; + } + + public: + + Scanner() + { + } + + CHECK CheckIndex() const + { +#if defined(_DEBUG) + CHECK(This()->DoCheck()); +#endif + CHECK_OK; + } + + ELEMENT &operator*() const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex()); + + return This()->Get(); + } + ELEMENT *operator->() const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex()); + + return &This()->Get(); + } + SUBTYPE &operator++() + { + PRECONDITION(CheckPointer(This())); + + This()->Next(); + return *This(); + } + SUBTYPE operator++(int) + { + PRECONDITION(CheckPointer(This())); + + SUBTYPE i = *This(); + This()->Next(); + return i; + } + SUBTYPE &operator--() + { + PRECONDITION(CheckPointer(This())); + + This()->Previous(); + return *This(); + } + SUBTYPE operator--(int) + { + PRECONDITION(CheckPointer(this)); + + SUBTYPE i = *This(); + This()->Previous(); + return i; + } + bool operator==(const SUBTYPE &i) const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return This()->Equal(i); + } + bool operator!=(const SUBTYPE &i) const + { + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return !This()->Equal(i); + } +}; + +template +class Indexer +{ + private: + const SUBTYPE *This() const + { + return (const SUBTYPE *)this; + } + + SUBTYPE *This() + { + return (SUBTYPE *)this; + } + + public: + + Indexer() + { + LIMITED_METHOD_DAC_CONTRACT; + } + + CHECK CheckIndex() const + { +#if defined(_DEBUG) + CHECK(This()->DoCheck(0)); +#endif + CHECK_OK; + } + + CHECK CheckIndex(int index) const + { +#if defined(_DEBUG) + CHECK(This()->DoCheck(index)); +#endif + CHECK_OK; + } + + ELEMENT &operator*() const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex(0)); + + return *(ELEMENT*)&This()->GetAt(0); + } + ELEMENT *operator->() const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex(0)); + + return &This()->GetAt(0); + } + ELEMENT &operator[](int index) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(This()->CheckIndex(index)); + return *(ELEMENT*)&This()->GetAt(index); + } + SUBTYPE &operator++() + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + This()->Skip(1); + return *This(); + } + SUBTYPE operator++(int) + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + SUBTYPE i = *This(); + This()->Skip(1); + return i; + } + SUBTYPE &operator--() + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + This()->Skip(-1); + return *This(); + } + SUBTYPE operator--(int) + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + SUBTYPE i = *This(); + This()->Skip(-1); + return i; + } + SUBTYPE &operator+=(SCOUNT_T index) + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + This()->Skip(index); + return *This(); + } + SUBTYPE operator+(SCOUNT_T index) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + SUBTYPE i = *This(); + i.Skip(index); + return i; + } + SUBTYPE &operator-=(SCOUNT_T index) + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + This()->Skip(-index); + return *This(); + } + SUBTYPE operator-(SCOUNT_T index) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + SUBTYPE i = *This(); + i.Skip(-index); + return i; + } + SCOUNT_T operator-(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return This()->Subtract(i); + } + bool operator==(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return This()->Subtract(i) == 0; + } + bool operator!=(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + + return This()->Subtract(i) != 0; + } + bool operator<(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + return This()->Subtract(i) < 0; + } + bool operator<=(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + return This()->Subtract(i) <= 0; + } + bool operator>(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + return This()->Subtract(i) > 0; + } + bool operator>=(const SUBTYPE &i) const + { + WRAPPER_NO_CONTRACT; + PRECONDITION(CheckPointer(This())); + PRECONDITION(i.Check()); + return This()->Subtract(i) >= 0; + } +}; + +#endif // ITERATOR_H_ diff --git a/lib/coreclr/src/inc/jithelpers.h b/lib/coreclr/src/inc/jithelpers.h new file mode 100644 index 0000000000..d7d501f382 --- /dev/null +++ b/lib/coreclr/src/inc/jithelpers.h @@ -0,0 +1,376 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// Allow multiple inclusion. + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +// The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the +// JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier +// must be updated. See code:JITEEVersionIdentifier for more information. +// +// THIS FILE IS PART OF THE JIT-EE INTERFACE. +// +// NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE +// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +#ifndef DYNAMICJITHELPER +//I should never try to generate an alignment stub for a dynamic helper +#define DYNAMICJITHELPER(code,fn,sig) JITHELPER(code,fn,sig) +#endif + + +// pfnHelper is set to NULL if it is a stubbed helper. +// It will be set in InitJITHelpers2 + + JITHELPER(CORINFO_HELP_UNDEF, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + + // Arithmetic + JITHELPER(CORINFO_HELP_DIV, JIT_Div, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_MOD, JIT_Mod, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_UDIV, JIT_UDiv, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_UMOD, JIT_UMod, CORINFO_HELP_SIG_8_STACK) + + // CORINFO_HELP_DBL2INT, CORINFO_HELP_DBL2UINT, and CORINFO_HELP_DBL2LONG get + // patched for CPUs that support SSE2 (P4 and above). +#ifndef _TARGET_64BIT_ + JITHELPER(CORINFO_HELP_LLSH, JIT_LLsh, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_LRSH, JIT_LRsh, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_LRSZ, JIT_LRsz, CORINFO_HELP_SIG_REG_ONLY) +#else // !_TARGET_64BIT_ + JITHELPER(CORINFO_HELP_LLSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + JITHELPER(CORINFO_HELP_LRSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + JITHELPER(CORINFO_HELP_LRSZ, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#endif // _TARGET_64BIT_ + JITHELPER(CORINFO_HELP_LMUL, JIT_LMul, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_LMUL_OVF, JIT_LMulOvf, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_ULMUL_OVF, JIT_ULMulOvf, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_LDIV, JIT_LDiv, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_LMOD, JIT_LMod, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_ULDIV, JIT_ULDiv, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_ULMOD, JIT_ULMod, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_LNG2DBL, JIT_Lng2Dbl, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_ULNG2DBL, JIT_ULng2Dbl, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2INT, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBL2INT_OVF, JIT_Dbl2IntOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2LNG, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBL2LNG_OVF, JIT_Dbl2LngOvf, CORINFO_HELP_SIG_8_STACK) + DYNAMICJITHELPER(CORINFO_HELP_DBL2UINT, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBL2UINT_OVF, JIT_Dbl2UIntOvf, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBL2ULNG, JIT_Dbl2ULng, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBL2ULNG_OVF, JIT_Dbl2ULngOvf, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_FLTREM, JIT_FltRem, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBLREM, JIT_DblRem, CORINFO_HELP_SIG_16_STACK) + JITHELPER(CORINFO_HELP_FLTROUND, JIT_FloatRound, CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_DBLROUND, JIT_DoubleRound, CORINFO_HELP_SIG_16_STACK) + + // Allocating a new object + JITHELPER(CORINFO_HELP_NEW_CROSSCONTEXT, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_NEWSFAST_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_New, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_VC, NULL, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_8_VA) + JITHELPER(CORINFO_HELP_NEW_MDARR_NONVARARG, JIT_NewMDArrNonVarArg,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_NEWARR_1_R2R_DIRECT, JIT_NewArr1_R2R,CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_STRCNS, JIT_StrCns, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_STRCNS_CURRENT_MODULE, NULL, CORINFO_HELP_SIG_REG_ONLY) + + // Object model + JITHELPER(CORINFO_HELP_INITCLASS, JIT_InitClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_INITINSTCLASS, JIT_InitInstantiatedClass, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_ISINSTANCEOFINTERFACE,JIT_IsInstanceOfInterface, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_ISINSTANCEOFARRAY, JIT_IsInstanceOfArray,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_ISINSTANCEOFCLASS, JIT_IsInstanceOfClass,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_ISINSTANCEOFANY, JIT_IsInstanceOfAny,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_CHKCASTINTERFACE, JIT_ChkCastInterface,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_CHKCASTARRAY, JIT_ChkCastArray, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_CHKCASTCLASS, JIT_ChkCastClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_CHKCASTANY, JIT_ChkCastAny, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL,JIT_ChkCastClassSpecial,CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_UNBOX, JIT_Unbox, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_UNBOX_NULLABLE, JIT_Unbox_Nullable, CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETREFANY, JIT_GetRefAny, CORINFO_HELP_SIG_8_STACK) +#if defined(_TARGET_ARM_) + DYNAMICJITHELPER(CORINFO_HELP_ARRADDR_ST, JIT_Stelem_Ref, CORINFO_HELP_SIG_4_STACK) +#else + JITHELPER(CORINFO_HELP_ARRADDR_ST, JIT_Stelem_Ref, CORINFO_HELP_SIG_4_STACK) +#endif // _TARGET_ARM_ + JITHELPER(CORINFO_HELP_LDELEMA_REF, JIT_Ldelema_Ref, CORINFO_HELP_SIG_4_STACK) + + // Exceptions + JITHELPER(CORINFO_HELP_THROW, IL_Throw, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_RETHROW, IL_Rethrow, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_USER_BREAKPOINT, JIT_UserBreakpoint, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_RNGCHKFAIL, JIT_RngChkFail, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_OVERFLOW, JIT_Overflow, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROWDIVZERO, JIT_ThrowDivZero, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROWNULLREF, JIT_ThrowNullRef, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_INTERNALTHROW, JIT_InternalThrow, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_VERIFICATION, IL_VerificationError,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SEC_UNMGDCODE_EXCPT, JIT_SecurityUnmanagedCodeException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_FAIL_FAST, JIT_FailFast, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_METHOD_ACCESS_EXCEPTION,JIT_ThrowMethodAccessException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_FIELD_ACCESS_EXCEPTION,JIT_ThrowFieldAccessException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_CLASS_ACCESS_EXCEPTION,JIT_ThrowClassAccessException, CORINFO_HELP_SIG_REG_ONLY) + +#ifdef WIN64EXCEPTIONS + JITHELPER(CORINFO_HELP_ENDCATCH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_ENDCATCH, JIT_EndCatch, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#endif + + JITHELPER(CORINFO_HELP_MON_ENTER, JIT_MonEnterWorker, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_MON_EXIT, JIT_MonExitWorker, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_MON_ENTER_STATIC, JIT_MonEnterStatic,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_MON_EXIT_STATIC, JIT_MonExitStatic,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_GETCLASSFROMMETHODPARAM, JIT_GetClassFromMethodParam, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, JIT_GetSyncFromClassHandle, CORINFO_HELP_SIG_REG_ONLY) + + // Security callout support + JITHELPER(CORINFO_HELP_SECURITY_PROLOG, JIT_Security_Prolog,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SECURITY_PROLOG_FRAMED, JIT_Security_Prolog_Framed,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_METHOD_ACCESS_CHECK, JIT_MethodAccessCheck,CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_FIELD_ACCESS_CHECK, JIT_FieldAccessCheck,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_CLASS_ACCESS_CHECK, JIT_ClassAccessCheck,CORINFO_HELP_SIG_4_STACK) + + JITHELPER(CORINFO_HELP_DELEGATE_SECURITY_CHECK, JIT_DelegateSecurityCheck,CORINFO_HELP_SIG_REG_ONLY) + + // Verification runtime callout support + JITHELPER(CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, JIT_VerificationRuntimeCheck,CORINFO_HELP_SIG_REG_ONLY) + + // GC support + DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, CORINFO_HELP_SIG_REG_ONLY) +#ifdef ENABLE_FAST_GCPOLL_HELPER + DYNAMICJITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY) +#else + JITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY) +#endif + JITHELPER(CORINFO_HELP_STRESS_GC, JIT_StressGC, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_CHECK_OBJ, JIT_CheckObj, CORINFO_HELP_SIG_REG_ONLY) + + // GC Write barrier support + DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF, JIT_WriteBarrier, CORINFO_HELP_SIG_NO_ALIGN_STUB) + DYNAMICJITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF, JIT_CheckedWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, JIT_WriteBarrierEnsureNonHeapTarget,CORINFO_HELP_SIG_REG_ONLY) + + DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_BYREF, JIT_ByRefWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_ASSIGN_STRUCT, JIT_StructWriteBarrier,CORINFO_HELP_SIG_4_STACK) + + // Accessing fields + JITHELPER(CORINFO_HELP_GETFIELD8, JIT_GetField8,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELD8, JIT_SetField8,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETFIELD16, JIT_GetField16,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELD16, JIT_SetField16,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETFIELD32, JIT_GetField32,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELD32, JIT_SetField32,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETFIELD64, JIT_GetField64,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELD64, JIT_SetField64,CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_GETFIELDOBJ, JIT_GetFieldObj,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELDOBJ, JIT_SetFieldObj,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETFIELDSTRUCT, JIT_GetFieldStruct,CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_SETFIELDSTRUCT, JIT_SetFieldStruct,CORINFO_HELP_SIG_8_STACK) + JITHELPER(CORINFO_HELP_GETFIELDFLOAT, JIT_GetFieldFloat,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELDFLOAT, JIT_SetFieldFloat,CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_GETFIELDDOUBLE, JIT_GetFieldDouble,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_SETFIELDDOUBLE, JIT_SetFieldDouble,CORINFO_HELP_SIG_8_STACK) + + JITHELPER(CORINFO_HELP_GETFIELDADDR, JIT_GetFieldAddr,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_GETSTATICFIELDADDR_CONTEXT, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + JITHELPER(CORINFO_HELP_GETSTATICFIELDADDR_TLS, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, JIT_GetGenericsGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, JIT_GetGenericsNonGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) + +#ifdef _TARGET_X86_ + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, NULL, CORINFO_HELP_SIG_REG_ONLY) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,NULL, CORINFO_HELP_SIG_REG_ONLY) +#else + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, JIT_GetSharedNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, JIT_GetSharedGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,JIT_GetSharedNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#endif + JITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS, JIT_ClassInitDynamicClass,CORINFO_HELP_SIG_REG_ONLY) + + // Thread statics + JITHELPER(CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, JIT_GetGenericsGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE, JIT_GetGenericsNonGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) + + // Debugger + JITHELPER(CORINFO_HELP_DBG_IS_JUST_MY_CODE, JIT_DbgIsJustMyCode,CORINFO_HELP_SIG_REG_ONLY) + + /* Profiling enter/leave probe addresses */ + DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_ENTER, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_LEAVE, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) + DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_TAILCALL, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) + + // Miscellaneous + JITHELPER(CORINFO_HELP_BBT_FCN_ENTER, JIT_LogMethodEnter,CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_PINVOKE_CALLI, GenericPInvokeCalliHelper, CORINFO_HELP_SIG_NO_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_TAILCALL, JIT_TailCall, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_GETCURRENTMANAGEDTHREADID, JIT_GetCurrentManagedThreadId, CORINFO_HELP_SIG_REG_ONLY) + +#ifdef _WIN64 + // On Windows X64, the last argument is ignored. + JITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, JIT_InitPInvokeFrame, CORINFO_HELP_SIG_REG_ONLY) +#else + DYNAMICJITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, NULL, CORINFO_HELP_SIG_REG_ONLY) +#endif + +#ifdef _TARGET_X86_ + JITHELPER(CORINFO_HELP_MEMSET, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) + JITHELPER(CORINFO_HELP_MEMCPY, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_MEMSET, JIT_MemSet, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_MEMCPY, JIT_MemCpy, CORINFO_HELP_SIG_REG_ONLY) +#endif + + // Generics + JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD, JIT_GenericHandleMethod, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG,JIT_GenericHandleMethodLogging, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS, JIT_GenericHandleClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG, JIT_GenericHandleClassLogging, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, JIT_GetRuntimeType, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, JIT_GetRuntimeMethodStub,CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, JIT_GetRuntimeFieldStub, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, JIT_GetRuntimeType, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_ARE_TYPES_EQUIVALENT, NULL, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, CORINFO_HELP_SIG_4_STACK) + //JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR_LOG,JIT_VirtualFunctionPointerLogging) + + JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_EE_PRESTUB, ThePreStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) + +#if defined(HAS_FIXUP_PRECODE) + JITHELPER(CORINFO_HELP_EE_PRECODE_FIXUP, PrecodeFixupThunk, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_EE_PRECODE_FIXUP, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#endif + + JITHELPER(CORINFO_HELP_EE_PINVOKE_FIXUP, NDirectImportThunk, CORINFO_HELP_SIG_NO_ALIGN_STUB) + +#ifdef FEATURE_PREJIT + JITHELPER(CORINFO_HELP_EE_VSD_FIXUP, StubDispatchFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_EE_VSD_FIXUP, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#endif + JITHELPER(CORINFO_HELP_EE_EXTERNAL_FIXUP, ExternalMethodFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#ifdef FEATURE_PREJIT + JITHELPER(CORINFO_HELP_EE_VTABLE_FIXUP, VirtualMethodFixupStub, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_EE_VTABLE_FIXUP, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#endif + + JITHELPER(CORINFO_HELP_EE_REMOTING_THUNK, NULL, CORINFO_HELP_SIG_UNDEF) + +// We do not need this to be saved in ngen images on Mac64 since the exception dispatch +// is not done via the OS and thus, there wont be any need to know this information +// by anyone. +#ifdef WIN64EXCEPTIONS + JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, ProcessCLRException, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, ProcessCLRException,CORINFO_HELP_SIG_UNDEF) +#else // WIN64EXCEPTIONS + JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, NULL, CORINFO_HELP_SIG_UNDEF) +#endif // !WIN64EXCEPTIONS + +#ifdef _TARGET_X86_ + JITHELPER(CORINFO_HELP_ASSIGN_REF_EAX, JIT_WriteBarrierEAX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EBX, JIT_WriteBarrierEBX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_ECX, JIT_WriteBarrierECX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_ESI, JIT_WriteBarrierESI, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EDI, JIT_WriteBarrierEDI, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EBP, JIT_WriteBarrierEBP, CORINFO_HELP_SIG_NO_ALIGN_STUB) + + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, JIT_CheckedWriteBarrierEAX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, JIT_CheckedWriteBarrierEBX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, JIT_CheckedWriteBarrierECX, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, JIT_CheckedWriteBarrierESI, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, JIT_CheckedWriteBarrierEDI, CORINFO_HELP_SIG_NO_ALIGN_STUB) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, JIT_CheckedWriteBarrierEBP, CORINFO_HELP_SIG_NO_ALIGN_STUB) +#else + JITHELPER(CORINFO_HELP_ASSIGN_REF_EAX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EBX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_ASSIGN_REF_ECX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_ASSIGN_REF_ESI, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EDI, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_ASSIGN_REF_EBP, NULL, CORINFO_HELP_SIG_UNDEF) + + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, NULL, CORINFO_HELP_SIG_UNDEF) +#endif + + JITHELPER(CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR, JIT_LoopCloneChoiceAddr, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, JIT_DebugLogLoopCloning, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_THROW_ARGUMENTEXCEPTION, JIT_ThrowArgumentException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, JIT_ThrowArgumentOutOfRangeException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROW_NOT_IMPLEMENTED, JIT_ThrowNotImplementedException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, JIT_ThrowPlatformNotSupportedException, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, JIT_ThrowTypeNotSupportedException, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, JIT_PInvokeBegin, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, JIT_PInvokeEnd, CORINFO_HELP_SIG_REG_ONLY) + + JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, NULL, CORINFO_HELP_SIG_UNDEF) + JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, NULL, CORINFO_HELP_SIG_UNDEF) + + JITHELPER(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) + +#undef JITHELPER +#undef DYNAMICJITHELPER +#undef JITHELPER +#undef DYNAMICJITHELPER diff --git a/lib/coreclr/src/inc/jitperf.h b/lib/coreclr/src/inc/jitperf.h new file mode 100644 index 0000000000..022cfd2169 --- /dev/null +++ b/lib/coreclr/src/inc/jitperf.h @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- +// JitPerf.h +// Internal interface for gathering JIT perfmormance stats. These stats are +// logged (or displayed) in two ways. If PERF_COUNTERS are enabled the +// perfmon etc. would display the jit stats. If ENABLE_PERF_LOG is enabled +// and PERF_OUTPUT env var is defined then the jit stats are displayed on the +// stdout. (The jit stats are outputted in a specific format to a file for +// automated perf tests.) +// + +//----------------------------------------------------------------------------- + + +#ifndef __JITPERF_H__ +#define __JITPERF_H__ + +#include "mscoree.h" +#include "clrinternal.h" + +// ENABLE_JIT_PERF tag used to activate JIT specific profiling. +#define ENABLE_JIT_PERF + +#if defined(ENABLE_JIT_PERF) + +extern __int64 g_JitCycles; +extern size_t g_NonJitCycles; +extern CRITSEC_COOKIE g_csJit; +extern __int64 g_tlsJitCycles; +extern int g_fJitPerfOn; + +extern size_t g_dwTlsx86CodeSize; +extern size_t g_TotalILCodeSize; +extern size_t g_Totalx86CodeSize; +extern size_t g_TotalMethodsJitted; + +// Public interface to initialize jit stats data structs +void InitJitPerf(void); +// Public interface to deallocate datastruct and output the stats. +void DoneJitPerfStats(void); + +// Start/StopNonJITPerf macros are used many times. Factor out the payload +// into helper method to reduce code size. +void StartNonJITPerfWorker(LARGE_INTEGER * pCycleStart); +void StopNonJITPerfWorker(LARGE_INTEGER * pCycleStart); + +// Use the callee's stack frame (so START & STOP functions can share variables) +#define START_JIT_PERF() \ + if (g_fJitPerfOn) { \ + ClrFlsSetValue (TlsIdx_JitPerf, (LPVOID)0); \ + g_dwTlsx86CodeSize = 0; \ + ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)g_dwTlsx86CodeSize); \ + } + + +#define STOP_JIT_PERF() \ + if (g_fJitPerfOn) { \ + size_t dwTlsNonJitCycles = (size_t)ClrFlsGetValue (TlsIdx_JitPerf); \ + size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ + CRITSEC_Holder csh (g_csJit); \ + g_JitCycles += static_cast(CycleStop.QuadPart - CycleStart.QuadPart); \ + g_NonJitCycles += dwTlsNonJitCycles; \ + g_TotalILCodeSize += methodInfo.ILCodeSize; \ + g_Totalx86CodeSize += dwx86CodeSize; \ + g_TotalMethodsJitted ++; \ + } + +#define START_NON_JIT_PERF() \ + LARGE_INTEGER CycleStart; \ + if(g_fJitPerfOn) { \ + StartNonJITPerfWorker(&CycleStart); \ + } + +#define STOP_NON_JIT_PERF() \ + if(g_fJitPerfOn) { \ + StopNonJITPerfWorker(&CycleStart); \ + } + +#define JIT_PERF_UPDATE_X86_CODE_SIZE(size) \ + if(g_fJitPerfOn) { \ + size_t dwx86CodeSize = (size_t)ClrFlsGetValue (TlsIdx_JitX86Perf); \ + dwx86CodeSize += (size); \ + ClrFlsSetValue (TlsIdx_JitX86Perf, (LPVOID)dwx86CodeSize); \ + } + + +#else //ENABLE_JIT_PERF +#define START_JIT_PERF() +#define STOP_JIT_PERF() +#define START_NON_JIT_PERF() +#define STOP_NON_JIT_PERF() +#define JIT_PERF_UPDATE_X86_CODE_SIZE(size) +#endif //ENABLE_JIT_PERF + +#endif //__JITPERF_H__ diff --git a/lib/coreclr/src/inc/lazycow.h b/lib/coreclr/src/inc/lazycow.h new file mode 100644 index 0000000000..c4605b6e0d --- /dev/null +++ b/lib/coreclr/src/inc/lazycow.h @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// LazyCOW.h +// + +// +// Provides support for "lazy copy-on-write" pages. +// +// NGEN images contain a large amount of writable data. At runtime, we typically only actually write to a small portion of this data. +// When we write to a writable page in an image, the OS must create a process-local copy of that page, so that other proceses +// cannot see the written data. To prevent this copy from failing, the OS pre-commits space in the pagefile for all writable +// pages when the image is loaded. Thus we get charged for every writable page, even if we only write to a few of them. +// +// FEATURE_LAZY_COW_PAGES enables "lazy copy-on-write." We mark the pages in the image file as read-only, and thus the OS +// does not pre-commit pagefile for these pages. At runtime, prior to writing to any page, we update it to be writable. +// This may fail, and thus is not appropriate for scenarios where strong reliability guarantees must be met. But for +// devices with small memory this is still worth it. +// +// -------------------------------------------------------------------------------- + +#ifndef LAZY_COW_H +#define LAZY_COW_H + +#ifdef FEATURE_LAZY_COW_PAGES + +#ifdef _WIN64 // due to the way we track pages, we cannot currently support 64-bit. +#error FEATURE_LAZY_COW_PAGES is only supported on 32-bit platforms. +#endif + +class PEDecoder; + +// If hModule is a native image, establishes copy-on-write tracking for the image. +// FreeLazyCOWPages must be called immediately before the module is unloaded. +void AllocateLazyCOWPages(PEDecoder * pImage); + +// If hModule is a native image, disestablishes copy-on-write tracking for the image. +// The image must be immediately unloaded following this call. +void FreeLazyCOWPages(PEDecoder * pImage); + +bool IsInReadOnlyLazyCOWPage(void* p); + + +// Forces the page(s) covered by the given address range to be made writable, +// if they are being tracked as copy-on-write pages. Otherwise does nothing. +// Returns false if we could not allocate the necessary memory. +bool EnsureWritablePagesNoThrow(void* p, size_t len); + +// Version for executable pages +bool EnsureWritableExecutablePagesNoThrow(void* p, size_t len); + +// Throwing version of EnsureWritablePagesNoThrow +void EnsureWritablePages(void* p, size_t len); + +// Version for executable pages +void EnsureWritableExecutablePages(void* p, size_t len); + +#else //FEATURE_LAZY_COW_PAGES + +inline bool EnsureWritablePagesNoThrow(void* p, size_t len) +{ + return true; +} + +inline bool EnsureWritableExecutablePagesNoThrow(void* p, size_t len) +{ + return true; +} + +inline void EnsureWritablePages(void* p, size_t len) +{ +} + +inline void EnsureWritableExecutablePages(void* p, size_t len) +{ +} + +#endif //FEATURE_LAZY_COW_PAGES + +// Typed version of EnsureWritable. Returns p, so this can be inserted in expressions. +// Ignores any failure to allocate. In typical cases this means that the write will AV. +// In the CLR that's OK; we handle the AV, try EnsureWritable(void*,size_t), and +// fail-fast when it fails. +template +inline T* EnsureWritablePages(T* p) +{ + EnsureWritablePages(p, sizeof(T)); + return p; +} + +template +inline T* EnsureWritableExecutablePages(T* p) +{ + EnsureWritableExecutablePages(p, sizeof(T)); + return p; +} + +#endif // LAZY_COW_H diff --git a/lib/coreclr/src/inc/livedatatarget.h b/lib/coreclr/src/inc/livedatatarget.h new file mode 100644 index 0000000000..1ffbca7d78 --- /dev/null +++ b/lib/coreclr/src/inc/livedatatarget.h @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// +// Define a Data-Target for a live process. +// +//***************************************************************************** + +#ifndef _LIVEPROC_DATATARGET_H_ +#define _LIVEPROC_DATATARGET_H_ + +// Defines the Data-Target and other public interfaces. +// Does not include IXClrData definitions. +#include + +#ifndef FEATURE_PAL + +//--------------------------------------------------------------------------------------- +// +// Provides a simple legacy data-target implementation for a live, local, process. +// Note that in arrowhead, most debuggers use ICorDebugDataTarget, and we have +// implementations of this in MDbg. +// +class LiveProcDataTarget : public ICLRDataTarget +{ +public: + LiveProcDataTarget(HANDLE process, + DWORD processId, + CLRDATA_ADDRESS baseAddressOfEngine = NULL); + + // + // IUnknown. + // + // This class is intended to be kept on the stack + // or as a member and does not maintain a refcount. + // + + STDMETHOD(QueryInterface)( + THIS_ + IN REFIID InterfaceId, + OUT PVOID* Interface + ); + STDMETHOD_(ULONG, AddRef)( + THIS + ); + STDMETHOD_(ULONG, Release)( + THIS + ); + + // + // ICLRDataTarget. + // + + virtual HRESULT STDMETHODCALLTYPE GetMachineType( + /* [out] */ ULONG32 *machine); + virtual HRESULT STDMETHODCALLTYPE GetPointerSize( + /* [out] */ ULONG32 *size); + virtual HRESULT STDMETHODCALLTYPE GetImageBase( + /* [string][in] */ LPCWSTR name, + /* [out] */ CLRDATA_ADDRESS *base); + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ PBYTE buffer, + /* [in] */ ULONG32 request, + /* [optional][out] */ ULONG32 *done); + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ PBYTE buffer, + /* [in] */ ULONG32 request, + /* [optional][out] */ ULONG32 *done); + virtual HRESULT STDMETHODCALLTYPE GetTLSValue( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS* value); + virtual HRESULT STDMETHODCALLTYPE SetTLSValue( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value); + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( + /* [out] */ ULONG32* threadID); + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [out, size_is(contextSize)] */ PBYTE context); + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [in, size_is(contextSize)] */ PBYTE context); + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + +private: + HANDLE m_process; + DWORD m_processId; + CLRDATA_ADDRESS m_baseAddressOfEngine; +}; + +#endif // FEATURE_PAL + +#endif // _LIVEPROC_DATATARGET_H_ + diff --git a/lib/coreclr/src/inc/llvm/Dwarf.def b/lib/coreclr/src/inc/llvm/Dwarf.def new file mode 100644 index 0000000000..2bc9ef8621 --- /dev/null +++ b/lib/coreclr/src/inc/llvm/Dwarf.def @@ -0,0 +1,393 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ============================================================================== +// LLVM Release License +// ============================================================================== +// University of Illinois/NCSA +// Open Source License +// +// Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. +// All rights reserved. +// +// Developed by: +// +// LLVM Team +// +// University of Illinois at Urbana-Champaign +// +// http://llvm.org +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal with +// 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: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimers. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimers in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the names of the LLVM Team, University of Illinois at +// Urbana-Champaign, nor the names of its contributors may be used to +// endorse or promote products derived from this Software without specific +// prior written permission. +// +// 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 +// CONTRIBUTORS 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 WITH THE +// SOFTWARE. + +//===----------------------------------------------------------------------===// +// +// Macros for running through Dwarf enumerators. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \ + defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ + defined HANDLE_DW_VIRTUALITY) +#error "Missing macro definition of HANDLE_DW*" +#endif + +#ifndef HANDLE_DW_TAG +#define HANDLE_DW_TAG(ID, NAME) +#endif + +#ifndef HANDLE_DW_OP +#define HANDLE_DW_OP(ID, NAME) +#endif + +#ifndef HANDLE_DW_LANG +#define HANDLE_DW_LANG(ID, NAME) +#endif + +#ifndef HANDLE_DW_ATE +#define HANDLE_DW_ATE(ID, NAME) +#endif + +#ifndef HANDLE_DW_VIRTUALITY +#define HANDLE_DW_VIRTUALITY(ID, NAME) +#endif + +HANDLE_DW_TAG(0x0001, array_type) +HANDLE_DW_TAG(0x0002, class_type) +HANDLE_DW_TAG(0x0003, entry_point) +HANDLE_DW_TAG(0x0004, enumeration_type) +HANDLE_DW_TAG(0x0005, formal_parameter) +HANDLE_DW_TAG(0x0008, imported_declaration) +HANDLE_DW_TAG(0x000a, label) +HANDLE_DW_TAG(0x000b, lexical_block) +HANDLE_DW_TAG(0x000d, member) +HANDLE_DW_TAG(0x000f, pointer_type) +HANDLE_DW_TAG(0x0010, reference_type) +HANDLE_DW_TAG(0x0011, compile_unit) +HANDLE_DW_TAG(0x0012, string_type) +HANDLE_DW_TAG(0x0013, structure_type) +HANDLE_DW_TAG(0x0015, subroutine_type) +HANDLE_DW_TAG(0x0016, typedef) +HANDLE_DW_TAG(0x0017, union_type) +HANDLE_DW_TAG(0x0018, unspecified_parameters) +HANDLE_DW_TAG(0x0019, variant) +HANDLE_DW_TAG(0x001a, common_block) +HANDLE_DW_TAG(0x001b, common_inclusion) +HANDLE_DW_TAG(0x001c, inheritance) +HANDLE_DW_TAG(0x001d, inlined_subroutine) +HANDLE_DW_TAG(0x001e, module) +HANDLE_DW_TAG(0x001f, ptr_to_member_type) +HANDLE_DW_TAG(0x0020, set_type) +HANDLE_DW_TAG(0x0021, subrange_type) +HANDLE_DW_TAG(0x0022, with_stmt) +HANDLE_DW_TAG(0x0023, access_declaration) +HANDLE_DW_TAG(0x0024, base_type) +HANDLE_DW_TAG(0x0025, catch_block) +HANDLE_DW_TAG(0x0026, const_type) +HANDLE_DW_TAG(0x0027, constant) +HANDLE_DW_TAG(0x0028, enumerator) +HANDLE_DW_TAG(0x0029, file_type) +HANDLE_DW_TAG(0x002a, friend) +HANDLE_DW_TAG(0x002b, namelist) +HANDLE_DW_TAG(0x002c, namelist_item) +HANDLE_DW_TAG(0x002d, packed_type) +HANDLE_DW_TAG(0x002e, subprogram) +HANDLE_DW_TAG(0x002f, template_type_parameter) +HANDLE_DW_TAG(0x0030, template_value_parameter) +HANDLE_DW_TAG(0x0031, thrown_type) +HANDLE_DW_TAG(0x0032, try_block) +HANDLE_DW_TAG(0x0033, variant_part) +HANDLE_DW_TAG(0x0034, variable) +HANDLE_DW_TAG(0x0035, volatile_type) +HANDLE_DW_TAG(0x0036, dwarf_procedure) +HANDLE_DW_TAG(0x0037, restrict_type) +HANDLE_DW_TAG(0x0038, interface_type) +HANDLE_DW_TAG(0x0039, namespace) +HANDLE_DW_TAG(0x003a, imported_module) +HANDLE_DW_TAG(0x003b, unspecified_type) +HANDLE_DW_TAG(0x003c, partial_unit) +HANDLE_DW_TAG(0x003d, imported_unit) +HANDLE_DW_TAG(0x003f, condition) +HANDLE_DW_TAG(0x0040, shared_type) +HANDLE_DW_TAG(0x0041, type_unit) +HANDLE_DW_TAG(0x0042, rvalue_reference_type) +HANDLE_DW_TAG(0x0043, template_alias) + +// New in DWARF v5. +HANDLE_DW_TAG(0x0044, coarray_type) +HANDLE_DW_TAG(0x0045, generic_subrange) +HANDLE_DW_TAG(0x0046, dynamic_type) + +// User-defined tags. +HANDLE_DW_TAG(0x4081, MIPS_loop) +HANDLE_DW_TAG(0x4101, format_label) +HANDLE_DW_TAG(0x4102, function_template) +HANDLE_DW_TAG(0x4103, class_template) +HANDLE_DW_TAG(0x4106, GNU_template_template_param) +HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack) +HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack) +HANDLE_DW_TAG(0x4200, APPLE_property) +HANDLE_DW_TAG(0xb000, BORLAND_property) +HANDLE_DW_TAG(0xb001, BORLAND_Delphi_string) +HANDLE_DW_TAG(0xb002, BORLAND_Delphi_dynamic_array) +HANDLE_DW_TAG(0xb003, BORLAND_Delphi_set) +HANDLE_DW_TAG(0xb004, BORLAND_Delphi_variant) + +HANDLE_DW_OP(0x03, addr) +HANDLE_DW_OP(0x06, deref) +HANDLE_DW_OP(0x08, const1u) +HANDLE_DW_OP(0x09, const1s) +HANDLE_DW_OP(0x0a, const2u) +HANDLE_DW_OP(0x0b, const2s) +HANDLE_DW_OP(0x0c, const4u) +HANDLE_DW_OP(0x0d, const4s) +HANDLE_DW_OP(0x0e, const8u) +HANDLE_DW_OP(0x0f, const8s) +HANDLE_DW_OP(0x10, constu) +HANDLE_DW_OP(0x11, consts) +HANDLE_DW_OP(0x12, dup) +HANDLE_DW_OP(0x13, drop) +HANDLE_DW_OP(0x14, over) +HANDLE_DW_OP(0x15, pick) +HANDLE_DW_OP(0x16, swap) +HANDLE_DW_OP(0x17, rot) +HANDLE_DW_OP(0x18, xderef) +HANDLE_DW_OP(0x19, abs) +HANDLE_DW_OP(0x1a, and) +HANDLE_DW_OP(0x1b, div) +HANDLE_DW_OP(0x1c, minus) +HANDLE_DW_OP(0x1d, mod) +HANDLE_DW_OP(0x1e, mul) +HANDLE_DW_OP(0x1f, neg) +HANDLE_DW_OP(0x20, not) +HANDLE_DW_OP(0x21, or ) +HANDLE_DW_OP(0x22, plus) +HANDLE_DW_OP(0x23, plus_uconst) +HANDLE_DW_OP(0x24, shl) +HANDLE_DW_OP(0x25, shr) +HANDLE_DW_OP(0x26, shra) +HANDLE_DW_OP(0x27, xor) +HANDLE_DW_OP(0x2f, skip) +HANDLE_DW_OP(0x28, bra) +HANDLE_DW_OP(0x29, eq) +HANDLE_DW_OP(0x2a, ge) +HANDLE_DW_OP(0x2b, gt) +HANDLE_DW_OP(0x2c, le) +HANDLE_DW_OP(0x2d, lt) +HANDLE_DW_OP(0x2e, ne) +HANDLE_DW_OP(0x30, lit0) +HANDLE_DW_OP(0x31, lit1) +HANDLE_DW_OP(0x32, lit2) +HANDLE_DW_OP(0x33, lit3) +HANDLE_DW_OP(0x34, lit4) +HANDLE_DW_OP(0x35, lit5) +HANDLE_DW_OP(0x36, lit6) +HANDLE_DW_OP(0x37, lit7) +HANDLE_DW_OP(0x38, lit8) +HANDLE_DW_OP(0x39, lit9) +HANDLE_DW_OP(0x3a, lit10) +HANDLE_DW_OP(0x3b, lit11) +HANDLE_DW_OP(0x3c, lit12) +HANDLE_DW_OP(0x3d, lit13) +HANDLE_DW_OP(0x3e, lit14) +HANDLE_DW_OP(0x3f, lit15) +HANDLE_DW_OP(0x40, lit16) +HANDLE_DW_OP(0x41, lit17) +HANDLE_DW_OP(0x42, lit18) +HANDLE_DW_OP(0x43, lit19) +HANDLE_DW_OP(0x44, lit20) +HANDLE_DW_OP(0x45, lit21) +HANDLE_DW_OP(0x46, lit22) +HANDLE_DW_OP(0x47, lit23) +HANDLE_DW_OP(0x48, lit24) +HANDLE_DW_OP(0x49, lit25) +HANDLE_DW_OP(0x4a, lit26) +HANDLE_DW_OP(0x4b, lit27) +HANDLE_DW_OP(0x4c, lit28) +HANDLE_DW_OP(0x4d, lit29) +HANDLE_DW_OP(0x4e, lit30) +HANDLE_DW_OP(0x4f, lit31) +HANDLE_DW_OP(0x50, reg0) +HANDLE_DW_OP(0x51, reg1) +HANDLE_DW_OP(0x52, reg2) +HANDLE_DW_OP(0x53, reg3) +HANDLE_DW_OP(0x54, reg4) +HANDLE_DW_OP(0x55, reg5) +HANDLE_DW_OP(0x56, reg6) +HANDLE_DW_OP(0x57, reg7) +HANDLE_DW_OP(0x58, reg8) +HANDLE_DW_OP(0x59, reg9) +HANDLE_DW_OP(0x5a, reg10) +HANDLE_DW_OP(0x5b, reg11) +HANDLE_DW_OP(0x5c, reg12) +HANDLE_DW_OP(0x5d, reg13) +HANDLE_DW_OP(0x5e, reg14) +HANDLE_DW_OP(0x5f, reg15) +HANDLE_DW_OP(0x60, reg16) +HANDLE_DW_OP(0x61, reg17) +HANDLE_DW_OP(0x62, reg18) +HANDLE_DW_OP(0x63, reg19) +HANDLE_DW_OP(0x64, reg20) +HANDLE_DW_OP(0x65, reg21) +HANDLE_DW_OP(0x66, reg22) +HANDLE_DW_OP(0x67, reg23) +HANDLE_DW_OP(0x68, reg24) +HANDLE_DW_OP(0x69, reg25) +HANDLE_DW_OP(0x6a, reg26) +HANDLE_DW_OP(0x6b, reg27) +HANDLE_DW_OP(0x6c, reg28) +HANDLE_DW_OP(0x6d, reg29) +HANDLE_DW_OP(0x6e, reg30) +HANDLE_DW_OP(0x6f, reg31) +HANDLE_DW_OP(0x70, breg0) +HANDLE_DW_OP(0x71, breg1) +HANDLE_DW_OP(0x72, breg2) +HANDLE_DW_OP(0x73, breg3) +HANDLE_DW_OP(0x74, breg4) +HANDLE_DW_OP(0x75, breg5) +HANDLE_DW_OP(0x76, breg6) +HANDLE_DW_OP(0x77, breg7) +HANDLE_DW_OP(0x78, breg8) +HANDLE_DW_OP(0x79, breg9) +HANDLE_DW_OP(0x7a, breg10) +HANDLE_DW_OP(0x7b, breg11) +HANDLE_DW_OP(0x7c, breg12) +HANDLE_DW_OP(0x7d, breg13) +HANDLE_DW_OP(0x7e, breg14) +HANDLE_DW_OP(0x7f, breg15) +HANDLE_DW_OP(0x80, breg16) +HANDLE_DW_OP(0x81, breg17) +HANDLE_DW_OP(0x82, breg18) +HANDLE_DW_OP(0x83, breg19) +HANDLE_DW_OP(0x84, breg20) +HANDLE_DW_OP(0x85, breg21) +HANDLE_DW_OP(0x86, breg22) +HANDLE_DW_OP(0x87, breg23) +HANDLE_DW_OP(0x88, breg24) +HANDLE_DW_OP(0x89, breg25) +HANDLE_DW_OP(0x8a, breg26) +HANDLE_DW_OP(0x8b, breg27) +HANDLE_DW_OP(0x8c, breg28) +HANDLE_DW_OP(0x8d, breg29) +HANDLE_DW_OP(0x8e, breg30) +HANDLE_DW_OP(0x8f, breg31) +HANDLE_DW_OP(0x90, regx) +HANDLE_DW_OP(0x91, fbreg) +HANDLE_DW_OP(0x92, bregx) +HANDLE_DW_OP(0x93, piece) +HANDLE_DW_OP(0x94, deref_size) +HANDLE_DW_OP(0x95, xderef_size) +HANDLE_DW_OP(0x96, nop) +HANDLE_DW_OP(0x97, push_object_address) +HANDLE_DW_OP(0x98, call2) +HANDLE_DW_OP(0x99, call4) +HANDLE_DW_OP(0x9a, call_ref) +HANDLE_DW_OP(0x9b, form_tls_address) +HANDLE_DW_OP(0x9c, call_frame_cfa) +HANDLE_DW_OP(0x9d, bit_piece) +HANDLE_DW_OP(0x9e, implicit_value) +HANDLE_DW_OP(0x9f, stack_value) + +// Extensions for GNU-style thread-local storage. +HANDLE_DW_OP(0xe0, GNU_push_tls_address) + +// Extensions for Fission proposal. +HANDLE_DW_OP(0xfb, GNU_addr_index) +HANDLE_DW_OP(0xfc, GNU_const_index) + +// DWARF languages. +HANDLE_DW_LANG(0x0001, C89) +HANDLE_DW_LANG(0x0002, C) +HANDLE_DW_LANG(0x0003, Ada83) +HANDLE_DW_LANG(0x0004, C_plus_plus) +HANDLE_DW_LANG(0x0005, Cobol74) +HANDLE_DW_LANG(0x0006, Cobol85) +HANDLE_DW_LANG(0x0007, Fortran77) +HANDLE_DW_LANG(0x0008, Fortran90) +HANDLE_DW_LANG(0x0009, Pascal83) +HANDLE_DW_LANG(0x000a, Modula2) +HANDLE_DW_LANG(0x000b, Java) +HANDLE_DW_LANG(0x000c, C99) +HANDLE_DW_LANG(0x000d, Ada95) +HANDLE_DW_LANG(0x000e, Fortran95) +HANDLE_DW_LANG(0x000f, PLI) +HANDLE_DW_LANG(0x0010, ObjC) +HANDLE_DW_LANG(0x0011, ObjC_plus_plus) +HANDLE_DW_LANG(0x0012, UPC) +HANDLE_DW_LANG(0x0013, D) + +// New in DWARF 5: +HANDLE_DW_LANG(0x0014, Python) +HANDLE_DW_LANG(0x0015, OpenCL) +HANDLE_DW_LANG(0x0016, Go) +HANDLE_DW_LANG(0x0017, Modula3) +HANDLE_DW_LANG(0x0018, Haskell) +HANDLE_DW_LANG(0x0019, C_plus_plus_03) +HANDLE_DW_LANG(0x001a, C_plus_plus_11) +HANDLE_DW_LANG(0x001b, OCaml) +HANDLE_DW_LANG(0x001c, Rust) +HANDLE_DW_LANG(0x001d, C11) +HANDLE_DW_LANG(0x001e, Swift) +HANDLE_DW_LANG(0x001f, Julia) +HANDLE_DW_LANG(0x0020, Dylan) +HANDLE_DW_LANG(0x0021, C_plus_plus_14) +HANDLE_DW_LANG(0x0022, Fortran03) +HANDLE_DW_LANG(0x0023, Fortran08) +HANDLE_DW_LANG(0x8001, Mips_Assembler) +HANDLE_DW_LANG(0xb000, BORLAND_Delphi) + +// DWARF attribute type encodings. +HANDLE_DW_ATE(0x01, address) +HANDLE_DW_ATE(0x02, boolean) +HANDLE_DW_ATE(0x03, complex_float) +HANDLE_DW_ATE(0x04, float) +HANDLE_DW_ATE(0x05, signed) +HANDLE_DW_ATE(0x06, signed_char) +HANDLE_DW_ATE(0x07, unsigned) +HANDLE_DW_ATE(0x08, unsigned_char) +HANDLE_DW_ATE(0x09, imaginary_float) +HANDLE_DW_ATE(0x0a, packed_decimal) +HANDLE_DW_ATE(0x0b, numeric_string) +HANDLE_DW_ATE(0x0c, edited) +HANDLE_DW_ATE(0x0d, signed_fixed) +HANDLE_DW_ATE(0x0e, unsigned_fixed) +HANDLE_DW_ATE(0x0f, decimal_float) +HANDLE_DW_ATE(0x10, UTF) + +// DWARF virtuality codes. +HANDLE_DW_VIRTUALITY(0x00, none) +HANDLE_DW_VIRTUALITY(0x01, virtual) +HANDLE_DW_VIRTUALITY(0x02, pure_virtual) + +#undef HANDLE_DW_TAG +#undef HANDLE_DW_OP +#undef HANDLE_DW_LANG +#undef HANDLE_DW_ATE +#undef HANDLE_DW_VIRTUALITY diff --git a/lib/coreclr/src/inc/llvm/Dwarf.h b/lib/coreclr/src/inc/llvm/Dwarf.h new file mode 100644 index 0000000000..5fa73e931c --- /dev/null +++ b/lib/coreclr/src/inc/llvm/Dwarf.h @@ -0,0 +1,711 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ============================================================================== +// LLVM Release License +// ============================================================================== +// University of Illinois/NCSA +// Open Source License +// +// Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. +// All rights reserved. +// +// Developed by: +// +// LLVM Team +// +// University of Illinois at Urbana-Champaign +// +// http://llvm.org +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal with +// 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: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimers. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimers in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the names of the LLVM Team, University of Illinois at +// Urbana-Champaign, nor the names of its contributors may be used to +// endorse or promote products derived from this Software without specific +// prior written permission. +// +// 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 +// CONTRIBUTORS 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 WITH THE +// SOFTWARE. + +//===----------------------------------------------------------------------===// +// +// \file +// \brief This file contains constants used for implementing Dwarf +// debug support. +// +// For details on the Dwarf specfication see the latest DWARF Debugging +// Information Format standard document on http://www.dwarfstd.org. This +// file often includes support for non-released standard features. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DWARF_H +#define LLVM_SUPPORT_DWARF_H + +//===----------------------------------------------------------------------===// +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 +// reference manual http://www.dwarfstd.org/. +// + +// Do not mix the following two enumerations sets. DW_TAG_invalid changes the +// enumeration base type. + +enum LLVMConstants : uint32_t { + // LLVM mock tags (see also llvm/Support/Dwarf.def). + DW_TAG_invalid = ~0U, // Tag for invalid results. + DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results. + DW_MACINFO_invalid = ~0U, // Macinfo type for invalid results. + + // Other constants. + DWARF_VERSION = 4, // Default dwarf version we output. + DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. + DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. + DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. +}; + +// Special ID values that distinguish a CIE from a FDE in DWARF CFI. +// Not inside an enum because a 64-bit value is needed. +const uint32_t DW_CIE_ID = UINT32_MAX; +const uint64_t DW64_CIE_ID = UINT64_MAX; + +enum Tag : uint16_t { +#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID, +#include "Dwarf.def" + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff, + DW_TAG_user_base = 0x1000 // Recommended base for user tags. +}; + +inline bool isType(Tag T) { + switch (T) { + case DW_TAG_array_type: + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_enumeration_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_string_type: + case DW_TAG_structure_type: + case DW_TAG_subroutine_type: + case DW_TAG_union_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_set_type: + case DW_TAG_subrange_type: + case DW_TAG_base_type: + case DW_TAG_const_type: + case DW_TAG_file_type: + case DW_TAG_packed_type: + case DW_TAG_volatile_type: + case DW_TAG_typedef: + return true; + default: + return false; + } +} + +enum Attribute : uint16_t { + // Attributes + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_signature = 0x69, + DW_AT_main_subprogram = 0x6a, + DW_AT_data_bit_offset = 0x6b, + DW_AT_const_expr = 0x6c, + DW_AT_enum_class = 0x6d, + DW_AT_linkage_name = 0x6e, + + // New in DWARF 5: + DW_AT_string_length_bit_size = 0x6f, + DW_AT_string_length_byte_size = 0x70, + DW_AT_rank = 0x71, + DW_AT_str_offsets_base = 0x72, + DW_AT_addr_base = 0x73, + DW_AT_ranges_base = 0x74, + DW_AT_dwo_id = 0x75, + DW_AT_dwo_name = 0x76, + DW_AT_reference = 0x77, + DW_AT_rvalue_reference = 0x78, + DW_AT_macros = 0x79, + + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + + DW_AT_MIPS_loop_begin = 0x2002, + DW_AT_MIPS_tail_loop_begin = 0x2003, + DW_AT_MIPS_epilog_begin = 0x2004, + DW_AT_MIPS_loop_unroll_factor = 0x2005, + DW_AT_MIPS_software_pipeline_depth = 0x2006, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_MIPS_stride = 0x2008, + DW_AT_MIPS_abstract_name = 0x2009, + DW_AT_MIPS_clone_origin = 0x200a, + DW_AT_MIPS_has_inlines = 0x200b, + DW_AT_MIPS_stride_byte = 0x200c, + DW_AT_MIPS_stride_elem = 0x200d, + DW_AT_MIPS_ptr_dopetype = 0x200e, + DW_AT_MIPS_allocatable_dopetype = 0x200f, + DW_AT_MIPS_assumed_shape_dopetype = 0x2010, + + // This one appears to have only been implemented by Open64 for + // fortran and may conflict with other extensions. + DW_AT_MIPS_assumed_size = 0x2011, + + // GNU extensions + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_GNU_template_name = 0x2110, + + DW_AT_GNU_odr_signature = 0x210f, + DW_AT_GNU_macros = 0x2119, + + // Extensions for Fission proposal. + DW_AT_GNU_dwo_name = 0x2130, + DW_AT_GNU_dwo_id = 0x2131, + DW_AT_GNU_ranges_base = 0x2132, + DW_AT_GNU_addr_base = 0x2133, + DW_AT_GNU_pubnames = 0x2134, + DW_AT_GNU_pubtypes = 0x2135, + DW_AT_GNU_discriminator = 0x2136, + + // Borland extensions. + DW_AT_BORLAND_property_read = 0x3b11, + DW_AT_BORLAND_property_write = 0x3b12, + DW_AT_BORLAND_property_implements = 0x3b13, + DW_AT_BORLAND_property_index = 0x3b14, + DW_AT_BORLAND_property_default = 0x3b15, + DW_AT_BORLAND_Delphi_unit = 0x3b20, + DW_AT_BORLAND_Delphi_class = 0x3b21, + DW_AT_BORLAND_Delphi_record = 0x3b22, + DW_AT_BORLAND_Delphi_metaclass = 0x3b23, + DW_AT_BORLAND_Delphi_constructor = 0x3b24, + DW_AT_BORLAND_Delphi_destructor = 0x3b25, + DW_AT_BORLAND_Delphi_anonymous_method = 0x3b26, + DW_AT_BORLAND_Delphi_interface = 0x3b27, + DW_AT_BORLAND_Delphi_ABI = 0x3b28, + DW_AT_BORLAND_Delphi_return = 0x3b29, + DW_AT_BORLAND_Delphi_frameptr = 0x3b30, + DW_AT_BORLAND_closure = 0x3b31, + + // LLVM project extensions. + DW_AT_LLVM_include_path = 0x3e00, + DW_AT_LLVM_config_macros = 0x3e01, + DW_AT_LLVM_isysroot = 0x3e02, + + // Apple extensions. + DW_AT_APPLE_optimized = 0x3fe1, + DW_AT_APPLE_flags = 0x3fe2, + DW_AT_APPLE_isa = 0x3fe3, + DW_AT_APPLE_block = 0x3fe4, + DW_AT_APPLE_major_runtime_vers = 0x3fe5, + DW_AT_APPLE_runtime_class = 0x3fe6, + DW_AT_APPLE_omit_frame_ptr = 0x3fe7, + DW_AT_APPLE_property_name = 0x3fe8, + DW_AT_APPLE_property_getter = 0x3fe9, + DW_AT_APPLE_property_setter = 0x3fea, + DW_AT_APPLE_property_attribute = 0x3feb, + DW_AT_APPLE_objc_complete_type = 0x3fec, + DW_AT_APPLE_property = 0x3fed +}; + +enum Form : uint16_t { + // Attribute form encodings + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + DW_FORM_sec_offset = 0x17, + DW_FORM_exprloc = 0x18, + DW_FORM_flag_present = 0x19, + DW_FORM_ref_sig8 = 0x20, + + // Extensions for Fission proposal + DW_FORM_GNU_addr_index = 0x1f01, + DW_FORM_GNU_str_index = 0x1f02, + + // Alternate debug sections proposal (output of "dwz" tool). + DW_FORM_GNU_ref_alt = 0x1f20, + DW_FORM_GNU_strp_alt = 0x1f21 +}; + +enum LocationAtom { +#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID, +#include "Dwarf.def" + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff +}; + +enum TypeKind { +#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID, +#include "Dwarf.def" + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff +}; + +enum DecimalSignEncoding { + // Decimal sign attribute values + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05 +}; + +enum EndianityEncoding { + // Endianity attribute values + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff +}; + +enum AccessAttribute { + // Accessibility codes + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03 +}; + +enum VisibilityAttribute { + // Visibility codes + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03 +}; + +enum VirtualityAttribute { +#define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID, +#include "Dwarf.def" + DW_VIRTUALITY_max = 0x02 +}; + +enum SourceLanguage { +#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID, +#include "Dwarf.def" + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff +}; + +enum CaseSensitivity { + // Identifier case codes + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03 +}; + +enum CallingConvention { + // Calling convention codes + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_lo_user = 0x40, + DW_CC_GNU_borland_fastcall_i386 = 0x41, + DW_CC_BORLAND_safecall = 0xb0, + DW_CC_BORLAND_stdcall = 0xb1, + DW_CC_BORLAND_pascal = 0xb2, + DW_CC_BORLAND_msfastcall = 0xb3, + DW_CC_BORLAND_msreturn = 0xb4, + DW_CC_BORLAND_thiscall = 0xb5, + DW_CC_BORLAND_fastcall = 0xb6, + DW_CC_hi_user = 0xff +}; + +enum InlineAttribute { + // Inline codes + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03 +}; + +enum ArrayDimensionOrdering { + // Array ordering + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01 +}; + +enum DiscriminantList { + // Discriminant descriptor values + DW_DSC_label = 0x00, + DW_DSC_range = 0x01 +}; + +enum LineNumberOps { + // Line Number Standard Opcode Encodings + DW_LNS_extended_op = 0x00, + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c +}; + +enum LineNumberExtendedOps { + // Line Number Extended Opcode Encodings + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_set_discriminator = 0x04, + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff +}; + +enum MacinfoRecordType { + // Macinfo Type Encodings + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff +}; + +enum MacroEntryType { + // Macro Information Entry Type Encodings + DW_MACRO_define = 0x01, + DW_MACRO_undef = 0x02, + DW_MACRO_start_file = 0x03, + DW_MACRO_end_file = 0x04, + DW_MACRO_define_indirect = 0x05, + DW_MACRO_undef_indirect = 0x06, + DW_MACRO_transparent_include = 0x07, + DW_MACRO_define_indirect_sup = 0x08, + DW_MACRO_undef_indirect_sup = 0x09, + DW_MACRO_transparent_include_sup = 0x0a, + DW_MACRO_define_indirectx = 0x0b, + DW_MACRO_undef_indirectx = 0x0c, + DW_MACRO_lo_user = 0xe0, + DW_MACRO_hi_user = 0xff +}; + +enum CallFrameInfo { + // Call frame instruction encodings + DW_CFA_extended = 0x00, + DW_CFA_nop = 0x00, + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_MIPS_advance_loc8 = 0x1d, + DW_CFA_GNU_window_save = 0x2d, + DW_CFA_GNU_args_size = 0x2e, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f +}; + +enum Constants { + // Children flag + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_signed = 0x08, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80 +}; + +// Constants for debug_loc.dwo in the DWARF5 Split Debug Info Proposal +enum LocationListEntry : unsigned char { + DW_LLE_end_of_list_entry, + DW_LLE_base_address_selection_entry, + DW_LLE_start_end_entry, + DW_LLE_start_length_entry, + DW_LLE_offset_pair_entry +}; + +/// Contstants for the DW_APPLE_PROPERTY_attributes attribute. +/// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind. +enum ApplePropertyAttributes { + // Apple Objective-C Property Attributes + DW_APPLE_PROPERTY_readonly = 0x01, + DW_APPLE_PROPERTY_getter = 0x02, + DW_APPLE_PROPERTY_assign = 0x04, + DW_APPLE_PROPERTY_readwrite = 0x08, + DW_APPLE_PROPERTY_retain = 0x10, + DW_APPLE_PROPERTY_copy = 0x20, + DW_APPLE_PROPERTY_nonatomic = 0x40, + DW_APPLE_PROPERTY_setter = 0x80, + DW_APPLE_PROPERTY_atomic = 0x100, + DW_APPLE_PROPERTY_weak = 0x200, + DW_APPLE_PROPERTY_strong = 0x400, + DW_APPLE_PROPERTY_unsafe_unretained = 0x800 +}; + +// Constants for the DWARF5 Accelerator Table Proposal +enum AcceleratorTable { + // Data layout descriptors. + DW_ATOM_null = 0u, // Marker as the end of a list of atoms. + DW_ATOM_die_offset = 1u, // DIE offset in the debug_info section. + DW_ATOM_cu_offset = 2u, // Offset of the compile unit header that contains the + // item in question. + DW_ATOM_die_tag = 3u, // A tag entry. + DW_ATOM_type_flags = 4u, // Set of flags for a type. + + // DW_ATOM_type_flags values. + + // Always set for C++, only set for ObjC if this is the @implementation for a + // class. + DW_FLAG_type_implementation = 2u, + + // Hash functions. + + // Daniel J. Bernstein hash. + DW_hash_function_djb = 0u +}; + +// Constants for the GNU pubnames/pubtypes extensions supporting gdb index. +enum GDBIndexEntryKind { + GIEK_NONE, + GIEK_TYPE, + GIEK_VARIABLE, + GIEK_FUNCTION, + GIEK_OTHER, + GIEK_UNUSED5, + GIEK_UNUSED6, + GIEK_UNUSED7 +}; + +enum GDBIndexEntryLinkage { + GIEL_EXTERNAL, + GIEL_STATIC +}; + +/// \defgroup DwarfConstantsDumping Dwarf constants dumping functions +/// +/// All these functions map their argument's value back to the +/// corresponding enumerator name or return nullptr if the value isn't +/// known. +/// +/// @{ +const char *TagString(unsigned Tag); +const char *ChildrenString(unsigned Children); +const char *AttributeString(unsigned Attribute); +const char *FormEncodingString(unsigned Encoding); +const char *OperationEncodingString(unsigned Encoding); +const char *AttributeEncodingString(unsigned Encoding); +const char *DecimalSignString(unsigned Sign); +const char *EndianityString(unsigned Endian); +const char *AccessibilityString(unsigned Access); +const char *VisibilityString(unsigned Visibility); +const char *VirtualityString(unsigned Virtuality); +const char *LanguageString(unsigned Language); +const char *CaseString(unsigned Case); +const char *ConventionString(unsigned Convention); +const char *InlineCodeString(unsigned Code); +const char *ArrayOrderString(unsigned Order); +const char *DiscriminantString(unsigned Discriminant); +const char *LNStandardString(unsigned Standard); +const char *LNExtendedString(unsigned Encoding); +const char *MacinfoString(unsigned Encoding); +const char *CallFrameString(unsigned Encoding); +const char *ApplePropertyString(unsigned); +const char *AtomTypeString(unsigned Atom); +const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); +const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); +/// @} + +/// \brief Returns the symbolic string representing Val when used as a value +/// for attribute Attr. +const char *AttributeValueString(uint16_t Attr, unsigned Val); + +/// \brief Decsribes an entry of the various gnu_pub* debug sections. +/// +/// The gnu_pub* kind looks like: +/// +/// 0-3 reserved +/// 4-6 symbol kind +/// 7 0 == global, 1 == static +/// +/// A gdb_index descriptor includes the above kind, shifted 24 bits up with the +/// offset of the cu within the debug_info section stored in those 24 bits. +struct PubIndexEntryDescriptor { + GDBIndexEntryKind Kind; + GDBIndexEntryLinkage Linkage; + PubIndexEntryDescriptor(GDBIndexEntryKind Kind, GDBIndexEntryLinkage Linkage) + : Kind(Kind), Linkage(Linkage) {} + /* implicit */ PubIndexEntryDescriptor(GDBIndexEntryKind Kind) + : Kind(Kind), Linkage(GIEL_EXTERNAL) {} + explicit PubIndexEntryDescriptor(uint8_t Value) + : Kind(static_cast((Value & KIND_MASK) >> + KIND_OFFSET)), + Linkage(static_cast((Value & LINKAGE_MASK) >> + LINKAGE_OFFSET)) {} + uint8_t toBits() { return Kind << KIND_OFFSET | Linkage << LINKAGE_OFFSET; } + +private: + enum { + KIND_OFFSET = 4, + KIND_MASK = 7 << KIND_OFFSET, + LINKAGE_OFFSET = 7, + LINKAGE_MASK = 1 << LINKAGE_OFFSET + }; +}; + +#endif diff --git a/lib/coreclr/src/inc/llvm/ELF.h b/lib/coreclr/src/inc/llvm/ELF.h new file mode 100644 index 0000000000..76c7824208 --- /dev/null +++ b/lib/coreclr/src/inc/llvm/ELF.h @@ -0,0 +1,1273 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ============================================================================== +// LLVM Release License +// ============================================================================== +// University of Illinois/NCSA +// Open Source License +// +// Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. +// All rights reserved. +// +// Developed by: +// +// LLVM Team +// +// University of Illinois at Urbana-Champaign +// +// http://llvm.org +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal with +// 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: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimers. +// +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimers in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the names of the LLVM Team, University of Illinois at +// Urbana-Champaign, nor the names of its contributors may be used to +// endorse or promote products derived from this Software without specific +// prior written permission. +// +// 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 +// CONTRIBUTORS 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 WITH THE +// SOFTWARE. + +//===----------------------------------------------------------------------===// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on the Tool +// Interface Standard (TIS) Executable and Linking Format (ELF) Specification +// Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format +// Version 1.5, Draft 2, May 1998 as well as OpenBSD header files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ELF_H +#define LLVM_SUPPORT_ELF_H + +typedef uint32_t Elf32_Addr; // Program address +typedef uint32_t Elf32_Off; // File offset +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; + +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; + +// Object file magic string. +static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; + +// e_ident size and indices. +enum { + EI_MAG0 = 0, // File identification index. + EI_MAG1 = 1, // File identification index. + EI_MAG2 = 2, // File identification index. + EI_MAG3 = 3, // File identification index. + EI_CLASS = 4, // File class. + EI_DATA = 5, // Data encoding. + EI_VERSION = 6, // File version. + EI_OSABI = 7, // OS/ABI identification. + EI_ABIVERSION = 8, // ABI version. + EI_PAD = 9, // Start of padding bytes. + EI_NIDENT = 16 // Number of bytes in e_ident. +}; + +struct Elf32_Ehdr { + unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes + Elf32_Half e_type; // Type of file (see ET_* below) + Elf32_Half e_machine; // Required architecture for this file (see EM_*) + Elf32_Word e_version; // Must be equal to 1 + Elf32_Addr e_entry; // Address to jump to in order to start program + Elf32_Off e_phoff; // Program header table's file offset, in bytes + Elf32_Off e_shoff; // Section header table's file offset, in bytes + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // Size of ELF header, in bytes + Elf32_Half e_phentsize; // Size of an entry in the program header table + Elf32_Half e_phnum; // Number of entries in the program header table + Elf32_Half e_shentsize; // Size of an entry in the section header table + Elf32_Half e_shnum; // Number of entries in the section header table + Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } + Elf32_Ehdr(); +}; + +// 64-bit ELF header. Fields are the same as for ELF32, but with different +// types (see above). +struct Elf64_Ehdr { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; + bool checkMagic() const { + return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; + } + unsigned char getFileClass() const { return e_ident[EI_CLASS]; } + unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } + Elf64_Ehdr(); +}; + +// File types +enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific +}; + +// Versioning +enum { + EV_NONE = 0, + EV_CURRENT = 1 +}; + +// Machine architectures +// See current registered ELF machine architectures at: +// http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html +enum { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_IAMCU = 6, // Intel MCU + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_S370 = 9, // IBM System/370 + EM_MIPS_RS3_LE = 10, // MIPS RS3000 Little-endian + EM_PARISC = 15, // Hewlett-Packard PA-RISC + EM_VPP500 = 17, // Fujitsu VPP500 + EM_SPARC32PLUS = 18, // Enhanced instruction set SPARC + EM_960 = 19, // Intel 80960 + EM_PPC = 20, // PowerPC + EM_PPC64 = 21, // PowerPC64 + EM_S390 = 22, // IBM System/390 + EM_SPU = 23, // IBM SPU/SPC + EM_V800 = 36, // NEC V800 + EM_FR20 = 37, // Fujitsu FR20 + EM_RH32 = 38, // TRW RH-32 + EM_RCE = 39, // Motorola RCE + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SH = 42, // Hitachi SH + EM_SPARCV9 = 43, // SPARC V9 + EM_TRICORE = 44, // Siemens TriCore + EM_ARC = 45, // Argonaut RISC Core + EM_H8_300 = 46, // Hitachi H8/300 + EM_H8_300H = 47, // Hitachi H8/300H + EM_H8S = 48, // Hitachi H8S + EM_H8_500 = 49, // Hitachi H8/500 + EM_IA_64 = 50, // Intel IA-64 processor architecture + EM_MIPS_X = 51, // Stanford MIPS-X + EM_COLDFIRE = 52, // Motorola ColdFire + EM_68HC12 = 53, // Motorola M68HC12 + EM_MMA = 54, // Fujitsu MMA Multimedia Accelerator + EM_PCP = 55, // Siemens PCP + EM_NCPU = 56, // Sony nCPU embedded RISC processor + EM_NDR1 = 57, // Denso NDR1 microprocessor + EM_STARCORE = 58, // Motorola Star*Core processor + EM_ME16 = 59, // Toyota ME16 processor + EM_ST100 = 60, // STMicroelectronics ST100 processor + EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor family + EM_X86_64 = 62, // AMD x86-64 architecture + EM_PDSP = 63, // Sony DSP Processor + EM_PDP10 = 64, // Digital Equipment Corp. PDP-10 + EM_PDP11 = 65, // Digital Equipment Corp. PDP-11 + EM_FX66 = 66, // Siemens FX66 microcontroller + EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller + EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller + EM_68HC16 = 69, // Motorola MC68HC16 Microcontroller + EM_68HC11 = 70, // Motorola MC68HC11 Microcontroller + EM_68HC08 = 71, // Motorola MC68HC08 Microcontroller + EM_68HC05 = 72, // Motorola MC68HC05 Microcontroller + EM_SVX = 73, // Silicon Graphics SVx + EM_ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller + EM_VAX = 75, // Digital VAX + EM_CRIS = 76, // Axis Communications 32-bit embedded processor + EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded processor + EM_FIREPATH = 78, // Element 14 64-bit DSP Processor + EM_ZSP = 79, // LSI Logic 16-bit DSP Processor + EM_MMIX = 80, // Donald Knuth's educational 64-bit processor + EM_HUANY = 81, // Harvard University machine-independent object files + EM_PRISM = 82, // SiTera Prism + EM_AVR = 83, // Atmel AVR 8-bit microcontroller + EM_FR30 = 84, // Fujitsu FR30 + EM_D10V = 85, // Mitsubishi D10V + EM_D30V = 86, // Mitsubishi D30V + EM_V850 = 87, // NEC v850 + EM_M32R = 88, // Mitsubishi M32R + EM_MN10300 = 89, // Matsushita MN10300 + EM_MN10200 = 90, // Matsushita MN10200 + EM_PJ = 91, // picoJava + EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor + EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old + // spelling/synonym: EM_ARC_A5) + EM_XTENSA = 94, // Tensilica Xtensa Architecture + EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor + EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor + EM_NS32K = 97, // National Semiconductor 32000 series + EM_TPC = 98, // Tenor Network TPC processor + EM_SNP1K = 99, // Trebia SNP 1000 processor + EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 + EM_IP2K = 101, // Ubicom IP2xxx microcontroller family + EM_MAX = 102, // MAX Processor + EM_CR = 103, // National Semiconductor CompactRISC microprocessor + EM_F2MC16 = 104, // Fujitsu F2MC16 + EM_MSP430 = 105, // Texas Instruments embedded microcontroller msp430 + EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) processor + EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors + EM_SEP = 108, // Sharp embedded microprocessor + EM_ARCA = 109, // Arca RISC Microprocessor + EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC + // of Peking University + EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU + EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor + EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor + EM_CRX = 114, // National Semiconductor CompactRISC CRX + EM_XGATE = 115, // Motorola XGATE embedded processor + EM_C166 = 116, // Infineon C16x/XC16x processor + EM_M16C = 117, // Renesas M16C series microprocessors + EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal + // Controller + EM_CE = 119, // Freescale Communication Engine RISC core + EM_M32C = 120, // Renesas M32C series microprocessors + EM_TSK3000 = 131, // Altium TSK3000 core + EM_RS08 = 132, // Freescale RS08 embedded processor + EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP + // processors + EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor + EM_SCORE7 = 135, // Sunplus S+core7 RISC processor + EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor + EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor + EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture + EM_SE_C17 = 139, // Seiko Epson C17 family + EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP family + EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP family + EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP family + EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor + EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor + EM_R32C = 162, // Renesas R32C series microprocessors + EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family + EM_HEXAGON = 164, // Qualcomm Hexagon processor + EM_8051 = 165, // Intel 8051 and variants + EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable + // and extensible RISC processors + EM_NDS32 = 167, // Andes Technology compact code size embedded RISC + // processor family + EM_ECOG1 = 168, // Cyan Technology eCOG1X family + EM_ECOG1X = 168, // Cyan Technology eCOG1X family + EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers + EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor + EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor + EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture + EM_RX = 173, // Renesas RX family + EM_METAG = 174, // Imagination Technologies META processor + // architecture + EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture + EM_ECOG16 = 176, // Cyan Technology eCOG16 family + EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit + // microprocessor + EM_ETPU = 178, // Freescale Extended Time Processing Unit + EM_SLE9X = 179, // Infineon Technologies SLE9X core + EM_L10M = 180, // Intel L10M + EM_K10M = 181, // Intel K10M + EM_AARCH64 = 183, // ARM AArch64 + EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family + EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller + EM_TILE64 = 187, // Tilera TILE64 multicore architecture family + EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family + EM_CUDA = 190, // NVIDIA CUDA architecture + EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family + EM_CLOUDSHIELD = 192, // CloudShield architecture family + EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family + EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family + EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 + EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core + EM_RL78 = 197, // Renesas RL78 family + EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor + EM_78KOR = 199, // Renesas 78KOR family + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family + EM_INTEL205 = 205, // Reserved by Intel + EM_INTEL206 = 206, // Reserved by Intel + EM_INTEL207 = 207, // Reserved by Intel + EM_INTEL208 = 208, // Reserved by Intel + EM_INTEL209 = 209, // Reserved by Intel + EM_KM32 = 210, // KM211 KM32 32-bit processor + EM_KMX32 = 211, // KM211 KMX32 32-bit processor + EM_KMX16 = 212, // KM211 KMX16 16-bit processor + EM_KMX8 = 213, // KM211 KMX8 8-bit processor + EM_KVARC = 214, // KM211 KVARC processor + EM_CDP = 215, // Paneve CDP architecture family + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // iCelero CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family + EM_AMDGPU = 224, // AMD GPU architecture + + // A request has been made to the maintainer of the official registry for + // such numbers for an official value for WebAssembly. As soon as one is + // allocated, this enum will be updated to use it. + EM_WEBASSEMBLY = 0x4157, // WebAssembly architecture +}; + +// Object file classes. +enum { + ELFCLASSNONE = 0, + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file +}; + +// Object file byte orderings. +enum { + ELFDATANONE = 0, // Invalid data encoding. + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file +}; + +// OS ABI identification. +enum { + ELFOSABI_NONE = 0, // UNIX System V ABI + ELFOSABI_HPUX = 1, // HP-UX operating system + ELFOSABI_NETBSD = 2, // NetBSD + ELFOSABI_GNU = 3, // GNU/Linux + ELFOSABI_LINUX = 3, // Historical alias for ELFOSABI_GNU. + ELFOSABI_HURD = 4, // GNU/Hurd + ELFOSABI_SOLARIS = 6, // Solaris + ELFOSABI_AIX = 7, // AIX + ELFOSABI_IRIX = 8, // IRIX + ELFOSABI_FREEBSD = 9, // FreeBSD + ELFOSABI_TRU64 = 10, // TRU64 UNIX + ELFOSABI_MODESTO = 11, // Novell Modesto + ELFOSABI_OPENBSD = 12, // OpenBSD + ELFOSABI_OPENVMS = 13, // OpenVMS + ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel + ELFOSABI_AROS = 15, // AROS + ELFOSABI_FENIXOS = 16, // FenixOS + ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI + ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 + ELFOSABI_AMDGPU_HSA = 64, // AMD HSA runtime + ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 + ELFOSABI_ARM = 97, // ARM + ELFOSABI_STANDALONE = 255 // Standalone (embedded) application +}; + +#define ELF_RELOC(name, value) name = value, + +// Specific e_flags for PPC64 +enum { + // e_flags bits specifying ABI: + // 1 for original ABI using function descriptors, + // 2 for revised ABI without function descriptors, + // 0 for unspecified or not using any features affected by the differences. + EF_PPC64_ABI = 3 +}; + +// Special values for the st_other field in the symbol table entry for PPC64. +enum { + STO_PPC64_LOCAL_BIT = 5, + STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT) +}; +static inline int64_t +decodePPC64LocalEntryOffset(unsigned Other) { + unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; + return ((1 << Val) >> 2) << 2; +} +static inline unsigned +encodePPC64LocalEntryOffset(int64_t Offset) { + unsigned Val = (Offset >= 4 * 4 + ? (Offset >= 8 * 4 + ? (Offset >= 16 * 4 ? 6 : 5) + : 4) + : (Offset >= 2 * 4 + ? 3 + : (Offset >= 1 * 4 ? 2 : 0))); + return Val << STO_PPC64_LOCAL_BIT; +} + +// ARM Specific e_flags +enum : unsigned { + EF_ARM_SOFT_FLOAT = 0x00000200U, + EF_ARM_VFP_FLOAT = 0x00000400U, + EF_ARM_EABI_UNKNOWN = 0x00000000U, + EF_ARM_EABI_VER1 = 0x01000000U, + EF_ARM_EABI_VER2 = 0x02000000U, + EF_ARM_EABI_VER3 = 0x03000000U, + EF_ARM_EABI_VER4 = 0x04000000U, + EF_ARM_EABI_VER5 = 0x05000000U, + EF_ARM_EABIMASK = 0xFF000000U +}; + +// AVR specific e_flags +enum : unsigned { + EF_AVR_ARCH_AVR1 = 1, + EF_AVR_ARCH_AVR2 = 2, + EF_AVR_ARCH_AVR25 = 25, + EF_AVR_ARCH_AVR3 = 3, + EF_AVR_ARCH_AVR31 = 31, + EF_AVR_ARCH_AVR35 = 35, + EF_AVR_ARCH_AVR4 = 4, + EF_AVR_ARCH_AVR5 = 5, + EF_AVR_ARCH_AVR51 = 51, + EF_AVR_ARCH_AVR6 = 6, + EF_AVR_ARCH_AVRTINY = 100, + EF_AVR_ARCH_XMEGA1 = 101, + EF_AVR_ARCH_XMEGA2 = 102, + EF_AVR_ARCH_XMEGA3 = 103, + EF_AVR_ARCH_XMEGA4 = 104, + EF_AVR_ARCH_XMEGA5 = 105, + EF_AVR_ARCH_XMEGA6 = 106, + EF_AVR_ARCH_XMEGA7 = 107 +}; + +// Mips Specific e_flags +enum : unsigned { + EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions + EF_MIPS_PIC = 0x00000002, // Position independent code + EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code + EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI + EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine + // in 32-bit mode + EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine + // but uses 64-bit FP registers + EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding + + // ABI flags + EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. + EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. + EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. + EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. + + // MIPS machine variant + EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 + EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 + EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 + EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650 + EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120 + EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181 + EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1 + EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon + EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr + EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2 + EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3 + EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400 + EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900 + EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500 + EF_MIPS_MACH_9000 = 0x00990000, // Unknown + EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E + EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F + EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A + EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask + + // ARCH_ASE + EF_MIPS_MICROMIPS = 0x02000000, // microMIPS + EF_MIPS_ARCH_ASE_M16 = + 0x04000000, // Has Mips-16 ISA extensions + EF_MIPS_ARCH_ASE_MDMX = + 0x08000000, // Has MDMX multimedia extensions + EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags + + // ARCH + EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set + EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set + EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set + EF_MIPS_ARCH_4 = 0x30000000, // MIPS4 instruction set + EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set + EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h + EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h + EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5 + EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5 + EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 + EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 + EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant +}; + +// Special values for the st_other field in the symbol table entry for MIPS. +enum { + STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional + STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record + STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC + STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips + STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 +}; + +// .MIPS.options section descriptor kinds +enum { + ODK_NULL = 0, // Undefined + ODK_REGINFO = 1, // Register usage information + ODK_EXCEPTIONS = 2, // Exception processing options + ODK_PAD = 3, // Section padding options + ODK_HWPATCH = 4, // Hardware patches applied + ODK_FILL = 5, // Linker fill value + ODK_TAGS = 6, // Space for tool identification + ODK_HWAND = 7, // Hardware AND patches applied + ODK_HWOR = 8, // Hardware OR patches applied + ODK_GP_GROUP = 9, // GP group to use for text/data sections + ODK_IDENT = 10, // ID information + ODK_PAGESIZE = 11 // Page size information +}; + +// Hexagon-specific e_flags +enum { + // Object processor version flags, bits[11:0] + EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 + EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 + EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 + EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 + EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55 + EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 + + // Highest ISA version flags + EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0] + // of e_flags + EF_HEXAGON_ISA_V2 = 0x00000010, // Hexagon V2 ISA + EF_HEXAGON_ISA_V3 = 0x00000020, // Hexagon V3 ISA + EF_HEXAGON_ISA_V4 = 0x00000030, // Hexagon V4 ISA + EF_HEXAGON_ISA_V5 = 0x00000040, // Hexagon V5 ISA + EF_HEXAGON_ISA_V55 = 0x00000050, // Hexagon V55 ISA + EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA +}; + +// Hexagon-specific section indexes for common small data +enum { + SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes + SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access + SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access + SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access + SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access +}; + + +#undef ELF_RELOC + +// Section header. +struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) + Elf32_Word sh_type; // Section type (SHT_*) + Elf32_Word sh_flags; // Section flags (SHF_*) + Elf32_Addr sh_addr; // Address where section is to be loaded + Elf32_Off sh_offset; // File offset of section data, in bytes + Elf32_Word sh_size; // Size of section, in bytes + Elf32_Word sh_link; // Section type-specific header table index link + Elf32_Word sh_info; // Section type-specific extra information + Elf32_Word sh_addralign; // Section address alignment + Elf32_Word sh_entsize; // Size of records contained within the section +}; + +// Section header for ELF64 - same fields as ELF32, different types. +struct Elf64_Shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + +// Special section indices. +enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_LOOS = 0xff20, // Lowest operating system-specific index + SHN_HIOS = 0xff3f, // Highest operating system-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE + SHN_HIRESERVE = 0xffff // Highest reserved index +}; + +// Section types. +enum : unsigned { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_INIT_ARRAY = 14, // Pointers to initialization functions. + SHT_FINI_ARRAY = 15, // Pointers to termination functions. + SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. + SHT_GROUP = 17, // Section group. + SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. + SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. + SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. + SHT_GNU_verneed = 0x6ffffffe, // GNU version references. + SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. + SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. + // Fixme: All this is duplicated in MCSectionELF. Why?? + // Exception Index table + SHT_ARM_EXIDX = 0x70000001U, + // BPABI DLL dynamic linking pre-emption map + SHT_ARM_PREEMPTMAP = 0x70000002U, + // Object file compatibility attributes + SHT_ARM_ATTRIBUTES = 0x70000003U, + SHT_ARM_DEBUGOVERLAY = 0x70000004U, + SHT_ARM_OVERLAYSECTION = 0x70000005U, + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes + SHT_X86_64_UNWIND = 0x70000001, // Unwind information + + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. +}; + +// Section flags. +enum : unsigned { + // Section data should be writable during execution. + SHF_WRITE = 0x1, + + // Section occupies memory during program execution. + SHF_ALLOC = 0x2, + + // Section contains executable machine instructions. + SHF_EXECINSTR = 0x4, + + // The data in this section may be merged. + SHF_MERGE = 0x10, + + // The data in this section is null-terminated strings. + SHF_STRINGS = 0x20, + + // A field in this section holds a section header table index. + SHF_INFO_LINK = 0x40U, + + // Adds special ordering requirements for link editors. + SHF_LINK_ORDER = 0x80U, + + // This section requires special OS-specific processing to avoid incorrect + // behavior. + SHF_OS_NONCONFORMING = 0x100U, + + // This section is a member of a section group. + SHF_GROUP = 0x200U, + + // This section holds Thread-Local Storage. + SHF_TLS = 0x400U, + + // This section is excluded from the final executable or shared library. + SHF_EXCLUDE = 0x80000000U, + + // Start of target-specific flags. + + /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped + /// together by the linker to form the constant pool and the cp register is + /// set to the start of the constant pool by the boot code. + XCORE_SHF_CP_SECTION = 0x800U, + + /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped + /// together by the linker to form the data section and the dp register is + /// set to the start of the section by the boot code. + XCORE_SHF_DP_SECTION = 0x1000U, + + SHF_MASKOS = 0x0ff00000, + + // Bits indicating processor-specific flags. + SHF_MASKPROC = 0xf0000000, + + // If an object file section does not have this flag set, then it may not hold + // more than 2GB and can be freely referred to in objects using smaller code + // models. Otherwise, only objects using larger code models can refer to them. + // For example, a medium code model object can refer to data in a section that + // sets this flag besides being able to refer to data in a section that does + // not set it; likewise, a small code model object can refer only to code in a + // section that does not set this flag. + SHF_X86_64_LARGE = 0x10000000, + + // All sections with the GPREL flag are grouped into a global data area + // for faster accesses + SHF_HEX_GPREL = 0x10000000, + + // Section contains text/data which may be replicated in other sections. + // Linker must retain only one copy. + SHF_MIPS_NODUPES = 0x01000000, + + // Linker must generate implicit hidden weak names. + SHF_MIPS_NAMES = 0x02000000, + + // Section data local to process. + SHF_MIPS_LOCAL = 0x04000000, + + // Do not strip this section. + SHF_MIPS_NOSTRIP = 0x08000000, + + // Section must be part of global data area. + SHF_MIPS_GPREL = 0x10000000, + + // This section should be merged. + SHF_MIPS_MERGE = 0x20000000, + + // Address size to be inferred from section entry size. + SHF_MIPS_ADDR = 0x40000000, + + // Section data is string data by default. + SHF_MIPS_STRING = 0x80000000, + + SHF_AMDGPU_HSA_GLOBAL = 0x00100000, + SHF_AMDGPU_HSA_READONLY = 0x00200000, + SHF_AMDGPU_HSA_CODE = 0x00400000, + SHF_AMDGPU_HSA_AGENT = 0x00800000 +}; + +// Section Group Flags +enum : unsigned { + GRP_COMDAT = 0x1, + GRP_MASKOS = 0x0ff00000, + GRP_MASKPROC = 0xf0000000 +}; + +// Symbol table entries for ELF32. +struct Elf32_Sym { + Elf32_Word st_name; // Symbol name (index into string table) + Elf32_Addr st_value; // Value or address associated with the symbol + Elf32_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf32_Half st_shndx; // Which section (header table index) it's defined in + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// Symbol table entries for ELF64. +struct Elf64_Sym { + Elf64_Word st_name; // Symbol name (index into string table) + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf64_Half st_shndx; // Which section (header tbl index) it's defined in + Elf64_Addr st_value; // Value or address associated with the symbol + Elf64_Xword st_size; // Size of the symbol + + // These accessors and mutators are identical to those defined for ELF32 + // symbol table entries. + unsigned char getBinding() const { return st_info >> 4; } + unsigned char getType() const { return st_info & 0x0f; } + void setBinding(unsigned char b) { setBindingAndType(b, getType()); } + void setType(unsigned char t) { setBindingAndType(getBinding(), t); } + void setBindingAndType(unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// The size (in bytes) of symbol table entries. +enum { + SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size + SYMENTRY_SIZE64 = 24 // 64-bit symbol entry size. +}; + +// Symbol bindings. +enum { + STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def + STB_GLOBAL = 1, // Global symbol, visible to all object files being combined + STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_GNU_UNIQUE = 10, + STB_LOOS = 10, // Lowest operating system-specific binding type + STB_HIOS = 12, // Highest operating system-specific binding type + STB_LOPROC = 13, // Lowest processor-specific binding type + STB_HIPROC = 15 // Highest processor-specific binding type +}; + +// Symbol types. +enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4, // Local, absolute symbol that refers to a file + STT_COMMON = 5, // An uninitialized common block + STT_TLS = 6, // Thread local data object + STT_GNU_IFUNC = 10, // GNU indirect function + STT_LOOS = 10, // Lowest operating system-specific symbol type + STT_HIOS = 12, // Highest operating system-specific symbol type + STT_LOPROC = 13, // Lowest processor-specific symbol type + STT_HIPROC = 15, // Highest processor-specific symbol type + + // AMDGPU symbol types + STT_AMDGPU_HSA_KERNEL = 10, + STT_AMDGPU_HSA_INDIRECT_FUNCTION = 11, + STT_AMDGPU_HSA_METADATA = 12 +}; + +enum { + STV_DEFAULT = 0, // Visibility is specified by binding type + STV_INTERNAL = 1, // Defined by processor supplements + STV_HIDDEN = 2, // Not visible to other components + STV_PROTECTED = 3 // Visible in other components but not preemptable +}; + +// Symbol number. +enum { + STN_UNDEF = 0 +}; + +// Special relocation symbols used in the MIPS64 ELF relocation entries +enum { + RSS_UNDEF = 0, // None + RSS_GP = 1, // Value of gp + RSS_GP0 = 2, // Value of gp used to create object being relocated + RSS_LOC = 3 // Address of location being relocated +}; + +// Relocation entry, without explicit addend. +struct Elf32_Rel { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry with explicit addend. +struct Elf32_Rela { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + Elf32_Sword r_addend; // Compute value for relocatable field by adding this + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol() const { return (r_info >> 8); } + unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } + void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + } +}; + +// Relocation entry, without explicit addend. +struct Elf64_Rel { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); + } + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); + } +}; + +// Relocation entry with explicit addend. +struct Elf64_Rela { + Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). + Elf64_Xword r_info; // Symbol table index and type of relocation to apply. + Elf64_Sxword r_addend; // Compute value for relocatable field by adding this. + + // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, + // and ELF64_R_INFO macros defined in the ELF specification: + Elf64_Word getSymbol() const { return (r_info >> 32); } + Elf64_Word getType() const { + return (Elf64_Word) (r_info & 0xffffffffL); + } + void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } + void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } + void setSymbolAndType(Elf64_Word s, Elf64_Word t) { + r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); + } +}; + +// Program header for ELF32. +struct Elf32_Phdr { + Elf32_Word p_type; // Type of segment + Elf32_Off p_offset; // File offset where segment is located, in bytes + Elf32_Addr p_vaddr; // Virtual address of beginning of segment + Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Segment alignment constraint +}; + +// Program header for ELF64. +struct Elf64_Phdr { + Elf64_Word p_type; // Type of segment + Elf64_Word p_flags; // Segment flags + Elf64_Off p_offset; // File offset where segment is located, in bytes + Elf64_Addr p_vaddr; // Virtual address of beginning of segment + Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) + Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf64_Xword p_align; // Segment alignment constraint +}; + +// Segment types. +enum { + PT_NULL = 0, // Unused segment. + PT_LOAD = 1, // Loadable segment. + PT_DYNAMIC = 2, // Dynamic linking information. + PT_INTERP = 3, // Interpreter pathname. + PT_NOTE = 4, // Auxiliary information. + PT_SHLIB = 5, // Reserved. + PT_PHDR = 6, // The program header table itself. + PT_TLS = 7, // The thread-local storage template. + PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff, // Highest processor-specific program hdr entry type. + + // x86-64 program header types. + // These all contain stack unwind tables. + PT_GNU_EH_FRAME = 0x6474e550, + PT_SUNW_EH_FRAME = 0x6474e550, + PT_SUNW_UNWIND = 0x6464e550, + + PT_GNU_STACK = 0x6474e551, // Indicates stack executability. + PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. + + // ARM program header types. + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info + // These all contain stack unwind tables. + PT_ARM_EXIDX = 0x70000001, + PT_ARM_UNWIND = 0x70000001, + + // MIPS program header types. + PT_MIPS_REGINFO = 0x70000000, // Register usage information. + PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. + PT_MIPS_OPTIONS = 0x70000002, // Options segment. + PT_MIPS_ABIFLAGS = 0x70000003, // Abiflags segment. + + // AMDGPU program header types. + PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM = 0x60000000, + PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT = 0x60000001, + PT_AMDGPU_HSA_LOAD_READONLY_AGENT = 0x60000002, + PT_AMDGPU_HSA_LOAD_CODE_AGENT = 0x60000003, + + // WebAssembly program header types. + PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions. +}; + +// Segment flag bits. +enum : unsigned { + PF_X = 1, // Execute + PF_W = 2, // Write + PF_R = 4, // Read + PF_MASKOS = 0x0ff00000,// Bits for operating system-specific semantics. + PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics. +}; + +// Dynamic table entry for ELF32. +struct Elf32_Dyn +{ + Elf32_Sword d_tag; // Type of dynamic table entry. + union + { + Elf32_Word d_val; // Integer value of entry. + Elf32_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry for ELF64. +struct Elf64_Dyn +{ + Elf64_Sxword d_tag; // Type of dynamic table entry. + union + { + Elf64_Xword d_val; // Integer value of entry. + Elf64_Addr d_ptr; // Pointer value of entry. + } d_un; +}; + +// Dynamic table entry tags. +enum { + DT_NULL = 0, // Marks end of dynamic array. + DT_NEEDED = 1, // String table offset of needed library. + DT_PLTRELSZ = 2, // Size of relocation entries in PLT. + DT_PLTGOT = 3, // Address associated with linkage table. + DT_HASH = 4, // Address of symbolic hash table. + DT_STRTAB = 5, // Address of dynamic string table. + DT_SYMTAB = 6, // Address of dynamic symbol table. + DT_RELA = 7, // Address of relocation table (Rela entries). + DT_RELASZ = 8, // Size of Rela relocation table. + DT_RELAENT = 9, // Size of a Rela relocation entry. + DT_STRSZ = 10, // Total size of the string table. + DT_SYMENT = 11, // Size of a symbol table entry. + DT_INIT = 12, // Address of initialization function. + DT_FINI = 13, // Address of termination function. + DT_SONAME = 14, // String table offset of a shared objects name. + DT_RPATH = 15, // String table offset of library search path. + DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. + DT_REL = 17, // Address of relocation table (Rel entries). + DT_RELSZ = 18, // Size of Rel relocation table. + DT_RELENT = 19, // Size of a Rel relocation entry. + DT_PLTREL = 20, // Type of relocation entry used for linking. + DT_DEBUG = 21, // Reserved for debugger. + DT_TEXTREL = 22, // Relocations exist for non-writable segments. + DT_JMPREL = 23, // Address of relocations associated with PLT. + DT_BIND_NOW = 24, // Process all relocations before execution. + DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. + DT_FINI_ARRAY = 26, // Pointer to array of termination functions. + DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. + DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. + DT_RUNPATH = 29, // String table offset of lib search path. + DT_FLAGS = 30, // Flags. + DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules + // for the interpretation of the d_un union. + + DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. + DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. + + DT_LOOS = 0x60000000, // Start of environment specific tags. + DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. + DT_LOPROC = 0x70000000, // Start of processor specific tags. + DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + + DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. + DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. + DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. + + DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. + DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. + DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. + DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. + DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. + DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED. + + // Mips specific dynamic table entry tags. + DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime + // linker interface. + DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp. + DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings + // and common sizes. + DT_MIPS_IVERSION = 0x70000004, // Index of version string + // in string table. + DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags. + DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment. + DT_MIPS_MSYM = 0x70000007, // Address of .msym section. + DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section. + DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section. + DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset + // table entries. + DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries + // in the .conflict section. + DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries + // in the .liblist section. + DT_MIPS_SYMTABNO = 0x70000011, // Number of entries + // in the .dynsym section. + DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol + // not referenced locally. + DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol + // in global offset table. + DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries + // in global offset table. + DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map, + // used for debugging. + DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition. + DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries + // in DT_MIPS_DELTA_CLASS. + DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances. + DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries + // in DT_MIPS_DELTA_INSTANCE. + DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations. + DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries + // in DT_MIPS_DELTA_RELOC. + DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta + // relocations refer to. + DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries + // in DT_MIPS_DELTA_SYM. + DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold + // class declarations. + DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries + // in DT_MIPS_DELTA_CLASSSYM. + DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information + // about C++ flavor. + DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information. + DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib + DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE + // for a segment + DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE + // for a local symbol + DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE + // for a hidden symbol + DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE + // for a protected symbol + DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'. + DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'. + DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown. + DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section. + DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve + // function stored in the GOT. + DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added + // by rld on dlopen() calls. + DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation + // section (O32). + DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs. + DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic. + DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. + DT_MIPS_RWPLT = 0x70000034, // Points to the base + // of a writable PLT. + DT_MIPS_RLD_MAP_REL = 0x70000035 // Relative offset of run time loader + // map, used for debugging. +}; + +// DT_FLAGS values. +enum { + DF_ORIGIN = 0x01, // The object may reference $ORIGIN. + DF_SYMBOLIC = 0x02, // Search the shared lib before searching the exe. + DF_TEXTREL = 0x04, // Relocations may modify a non-writable segment. + DF_BIND_NOW = 0x08, // Process all relocations on load. + DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. +}; + +// State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. +enum { + DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. + DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. + DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. + DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. + DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. + DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. + DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. + DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. + DF_1_DIRECT = 0x00000100, // Direct binding enabled. + DF_1_TRANS = 0x00000200, + DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. + DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. + DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. + DF_1_CONFALT = 0x00002000, // Configuration alternative created. + DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. + DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. + DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time. + DF_1_NODIRECT = 0x00020000, // Object has no-direct binding. + DF_1_IGNMULDEF = 0x00040000, + DF_1_NOKSYMS = 0x00080000, + DF_1_NOHDR = 0x00100000, + DF_1_EDITED = 0x00200000, // Object is modified after built. + DF_1_NORELOC = 0x00400000, + DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. + DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. + DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. +}; + +// DT_MIPS_FLAGS values. +enum { + RHF_NONE = 0x00000000, // No flags. + RHF_QUICKSTART = 0x00000001, // Uses shortcut pointers. + RHF_NOTPOT = 0x00000002, // Hash size is not a power of two. + RHS_NO_LIBRARY_REPLACEMENT = 0x00000004, // Ignore LD_LIBRARY_PATH. + RHF_NO_MOVE = 0x00000008, // DSO address may not be relocated. + RHF_SGI_ONLY = 0x00000010, // SGI specific features. + RHF_GUARANTEE_INIT = 0x00000020, // Guarantee that .init will finish + // executing before any non-init + // code in DSO is called. + RHF_DELTA_C_PLUS_PLUS = 0x00000040, // Contains Delta C++ code. + RHF_GUARANTEE_START_INIT = 0x00000080, // Guarantee that .init will start + // executing before any non-init + // code in DSO is called. + RHF_PIXIE = 0x00000100, // Generated by pixie. + RHF_DEFAULT_DELAY_LOAD = 0x00000200, // Delay-load DSO by default. + RHF_REQUICKSTART = 0x00000400, // Object may be requickstarted + RHF_REQUICKSTARTED = 0x00000800, // Object has been requickstarted + RHF_CORD = 0x00001000, // Generated by cord. + RHF_NO_UNRES_UNDEF = 0x00002000, // Object contains no unresolved + // undef symbols. + RHF_RLD_ORDER_SAFE = 0x00004000 // Symbol table is in a safe order. +}; + +// ElfXX_VerDef structure version (GNU versioning) +enum { + VER_DEF_NONE = 0, + VER_DEF_CURRENT = 1 +}; + +// VerDef Flags (ElfXX_VerDef::vd_flags) +enum { + VER_FLG_BASE = 0x1, + VER_FLG_WEAK = 0x2, + VER_FLG_INFO = 0x4 +}; + +// Special constants for the version table. (SHT_GNU_versym/.gnu.version) +enum { + VER_NDX_LOCAL = 0, // Unversioned local symbol + VER_NDX_GLOBAL = 1, // Unversioned global symbol + VERSYM_VERSION = 0x7fff, // Version Index mask + VERSYM_HIDDEN = 0x8000 // Hidden bit (non-default version) +}; + +// ElfXX_VerNeed structure version (GNU versioning) +enum { + VER_NEED_NONE = 0, + VER_NEED_CURRENT = 1 +}; + + +#endif diff --git a/lib/coreclr/src/inc/loaderheap.h b/lib/coreclr/src/inc/loaderheap.h new file mode 100644 index 0000000000..ee45b74645 --- /dev/null +++ b/lib/coreclr/src/inc/loaderheap.h @@ -0,0 +1,1081 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// LoaderHeap.h +// + +// +// Utility functions for managing memory allocations that typically do not +// need releasing. +// +//***************************************************************************** + + +#ifndef __LoaderHeap_h__ +#define __LoaderHeap_h__ + +#include "utilcode.h" +#include "ex.h" + +//============================================================================== +// Interface used to back out loader heap allocations. +//============================================================================== +class ILoaderHeapBackout +{ +#ifdef _DEBUG +#define BackoutMem(pMem, dwSize) RealBackoutMem( (pMem), (dwSize), __FILE__, __LINE__, "UNKNOWN", -1 ) +#else +#define BackoutMem(pMem, dwSize) RealBackoutMem( (pMem), (dwSize) ) +#endif + +public: + virtual void RealBackoutMem(void *pMem + , size_t dwSize +#ifdef _DEBUG + , __in __in_z const char *szFile + , int lineNum + , __in __in_z const char *szAllocFile + , int allocLineNum +#endif + ) = 0; +}; + +//============================================================================== +// This structure packages up all the data needed to back out an AllocMem. +// It's mainly a short term parking place to get the data from the AllocMem +// to the AllocMemHolder while preserving the illusion that AllocMem() still +// returns just a pointer as it did in V1. +//============================================================================== +struct TaggedMemAllocPtr +{ + // Note: For AllocAlignedMem blocks, m_pMem and m_dwRequestedSize are the actual values to pass + // to BackoutMem. Do not add "m_dwExtra" + void *m_pMem; //Pointer to AllocMem'd block (needed to pass back to BackoutMem) + size_t m_dwRequestedSize; //Requested allocation size (needed to pass back to BackoutMem) + + ILoaderHeapBackout *m_pHeap; //The heap that alloc'd the block (needed to know who to call BackoutMem on) + + //For AllocMem'd blocks, this is always 0. + //For AllocAlignedMem blocks, you have to add m_dwExtra to m_pMem to arrive + // at the actual aligned pointer. + size_t m_dwExtra; + +#ifdef _DEBUG + const char *m_szFile; //File that called AllocMem + int m_lineNum; //Line # of AllocMem callsite +#endif + +//! Note: this structure is copied around using bitwise copy ("="). +//! Don't get too fancy putting stuff in here. It's really just a temporary +//! holding place to get stuff from RealAllocMem() to the MemAllocHolder. + + + public: + + // + // This makes "void *ptr = pLoaderHeap->AllocMem()" work as in V1. + // + operator void*() const + { + LIMITED_METHOD_CONTRACT; + return (void*)(m_dwExtra + (BYTE*)m_pMem); + } + + template < typename T > + T cast() const + { + LIMITED_METHOD_CONTRACT; + return reinterpret_cast< T >( operator void *() ); + } +}; + + + +// # bytes to leave between allocations in debug mode +// Set to a > 0 boundary to debug problems - I've made this zero, otherwise a 1 byte allocation becomes +// a (1 + LOADER_HEAP_DEBUG_BOUNDARY) allocation +#define LOADER_HEAP_DEBUG_BOUNDARY 0 + +#define VIRTUAL_ALLOC_RESERVE_GRANULARITY (64*1024) // 0x10000 (64 KB) + +typedef DPTR(struct LoaderHeapBlock) PTR_LoaderHeapBlock; + +struct LoaderHeapBlock +{ + PTR_LoaderHeapBlock pNext; + PTR_VOID pVirtualAddress; + size_t dwVirtualSize; + BOOL m_fReleaseMemory; + +#ifndef DACCESS_COMPILE + // pVirtualMemory - the start address of the virtual memory + // cbVirtualMemory - the length in bytes of the virtual memory + // fReleaseMemory - should LoaderHeap be responsible for releasing this memory + void Init(void *pVirtualMemory, + size_t cbVirtualMemory, + BOOL fReleaseMemory) + { + LIMITED_METHOD_CONTRACT; + this->pNext = NULL; + this->pVirtualAddress = pVirtualMemory; + this->dwVirtualSize = cbVirtualMemory; + this->m_fReleaseMemory = fReleaseMemory; + } + + // Just calls LoaderHeapBlock::Init + LoaderHeapBlock(void *pVirtualMemory, + size_t cbVirtualMemory, + BOOL fReleaseMemory) + { + WRAPPER_NO_CONTRACT; + Init(pVirtualMemory, cbVirtualMemory, fReleaseMemory); + } + + LoaderHeapBlock() + { + WRAPPER_NO_CONTRACT; + Init(NULL, 0, FALSE); + } +#else + // No ctors in DAC builds + LoaderHeapBlock() {} +#endif +}; + +struct LoaderHeapFreeBlock; + +// Collection of methods for helping in debugging heap corruptions +#ifdef _DEBUG +class LoaderHeapSniffer; +struct LoaderHeapEvent; +#endif + + + + + + + + +//=============================================================================== +// This is the base class for LoaderHeap and ExplicitControlLoaderHeap. Unfortunately, +// this class has become schizophrenic. Sometimes, it's used as a simple +// allocator that's semantically (but not perfwise!) equivalent to a blackbox +// alloc/free heap. Othertimes, it's used by callers who are actually aware +// of how it reserves addresses and want direct control over the range over which +// this thing allocates. These two types of allocations are handed out +// from two independent pools inside the heap. +// +// The backout strategy we use for the simple heap probably isn't +// directly applicable to the more advanced uses. +// +// We don't have time to refactor this so as a second-best measure, +// we make most of UnlockedLoaderHeap's methods protected and force everyone +// to use it them through two public derived classes that are mutual siblings. +// +// The LoaderHeap is the black-box heap and has a Backout() method but none +// of the advanced features that let you control address ranges. +// +// The ExplicitControlLoaderHeap exposes all the advanced features but +// has no Backout() feature. (If someone wants a backout feature, they need +// to design an appropriate one into this class.) +//=============================================================================== +class UnlockedLoaderHeap +{ +#ifdef _DEBUG + friend class LoaderHeapSniffer; +#endif + +#ifdef DACCESS_COMPILE + friend class ClrDataAccess; +#endif + +private: + // Linked list of ClrVirtualAlloc'd pages + PTR_LoaderHeapBlock m_pFirstBlock; + + // Allocation pointer in current block + PTR_BYTE m_pAllocPtr; + + // Points to the end of the committed region in the current block + PTR_BYTE m_pPtrToEndOfCommittedRegion; + PTR_BYTE m_pEndReservedRegion; + + PTR_LoaderHeapBlock m_pCurBlock; + + // When we need to ClrVirtualAlloc() MEM_RESERVE a new set of pages, number of bytes to reserve + DWORD m_dwReserveBlockSize; + + // When we need to commit pages from our reserved list, number of bytes to commit at a time + DWORD m_dwCommitBlockSize; + + // Range list to record memory ranges in + RangeList * m_pRangeList; + + size_t m_dwTotalAlloc; + + size_t * m_pPrivatePerfCounter_LoaderBytes; + + DWORD m_Options; + + LoaderHeapFreeBlock *m_pFirstFreeBlock; + + // This is used to hold on to a block of reserved memory provided to the + // constructor. We do this instead of adding it as the first block because + // that requires comitting the first page of the reserved block, and for + // startup working set reasons we want to delay that as long as possible. + LoaderHeapBlock m_reservedBlock; + +public: + +#ifdef _DEBUG + enum + { + kCallTracing = 0x00000001, // Keep a permanent log of all callers + + kEncounteredOOM = 0x80000000, // One time flag to record that an OOM interrupted call tracing + } + LoaderHeapDebugFlags; + + DWORD m_dwDebugFlags; + + LoaderHeapEvent *m_pEventList; // Linked list of events (in reverse time order) +#endif + + + +#ifdef _DEBUG + size_t m_dwDebugWastedBytes; + static DWORD s_dwNumInstancesOfLoaderHeaps; +#endif + +#ifdef _DEBUG + size_t DebugGetWastedBytes() + { + WRAPPER_NO_CONTRACT; + return m_dwDebugWastedBytes + GetBytesAvailCommittedRegion(); + } +#endif + +#ifdef _DEBUG + // Stubs allocated from a LoaderHeap will have unwind info registered with NT. + // The info must be unregistered when the heap is destroyed. + BOOL m_fPermitStubsWithUnwindInfo; + BOOL m_fStubUnwindInfoUnregistered; +#endif + +public: + BOOL m_fExplicitControl; // Am I a LoaderHeap or an ExplicitControlLoaderHeap? + +#ifdef DACCESS_COMPILE +public: + void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); +#endif + +public: + typedef bool EnumPageRegionsCallback (PTR_VOID pvArgs, PTR_VOID pvAllocationBase, SIZE_T cbReserved); + void EnumPageRegions (EnumPageRegionsCallback *pCallback, PTR_VOID pvArgs); + +#ifndef DACCESS_COMPILE +protected: + // Use this version if dwReservedRegionAddress already points to a + // blob of reserved memory. This will set up internal data structures, + // using the provided, reserved memory. + UnlockedLoaderHeap(DWORD dwReserveBlockSize, + DWORD dwCommitBlockSize, + const BYTE* dwReservedRegionAddress, + SIZE_T dwReservedRegionSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, + BOOL fMakeExecutable = FALSE); + + ~UnlockedLoaderHeap(); +#endif + +private: + size_t GetBytesAvailCommittedRegion(); + size_t GetBytesAvailReservedRegion(); + +protected: + // number of bytes available in region + size_t UnlockedGetReservedBytesFree() + { + LIMITED_METHOD_CONTRACT; + return m_pEndReservedRegion - m_pAllocPtr; + } + +private: + // Get some more committed pages - either commit some more in the current reserved region, or, if it + // has run out, reserve another set of pages + BOOL GetMoreCommittedPages(size_t dwMinSize); + +protected: + // Reserve some pages at any address + BOOL UnlockedReservePages(size_t dwCommitBlockSize); + +protected: + // In debug mode, allocate an extra LOADER_HEAP_DEBUG_BOUNDARY bytes and fill it with invalid data. The reason we + // do this is that when we're allocating vtables out of the heap, it is very easy for code to + // get careless, and end up reading from memory that it doesn't own - but since it will be + // reading some other allocation's vtable, no crash will occur. By keeping a gap between + // allocations, it is more likely that these errors will be encountered. + void *UnlockedAllocMem(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ); + void *UnlockedAllocMem_NoThrow(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ); + + + + + +protected: + // Allocates memory aligned on power-of-2 boundary. + // + // The return value is a pointer that's guaranteed to be aligned. + // + // FREEING THIS BLOCK: Underneath, the actual block allocated may + // be larger and start at an address prior to the one you got back. + // It is this adjusted size and pointer that you pass to BackoutMem. + // The required adjustment is passed back thru the pdwExtra pointer. + // + // Here is how to properly backout the memory: + // + // size_t dwExtra; + // void *pMem = UnlockedAllocAlignedMem(dwRequestedSize, alignment, &dwExtra); + // _ASSERTE( 0 == (pMem & (alignment - 1)) ); + // UnlockedBackoutMem( ((BYTE*)pMem) - dExtra, dwRequestedSize + dwExtra ); + // + // If you use the AllocMemHolder or AllocMemTracker, all this is taken care of + // behind the scenes. + // + // + void *UnlockedAllocAlignedMem(size_t dwRequestedSize + ,size_t dwAlignment + ,size_t *pdwExtra +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ); + + void *UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSize + ,size_t dwAlignment + ,size_t *pdwExtra +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ); + +protected: + // This frees memory allocated by UnlockAllocMem. It's given this horrible name to emphasize + // that it's purpose is for error path leak prevention purposes. You shouldn't + // use LoaderHeap's as general-purpose alloc-free heaps. + void UnlockedBackoutMem(void *pMem + , size_t dwSize +#ifdef _DEBUG + , __in __in_z const char *szFile + , int lineNum + , __in __in_z const char *szAllocFile + , int AllocLineNum +#endif + ); + +public: + // Perf Counter reports the size of the heap + size_t GetSize () + { + LIMITED_METHOD_CONTRACT; + return m_dwTotalAlloc; + } + + BOOL IsExecutable(); + +public: +#ifdef _DEBUG + void DumpFreeList(); +#endif + +public: +// Extra CallTracing support +#ifdef _DEBUG + void UnlockedClearEvents(); //Discard saved events + void UnlockedCompactEvents(); //Discard matching alloc/free events + void UnlockedPrintEvents(); //Print event list +#endif + +protected: + void *UnlockedAllocMemForCode_NoThrow(size_t dwHeaderSize, size_t dwCodeSize, DWORD dwCodeAlignment, size_t dwReserveForJumpStubs); + + void UnlockedSetReservedRegion(BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, BOOL fReleaseMemory); +}; + +//=============================================================================== +// Create the LoaderHeap lock. It's the same lock for several different Heaps. +//=============================================================================== +inline CRITSEC_COOKIE CreateLoaderHeapLock() +{ + return ClrCreateCriticalSection(CrstLoaderHeap,CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD)); +} + +//=============================================================================== +// The LoaderHeap is the black-box heap and has a Backout() method but none +// of the advanced features that let you control address ranges. +//=============================================================================== +typedef DPTR(class LoaderHeap) PTR_LoaderHeap; +class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout +{ +private: + CRITSEC_COOKIE m_CriticalSection; + +#ifndef DACCESS_COMPILE +public: + LoaderHeap(DWORD dwReserveBlockSize, + DWORD dwCommitBlockSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, + BOOL fMakeExecutable = FALSE + ) + : UnlockedLoaderHeap(dwReserveBlockSize, + dwCommitBlockSize, + NULL, 0, + pPrivatePerfCounter_LoaderBytes, + pRangeList, + fMakeExecutable) + { + WRAPPER_NO_CONTRACT; + m_CriticalSection = NULL; + m_CriticalSection = CreateLoaderHeapLock(); + m_fExplicitControl = FALSE; + } + +public: + LoaderHeap(DWORD dwReserveBlockSize, + DWORD dwCommitBlockSize, + const BYTE* dwReservedRegionAddress, + SIZE_T dwReservedRegionSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, + BOOL fMakeExecutable = FALSE + ) + : UnlockedLoaderHeap(dwReserveBlockSize, + dwCommitBlockSize, + dwReservedRegionAddress, + dwReservedRegionSize, + pPrivatePerfCounter_LoaderBytes, + pRangeList, + fMakeExecutable) + { + WRAPPER_NO_CONTRACT; + m_CriticalSection = NULL; + m_CriticalSection = CreateLoaderHeapLock(); + m_fExplicitControl = FALSE; + } + +#endif // DACCESS_COMPILE + + virtual ~LoaderHeap() + { + WRAPPER_NO_CONTRACT; + +#ifndef DACCESS_COMPILE + if (m_CriticalSection != NULL) + { + ClrDeleteCriticalSection(m_CriticalSection); + } +#endif // DACCESS_COMPILE + } + + + +#ifdef _DEBUG +#define AllocMem(dwSize) RealAllocMem( (dwSize), __FILE__, __LINE__ ) +#define AllocMem_NoThrow(dwSize) RealAllocMem_NoThrow( (dwSize), __FILE__, __LINE__ ) +#else +#define AllocMem(dwSize) RealAllocMem( (dwSize) ) +#define AllocMem_NoThrow(dwSize) RealAllocMem_NoThrow( (dwSize) ) +#endif + +public: + FORCEINLINE TaggedMemAllocPtr RealAllocMem(S_SIZE_T dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + if(dwSize.IsOverflow()) ThrowOutOfMemory(); + + return RealAllocMemUnsafe(dwSize.Value() COMMA_INDEBUG(szFile) COMMA_INDEBUG(lineNum)); + + } + + FORCEINLINE TaggedMemAllocPtr RealAllocMem_NoThrow(S_SIZE_T dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + if(dwSize.IsOverflow()) { + TaggedMemAllocPtr tmap; + tmap.m_pMem = NULL; + tmap.m_dwRequestedSize = dwSize.Value(); + tmap.m_pHeap = this; + tmap.m_dwExtra = 0; +#ifdef _DEBUG + tmap.m_szFile = szFile; + tmap.m_lineNum = lineNum; +#endif + + return tmap; + } + + return RealAllocMemUnsafe_NoThrow(dwSize.Value() COMMA_INDEBUG(szFile) COMMA_INDEBUG(lineNum)); + } +private: + + TaggedMemAllocPtr RealAllocMemUnsafe(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + + void *pResult; + TaggedMemAllocPtr tmap; + + CRITSEC_Holder csh(m_CriticalSection); + pResult = UnlockedAllocMem(dwSize +#ifdef _DEBUG + , szFile + , lineNum +#endif + ); + tmap.m_pMem = pResult; + tmap.m_dwRequestedSize = dwSize; + tmap.m_pHeap = this; + tmap.m_dwExtra = 0; +#ifdef _DEBUG + tmap.m_szFile = szFile; + tmap.m_lineNum = lineNum; +#endif + return tmap; + } + + TaggedMemAllocPtr RealAllocMemUnsafe_NoThrow(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + void *pResult; + TaggedMemAllocPtr tmap; + + CRITSEC_Holder csh(m_CriticalSection); + + pResult = UnlockedAllocMem_NoThrow(dwSize +#ifdef _DEBUG + , szFile + , lineNum +#endif + ); + + tmap.m_pMem = pResult; + tmap.m_dwRequestedSize = dwSize; + tmap.m_pHeap = this; + tmap.m_dwExtra = 0; +#ifdef _DEBUG + tmap.m_szFile = szFile; + tmap.m_lineNum = lineNum; +#endif + + return tmap; + } + + + +#ifdef _DEBUG +#define AllocAlignedMem(dwSize, dwAlign) RealAllocAlignedMem( (dwSize), (dwAlign), __FILE__, __LINE__) +#define AllocAlignedMem_NoThrow(dwSize, dwAlign) RealAllocAlignedMem_NoThrow( (dwSize), (dwAlign), __FILE__, __LINE__) +#else +#define AllocAlignedMem(dwSize, dwAlign) RealAllocAlignedMem( (dwSize), (dwAlign) ) +#define AllocAlignedMem_NoThrow(dwSize, dwAlign) RealAllocAlignedMem_NoThrow( (dwSize), (dwAlign) ) +#endif + +public: + TaggedMemAllocPtr RealAllocAlignedMem(size_t dwRequestedSize + ,size_t dwAlignment +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + CRITSEC_Holder csh(m_CriticalSection); + + + TaggedMemAllocPtr tmap; + void *pResult; + size_t dwExtra; + + pResult = UnlockedAllocAlignedMem(dwRequestedSize + ,dwAlignment + ,&dwExtra +#ifdef _DEBUG + ,szFile + ,lineNum +#endif + ); + + tmap.m_pMem = (void*)(((BYTE*)pResult) - dwExtra); + tmap.m_dwRequestedSize = dwRequestedSize + dwExtra; + tmap.m_pHeap = this; + tmap.m_dwExtra = dwExtra; +#ifdef _DEBUG + tmap.m_szFile = szFile; + tmap.m_lineNum = lineNum; +#endif + + return tmap; + } + + + TaggedMemAllocPtr RealAllocAlignedMem_NoThrow(size_t dwRequestedSize + ,size_t dwAlignment +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + CRITSEC_Holder csh(m_CriticalSection); + + + TaggedMemAllocPtr tmap; + void *pResult; + size_t dwExtra; + + pResult = UnlockedAllocAlignedMem_NoThrow(dwRequestedSize + ,dwAlignment + ,&dwExtra +#ifdef _DEBUG + ,szFile + ,lineNum +#endif + ); + + _ASSERTE(!(pResult == NULL && dwExtra != 0)); + + tmap.m_pMem = (void*)(((BYTE*)pResult) - dwExtra); + tmap.m_dwRequestedSize = dwRequestedSize + dwExtra; + tmap.m_pHeap = this; + tmap.m_dwExtra = dwExtra; +#ifdef _DEBUG + tmap.m_szFile = szFile; + tmap.m_lineNum = lineNum; +#endif + + return tmap; + } + + +public: + // This frees memory allocated by AllocMem. It's given this horrible name to emphasize + // that it's purpose is for error path leak prevention purposes. You shouldn't + // use LoaderHeap's as general-purpose alloc-free heaps. + void RealBackoutMem(void *pMem + , size_t dwSize +#ifdef _DEBUG + , __in __in_z const char *szFile + , int lineNum + , __in __in_z const char *szAllocFile + , int allocLineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + CRITSEC_Holder csh(m_CriticalSection); + UnlockedBackoutMem(pMem + , dwSize +#ifdef _DEBUG + , szFile + , lineNum + , szAllocFile + , allocLineNum +#endif + ); + } + +public: +// Extra CallTracing support +#ifdef _DEBUG + void ClearEvents() + { + WRAPPER_NO_CONTRACT; + CRITSEC_Holder csh(m_CriticalSection); + UnlockedClearEvents(); + } + + void CompactEvents() + { + WRAPPER_NO_CONTRACT; + CRITSEC_Holder csh(m_CriticalSection); + UnlockedCompactEvents(); + } + + void PrintEvents() + { + WRAPPER_NO_CONTRACT; + CRITSEC_Holder csh(m_CriticalSection); + UnlockedPrintEvents(); + } +#endif + +}; + + + + + +//=============================================================================== +// The ExplicitControlLoaderHeap exposes all the advanced features but +// has no Backout() feature. (If someone wants a backout feature, they need +// to design an appropriate one into this class.) +// +// Caller is responsible for synchronization. ExplicitControlLoaderHeap is +// not multithread safe. +//=============================================================================== +typedef DPTR(class ExplicitControlLoaderHeap) PTR_ExplicitControlLoaderHeap; +class ExplicitControlLoaderHeap : public UnlockedLoaderHeap +{ +#ifndef DACCESS_COMPILE +public: + ExplicitControlLoaderHeap(size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, + BOOL fMakeExecutable = FALSE + ) + : UnlockedLoaderHeap(0, 0, NULL, 0, + pPrivatePerfCounter_LoaderBytes, + pRangeList, + fMakeExecutable) + { + WRAPPER_NO_CONTRACT; + m_fExplicitControl = TRUE; + } +#endif // DACCESS_COMPILE + +public: + void *RealAllocMem(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + void *pResult; + + pResult = UnlockedAllocMem(dwSize +#ifdef _DEBUG + , szFile + , lineNum +#endif + ); + return pResult; + } + + void *RealAllocMem_NoThrow(size_t dwSize +#ifdef _DEBUG + ,__in __in_z const char *szFile + ,int lineNum +#endif + ) + { + WRAPPER_NO_CONTRACT; + + void *pResult; + + pResult = UnlockedAllocMem_NoThrow(dwSize +#ifdef _DEBUG + , szFile + , lineNum +#endif + ); + return pResult; + } + + +public: + void *AllocMemForCode_NoThrow(size_t dwHeaderSize, size_t dwCodeSize, DWORD dwCodeAlignment, size_t dwReserveForJumpStubs) + { + WRAPPER_NO_CONTRACT; + return UnlockedAllocMemForCode_NoThrow(dwHeaderSize, dwCodeSize, dwCodeAlignment, dwReserveForJumpStubs); + } + + void SetReservedRegion(BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, BOOL fReleaseMemory) + { + WRAPPER_NO_CONTRACT; + return UnlockedSetReservedRegion(dwReservedRegionAddress, dwReservedRegionSize, fReleaseMemory); + } + +public: + // number of bytes available in region + size_t GetReservedBytesFree() + { + WRAPPER_NO_CONTRACT; + return UnlockedGetReservedBytesFree(); + } +}; + + + +//============================================================================== +// AllocMemHolder : Allocated memory from LoaderHeap +// +// Old: +// +// Foo* pFoo = (Foo*)pLoaderHeap->AllocMem(size); +// pFoo->BackoutMem(pFoo, size) +// +// +// New: +// +// { +// AllocMemHolder pfoo = pLoaderHeap->AllocMem(); +// } // BackoutMem on out of scope +// +//============================================================================== +template +class AllocMemHolder +{ + private: + TaggedMemAllocPtr m_value; + BOOL m_fAcquired; + + + //-------------------------------------------------------------------- + // All allowed (and disallowed) ctors here. + //-------------------------------------------------------------------- + public: + // Allow the construction "Holder h;" + AllocMemHolder() + { + LIMITED_METHOD_CONTRACT; + + m_value.m_pMem = NULL; + m_value.m_dwRequestedSize = 0; + m_value.m_pHeap = 0; + m_value.m_dwExtra = 0; +#ifdef _DEBUG + m_value.m_szFile = NULL; + m_value.m_lineNum = 0; +#endif + m_fAcquired = FALSE; + } + + public: + // Allow the construction "Holder h = pHeap->AllocMem()" + AllocMemHolder(const TaggedMemAllocPtr value) + { + LIMITED_METHOD_CONTRACT; + m_value = value; + m_fAcquired = TRUE; + } + + private: + // Disallow "Holder holder1 = holder2" + AllocMemHolder(const AllocMemHolder &); + + + private: + // Disallow "Holder holder1 = void*" + AllocMemHolder(const LPVOID &); + + //-------------------------------------------------------------------- + // Destructor (and the whole point of AllocMemHolder) + //-------------------------------------------------------------------- + public: + ~AllocMemHolder() + { + WRAPPER_NO_CONTRACT; + if (m_fAcquired && m_value.m_pMem) + { + m_value.m_pHeap->RealBackoutMem(m_value.m_pMem, + m_value.m_dwRequestedSize +#ifdef _DEBUG + ,__FILE__ + ,__LINE__ + ,m_value.m_szFile + ,m_value.m_lineNum +#endif + ); + } + } + + + //-------------------------------------------------------------------- + // All allowed (and disallowed) assignment operators here. + //-------------------------------------------------------------------- + public: + // Reluctantly allow "AllocMemHolder h; ... h = pheap->AllocMem()" + void operator=(const TaggedMemAllocPtr & value) + { + WRAPPER_NO_CONTRACT; + // However, prevent repeated assignments as that would leak. + _ASSERTE(m_value.m_pMem == NULL && !m_fAcquired); + m_value = value; + m_fAcquired = TRUE; + } + + private: + // Disallow "holder == holder2" + const AllocMemHolder & operator=(const AllocMemHolder &); + + private: + // Disallow "holder = void*" + const AllocMemHolder & operator=(const LPVOID &); + + + //-------------------------------------------------------------------- + // Operations on the holder itself + //-------------------------------------------------------------------- + public: + // Call this when you're ready to take ownership away from the holder. + void SuppressRelease() + { + LIMITED_METHOD_CONTRACT; + m_fAcquired = FALSE; + } + + + + //-------------------------------------------------------------------- + // ... And the smart-pointer stuff so we can drop holders on top + // of former pointer variables (mostly) + //-------------------------------------------------------------------- + public: + // Allow holder to be treated as the underlying pointer type + operator TYPE* () + { + LIMITED_METHOD_CONTRACT; + return (TYPE*)(void*)m_value; + } + + public: + // Allow holder to be treated as the underlying pointer type + TYPE* operator->() + { + LIMITED_METHOD_CONTRACT; + return (TYPE*)(void*)m_value; + } + public: + int operator==(TYPE* value) + { + LIMITED_METHOD_CONTRACT; + return ((void*)m_value) == ((void*)value); + } + + public: + int operator!=(TYPE* value) + { + LIMITED_METHOD_CONTRACT; + return ((void*)m_value) != ((void*)value); + } + + public: + int operator!() const + { + LIMITED_METHOD_CONTRACT; + return m_value.m_pMem == NULL; + } + + +}; + + + +// This utility helps track loaderheap allocations. Its main purpose +// is to backout allocations in case of an exception. +class AllocMemTracker +{ + public: + AllocMemTracker(); + ~AllocMemTracker(); + + // Tells tracker to store an allocated loaderheap block. + // + // Returns the pointer address of block for convenience. + // + // Ok to call on failed loaderheap allocation (will just do nothing and propagate the OOM as apropos). + // + // If Track fails due to an OOM allocating node space, it will backout the loaderheap block before returning. + void *Track(TaggedMemAllocPtr tmap); + void *Track_NoThrow(TaggedMemAllocPtr tmap); + + void SuppressRelease(); + + private: + struct AllocMemTrackerNode + { + ILoaderHeapBackout *m_pHeap; + void *m_pMem; + size_t m_dwRequestedSize; +#ifdef _DEBUG + const char *m_szAllocFile; + int m_allocLineNum; +#endif + }; + + enum + { + kAllocMemTrackerBlockSize = +#ifdef _DEBUG + 3 +#else + 20 +#endif + }; + + struct AllocMemTrackerBlock + { + AllocMemTrackerBlock *m_pNext; + int m_nextFree; + AllocMemTrackerNode m_Node[kAllocMemTrackerBlockSize]; + }; + + + AllocMemTrackerBlock *m_pFirstBlock; + AllocMemTrackerBlock m_FirstBlock; // Stack-allocate the first block - "new" the rest. + + protected: + BOOL m_fReleased; + +}; + +#endif // __LoaderHeap_h__ + diff --git a/lib/coreclr/src/inc/log.h b/lib/coreclr/src/inc/log.h new file mode 100644 index 0000000000..37aab45711 --- /dev/null +++ b/lib/coreclr/src/inc/log.h @@ -0,0 +1,99 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Logging Facility +// + + +// Logging Subsystems + + +#ifndef __LOG_H__ +#define __LOG_H__ + + +#define DEFINE_LOG_FACILITY(logname, value) logname = value, + +enum { +#include "loglf.h" + LF_ALWAYS = 0x80000000, // Log message irrepespective of LogFacility (if the level matches) + LF_ALL = 0xFFFFFFFF, // Used only to mask bits. Never use as LOG((LF_ALL, ...)) + + // LogFacility2: all 32-bit of LogFacility are used, need a 2nd DWORD for more facilities + LF2_MULTICOREJIT = 0x00000001 // Multicore JIT +}; + + +#define LL_EVERYTHING 10 +#define LL_INFO1000000 9 // can be expected to generate 1,000,000 logs per small but not trival run +#define LL_INFO100000 8 // can be expected to generate 100,000 logs per small but not trival run +#define LL_INFO10000 7 // can be expected to generate 10,000 logs per small but not trival run +#define LL_INFO1000 6 // can be expected to generate 1,000 logs per small but not trival run +#define LL_INFO100 5 // can be expected to generate 100 logs per small but not trival run +#define LL_INFO10 4 // can be expected to generate 10 logs per small but not trival run +#define LL_WARNING 3 +#define LL_ERROR 2 +#define LL_FATALERROR 1 +#define LL_ALWAYS 0 // impossible to turn off (log level never negative) + + +#define INFO5 LL_INFO10 +#define INFO4 LL_INFO100 +#define INFO3 LL_INFO1000 +#define INFO2 LL_INFO10000 +#define INFO1 LL_INFO100000 +#define WARNING 0 +#define ERROR 0 +#define FATALERROR 0 + +#ifndef LOGGING + +#define LOG(x) +#define LOG2(x) + +#define InitializeLogging() +#define InitLogging() +#define ShutdownLogging() +#define FlushLogging() +#define LoggingOn(facility, level) 0 +#define Logging2On(facility, level) 0 +#define EnterLogLock() +#define LeaveLogLock() + +#else + +extern VOID InitializeLogging(); +extern VOID InitLogging(); +extern VOID ShutdownLogging(); +extern VOID FlushLogging(); + +extern VOID LogSpew(DWORD facility, DWORD level, const char *fmt, ... ); +extern VOID LogSpewValist(DWORD facility, DWORD level, const char *fmt, va_list args); + +extern VOID LogSpew2(DWORD facility2, DWORD level, const char *fmt, ... ); +extern VOID LogSpew2Valist(DWORD facility2, DWORD level, const char *fmt, va_list args); + +extern VOID LogSpewAlwaysValist(const char *fmt, va_list args); +extern VOID LogSpewAlways (const char *fmt, ... ); +extern VOID EnterLogLock(); +extern VOID LeaveLogLock(); + +VOID AddLoggingFacility( DWORD facility ); +VOID SetLoggingLevel( DWORD level ); +bool LoggingEnabled(); +bool LoggingOn(DWORD facility, DWORD level); +bool Logging2On(DWORD facility, DWORD level); + +#define LOG(x) do { if (LoggingEnabled()) { LogSpew x; } } while (0) + +#define LOG2(x) do { if (LoggingEnabled()) { LogSpew2 x; } } while (0) + +#endif + +#ifdef __cplusplus +#include "stresslog.h" // special logging for retail code +#endif + +#endif //__LOG_H__ diff --git a/lib/coreclr/src/inc/loglf.h b/lib/coreclr/src/inc/loglf.h new file mode 100644 index 0000000000..76a9897b53 --- /dev/null +++ b/lib/coreclr/src/inc/loglf.h @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// The code in sos.DumpLog depends on the first 32 facility codes +// being bit flags sorted in incresing order. + +DEFINE_LOG_FACILITY(LF_GC ,0x00000001) +DEFINE_LOG_FACILITY(LF_GCINFO ,0x00000002) +DEFINE_LOG_FACILITY(LF_STUBS ,0x00000004) +DEFINE_LOG_FACILITY(LF_JIT ,0x00000008) +DEFINE_LOG_FACILITY(LF_LOADER ,0x00000010) +DEFINE_LOG_FACILITY(LF_METADATA ,0x00000020) +DEFINE_LOG_FACILITY(LF_SYNC ,0x00000040) +DEFINE_LOG_FACILITY(LF_EEMEM ,0x00000080) +DEFINE_LOG_FACILITY(LF_GCALLOC ,0x00000100) +DEFINE_LOG_FACILITY(LF_CORDB ,0x00000200) +DEFINE_LOG_FACILITY(LF_CLASSLOADER ,0x00000400) +DEFINE_LOG_FACILITY(LF_CORPROF ,0x00000800) +DEFINE_LOG_FACILITY(LF_DIAGNOSTICS_PORT ,0x00001000) +DEFINE_LOG_FACILITY(LF_DBGALLOC ,0x00002000) +DEFINE_LOG_FACILITY(LF_EH ,0x00004000) +DEFINE_LOG_FACILITY(LF_ENC ,0x00008000) +DEFINE_LOG_FACILITY(LF_ASSERT ,0x00010000) +DEFINE_LOG_FACILITY(LF_VERIFIER ,0x00020000) +DEFINE_LOG_FACILITY(LF_THREADPOOL ,0x00040000) +DEFINE_LOG_FACILITY(LF_GCROOTS ,0x00080000) +DEFINE_LOG_FACILITY(LF_INTEROP ,0x00100000) +DEFINE_LOG_FACILITY(LF_MARSHALER ,0x00200000) +DEFINE_LOG_FACILITY(LF_TIEREDCOMPILATION ,0x00400000) // This used to be IJW, but now repurposed for tiered compilation +DEFINE_LOG_FACILITY(LF_ZAP ,0x00800000) +DEFINE_LOG_FACILITY(LF_STARTUP ,0x01000000) // Log startupa and shutdown failures +DEFINE_LOG_FACILITY(LF_APPDOMAIN ,0x02000000) +DEFINE_LOG_FACILITY(LF_CODESHARING ,0x04000000) +DEFINE_LOG_FACILITY(LF_STORE ,0x08000000) +DEFINE_LOG_FACILITY(LF_SECURITY ,0x10000000) +DEFINE_LOG_FACILITY(LF_LOCKS ,0x20000000) +DEFINE_LOG_FACILITY(LF_BCL ,0x40000000) +// LF_ALWAYS 0x80000000 // make certain you don't try to use this bit for a real facility +// LF_ALL 0xFFFFFFFF +// +#undef DEFINE_LOG_FACILITY + diff --git a/lib/coreclr/src/inc/longfilepathwrappers.h b/lib/coreclr/src/inc/longfilepathwrappers.h new file mode 100644 index 0000000000..3bb9166990 --- /dev/null +++ b/lib/coreclr/src/inc/longfilepathwrappers.h @@ -0,0 +1,156 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _WIN_PATH_APIS_WRAPPER_ +#define _WIN_PATH_APIS_WRAPPER_ +class SString; + +HMODULE +LoadLibraryExWrapper( + _In_ LPCWSTR lpLibFileName, + _Reserved_ HANDLE hFile = NULL, + _In_ DWORD dwFlags = 0 + ); + +HANDLE +CreateFileWrapper( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwDesiredAccess, + _In_ DWORD dwShareMode, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, + _In_ DWORD dwCreationDisposition, + _In_ DWORD dwFlagsAndAttributes, + _In_opt_ HANDLE hTemplateFile + ); + +BOOL +SetFileAttributesWrapper( + _In_ LPCWSTR lpFileName, + _In_ DWORD dwFileAttributes + ); + +DWORD +GetFileAttributesWrapper( + _In_ LPCWSTR lpFileName + ); + +BOOL +GetFileAttributesExWrapper( + _In_ LPCWSTR lpFileName, + _In_ GET_FILEEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation + ); +BOOL +DeleteFileWrapper( + _In_ LPCWSTR lpFileName + ); + +HANDLE +FindFirstFileExWrapper( + _In_ LPCWSTR lpFileName, + _In_ FINDEX_INFO_LEVELS fInfoLevelId, + _Out_writes_bytes_(sizeof(WIN32_FIND_DATAW)) LPVOID lpFindFileData, + _In_ FINDEX_SEARCH_OPS fSearchOp, + _Reserved_ LPVOID lpSearchFilter, + _In_ DWORD dwAdditionalFlags + ); + +BOOL +CopyFileWrapper( + _In_ LPCWSTR lpExistingFileName, + _In_ LPCWSTR lpNewFileName, + _In_ BOOL bFailIfExists + ); + +#ifndef FEATURE_PAL +BOOL +CopyFileExWrapper( + _In_ LPCWSTR lpExistingFileName, + _In_ LPCWSTR lpNewFileName, + _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine, + _In_opt_ LPVOID lpData, + _When_(pbCancel != NULL, _Pre_satisfies_(*pbCancel == FALSE)) + _Inout_opt_ LPBOOL pbCancel, + _In_ DWORD dwCopyFlags + ); +#endif //FEATURE_PAL + +BOOL +MoveFileExWrapper( + _In_ LPCWSTR lpExistingFileName, + _In_opt_ LPCWSTR lpNewFileName, + _In_ DWORD dwFlags + ); + +BOOL +CreateDirectoryWrapper( + _In_ LPCWSTR lpPathName, + _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +BOOL +RemoveDirectoryWrapper( + _In_ LPCWSTR lpPathName + ); + +BOOL +CreateHardLinkWrapper( + _In_ LPCWSTR lpFileName, + _In_ LPCWSTR lpExistingFileName, + _Reserved_ LPSECURITY_ATTRIBUTES lpSecurityAttributes + ); + +DWORD +SearchPathWrapper( + _In_opt_ LPCWSTR lpPath, + _In_ LPCWSTR lpFileName, + _In_opt_ LPCWSTR lpExtension, + _In_ BOOL getPath, + SString& lpBuffer, + _Out_opt_ LPWSTR * lpFilePart + ); + + +DWORD +GetShortPathNameWrapper( + _In_ LPCWSTR lpszLongPath, + SString& lpszShortPath + ); + +DWORD +GetLongPathNameWrapper( + _In_ LPCWSTR lpszShortPath, + SString& lpszLongPath + ); + +UINT WINAPI GetTempFileNameWrapper( + _In_ LPCTSTR lpPathName, + _In_ LPCTSTR lpPrefixString, + _In_ UINT uUnique, + SString& lpTempFileName + ); + +DWORD WINAPI GetTempPathWrapper( + SString& lpBuffer + ); + +DWORD WINAPI GetCurrentDirectoryWrapper( + SString& lpBuffer + ); + +DWORD +GetModuleFileNameWrapper( + _In_opt_ HMODULE hModule, + SString& buffer + ); + +DWORD WINAPI GetEnvironmentVariableWrapper( + _In_opt_ LPCTSTR lpName, + _Out_opt_ SString& lpBuffer + ); + +BOOL PAL_GetPALDirectoryWrapper(SString& pbuffer); + +#endif //_WIN_PATH_APIS_WRAPPER_ + diff --git a/lib/coreclr/src/inc/md5.h b/lib/coreclr/src/inc/md5.h new file mode 100644 index 0000000000..b3684718e5 --- /dev/null +++ b/lib/coreclr/src/inc/md5.h @@ -0,0 +1,134 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// md5.h +// + +// +// A pretty fast implementation of MD5 +// + + +#ifndef __MD5_H__ +#define __MD5_H__ + +///////////////////////////////////////////////////////////////////////////////////// +// +// Declaration of the central transform function +// +void __stdcall MD5Transform(ULONG state[4], const ULONG* data); + +///////////////////////////////////////////////////////////////////////////////////// + +#include + + +// This structure is used to return the final resulting hash. +// +struct MD5HASHDATA + { + union + { + BYTE rgb[16]; + struct + { + ULONGLONG ullLow; + ULONGLONG ullHigh; + } u; + struct + { + ULONG u0; + ULONG u1; + ULONG u2; + ULONG u3; + } v; + }; + }; + +inline BOOL operator==(const MD5HASHDATA& me, const MD5HASHDATA& him) + { + return memcmp(&me, &him, sizeof(MD5HASHDATA)) == 0; + } + +inline BOOL operator!=(const MD5HASHDATA& me, const MD5HASHDATA& him) + { + return memcmp(&me, &him, sizeof(MD5HASHDATA)) != 0; + } + + +// The engine that carries out the hash +// +class MD5 + { + // These four values must be contiguous, and in this order + union + { + ULONG m_state[4]; + struct + { + ULONG m_a; // state + ULONG m_b; // ... variables + ULONG m_c; // ... as found in + ULONG m_d; // ... RFC1321 + } u; + }; + + BYTE m_data[64]; // where to accumulate the data as we are passed it + ULONGLONG m_cbitHashed; // amount of data that we've hashed + ULONG m_cbData; // number of bytes presently in data + + BYTE m_padding[64]; // padding data, used if length data not = 0 mod 64 + +public: + + ///////////////////////////////////////////////////////////////////////////////////// + + void Hash(const BYTE* pbData, ULONG cbData, MD5HASHDATA* phash, BOOL fConstructed = FALSE) + { + Init(fConstructed); + HashMore(pbData, cbData); + GetHashValue(phash); + } + + ///////////////////////////////////////////////////////////////////////////////////// + + void Hash(const BYTE* pbData, ULONGLONG cbData, MD5HASHDATA* phash, BOOL fConstructed = FALSE) + { + Init(fConstructed); + + ULARGE_INTEGER ul; + ul.QuadPart = cbData; + + while (ul.u.HighPart) + { + ULONG cbHash = 0xFFFFFFFF; // Hash as much as we can at once + HashMore(pbData, cbHash); + pbData += cbHash; + ul.QuadPart -= cbHash; + } + + HashMore(pbData, ul.u.LowPart); // Hash whatever is left + + GetHashValue(phash); + } + + ///////////////////////////////////////////////////////////////////////////////////// + + void Init(BOOL fConstructed = FALSE); + + ///////////////////////////////////////////////////////////////////////////////////// + + void HashMore(const void* pvInput, ULONG cbInput); + + ///////////////////////////////////////////////////////////////////////////////////// + + void GetHashValue(MD5HASHDATA* phash); + + ///////////////////////////////////////////////////////////////////////////////////// + + }; + +#include + +#endif diff --git a/lib/coreclr/src/inc/mdcommon.h b/lib/coreclr/src/inc/mdcommon.h new file mode 100644 index 0000000000..7aeb710aa8 --- /dev/null +++ b/lib/coreclr/src/inc/mdcommon.h @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// MDCommon.h +// +// Common header file for both MD and COMPLIB subdirectories +// +//***************************************************************************** + +#ifndef __MDCommon_h__ +#define __MDCommon_h__ + +// File types for the database. +enum FILETYPE +{ + FILETYPE_UNKNOWN, // Unknown or undefined type. + FILETYPE_CLB, // Native .clb file format. + FILETYPE_CLX, // An obsolete file format. + FILETYPE_NTPE, // Windows PE executable. + FILETYPE_NTOBJ, // .obj file format (with .clb embedded). + FILETYPE_TLB // Typelib format. +}; + +enum MAPPINGTYPE +{ + MTYPE_NOMAPPING, // No mapped file + MTYPE_FLAT, // Mapped as a flat file + MTYPE_IMAGE // Mapped with the SEC_IMAGE flag +}; + + +#define SCHEMA_STREAM_A "#Schema" +#define STRING_POOL_STREAM_A "#Strings" +#define BLOB_POOL_STREAM_A "#Blob" +#define US_BLOB_POOL_STREAM_A "#US" +#define GUID_POOL_STREAM_A "#GUID" +#define COMPRESSED_MODEL_STREAM_A "#~" +#define ENC_MODEL_STREAM_A "#-" +#define MINIMAL_MD_STREAM_A "#JTD" +#define HOT_MODEL_STREAM_A "#!" + + +#define SCHEMA_STREAM W("#Schema") +#define STRING_POOL_STREAM W("#Strings") +#define BLOB_POOL_STREAM W("#Blob") +#define US_BLOB_POOL_STREAM W("#US") +#define GUID_POOL_STREAM W("#GUID") +#define COMPRESSED_MODEL_STREAM W("#~") +#define ENC_MODEL_STREAM W("#-") +#define MINIMAL_MD_STREAM W("#JTD") +#define HOT_MODEL_STREAM W("#!") + +#endif // __MDCommon_h__ diff --git a/lib/coreclr/src/inc/memorypool.h b/lib/coreclr/src/inc/memorypool.h new file mode 100644 index 0000000000..9ea524f1f2 --- /dev/null +++ b/lib/coreclr/src/inc/memorypool.h @@ -0,0 +1,143 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _MEMORYPOOL_ +#define _MEMORYPOOL_ + +#include "daccess.h" +#include "contract.h" + +// +// A MemoryPool is an allocator for a fixed size elements. +// Allocating and freeing elements from the pool is very cheap compared +// to a general allocator like new. However, a MemoryPool is slightly +// more greedy - it preallocates a bunch of elements at a time, and NEVER +// RELEASES MEMORY FROM THE POOL ONCE IT IS ALLOCATED, (unless you call +// FreeAllElements.) +// +// It also has several additional features: +// * you can free the entire pool of objects cheaply. +// * you can test an object to see if it's an element of the pool. +// + +class MemoryPool +{ + public: + +#ifndef DACCESS_COMPILE + MemoryPool(SIZE_T elementSize, SIZE_T initGrowth = 20, SIZE_T initCount = 0); +#else + MemoryPool() {} +#endif + ~MemoryPool() DAC_EMPTY(); + + BOOL IsElement(void *element); + BOOL IsAllocatedElement(void *element); + void *AllocateElement(); + void *AllocateElementNoThrow(); + void FreeElement(void *element); + void FreeAllElements(); + size_t GetSize(); + private: + + struct Element + { + Element *next; +#if _DEBUG + int deadBeef; +#endif + }; + + struct Block + { + Block *next; + Element *elementsEnd; +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) +#endif + Element elements[0]; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + }; + + SIZE_T m_elementSize; + SIZE_T m_growCount; + Block *m_blocks; + Element *m_freeList; + + BOOL AddBlock(SIZE_T elementCount); + void DeadBeef(Element *element); + + public: + + // + // NOTE: You can currently only iterate the elements + // if none have been freed. + // + + class Iterator + { + private: + Block *m_next; + BYTE *m_e, *m_eEnd; + BYTE *m_end; + SIZE_T m_size; + + public: + Iterator(MemoryPool *pool); + + BOOL Next(); + + void *GetElement() {LIMITED_METHOD_CONTRACT; return (void *) (m_e-m_size); } + }; + + friend class Iterator; +}; + +class MemoryPoolElementHolder +{ + protected: + MemoryPool* m_pool; + void* m_element; + BOOL bRelease; + public: + void SuppressRelease() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(bRelease); + bRelease=false; + } + void Release() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(bRelease); + m_pool->FreeElement(m_element); + bRelease=false; + } + MemoryPoolElementHolder(MemoryPool* pool, void* element) + { + LIMITED_METHOD_CONTRACT; + m_pool=pool; + m_element=element; + bRelease=true; + } + + ~MemoryPoolElementHolder() + { + LIMITED_METHOD_CONTRACT; + if (bRelease) + Release(); + } + + operator void* () + { + LIMITED_METHOD_CONTRACT; + return m_element; + } +}; + +#endif // _MEMORYPOOL_ diff --git a/lib/coreclr/src/inc/memoryrange.h b/lib/coreclr/src/inc/memoryrange.h new file mode 100644 index 0000000000..d558d6b847 --- /dev/null +++ b/lib/coreclr/src/inc/memoryrange.h @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// MemoryRange.h +// +// defines the code:MemoryRange class. +//***************************************************************************** + +#ifndef _memory_range_h +#define _memory_range_h + +#include "daccess.h" + +// MemoryRange is a descriptor of a memory range. This groups (pointer + size). +// +// Some key qualities: +// - simple! +// - Not mutable +// - blitabble descriptor which can be useful for out-of-process tools like the debugger. +// - no ownership semantics. +// - no manipulation, growing semantics. +// - no memory marshalling, allocation, copying. etc. +// - can be efficiently passed / copied / returned by value +// +// This class has general value as an abstraction to group pointer and size together. It also has significant +// value to the debugger. An expected design pattern is that other mutable complex data structures (eg, +// code:SBuffer, code:CGrowableStream) will provide an accessor to expose their underlying storage as a +// MemoryRange to debugger. This mirrors the Debugger's code:TargetBuffer data structure, but as a +// general-purpose VM utility versus a debugger right-side data structure. + +// +class MemoryRange +{ +public: + // Constructor to create a memory range around a (start address, size) pair. + MemoryRange() : + m_pStartAddress(NULL), + m_cbBytes(0) + { + SUPPORTS_DAC; + } + + MemoryRange(PTR_VOID pStartAddress, SIZE_T cbBytes) : + m_pStartAddress(pStartAddress), + m_cbBytes(cbBytes) + { + SUPPORTS_DAC; + } + + // Note: use compiler-default copy ctor and assignment operator + + + + // Check whether a pointer is in the memory range represented by this instance. + BOOL IsInRange(PTR_VOID pAddress) const + { + LIMITED_METHOD_DAC_CONTRACT; + + return (dac_cast(pAddress) - dac_cast(m_pStartAddress)) < m_cbBytes; + } + + // Check whether a pointer is in the memory range represented by this instance. + BOOL IsInRange(TADDR pAddress) const + { + LIMITED_METHOD_DAC_CONTRACT; + + return (pAddress - dac_cast(m_pStartAddress)) < m_cbBytes; + } + + // Get the starting address. + PTR_VOID StartAddress() const + { + SUPPORTS_DAC; + return m_pStartAddress; + } + + // Get the size of the range in bytes + SIZE_T Size() const + { + SUPPORTS_DAC; + return m_cbBytes; + } + +private: + // The start of the memory range. + PTR_VOID const m_pStartAddress; + + // The size of the memory range in bytes. + // This is s SIZE_T so that it can describe any memory range in the process (for example, larger than 4gb on 64-bit machines) + const SIZE_T m_cbBytes; + +}; + +typedef ArrayDPTR(MemoryRange) ARRAY_PTR_MemoryRange; + +#endif // _memory_range_h + diff --git a/lib/coreclr/src/inc/metadata.h b/lib/coreclr/src/inc/metadata.h new file mode 100644 index 0000000000..8fcf493a23 --- /dev/null +++ b/lib/coreclr/src/inc/metadata.h @@ -0,0 +1,1557 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//**************************************************************************** +// File: metadata.h +// + +// +// Notes: +// Common includes for EE & metadata internal. This file contains +// definition of CorMetaDataScope +//**************************************************************************** + +#ifndef _METADATA_H_ +#define _METADATA_H_ + +#include "../md/inc/metamodelro.h" +#include "../md/inc/liteweightstgdb.h" + +class UTSemReadWrite; + +inline int IsGlobalMethodParentTk(mdTypeDef td) +{ + LIMITED_METHOD_CONTRACT; + + return (td == mdTypeDefNil || td == mdTokenNil); +} + +typedef enum CorInternalStates +{ + tdNoTypes = 0x00000000, + tdAllAssemblies = 0x00000001, + tdAllTypes = 0xffffffff, +} CorInternalStates; + +// +// MetaData custom value names. +// +enum CorIfaceAttr +{ + ifDual = 0, // Interface derives from IDispatch. + ifVtable = 1, // Interface derives from IUnknown. + ifDispatch = 2, // Interface is a dispinterface. + ifInspectable = 3, // Interface derives from IInspectable. + ifLast = 4, // The last member of the enum. +}; + +inline BOOL IsDispatchBasedItf(CorIfaceAttr ifaceAttr) +{ + return (ifaceAttr == ifDual || ifaceAttr == ifDispatch); +} + +enum CorClassIfaceAttr +{ + clsIfNone = 0, // No class interface is generated. + clsIfAutoDisp = 1, // A dispatch only class interface is generated. + clsIfAutoDual = 2, // A dual class interface is generated. + clsIfLast = 3, // The last member of the enum. +}; + +// +// The default values for the COM interface and class interface types. +// +#define DEFAULT_COM_INTERFACE_TYPE ifDual +#define DEFAULT_CLASS_INTERFACE_TYPE clsIfAutoDisp + +#define HANDLE_UNCOMPRESSED(func) (E_FAIL) +#define HANDLE_UNCOMPRESSED_BOOL(func) (false) + +class TOKENLIST : public CDynArray +{ +}; + + +typedef enum tagEnumType +{ + MDSimpleEnum = 0x0, // simple enumerator that doesn't allocate memory + + // You could get this kind of enum if you perform a non-simple query (such as EnumMethodWithName). + // + MDDynamicArrayEnum = 0x2, // dynamic array that holds tokens + + MDCustomEnum = 0x3, // Custom enumerator that doesnt work with the enum functions +} EnumType; + +//***************************************** +// Enumerator used by MetaDataInternal +//***************************************** +struct HENUMInternal +{ + DWORD m_tkKind; // kind of tables that the enum is holding the result + ULONG m_ulCount; // count of total entries holding by the enumerator + + EnumType m_EnumType; + + struct { + ULONG m_ulStart; + ULONG m_ulEnd; + ULONG m_ulCur; + } u; + + // m_cursor will go away when we no longer support running EE with uncompressed + // format. WHEN WE REMOVE THIS, REMOVE ITS VESTIAGES FROM ZeroEnum as well + // + union { + void* m_alignpad; // The first item is m_cursor[] is a pointer + char m_cursor[32]; // cursor holding query result for read/write mode + }; + + // TOKENLIST daTKList; // dynamic arrays of token list + HENUMInternal() : m_EnumType(MDSimpleEnum) { LIMITED_METHOD_DAC_CONTRACT; } + + // in-place initialization + static void InitDynamicArrayEnum( + HENUMInternal *pEnum); // HENUMInternal to be initialized + + static void InitSimpleEnum( + DWORD tkKind, // kind of token that we are iterating + ULONG ridStart, // starting rid + ULONG ridEnd, // end rid + HENUMInternal *pEnum); // HENUMInternal to be initialized + + // Specialized helper which should be better than always calling memset + inline + static void ZeroEnum( + HENUMInternal *pEnum) + { + // we use this to avoid the memset that will happen otherwise. + // this should be inlined in its caller. we are seeing a large + // number of calls to memset from MDInternalRO::EnumPermissionSetsInit + // on x64 which we can eliminate with this code. + pEnum->m_tkKind = 0; + pEnum->m_ulCount = 0; + pEnum->m_EnumType = MDSimpleEnum; + pEnum->u.m_ulStart = 0; + pEnum->u.m_ulEnd = 0; + pEnum->u.m_ulCur = 0; + + // TODO: remove this when we remove m_cursor from the HENUMInternal structure + _ASSERTE(IS_ALIGNED(pEnum->m_cursor, sizeof(DWORD))); + _ASSERTE((sizeof(HENUMInternal) - offsetof(HENUMInternal, m_cursor)) == (8 * sizeof(DWORD))); + + DWORD* pBuffer = (DWORD*)pEnum->m_cursor; + pBuffer[0] = 0; + pBuffer[1] = 0; + pBuffer[2] = 0; + pBuffer[3] = 0; + pBuffer[4] = 0; + pBuffer[5] = 0; + pBuffer[6] = 0; + pBuffer[7] = 0; + } + + // This will only clear the content of enum and will not free the memory of enum + static void ClearEnum( + HENUMInternal *pmdEnum); + + // create a HENUMInternal. This will allocate the memory + __checkReturn + static HRESULT CreateSimpleEnum( + DWORD tkKind, // kind of token that we are iterating + ULONG ridStart, // starting rid + ULONG ridEnd, // end rid + HENUMInternal **ppEnum); // return the created HENUMInternal + + __checkReturn + static HRESULT CreateDynamicArrayEnum( + DWORD tkKind, // kind of token that we are iterating + HENUMInternal **ppEnum); // return the created HENUMInternal + + // Destory Enum. This will free the memory + static void DestroyEnum( + HENUMInternal *pmdEnum); + + static void DestroyEnumIfEmpty( + HENUMInternal **ppEnum); // reset the enumerator pointer to NULL if empty + + __checkReturn + static HRESULT EnumWithCount( + HENUMInternal *pEnum, // enumerator + ULONG cMax, // max tokens that caller wants + mdToken rTokens[], // output buffer to fill the tokens + ULONG *pcTokens); // number of tokens fill to the buffer upon return + + __checkReturn + static HRESULT EnumWithCount( + HENUMInternal *pEnum, // enumerator + ULONG cMax, // max tokens that caller wants + mdToken rTokens1[], // first output buffer to fill the tokens + mdToken rTokens2[], // second output buffer to fill the tokens + ULONG *pcTokens); // number of tokens fill to the buffer upon return + + __checkReturn + static HRESULT AddElementToEnum( + HENUMInternal *pEnum, // return the created HENUMInternal + mdToken tk); // token to fill + + //***************************************** + // Get next value contained in the enumerator + //***************************************** + static bool EnumNext( + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + mdToken *ptk); // [OUT] token to scope the search + + __checkReturn + static HRESULT GetCount( + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + ULONG *pCount); // ]OUT] the index of the desired item + + __checkReturn + static HRESULT GetElement( + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + ULONG ix, // ]IN] the index of the desired item + mdToken *ptk); // [OUT] token to fill + +}; + + + +//***************************************** +// Default Value for field, param or property. Returned by GetDefaultValue +//***************************************** +typedef struct _MDDefaultValue +{ +#if BIGENDIAN + _MDDefaultValue(void) + { + m_bType = ELEMENT_TYPE_END; + } + ~_MDDefaultValue(void) + { + if (m_bType == ELEMENT_TYPE_STRING) + { + delete[] m_wzValue; + } + } +#endif + + // type of default value + BYTE m_bType; // CorElementType for the default value + + // the default value + union + { + BOOL m_bValue; // ELEMENT_TYPE_BOOLEAN + CHAR m_cValue; // ELEMENT_TYPE_I1 + BYTE m_byteValue; // ELEMENT_TYPE_UI1 + SHORT m_sValue; // ELEMENT_TYPE_I2 + USHORT m_usValue; // ELEMENT_TYPE_UI2 + LONG m_lValue; // ELEMENT_TYPE_I4 + ULONG m_ulValue; // ELEMENT_TYPE_UI4 + LONGLONG m_llValue; // ELEMENT_TYPE_I8 + ULONGLONG m_ullValue; // ELEMENT_TYPE_UI8 + FLOAT m_fltValue; // ELEMENT_TYPE_R4 + DOUBLE m_dblValue; // ELEMENT_TYPE_R8 + LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING + IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS + }; + ULONG m_cbSize; // default value size (for blob) + +} MDDefaultValue; + + + +//***************************************** +// structure use to in GetAllEventAssociates and GetAllPropertyAssociates +//***************************************** +typedef struct +{ + mdMethodDef m_memberdef; + DWORD m_dwSemantics; +} ASSOCIATE_RECORD; + + +// +// structure use to retrieve class layout informaiton +// +typedef struct +{ + RID m_ridFieldCur; // indexing to the field table + RID m_ridFieldEnd; // end index to field table +} MD_CLASS_LAYOUT; + + +// Structure for describing the Assembly MetaData. +typedef struct +{ + USHORT usMajorVersion; // Major Version. + USHORT usMinorVersion; // Minor Version. + USHORT usBuildNumber; // Build Number. + USHORT usRevisionNumber; // Revision Number. + LPCSTR szLocale; // Locale. + DWORD *rProcessor; // Processor array. + ULONG ulProcessor; // [IN/OUT] Size of the processor array/Actual # of entries filled in. + OSINFO *rOS; // OSINFO array. + ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. +} AssemblyMetaDataInternal; + + + +// Callback definition for comparing signatures. +// (*PSIGCOMPARE) (BYTE ScopeSignature[], DWORD ScopeSignatureLength, +// BYTE ExternalSignature[], DWORD ExternalSignatureLength, +// void* SignatureData); +typedef BOOL (*PSIGCOMPARE)(PCCOR_SIGNATURE, DWORD, PCCOR_SIGNATURE, DWORD, void*); + + + +// {CE0F34ED-BBC6-11d2-941E-0000F8083460} +EXTERN_GUID(IID_IMDInternalImport, 0xce0f34ed, 0xbbc6, 0x11d2, 0x94, 0x1e, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); + +#undef INTERFACE +#define INTERFACE IMDInternalImport +DECLARE_INTERFACE_(IMDInternalImport, IUnknown) +{ + //---------------------------------------------------------------------------------------- + // !!! READ THIS !!! + // + // New methods have to be added at the end. The order and signatures of the existing methods + // have to be preserved. We need to maintain a backward compatibility for this interface to + // allow ildasm to work on SingleCLR. + // + //---------------------------------------------------------------------------------------- + + //***************************************************************************** + // return the count of entries of a given kind in a scope + // For example, pass in mdtMethodDef will tell you how many MethodDef + // contained in a scope + //***************************************************************************** + STDMETHOD_(ULONG, GetCountWithTokenKind)(// return hresult + DWORD tkKind) PURE; // [IN] pass in the kind of token. + + //***************************************************************************** + // enumerator for typedef + //***************************************************************************** + __checkReturn + STDMETHOD(EnumTypeDefInit)( // return hresult + HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data + + STDMETHOD_(ULONG, EnumTypeDefGetCount)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information + + STDMETHOD_(void, EnumTypeDefReset)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information + + STDMETHOD_(bool, EnumTypeDefNext)( // return hresult + HENUMInternal *phEnum, // [IN] input enum + mdTypeDef *ptd) PURE; // [OUT] return token + + STDMETHOD_(void, EnumTypeDefClose)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information + + //***************************************************************************** + // enumerator for MethodImpl + //***************************************************************************** + __checkReturn + STDMETHOD(EnumMethodImplInit)( // return hresult + mdTypeDef td, // [IN] TypeDef over which to scope the enumeration. + HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens. + HENUMInternal *phEnumDecl) PURE; // [OUT] buffer to fill for enumerator data for MethodDecl tokens. + + STDMETHOD_(ULONG, EnumMethodImplGetCount)( + HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. + HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. + + STDMETHOD_(void, EnumMethodImplReset)( + HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. + HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. + + __checkReturn + STDMETHOD(EnumMethodImplNext)( // return hresult (S_OK = TRUE, S_FALSE = FALSE or error code) + HENUMInternal *phEnumBody, // [IN] input enum for MethodBody + HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl + mdToken *ptkBody, // [OUT] return token for MethodBody + mdToken *ptkDecl) PURE; // [OUT] return token for MethodDecl + + STDMETHOD_(void, EnumMethodImplClose)( + HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. + HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. + + //***************************************** + // Enumerator helpers for memberdef, memberref, interfaceimp, + // event, property, exception, param + //***************************************** + + __checkReturn + STDMETHOD(EnumGlobalFunctionsInit)( // return hresult + HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data + + __checkReturn + STDMETHOD(EnumGlobalFieldsInit)( // return hresult + HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data + + __checkReturn + STDMETHOD(EnumInit)( // return S_FALSE if record not found + DWORD tkKind, // [IN] which table to work on + mdToken tkParent, // [IN] token to scope the search + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + + __checkReturn + STDMETHOD(EnumAllInit)( // return S_FALSE if record not found + DWORD tkKind, // [IN] which table to work on + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + + STDMETHOD_(bool, EnumNext)( + HENUMInternal *phEnum, // [IN] the enumerator to retrieve information + mdToken *ptk) PURE; // [OUT] token to scope the search + + STDMETHOD_(ULONG, EnumGetCount)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to retrieve information + + STDMETHOD_(void, EnumReset)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to be reset + + STDMETHOD_(void, EnumClose)( + HENUMInternal *phEnum) PURE; // [IN] the enumerator to be closed + + //***************************************** + // Enumerator helpers for declsecurity. + //***************************************** + __checkReturn + STDMETHOD(EnumPermissionSetsInit)( // return S_FALSE if record not found + mdToken tkParent, // [IN] token to scope the search + CorDeclSecurity Action, // [IN] Action to scope the search + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + + //***************************************** + // Enumerator helpers for CustomAttribute + //***************************************** + __checkReturn + STDMETHOD(EnumCustomAttributeByNameInit)(// return S_FALSE if record not found + mdToken tkParent, // [IN] token to scope the search + LPCSTR szName, // [IN] CustomAttribute's name to scope the search + HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill + + //***************************************** + // Nagivator helper to navigate back to the parent token given a token. + // For example, given a memberdef token, it will return the containing typedef. + // + // the mapping is as following: + // ---given child type---------parent type + // mdMethodDef mdTypeDef + // mdFieldDef mdTypeDef + // mdInterfaceImpl mdTypeDef + // mdParam mdMethodDef + // mdProperty mdTypeDef + // mdEvent mdTypeDef + // + //***************************************** + __checkReturn + STDMETHOD(GetParentToken)( + mdToken tkChild, // [IN] given child token + mdToken *ptkParent) PURE; // [OUT] returning parent + + //***************************************** + // Custom value helpers + //***************************************** + __checkReturn + STDMETHOD(GetCustomAttributeProps)( // S_OK or error. + mdCustomAttribute at, // [IN] The attribute. + mdToken *ptkType) PURE; // [OUT] Put attribute type here. + + __checkReturn + STDMETHOD(GetCustomAttributeAsBlob)( + mdCustomAttribute cv, // [IN] given custom value token + void const **ppBlob, // [OUT] return the pointer to internal blob + ULONG *pcbSize) PURE; // [OUT] return the size of the blob + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD (GetScopeProps)( + LPCSTR *pszName, // [OUT] scope name + GUID *pmvid) PURE; // [OUT] version id + + // finding a particular method + __checkReturn + STDMETHOD(FindMethodDef)( + mdTypeDef classdef, // [IN] given typedef + LPCSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + mdMethodDef *pmd) PURE; // [OUT] matching memberdef + + // return a iSeq's param given a MethodDef + __checkReturn + STDMETHOD(FindParamOfMethod)( // S_OK or error. + mdMethodDef md, // [IN] The owning method of the param. + ULONG iSeq, // [IN] The sequence # of the param. + mdParamDef *pparamdef) PURE; // [OUT] Put ParamDef token here. + + //***************************************** + // + // GetName* functions + // + //***************************************** + + // return the name and namespace of typedef + __checkReturn + STDMETHOD(GetNameOfTypeDef)( + mdTypeDef classdef, // given classdef + LPCSTR *pszname, // return class name(unqualified) + LPCSTR *psznamespace) PURE; // return the name space name + + __checkReturn + STDMETHOD(GetIsDualOfTypeDef)( + mdTypeDef classdef, // [IN] given classdef. + ULONG *pDual) PURE; // [OUT] return dual flag here. + + __checkReturn + STDMETHOD(GetIfaceTypeOfTypeDef)( + mdTypeDef classdef, // [IN] given classdef. + ULONG *pIface) PURE; // [OUT] 0=dual, 1=vtable, 2=dispinterface + + // get the name of either methoddef + __checkReturn + STDMETHOD(GetNameOfMethodDef)( // return the name of the memberdef in UTF8 + mdMethodDef md, // given memberdef + LPCSTR *pszName) PURE; + + __checkReturn + STDMETHOD(GetNameAndSigOfMethodDef)( + mdMethodDef methoddef, // [IN] given memberdef + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature + ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob + LPCSTR *pszName) PURE; + + // return the name of a FieldDef + __checkReturn + STDMETHOD(GetNameOfFieldDef)( + mdFieldDef fd, // given memberdef + LPCSTR *pszName) PURE; + + // return the name of typeref + __checkReturn + STDMETHOD(GetNameOfTypeRef)( + mdTypeRef classref, // [IN] given typeref + LPCSTR *psznamespace, // [OUT] return typeref name + LPCSTR *pszname) PURE; // [OUT] return typeref namespace + + // return the resolutionscope of typeref + __checkReturn + STDMETHOD(GetResolutionScopeOfTypeRef)( + mdTypeRef classref, // given classref + mdToken *ptkResolutionScope) PURE; + + // Find the type token given the name. + __checkReturn + STDMETHOD(FindTypeRefByName)( + LPCSTR szNamespace, // [IN] Namespace for the TypeRef. + LPCSTR szName, // [IN] Name of the TypeRef. + mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef. + mdTypeRef *ptk) PURE; // [OUT] TypeRef token returned. + + // return the TypeDef properties + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetTypeDefProps)( + mdTypeDef classdef, // given classdef + DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract + mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here + + // return the item's guid + __checkReturn + STDMETHOD(GetItemGuid)( + mdToken tkObj, // [IN] given item. + CLSID *pGuid) PURE; // [out[ put guid here. + + // Get enclosing class of the NestedClass. + __checkReturn + STDMETHOD(GetNestedClassProps)( // S_OK or error + mdTypeDef tkNestedClass, // [IN] NestedClass token. + mdTypeDef *ptkEnclosingClass) PURE; // [OUT] EnclosingClass token. + + // Get count of Nested classes given the enclosing class. + __checkReturn + STDMETHOD(GetCountNestedClasses)( // return count of Nested classes. + mdTypeDef tkEnclosingClass, // Enclosing class. + ULONG *pcNestedClassesCount) PURE; + + // Return array of Nested classes given the enclosing class. + __checkReturn + STDMETHOD(GetNestedClasses)( // Return actual count. + mdTypeDef tkEnclosingClass, // [IN] Enclosing class. + mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens. + ULONG ulNestedClasses, // [IN] Size of array. + ULONG *pcNestedClasses) PURE; + + // return the ModuleRef properties + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetModuleRefProps)( + mdModuleRef mur, // [IN] moduleref token + LPCSTR *pszName) PURE; // [OUT] buffer to fill with the moduleref name + + //***************************************** + // + // GetSig* functions + // + //***************************************** + __checkReturn + STDMETHOD(GetSigOfMethodDef)( + mdMethodDef tkMethodDef, // [IN] given MethodDef + ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob + PCCOR_SIGNATURE * ppSig) PURE; + + __checkReturn + STDMETHOD(GetSigOfFieldDef)( + mdFieldDef tkFieldDef, // [IN] given FieldDef + ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob + PCCOR_SIGNATURE * ppSig) PURE; + + __checkReturn + STDMETHOD(GetSigFromToken)( + mdToken tk, // FieldDef, MethodDef, Signature or TypeSpec token + ULONG * pcbSig, + PCCOR_SIGNATURE * ppSig) PURE; + + + + //***************************************** + // get method property + //***************************************** + __checkReturn + STDMETHOD(GetMethodDefProps)( + mdMethodDef md, // The method for which to get props. + DWORD *pdwFlags) PURE; + + //***************************************** + // return method implementation informaiton, like RVA and implflags + //***************************************** + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetMethodImplProps)( + mdToken tk, // [IN] MethodDef + ULONG *pulCodeRVA, // [OUT] CodeRVA + DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags + + //***************************************** + // return method implementation informaiton, like RVA and implflags + //***************************************** + __checkReturn + STDMETHOD(GetFieldRVA)( + mdFieldDef fd, // [IN] fielddef + ULONG *pulCodeRVA) PURE; // [OUT] CodeRVA + + //***************************************** + // get field property + //***************************************** + __checkReturn + STDMETHOD(GetFieldDefProps)( + mdFieldDef fd, // [IN] given fielddef + DWORD *pdwFlags) PURE; // [OUT] return fdPublic, fdPrive, etc flags + + //***************************************************************************** + // return default value of a token(could be paramdef, fielddef, or property + //***************************************************************************** + __checkReturn + STDMETHOD(GetDefaultValue)( + mdToken tk, // [IN] given FieldDef, ParamDef, or Property + MDDefaultValue *pDefaultValue) PURE;// [OUT] default value to fill + + + //***************************************** + // get dispid of a MethodDef or a FieldDef + //***************************************** + __checkReturn + STDMETHOD(GetDispIdOfMemberDef)( // return hresult + mdToken tk, // [IN] given methoddef or fielddef + ULONG *pDispid) PURE; // [OUT] Put the dispid here. + + //***************************************** + // return TypeRef/TypeDef given an InterfaceImpl token + //***************************************** + __checkReturn + STDMETHOD(GetTypeOfInterfaceImpl)( // return the TypeRef/typedef token for the interfaceimpl + mdInterfaceImpl iiImpl, // given a interfaceimpl + mdToken *ptkType) PURE; + + //***************************************** + // look up function for TypeDef + //***************************************** + __checkReturn + STDMETHOD(FindTypeDef)( + LPCSTR szNamespace, // [IN] Namespace for the TypeDef. + LPCSTR szName, // [IN] Name of the TypeDef. + mdToken tkEnclosingClass, // [IN] TypeRef/TypeDef Token for the enclosing class. + mdTypeDef *ptypedef) PURE; // [IN] return typedef + + //***************************************** + // return name and sig of a memberref + //***************************************** + __checkReturn + STDMETHOD(GetNameAndSigOfMemberRef)( // return name here + mdMemberRef memberref, // given memberref + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature + ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob + LPCSTR *pszName) PURE; + + //***************************************************************************** + // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef + //***************************************************************************** + __checkReturn + STDMETHOD(GetParentOfMemberRef)( + mdMemberRef memberref, // given memberref + mdToken *ptkParent) PURE; // return the parent token + + __checkReturn + STDMETHOD(GetParamDefProps)( + mdParamDef paramdef, // given a paramdef + USHORT *pusSequence, // [OUT] slot number for this parameter + DWORD *pdwAttr, // [OUT] flags + LPCSTR *pszName) PURE; // [OUT] return the name of the parameter + + __checkReturn + STDMETHOD(GetPropertyInfoForMethodDef)( // Result. + mdMethodDef md, // [IN] memberdef + mdProperty *ppd, // [OUT] put property token here + LPCSTR *pName, // [OUT] put pointer to name here + ULONG *pSemantic) PURE; // [OUT] put semantic here + + //***************************************** + // class layout/sequence information + //***************************************** + __checkReturn + STDMETHOD(GetClassPackSize)( // return error if class doesn't have packsize + mdTypeDef td, // [IN] give typedef + ULONG *pdwPackSize) PURE; // [OUT] 1, 2, 4, 8, or 16 + + __checkReturn + STDMETHOD(GetClassTotalSize)( // return error if class doesn't have total size info + mdTypeDef td, // [IN] give typedef + ULONG *pdwClassSize) PURE; // [OUT] return the total size of the class + + __checkReturn + STDMETHOD(GetClassLayoutInit)( + mdTypeDef td, // [IN] give typedef + MD_CLASS_LAYOUT *pLayout) PURE; // [OUT] set up the status of query here + + __checkReturn + STDMETHOD(GetClassLayoutNext)( + MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here + mdFieldDef *pfd, // [OUT] return the fielddef + ULONG *pulOffset) PURE; // [OUT] return the offset/ulSequence associate with it + + //***************************************** + // marshal information of a field + //***************************************** + __checkReturn + STDMETHOD(GetFieldMarshal)( // return error if no native type associate with the token + mdFieldDef fd, // [IN] given fielddef + PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature + ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType + + + //***************************************** + // property APIs + //***************************************** + // find a property by name + __checkReturn + STDMETHOD(FindProperty)( + mdTypeDef td, // [IN] given a typdef + LPCSTR szPropName, // [IN] property name + mdProperty *pProp) PURE; // [OUT] return property token + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetPropertyProps)( + mdProperty prop, // [IN] property token + LPCSTR *szProperty, // [OUT] property name + DWORD *pdwPropFlags, // [OUT] property flags. + PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob + ULONG *pcbSig) PURE; // [OUT] count of bytes in *ppvSig + + //********************************** + // Event APIs + //********************************** + __checkReturn + STDMETHOD(FindEvent)( + mdTypeDef td, // [IN] given a typdef + LPCSTR szEventName, // [IN] event name + mdEvent *pEvent) PURE; // [OUT] return event token + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetEventProps)( + mdEvent ev, // [IN] event token + LPCSTR *pszEvent, // [OUT] Event name + DWORD *pdwEventFlags, // [OUT] Event flags. + mdToken *ptkEventType) PURE; // [OUT] EventType class + + + //********************************** + // find a particular associate of a property or an event + //********************************** + __checkReturn + STDMETHOD(FindAssociate)( + mdToken evprop, // [IN] given a property or event token + DWORD associate, // [IN] given a associate semantics(setter, getter, testdefault, reset, AddOn, RemoveOn, Fire) + mdMethodDef *pmd) PURE; // [OUT] return method def token + + // Note, void function in v1.0/v1.1 + __checkReturn + STDMETHOD(EnumAssociateInit)( + mdToken evprop, // [IN] given a property or an event token + HENUMInternal *phEnum) PURE; // [OUT] cursor to hold the query result + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetAllAssociates)( + HENUMInternal *phEnum, // [IN] query result form GetPropertyAssociateCounts + ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output + ULONG cAssociateRec) PURE; // [IN] size of the buffer + + + //********************************** + // Get info about a PermissionSet. + //********************************** + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetPermissionSetProps)( + mdPermission pm, // [IN] the permission token. + DWORD *pdwAction, // [OUT] CorDeclSecurity. + void const **ppvPermission, // [OUT] permission blob. + ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. + + //**************************************** + // Get the String given the String token. + // Returns a pointer to the string, or NULL in case of error. + //**************************************** + __checkReturn + STDMETHOD(GetUserString)( + mdString stk, // [IN] the string token. + ULONG *pchString, // [OUT] count of characters in the string. + BOOL *pbIs80Plus, // [OUT] specifies where there are extended characters >= 0x80. + LPCWSTR *pwszUserString) PURE; + + //***************************************************************************** + // p-invoke APIs. + //***************************************************************************** + __checkReturn + STDMETHOD(GetPinvokeMap)( + mdToken tk, // [IN] FieldDef, MethodDef. + DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. + LPCSTR *pszImportName, // [OUT] Import name. + mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. + + //***************************************************************************** + // helpers to convert a text signature to a com format + //***************************************************************************** + __checkReturn + STDMETHOD(ConvertTextSigToComSig)( // Return hresult. + BOOL fCreateTrIfNotFound, // [IN] create typeref if not found + LPCSTR pSignature, // [IN] class file format signature + CQuickBytes *pqbNewSig, // [OUT] place holder for CLR signature + ULONG *pcbCount) PURE; // [OUT] the result size of signature + + //***************************************************************************** + // Assembly MetaData APIs. + //***************************************************************************** + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetAssemblyProps)( + mdAssembly mda, // [IN] The Assembly for which to get the properties. + const void **ppbPublicKey, // [OUT] Pointer to the public key. + ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. + ULONG *pulHashAlgId, // [OUT] Hash Algorithm. + LPCSTR *pszName, // [OUT] Buffer to fill with name. + AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. + DWORD *pdwAssemblyFlags) PURE;// [OUT] Flags. + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetAssemblyRefProps)( + mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. + const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. + ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. + LPCSTR *pszName, // [OUT] Buffer to fill with name. + AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. + const void **ppbHashValue, // [OUT] Hash blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. + DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetFileProps)( + mdFile mdf, // [IN] The File for which to get the properties. + LPCSTR *pszName, // [OUT] Buffer to fill with name. + const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. + ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. + DWORD *pdwFileFlags) PURE; // [OUT] Flags. + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetExportedTypeProps)( + mdExportedType mdct, // [IN] The ExportedType for which to get the properties. + LPCSTR *pszNamespace, // [OUT] Namespace. + LPCSTR *pszName, // [OUT] Name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. + mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. + DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. + + // returned void in v1.0/v1.1 + __checkReturn + STDMETHOD(GetManifestResourceProps)( + mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. + LPCSTR *pszName, // [OUT] Buffer to fill with name. + mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. + DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. + DWORD *pdwResourceFlags) PURE;// [OUT] Flags. + + __checkReturn + STDMETHOD(FindExportedTypeByName)( // S_OK or error + LPCSTR szNamespace, // [IN] Namespace of the ExportedType. + LPCSTR szName, // [IN] Name of the ExportedType. + mdExportedType tkEnclosingType, // [IN] ExportedType for the enclosing class. + mdExportedType *pmct) PURE; // [OUT] Put ExportedType token here. + + __checkReturn + STDMETHOD(FindManifestResourceByName)( // S_OK or error + LPCSTR szName, // [IN] Name of the ManifestResource. + mdManifestResource *pmmr) PURE; // [OUT] Put ManifestResource token here. + + __checkReturn + STDMETHOD(GetAssemblyFromScope)( // S_OK or error + mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. + + __checkReturn + STDMETHOD(GetCustomAttributeByName)( // S_OK or error + mdToken tkObj, // [IN] Object with Custom Attribute. + LPCUTF8 szName, // [IN] Name of desired Custom Attribute. + const void **ppData, // [OUT] Put pointer to data here. + ULONG *pcbData) PURE; // [OUT] Put size of data here. + + // Note: The return type of this method was void in v1 + __checkReturn + STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. + mdTypeSpec typespec, // [IN] Signature token. + PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. + ULONG *pcbSig) PURE; // [OUT] return size of signature. + + __checkReturn + STDMETHOD(SetUserContextData)( // S_OK or E_NOTIMPL + IUnknown *pIUnk) PURE; // The user context. + + __checkReturn + STDMETHOD_(BOOL, IsValidToken)( // True or False. + mdToken tk) PURE; // [IN] Given token. + + __checkReturn + STDMETHOD(TranslateSigWithScope)( + IMDInternalImport *pAssemImport, // [IN] import assembly scope. + const void *pbHashValue, // [IN] hash value for the import assembly. + ULONG cbHashValue, // [IN] count of bytes in the hash value. + PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope + ULONG cbSigBlob, // [IN] count of bytes of signature + IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope. + IMetaDataEmit *emit, // [IN] emit interface + CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature + ULONG *pcbSig) PURE; // [OUT] count of bytes in the translated signature + + STDMETHOD_(IMetaModelCommon*, GetMetaModelCommon)( // Return MetaModelCommon interface. + ) PURE; + + STDMETHOD_(IUnknown *, GetCachedPublicInterface)(BOOL fWithLock) PURE; // return the cached public interface + __checkReturn + STDMETHOD(SetCachedPublicInterface)(IUnknown *pUnk) PURE; // no return value + STDMETHOD_(UTSemReadWrite*, GetReaderWriterLock)() PURE; // return the reader writer lock + __checkReturn + STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; + + STDMETHOD_(mdModule, GetModuleFromScope)() PURE; // [OUT] Put mdModule token here. + + + //----------------------------------------------------------------- + // Additional custom methods + + // finding a particular method + __checkReturn + STDMETHOD(FindMethodDefUsingCompare)( + mdTypeDef classdef, // [IN] given typedef + LPCSTR szName, // [IN] member name + PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature + ULONG cbSigBlob, // [IN] count of bytes in the signature blob + PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures + void* pSignatureArgs, // [IN] Additional info to supply the compare function + mdMethodDef *pmd) PURE; // [OUT] matching memberdef + + // Additional v2 methods. + + //***************************************** + // return a field offset for a given field + //***************************************** + __checkReturn + STDMETHOD(GetFieldOffset)( + mdFieldDef fd, // [IN] fielddef + ULONG *pulOffset) PURE; // [OUT] FieldOffset + + __checkReturn + STDMETHOD(GetMethodSpecProps)( + mdMethodSpec ms, // [IN] The method instantiation + mdToken *tkParent, // [OUT] MethodDef or MemberRef + PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data + ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob + + __checkReturn + STDMETHOD(GetTableInfoWithIndex)( + ULONG index, // [IN] pass in the table index + void **pTable, // [OUT] pointer to table at index + void **pTableSize) PURE; // [OUT] size of table at index + + __checkReturn + STDMETHOD(ApplyEditAndContinue)( + void *pDeltaMD, // [IN] the delta metadata + ULONG cbDeltaMD, // [IN] length of pData + IMDInternalImport **ppv) PURE; // [OUT] the resulting metadata interface + + //********************************** + // Generics APIs + //********************************** + __checkReturn + STDMETHOD(GetGenericParamProps)( // S_OK or error. + mdGenericParam rd, // [IN] The type parameter + ULONG* pulSequence, // [OUT] Parameter sequence number + DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) + mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) + DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use) + LPCSTR *szName) PURE; // [OUT] The name + + __checkReturn + STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. + mdGenericParamConstraint rd, // [IN] The constraint token + mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained + mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint + + //***************************************************************************** + // This function gets the "built for" version of a metadata scope. + // NOTE: if the scope has never been saved, it will not have a built-for + // version, and an empty string will be returned. + //***************************************************************************** + __checkReturn + STDMETHOD(GetVersionString)( // S_OK or error. + LPCSTR *pVer) PURE; // [OUT] Put version string here. + + + __checkReturn + STDMETHOD(SafeAndSlowEnumCustomAttributeByNameInit)(// return S_FALSE if record not found + mdToken tkParent, // [IN] token to scope the search + LPCSTR szName, // [IN] CustomAttribute's name to scope the search + HENUMInternal *phEnum) PURE; // [OUT] The enumerator + + __checkReturn + STDMETHOD(SafeAndSlowEnumCustomAttributeByNameNext)(// return S_FALSE if record not found + mdToken tkParent, // [IN] token to scope the search + LPCSTR szName, // [IN] CustomAttribute's name to scope the search + HENUMInternal *phEnum, // [IN] The enumerator + mdCustomAttribute *mdAttribute) PURE; // [OUT] The custom attribute that was found + + + __checkReturn + STDMETHOD(GetTypeDefRefTokenInTypeSpec)(// return S_FALSE if enclosing type does not have a token + mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at + mdToken *tkEnclosedToken) PURE; // [OUT] The enclosed type token + +#define MD_STREAM_VER_1X 0x10000 +#define MD_STREAM_VER_2_B1 0x10001 +#define MD_STREAM_VER_2 0x20000 + STDMETHOD_(DWORD, GetMetadataStreamVersion)() PURE; //returns DWORD with major version of + // MD stream in senior word and minor version--in junior word + + __checkReturn + STDMETHOD(GetNameOfCustomAttribute)(// S_OK or error + mdCustomAttribute mdAttribute, // [IN] The Custom Attribute + LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute. + LPCUTF8 *pszName) PURE; // [OUT] Name of Custom Attribute. + + STDMETHOD(SetOptimizeAccessForSpeed)(// S_OK or error + BOOL fOptSpeed) PURE; + + STDMETHOD(SetVerifiedByTrustedSource)(// S_OK or error + BOOL fVerified) PURE; + + STDMETHOD(GetRvaOffsetData)( + DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table. + DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table. + DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table. + DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table. + DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table. + DWORD *pFieldRvaCount // [OUT] Number of records in FieldRVA table. + ) PURE; + + //---------------------------------------------------------------------------------------- + // !!! READ THIS !!! + // + // New methods have to be added at the end. The order and signatures of the existing methods + // have to be preserved. We need to maintain a backward compatibility for this interface to + // allow ildasm to work on SingleCLR. + // + //---------------------------------------------------------------------------------------- + +}; // IMDInternalImport + + +// {E03D7730-D7E3-11d2-8C0D-00C04FF7431A} +EXTERN_GUID(IID_IMDInternalImportENC, 0xe03d7730, 0xd7e3, 0x11d2, 0x8c, 0xd, 0x0, 0xc0, 0x4f, 0xf7, 0x43, 0x1a); + +#undef INTERFACE +#define INTERFACE IMDInternalImportENC +DECLARE_INTERFACE_(IMDInternalImportENC, IMDInternalImport) +{ +private: + using IMDInternalImport::ApplyEditAndContinue; +public: + // ENC only methods here. + STDMETHOD(ApplyEditAndContinue)( // S_OK or error. + MDInternalRW *pDelta) PURE; // Interface to MD with the ENC delta. + + STDMETHOD(EnumDeltaTokensInit)( // return hresult + HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data + +}; // IMDInternalImportENC + +// {F102C526-38CB-49ed-9B5F-498816AE36E0} +EXTERN_GUID(IID_IMDInternalEmit, 0xf102c526, 0x38cb, 0x49ed, 0x9b, 0x5f, 0x49, 0x88, 0x16, 0xae, 0x36, 0xe0); + +#undef INTERFACE +#define INTERFACE IMDInternalEmit +DECLARE_INTERFACE_(IMDInternalEmit, IUnknown) +{ + STDMETHOD(ChangeMvid)( // S_OK or error. + REFGUID newMvid) PURE; // GUID to use as the MVID + + STDMETHOD(SetMDUpdateMode)( + ULONG updateMode, ULONG *pPreviousUpdateMode) PURE; + +}; // IMDInternalEmit + +#ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE + +struct IMDCustomDataSource; + +#include "../md/inc/metamodel.h" + +// {CC0C8F7A-A00B-493D-80B6-CE0C92491670} +EXTERN_GUID(IID_IMDCustomDataSource, 0xcc0c8f7a, 0xa00b, 0x493d, 0x80, 0xb6, 0xce, 0xc, 0x92, 0x49, 0x16, 0x70); + +#undef INTERFACE +#define INTERFACE IMDCustomDataSource +DECLARE_INTERFACE_(IMDCustomDataSource, IUnknown) +{ + STDMETHOD(GetSchema)(CMiniMdSchema* pSchema) PURE; + STDMETHOD(GetTableDef)(ULONG32 tableIndex, CMiniTableDef* pTableDef) PURE; + STDMETHOD(GetBlobHeap)(MetaData::DataBlob* pBlobHeapData) PURE; + STDMETHOD(GetGuidHeap)(MetaData::DataBlob* pGuidHeapData) PURE; + STDMETHOD(GetStringHeap)(MetaData::DataBlob* pStringHeapData) PURE; + STDMETHOD(GetUserStringHeap)(MetaData::DataBlob* pUserStringHeapData) PURE; + STDMETHOD(GetTableRecords)(ULONG32 tableIndex, MetaData::DataBlob* pTableRecordData) PURE; + STDMETHOD(GetTableSortable)(ULONG32 tableIndex, BOOL* pSortable) PURE; + STDMETHOD(GetStorageSignature)(MetaData::DataBlob* pStorageSignature) PURE; + +}; // IMDCustomDataSource + +// {503F79FB-7AAE-4364-BDA6-8E235D173AEC} +EXTERN_GUID(IID_IMetaDataDispenserCustom, + 0x503f79fb, 0x7aae, 0x4364, 0xbd, 0xa6, 0x8e, 0x23, 0x5d, 0x17, 0x3a, 0xec); + +#undef INTERFACE +#define INTERFACE IMetaDataDispenserCustom +DECLARE_INTERFACE_(IMetaDataDispenserCustom, IUnknown) +{ + STDMETHOD(OpenScopeOnCustomDataSource)( // Return code. + IMDCustomDataSource *pCustomSource, // [in] The scope to open. + DWORD dwOpenFlags, // [in] Open mode flags. + REFIID riid, // [in] The interface desired. + IUnknown **ppIUnk) PURE; // [out] Return interface on success. + +}; // IMetaDataDispenserCustom + +#endif // FEATURE_METADATA_CUSTOM_DATA_SOURCE + +#ifdef FEATURE_METADATA_DEBUGGEE_DATA_SOURCE +struct ICorDebugDataTarget; +HRESULT CreateRemoteMDInternalRWSource(TADDR mdInternalRWRemoteAddress, ICorDebugDataTarget* pDataTarget, DWORD defines, DWORD dataStructureVersion, IMDCustomDataSource** ppDataSource); +#endif + +#ifdef __HOLDER_H_ + +void DECLSPEC_NORETURN ThrowHR(HRESULT hr); + +// This wrapper class ensures that the HENUMInternal is EnumTypeDefClose'd no matter how the scope is exited. +class HENUMTypeDefInternalHolder +{ +public: + FORCEINLINE HENUMTypeDefInternalHolder(IMDInternalImport *pInternalImport) + { + WRAPPER_NO_CONTRACT; + + m_pInternalImport = pInternalImport; + m_fAcquired = FALSE; + } + + FORCEINLINE VOID EnumTypeDefInit() + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); + if (FAILED(hr)) + { + ThrowHR(hr); + } + m_fAcquired = TRUE; + + } + + FORCEINLINE HRESULT EnumTypeDefInitNoThrow() + { + WRAPPER_NO_CONTRACT; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); + if (FAILED(hr)) + { + return hr; + } + m_fAcquired = TRUE; + + return hr; + } + + FORCEINLINE ~HENUMTypeDefInternalHolder() + { + WRAPPER_NO_CONTRACT; + + if (m_fAcquired) + { + m_pInternalImport->EnumTypeDefClose(&m_hEnum); + } + } + + FORCEINLINE HENUMInternal* operator& () + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(m_fAcquired); + return &m_hEnum; + } + +private: + FORCEINLINE HENUMTypeDefInternalHolder(const HENUMTypeDefInternalHolder &) + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(!"Don't try to assign this class."); + } + +private: + IMDInternalImport *m_pInternalImport; + HENUMInternal m_hEnum; + BOOL m_fAcquired; +}; + + +// This wrapper class ensures that the HENUMInternal is EnumClose'd no matter how the scope is exited. +class HENUMInternalHolder +{ +public: + FORCEINLINE HENUMInternalHolder(IMDInternalImport *pInternalImport) + { + WRAPPER_NO_CONTRACT; + + m_pInternalImport = pInternalImport; + m_fAcquired = FALSE; + } + + FORCEINLINE BOOL EnumPermissionSetsInit(mdToken tkToken, CorDeclSecurity action) + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumPermissionSetsInit(tkToken, action, &m_hEnum); + + if (hr == CLDB_E_RECORD_NOTFOUND) + return FALSE; + + if (FAILED(hr) ) + { + ThrowHR(hr); + } + + m_fAcquired = TRUE; + + return TRUE; + } + + FORCEINLINE VOID EnumGlobalFunctionsInit() + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumGlobalFunctionsInit(&m_hEnum); + if (FAILED(hr)) + { + ThrowHR(hr); + } + m_fAcquired = TRUE; + + } + + + FORCEINLINE VOID EnumGlobalFieldsInit() + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumGlobalFieldsInit(&m_hEnum); + if (FAILED(hr)) + { + ThrowHR(hr); + } + m_fAcquired = TRUE; + + } + + FORCEINLINE VOID EnumTypeDefInit() + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); + if (FAILED(hr)) + { + ThrowHR(hr); + } + m_fAcquired = TRUE; + } + + FORCEINLINE VOID EnumAssociateInit(mdToken tkParent) // [IN] token to scope the search + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + IfFailThrow(m_pInternalImport->EnumAssociateInit(tkParent, &m_hEnum)); + m_fAcquired = TRUE; + } + + FORCEINLINE VOID EnumInit(DWORD tkKind, // [IN] which table to work on + mdToken tkParent // [IN] token to scope the search + ) + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + HRESULT hr = EnumInitNoThrow(tkKind, tkParent); + if (FAILED(hr)) + { + ThrowHR(hr); + } + } + + __checkReturn + FORCEINLINE HRESULT EnumInitNoThrow(DWORD tkKind, // [IN] which table to work on + mdToken tkParent // [IN] token to scope the search + ) + { + CONTRACTL { + NOTHROW; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumInit(tkKind, tkParent, &m_hEnum); + if (SUCCEEDED(hr)) + { + m_fAcquired = TRUE; + } + return hr; + } + + FORCEINLINE VOID EnumAllInit(DWORD tkKind // [IN] which table to work on + ) + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumAllInit(tkKind, &m_hEnum); + if (FAILED(hr)) + { + ThrowHR(hr); + } + m_fAcquired = TRUE; + + } + + FORCEINLINE ULONG EnumGetCount() + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + CONSISTENCY_CHECK(m_fAcquired); + } CONTRACTL_END; + + return m_pInternalImport->EnumGetCount(&m_hEnum); + } + + FORCEINLINE bool EnumNext(mdToken * pTok) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + CONSISTENCY_CHECK(m_fAcquired); + } CONTRACTL_END; + + return m_pInternalImport->EnumNext(&m_hEnum, pTok); + } + + FORCEINLINE void EnumReset() + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + CONSISTENCY_CHECK(m_fAcquired); + } CONTRACTL_END; + + return m_pInternalImport->EnumReset(&m_hEnum); + } + + FORCEINLINE ~HENUMInternalHolder() + { + WRAPPER_NO_CONTRACT; + + if (m_fAcquired) + { + // Ignore the error + (void)m_pInternalImport->EnumClose(&m_hEnum); + } + } + + FORCEINLINE HENUMInternal* operator& () + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(m_fAcquired); + return &m_hEnum; + } + +private: + FORCEINLINE HENUMInternalHolder(const HENUMInternalHolder &) + { + WRAPPER_NO_CONTRACT; + + _ASSERTE(!"Don't try to assign this class."); + } + + +protected: + IMDInternalImport *m_pInternalImport; + HENUMInternal m_hEnum; + BOOL m_fAcquired; +}; + +class HENUMInternalMethodImplHolder : protected HENUMInternalHolder +{ + public: + FORCEINLINE HENUMInternalMethodImplHolder(IMDInternalImport *pInternalImport) + : HENUMInternalHolder(pInternalImport) + { + WRAPPER_NO_CONTRACT; + } + + FORCEINLINE ~HENUMInternalMethodImplHolder() + { + WRAPPER_NO_CONTRACT; + + if (m_fAcquired) + { + // Ignore the error + (void)m_pInternalImport->EnumClose(&m_hEnum2); + } + } + + FORCEINLINE void EnumMethodImplInit(mdToken tkParent // [IN] token to scope the search + ) + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + HRESULT hr = EnumMethodImplInitNoThrow(tkParent); + if (FAILED(hr)) + { + ThrowHR(hr); + } + } + + __checkReturn + FORCEINLINE HRESULT EnumMethodImplInitNoThrow(mdToken tkParent // [IN] token to scope the search + ) + { + CONTRACTL { + NOTHROW; + } CONTRACTL_END; + + _ASSERTE(!m_fAcquired); + HRESULT hr = m_pInternalImport->EnumMethodImplInit(tkParent, &m_hEnum, &m_hEnum2); + if (SUCCEEDED(hr)) + { + m_fAcquired = TRUE; + } + return hr; + } + + __checkReturn + FORCEINLINE HRESULT EnumMethodImplNext( + mdToken *ptkImpl, + mdToken *ptkDecl) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + CONSISTENCY_CHECK(m_fAcquired); + } CONTRACTL_END; + + return m_pInternalImport->EnumMethodImplNext(&m_hEnum, &m_hEnum2, ptkImpl, ptkDecl); + } + + FORCEINLINE ULONG EnumMethodImplGetCount() + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + CONSISTENCY_CHECK(m_fAcquired); + } CONTRACTL_END; + + return m_pInternalImport->EnumMethodImplGetCount(&m_hEnum, &m_hEnum2); + } + + protected: + HENUMInternal m_hEnum2; +}; + +#endif //__HOLDER_H_ + +#endif // _METADATA_H_ diff --git a/lib/coreclr/src/inc/metadataexports.h b/lib/coreclr/src/inc/metadataexports.h new file mode 100644 index 0000000000..159af69fb3 --- /dev/null +++ b/lib/coreclr/src/inc/metadataexports.h @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// MDCommon.h +// + +// +// Header for functions exported by metadata. These are consumed 2 ways: +// 1. Mscoree provides public exports that plumb to some of these functions to invoke these dynamically. +// 2. Standalone metadata (statically linked) +// +//***************************************************************************** + + +#ifndef _METADATA_EXPORTS_ +#define _METADATA_EXPORTS_ + + + +// General creation function for ClassFactory semantics. +STDAPI MetaDataDllGetClassObject(REFCLSID rclsid, REFIID riid, void ** ppv); + +// Specific creation function to get IMetaDataDispenser(Ex) interface. +HRESULT InternalCreateMetaDataDispenser(REFIID riid, void ** pMetaDataDispenserOut); + +STDAPI GetMDInternalInterface( + LPVOID pData, + ULONG cbData, + DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC + REFIID riid, // [in] The interface desired. + void **ppIUnk); // [out] Return interface on success. + +STDAPI GetMDInternalInterfaceFromPublic( + IUnknown *pIUnkPublic, // [IN] Given scope. + REFIID riid, // [in] The interface desired. + void **ppIUnkInternal); // [out] Return interface on success. + +STDAPI GetMDPublicInterfaceFromInternal( + void *pIUnkPublic, // [IN] Given scope. + REFIID riid, // [in] The interface desired. + void **ppIUnkInternal); // [out] Return interface on success. + +STDAPI MDReOpenMetaDataWithMemory( + void *pImport, // [IN] Given scope. public interfaces + LPCVOID pData, // [in] Location of scope data. + ULONG cbData); // [in] Size of the data pointed to by pData. + +STDAPI MDReOpenMetaDataWithMemoryEx( + void *pImport, // [IN] Given scope. public interfaces + LPCVOID pData, // [in] Location of scope data. + ULONG cbData, // [in] Size of the data pointed to by pData. + DWORD dwReOpenFlags); // [in] ReOpen flags + + + +#endif // _METADATA_EXPORTS_ diff --git a/lib/coreclr/src/inc/metadatatracker.h b/lib/coreclr/src/inc/metadatatracker.h new file mode 100644 index 0000000000..90db2424af --- /dev/null +++ b/lib/coreclr/src/inc/metadatatracker.h @@ -0,0 +1,360 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _METADATATRACKER_H_ +#define _METADATATRACKER_H_ + +#ifdef FEATURE_PREJIT + +#define METADATATRACKER_DATA 1 +#if !defined(DACCESS_COMPILE) +#define METADATATRACKER_ENABLED 1 +#endif + +#endif + +#if METADATATRACKER_ENABLED + +#define METADATATRACKER_ONLY(s) (s) + +#include "winbase.h" +#include "winwrap.h" +#include "holder.h" +#include "contract.h" +#include +#include +#include +#include "stdmacros.h" + +#include "metamodelpub.h" + +#define NUM_MD_SECTIONS (TBL_COUNT + MDPoolCount) + +#define STRING_POOL (TBL_COUNT + MDPoolStrings) +#define GUID_POOL (TBL_COUNT + MDPoolGuids) +#define BLOB_POOL (TBL_COUNT + MDPoolBlobs) +#define USERSTRING_POOL (TBL_COUNT + MDPoolUSBlobs) + +class MetaDataTracker +{ + LPWSTR m_ModuleName; + BYTE *m_MetadataBase; + SIZE_T m_MetadataSize; + MetaDataTracker *m_next; + + BYTE *m_mdSections[NUM_MD_SECTIONS]; + SIZE_T m_mdSectionSize[NUM_MD_SECTIONS]; + SIZE_T m_mdSectionRowSize[NUM_MD_SECTIONS]; + BOOL m_bActivated; + + static BOOL s_bEnabled; + + static MetaDataTracker *m_MDTrackers; + +public: + // callback into IBCLogger.cpp. Done this crummy way because we can't include IBCLogger.h here nor link + // to IBCLogger.cpp + static void (*s_IBCLogMetaDataAccess)(const void *addr); + static void (*s_IBCLogMetaDataSearch)(const void *result); + + MetaDataTracker(BYTE *baseAddress, DWORD mdSize, LPCWSTR modName) + { + CONTRACTL + { + CONSTRUCTOR_CHECK; + THROWS; + GC_NOTRIGGER; + INJECT_FAULT(ThrowOutOfMemory()); + } + CONTRACTL_END; + + m_ModuleName = NULL; + + size_t len = wcslen(modName); + m_ModuleName = new wchar_t[len + 1]; + NewArrayHolder moduleNameHolder(m_ModuleName); + wcscpy_s((wchar_t *)m_ModuleName, len + 1, (wchar_t *)modName); + + m_MetadataBase = baseAddress; + m_MetadataSize = mdSize; + + m_next = m_MDTrackers; + m_MDTrackers = this; + + memset (m_mdSections, 0, NUM_MD_SECTIONS*sizeof(BYTE*)); + memset (m_mdSectionSize, 0, NUM_MD_SECTIONS*sizeof(SIZE_T)); + + moduleNameHolder.SuppressRelease(); + } + + ~MetaDataTracker() + { + CONTRACTL + { + DESTRUCTOR_CHECK; + NOTHROW; + GC_NOTRIGGER; + FORBID_FAULT; + } + CONTRACTL_END; + + // Surely if we are dying, we are being deactivated as well + Deactivate(); + + if (m_ModuleName) + delete m_ModuleName; + + // Remove this tracker from the global list of trackers + + MetaDataTracker *mdMod = m_MDTrackers; + + _ASSERTE (mdMod && "Trying to delete metadata tracker where none exist"); + + // If ours is the first tracker + if (mdMod == this) + { + m_MDTrackers = mdMod->m_next; + mdMod->m_next = NULL; + } + else + { + // Now traverse thru the list and maintain the prev ptr. + MetaDataTracker *mdModPrev = mdMod; + mdMod = mdMod->m_next; + while(mdMod) + { + if (mdMod == this) + { + mdModPrev->m_next = mdMod->m_next; + mdMod->m_next = NULL; + break; + } + mdModPrev = mdMod; + mdMod = mdMod->m_next; + } + } + } + + static void Enable() + { LIMITED_METHOD_CONTRACT; + s_bEnabled = TRUE; + } + + static void Disable() + { LIMITED_METHOD_CONTRACT; + s_bEnabled = FALSE; + } + + static BOOL Enabled() + { LIMITED_METHOD_CONTRACT; + return s_bEnabled; + } + + static void NoteSection(DWORD secNum, void *address, size_t size, size_t rowSize) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (!Enabled()) + return; + + MetaDataTracker *mdMod = m_MDTrackers; + while( mdMod) + { + if (mdMod->NoteSectionInModule(secNum, address, size, rowSize)) + return; + + mdMod = mdMod->m_next; + } + } + + // With logging disabled this quickly returns the address that was passed in + // this allows us to inline a smaller amount of code at callsites. + __forceinline static void* NoteAccess(void *address) + { + WRAPPER_NO_CONTRACT; + + if (!Enabled()) + return address; + + return NoteAccessWorker(address); + } + + NOINLINE static void* NoteAccessWorker(void *address) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (s_IBCLogMetaDataAccess != NULL) + s_IBCLogMetaDataAccess(address); + + return address; + } + + // See the comment above CMiniMdRW::GetHotMetadataTokensSearchAware + __forceinline static void NoteSearch(void *result) + { + WRAPPER_NO_CONTRACT; + + if (!Enabled()) + return; + + NoteSearchWorker(result); + } + + NOINLINE static void NoteSearchWorker(void *result) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + if (s_IBCLogMetaDataSearch != NULL && result != NULL) + s_IBCLogMetaDataSearch(result); + } + + static MetaDataTracker * FindTracker(BYTE *_MDBaseAddress) + { + LIMITED_METHOD_CONTRACT; + + if (!Enabled()) + return NULL; + + MetaDataTracker *mdMod = m_MDTrackers; + while( mdMod) + { + if (mdMod->m_MetadataBase == _MDBaseAddress) + return mdMod; + + mdMod = mdMod->m_next; + } + + return NULL; + } + + void Activate() + { + LIMITED_METHOD_CONTRACT; + + m_bActivated = TRUE; + } + + void Deactivate() + { + LIMITED_METHOD_CONTRACT; + + m_bActivated = FALSE; + } + + BOOL IsActivated() + { + LIMITED_METHOD_CONTRACT; + + return m_bActivated; + } + + static MetaDataTracker *GetOrCreateMetaDataTracker (BYTE *baseAddress, DWORD mdSize, LPCWSTR modName) + { + CONTRACT(MetaDataTracker *) + { + THROWS; + GC_NOTRIGGER; + INJECT_FAULT(ThrowOutOfMemory()); + POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); + } + CONTRACT_END; + + MetaDataTracker *pTracker = NULL; + + if (MetaDataTracker::Enabled()) + { + pTracker = MetaDataTracker::FindTracker(baseAddress); + if (!pTracker) + { + FAULT_NOT_FATAL(); // It's ok - an OOM here is nonfatal + pTracker = new MetaDataTracker(baseAddress, mdSize, modName); + } + pTracker->Activate(); + } + + RETURN pTracker; + } + + // Map a metadata address to a token for the purposes of the IBCLogger + static mdToken MapAddrToToken(const void *addr) + { + WRAPPER_NO_CONTRACT; + + mdToken token = 0; + for (MetaDataTracker *mdMod = m_MDTrackers; mdMod; mdMod = mdMod->m_next) + { + token = mdMod->MapAddrToTokenInModule(addr); + if (token != 0) + break; + } + return token; + } + + +private: + + // *************************************************************************** + // Helper functions + // *************************************************************************** + + BOOL NoteSectionInModule(DWORD secNum, void *address, size_t size, size_t rowSize) + { + WRAPPER_NO_CONTRACT; + + PREFAST_ASSUME(secNum < NUM_MD_SECTIONS); + + if (address < m_MetadataBase || address >= (m_MetadataBase + m_MetadataSize)) + return FALSE; + + // This address range belongs to us but the tracker is not activated. + if (!IsActivated()) + { + // _ASSERTE (!"Metadata Tracker not active but trying to access metadata"); + return TRUE; + } + + m_mdSections[secNum] = (BYTE *)address; + m_mdSectionSize[secNum] = size; + m_mdSectionRowSize[secNum] = rowSize; + + return TRUE; + } + + // Map a metadata address to a fake token for the purposes of the IBCLogger + mdToken MapAddrToTokenInModule(const void *addr) + { + LIMITED_METHOD_CONTRACT; + + if (!IsActivated()) + return 0; + + BYTE *address = (BYTE *)addr; + + if (address < m_MetadataBase || address >= (m_MetadataBase + m_MetadataSize)) + return 0; + + for (DWORD secNum = 0; secNum < NUM_MD_SECTIONS; secNum++) + { + if ((address >= m_mdSections[secNum]) && (address < m_mdSections[secNum] + m_mdSectionSize[secNum])) + { + DWORD rid = (DWORD)((address - m_mdSections[secNum])/m_mdSectionRowSize[secNum]); + if (secNum < TBL_COUNT) + rid++; + return TokenFromRid(rid, (secNum<<24)); + } + } + return 0; + } +}; + +#else // METADATATRACKER_ENABLED + +#define METADATATRACKER_ONLY(s) + +#endif // METADATATRACKER_ENABLED + +#endif // _METADATATRACKER_H_ diff --git a/lib/coreclr/src/inc/metahost.idl b/lib/coreclr/src/inc/metahost.idl new file mode 100644 index 0000000000..1ed19b5ba9 --- /dev/null +++ b/lib/coreclr/src/inc/metahost.idl @@ -0,0 +1,548 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/************************************************************************************** + ** Motivation for redesigning the shim APIs: ** + ** - old APIs assume that there is only one runtime in the process ** + ** - old APIs are redundant (multiple ways for achieving the same effect) ** + ** - old APIs are flat and difficult to version (*Ex variants etc.) ** + ** - old APIs mix together totally different concepts - choosing a runtime vs. ** + ** activating the runtime vs. performing an operation on the activated runtime ** + ** - old APIs are poorly named (incosistent use of the Cor* prefix etc.) ** + ** - all in all there's a lot of legacy behavior in the old APIs that it makes ** + ** sense to start from scratch ** + ** ** + ** Design goals: ** + ** - clear separation between the no-policy base part and the policy-decision- ** + ** making part ** + ** - easy to extend with additional functionality by introducing new versions of ** + ** the interfaces (interface types are not hardcoded in method signatures) ** + ** - functions performing clearly defined steps rather than poorly documented ** + ** heavy-weight black boxes ** + **************************************************************************************/ + +/************************************************************************************** + ** Interfaces described in this IDL file follow the "Nano-COM" model. Basically ** + ** lifetime management (AddRef/Release) and encapsulation (implicit context) are ** + ** used from COM. There are no COM types (BSTR, SAFEARRAY, VARIANT), apartment ** + ** models, aggregation, or registry activation (CoCreateInstance). ** + **************************************************************************************/ + + +import "unknwn.idl"; +import "oaidl.idl"; +import "ocidl.idl"; + +import "mscoree.idl"; + +cpp_quote("#include ") + +cpp_quote("STDAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, /*iid_is(riid)*/ LPVOID *ppInterface);") + +// IID ICLRMetaHost : uuid(D332DB9E-B9B3-4125-8207-A14884F53216) +cpp_quote("EXTERN_GUID(IID_ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);") + +// CLSID_CLRMetaHost : uuid(9280188D-0E8E-4867-B30C-7FA83884E8DE) +cpp_quote("EXTERN_GUID(CLSID_CLRMetaHost, 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);") + +// IID ICLRDebugging : uuid(D28F3C5A-9634-4206-A509-477552EEFB10) +cpp_quote("EXTERN_GUID(IID_ICLRDebugging, 0xd28f3c5a, 0x9634, 0x4206, 0xa5, 0x9, 0x47, 0x75, 0x52, 0xee, 0xfb, 0x10);") + +// CLSID_CLRDebugging : uuid(BACC578D-FBDD-48a4-969F-02D932B74634) +cpp_quote("EXTERN_GUID(CLSID_CLRDebugging, 0xbacc578d, 0xfbdd, 0x48a4, 0x96, 0x9f, 0x2, 0xd9, 0x32, 0xb7, 0x46, 0x34);") + +// IID ICLRRuntimeInfo : uuid(BD39D1D2-BA2F-486a-89B0-B4B0CB466891) +cpp_quote("EXTERN_GUID(IID_ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);") + +// IID ICLRDebuggingLibraryProvider interface : uuid{3151C08D-4D09-4f9b-8838-2880BF18FE51} +cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51);") + +// IID ICLRDebuggingLibraryProvider2 interface : uuid{E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA} +cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA);") + +// For use in ICLRMetaHost::RequestRuntimeLoadedNotification +interface ICLRRuntimeInfo; + +typedef HRESULT (__stdcall *CallbackThreadSetFnPtr)(); +typedef HRESULT (__stdcall *CallbackThreadUnsetFnPtr)(); + +typedef void (__stdcall *RuntimeLoadedCallbackFnPtr)( + ICLRRuntimeInfo *pRuntimeInfo, + CallbackThreadSetFnPtr pfnCallbackThreadSet, + CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); + +/************************************************************************************** + ** ICLRMetaHost ** + ** Activated using mscoree!CLRCreateInstance. Does not do any policy decisions, get ** + ** ICLRMetaHostPolicy if you need that. ** + **************************************************************************************/ +[ + uuid(D332DB9E-B9B3-4125-8207-A14884F53216), + version(1.0), + helpstring("CLR meta hosting interface"), + local +] +interface ICLRMetaHost : IUnknown +{ + /********************************************************************************** + ** Returns installed runtime with the specific version. Fails if not found. ** + ** NULL or any other wildcard is not accepted as pwzVersion ** + ** Supersedes: CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE ** + **********************************************************************************/ + HRESULT GetRuntime( + [in] LPCWSTR pwzVersion, + [in] REFIID riid, // IID_ICLRRuntimeInfo + [out, iid_is(riid), retval] LPVOID *ppRuntime); + + /********************************************************************************** + ** Returns runtime version burned into a file's metadata. ** + ** Supersedes: GetFileVersion ** + **********************************************************************************/ + HRESULT GetVersionFromFile( + [in] LPCWSTR pwzFilePath, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, + [in, out] DWORD *pcchBuffer); + + /********************************************************************************** + ** Returns an enumerator of runtimes installed on the machine. ** + ** Supersedes: (none) ** + **********************************************************************************/ + HRESULT EnumerateInstalledRuntimes( + [out, retval] IEnumUnknown **ppEnumerator); + + /********************************************************************************** + ** Provides an enumerator of runtimes loaded into the given process. ** + ** Supersedes: GetVersionFromProcess ** + **********************************************************************************/ + HRESULT EnumerateLoadedRuntimes( + [in] HANDLE hndProcess, + [out, retval] IEnumUnknown **ppEnumerator); + + /********************************************************************************** + ** Provides a callback when a new runtime version has just been loaded, but not ** + ** started. ** + ** ** + ** The callback works in the following way: ** + ** - the callback is invoked only when a runtime is loaded for the first time ** + ** - the callback will not be invoked for reentrant loads of the same runtime ** + ** - the callback will be for reentrant loads of other runtimes ** + ** - it is guaranteed that no other thread may load the runtime until the ** + ** callback returns; any thread that does so blocks until this time. ** + ** - for non-reentrant multi-threaded runtime loads, callbacks are serialized ** + ** - if the host intends to load (or cause to be loaded) another runtime in a ** + ** reentrant fashion, or intends to perform any operations on the runtime ** + ** corresponding to the callback instance, the pfnCallbackThreadSet and ** + ** pfnCallbackThreadUnset arguments provided in the callback must be used ** + ** in the following way: ** + ** - pfnCallbackThreadSet must be called by the thread that might cause a ** + ** runtime load before such a load is attempted ** + ** - pfnCallbackThreadUnset must be called when the thread will no longer ** + ** cause such a runtime load (and before returning from the initial ** + ** callback) ** + ** - pfnCallbackThreadSet and pfnCallbackThreadUnset are non-reentrant. ** + ** ** + ** pCallbackFunction: This function is invoked when a new runtime has just ** + ** been loaded. A value of NULL results in a failure ** + ** return value of E_POINTER. ** + ** ** + ** Supersedes: LockClrVersion ** + **********************************************************************************/ + HRESULT RequestRuntimeLoadedNotification( + [in] RuntimeLoadedCallbackFnPtr pCallbackFunction); + + /********************************************************************************** + ** Returns interface representing the runtime to which the legacy activation ** + ** policy has been bound (for example, by a useLegacyV2RuntimeActivationPolicy ** + ** config entry or by a call to ICLRRuntimeInfo::BindAsLegacyV2Runtime). ** + **********************************************************************************/ + HRESULT QueryLegacyV2RuntimeBinding( + [in] REFIID riid, + [out, iid_is(riid), retval] LPVOID *ppUnk); + + /********************************************************************************** + ** Shuts down the current process. ** + ** Supersedes: CorExitProcess ** + **********************************************************************************/ + HRESULT ExitProcess( + [in] INT32 iExitCode); +} // interface ICLRMetaHost + +/************************************************************************************* + ** This structure defines the version of a CLR for debugging purposes. ** + ** The wStructVersion field allows for future revisions to this structure to be ** + ** made. Currently it must be set to 0. The remaining fields represent the ** + ** typical major.minor.build.revision product version information. ** + *************************************************************************************/ +typedef struct _CLR_DEBUGGING_VERSION +{ + WORD wStructVersion; + WORD wMajor; + WORD wMinor; + WORD wBuild; + WORD wRevision; +} +CLR_DEBUGGING_VERSION; + +typedef enum +{ + /********************************************************************************** + ** This runtime has a non-catchup managed debug event to send ** + ** Catchup events include process, app domain, assembly, module, and thread ** + ** creation notifications that bring the debugger up to the current state after ** + ** attaching. Non-catchup events are everything else. ** + **********************************************************************************/ + CLR_DEBUGGING_MANAGED_EVENT_PENDING = 1, + + /********************************************************************************** + ** The managed event that is pending is a Debugger.Launch request ** + **********************************************************************************/ + CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH = 2, +} +CLR_DEBUGGING_PROCESS_FLAGS; + + /************************************************************************************** + ** ICLRDebuggingLibraryProvider ** + ** Implemented by API user ** + ** This interface allows the debugger to provide modules which are needed for ** + ** debugging a particular CLR such as mscordbi and mscordacwks. The module handles ** + ** need to remain valid until a call to ICLRDebugging::CanUnloadNow indicates they ** + ** may be freed, at which point it is the caller's responsibility to free the ** + ** handles. ** + **************************************************************************************/ +[ + uuid(3151C08D-4D09-4f9b-8838-2880BF18FE51), + version(1.0), + helpstring("CLR debugging LibraryProvider callback interface"), + local +] +interface ICLRDebuggingLibraryProvider : IUnknown +{ + /********************************************************************************** + ** The goal of this method is to allow the debugger to provide a handle to a ** + ** module which is needed for debugging. The debugger may use any available means** + ** to locate and/or procure the module. See the security note below for important** + ** information about implementing this method securely. ** + ** Arguments: ** + ** pwzFileName - The name of the module being requested ** + ** dwTimeStamp - The date time stamp stored in the COFF file header of PE files ** + ** dwSizeOfImage - The SizeOfImage field stored in the COFF optional file header ** + ** of PE files ** + ** phModule - Set this to the handle to the requested module on success. On ** + ** failure leave it untouched. See security note below! ** + ** ** + ** Return value - S_OK if the module was provided, or any other convenient ** + ** error HRESULT if the module could not be provided ** + ** ** + ** ** + ** !!!!!!!!!!!!!! ** + ** SECURITY NOTE: Anything the caller would not be willing to execute itself, it ** + ** should not provide to the this API call ** + ***********************************************************************************/ + HRESULT ProvideLibrary( + [in] const WCHAR* pwszFileName, + [in] DWORD dwTimestamp, + [in] DWORD dwSizeOfImage, + [out] HMODULE* phModule); +} + + /************************************************************************************** + ** ICLRDebuggingLibraryProvider2 ** + ** Implemented by API user ** + ** This interface allows the debugger to provide module paths which are needed for ** + ** debugging a particular CLR such as mscordbi and mscordacwks. ** + **************************************************************************************/ +[ + uuid(E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA), + version(1.0), + helpstring("CLR debugging LibraryProvider callback interface"), + local +] +interface ICLRDebuggingLibraryProvider2 : IUnknown +{ + /********************************************************************************** + ** The goal of this method is to allow the debugger to provide a module path ** + ** which is needed for debugging. The debugger may use any available means to ** + ** locate and/or procure the module. See the security note below for important ** + ** information about implementing this method securely. ** + ** Arguments: ** + ** pwzFileName - The name of the module being requested ** + ** dwTimeStamp - The date time stamp stored in the COFF file header of PE files ** + ** dwSizeOfImage - The SizeOfImage field stored in the COFF optional file header ** + ** of PE files ** + ** ppResolvedModulePath - Where *ppResolvedModulePath is a null terminated ** + ** path to the module dll. On Windows it should be ** + ** allocated with CoTaskMemAlloc. On Unix it should be ** + ** allocated with malloc. Failure leave it untouched. See ** + ** security note below! ** + ** ** + ** Return value - S_OK if the module was provided, or any other convenient ** + ** error HRESULT if the module could not be provided ** + ** ** + ** !!!!!!!!!!!!!! ** + ** SECURITY NOTE: Anything the caller would not be willing to execute itself, it ** + ** should not provide to the this API call ** + ***********************************************************************************/ + HRESULT ProvideLibrary2( + [in] const WCHAR* pwszFileName, + [in] DWORD dwTimestamp, + [in] DWORD dwSizeOfImage, + [out] LPWSTR* ppResolvedModulePath); +} + +/************************************************************************************** + ** ICLRDebugging ** + ** Activated using mscoree!CLRCreateInstance. ** + **************************************************************************************/ +[ + uuid(D28F3C5A-9634-4206-A509-477552EEFB10), + version(1.0), + helpstring("CLR debugging interface for MetaHost interface"), + local +] +interface ICLRDebugging : IUnknown +{ + /********************************************************************************** + ** Get the ICorDebugProcess and other information corresponding to a clr module ** + ** loaded in the process ** + ** Arguments: ** + ** moduleBaseAddress - The base address of a module in the target process. ** + ** COR_E_NOT_CLR will be returned if the indicated module is ** + ** not a clr. ** + ** pDataTarget - A data target abstraction which allows the managed ** + ** debugger to inspect process state. It must implement ** + ** at least ICorDebugDataTarget. ** + ** pLibraryProvider - A library provider callback interface that allows version ** + ** specific debugging libraries to be located and loaded on ** + ** demand. This parameter is only required if ppProcess or ** + ** pFlags is non-NULL. ** + ** pMaxDebuggerSupportedVersion - The version of the CLR this debugger is ** + ** designed to support. The debugger should specify the ** + ** major and minor versions from the newest CLR version this ** + ** debugger supports. The function may still succeed with ** + ** a newer version of the CLR than this if the CLR ** + ** determines that it should be compatible. The build and ** + ** revision values are currently ignored. ** + ** riidProcess - The interface ID of the desired ICorDebugProcess ** + ** interface. Currently the only legal values are ** + ** IID_CORDEBUGPROCESS3, IID_CORDEBUGPROCESS2, and ** + ** IID_CORDEBUGPROCESS. ** + ** ppProcess - Returns a pointer to a COM interface identified by ** + ** riidProcess. Future versions of the runtime may implement ** + ** other interfaces. ** + ** pwszVersion - On input this is either null, or points to a ** + ** CLR_DEBUGGING_VERSION structure. The wStructVersion field ** + ** must be initialized to 0. On output the structure will be ** + ** filled in with the CLR version information. ** + ** pFlags - Informational flags about the specified runtime, see ** + ** CLR_DEBUGGING_PROCESS_FLAGS for a description of the ** + ** flags. ** + ** ** + ** The return value is S_OK if succeeded or: ** + ** E_POINTER if pDataTarget is NULL ** + ** CORDBG_E_LIBRARY_PROVIDER_ERROR if the ICLRDebuggingLibraryProvider callback** + ** returns an error or does not provide a valid** + ** handle ** + ** CORDBG_E_MISSING_DATA_TARGET_INTERFACE if the pDataTarget argument does not** + ** implement the required data target ** + ** interfaces for this version of the runtime. ** + ** CORDBG_E_NOT_CLR if the indicated module is not a clr. It is ** + ** possible that modules which do represent a ** + ** CLR will not be detected if memory has been ** + ** corrupted, is not available, or the CLR is ** + ** of a newer version than the shim. ** + ** CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL if this runtime version does not ** + ** support this debugging model. Currently v4 ** + ** supports this model and no previous version ** + ** does. The pVersion output argument will ** + ** still be set to the correct value after ** + ** receiving this error. ** + ** CORDBG_E_UNSUPPORTED_FORWARD_COMPAT if the version of the CLR is not ** + ** compatible with the version this debugger ** + ** claims to support. The pVersion output ** + ** argument will still be set to the correct ** + ** value after receiving this error. ** + ** E_NO_INTERFACE if the riidProcess interface is not ** + ** available. ** + ** CORDBG_E_UNSUPPORTED_VERSION_STRUCT if the version struct does not have a ** + ** recognized value for wStructVersion. The ** + ** only accepted value at this time is 0. ** + ** Any other convenient HRESULT error, depending on the execution. ** + **********************************************************************************/ + HRESULT OpenVirtualProcess( + [in] ULONG64 moduleBaseAddress, + [in] IUnknown * pDataTarget, + [in] ICLRDebuggingLibraryProvider * pLibraryProvider, + [in] CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion, + [in] REFIID riidProcess, + [out, iid_is(riidProcess)] IUnknown ** ppProcess, + [in, out] CLR_DEBUGGING_VERSION * pVersion, + [out] CLR_DEBUGGING_PROCESS_FLAGS * pdwFlags); + + /********************************************************************************** + ** Determines if a library provided via an ICLRDebuggingLibraryProvider is still ** + ** in use. Functionally this checks to see if all instances of ICorDebug* ** + ** interfaces have been released and no thread is currently within a call to ** + ** OpenVirtualProcess. ** + ** Arguments: ** + ** hModule - A module handle previously provided by the ** + ** ICLRDebuggingLibraryProvider used in OpenVirtualProcess ** + ** Returns: ** + ** S_OK if the module can be unloaded now ** + ** S_FALSE if the module is still in use ** + ** Any other error HRESULT if a failure occurs ** + ** ** + ** Notes: As of the V4.0 implementation unloading is still not fully supported ** + ** and all calls to this method will return S_FALSE. ** + **********************************************************************************/ + HRESULT CanUnloadNow(HMODULE hModule); +} // interface ICLRDebugging + +/************************************************************************************** + ** ICLRRuntimeInfo ** + ** Represents a runtime - installed on the machine and/or loaded into a process. ** + ** Includes functionality for obtaining various properties and for loading the ** + ** runtime into the current process. The same installed runtime can be loaded ** + ** multiple times in the same process (may not be supported in Dev10). ** + **************************************************************************************/ +[ + uuid(BD39D1D2-BA2F-486a-89B0-B4B0CB466891), + version(1.0), + helpstring("CLR runtime instance"), + local +] +interface ICLRRuntimeInfo : IUnknown +{ + // Methods that query information: + + /********************************************************************************** + ** Returns the version of this runtime in the usual v-prefixed dotted form. ** + ** Supersedes: GetRequestedRuntimeInfo, GetRequestedRuntimeVersion, ** + ** GetCORVersion ** + **********************************************************************************/ + HRESULT GetVersionString( + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_opt_(*pcchBuffer)")] + LPWSTR pwzBuffer, + [in, out] DWORD *pcchBuffer); + + /********************************************************************************** + ** Returns the directory where this runtime is installed. ** + ** Supersedes: GetCORSystemDirectory ** + **********************************************************************************/ + HRESULT GetRuntimeDirectory( + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, + [in, out] DWORD *pcchBuffer); + + /********************************************************************************** + ** Returns TRUE if this runtime is loaded into the specified process. ** + ** Supersedes: GetCORSystemDirectory ** + **********************************************************************************/ + HRESULT IsLoaded( + [in] HANDLE hndProcess, + [out, retval] BOOL *pbLoaded); + + // Methods that may load the runtime: + + /********************************************************************************** + ** Translates an HRESULT value into an error message. Use iLocaleID -1 for the ** + ** default culture of the current thread. ** + ** Supersedes: LoadStringRC, LoadStringRCEx ** + **********************************************************************************/ + HRESULT LoadErrorString( + [in] UINT iResourceID, + [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] + LPWSTR pwzBuffer, + [in, out] DWORD *pcchBuffer, + [in, lcid] LONG iLocaleID); + + /********************************************************************************** + ** Loads a library located alongside this runtime. ** + ** Supersedes: LoadLibraryShim ** + **********************************************************************************/ + HRESULT LoadLibrary( + [in] LPCWSTR pwzDllName, + [out, retval] HMODULE *phndModule); + + /********************************************************************************** + ** Gets the address of the specified function exported from this runtime. ** + ** It should NOT be documented what module the function lives in. We may want ** + ** to implement some forwarding policy here. The reason for exposing ** + ** GetProcAddress are functions like mscorwks!GetCLRIdentityManager. ** + ** Supersedes: GetRealProcAddress ** + **********************************************************************************/ + HRESULT GetProcAddress( + [in] LPCSTR pszProcName, + [out, retval] LPVOID *ppProc); + + /********************************************************************************** + ** Loads the runtime into the current process and returns an interface through ** + ** which runtime functionality is provided. ** + ** ** + ** Supported CLSIDs/IIDs: ** + ** CLSID_CorMetaDataDispenser IID_IMetaDataDispenser,IID_IMetaDataDispenserEx ** + ** CLSID_CorMetaDataDispenserRuntime dtto ** + ** CLSID_CorRuntimeHost IID_ICorRuntimeHost ** + ** CLSID_CLRRuntimeHost IID_ICLRRuntimeHost ** + ** CLSID_TypeNameFactory IID_ITypeNameFactory ** + ** CLSID_CLRStrongName IID_ICLRStrongName ** + ** CLSID_CLRDebuggingLegacy IID_ICorDebug ** + ** ** + ** Supersedes: CorBindTo* and others ** + **********************************************************************************/ + HRESULT GetInterface( + [in] REFCLSID rclsid, + [in] REFIID riid, + [out, iid_is(riid), retval] LPVOID *ppUnk); + + // Does not load runtime + + /********************************************************************************** + ** Returns TRUE if this runtime could be loaded into the current process. Note ** + ** that this method is side-effect free, and thus does not represent a ** + ** commitment to be able to load this runtime if it sets *pbLoadable to be TRUE.** + ** Supersedes: none ** + **********************************************************************************/ + HRESULT IsLoadable( + [out, retval] BOOL *pbLoadable); + + /********************************************************************************** + ** Sets startup flags and host config file that will be used at startup. ** + ** Supersedes: The startupFlags parameter in CorBindToRuntimeEx/Host ** + **********************************************************************************/ + HRESULT SetDefaultStartupFlags( + [in] DWORD dwStartupFlags, + [in] LPCWSTR pwzHostConfigFile); + + /********************************************************************************** + ** Gets startup flags and host config file that will be used at startup. ** + ** Supersedes: GetStartupFlags, GetHostConfigurationFile ** + **********************************************************************************/ + HRESULT GetDefaultStartupFlags( + [out] DWORD *pdwStartupFlags, + [out, size_is(*pcchHostConfigFile), annotation("_Out_writes_all_opt_(*pcchHostConfigFile)")] + LPWSTR pwzHostConfigFile, + [in, out] DWORD *pcchHostConfigFile); + + /********************************************************************************** + ** If not already bound (for example, with a useLegacyV2RuntimeActivationPolicy ** + ** config setting), binds this runtime for all legacy V2 activation policy ** + ** decisions. If a different runtime was already bound to the legacy V2 ** + ** activation policy, returns CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND. If this ** + ** runtime was already bound as the legacy V2 activation policy runtime, ** + ** returns S_OK. ** + **********************************************************************************/ + HRESULT BindAsLegacyV2Runtime(); + + /********************************************************************************** + ** Returns TRUE if the runtime has been started, i.e. Start() has been called. ** + ** If it has been started, its STARTUP_FLAGS are returned. ** + ** ** + ** IMPORTANT: This method is valid only for v4+ runtimes. This method will ** + ** return E_NOTIMPL for all pre-v4 runtimes. ** + **********************************************************************************/ + HRESULT IsStarted( + [out] BOOL *pbStarted, + [out] DWORD *pdwStartupFlags); +}; diff --git a/lib/coreclr/src/inc/metamodelpub.h b/lib/coreclr/src/inc/metamodelpub.h new file mode 100644 index 0000000000..ba68ae0c30 --- /dev/null +++ b/lib/coreclr/src/inc/metamodelpub.h @@ -0,0 +1,1672 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// MetaModelPub.h -- header file for Common Language Runtime metadata. +// + +// +//***************************************************************************** + +#ifndef _METAMODELPUB_H_ +#define _METAMODELPUB_H_ + +#if _MSC_VER >= 1100 +# pragma once +#endif + +#include +#include + +#ifndef lengthof +# define lengthof(x) (sizeof(x)/sizeof((x)[0])) +#endif + +template inline T Align4(T p) +{ + LIMITED_METHOD_CONTRACT; + + INT_PTR i = (INT_PTR)p; + i = (i+(3)) & ~3; + return (T)i; +} + +typedef ULONG RID; + +// check if a rid is valid or not +#define InvalidRid(rid) ((rid) == 0) + +#ifndef METADATA_FIELDS_PROTECTION +#define METADATA_FIELDS_PROTECTION public +#endif + +//***************************************************************************** +// Record definitions. Records have some combination of fixed size fields and +// variable sized fields (actually, constant across a database, but variable +// between databases). +// +// In this section we define record definitions which include the fixed size +// fields and an enumeration of the variable sized fields. +// +// Naming is as follows: +// Given some table "Xyz": +// class XyzRec { public: +// SOMETYPE m_SomeField; +// // rest of the fixed fields. +// enum { COL_Xyz_SomeOtherField, +// // rest of the fields, enumerated. +// COL_Xyz_COUNT }; +// }; +// +// The important features are the class name (XyzRec), the enumerations +// (COL_Xyz_FieldName), and the enumeration count (COL_Xyz_COUNT). +// +// THESE NAMING CONVENTIONS ARE CARVED IN STONE! DON'T TRY TO BE CREATIVE! +// +//***************************************************************************** +// Have the compiler generate two byte alignment. Be careful to manually lay +// out the fields for proper alignment. The alignment for variable-sized +// fields will be computed at save time. +#include + +// Non-sparse tables. +class ModuleRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Generation; // ENC generation. +public: + enum { + COL_Generation, + + COL_Name, + COL_Mvid, + COL_EncId, + COL_EncBaseId, + COL_COUNT, + COL_KEY + }; + USHORT GetGeneration() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Generation); + } + void SetGeneration(USHORT Generation) + { + LIMITED_METHOD_CONTRACT; + + m_Generation = VAL16(Generation); + } +}; + +class TypeRefRec +{ +public: + enum { + COL_ResolutionScope, // mdModuleRef or mdAssemblyRef. + COL_Name, + COL_Namespace, + COL_COUNT, + COL_KEY + }; +}; + +class TypeDefRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Flags; // Flags for this TypeDef +public: + enum { + COL_Flags, + + COL_Name, // offset into string pool. + COL_Namespace, + COL_Extends, // coded token to typedef/typeref. + COL_FieldList, // rid of first field. + COL_MethodList, // rid of first method. + COL_COUNT, + COL_KEY + }; + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } + void AddFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags |= VAL32(Flags); + } + void RemoveFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags &= ~VAL32(Flags); + } + +}; + +class FieldPtrRec +{ +public: + enum { + COL_Field, + COL_COUNT, + COL_KEY + }; +}; + +class FieldRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Flags; // Flags for the field. +public: + enum { + COL_Flags, + + COL_Name, + COL_Signature, + COL_COUNT, + COL_KEY + }; + USHORT GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = (USHORT)VAL16(Flags); + } + void AddFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags |= (USHORT)VAL16(Flags); + } + void RemoveFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags &= (USHORT)~VAL16(Flags); + } + + +}; + +class MethodPtrRec +{ +public: + enum { + COL_Method, + COL_COUNT, + COL_KEY + }; +}; + +class MethodRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_RVA; // RVA of the Method. + USHORT m_ImplFlags; // Descr flags of the Method. + USHORT m_Flags; // Flags for the Method. +public: + enum { + COL_RVA, + COL_ImplFlags, + COL_Flags, + + COL_Name, + COL_Signature, + COL_ParamList, // Rid of first param. + COL_COUNT, + COL_KEY + }; + + void Copy(MethodRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_RVA = pFrom->m_RVA; + m_ImplFlags = pFrom->m_ImplFlags; + m_Flags = pFrom->m_Flags; + } + + ULONG GetRVA() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_RVA); + } + void SetRVA(ULONG RVA) + { + LIMITED_METHOD_CONTRACT; + + m_RVA = VAL32(RVA); + } + + USHORT GetImplFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_ImplFlags); + } + void SetImplFlags(USHORT ImplFlags) + { + LIMITED_METHOD_CONTRACT; + + m_ImplFlags = VAL16(ImplFlags); + } + void AddImplFlags(USHORT ImplFlags) + { + LIMITED_METHOD_CONTRACT; + + m_ImplFlags |= VAL16(ImplFlags); + } + void RemoveImplFlags(USHORT ImplFlags) + { + LIMITED_METHOD_CONTRACT; + + m_ImplFlags &= ~VAL16(ImplFlags); + } + + + USHORT GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = (USHORT)VAL16(Flags); + } + void AddFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags |= (USHORT)VAL16(Flags); + } + void RemoveFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags &= (USHORT)~VAL16(Flags); + } +}; + +class ParamPtrRec +{ +public: + enum { + COL_Param, + COL_COUNT, + COL_KEY + }; +}; + +class ParamRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Flags; // Flags for this Param. + USHORT m_Sequence; // Sequence # of param. 0 - return value. +public: + enum { + COL_Flags, + COL_Sequence, + + COL_Name, // Name of the param. + COL_COUNT, + COL_KEY + }; + + void Copy(ParamRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = pFrom->m_Flags; + m_Sequence = pFrom->m_Sequence; + } + + USHORT GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = (USHORT)VAL16(Flags); + } + void AddFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags |= (USHORT)VAL16(Flags); + } + void RemoveFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags &= (USHORT)~VAL16(Flags); + } + + USHORT GetSequence() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Sequence); + } + void SetSequence(USHORT Sequence) + { + LIMITED_METHOD_CONTRACT; + + m_Sequence = VAL16(Sequence); + } + +}; + +class InterfaceImplRec +{ +public: + enum { + COL_Class, // Rid of class' TypeDef. + COL_Interface, // Coded rid of implemented interface. + COL_COUNT, + COL_KEY = COL_Class + }; +}; + +class MemberRefRec +{ +public: + enum { + COL_Class, // Rid of TypeDef. + COL_Name, + COL_Signature, + COL_COUNT, + COL_KEY + }; +}; + +class StandAloneSigRec +{ +public: + enum { + COL_Signature, + COL_COUNT, + COL_KEY + }; +}; + +// Sparse tables. These contain modifiers for tables above. +class ConstantRec +{ +METADATA_FIELDS_PROTECTION: + BYTE m_Type; // Type of the constant. + BYTE m_PAD1; +public: + enum { + COL_Type, + + COL_Parent, // Coded rid of object (param, field). + COL_Value, // Index into blob pool. + COL_COUNT, + COL_KEY = COL_Parent + }; + BYTE GetType() + { + LIMITED_METHOD_CONTRACT; + + return m_Type; + } + void SetType(BYTE Type) + { + LIMITED_METHOD_CONTRACT; + + m_Type = Type; + } +}; + +class CustomAttributeRec +{ +public: + enum { + COL_Parent, // Coded rid of any object. + COL_Type, // TypeDef or TypeRef. + COL_Value, // Blob. + COL_COUNT, + COL_KEY = COL_Parent + }; +}; + +class FieldMarshalRec +{ +public: + enum { + COL_Parent, // Coded rid of field or param. + COL_NativeType, + COL_COUNT, + COL_KEY = COL_Parent + }; +}; + +class DeclSecurityRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Action; +public: + enum { + COL_Action, + + COL_Parent, + COL_PermissionSet, + COL_COUNT, + COL_KEY = COL_Parent + }; + + void Copy(DeclSecurityRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_Action = pFrom->m_Action; + } + USHORT GetAction() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Action); + } + void SetAction(USHORT Action) + { + LIMITED_METHOD_CONTRACT; + + m_Action = VAL16(Action); + } +}; + + +class ClassLayoutRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_PackingSize; + ULONG m_ClassSize; +public: + enum { + COL_PackingSize, + COL_ClassSize, + + COL_Parent, // Rid of TypeDef. + COL_COUNT, + COL_KEY = COL_Parent + }; + + void Copy(ClassLayoutRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_PackingSize = pFrom->m_PackingSize; + m_ClassSize = pFrom->m_ClassSize; + } + USHORT GetPackingSize() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_PackingSize); + } + void SetPackingSize(USHORT PackingSize) + { + LIMITED_METHOD_CONTRACT; + + m_PackingSize = VAL16(PackingSize); + } + + ULONG GetClassSize() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_ClassSize); + } + void SetClassSize(ULONG ClassSize) + { + LIMITED_METHOD_CONTRACT; + + m_ClassSize = VAL32(ClassSize); + } +}; + +class FieldLayoutRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_OffSet; +public: + enum { + COL_OffSet, + + COL_Field, + COL_COUNT, + COL_KEY = COL_Field + }; + + void Copy(FieldLayoutRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_OffSet = pFrom->m_OffSet; + } + ULONG GetOffSet() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OffSet); + } + void SetOffSet(ULONG Offset) + { + LIMITED_METHOD_CONTRACT; + + m_OffSet = VAL32(Offset); + } +}; + +class EventMapRec +{ +public: + enum { + COL_Parent, + COL_EventList, // rid of first event. + COL_COUNT, + COL_KEY + }; +}; + +class EventPtrRec +{ +public: + enum { + COL_Event, + COL_COUNT, + COL_KEY + }; +}; + +class EventRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_EventFlags; +public: + enum { + COL_EventFlags, + + COL_Name, + COL_EventType, + COL_COUNT, + COL_KEY + }; + USHORT GetEventFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_EventFlags); + } + void SetEventFlags(USHORT EventFlags) + { + LIMITED_METHOD_CONTRACT; + + m_EventFlags = VAL16(EventFlags); + } + void AddEventFlags(USHORT EventFlags) + { + LIMITED_METHOD_CONTRACT; + + m_EventFlags |= VAL16(EventFlags); + } +}; + +class PropertyMapRec +{ +public: + enum { + COL_Parent, + COL_PropertyList, // rid of first property. + COL_COUNT, + COL_KEY + }; +}; + +class PropertyPtrRec +{ +public: + enum { + COL_Property, + COL_COUNT, + COL_KEY + }; +}; + +class PropertyRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_PropFlags; +public: + enum { + COL_PropFlags, + + COL_Name, + COL_Type, + COL_COUNT, + COL_KEY + }; + USHORT GetPropFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_PropFlags); + } + void SetPropFlags(USHORT PropFlags) + { + LIMITED_METHOD_CONTRACT; + + m_PropFlags = VAL16(PropFlags); + } + void AddPropFlags(USHORT PropFlags) + { + LIMITED_METHOD_CONTRACT; + + m_PropFlags |= VAL16(PropFlags); + } +}; + +class MethodSemanticsRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Semantic; +public: + enum { + COL_Semantic, + + COL_Method, + COL_Association, + COL_COUNT, + COL_KEY = COL_Association + }; + USHORT GetSemantic() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Semantic); + } + void SetSemantic(USHORT Semantic) + { + LIMITED_METHOD_CONTRACT; + + m_Semantic = VAL16(Semantic); + } +}; + +class MethodImplRec +{ +public: + enum { + COL_Class, // TypeDef where the MethodBody lives. + COL_MethodBody, // MethodDef or MemberRef. + COL_MethodDeclaration, // MethodDef or MemberRef. + COL_COUNT, + COL_KEY = COL_Class + }; +}; + +class ModuleRefRec +{ +public: + enum { + COL_Name, + COL_COUNT, + COL_KEY + }; +}; + +class TypeSpecRec +{ +public: + enum { + COL_Signature, + COL_COUNT, + COL_KEY + }; +}; + +class ImplMapRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_MappingFlags; +public: + enum { + COL_MappingFlags, + + COL_MemberForwarded, // mdField or mdMethod. + COL_ImportName, + COL_ImportScope, // mdModuleRef. + COL_COUNT, + COL_KEY = COL_MemberForwarded + }; + USHORT GetMappingFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_MappingFlags); + } + void SetMappingFlags(USHORT MappingFlags) + { + LIMITED_METHOD_CONTRACT; + + m_MappingFlags = VAL16(MappingFlags); + } + +}; + +class FieldRVARec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_RVA; +public: + enum{ + COL_RVA, + + COL_Field, + COL_COUNT, + COL_KEY = COL_Field + }; + + void Copy(FieldRVARec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_RVA = pFrom->m_RVA; + } + ULONG GetRVA() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_RVA); + } + void SetRVA(ULONG RVA) + { + LIMITED_METHOD_CONTRACT; + + m_RVA = VAL32(RVA); + } +}; + +class ENCLogRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Token; // Token, or like a token, but with (ixTbl|0x80) instead of token type. + ULONG m_FuncCode; // Function code describing the nature of ENC change. +public: + enum { + COL_Token, + COL_FuncCode, + COL_COUNT, + COL_KEY + }; + ULONG GetToken() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Token); + } + void SetToken(ULONG Token) + { + LIMITED_METHOD_CONTRACT; + + m_Token = VAL32(Token); + } + + ULONG GetFuncCode() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_FuncCode); + } + void SetFuncCode(ULONG FuncCode) + { + LIMITED_METHOD_CONTRACT; + + m_FuncCode = VAL32(FuncCode); + } +}; + +class ENCMapRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Token; // Token, or like a token, but with (ixTbl|0x80) instead of token type. +public: + enum { + COL_Token, + COL_COUNT, + COL_KEY + }; + ULONG GetToken() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Token); + } + void SetToken(ULONG Token) + { + LIMITED_METHOD_CONTRACT; + + m_Token = VAL32(Token); + } +}; + +// Assembly tables. + +class AssemblyRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_HashAlgId; + USHORT m_MajorVersion; + USHORT m_MinorVersion; + USHORT m_BuildNumber; + USHORT m_RevisionNumber; + ULONG m_Flags; +public: + enum { + COL_HashAlgId, + COL_MajorVersion, + COL_MinorVersion, + COL_BuildNumber, + COL_RevisionNumber, + COL_Flags, + + COL_PublicKey, // Public key identifying the publisher + COL_Name, + COL_Locale, + COL_COUNT, + COL_KEY + }; + + void Copy(AssemblyRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_HashAlgId = pFrom->m_HashAlgId; + m_MajorVersion = pFrom->m_MajorVersion; + m_MinorVersion = pFrom->m_MinorVersion; + m_BuildNumber = pFrom->m_BuildNumber; + m_RevisionNumber = pFrom->m_RevisionNumber; + m_Flags = pFrom->m_Flags; + } + + ULONG GetHashAlgId() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_HashAlgId); + } + void SetHashAlgId (ULONG HashAlgId) + { + LIMITED_METHOD_CONTRACT; + + m_HashAlgId = VAL32(HashAlgId); + } + + USHORT GetMajorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_MajorVersion); + } + void SetMajorVersion (USHORT MajorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_MajorVersion = VAL16(MajorVersion); + } + + USHORT GetMinorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_MinorVersion); + } + void SetMinorVersion (USHORT MinorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_MinorVersion = VAL16(MinorVersion); + } + + USHORT GetBuildNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_BuildNumber); + } + void SetBuildNumber (USHORT BuildNumber) + { + LIMITED_METHOD_CONTRACT; + + m_BuildNumber = VAL16(BuildNumber); + } + + USHORT GetRevisionNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_RevisionNumber); + } + void SetRevisionNumber (USHORT RevisionNumber) + { + LIMITED_METHOD_CONTRACT; + + m_RevisionNumber = VAL16(RevisionNumber); + } + + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags (ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } + +}; + +class AssemblyProcessorRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Processor; +public: + enum { + COL_Processor, + + COL_COUNT, + COL_KEY + }; + ULONG GetProcessor() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Processor); + } + void SetProcessor(ULONG Processor) + { + LIMITED_METHOD_CONTRACT; + + m_Processor = VAL32(Processor); + } +}; + +class AssemblyOSRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_OSPlatformId; + ULONG m_OSMajorVersion; + ULONG m_OSMinorVersion; +public: + enum { + COL_OSPlatformId, + COL_OSMajorVersion, + COL_OSMinorVersion, + + COL_COUNT, + COL_KEY + }; + ULONG GetOSPlatformId() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSPlatformId); + } + void SetOSPlatformId(ULONG OSPlatformId) + { + LIMITED_METHOD_CONTRACT; + + m_OSPlatformId = VAL32(OSPlatformId); + } + + ULONG GetOSMajorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSMajorVersion); + } + void SetOSMajorVersion(ULONG OSMajorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_OSMajorVersion = VAL32(OSMajorVersion); + } + + ULONG GetOSMinorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSMinorVersion); + } + void SetOSMinorVersion(ULONG OSMinorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_OSMinorVersion = VAL32(OSMinorVersion); + } + +}; + +class AssemblyRefRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_MajorVersion; + USHORT m_MinorVersion; + USHORT m_BuildNumber; + USHORT m_RevisionNumber; + ULONG m_Flags; +public: + enum { + COL_MajorVersion, + COL_MinorVersion, + COL_BuildNumber, + COL_RevisionNumber, + COL_Flags, + + COL_PublicKeyOrToken, // The public key or token identifying the publisher of the Assembly. + COL_Name, + COL_Locale, + COL_HashValue, + COL_COUNT, + COL_KEY + }; + void Copy(AssemblyRefRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_MajorVersion = pFrom->m_MajorVersion; + m_MinorVersion = pFrom->m_MinorVersion; + m_BuildNumber = pFrom->m_BuildNumber; + m_RevisionNumber = pFrom->m_RevisionNumber; + m_Flags = pFrom->m_Flags; + } + USHORT GetMajorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_MajorVersion); + } + void SetMajorVersion(USHORT MajorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_MajorVersion = VAL16(MajorVersion); + } + + USHORT GetMinorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_MinorVersion); + } + void SetMinorVersion(USHORT MinorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_MinorVersion = VAL16(MinorVersion); + } + + USHORT GetBuildNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_BuildNumber); + } + void SetBuildNumber(USHORT BuildNumber) + { + LIMITED_METHOD_CONTRACT; + + m_BuildNumber = VAL16(BuildNumber); + } + + USHORT GetRevisionNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_RevisionNumber); + } + void SetRevisionNumber(USHORT RevisionNumber) + { + LIMITED_METHOD_CONTRACT; + + m_RevisionNumber = RevisionNumber; + } + + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } + +}; + +class AssemblyRefProcessorRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Processor; +public: + enum { + COL_Processor, + + COL_AssemblyRef, // mdtAssemblyRef + COL_COUNT, + COL_KEY + }; + ULONG GetProcessor() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Processor); + } + void SetProcessor(ULONG Processor) + { + LIMITED_METHOD_CONTRACT; + + m_Processor = VAL32(Processor); + } +}; + +class AssemblyRefOSRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_OSPlatformId; + ULONG m_OSMajorVersion; + ULONG m_OSMinorVersion; +public: + enum { + COL_OSPlatformId, + COL_OSMajorVersion, + COL_OSMinorVersion, + + COL_AssemblyRef, // mdtAssemblyRef. + COL_COUNT, + COL_KEY + }; + ULONG GetOSPlatformId() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSPlatformId); + } + void SetOSPlatformId(ULONG OSPlatformId) + { + LIMITED_METHOD_CONTRACT; + + m_OSPlatformId = VAL32(OSPlatformId); + } + + ULONG GetOSMajorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSMajorVersion); + } + void SetOSMajorVersion(ULONG OSMajorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_OSMajorVersion = VAL32(OSMajorVersion); + } + + ULONG GetOSMinorVersion() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_OSMinorVersion); + } + void SetOSMinorVersion(ULONG OSMinorVersion) + { + LIMITED_METHOD_CONTRACT; + + m_OSMinorVersion = VAL32(OSMinorVersion); + } +}; + +class FileRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Flags; +public: + enum { + COL_Flags, + + COL_Name, + COL_HashValue, + COL_COUNT, + COL_KEY + }; + void Copy(FileRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = pFrom->m_Flags; + } + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } +}; + +class ExportedTypeRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Flags; + ULONG m_TypeDefId; +public: + enum { + COL_Flags, + COL_TypeDefId, + + COL_TypeName, + COL_TypeNamespace, + COL_Implementation, // mdFile or mdAssemblyRef. + COL_COUNT, + COL_KEY + }; + void Copy(ExportedTypeRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = pFrom->m_Flags; + m_TypeDefId = pFrom->m_TypeDefId; + } + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } + + ULONG GetTypeDefId() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_TypeDefId); + } + void SetTypeDefId(ULONG TypeDefId) + { + LIMITED_METHOD_CONTRACT; + + m_TypeDefId = VAL32(TypeDefId); + } +}; + +class ManifestResourceRec +{ +METADATA_FIELDS_PROTECTION: + ULONG m_Offset; + ULONG m_Flags; +public: + enum { + COL_Offset, + COL_Flags, + + COL_Name, + COL_Implementation, // mdFile or mdAssemblyRef. + COL_COUNT, + COL_KEY + }; + void Copy(ManifestResourceRec *pFrom) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = pFrom->m_Flags; + m_Offset = pFrom->m_Offset; + } + + ULONG GetOffset() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Offset); + } + void SetOffset(ULONG Offset) + { + LIMITED_METHOD_CONTRACT; + + m_Offset = VAL32(Offset); + } + + ULONG GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL32(&m_Flags); + } + void SetFlags(ULONG Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL32(Flags); + } + +}; + +// End Assembly Tables. + +class NestedClassRec +{ +public: + enum { + COL_NestedClass, + COL_EnclosingClass, + COL_COUNT, + COL_KEY = COL_NestedClass + }; +}; + +// Generics + + +class GenericParamRec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Number; // index; zero = first var + USHORT m_Flags; // index; zero = first var +public: + enum { + + COL_Number, // index; zero = first var + COL_Flags, // flags, for future use + COL_Owner, // typeDef/methodDef + COL_Name, // Purely descriptive, not used for binding purposes + COL_COUNT, + COL_KEY = COL_Owner + }; + + USHORT GetNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Number); + } + void SetNumber(USHORT Number) + { + LIMITED_METHOD_CONTRACT; + + m_Number = VAL16(Number); + } + + USHORT GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Flags); + } + void SetFlags(USHORT Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL16(Flags); + } +}; + +// @todo: this definition is for reading the old (and wrong) GenericParamRec from a +// Beta1 assembly. +class GenericParamV1_1Rec +{ +METADATA_FIELDS_PROTECTION: + USHORT m_Number; // index; zero = first var + USHORT m_Flags; // index; zero = first var +public: + enum { + + COL_Number, // index; zero = first var + COL_Flags, // flags, for future use + COL_Owner, // typeDef/methodDef + COL_Name, // Purely descriptive, not used for binding purposes + COL_Kind, // typeDef/Ref/Spec, reserved for future use + COL_COUNT, + COL_KEY = COL_Owner + }; + + USHORT GetNumber() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Number); + } + void SetNumber(USHORT Number) + { + LIMITED_METHOD_CONTRACT; + + m_Number = VAL16(Number); + } + + USHORT GetFlags() + { + LIMITED_METHOD_CONTRACT; + + return GET_UNALIGNED_VAL16(&m_Flags); + } + void SetFlags(USHORT Flags) + { + LIMITED_METHOD_CONTRACT; + + m_Flags = VAL16(Flags); + } +}; + +class MethodSpecRec +{ +public: + enum { + COL_Method, // methodDef/memberRef + COL_Instantiation, // signature + COL_COUNT, + COL_KEY + }; +}; + + +class GenericParamConstraintRec +{ +public: + enum { + + COL_Owner, // GenericParam + COL_Constraint, // typeDef/Ref/Spec + COL_COUNT, + COL_KEY = COL_Owner + }; +}; + +#include + +// List of MiniMd tables. + +#define MiniMdTables() \ + MiniMdTable(Module) \ + MiniMdTable(TypeRef) \ + MiniMdTable(TypeDef) \ + MiniMdTable(FieldPtr) \ + MiniMdTable(Field) \ + MiniMdTable(MethodPtr) \ + MiniMdTable(Method) \ + MiniMdTable(ParamPtr) \ + MiniMdTable(Param) \ + MiniMdTable(InterfaceImpl) \ + MiniMdTable(MemberRef) \ + MiniMdTable(Constant) \ + MiniMdTable(CustomAttribute)\ + MiniMdTable(FieldMarshal) \ + MiniMdTable(DeclSecurity) \ + MiniMdTable(ClassLayout) \ + MiniMdTable(FieldLayout) \ + MiniMdTable(StandAloneSig) \ + MiniMdTable(EventMap) \ + MiniMdTable(EventPtr) \ + MiniMdTable(Event) \ + MiniMdTable(PropertyMap) \ + MiniMdTable(PropertyPtr) \ + MiniMdTable(Property) \ + MiniMdTable(MethodSemantics)\ + MiniMdTable(MethodImpl) \ + MiniMdTable(ModuleRef) \ + MiniMdTable(TypeSpec) \ + MiniMdTable(ImplMap) \ + MiniMdTable(FieldRVA) \ + MiniMdTable(ENCLog) \ + MiniMdTable(ENCMap) \ + MiniMdTable(Assembly) \ + MiniMdTable(AssemblyProcessor) \ + MiniMdTable(AssemblyOS) \ + MiniMdTable(AssemblyRef) \ + MiniMdTable(AssemblyRefProcessor) \ + MiniMdTable(AssemblyRefOS) \ + MiniMdTable(File) \ + MiniMdTable(ExportedType) \ + MiniMdTable(ManifestResource) \ + MiniMdTable(NestedClass) \ + MiniMdTable(GenericParam) \ + MiniMdTable(MethodSpec) \ + MiniMdTable(GenericParamConstraint) \ + +#undef MiniMdTable +#define MiniMdTable(x) TBL_##x, +enum { + MiniMdTables() + TBL_COUNT, // Highest table. + TBL_COUNT_V1 = TBL_NestedClass + 1, // Highest table in v1.0 database + TBL_COUNT_V2 = TBL_GenericParamConstraint + 1 // Highest in v2.0 database +}; +#undef MiniMdTable + +// List of MiniMd coded token types. +#define MiniMdCodedTokens() \ + MiniMdCodedToken(TypeDefOrRef) \ + MiniMdCodedToken(HasConstant) \ + MiniMdCodedToken(HasCustomAttribute) \ + MiniMdCodedToken(HasFieldMarshal) \ + MiniMdCodedToken(HasDeclSecurity) \ + MiniMdCodedToken(MemberRefParent) \ + MiniMdCodedToken(HasSemantic) \ + MiniMdCodedToken(MethodDefOrRef) \ + MiniMdCodedToken(MemberForwarded) \ + MiniMdCodedToken(Implementation) \ + MiniMdCodedToken(CustomAttributeType) \ + MiniMdCodedToken(ResolutionScope) \ + MiniMdCodedToken(TypeOrMethodDef) \ + +#undef MiniMdCodedToken +#define MiniMdCodedToken(x) CDTKN_##x, +enum { + MiniMdCodedTokens() + CDTKN_COUNT +}; +#undef MiniMdCodedToken + +//***************************************************************************** +// Meta-meta data. Constant across all MiniMds. +//***************************************************************************** +#ifndef _META_DATA_META_CONSTANTS_DEFINED +#define _META_DATA_META_CONSTANTS_DEFINED +const unsigned int iRidMax = 63; +const unsigned int iCodedToken = 64; // base of coded tokens. +const unsigned int iCodedTokenMax = 95; +const unsigned int iSHORT = 96; // fixed types. +const unsigned int iUSHORT = 97; +const unsigned int iLONG = 98; +const unsigned int iULONG = 99; +const unsigned int iBYTE = 100; +const unsigned int iSTRING = 101; // pool types. +const unsigned int iGUID = 102; +const unsigned int iBLOB = 103; + +inline int IsRidType(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix <= iRidMax; } +inline int IsCodedTokenType(ULONG ix) {LIMITED_METHOD_CONTRACT; return (ix >= iCodedToken) && (ix <= iCodedTokenMax); } +inline int IsRidOrToken(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix <= iCodedTokenMax; } +inline int IsHeapType(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix >= iSTRING; } +inline int IsFixedType(ULONG ix) {LIMITED_METHOD_CONTRACT; return (ix < iSTRING) && (ix > iCodedTokenMax); } +#endif + + +enum MDPools { + MDPoolStrings, // Id for the string pool. + MDPoolGuids, // ...the GUID pool. + MDPoolBlobs, // ...the blob pool. + MDPoolUSBlobs, // ...the user string pool. + + MDPoolCount, // Count of pools, for array sizing. +}; // enum MDPools + + +struct CCodedTokenDef +{ + ULONG m_cTokens; // Count of tokens. + const mdToken *m_pTokens; // Array of tokens. + const char *m_pName; // Name of the coded-token type. +}; + +struct CMiniColDef +{ + BYTE m_Type; // Type of the column. + BYTE m_oColumn; // Offset of the column. + BYTE m_cbColumn; // Size of the column. +}; + +struct CMiniTableDef +{ + CMiniColDef *m_pColDefs; // Array of field defs. + BYTE m_cCols; // Count of columns in the table. + BYTE m_iKey; // Column which is the key, if any. + USHORT m_cbRec; // Size of the records. +}; +struct CMiniTableDefEx +{ + CMiniTableDef m_Def; // Table definition. + const char * const *m_pColNames; // Array of column names. + const char *m_pName; // Name of the table. +}; + +#endif // _METAMODELPUB_H_ +// eof ------------------------------------------------------------------------ diff --git a/lib/coreclr/src/inc/mpl/type_list b/lib/coreclr/src/inc/mpl/type_list new file mode 100644 index 0000000000..9073c5e8d0 --- /dev/null +++ b/lib/coreclr/src/inc/mpl/type_list @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Used in template metaprogramming, type lists consist of a series of +// Scheme-like nodes that contain a Head type and a Tail type. The head +// type is usually a non-list type, but compound lists are possible. +// +// Type lists are always terminated with a tail type of mpl::null_type. +// + +#ifndef __type_list__ +#define __type_list__ + +namespace mpl // 'mpl' => 'meta-programming library' +{ + // Used as terminator in type_lists. + class null_type {}; + + // The core type. See file comment for details. + template + struct type_list + { + typedef T head; + typedef U tail; + }; + + template + struct type_at; + + template + struct type_at, IDX> + { typedef typename type_at::type type; }; + + template + struct type_at, 0> + { typedef head type; }; + + // Helper struct to create a type_list chain from a list of arguments. + template + < + typename T1 = null_type, typename T2 = null_type, typename T3 = null_type, + typename T4 = null_type, typename T5 = null_type, typename T6 = null_type, + typename T7 = null_type, typename T8 = null_type, typename T9 = null_type, + typename T10 = null_type, typename T11 = null_type, typename T12 = null_type, + typename T13 = null_type, typename T14 = null_type, typename T15 = null_type, + typename T16 = null_type, typename T17 = null_type, typename T18 = null_type + > + struct make_type_list + { + private: + // recurse on the tail elements + typedef typename make_type_list::type tail; + + public: + // combine head with computed tail + typedef type_list type; + }; + + template<> + struct make_type_list + < + null_type, null_type, null_type, null_type, null_type, null_type, + null_type, null_type, null_type, null_type, null_type, null_type, + null_type, null_type, null_type, null_type, null_type, null_type + > + { + public: + typedef null_type type; + }; +} + +#endif // __type_list__ + diff --git a/lib/coreclr/src/inc/mscorsvc.idl b/lib/coreclr/src/inc/mscorsvc.idl new file mode 100644 index 0000000000..33ded4247f --- /dev/null +++ b/lib/coreclr/src/inc/mscorsvc.idl @@ -0,0 +1,683 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/* -------------------------------------------------------------------------- * + * Microsoft .NET Framework Service + * -------------------------------------------------------------------------- */ + +#ifndef IN_MSCOREE +cpp_quote("#if 0") // So that the outputted header file doesn't cause redefines + +import "unknwn.idl"; + +cpp_quote("#endif") + +// CLSID_CorSvcWorker +cpp_quote("EXTERN_GUID(CLSID_CorSvcWorker, 0x8ed1a844, 0x32a7, 0x4a67, 0xba, 0x62, 0xf8, 0xd5, 0xaf, 0xdf, 0xf4, 0x60);") + +// CLSID_CorSvcBindToWorker +cpp_quote("EXTERN_GUID(CLSID_CorSvcBindToWorker, 0x9f74fb09, 0x4221, 0x40b4, 0xae, 0x21, 0xae, 0xb6, 0xdf, 0xf2, 0x99, 0x4e);") + +#pragma midl_echo("STDAPI CorGetSvc(IUnknown **pIUnknown);") + +[ + uuid(d69cca64-16f7-485c-8cf1-67063e44f0c3), + version(2.0), + helpstring("Common Language Runtime Execution Engine 2.0 Library") +] +library mscorsvc +{ + importlib("stdole32.tlb"); + +#endif // IN_MSCOREE + + + //***************************************************************************** + // ICorSvcDependencies is used to enumerate the dependencies of an + // IL image. It is used by the native image service. + //*****************************************************************************[ + + [ + object, + oleautomation, + uuid(ddb34005-9ba3-4025-9554-f00a2df5dbf5), + pointer_default(unique), + ] + interface ICorSvcDependencies : IUnknown + { + HRESULT GetAssemblyDependencies( + [in] BSTR pAssemblyName, + [out] SAFEARRAY(BSTR) *pDependencies, + [out] DWORD *assemblyNGenSetting, + [out] BSTR *pNativeImageIdentity, + [out] BSTR *pAssemblyDisplayName, + [out] SAFEARRAY(DWORD) *pDependencyLoadSetting, + [out] SAFEARRAY(DWORD) *pDependencyNGenSetting + ); + } + + //***************************************************************************** + // ICorSvcWorker contains methods for generating native images and enumerating + // their dependencies. + //*****************************************************************************[ + + typedef enum + { + ScenarioDefault = 0x00000000, // No special scenario flags + ScenarioAll = 0x00000001, // All scenarios (used to indicate all configurations) + ScenarioDebug = 0x00000002, // Unoptimized debuggable code + ScenarioProfile = 0x00000008, // Used for profiling (enter/leave notifications) + ScenarioTuningDataCollection = 0x00000010, // Used to gather IBC data + ScenarioLegacy = 0x00000020, // Follow hard dependencies only + + ScenarioNgenLastRetry = 0x00010000, // Ngen failed last time and this a final retry + ScenarioAutoNGen = 0x00100000, // This is an Auto NGen request + ScenarioRepositoryOnly = 0x00200000, // Install from repository only, no real NGen + } OptimizationScenario; + + typedef enum + { + ScenarioEmitFixups = 0x00010000, // Emit fixups for Vulcan + ScenarioProfileInfo = 0x00020000 // Generate a PE section with profile ranges data + } PrivateOptimizationScenario; + + typedef struct _SvcWorkerPriority + { + DWORD dwPriorityClass; + } SvcWorkerPriority; + + [ + object, + oleautomation, + uuid(d1047bc2-67c0-400c-a94c-e64446a67fbe), + pointer_default(unique), + ] + interface ICorSvcWorker : IUnknown + { + HRESULT SetPriority( + [in] SvcWorkerPriority priority + ); + + HRESULT OptimizeAssembly( + [in] BSTR pAssemblyName, + [in] BSTR pApplicationName, + [in] OptimizationScenario scenario, + [in] SAFEARRAY(BSTR) loadAlwaysList, + [in] SAFEARRAY(BSTR) loadSometimesList, + [in] SAFEARRAY(BSTR) loadNeverList, + [out] BSTR *pNativeImageIdentity + ); + + HRESULT DeleteNativeImage( + [in] BSTR pAssemblyName, + [in] BSTR pNativeImage + ); + + HRESULT DisplayNativeImages( + [in] BSTR pAssemblyName + ); + + HRESULT GetCorSvcDependencies( + [in] BSTR pApplicationName, + [in] OptimizationScenario scenario, + [out] ICorSvcDependencies **pCorSvcDependencies + ); + + HRESULT Stop( + ); + } + + [ + object, + oleautomation, + uuid(f3358a7d-0061-4776-880e-a2f21b9ef93e), + pointer_default(unique), + ] + interface ICorSvcWorker2 : ICorSvcWorker { + // Create a PDB for the NGEN image that was generated for pAssemblyName + // when compiled with the given appbase and scenario. + HRESULT CreatePdb([in] BSTR pAssemblyName, + [in] BSTR pAppBaseOrConfig, + [in] OptimizationScenario scenario, + [in] BSTR pNativeImagePath, + [in] BSTR pPdbPath); + }; + + [ + object, + oleautomation, + uuid(DC516615-47BE-477e-8B55-C5ABE0D76B8F), + pointer_default(unique), + ] + interface ICorSvcWorker3 : ICorSvcWorker2 { + // Create a PDB for the NGEN image that was generated for pAssemblyName + // when compiled with the given appbase and scenario. Optionally include + // source lines information in the geneated PDB + HRESULT CreatePdb2([in] BSTR pAssemblyName, + [in] BSTR pAppBaseOrConfig, + [in] OptimizationScenario scenario, + [in] BSTR pNativeImagePath, + [in] BSTR pPdbPath, + [in] BOOL pdbLines, + [in] BSTR managedPdbSearchPath); + }; + + //***************************************************************************** + // ICorSvcSetPrivateAttributes sets private attributes that are used just for + // the initial compilation + //*****************************************************************************[ + + typedef enum + { + DbgTypePdb = 0x00000001, // Generate a pdb for the NGen image + } NGenPrivateAttributesFlags; + + typedef struct _NGenPrivateAttributes + { + DWORD Flags; + DWORD ZapStats; + BSTR DbgDir; + } NGenPrivateAttributes; + + [ + object, + oleautomation, + uuid(b18e0b40-c089-4350-8328-066c668bccc2), + pointer_default(unique), + ] + interface ICorSvcSetPrivateAttributes : IUnknown + { + HRESULT SetNGenPrivateAttributes( + [in] NGenPrivateAttributes ngenPrivateAttributes + ); + + } + + //***************************************************************************** + // ICorSvcRepository controls native images repository + //*****************************************************************************[ + + typedef enum + { + RepositoryDefault = 0x0, // default settings + MoveFromRepository = 0x1, // move the native images from repository + CopyToRepository = 0x2, // copy the generated native images to repository + IgnoreRepository = 0x4, // Do not use the repository + } RepositoryFlags; + + [ + object, + oleautomation, + uuid(d5346658-b5fd-4353-9647-07ad4783d5a0), + pointer_default(unique), + ] + interface ICorSvcRepository : IUnknown + { + HRESULT SetRepository( + [in] BSTR pRepositoryDir, + [in] RepositoryFlags repositoryFlags + ); + + } + +#ifdef FEATURE_APPX + //***************************************************************************** + // ICorSvcAppX contains AppX-related method + //*****************************************************************************[ + + [ + object, + uuid(5c814791-559e-4f7f-83ce-184a4ccbae24), + pointer_default(unique), + ] + interface ICorSvcAppX : IUnknown + { + HRESULT SetPackage([in] BSTR pPackageFullName); + + HRESULT SetLocalAppDataDirectory([in] BSTR pLocalAppDataDirectory); + } +#endif + + //***************************************************************************** + // ICorSvcLogger is used to log various messages to the service process + //*****************************************************************************[ + + typedef enum CorSvcLogLevel + { + LogLevel_Error, + LogLevel_Warning, + LogLevel_Success, + LogLevel_Info + } CorSvcLogLevel; + + [ + object, + oleautomation, + uuid(d189ff1a-e266-4f13-9637-4b9522279ffc), + pointer_default(unique), + ] + interface ICorSvcLogger : IUnknown + { + HRESULT Log( + [in] CorSvcLogLevel logLevel, + [in] BSTR message + ); + } + + //***************************************************************************** + // ICorSvcPooledWorker is used to determine whether a worker process can be + // reused + //*****************************************************************************[ + + [ + object, + oleautomation, + uuid(0631e7e2-6046-4fde-8b6d-a09b64fda6f3), + pointer_default(unique), + ] + interface ICorSvcPooledWorker : IUnknown + { + HRESULT CanReuseProcess( + [in] OptimizationScenario scenario, + [in] ICorSvcLogger *pCorSvcLogger, + [out] BOOL *pCanContinue + ); + } + + + //***************************************************************************** + // ICorSvcBindToWorker is used to bind to a specific runtime version. + //*****************************************************************************[ + + + [ + object, + oleautomation, + uuid(5c6fb596-4828-4ed5-b9dd-293dad736fb5), + pointer_default(unique), + ] + interface ICorSvcBindToWorker : IUnknown + { + HRESULT BindToRuntimeWorker( + [in] BSTR pRuntimeVersion, + [in] DWORD ParentProcessID, + [in] BSTR pInterruptEventName, + [in] ICorSvcLogger *pCorSvcLogger, + [out] ICorSvcWorker **pCorSvcWorker + ); + } + +#ifndef IN_MSCOREE +} + +typedef enum +{ + Service_NoAction = -1 , + Service_Start = 0x0, // start service + Service_Stop = 0x1, // Stop service + Service_Pause = 0x2, // pause service + Service_Continue = 0x3, // continue a paused service + Service_Interrogate = 0x4, // continue a paused service + Service_StartPaused = 0x5, // pause service. start and pause if it's stopped +} ControlServiceAction; + +// Haven't seen a better way of doing this. Everybody seems to be duplicating +// into IDLs (for example wtypes.idl) +typedef struct _COR_SERVICE_STATUS +{ + WCHAR sServiceName[64]; + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; +} COR_SERVICE_STATUS, *LPCOR_SERVICE_STATUS; + +/* -------------------------------------------------------------------------- * + * ICorSvc is implemented by the service dispatcher and contains APIs + * for installing/uninstalling/starting/stopping the native image service, + * as well as marshaling logic that provides the ICorOptSvcManager interface. + * -------------------------------------------------------------------------- */ +typedef struct _ServiceOptions +{ + BOOL RunAsWindowsService; + BOOL RunAsPrivateRuntime; + BOOL StartPaused; +} ServiceOptions; + + +[ + object, + uuid(3eef5ff0-3680-4f20-8a8f-9051aca66b22), + pointer_default(unique), +] +interface ICorSvc : IUnknown +{ + HRESULT GetServiceManagerInterface( + [in] IUnknown **pIUnknown + ); + + HRESULT InstallService( + ); + + HRESULT UninstallService( + ); + + HRESULT ControlService( + [in] ControlServiceAction Action, + [out] LPCOR_SERVICE_STATUS lpServiceStatus + ); + + HRESULT RunService( + [in] ServiceOptions options + ); +} + +[ + object, + uuid(01c10030-6c81-4671-bd51-14b184c673b2), + pointer_default(unique), +] +interface ICompileProgressNotification : IUnknown +{ + // Notify the installer that compilation has started, and give it an + // estimation of how long it will take. + HRESULT CompileStarted( + [in] DWORD cAssembliesToCompile, + [in] DWORD cTimeEstimate + ); + + // Notify the installer that one more assembly has been compiled. The + // installer can return E_ABORT from ProgressNotification if it wants to + // abort the compilation. + HRESULT ProgressNotification( + [in] DWORD cAssembly, + [in] BSTR pAssemblyName, + [in] BOOL isStartNotification, // if TRUE: we're starting to compile, if FALSE, we finished + [in] HRESULT hrResult, + [in] BSTR errorExplanation, + [in] DWORD cTimeRemainingEstimate + ); + + +} + +/* + * Ndp v4 interface that provides a threadID in notification messages + */ +[ + object, + uuid(98E5BDE2-E9A0-4ADE-9CB2-6CD06FDB1A85), + pointer_default(unique), +] +interface ICompileProgressNotification2 : IUnknown +{ + // Notify the installer that compilation has started, and give it an + // estimation of how long it will take. + HRESULT CompileStarted( + [in] DWORD cAssembliesToCompile, + [in] DWORD cTimeEstimate, + [in] DWORD threadID + ); + + // Notify the installer that one more assembly has been compiled. The + // installer can return E_ABORT from ProgressNotification if it wants to + // abort the compilation. + HRESULT ProgressNotification( + [in] DWORD cAssembly, + [in] BSTR pAssemblyName, + [in] BOOL isStartNotification, // if TRUE: we're starting to compile, if FALSE, we finished + [in] HRESULT hrResult, + [in] BSTR errorExplanation, + [in] DWORD cTimeRemainingEstimate, + [in] DWORD threadID + ); + + +} + +typedef enum +{ + DefaultOptimizeFlags = 0x0, // default settings + TolerateCompilationFailures = 0x1, // continue after encoutering compilation failures + OptimizeNGenQueueOnly = 0x2 // only take work items from the NGen Queue +} OptimizeFlags; + + +[ + object, + uuid(0523feee-eb0e-4857-b2aa-db787521d077), + pointer_default(unique), +] +interface ICorSvcInstaller : IUnknown +{ + HRESULT Install( + [in] BSTR path + ); + + HRESULT Uninstall( + [in] BSTR path + ); + + HRESULT Optimize( + [in] ICompileProgressNotification *pCompileProgressNotification, + [in] OptimizeFlags optimizeFlags + ); + + HRESULT SetLogger( + [in] ICorSvcLogger *pCorSvcLogger + ); +} + +typedef enum +{ + DefaultFlags = 0x0, // default settings + AllowPartialNames = 0x1, // input path allows partial names + KeepPriority = 0x2, // keep priority after ngen completes + NoRoot = 0x4, // Do not persist NGen root (automatically initiated NGen) +} GeneralFlags; + +typedef enum +{ + Priority_None = -1, + Priority_0 = 0x0, // NGen offline queue. Do not use for anything else + Priority_1 = 0x1, + Priority_2 = 0x2, + Priority_3 = 0x3, // If you add or remove priorities, update Priority_Lowest + + Priority_Default = Priority_3, + Priority_Lowest = Priority_3, + Priority_LowestAggressive = Priority_2, // The lowest priority for which assemblies are compiled aggressively + Priority_Highest = Priority_0, + Priority_Highest_Root = Priority_1, + Priority_Lowest_Root = Priority_3 +} PriorityLevel; + + +/* -------------------------------------------------------------------------- * + * ICorSvcAdvancedInstaller is implemented by the service manager and + * used by installers with custom install requirements + * such as special scenarios or hosting requirements). + * -------------------------------------------------------------------------- */ + +[ + object, + uuid(0871fb80-3ea0-47cc-9b51-d92e2aee75db), + pointer_default(unique), +] +interface ICorSvcAdvancedInstaller : IUnknown +{ + HRESULT Install( + [in] BSTR path, + [in] OptimizationScenario optScenario, + [in] BSTR config, + [in] GeneralFlags generalFlags, + [in] PriorityLevel priorityLevel + ); + + HRESULT Uninstall( + [in] BSTR path, + [in] OptimizationScenario optScenario, + [in] BSTR config, + [in] GeneralFlags generalFlags + ); +} + + +/* -------------------------------------------------------------------------- * + * ICorSvcOptimizer is implemented by the service manager and is called + * by installers and other tools to repair the native image caches. + * -------------------------------------------------------------------------- */ + +typedef enum +{ + UpdateDefault = 0x0, // no hints about the scope of the update + Force = 0x1, // force generation of new native images + PostReboot = 0x2 // Update must happen after reboot +} UpdateFlags; + + +[ + object, + uuid(94af0ec4-c10d-45d4-a625-d68d1b02a396), + pointer_default(unique), +] +interface ICorSvcOptimizer : IUnknown +{ + // Optimize the native image for a given application or assembly (will regenerate + // native images that are out of date) + HRESULT Update( + [in] BSTR path, + [in] UpdateFlags updateFlags, + [in] GeneralFlags generalFlags + ); + + HRESULT Display( + [in] BSTR path, + [in] GeneralFlags generalFlags + ); + + HRESULT ScheduleWork( + [in] PriorityLevel priorityLevel + ); +} + +[ + object, + uuid(ee3b09c2-0110-4b6e-a73f-a3d6562f98ab), + pointer_default(unique) +] +interface ICorSvcOptimizer2 : ICorSvcOptimizer { + // generate a PDB for the given native image + HRESULT CreatePdb([in] BSTR nativeImagePath, [in] BSTR pdbPath); +} + +[ + object, + uuid(6EED164F-61EE-4a07-ABE8-670F92B4B7A9), + pointer_default(unique) +] +interface ICorSvcOptimizer3 : ICorSvcOptimizer2 { + // generate a PDB for the given native image, optionally including source lines info + HRESULT CreatePdb2([in] BSTR nativeImagePath, [in] BSTR pdbPath, [in] BOOL pdbLines, [in] BSTR managedPdbSearchPath); +} + +typedef enum +{ + NewWorkAvailable = 0x0, // Notify the service that there is new work to do. + ClientWorkStart = 0x1, // Notify the service that there is client starting to do work. + ClientWorkDone = 0x2, // Notify the service that the client is done doing work. + UpdatePostReboot = 0x3, // Notify the service that it should do an 'ngen update' after reboot + NewWorkAvailableWithDelay = 0x4, // Like NewWorkAvailable, but service should wait a while before working +} ServiceNotification; + + +/* -------------------------------------------------------------------------- * + * ICorSvcManager is implemented by the service manager and used by + * the service controller in balancing the need to generate native images + * with the desire to not interfere with the usage of the computer. + * -------------------------------------------------------------------------- */ +[ + object, + uuid(8f416a48-d663-4a7e-9732-fbca3fc46ea8), + pointer_default(unique), +] +interface ICorSvcManager : IUnknown +{ + // Schedule work only for selected priority level + HRESULT ScheduleWorkForSinglePriorityLevel( + [in] PriorityLevel priorityLevel, + [in] BSTR pInterruptEventName, + [out] BOOL* pWorkScheduled + ); + + // Do scheduled work + HRESULT Optimize( + [in] DWORD dwWorkerPriorityClass, + [in] ICompileProgressNotification *pCompileProgressNotification, + [in] BSTR pInterruptEventName + ); + + // Notify the service of new work + HRESULT NotifyService(ServiceNotification notification); + + HRESULT IsWorkAvailable ([in] PriorityLevel priorityLevel, + [out] BOOL* pWorkAvailable); + + HRESULT Update( + [in] UpdateFlags updateFlags, + [in] BSTR pInterruptEventName + ); + + HRESULT SetSvcLogger( + [in] ICorSvcLogger *pCorSvcLogger + ); +} + +[ + object, + uuid(29626056-8031-441b-affa-7a82480058b3), + pointer_default(unique), +] +interface ICorSvcManager2 : IUnknown +{ + HRESULT SetRuntimeVersion(BSTR version); + + HRESULT SetPackageMoniker(BSTR moniker); + + HRESULT SetLocalAppData(BSTR directory); +} + +[ + object, + uuid(35e5d609-ec3d-4fc2-9ba2-5f99e42ff42f), + pointer_default(unique), +] +interface ICorSvcSetLegacyServiceBehavior : IUnknown +{ + HRESULT SetLegacyServiceBehavior(); +} + +[ + object, + uuid(115466A4-7005-4CA3-971F-01F0A2C8EF09), + pointer_default(unique), +] +interface ICorSvcSetTaskBootTriggerState : IUnknown +{ + HRESULT SetTaskBootTriggerState(BOOL bEnabled); +} + +[ + object, + uuid(261DD1E3-F07E-4B8D-B54E-F26889413626), + pointer_default(unique), +] +interface ICorSvcSetTaskDelayStartTriggerState : IUnknown +{ + HRESULT SetTaskDelayStartTriggerState(BOOL bEnabled); +} + +#endif // IN_MSCOREE diff --git a/lib/coreclr/src/inc/msodw.h b/lib/coreclr/src/inc/msodw.h new file mode 100644 index 0000000000..a1acc2f16f --- /dev/null +++ b/lib/coreclr/src/inc/msodw.h @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#pragma once + +/**************************************************************************** + This files contains the handshake structure with which apps will launch + Watson. +****************************************************************************/ + +#ifndef MSODW_H +#define MSODW_H +#pragma pack(push, msodw_h) +#pragma pack(4) + +#define DW_MAX_BUCKETPARAM_CWC 255 + +typedef struct _GenericModeBlock +{ + BOOL fInited; + WCHAR wzEventTypeName[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP1[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP2[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP3[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP4[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP5[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP6[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP7[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP8[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP9[DW_MAX_BUCKETPARAM_CWC]; + WCHAR wzP10[DW_MAX_BUCKETPARAM_CWC]; +} GenericModeBlock; + +#pragma pack(pop, msodw_h) +#endif // MSODW_H diff --git a/lib/coreclr/src/inc/msodwwrap.h b/lib/coreclr/src/inc/msodwwrap.h new file mode 100644 index 0000000000..28c7247502 --- /dev/null +++ b/lib/coreclr/src/inc/msodwwrap.h @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#ifndef __msodwwrap_h__ +#define __msodwwrap_h__ + +#ifndef MSODW_H +#include "msodw.h" +#endif // MSODW_H + +#endif // __msodwwrap_h__ diff --git a/lib/coreclr/src/inc/nativevaraccessors.h b/lib/coreclr/src/inc/nativevaraccessors.h new file mode 100644 index 0000000000..b3ee7bba0b --- /dev/null +++ b/lib/coreclr/src/inc/nativevaraccessors.h @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// The following are used to read and write data given NativeVarInfo +// for primitive types. Don't use these for VALUECLASSes. +//***************************************************************************** + + +#ifndef _NATIVE_VAR_ACCESSORS_H_ +#define _NATIVE_VAR_ACCESSORS_H_ + +#include "corjit.h" + +bool operator ==(const ICorDebugInfo::VarLoc &varLoc1, + const ICorDebugInfo::VarLoc &varLoc2); + +#define MAX_NATIVE_VAR_LOCS 2 + +SIZE_T GetRegOffsInCONTEXT(ICorDebugInfo::RegNum regNum); + +struct NativeVarLocation +{ + ULONG64 addr; + TADDR size; + bool contextReg; +}; + +ULONG NativeVarLocations(const ICorDebugInfo::VarLoc & varLoc, + PT_CONTEXT pCtx, + ULONG numLocs, + NativeVarLocation* locs); + +SIZE_T *NativeVarStackAddr(const ICorDebugInfo::VarLoc & varLoc, + PT_CONTEXT pCtx); + +bool GetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, + PT_CONTEXT pCtx, + SIZE_T * pVal1, + SIZE_T * pVal2 + WIN64_ARG(SIZE_T cbSize)); + +bool SetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, + PT_CONTEXT pCtx, + SIZE_T val1, + SIZE_T val2 + WIN64_ARG(SIZE_T cbSize)); +#endif // #ifndef _NATIVE_VAR_ACCESSORS_H_ diff --git a/lib/coreclr/src/inc/new.hpp b/lib/coreclr/src/inc/new.hpp new file mode 100644 index 0000000000..3e6644d184 --- /dev/null +++ b/lib/coreclr/src/inc/new.hpp @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// + +#ifndef __new__hpp +#define __new__hpp + +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define NOEXCEPT +#else +#define NOEXCEPT noexcept +#endif + +struct NoThrow { int x; }; +extern const NoThrow nothrow; + +void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; +void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT; + +#ifdef _DEBUG +void DisableThrowCheck(); +#endif + +#endif diff --git a/lib/coreclr/src/inc/ngen.h b/lib/coreclr/src/inc/ngen.h new file mode 100644 index 0000000000..fa0b9829d4 --- /dev/null +++ b/lib/coreclr/src/inc/ngen.h @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// This file is the interface to NGen (*N*ative code *G*eneration), +// which compiles IL modules to machine code ahead-of-time. +// This avoids the need for JIT compiling the code at program startup. +// + + +#ifndef _NGEN_H_ +#define _NGEN_H_ + +#include "mscorsvc.h" + +// Log size default of 10 MB. +#define DEFAULT_SERVICE_LOG_SIZE (10 * 1024 * 1024) +// NGEN.log is smaller 1MB +#define DEFAULT_MACHINE_WIDE_LOG_SIZE (1 * 1024 * 1024) +// User specific log is yet smaller 200KB +#define DEFAULT_USER_WIDE_LOG_SIZE (200 * 1024) +// Log size default of 100 KB. This should be big enough to hold some log info from roughly 100 +// ngen events. (Roughly 200KB of space including secondary log file.) +#define DEFAULT_APPLOCAL_WIDE_LOG_SIZE (100*1024) + +#define NGEN_LOG_HEADER_TEXT W("To learn about increasing the verbosity of the NGen log files please see http://go.microsoft.com/fwlink/?linkid=210113\r\n") + +// supported debug info types +enum DebugType +{ + DT_NIL, + DT_PDB +}; + +// +// IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT +// +// This structure cannot have any fields removed from it!!! +// +// IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT * IMPORTANT +// +// NGening a module invokes the runtime against which the module was built. +// Thus this structure needs to be backwards-compatible. +// +// If additional options need to be added to this structure, +// add them to the end of the structure and make sure you update +// logic throughout the runtime to look at a different size in the dwSize +// field. This is how we'll 'version' this structure. +// +// If you are adding a code-generation flag (like debug or prof), use +// fInstrument as a template (but be sure to add your new flag as the +// last element in the struct). + +typedef struct _NGenOptions +{ + DWORD dwSize; // Size of the structure. Used to version the structure + + // V1 + + bool fDebug; // Generate debuggable code and debug information + bool fDebugOpt; // Generate debugging information, but optimized code + bool fProf; // Generate instrumented code for profiling (call graphs) + + bool fSilent; // Dont spew text output + LPCWSTR lpszExecutableFileName; // Name of the module to ngen + + // V2 (Whidbey) + + bool fInstrument; // Generate instrumented code for basic-block profiling + + // No longer supported + bool fWholeProgram; // Do cross function optimizations (whole program) + + // No longer supported + bool fProfInfo; // Embed working set profiling data into the image + + LPCWSTR lpszRepositoryDir; // Directory for repository of native images + RepositoryFlags repositoryFlags; + + // No longer supported + DebugType dtRequested; // the requested debug type + LPCWSTR lpszDebugDir; // the name of the output debug dir for the above + + // No longer supported + bool fNoInstall; // Creates stand alone ngen-images that can be installed in the NIC later + + // No longer supported + bool fEmitFixups; // Support for Vulcan + bool fFatHeaders; + + // Diagnostic flags + bool fVerbose; // print verbose descriptions of native images + unsigned uStats; // image stats mask + +#define LAST_WHIDBEY_NGENOPTION uStats + + // V4 + bool fNgenLastRetry; // Ngen has previously failed and this is the last retry + + // V4.5 + bool fAutoNGen; // This is an automatically generated NGen request + + // Blue + bool fRepositoryOnly;// Install from repository only, no real NGen + +} NGenOptions; + +// Function pointer types that we use to dynamically bind to the appropriate runtime version +extern "C" typedef HRESULT STDAPICALLTYPE + NGenCreateZapperAPI( + HANDLE* hZapper, + NGenOptions *options); +typedef NGenCreateZapperAPI *PNGenCreateZapper; + +extern "C" typedef HRESULT STDAPICALLTYPE + NGenTryEnumerateFusionCacheAPI( + HANDLE hZapper, + LPCWSTR assemblyName, + bool fPrint, + bool fDelete); +typedef NGenTryEnumerateFusionCacheAPI *PNGenTryEnumerateFusionCache; + +// The return type should really be HRESULT. +// However, it is BOOL for backwards-compatibility +extern "C" typedef BOOL STDAPICALLTYPE + NGenCompileAPI( + HANDLE hZapper, + LPCWSTR path); +typedef NGenCompileAPI *PNGenCompile; + +extern "C" typedef HRESULT STDAPICALLTYPE + NGenFreeZapperAPI( + HANDLE hZapper); +typedef NGenFreeZapperAPI *PNGenFreeZapper; + +class ILocalServerLifetime +{ +public: + virtual void AddRefServerProcess() = 0; + virtual void ReleaseServerProcess() = 0; +}; + +struct ICorSvcLogger; + +extern "C" typedef HRESULT STDAPICALLTYPE + NGenCreateNGenWorkerAPI( + ICorSvcWorker **pCorSvcWorker, + ILocalServerLifetime *pLocalServerLifetime, + ICorSvcLogger *pCorSvcLogger + ); +typedef NGenCreateNGenWorkerAPI *PNGenCreateNGenWorker; + +#endif diff --git a/lib/coreclr/src/inc/nibblemapmacros.h b/lib/coreclr/src/inc/nibblemapmacros.h new file mode 100644 index 0000000000..42ea90a2b6 --- /dev/null +++ b/lib/coreclr/src/inc/nibblemapmacros.h @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef NIBBLEMAPMACROS_H_ +#define NIBBLEMAPMACROS_H_ + +/////////////////////////////////////////////////////////////////////// +//// some mmgr stuff for JIT, especially for jit code blocks +/////////////////////////////////////////////////////////////////////// +// +// In order to quickly find the start of a jit code block +// we keep track of all those positions via a map. +// Each entry in this map represents 32 byte (a bucket) of the code heap. +// We make the assumption that no two code-blocks can start in +// the same 32byte bucket; +// Additionally we assume that every code header is DWORD aligned. +// Because we cannot guarantee that jitblocks always start at +// multiples of 32 bytes we cannot use a simple bitmap; instead we +// use a nibble (4 bit) per bucket and encode the offset of the header +// inside the bucket (in DWORDS). In order to make initialization +// easier we add one to the real offset, a nibble-value of zero +// means that there is no header start in the resp. bucket. +// In order to speed up "backwards scanning" we start numbering +// nibbles inside a DWORD from the highest bits (28..31). Because +// of that we can scan backwards inside the DWORD with right shifts. + +#if defined(_WIN64) +// TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist. +// TODO: there is something wrong with USE_INDIRECT_CODEHEADER with CODE_ALIGN=16 +# define CODE_ALIGN 4 +# define LOG2_CODE_ALIGN 2 +#else +# define CODE_ALIGN sizeof(DWORD) // 4 byte boundry +# define LOG2_CODE_ALIGN 2 +#endif +#define NIBBLE_MASK 0xf +#define NIBBLE_SIZE 4 // 4 bits +#define LOG2_NIBBLE_SIZE 2 +#define NIBBLES_PER_DWORD ((8*sizeof(DWORD)) >> LOG2_NIBBLE_SIZE) // 8 (4-bit) nibbles per dword +#define NIBBLES_PER_DWORD_MASK (NIBBLES_PER_DWORD - 1) // 7 +#define LOG2_NIBBLES_PER_DWORD 3 +#define BYTES_PER_BUCKET (NIBBLES_PER_DWORD * CODE_ALIGN) // 32 bytes per bucket +#define LOG2_BYTES_PER_BUCKET (LOG2_CODE_ALIGN + LOG2_NIBBLES_PER_DWORD) // 5 bits per bucket +#define MASK_BYTES_PER_BUCKET (BYTES_PER_BUCKET - 1) // 31 +#define HIGHEST_NIBBLE_BIT (32 - NIBBLE_SIZE) // 28 (i.e 32 - 4) +#define HIGHEST_NIBBLE_MASK (NIBBLE_MASK << HIGHEST_NIBBLE_BIT) // 0xf0000000 + +#define ADDR2POS(x) ((x) >> LOG2_BYTES_PER_BUCKET) +#define ADDR2OFFS(x) (DWORD) ((((x) & MASK_BYTES_PER_BUCKET) >> LOG2_CODE_ALIGN) + 1) +#define POSOFF2ADDR(pos, of) (size_t) (((pos) << LOG2_BYTES_PER_BUCKET) + (((of) - 1) << LOG2_CODE_ALIGN)) +#define HEAP2MAPSIZE(x) (((x) / (BYTES_PER_BUCKET * NIBBLES_PER_DWORD)) * CODE_ALIGN) +#define POS2SHIFTCOUNT(x) (DWORD) (HIGHEST_NIBBLE_BIT - (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) +#define POS2MASK(x) (DWORD) ~(HIGHEST_NIBBLE_MASK >> (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) + +#endif // NIBBLEMAPMACROS_H_ diff --git a/lib/coreclr/src/inc/nibblestream.h b/lib/coreclr/src/inc/nibblestream.h new file mode 100644 index 0000000000..1b92bd06ed --- /dev/null +++ b/lib/coreclr/src/inc/nibblestream.h @@ -0,0 +1,300 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// NibbleStream reader and writer. + + +#ifndef _NIBBLESTREAM_H_ +#define _NIBBLESTREAM_H_ + +#include "contract.h" +#include "sigbuilder.h" + +typedef BYTE NIBBLE; + +//----------------------------------------------------------------------------- +// Helpers for compression routines. +//----------------------------------------------------------------------------- +// This class allows variable-length compression of DWORDs. +// +// A value can be stored using one or more nibbles. 3 bits of a nibble are used +// to store 3 bits of the value, and the top bit indicates if the following nibble +// contains rest of the value. If the top bit is not set, then this +// nibble is the last part of the value. +// The higher bits of the value are written out first, and the lowest 3 bits +// are written out last. +// +// In the encoded stream of bytes, the lower nibble of a byte is used before +// the high nibble. +// +// A binary value ABCDEFGHI (where A is the highest bit) is encoded as +// the follow two bytes : 1DEF1ABC XXXX0GHI +// +// Examples : +// 0 => X0 +// 1 => X1 +// +// 7 => X7 +// 8 => 09 +// 9 => 19 +// +// 0x3F (63) => 7F +// 0x40 (64) => F9 X0 +// 0x41 (65) => F9 X1 +// +// 0x1FF (511) => FF X7 +// 0x200 (512) => 89 08 +// 0x201 (513) => 89 18 + +class NibbleWriter +{ +public: + NibbleWriter() + { + LIMITED_METHOD_CONTRACT; + + m_fPending = false; + } + + void Flush() + { + if (m_fPending) + m_SigBuilder.AppendByte(m_PendingNibble); + } + + PVOID GetBlob(DWORD * pdwLength) + { + return m_SigBuilder.GetSignature(pdwLength); + } + + DWORD GetBlobLength() + { + return m_SigBuilder.GetSignatureLength(); + } + +//............................................................................. +// Writer methods +//............................................................................. + + + // Write a single nibble to the stream. + void WriteNibble(NIBBLE i) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + _ASSERTE(i <= 0xF); + + if (m_fPending) + { + // Use the high nibble after the low nibble is used + m_SigBuilder.AppendByte(m_PendingNibble | (i << 4)); + m_fPending = false; + } + else + { + // Use the low nibble first + m_PendingNibble = i; + m_fPending = true; + } + } + + // Write an unsigned int via variable length nibble encoding. + // We use the bit scheme: + // 0ABC (if 0 <= dw <= 0x7) + // 1ABC 0DEF (if 0 <= dw <= 0x7f) + // 1ABC 1DEF 0GHI (if 0 <= dw <= 0x7FF) + // etc.. + + void WriteEncodedU32(DWORD dw) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + // Fast path for common small inputs + if (dw <= 63) + { + if (dw > 7) + { + WriteNibble((NIBBLE) ((dw >> 3) | 8)); + } + + WriteNibble((NIBBLE) (dw & 7)); + return; + } + + // Note we must write this out with the low terminating nibble (0ABC) last b/c the + // reader gets nibbles in the same order we write them. + int i = 0; + while ((dw >> i) > 7) + { + i+= 3; + } + while(i > 0) + { + WriteNibble((NIBBLE) ((dw >> i) & 0x7) | 0x8); + i -= 3; + } + WriteNibble((NIBBLE) dw & 0x7); + } + + // Write a signed 32 bit value. + void WriteEncodedI32(int x) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + DWORD dw = (x < 0) ? (((-x) << 1) + 1) : (x << 1); + WriteEncodedU32(dw); + }; + +protected: + NIBBLE m_PendingNibble; // Pending value, not yet written out. + bool m_fPending; + + // SigBuilder is a convenient helper class for writing out small blobs + SigBuilder m_SigBuilder; +}; + +//----------------------------------------------------------------------------- + +class NibbleReader +{ +public: + NibbleReader(PTR_BYTE pBuffer, size_t size) + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + _ASSERTE(pBuffer != NULL); + + m_pBuffer = pBuffer; + m_cBytes = size; + m_cNibble = 0; + } + + // Get the index of the next Byte. + // This tells us how many bytes (rounding up to whole bytes) have been read. + // This is can be used to extract raw byte data that may be embedded on a byte boundary in the nibble stream. + size_t GetNextByteIndex() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_cNibble + 1) / 2; + } + + NIBBLE ReadNibble() + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + NIBBLE i = 0; + // Bufer should have been allocated large enough to hold data. + if (!(m_cNibble / 2 < m_cBytes)) + { + // We should never get here in a normal retail scenario. + // We could wind up here if somebody provided us invalid data (maybe by corrupting an ngenned image). + EX_THROW(HRException, (E_INVALIDARG)); + } + + BYTE p = m_pBuffer[m_cNibble / 2]; + if ((m_cNibble & 1) == 0) + { + // Read the low nibble first + i = (NIBBLE) (p & 0xF); + } + else + { + // Read the high nibble after the low nibble has been read + i = (NIBBLE) (p >> 4) & 0xF; + } + m_cNibble++; + + return i; + } + + // Read an unsigned int that was encoded via variable length nibble encoding + // from NibbleWriter::WriteEncodedU32. + DWORD ReadEncodedU32() + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + DWORD dw =0; + +#if defined(_DEBUG) || defined(DACCESS_COMPILE) + int dwCount = 0; +#endif + + // The encoding is variably lengthed, with the high-bit of every nibble indicating whether + // there is another nibble in the value. Each nibble contributes 3 bits to the value. + NIBBLE n; + do + { +#if defined(_DEBUG) || defined(DACCESS_COMPILE) + // If we've already read 11 nibbles (with 3 bits of usable data each), then we + // should be done reading a 32-bit integer. + // Avoid working with corrupted data and potentially long loops by failing + if(dwCount > 11) + { + _ASSERTE_MSG(false, "Corrupt nibble stream - value exceeded 32-bits in size"); +#ifdef DACCESS_COMPILE + DacError(CORDBG_E_TARGET_INCONSISTENT); +#endif + } + dwCount++; +#endif + + n = ReadNibble(); + dw = (dw << 3) + (n & 0x7); + } while((n & 0x8) > 0); + + return dw; + } + + int ReadEncodedI32() + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + DWORD dw = ReadEncodedU32(); + int x = dw >> 1; + return (dw & 1) ? (-x) : (x); + } + +protected: + PTR_BYTE m_pBuffer; + size_t m_cBytes; // size of buffer. + size_t m_cNibble; // Which nibble are we at? +}; + + + +#endif // _NIBBLESTREAM_H_ diff --git a/lib/coreclr/src/inc/nsutilpriv.h b/lib/coreclr/src/inc/nsutilpriv.h new file mode 100644 index 0000000000..ede064c6f8 --- /dev/null +++ b/lib/coreclr/src/inc/nsutilpriv.h @@ -0,0 +1,266 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// NSUtilPriv.h +// +// Helpers for converting namespace separators. +// +//***************************************************************************** + +#ifndef __NSUTILPRIV_H__ +#define __NSUTILPRIV_H__ + +template class CQuickArray; +class SString; + +struct ns +{ + +//***************************************************************************** +// Determine how many chars large a fully qualified name would be given the +// two parts of the name. The return value includes room for every character +// in both names, as well as room for the separator and a final terminator. +//***************************************************************************** +static +int GetFullLength( // Number of chars in full name. + const WCHAR *szNameSpace, // Namspace for value. + const WCHAR *szName); // Name of value. + +static +int GetFullLength( // Number of chars in full name. + LPCUTF8 szNameSpace, // Namspace for value. + LPCUTF8 szName); // Name of value. + +//***************************************************************************** +// Scan the given string to see if the name contains any invalid characters +// that are not allowed. +//***************************************************************************** +static +int IsValidName( // true if valid, false invalid. + const WCHAR *szName); // Name to parse. + +static +int IsValidName( // true if valid, false invalid. + LPCUTF8 szName); // Name to parse. + + +//***************************************************************************** +// Scan the string from the rear looking for the first valid separator. If +// found, return a pointer to it. Else return null. This code is smart enough +// to skip over special sequences, such as: +// a.b..ctor +// ^ +// | +// The ".ctor" is considered one token. +//***************************************************************************** +static +WCHAR *FindSep( // Pointer to separator or null. + const WCHAR *szPath); // The path to look in. + +static +LPUTF8 FindSep( // Pointer to separator or null. + LPCUTF8 szPath); // The path to look in. + + +//***************************************************************************** +// Take a path and find the last separator (nsFindSep), and then replace the +// separator with a '\0' and return a pointer to the name. So for example: +// a.b.c +// becomes two strings "a.b" and "c" and the return value points to "c". +//***************************************************************************** +static +WCHAR *SplitInline( // Pointer to name portion. + __inout __inout_z WCHAR *szPath); // The path to split. + +static +LPUTF8 SplitInline( // Pointer to name portion. + __inout __inout_z LPUTF8 szPath); // The path to split. + +static +void SplitInline( + __inout __inout_z LPWSTR szPath, // Path to split. + LPCWSTR &szNameSpace, // Return pointer to namespace. + LPCWSTR &szName); // Return pointer to name. + +static +void SplitInline( + __inout __inout_z LPUTF8 szPath, // Path to split. + LPCUTF8 &szNameSpace, // Return pointer to namespace. + LPCUTF8 &szName); // Return pointer to name. + + +//***************************************************************************** +// Split the last parsable element from the end of the string as the name, +// the first part as the namespace. +//***************************************************************************** +static +int SplitPath( // true ok, false trunction. + const WCHAR *szPath, // Path to split. + __out_ecount_opt (cchNameSpace) WCHAR *szNameSpace, // Output for namespace value. + int cchNameSpace, // Max chars for output. + __out_ecount_opt (cchName) WCHAR *szName, // Output for name. + int cchName); // Max chars for output. + +static +int SplitPath( // true ok, false trunction. + LPCUTF8 szPath, // Path to split. + __out_ecount_opt (cchNameSpace) LPUTF8 szNameSpace, // Output for namespace value. + int cchNameSpace, // Max chars for output. + __out_ecount_opt (cchName) LPUTF8 szName, // Output for name. + int cchName); // Max chars for output. + + +//***************************************************************************** +// Take two values and put them together in a fully qualified path using the +// correct separator. +//***************************************************************************** +static +int MakePath( // true ok, false truncation. + __out_ecount(cchChars) WCHAR *szOut, // output path for name. + int cchChars, // max chars for output path. + const WCHAR *szNameSpace, // Namespace. + const WCHAR *szName); // Name. + +static +int MakePath( // true ok, false truncation. + __out_ecount(cchChars) LPUTF8 szOut, // output path for name. + int cchChars, // max chars for output path. + LPCUTF8 szNameSpace, // Namespace. + LPCUTF8 szName); // Name. + +static +int MakePath( // true ok, false truncation. + __out_ecount(cchChars) WCHAR *szOut, // output path for name. + int cchChars, // max chars for output path. + LPCUTF8 szNameSpace, // Namespace. + LPCUTF8 szName); // Name. + +static +int MakePath( // true ok, false out of memory + CQuickBytes &qb, // Where to put results. + LPCUTF8 szNameSpace, // Namespace for name. + LPCUTF8 szName); // Final part of name. + +static +int MakePath( // true ok, false out of memory + CQuickArray &qa, // Where to put results. + LPCUTF8 szNameSpace, // Namespace for name. + LPCUTF8 szName); // Final part of name. + +static +int MakePath( // true ok, false out of memory + CQuickBytes &qb, // Where to put results. + const WCHAR *szNameSpace, // Namespace for name. + const WCHAR *szName); // Final part of name. + +static +void MakePath( // throws on out of memory + SString &ssBuf, // Where to put results. + const SString &ssNameSpace, // Namespace for name. + const SString &ssName); // Final part of name. + +//***************************************************************************** +// Concatinate type names to assembly names +//***************************************************************************** +static +bool MakeAssemblyQualifiedName( // true if ok, false if out of memory + CQuickBytes &qb, // location to put result + const WCHAR *szTypeName, // Type name + const WCHAR *szAssemblyName); // Assembly Name + +static +bool MakeAssemblyQualifiedName( // true ok, false truncation + __out_ecount (dwBuffer) WCHAR* pBuffer, // Buffer to recieve the results + int dwBuffer, // Number of characters total in buffer + const WCHAR *szTypeName, // Namespace for name. + int dwTypeName, // Number of characters (not including null) + const WCHAR *szAssemblyName, // Final part of name. + int dwAssemblyName); // Number of characters (not including null) + +static +int MakeNestedTypeName( // true ok, false out of memory + CQuickBytes &qb, // Where to put results. + LPCUTF8 szEnclosingName, // Full name for enclosing type + LPCUTF8 szNestedName); // Full name for nested type + +static +int MakeNestedTypeName( // true ok, false truncation. + __out_ecount (cchChars) LPUTF8 szOut, // output path for name. + int cchChars, // max chars for output path. + LPCUTF8 szEnclosingName, // Full name for enclosing type + LPCUTF8 szNestedName); // Full name for nested type + +static +void MakeNestedTypeName( // throws on out of memory + SString &ssBuf, // output path for name. + const SString &ssEnclosingName, // Full name for enclosing type + const SString &ssNestedName); // Full name for nested type +}; // struct ns + +#ifndef NAMESPACE_SEPARATOR_CHAR +#define NAMESPACE_SEPARATOR_CHAR '.' +#define NAMESPACE_SEPARATOR_WCHAR W('.') +#define NAMESPACE_SEPARATOR_STR "." +#define NAMESPACE_SEPARATOR_WSTR W(".") +#define NAMESPACE_SEPARATOR_LEN 1 +#define ASSEMBLY_SEPARATOR_CHAR ',' +#define ASSEMBLY_SEPARATOR_WCHAR W(',') +#define ASSEMBLY_SEPARATOR_STR ", " +#define ASSEMBLY_SEPARATOR_WSTR W(", ") +#define ASSEMBLY_SEPARATOR_LEN 2 +#define BACKSLASH_CHAR '\\' +#define BACKSLASH_WCHAR W('\\') +#define NESTED_SEPARATOR_CHAR '+' +#define NESTED_SEPARATOR_WCHAR W('+') +#define NESTED_SEPARATOR_STR "+" +#define NESTED_SEPARATOR_WSTR W("+") +#endif + +#define EMPTY_STR "" +#define EMPTY_WSTR W("") + +#define MAKE_FULL_PATH_ON_STACK_UTF8(toptr, pnamespace, pname) \ +{ \ + int __i##toptr = ns::GetFullLength(pnamespace, pname); \ + toptr = (char *) alloca(__i##toptr); \ + ns::MakePath(toptr, __i##toptr, pnamespace, pname); \ +} + +#define MAKE_FULL_PATH_ON_STACK_UNICODE(toptr, pnamespace, pname) \ +{ \ + int __i##toptr = ns::GetFullLength(pnamespace, pname); \ + toptr = (WCHAR *) alloca(__i##toptr * sizeof(WCHAR)); \ + ns::MakePath(toptr, __i##toptr, pnamespace, pname); \ +} + +#define MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszNameSpace, pszName) MAKE_FULL_PATH_ON_STACK_UTF8(pszFullyQualifiedName, pszNameSpace, pszName) + +#define MAKE_FULLY_QUALIFIED_MEMBER_NAME(ptr, pszNameSpace, pszClassName, pszMemberName, pszSig) \ +{ \ + int __i##ptr = ns::GetFullLength(pszNameSpace, pszClassName); \ + __i##ptr += (pszMemberName ? (int) strlen(pszMemberName) : 0); \ + __i##ptr += (NAMESPACE_SEPARATOR_LEN * 2); \ + __i##ptr += (pszSig ? (int) strlen(pszSig) : 0); \ + ptr = (LPUTF8) alloca(__i##ptr); \ + ns::MakePath(ptr, __i##ptr, pszNameSpace, pszClassName); \ + if (pszMemberName) { \ + strcat_s(ptr, __i##ptr, NAMESPACE_SEPARATOR_STR); \ + strcat_s(ptr, __i##ptr, pszMemberName); \ + } \ + if (pszSig) { \ + if (! pszMemberName) \ + strcat_s(ptr, __i##ptr, NAMESPACE_SEPARATOR_STR); \ + strcat_s(ptr, __i##ptr, pszSig); \ + } \ +} + +#ifdef _PREFAST_ +// need to eliminate the expansion of MAKE_FULLY_QUALIFIED_MEMBER_NAME in prefast +// builds to prevent it complaining about the potential for NULLs to strlen and strcat +#undef MAKE_FULLY_QUALIFIED_MEMBER_NAME +// need to set ptr=NULL so we don't get a build error because ptr isn't inited in a couple cases +#define MAKE_FULLY_QUALIFIED_MEMBER_NAME(ptr, pszNameSpace, pszClassName, pszMemberName, pszSig) ptr=NULL; +#endif + +#endif diff --git a/lib/coreclr/src/inc/opcode.def b/lib/coreclr/src/inc/opcode.def new file mode 100644 index 0000000000..9d495c2895 --- /dev/null +++ b/lib/coreclr/src/inc/opcode.def @@ -0,0 +1,359 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/***************************************************************************** + ** ** + ** Opcode.def - COM+ Intrinsic Opcodes and Macros. ** + ** ** + ** This is the master table from which all opcode lists ** + ** are derived. New instructions must be added to this ** + ** table and generators run to produce the lookup tables ** + ** used by the interpreter loop. ** + ** ** + ** Stack Behaviour is describing the number of 4 byte ** + ** slots pushed and Poped. ** + ** ** + *****************************************************************************/ + + +#ifndef __OPCODE_DEF_ +#define __OPCODE_DEF_ + +#define MOOT 0x00 // Marks unused second byte when encoding single +#define STP1 0xFE // Prefix code 1 for Standard Map +#define REFPRE 0xFF // Prefix for Reference Code Encoding +#define RESERVED_PREFIX_START 0xF7 + +#endif + +// If the first byte of the standard encoding is 0xFF, then +// the second byte can be used as 1 byte encoding. Otherwise l b b +// the encoding is two bytes. e y y +// n t t +// g e e +// (unused) t +// Canonical Name String Name Stack Behaviour Operand Params Opcode Kind h 1 2 Control Flow +// ------------------------------------------------------------------------------------------------------------------------------------------------------- +OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) +OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) +OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) +OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) +OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) +OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) +OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) +OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) +OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) +OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) +OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) +OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) +OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) +OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) +OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) +OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) +OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) +OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) +OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) +OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) +OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) +OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) +OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) +OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) +OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) +OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) +OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) +OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) +OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) +OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) +OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) +OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) +OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) +OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) +OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) +OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) +OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) +OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) +OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) +OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) +OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) +OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) +OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) +OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) +OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) +OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) +OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) +OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) +OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) +OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) +OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) +OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) +OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) +OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) +OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) +OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) +OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) +OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) +OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) +OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) +OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) +OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) +OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) +OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) +OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) +OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) +OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) +OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) +OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) +OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) +OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) +OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) +OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) +OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) +OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) +OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) +OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) +OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) +OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) +OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) +OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) +OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) +OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) +OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) +OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) +OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) +OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) +OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) +OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) +OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) +OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) +OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) +OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) +OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) +OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) +OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) +OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) +OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) +OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) +OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) +OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) +OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) +OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) +OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) +OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) +OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) +OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) +OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) +OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) +OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) +OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) +OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) +OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) +OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) +OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) +OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) +OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) +OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) +OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) +OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) +OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) +OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) +OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) +OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) +OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) +OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) +OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) +OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) +OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) +OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) +OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) +OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) +OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) +OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) +OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) +OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) +OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) +OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) +OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) +OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) +OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) +OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) +OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) +OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) +OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) +OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) +OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) +OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) +OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) +OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) +OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) +OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) +OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) +OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) +OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) +OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) +OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) +OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) +OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) +OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) +OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) +OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) +OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) +OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) +OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) +OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) +OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) +OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) +OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) +OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) +OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) +OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) +OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) +OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) +OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) +OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) +OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) +OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) +OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) +OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) +OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) +OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) +OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) +OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) +OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) +OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) +OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) +OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) +OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) +OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) +OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) +OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) +OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) +OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) +OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) +OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) +OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) +OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) +OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) +OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) +OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) +OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) +OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) +OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) +OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) +OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) +OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) +OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) +OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) +OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) +OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) +OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) +OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) +OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) +OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) +OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) +OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) +OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) +OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) +OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) +OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) +OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) +OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) +OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) +OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) +OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) +OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) +OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) +OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) +OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) +OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) +OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) +OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) +OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) +OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) +OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) +OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) +OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) +OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) +OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) +OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) +OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) +OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) +OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) +OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) +OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) +OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) +OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) +OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) +OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) +OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) +OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) +OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) +OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) +OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) +OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) + +OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) +OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) +OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) +OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) +OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) +OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) +OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) +OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) +OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) +OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) +OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) +OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) +OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) +OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) +OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) +OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) +OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) +OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) +OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) +OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) +OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) +OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) +OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) +OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) +OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) +OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) +OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) +OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) +OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) +OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) +OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) +OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) +OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) +OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) +OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) + +// These are not real opcodes, but they are handy internally in the EE + +OPDEF(CEE_ILLEGAL, "illegal", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) +OPDEF(CEE_MACRO_END, "endmac", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) +OPDEF(CEE_CODE_LABEL, "codelabel", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) + +#ifndef OPALIAS +#define _OPALIAS_DEFINED_ +#define OPALIAS(canonicalName, stringName, realOpcode) +#endif + +OPALIAS(CEE_BRNULL, "brnull", CEE_BRFALSE) +OPALIAS(CEE_BRNULL_S, "brnull.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRZERO, "brzero", CEE_BRFALSE) +OPALIAS(CEE_BRZERO_S, "brzero.s", CEE_BRFALSE_S) +OPALIAS(CEE_BRINST, "brinst", CEE_BRTRUE) +OPALIAS(CEE_BRINST_S, "brinst.s", CEE_BRTRUE_S) +OPALIAS(CEE_LDIND_U8, "ldind.u8", CEE_LDIND_I8) +OPALIAS(CEE_LDELEM_U8, "ldelem.u8", CEE_LDELEM_I8) +OPALIAS(CEE_LDELEM_ANY, "ldelem.any", CEE_LDELEM) +OPALIAS(CEE_STELEM_ANY, "stelem.any", CEE_STELEM) +OPALIAS(CEE_LDC_I4_M1x, "ldc.i4.M1", CEE_LDC_I4_M1) +OPALIAS(CEE_ENDFAULT, "endfault", CEE_ENDFINALLY) + +#ifdef _OPALIAS_DEFINED_ +#undef OPALIAS +#undef _OPALIAS_DEFINED_ +#endif + diff --git a/lib/coreclr/src/inc/openum.h b/lib/coreclr/src/inc/openum.h new file mode 100644 index 0000000000..f71e411ddc --- /dev/null +++ b/lib/coreclr/src/inc/openum.h @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __openum_h__ +#define __openum_h__ + + +typedef enum opcode_t +{ +#define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) c, +#include "opcode.def" +#undef OPDEF + CEE_COUNT, /* number of instructions and macros pre-defined */ +} OPCODE; + + +typedef enum opcode_format_t +{ + InlineNone = 0, // no inline args + InlineVar = 1, // local variable (U2 (U1 if Short on)) + InlineI = 2, // an signed integer (I4 (I1 if Short on)) + InlineR = 3, // a real number (R8 (R4 if Short on)) + InlineBrTarget = 4, // branch target (I4 (I1 if Short on)) + InlineI8 = 5, + InlineMethod = 6, // method token (U4) + InlineField = 7, // field token (U4) + InlineType = 8, // type token (U4) + InlineString = 9, // string TOKEN (U4) + InlineSig = 10, // signature tok (U4) + InlineRVA = 11, // ldptr token (U4) + InlineTok = 12, // a meta-data token of unknown type (U4) + InlineSwitch = 13, // count (U4), pcrel1 (U4) .... pcrelN (U4) + InlinePhi = 14, // count (U1), var1 (U2) ... varN (U2) + + // WATCH OUT we are close to the limit here, if you add + // more enumerations you need to change ShortIline definition below + + // The extended enumeration also encodes the size in the IL stream + ShortInline = 16, // if this bit is set, the format is the 'short' format + PrimaryMask = (ShortInline-1), // mask these off to get primary enumeration above + ShortInlineVar = (ShortInline + InlineVar), + ShortInlineI = (ShortInline + InlineI), + ShortInlineR = (ShortInline + InlineR), + ShortInlineBrTarget = (ShortInline + InlineBrTarget), + InlineOpcode = (ShortInline + InlineNone), // This is only used internally. It means the 'opcode' is two byte instead of 1 +} OPCODE_FORMAT; + +#endif /* __openum_h__ */ + + diff --git a/lib/coreclr/src/inc/opinfo.h b/lib/coreclr/src/inc/opinfo.h new file mode 100644 index 0000000000..d98c006ecd --- /dev/null +++ b/lib/coreclr/src/inc/opinfo.h @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/***************************************************************************/ +/* OpInfo.h */ +/***************************************************************************/ + +/* contains OpInfo, a wrapper that allows you to get useful information + about IL opcodes, and how to decode them */ + +/***************************************************************************/ + +#ifndef OpInfo_h +#define OpInfo_h + +#include "openum.h" + + // Decribes the flow of control properties of the instruction +enum OpFlow { + FLOW_META, // not a real instuction + FLOW_CALL, // a call instruction + FLOW_BRANCH, // unconditional branch, does not fall through + FLOW_COND_BRANCH, // may fall through + FLOW_PHI, + FLOW_THROW, + FLOW_BREAK, + FLOW_RETURN, + FLOW_NEXT, // flows into next instruction (none of the above) +}; + + // These are all the possible arguments for the instruction +/****************************************************************************/ +union OpArgsVal { + __int32 i; + __int64 i8; + double r; + struct { + unsigned count; + int* targets; // targets are pcrelative displacements (little-endian) + } switch_; + struct { + unsigned count; + unsigned short* vars; + } phi; +}; + +/***************************************************************************/ + + // OpInfo parses a il instrution into an opcode, and a arg and updates the IP +class OpInfo { +public: + OpInfo() { data = 0; } + OpInfo(OPCODE opCode) { _ASSERTE(opCode < CEE_COUNT); data = &table[opCode]; } + + // fetch instruction at 'instrPtr, fills in 'args' returns pointer + // to next instruction + const unsigned char* fetch(const unsigned char* instrPtr, OpArgsVal* args); + + const char* getName() { return(data->name); } + OPCODE_FORMAT getArgsInfo() { return(OPCODE_FORMAT(data->format & PrimaryMask)); } + OpFlow getFlow() { return(data->flow); } + OPCODE getOpcode() { return((OPCODE) (data-table)); } + int getNumPop() { return(data->numPop); } + int getNumPush() { return(data->numPush); } + +private: + struct OpInfoData { + const char* name; + OPCODE_FORMAT format : 8; + OpFlow flow : 8; + int numPop : 3; // < 0 means depends on instr args + int numPush : 3; // < 0 means depends on instr args + OPCODE opcode : 10; // This is the same as the index into the table + }; + + static OpInfoData table[]; +private: + OpInfoData* data; +}; + +#endif diff --git a/lib/coreclr/src/inc/optdefault.h b/lib/coreclr/src/inc/optdefault.h new file mode 100644 index 0000000000..dd0bd44c04 --- /dev/null +++ b/lib/coreclr/src/inc/optdefault.h @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Revert optimizations back to default +// +#undef FPO_ON + +#ifdef _MSC_VER +#pragma optimize("",on) +#endif diff --git a/lib/coreclr/src/inc/optsmallperfcritical.h b/lib/coreclr/src/inc/optsmallperfcritical.h new file mode 100644 index 0000000000..68c80884e3 --- /dev/null +++ b/lib/coreclr/src/inc/optsmallperfcritical.h @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Set optimizations settings for small performance critical methods +// + +#ifdef FPO_ON +#error Recursive use of FPO_ON not supported +#endif + +#define FPO_ON 1 + + +#if defined(_MSC_VER) && !defined(_DEBUG) + #pragma optimize("t", on) // optimize for speed + #if !defined(_AMD64_) // 'y' isn't an option on amd64 + #pragma optimize("y", on) // omit frame pointer + #endif // !defined(_TARGET_AMD64_) +#endif diff --git a/lib/coreclr/src/inc/ostype.h b/lib/coreclr/src/inc/ostype.h new file mode 100644 index 0000000000..b64927c608 --- /dev/null +++ b/lib/coreclr/src/inc/ostype.h @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#include "staticcontract.h" + +#ifndef WRAPPER_NO_CONTRACT +#define WRAPPER_NO_CONTRACT ANNOTATION_WRAPPER +#endif + +#ifndef LIMITED_METHOD_CONTRACT +#define LIMITED_METHOD_CONTRACT ANNOTATION_FN_LEAF +#endif + +//***************************************************************************** +// Enum to track which version of the OS we are running +// Note that NT5 (Win2k) is the minimum supported platform. Any code using +// utilcode (which includes the CLR's execution engine) will fail to start +// on a pre-Win2k platform. This is enforced by InitRunningOnVersionStatus. +// +// Note: The value is used for data mining from links clicked by user in shim dialog - see code:FWLinkTemplateFromTextID +// Please do not modify existing values, adding new ones is fine. +//***************************************************************************** +typedef enum { + RUNNING_ON_STATUS_UNINITED = 0, + RUNNING_ON_WIN7 = 1, + RUNNING_ON_WIN8 = 2 +} RunningOnStatusEnum; + +extern RunningOnStatusEnum gRunningOnStatus; + +void InitRunningOnVersionStatus(); + +#if defined(FEATURE_COMINTEROP) && !defined(FEATURE_CORESYSTEM) +typedef enum +{ + WINRT_STATUS_UNINITED = 0, + WINRT_STATUS_UNSUPPORTED, + WINRT_STATUS_SUPPORTED +} +WinRTStatusEnum; + +extern WinRTStatusEnum gWinRTStatus; + +void InitWinRTStatus(); +#endif // FEATURE_COMINTEROP && !FEATURE_CORESYSTEM + +//***************************************************************************** +// Returns true if you are running on Windows 8 or newer. +//***************************************************************************** +inline BOOL RunningOnWin8() +{ + WRAPPER_NO_CONTRACT; +#if (!defined(_X86_) && !defined(_AMD64_)) || defined(CROSSGEN_COMPILE) + return TRUE; +#else + if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED) + { + InitRunningOnVersionStatus(); + } + + return (gRunningOnStatus >= RUNNING_ON_WIN8) ? TRUE : FALSE; +#endif +} + +#ifdef FEATURE_COMINTEROP + +#ifdef FEATURE_CORESYSTEM + +inline BOOL WinRTSupported() +{ + return RunningOnWin8(); +} +#else +inline BOOL WinRTSupported() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + +#ifdef CROSSGEN_COMPILE + return TRUE; +#endif + + if (gWinRTStatus == WINRT_STATUS_UNINITED) + { + InitWinRTStatus(); + } + + return gWinRTStatus == WINRT_STATUS_SUPPORTED; +} +#endif // FEATURE_CORESYSTEM + +#endif // FEATURE_COMINTEROP + +#ifdef _WIN64 +inline BOOL RunningInWow64() +{ + return FALSE; +} +#else +BOOL RunningInWow64(); +#endif diff --git a/lib/coreclr/src/inc/outstring.h b/lib/coreclr/src/inc/outstring.h new file mode 100644 index 0000000000..167ef9ad15 --- /dev/null +++ b/lib/coreclr/src/inc/outstring.h @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*****************************************************************/ +/* OutString.h */ +/*****************************************************************/ +/* A simple, lightweight, character output stream, with very few + external dependancies (like sprintf ... ) */ + +/* + Date : 2/1/99 */ +/*****************************************************************/ + +#ifndef _OutString_h +#define _OutString_h 1 + +#include "utilcode.h" // for overloaded new +#include // for strlen, strcpy + +/*****************************************************************/ + // a light weight character 'output' stream +class OutString { +public: + enum FormatFlags { // used to control printing of numbers + none = 0, + put0x = 1, // put leading 0x on hexidecimal + zeroFill = 2, // zero fill (instead of space fill) + }; + + OutString() : start(0), end(0), cur(0) {} + + OutString(unsigned initialAlloc) { + cur = start = new char[initialAlloc+1]; // for null termination + end = &start[initialAlloc]; + } + + ~OutString() { delete [] start; } + + // shortcut for printing decimal + OutString& operator<<(int i) { return(dec(i)); } + + OutString& operator<<(double d); + + // FIX make this really unsigned + OutString& operator<<(unsigned i) { return(dec(i)); } + + // prints out the hexidecimal representation + OutString& dec(int i, size_t minWidth = 0); + + // prints out the hexidecimal representation + OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none); + + OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none); + + OutString& hex(int i, int minWidth = 0, unsigned flags = none) { + return hex(unsigned(i), minWidth, flags); + } + + OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) { + return hex((unsigned __int64) i, minWidth, flags); + } + + // print out 'count' instances of the character 'c' + OutString& pad(size_t count, char c); + + OutString& operator<<(char c) { + if (cur >= end) + Realloc(1); + *cur++ = c; + _ASSERTE(start <= cur && cur <= end); + return(*this); + } + + OutString& operator<<(const wchar_t* str) { + size_t len = wcslen(str); + if (cur+len > end) + Realloc(len); + while(str != 0) + *cur++ = (char) *str++; + _ASSERTE(start <= cur && cur <= end); + return(*this); + } + + OutString& prepend(const char c) { + char buff[2]; buff[0] = c; buff[1] = 0; + return(prepend(buff)); + } + + OutString& prepend(const char* str) { + size_t len = strlen(str); + if (cur+len > end) + Realloc(len); + memmove(start+len, start, cur-start); + memcpy(start, str, len); + cur = cur + len; + _ASSERTE(start <= cur && cur <= end); + return(*this); + } + + OutString& operator=(const OutString& str) { + clear(); + *this << str; + return(*this); + } + + OutString& operator<<(const OutString& str) { + write(str.start, str.cur-str.start); + return(*this); + } + + OutString& operator<<(const char* str) { + write(str, strlen(str)); + return(*this); + } + + void write(const char* str, size_t len) { + if (cur+len > end) + Realloc(len); + memcpy(cur, str, len); + cur = cur + len; + _ASSERTE(start <= cur && cur <= end); + } + + void swap(OutString& str) { + char* tmp = start; + start = str.start; + str.start = tmp; + tmp = end; + end = str.end; + str.end = tmp; + tmp = cur; + cur = str.cur; + str.cur = tmp; + _ASSERTE(start <= cur && cur <= end); + } + + void clear() { cur = start; } + size_t length() const { return(cur-start); } + + // return the null terminated string, OutString keeps ownership + const char* val() const { *cur = 0; return(start); } + + // grab string (caller must now delete) OutString is cleared + char* grab() { char* ret = start; *cur = 0; end = cur = start = 0; return(ret); } + +private: + void Realloc(size_t neededSpace); + + char *start; // start of the buffer + char *end; // points at the last place null terminator can go + char *cur; // points at a null terminator +}; + +#endif // _OutString_h + diff --git a/lib/coreclr/src/inc/palclr.h b/lib/coreclr/src/inc/palclr.h new file mode 100644 index 0000000000..3b42ac5dae --- /dev/null +++ b/lib/coreclr/src/inc/palclr.h @@ -0,0 +1,631 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: palclr.h +// +// Various macros and constants that are necessary to make the CLR portable. +// + +// =========================================================================== + + +#if !defined(FEATURE_PAL) + +#ifndef __PALCLR_H__ +#define __PALCLR_H__ + +// This macro is used to standardize the wide character string literals between UNIX and Windows. +// Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size +// of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined +// as u"" (char16_t) +#ifdef PLATFORM_UNIX +#define W(str) u##str +#else // PLATFORM_UNIX +#define W(str) L##str +#endif // PLATFORM_UNIX + +#include + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +#if __GNUC__ +#ifndef __cdecl +#define __cdecl __attribute__((__cdecl__)) +#endif +#endif + +#ifndef NOTHROW_DECL +#ifdef _MSC_VER +#define NOTHROW_DECL __declspec(nothrow) +#else +#define NOTHROW_DECL __attribute__((nothrow)) +#endif // !_MSC_VER +#endif // !NOTHROW_DECL + +#ifndef NOINLINE +#ifdef _MSC_VER +#define NOINLINE __declspec(noinline) +#else +#define NOINLINE __attribute__((noinline)) +#endif // !_MSC_VER +#endif // !NOINLINE + +#define ANALYZER_NORETURN + +// +// CPP_ASSERT() can be used within a class definition, to perform a +// compile-time assertion involving private names within the class. +// +// MS compiler doesn't allow redefinition of the typedef within a template. +// gcc doesn't allow redefinition of the typedef within a class, though +// it does at file scope. +#define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; + + +// PORTABILITY_ASSERT and PORTABILITY_WARNING macros are meant to be used to +// mark places in the code that needs attention for portability. The usual +// usage pattern is: +// +// int get_scratch_register() { +// #if defined(_TARGET_X86_) +// return eax; +// #elif defined(_TARGET_AMD64_) +// return rax; +// #elif defined(_TARGET_ARM_) +// return r0; +// #else +// PORTABILITY_ASSERT("scratch register"); +// return 0; +// #endif +// } +// +// PORTABILITY_ASSERT is meant to be used inside functions/methods. It can +// introduce compile-time and/or run-time errors. +// PORTABILITY_WARNING is meant to be used outside functions/methods. It can +// introduce compile-time errors or warnings only. +// +// People starting new ports will first define these to just cause run-time +// errors. Once they fix all the places that need attention for portability, +// they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause +// compile-time errors to make sure that they haven't missed anything. +// +// If it is reasonably possible all codepaths containing PORTABILITY_ASSERT +// should be compilable (e.g. functions should return NULL or something if +// they are expected to return a value). +// +// The message in these two macros should not contain any keywords like TODO +// or NYI. It should be just the brief description of the problem. + +#if defined(_TARGET_X86_) +// Finished ports - compile-time errors +#define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) +#define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) +#else +// Ports in progress - run-time asserts only +#define PORTABILITY_WARNING(message) +#define PORTABILITY_ASSERT(message) _ASSERTE(false && message) +#endif + +#define DIRECTORY_SEPARATOR_CHAR_A '\\' +#define DIRECTORY_SEPARATOR_STR_A "\\" +#define DIRECTORY_SEPARATOR_CHAR_W W('\\') +#define DIRECTORY_SEPARATOR_STR_W W("\\") + +#define PATH_SEPARATOR_CHAR_W W(';') +#define PATH_SEPARATOR_STR_W W(";") + +#define VOLUME_SEPARATOR_CHAR_W W(':') + +// PAL Macros +// Not all compilers support fully anonymous aggregate types, so the +// PAL provides names for those types. To allow existing definitions of +// those types to continue to work, we provide macros that should be +// used to reference fields within those types. + +#ifndef DECIMAL_SCALE +#define DECIMAL_SCALE(dec) ((dec).scale) +#endif + +#ifndef DECIMAL_SIGN +#define DECIMAL_SIGN(dec) ((dec).sign) +#endif + +#ifndef DECIMAL_SIGNSCALE +#define DECIMAL_SIGNSCALE(dec) ((dec).signscale) +#endif + +#ifndef DECIMAL_LO32 +#define DECIMAL_LO32(dec) ((dec).Lo32) +#endif + +#ifndef DECIMAL_MID32 +#define DECIMAL_MID32(dec) ((dec).Mid32) +#endif + +#ifndef DECIMAL_HI32 +#define DECIMAL_HI32(dec) ((dec).Hi32) +#endif + +#ifndef DECIMAL_LO64_GET +#define DECIMAL_LO64_GET(dec) ((dec).Lo64) +#endif + +#ifndef DECIMAL_LO64_SET +#define DECIMAL_LO64_SET(dec,value) {(dec).Lo64 = value; } +#endif + +#ifndef IMAGE_RELOC_FIELD +#define IMAGE_RELOC_FIELD(img, f) ((img).f) +#endif + +#ifndef IMAGE_IMPORT_DESC_FIELD +#define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).f) +#endif + +#define IMAGE_RDE_ID(img) ((img)->Id) + +#define IMAGE_RDE_NAME(img) ((img)->Name) + +#define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData) + +#ifndef IMAGE_RDE_NAME_FIELD +#define IMAGE_RDE_NAME_FIELD(img, f) ((img)->f) +#endif + +#define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f) + +#ifndef IMAGE_FE64_FIELD +#define IMAGE_FE64_FIELD(img, f) ((img).f) +#endif + +#ifndef IMPORT_OBJ_HEADER_FIELD +#define IMPORT_OBJ_HEADER_FIELD(obj, f) ((obj).f) +#endif + +#ifndef IMAGE_COR20_HEADER_FIELD +#define IMAGE_COR20_HEADER_FIELD(obj, f) ((obj).f) +#endif + + +// PAL Numbers +// Used to ensure cross-compiler compatibility when declaring large +// integer constants. 64-bit integer constants should be wrapped in the +// declarations listed here. +// +// Each of the #defines here is wrapped to avoid conflicts with pal.h. + +#if defined(_MSC_VER) + +// MSVC's way of declaring large integer constants +// If you define these in one step, without the _HELPER macros, you +// get extra whitespace when composing these with other concatenating macros. +#ifndef I64 +#define I64_HELPER(x) x ## i64 +#define I64(x) I64_HELPER(x) +#endif + +#ifndef UI64 +#define UI64_HELPER(x) x ## ui64 +#define UI64(x) UI64_HELPER(x) +#endif + +#else + +// GCC's way of declaring large integer constants +// If you define these in one step, without the _HELPER macros, you +// get extra whitespace when composing these with other concatenating macros. +#ifndef I64 +#define I64_HELPER(x) x ## LL +#define I64(x) I64_HELPER(x) +#endif + +#ifndef UI64 +#define UI64_HELPER(x) x ## ULL +#define UI64(x) UI64_HELPER(x) +#endif + +#endif + + +// PAL SEH +// Macros for portable exception handling. The Win32 SEH is emulated using +// these macros and setjmp/longjmp on Unix +// +// Usage notes: +// +// - The filter has to be a function taking two parameters: +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// +// - It is not possible to directly use the local variables in the filter. +// All the local information that the filter has to need to know about should +// be passed through pv parameter +// +// - Do not use goto to jump out of the PAL_TRY block +// (jumping out of the try block is not a good idea even on Win32, because of +// it causes stack unwind) +// +// - It is not possible to directly use the local variables in the try block. +// All the local information that the filter has to need to know about should +// be passed through pv parameter +// +// +// Simple examples: +// +// struct Param { ... local variables used in try block and filter ... } param; +// PAL_TRY(Param *, pParam, ¶m) { // read as: Param *pParam = ¶m; +// .... +// } PAL_FINALLY { +// .... +// } +// PAL_ENDTRY +// +// +// struct Param { ... local variables used in try block and filter ... } param; +// PAL_TRY(Param *, pParam, ¶m) { +// .... +// } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { +// .... +// } +// PAL_ENDTRY +// +// +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// { +// ... +// } +// PAL_TRY(void *, unused, NULL) { +// .... +// } PAL_EXCEPT_FILTER(MyFilter) { +// .... +// } +// PAL_ENDTRY +// +// +// Complex example: +// +// struct MyParams +// { +// ... +// } params; +// +// PAL_TRY(MyParams *, pMyParamsOuter, ¶ms) { +// PAL_TRY(MyParams *, pMyParamsInnter, pMyParamsOuter) { +// ... +// if (error) goto Done; +// ... +// Done: ; +// } PAL_EXCEPT_FILTER(OtherFilter) { +// ... +// } +// PAL_ENDTRY +// } +// PAL_FINALLY { +// } +// PAL_ENDTRY +// + +#include "staticcontract.h" + +#define HardwareExceptionHolder + +// Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically +// when these macros are used from within the VM. +#define PAL_SEH_RESTORE_GUARD_PAGE + +#define PAL_TRY_NAKED \ + { \ + bool __exHandled; __exHandled = false; \ + DWORD __exCode; __exCode = 0; \ + SCAN_EHMARKER(); \ + __try \ + { \ + SCAN_EHMARKER_TRY(); + +#define PAL_EXCEPT_NAKED(Disposition) \ + } \ + __except(__exCode = GetExceptionCode(), Disposition) \ + { \ + __exHandled = true; \ + SCAN_EHMARKER_CATCH(); \ + PAL_SEH_RESTORE_GUARD_PAGE + +#define PAL_EXCEPT_FILTER_NAKED(pfnFilter, param) \ + } \ + __except(__exCode = GetExceptionCode(), \ + pfnFilter(GetExceptionInformation(), param)) \ + { \ + __exHandled = true; \ + SCAN_EHMARKER_CATCH(); \ + PAL_SEH_RESTORE_GUARD_PAGE + +#define PAL_FINALLY_NAKED \ + } \ + __finally \ + { \ + +#define PAL_ENDTRY_NAKED \ + } \ + PAL_ENDTRY_NAKED_DBG \ + } \ + + +#if defined(_DEBUG) && !defined(DACCESS_COMPILE) +// +// In debug mode, compile the try body as a method of a local class. +// This way, the compiler will check that the body is not directly +// accessing any local variables and arguments. +// +#define PAL_TRY(__ParamType, __paramDef, __paramRef) \ +{ \ + __ParamType __param = __paramRef; \ + __ParamType __paramToPassToFilter = __paramRef; \ + class __Body \ + { \ + public: \ + static void Run(__ParamType __paramDef) \ + { \ + PAL_TRY_HANDLER_DBG_BEGIN + +// PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by +// JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods +// as on PAL. +#define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) \ +{ \ + struct __HandlerData { \ + __ParamType __param; \ + COMPILER_INSTANCE *__ciPtr; \ + }; \ + __HandlerData handlerData; \ + handlerData.__param = __paramRef; \ + handlerData.__ciPtr = ciPtr; \ + __HandlerData* __param = &handlerData; \ + __ParamType __paramToPassToFilter = __paramRef; \ + class __Body \ + { \ + public: \ + static void Run(__HandlerData* __pHandlerData) \ + { \ + PAL_TRY_HANDLER_DBG_BEGIN \ + COMPILER_INSTANCE *ciPtr = __pHandlerData->__ciPtr; \ + __ParamType __paramDef = __pHandlerData->__param; + + +#define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ +{ \ + __ParamType __param = __paramRef; \ + __ParamType __paramToPassToFilter = __paramRef; \ + class __Body \ + { \ + public: \ + static void Run(__ParamType __paramDef) \ + { \ + PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) + +#define PAL_EXCEPT(Disposition) \ + PAL_TRY_HANDLER_DBG_END \ + } \ + }; \ + PAL_TRY_NAKED \ + __Body::Run(__param); \ + PAL_EXCEPT_NAKED(Disposition) + +#define PAL_EXCEPT_FILTER(pfnFilter) \ + PAL_TRY_HANDLER_DBG_END \ + } \ + }; \ + PAL_TRY_NAKED \ + __Body::Run(__param); \ + PAL_EXCEPT_FILTER_NAKED(pfnFilter, __paramToPassToFilter) + +#define PAL_FINALLY \ + PAL_TRY_HANDLER_DBG_END \ + } \ + }; \ + PAL_TRY_NAKED \ + __Body::Run(__param); \ + PAL_FINALLY_NAKED + +#define PAL_ENDTRY \ + PAL_ENDTRY_NAKED \ +} + +#else // _DEBUG + +#define PAL_TRY(__ParamType, __paramDef, __paramRef) \ +{ \ + __ParamType __param = __paramRef; \ + __ParamType __paramDef = __param; \ + PAL_TRY_NAKED \ + PAL_TRY_HANDLER_DBG_BEGIN + +// PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by +// JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods +// as on PAL. +#define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) PAL_TRY(__ParamType, __paramDef, __paramRef) + +#define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ +{ \ + __ParamType __param = __paramRef; \ + __ParamType __paramDef; __paramDef = __param; \ + PAL_TRY_NAKED \ + PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) + +#define PAL_EXCEPT(Disposition) \ + PAL_TRY_HANDLER_DBG_END \ + PAL_EXCEPT_NAKED(Disposition) + +#define PAL_EXCEPT_FILTER(pfnFilter) \ + PAL_TRY_HANDLER_DBG_END \ + PAL_EXCEPT_FILTER_NAKED(pfnFilter, __param) + +#define PAL_FINALLY \ + PAL_TRY_HANDLER_DBG_END \ + PAL_FINALLY_NAKED + +#define PAL_ENDTRY \ + PAL_ENDTRY_NAKED \ + } + +#endif // _DEBUG + +// Executes the handler if the specified exception code matches +// the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. +#define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == dwExceptionCode)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) + +#define PAL_CPP_TRY try +#define PAL_CPP_ENDTRY +#define PAL_CPP_THROW(type, obj) do { SCAN_THROW_MARKER; throw obj; } while (false) +#define PAL_CPP_RETHROW do { SCAN_THROW_MARKER; throw; } while (false) +#define PAL_CPP_CATCH_DERIVED(type, obj) catch (type * obj) +#define PAL_CPP_CATCH_ALL catch (...) +#define PAL_CPP_CATCH_EXCEPTION_NOARG catch (Exception *) + + +// SELECTANY macro is intended to prevent duplication of static const +// arrays declared in .h files in binary modules. +// The problem is that const variables have static internal linkage +// in C++. That means that if a const variable is declared in a .h file +// the compiler will emit it into every translation unit that uses that .h file. +// That will cause duplication of the data when those translation units +// are linked into a binary module. +// SELECTANY declares a variable as extern to give it external linkage +// and it provides __declspec(selectany) to instruct the linker to merge +// duplicate external const static data copies into one. +// +#if defined(SOURCE_FORMATTING) +#define SELECTANY extern +#else +#if defined(__GNUC__) +#define SELECTANY extern __attribute__((weak)) +#else +#define SELECTANY extern __declspec(selectany) +#endif +#endif +#if defined(SOURCE_FORMATTING) +#define __annotation(x) +#endif + + +#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS) +#define PAL_TRY_HANDLER_DBG_BEGIN \ + BOOL ___oldOkayToThrowValue = FALSE; \ + ClrDebugState *___pState = ::GetClrDebugState(); \ + __try \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___pState->SetOkToThrow(); \ + PAL_ENTER_THROWS_REGION; + +// Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. +#define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ + BOOL ___oldOkayToThrowValue = FALSE; \ + ClrDebugState *___pState = NULL; \ + if (_reason != DLL_PROCESS_ATTACH) \ + ___pState = CheckClrDebugState(); \ + __try \ + { \ + if (___pState) \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___pState->SetOkToThrow(); \ + } \ + if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ + { \ + ___pState = NULL; \ + } \ + PAL_ENTER_THROWS_REGION; + +#define PAL_TRY_HANDLER_DBG_END \ + PAL_LEAVE_THROWS_REGION \ + } \ + __finally \ + { \ + if (___pState != NULL) \ + { \ + _ASSERTE(___pState == CheckClrDebugState()); \ + ___pState->SetOkToThrow( ___oldOkayToThrowValue ); \ + } \ + } + +#define PAL_ENDTRY_NAKED_DBG + +#else +#define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; +#define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; +#define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; +#define PAL_ENDTRY_NAKED_DBG +#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) + + +#if !BIGENDIAN +// For little-endian machines, do nothing +#define VAL16(x) x +#define VAL32(x) x +#define VAL64(x) x +#define SwapString(x) +#define SwapStringLength(x, y) +#define SwapGuid(x) +#endif // !BIGENDIAN + +#ifdef _MSC_VER +// Get Unaligned values from a potentially unaligned object +#define GET_UNALIGNED_16(_pObject) (*(UINT16 UNALIGNED *)(_pObject)) +#define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) +#define GET_UNALIGNED_64(_pObject) (*(UINT64 UNALIGNED *)(_pObject)) + +// Set Value on an potentially unaligned object +#define SET_UNALIGNED_16(_pObject, _Value) (*(UNALIGNED UINT16 *)(_pObject)) = (UINT16)(_Value) +#define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value) +#define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) + +// Get Unaligned values from a potentially unaligned object and swap the value +#define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject)) +#define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) +#define GET_UNALIGNED_VAL64(_pObject) VAL64(GET_UNALIGNED_64(_pObject)) + +// Set a swap Value on an potentially unaligned object +#define SET_UNALIGNED_VAL16(_pObject, _Value) SET_UNALIGNED_16(_pObject, VAL16((UINT16)_Value)) +#define SET_UNALIGNED_VAL32(_pObject, _Value) SET_UNALIGNED_32(_pObject, VAL32((UINT32)_Value)) +#define SET_UNALIGNED_VAL64(_pObject, _Value) SET_UNALIGNED_64(_pObject, VAL64((UINT64)_Value)) +#endif + +#ifdef _WIN64 +#define VALPTR(x) VAL64(x) +#define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) +#define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) +#define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_64(p,x) +#define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL64(p,x) +#else +#define VALPTR(x) VAL32(x) +#define GET_UNALIGNED_PTR(x) GET_UNALIGNED_32(x) +#define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL32(x) +#define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_32(p,x) +#define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) +#endif + +#define MAKEDLLNAME_W(name) name W(".dll") +#define MAKEDLLNAME_A(name) name ".dll" + +#ifdef UNICODE +#define MAKEDLLNAME(x) MAKEDLLNAME_W(x) +#else +#define MAKEDLLNAME(x) MAKEDLLNAME_A(x) +#endif + +#if !defined(MAX_LONGPATH) +#define MAX_LONGPATH 260 /* max. length of full pathname */ +#endif +#if !defined(MAX_PATH_FNAME) +#define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */ +#endif + +#define __clr_reserved __reserved + +#endif // __PALCLR_H__ + +#include "palclr_win.h" + +#endif // !defined(FEATURE_PAL) diff --git a/lib/coreclr/src/inc/palclr_win.h b/lib/coreclr/src/inc/palclr_win.h new file mode 100644 index 0000000000..5050586955 --- /dev/null +++ b/lib/coreclr/src/inc/palclr_win.h @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: palclr.h +// +// Various macros and constants that are necessary to make the CLR portable. +// + +// =========================================================================== + +#ifndef __PALCLR_WIN_H__ +#define __PALCLR_WIN_H__ + +// PAL SEH +// Macros for portable exception handling. The Win32 SEH is emulated using +// these macros and setjmp/longjmp on Unix +// +// Usage notes: +// +// - The filter has to be a function taking two parameters: +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// +// - It is not possible to directly use the local variables in the filter. +// All the local information that the filter has to need to know about should +// be passed through pv parameter +// +// - Do not use goto to jump out of the PAL_TRY block +// (jumping out of the try block is not a good idea even on Win32, because of +// it causes stack unwind) +// +// +// Simple examples: +// +// PAL_TRY { +// .... +// } WIN_PAL_FINALLY { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// PAL_TRY { +// .... +// } WIN_PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// { +// ... +// } +// PAL_TRY { +// .... +// } WIN_PAL_EXCEPT_FILTER(MyFilter, NULL) { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// Complex example: +// +// struct MyParams +// { +// ... +// } params; +// +// PAL_TRY { +// PAL_TRY { +// ... +// if (error) goto Done; +// ... +// Done: ; +// } WIN_PAL_EXCEPT_FILTER(OtherFilter, ¶ms) { +// ... +// } +// WIN_PAL_ENDTRY +// } +// WIN_PAL_FINALLY { +// } +// WIN_PAL_ENDTRY +// + + + +#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(_ARM_) // @ARMTODO +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN \ + BOOL ___oldOkayToThrowValue = FALSE; \ + ClrDebugState *___pState = GetClrDebugState(); \ + __try \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___pState->SetOkToThrow(TRUE); \ + ANNOTATION_TRY_BEGIN; + +// Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ + BOOL ___oldOkayToThrowValue = FALSE; \ + BOOL ___oldSOTolerantState = FALSE; \ + ClrDebugState *___pState = CheckClrDebugState(); \ + __try \ + { \ + if (___pState) \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___pState->SetOkToThrow(TRUE); \ + } \ + if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ + { \ + ___pState = NULL; \ + } \ + ANNOTATION_TRY_BEGIN; + +#define WIN_PAL_TRY_HANDLER_DBG_END \ + ANNOTATION_TRY_END; \ + } \ + __finally \ + { \ + if (___pState != NULL) \ + { \ + _ASSERTE(___pState == CheckClrDebugState()); \ + ___pState->SetOkToThrow(___oldOkayToThrowValue); \ + ___pState->SetSOTolerance(___oldSOTolerantState); \ + } \ + } + +#define WIN_PAL_ENDTRY_NAKED_DBG + +#else +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; +#define WIN_PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; +#define WIN_PAL_ENDTRY_NAKED_DBG +#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) + +#if !defined (FEATURE_PAL) +// Native system libray handle. +// In Windows, NATIVE_LIBRARY_HANDLE is the same as HMODULE. +typedef HMODULE NATIVE_LIBRARY_HANDLE; +#endif // !FEATURE_PAL + +#endif // __PALCLR_WIN_H__ diff --git a/lib/coreclr/src/inc/pedecoder.h b/lib/coreclr/src/inc/pedecoder.h new file mode 100644 index 0000000000..5dff335427 --- /dev/null +++ b/lib/coreclr/src/inc/pedecoder.h @@ -0,0 +1,477 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// PEDecoder.h +// + +// -------------------------------------------------------------------------------- + +// -------------------------------------------------------------------------------- +// PEDecoder - Utility class for reading and verifying PE files. +// +// Note that the Check step is optional if you are willing to trust the +// integrity of the image. +// (Or at any rate can be factored into an initial verification step.) +// +// Functions which access the memory of the PE file take a "flat" flag - this +// indicates whether the PE images data has been loaded flat the way it resides in the file, +// or if the sections have been mapped into memory at the proper base addresses. +// +// Finally, some functions take an optional "size" argument, which can be used for +// range verification. This is an optional parameter, but if you omit it be sure +// you verify the size in some other way. +// -------------------------------------------------------------------------------- + + +#ifndef PEDECODER_H_ +#define PEDECODER_H_ + +// -------------------------------------------------------------------------------- +// Required headers +// -------------------------------------------------------------------------------- + +#include "windows.h" +#include "clrtypes.h" +#include "check.h" +#include "contract.h" +#include "cor.h" +#include "corhdr.h" + +#include "corcompile.h" + +#include "readytorun.h" +typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER; +typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; + +typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER; + +// -------------------------------------------------------------------------------- +// Forward declared types +// -------------------------------------------------------------------------------- + +class Module; + +// -------------------------------------------------------------------------------- +// RVA definition +// -------------------------------------------------------------------------------- + +// Needs to be DWORD to avoid conflict with +typedef DWORD RVA; + +#ifdef _MSC_VER +// Wrapper to suppress ambigous overload problems with MSVC. +inline CHECK CheckOverflow(RVA value1, COUNT_T value2) +{ + WRAPPER_NO_CONTRACT; + CHECK(CheckOverflow((UINT32) value1, (UINT32) value2)); + CHECK_OK; +} +#endif // _MSC_VER + +// -------------------------------------------------------------------------------- +// IMAGE_FILE_MACHINE_NATIVE +// -------------------------------------------------------------------------------- + +#if defined(_TARGET_X86_) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386 +#elif defined(_TARGET_AMD64_) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64 +#elif defined(_TARGET_ARM_) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARMNT +#elif defined(_TARGET_ARM64_) +#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64 +#else +#error "port me" +#endif + +// Machine code for native images +#if defined(__APPLE__) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x4644 +#elif defined(__FreeBSD__) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC4 +#elif defined(__linux__) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79 +#elif defined(__NetBSD__) +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1993 +#else +#define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0 +#endif + +#define IMAGE_FILE_MACHINE_NATIVE_NI (IMAGE_FILE_MACHINE_NATIVE ^ IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE) + +// -------------------------------------------------------------------------------- +// Types +// -------------------------------------------------------------------------------- + +typedef DPTR(class PEDecoder) PTR_PEDecoder; + +typedef bool (*PEDecoder_ResourceTypesCallbackFunction)(LPCWSTR lpType, void* context); +typedef bool (*PEDecoder_ResourceNamesCallbackFunction)(LPCWSTR lpName, LPCWSTR lpType, void* context); +typedef bool (*PEDecoder_ResourceCallbackFunction)(LPCWSTR lpName, LPCWSTR lpType, DWORD langid, BYTE* data, COUNT_T cbData, void* context); + +class PEDecoder +{ + public: + + // ------------------------------------------------------------ + // Public API + // ------------------------------------------------------------ + + // Access functions are divided into 3 categories: + // Has - check if the element is present + // Check - Do consistency checks on the element (requires Has). + // This step is optional if you are willing to trust the integrity of the + // image. (It is asserted in a checked build.) + // Get - Access the element (requires Has and Check) + + PEDecoder(); + PEDecoder(void *flatBase, COUNT_T size); // flatBase is the raw disk layout data (using MapViewOfFile) + PEDecoder(PTR_VOID mappedBase, bool relocated = FALSE); // mappedBase is the mapped/expanded file (using LoadLibrary) + + void Init(void *flatBase, COUNT_T size); + HRESULT Init(void *mappedBase, bool relocated = FALSE); + void Reset(); //make sure you don't have a thread race + + PTR_VOID GetBase() const; // Currently loaded base, as opposed to GetPreferredBase() + BOOL IsMapped() const; + BOOL IsRelocated() const; + BOOL IsFlat() const; + BOOL HasContents() const; + COUNT_T GetSize() const; // size of file on disk, as opposed to GetVirtualSize() + + // High level image checks: + + CHECK CheckFormat() const; // Check whatever is present + CHECK CheckNTFormat() const; // Check a PE file image + CHECK CheckCORFormat() const; // Check a COR image (IL or native) + CHECK CheckILFormat() const; // Check a managed image + CHECK CheckILOnlyFormat() const; // Check an IL only image + CHECK CheckNativeFormat() const; // Check a native image + + // NT header access + + BOOL HasNTHeaders() const; + CHECK CheckNTHeaders() const; + + IMAGE_NT_HEADERS32 *GetNTHeaders32() const; + IMAGE_NT_HEADERS64 *GetNTHeaders64() const; + BOOL Has32BitNTHeaders() const; + + const void *GetHeaders(COUNT_T *pSize = NULL) const; + + BOOL IsDll() const; + BOOL HasBaseRelocations() const; + const void *GetPreferredBase() const; // OptionalHeaders.ImageBase + COUNT_T GetVirtualSize() const; // OptionalHeaders.SizeOfImage - size of mapped/expanded image in memory + WORD GetSubsystem() const; + WORD GetDllCharacteristics() const; + DWORD GetTimeDateStamp() const; + DWORD GetCheckSum() const; + WORD GetMachine() const; + WORD GetCharacteristics() const; + DWORD GetFileAlignment() const; + DWORD GetSectionAlignment() const; + SIZE_T GetSizeOfStackReserve() const; + SIZE_T GetSizeOfStackCommit() const; + SIZE_T GetSizeOfHeapReserve() const; + SIZE_T GetSizeOfHeapCommit() const; + UINT32 GetLoaderFlags() const; + UINT32 GetWin32VersionValue() const; + COUNT_T GetNumberOfRvaAndSizes() const; + COUNT_T GetNumberOfSections() const; + PTR_IMAGE_SECTION_HEADER FindFirstSection() const; + IMAGE_SECTION_HEADER *FindSection(LPCSTR sectionName) const; + + DWORD GetImageIdentity() const; + + BOOL HasWriteableSections() const; + + // Directory entry access + + BOOL HasDirectoryEntry(int entry) const; + CHECK CheckDirectoryEntry(int entry, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const; + IMAGE_DATA_DIRECTORY *GetDirectoryEntry(int entry) const; + TADDR GetDirectoryEntryData(int entry, COUNT_T *pSize = NULL) const; + + // IMAGE_DATA_DIRECTORY access + + CHECK CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const; + TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const; + TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const; + + // Basic RVA access + + CHECK CheckRva(RVA rva, IsNullOK ok = NULL_NOT_OK) const; + CHECK CheckRva(RVA rva, COUNT_T size, int forbiddenFlags=0, IsNullOK ok = NULL_NOT_OK) const; + TADDR GetRvaData(RVA rva, IsNullOK ok = NULL_NOT_OK) const; + // Called with ok=NULL_OK only for mapped fields (RVA statics) + + CHECK CheckData(const void *data, IsNullOK ok = NULL_NOT_OK) const; + CHECK CheckData(const void *data, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; + RVA GetDataRva(const TADDR data) const; + BOOL PointerInPE(PTR_CVOID data) const; + + // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress + CHECK CheckOffset(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const; + CHECK CheckOffset(COUNT_T fileOffset, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; + TADDR GetOffsetData(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const; + // Called with ok=NULL_OK only for mapped fields (RVA statics) + + // Mapping between RVA and file offsets + COUNT_T RvaToOffset(RVA rva) const; + RVA OffsetToRva(COUNT_T fileOffset) const; + + // Base intra-image pointer access + // (These are for pointers retrieved out of the PE image) + + CHECK CheckInternalAddress(SIZE_T address, IsNullOK ok = NULL_NOT_OK) const; + CHECK CheckInternalAddress(SIZE_T address, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; + TADDR GetInternalAddressData(SIZE_T address) const; + + // CLR loader IL Image verification - these checks apply to IL_ONLY images. + + BOOL IsILOnly() const; + CHECK CheckILOnly() const; + + void LayoutILOnly(void *base, BOOL allowFullPE = FALSE) const; + + // Strong name & hashing support + + BOOL HasStrongNameSignature() const; + CHECK CheckStrongNameSignature() const; + PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL) const; + + // CorHeader flag support + + // IsStrongNameSigned indicates whether the signature has been filled in. + // (otherwise if it has a signature it is delay signed.) + BOOL IsStrongNameSigned() const; // TRUE if the COMIMAGE_FLAGS_STRONGNAMESIGNED flag is set + + // TLS + + BOOL HasTls() const; + CHECK CheckTls() const; + PTR_VOID GetTlsRange(COUNT_T *pSize = NULL) const; + UINT32 GetTlsIndex() const; + + // Win32 resources + void *GetWin32Resource(LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSize = NULL) const; + bool EnumerateWin32ResourceTypes(PEDecoder_ResourceTypesCallbackFunction callback, void* context) const; + bool EnumerateWin32ResourceNames(LPCWSTR lpType, PEDecoder_ResourceNamesCallbackFunction callback, void* context) const; + bool EnumerateWin32Resources(LPCWSTR lpName, LPCWSTR lpType, PEDecoder_ResourceCallbackFunction callback, void* context) const; + public: + + // COR header fields + + BOOL HasCorHeader() const; + CHECK CheckCorHeader() const; + IMAGE_COR20_HEADER *GetCorHeader() const; + + PTR_CVOID GetMetadata(COUNT_T *pSize = NULL) const; + + const void *GetResources(COUNT_T *pSize = NULL) const; + CHECK CheckResource(COUNT_T offset) const; + const void *GetResource(COUNT_T offset, COUNT_T *pSize = NULL) const; + + BOOL HasManagedEntryPoint() const; + ULONG GetEntryPointToken() const; + IMAGE_COR_VTABLEFIXUP *GetVTableFixups(COUNT_T *pCount = NULL) const; + + // Native header access + BOOL HasNativeHeader() const; + CHECK CheckNativeHeader() const; + CORCOMPILE_HEADER *GetNativeHeader() const; + BOOL IsNativeMachineFormat() const; + BOOL IsI386() const; + + void GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine); // Returns CorPEKind flags + BOOL IsPlatformNeutral(); // Returns TRUE for IL-only platform neutral images + + // + // Verifies that the IL is within the bounds of the image. + // + CHECK CheckILMethod(RVA rva); + + // + // Compute size of IL blob. Assumes that the IL is within the bounds of the image - make sure + // to call CheckILMethod before calling this method. + // + static SIZE_T ComputeILMethodSize(TADDR pIL); + + // Debug directory access, returns NULL if no such entry + PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const; + + PTR_CVOID GetNativeManifestMetadata(COUNT_T* pSize = NULL) const; + +#ifdef FEATURE_PREJIT + CHECK CheckNativeHeaderVersion() const; + + // ManagedNative fields + CORCOMPILE_CODE_MANAGER_ENTRY *GetNativeCodeManagerTable() const; + CORCOMPILE_EE_INFO_TABLE *GetNativeEEInfoTable() const; + void *GetNativeHelperTable(COUNT_T *pSize = NULL) const; + CORCOMPILE_VERSION_INFO *GetNativeVersionInfo() const; + CORCOMPILE_VERSION_INFO *GetNativeVersionInfoMaybeNull(bool skipCheckNativeHeader = false) const; + BOOL HasNativeDebugMap() const; + TADDR GetNativeDebugMap(COUNT_T *pSize = NULL) const; + Module *GetPersistedModuleImage(COUNT_T *pSize = NULL) const; + PCODE GetNativeHotCode(COUNT_T * pSize = NULL) const; + PCODE GetNativeCode(COUNT_T * pSize = NULL) const; + PCODE GetNativeColdCode(COUNT_T * pSize = NULL) const; + + CORCOMPILE_METHOD_PROFILE_LIST *GetNativeProfileDataList(COUNT_T *pSize = NULL) const; + const void *GetNativePreferredBase() const; + BOOL GetNativeILHasSecurityDirectory() const; + BOOL GetNativeILIsIbcOptimized() const; + BOOL GetNativeILHasReadyToRunHeader() const; + BOOL IsNativeILILOnly() const; + BOOL IsNativeILDll() const; + void GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const; + CORCOMPILE_DEPENDENCY * GetNativeDependencies(COUNT_T *pCount = NULL) const; + + PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSections(COUNT_T *pCount = NULL) const; + PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionFromIndex(COUNT_T index) const; + PTR_CORCOMPILE_IMPORT_SECTION GetNativeImportSectionForRVA(RVA rva) const; + + TADDR GetStubsTable(COUNT_T *pSize = NULL) const; + TADDR GetVirtualSectionsTable(COUNT_T *pSize = NULL) const; +#endif // FEATURE_PREJIT + + BOOL HasReadyToRunHeader() const; + READYTORUN_HEADER *GetReadyToRunHeader() const; + + void GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const; + + CHECK CheckWillCreateGuardPage() const; + + // Native DLLMain Entrypoint + BOOL HasNativeEntryPoint() const; + void *GetNativeEntryPoint() const; + +#ifdef _DEBUG + // Stress mode for relocations + static BOOL GetForceRelocs(); + static BOOL ForceRelocForDLL(LPCWSTR lpFileName); +#endif + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis); +#endif + + protected: + + // ------------------------------------------------------------ + // Protected API for subclass use + // ------------------------------------------------------------ + + // Checking utilites + static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva); + static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size); + + static CHECK CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer); + static CHECK CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size); + + protected: + + // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress + IMAGE_SECTION_HEADER *RvaToSection(RVA rva) const; + IMAGE_SECTION_HEADER *OffsetToSection(COUNT_T fileOffset) const; + + void SetRelocated(); + + private: + + // ------------------------------------------------------------ + // Internal functions + // ------------------------------------------------------------ + + enum METADATA_SECTION_TYPE + { + METADATA_SECTION_FULL, +#ifdef FEATURE_PREJIT + METADATA_SECTION_MANIFEST +#endif + }; + + IMAGE_DATA_DIRECTORY *GetMetaDataHelper(METADATA_SECTION_TYPE type) const; + + static PTR_IMAGE_SECTION_HEADER FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders); + + IMAGE_NT_HEADERS *FindNTHeaders() const; + IMAGE_COR20_HEADER *FindCorHeader() const; + CORCOMPILE_HEADER *FindNativeHeader() const; + READYTORUN_HEADER *FindReadyToRunHeader() const; + + // Flat mapping utilities + RVA InternalAddressToRva(SIZE_T address) const; + + // NT header subchecks + CHECK CheckSection(COUNT_T previousAddressEnd, COUNT_T addressStart, COUNT_T addressSize, + COUNT_T previousOffsetEnd, COUNT_T offsetStart, COUNT_T offsetSize) const; + + // Pure managed subchecks + CHECK CheckILOnlyImportDlls() const; + CHECK CheckILOnlyImportByNameTable(RVA rva) const; + CHECK CheckILOnlyBaseRelocations() const; + CHECK CheckILOnlyEntryPoint() const; + + // ------------------------------------------------------------ + // Instance members + // ------------------------------------------------------------ + + enum + { + FLAG_MAPPED = 0x01, // the file is mapped/hydrated (vs. the raw disk layout) + FLAG_CONTENTS = 0x02, // the file has contents + FLAG_RELOCATED = 0x04, // relocs have been applied + FLAG_NT_CHECKED = 0x10, + FLAG_COR_CHECKED = 0x20, + FLAG_IL_ONLY_CHECKED = 0x40, + FLAG_NATIVE_CHECKED = 0x80, + + FLAG_HAS_NO_READYTORUN_HEADER = 0x100, + }; + + TADDR m_base; + COUNT_T m_size; // size of file on disk, as opposed to OptionalHeaders.SizeOfImage + ULONG m_flags; + + PTR_IMAGE_NT_HEADERS m_pNTHeaders; + PTR_IMAGE_COR20_HEADER m_pCorHeader; + PTR_CORCOMPILE_HEADER m_pNativeHeader; + PTR_READYTORUN_HEADER m_pReadyToRunHeader; +}; + +// +// MethodSectionIterator class is used to iterate hot (or) cold method section in an ngen image. +// It can also iterate nibble maps generated by the JIT in a regular HeapList. +// +class MethodSectionIterator +{ + private: + PTR_DWORD m_codeTableStart; + PTR_DWORD m_codeTable; + PTR_DWORD m_codeTableEnd; + + BYTE *m_code; + + DWORD m_dword; + DWORD m_index; + + BYTE *m_current; + + public: + + //If code is a target pointer, then GetMethodCode and FindMethodCode return + //target pointers. codeTable may be a pointer of either type, since it is + //converted internally into a host pointer. + MethodSectionIterator(const void *code, SIZE_T codeSize, + const void *codeTable, SIZE_T codeTableSize); + BOOL Next(); + BYTE *GetMethodCode() { return m_current; } // Get the start of method code of the current method in the iterator +}; + +#include "pedecoder.inl" + +#endif // PEDECODER_H_ diff --git a/lib/coreclr/src/inc/pedecoder.inl b/lib/coreclr/src/inc/pedecoder.inl new file mode 100644 index 0000000000..c17c03a5c8 --- /dev/null +++ b/lib/coreclr/src/inc/pedecoder.inl @@ -0,0 +1,1401 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// PEDecoder.inl +// + +// -------------------------------------------------------------------------------- + +#ifndef _PEDECODER_INL_ +#define _PEDECODER_INL_ + +#include "pedecoder.h" +#include "ex.h" + +#ifndef DACCESS_COMPILE + +inline PEDecoder::PEDecoder() + : m_base(0), + m_size(0), + m_flags(0), + m_pNTHeaders(nullptr), + m_pCorHeader(nullptr), + m_pNativeHeader(nullptr), + m_pReadyToRunHeader(nullptr) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + NOTHROW; + CANNOT_TAKE_LOCK; + GC_NOTRIGGER; + } + CONTRACTL_END; +} +#else +inline PEDecoder::PEDecoder() +{ + LIMITED_METHOD_CONTRACT; +} +#endif // #ifndef DACCESS_COMPILE + +inline PTR_VOID PEDecoder::GetBase() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return PTR_VOID(m_base); +} + +inline BOOL PEDecoder::IsMapped() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_flags & FLAG_MAPPED) != 0; +} + +inline BOOL PEDecoder::IsRelocated() const +{ + LIMITED_METHOD_CONTRACT; + + return (m_flags & FLAG_RELOCATED) != 0; +} + +inline void PEDecoder::SetRelocated() +{ + m_flags |= FLAG_RELOCATED; +} + +inline BOOL PEDecoder::IsFlat() const +{ + LIMITED_METHOD_CONTRACT; + + return HasContents() && !IsMapped(); +} + +inline BOOL PEDecoder::HasContents() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_flags & FLAG_CONTENTS) != 0; +} + +inline COUNT_T PEDecoder::GetSize() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return m_size; +} + +inline PEDecoder::PEDecoder(PTR_VOID mappedBase, bool fixedUp /*= FALSE*/) + : m_base(dac_cast(mappedBase)), + m_size(0), + m_flags(FLAG_MAPPED | FLAG_CONTENTS | FLAG_NT_CHECKED | (fixedUp ? FLAG_RELOCATED : 0)), + m_pNTHeaders(nullptr), + m_pCorHeader(nullptr), + m_pNativeHeader(nullptr), + m_pReadyToRunHeader(nullptr) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(mappedBase)); + PRECONDITION(CheckAligned(mappedBase, GetOsPageSize())); + PRECONDITION(PEDecoder(mappedBase,fixedUp).CheckNTHeaders()); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + // Temporarily set the size to 2 pages, so we can get the headers. + m_size = GetOsPageSize()*2; + + m_pNTHeaders = PTR_IMAGE_NT_HEADERS(FindNTHeaders()); + if (!m_pNTHeaders) + ThrowHR(COR_E_BADIMAGEFORMAT); + + m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); +} + +#ifndef DACCESS_COMPILE + +//REM +//what's the right way to do this? +//we want to use some against TADDR, but also want to do +//some against what's just in the current process. +//m_base is a TADDR in DAC all the time, though. +//Have to implement separate fn to do the lookup?? +inline PEDecoder::PEDecoder(void *flatBase, COUNT_T size) + : m_base((TADDR)flatBase), + m_size(size), + m_flags(FLAG_CONTENTS), + m_pNTHeaders(NULL), + m_pCorHeader(NULL), + m_pNativeHeader(NULL), + m_pReadyToRunHeader(NULL) +{ + CONTRACTL + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(flatBase)); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; +} + +inline void PEDecoder::Init(void *flatBase, COUNT_T size) +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION((size == 0) || CheckPointer(flatBase)); + PRECONDITION(!HasContents()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + m_base = (TADDR)flatBase; + m_size = size; + m_flags = FLAG_CONTENTS; +} + + + +inline HRESULT PEDecoder::Init(void *mappedBase, bool fixedUp /*= FALSE*/) +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(CheckPointer(mappedBase)); + PRECONDITION(CheckAligned(mappedBase, GetOsPageSize())); + PRECONDITION(!HasContents()); + } + CONTRACTL_END; + + m_base = (TADDR)mappedBase; + m_flags = FLAG_MAPPED | FLAG_CONTENTS; + if (fixedUp) + m_flags |= FLAG_RELOCATED; + + // Temporarily set the size to 2 pages, so we can get the headers. + m_size = GetOsPageSize()*2; + + m_pNTHeaders = FindNTHeaders(); + if (!m_pNTHeaders) + return COR_E_BADIMAGEFORMAT; + + m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); + return S_OK; +} + +inline void PEDecoder::Reset() +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + m_base=NULL; + m_flags=NULL; + m_size=NULL; + m_pNTHeaders=NULL; + m_pCorHeader=NULL; + m_pNativeHeader=NULL; + m_pReadyToRunHeader=NULL; +} +#endif // #ifndef DACCESS_COMPILE + + +inline IMAGE_NT_HEADERS32 *PEDecoder::GetNTHeaders32() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast(FindNTHeaders()); +} + +inline IMAGE_NT_HEADERS64 *PEDecoder::GetNTHeaders64() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return dac_cast(FindNTHeaders()); +} + +inline BOOL PEDecoder::Has32BitNTHeaders() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (FindNTHeaders()->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)); +} + +inline const void *PEDecoder::GetHeaders(COUNT_T *pSize) const +{ + CONTRACT(const void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + if (pSize != NULL) + *pSize = VAL32(FindNTHeaders()->OptionalHeader.SizeOfHeaders); + + RETURN (const void *) m_base; +} + +inline BOOL PEDecoder::IsDll() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_DLL)) != 0); +} + +inline BOOL PEDecoder::HasBaseRelocations() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_RELOCS_STRIPPED)) == 0); +} + +inline const void *PEDecoder::GetPreferredBase() const +{ + CONTRACT(const void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); + } + CONTRACT_END; + + if (Has32BitNTHeaders()) + RETURN (const void *) (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.ImageBase); + else + RETURN (const void *) (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.ImageBase); +} + +inline COUNT_T PEDecoder::GetVirtualSize() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.SizeOfImage); +} + +inline WORD PEDecoder::GetSubsystem() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL16(FindNTHeaders()->OptionalHeader.Subsystem); +} + +inline WORD PEDecoder::GetDllCharacteristics() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL16(FindNTHeaders()->OptionalHeader.DllCharacteristics); +} + +inline DWORD PEDecoder::GetTimeDateStamp() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL32(FindNTHeaders()->FileHeader.TimeDateStamp); +} + +inline DWORD PEDecoder::GetCheckSum() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.CheckSum); +} + +inline DWORD PEDecoder::GetFileAlignment() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.FileAlignment); +} + +inline DWORD PEDecoder::GetSectionAlignment() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + //even though some data in OptionalHeader is different for 32 and 64, this field is the same + return VAL32(FindNTHeaders()->OptionalHeader.SectionAlignment); +} + +inline WORD PEDecoder::GetMachine() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.Machine); +} + +inline WORD PEDecoder::GetCharacteristics() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.Characteristics); +} + +inline SIZE_T PEDecoder::GetSizeOfStackReserve() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackReserve); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackReserve); +} + + +inline SIZE_T PEDecoder::GetSizeOfStackCommit() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackCommit); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackCommit); +} + + +inline SIZE_T PEDecoder::GetSizeOfHeapReserve() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapReserve); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapReserve); +} + + +inline SIZE_T PEDecoder::GetSizeOfHeapCommit() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapCommit); + else + return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapCommit); +} + +inline UINT32 PEDecoder::GetLoaderFlags() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.LoaderFlags); + else + return VAL32(GetNTHeaders64()->OptionalHeader.LoaderFlags); +} + +inline UINT32 PEDecoder::GetWin32VersionValue() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.Win32VersionValue); + else + return VAL32(GetNTHeaders64()->OptionalHeader.Win32VersionValue); +} + +inline COUNT_T PEDecoder::GetNumberOfRvaAndSizes() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return VAL32(GetNTHeaders32()->OptionalHeader.NumberOfRvaAndSizes); + else + return VAL32(GetNTHeaders64()->OptionalHeader.NumberOfRvaAndSizes); +} + +inline BOOL PEDecoder::HasDirectoryEntry(int entry) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + if (Has32BitNTHeaders()) + return (GetNTHeaders32()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); + else + return (GetNTHeaders64()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); +} + +inline IMAGE_DATA_DIRECTORY *PEDecoder::GetDirectoryEntry(int entry) const +{ + CONTRACT(IMAGE_DATA_DIRECTORY *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + if (Has32BitNTHeaders()) + RETURN dac_cast( + dac_cast(GetNTHeaders32()) + + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory) + + entry * sizeof(IMAGE_DATA_DIRECTORY)); + else + RETURN dac_cast( + dac_cast(GetNTHeaders64()) + + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory) + + entry * sizeof(IMAGE_DATA_DIRECTORY)); +} + +inline TADDR PEDecoder::GetDirectoryEntryData(int entry, COUNT_T *pSize) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectoryEntry(entry, 0, NULL_OK)); + PRECONDITION(CheckPointer(pSize, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + IMAGE_DATA_DIRECTORY *pDir = GetDirectoryEntry(entry); + + if (pSize != NULL) + *pSize = VAL32(pDir->Size); + + RETURN GetDirectoryData(pDir); +} + +inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + RETURN GetRvaData(VAL32(pDir->VirtualAddress)); +} + +inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); + PRECONDITION(CheckPointer(pSize)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + *pSize = VAL32(pDir->Size); + + RETURN GetRvaData(VAL32(pDir->VirtualAddress)); +} + +inline TADDR PEDecoder::GetInternalAddressData(SIZE_T address) const +{ + CONTRACT(TADDR) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckInternalAddress(address, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer((void *)RETVAL)); + } + CONTRACT_END; + + RETURN GetRvaData(InternalAddressToRva(address)); +} + +inline BOOL PEDecoder::HasCorHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + SUPPORTS_DAC; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER); +} + +inline BOOL PEDecoder::IsILOnly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + // Pretend that ready-to-run images are IL-only + return((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_ILONLY)) != 0) || HasReadyToRunHeader(); +} + +inline COUNT_T PEDecoder::RvaToOffset(RVA rva) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckRva(rva,NULL_OK)); + NOTHROW; + CANNOT_TAKE_LOCK; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + if(rva > 0) + { + IMAGE_SECTION_HEADER *section = RvaToSection(rva); + if (section == NULL) + return rva; + + return rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData); + } + else return 0; +} + +inline RVA PEDecoder::OffsetToRva(COUNT_T fileOffset) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(CheckOffset(fileOffset,NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + if(fileOffset > 0) + { + IMAGE_SECTION_HEADER *section = OffsetToSection(fileOffset); + PREFIX_ASSUME (section!=NULL); //TODO: actually it is possible that it si null we need to rethink how we handle this cases and do better there + + return fileOffset - VAL32(section->PointerToRawData) + VAL32(section->VirtualAddress); + } + else return 0; +} + + +inline BOOL PEDecoder::IsStrongNameSigned() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return ((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_STRONGNAMESIGNED)) != 0); +} + + +inline BOOL PEDecoder::HasStrongNameSignature() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (GetCorHeader()->StrongNameSignature.VirtualAddress != 0); +} + +inline CHECK PEDecoder::CheckStrongNameSignature() const +{ + CONTRACT_CHECK + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasStrongNameSignature()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_CHECK_END; + + return CheckDirectory(&GetCorHeader()->StrongNameSignature, IMAGE_SCN_MEM_WRITE, NULL_OK); +} + +inline PTR_CVOID PEDecoder::GetStrongNameSignature(COUNT_T *pSize) const +{ + CONTRACT(PTR_CVOID) + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + PRECONDITION(HasStrongNameSignature()); + PRECONDITION(CheckStrongNameSignature()); + PRECONDITION(CheckPointer(pSize, NULL_OK)); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->StrongNameSignature; + + if (pSize != NULL) + *pSize = VAL32(pDir->Size); + + RETURN dac_cast(GetDirectoryData(pDir)); +} + +inline BOOL PEDecoder::HasTls() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS); +} + +inline CHECK PEDecoder::CheckTls() const +{ + CONTRACT_CHECK + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_CHECK_END; + + CHECK(CheckDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS, 0, NULL_OK)); + + IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); + + CHECK(CheckUnderflow(VALPTR(pTlsHeader->EndAddressOfRawData), VALPTR(pTlsHeader->StartAddressOfRawData))); + CHECK(VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData) <= COUNT_T_MAX); + + CHECK(CheckInternalAddress(VALPTR(pTlsHeader->StartAddressOfRawData), + (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)))); + + CHECK_OK; +} + +inline PTR_VOID PEDecoder::GetTlsRange(COUNT_T * pSize) const +{ + CONTRACT(void *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasTls()); + PRECONDITION(CheckTls()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + } + CONTRACT_END; + + IMAGE_TLS_DIRECTORY *pTlsHeader = + PTR_IMAGE_TLS_DIRECTORY(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS)); + + if (pSize != 0) + *pSize = (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)); + PREFIX_ASSUME (pTlsHeader!=NULL); + RETURN PTR_VOID(GetInternalAddressData(pTlsHeader->StartAddressOfRawData)); +} + +inline UINT32 PEDecoder::GetTlsIndex() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasTls()); + PRECONDITION(CheckTls()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); + + return (UINT32)*PTR_UINT32(GetInternalAddressData((SIZE_T)VALPTR(pTlsHeader->AddressOfIndex))); +} + +inline IMAGE_COR20_HEADER *PEDecoder::GetCorHeader() const +{ + CONTRACT(IMAGE_COR20_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + if (m_pCorHeader == NULL) + const_cast(this)->m_pCorHeader = + dac_cast(FindCorHeader()); + + RETURN m_pCorHeader; +} + +inline BOOL PEDecoder::IsNativeMachineFormat() const +{ + if (!HasContents() || !HasNTHeaders() ) + return FALSE; + _ASSERTE(m_pNTHeaders); + WORD expectedFormat = HasCorHeader() && (HasNativeHeader() || HasReadyToRunHeader()) ? + IMAGE_FILE_MACHINE_NATIVE_NI : + IMAGE_FILE_MACHINE_NATIVE; + //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion + return m_pNTHeaders->FileHeader.Machine==expectedFormat; +} + +inline BOOL PEDecoder::IsI386() const +{ + if (!HasContents() || !HasNTHeaders() ) + return FALSE; + _ASSERTE(m_pNTHeaders); + //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion + return m_pNTHeaders->FileHeader.Machine==IMAGE_FILE_MACHINE_I386; +} + +inline CORCOMPILE_HEADER *PEDecoder::GetNativeHeader() const +{ + CONTRACT(CORCOMPILE_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + if (m_pNativeHeader == NULL) + const_cast(this)->m_pNativeHeader = + dac_cast(FindNativeHeader()); + + RETURN m_pNativeHeader; +} + +#ifdef FEATURE_PREJIT +inline const void * PEDecoder::GetNativePreferredBase() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (const void *) GetNativeHeader()->ImageBase; +} + +inline BOOL PEDecoder::GetNativeILHasSecurityDirectory() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY) != 0; +} + +inline BOOL PEDecoder::GetNativeILIsIbcOptimized() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_IS_IBC_OPTIMIZED) != 0; +} + +inline BOOL PEDecoder::GetNativeILHasReadyToRunHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return (GetNativeHeader()->Flags & CORCOMPILE_HEADER_IS_READY_TO_RUN) != 0; +} + +inline BOOL PEDecoder::IsNativeILILOnly() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return((GetNativeHeader()->COR20Flags & VAL32(COMIMAGE_FLAGS_ILONLY)) != 0); +} + +inline BOOL PEDecoder::IsNativeILDll() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + PREFIX_ASSUME (GetNativeHeader()!=NULL); + return((GetNativeHeader()->Characteristics & VAL16(IMAGE_FILE_DLL)) != 0); +} + + +inline void PEDecoder::GetNativeILPEKindAndMachine(DWORD* pdwKind, DWORD* pdwMachine) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + CORCOMPILE_HEADER * pNativeHeader = GetNativeHeader(); + PREFIX_ASSUME (pNativeHeader!=NULL); + + if (pdwKind != NULL) + *pdwKind = pNativeHeader->PEKind; + if (pdwMachine != NULL) + *pdwMachine = pNativeHeader->Machine; +} + +inline CORCOMPILE_DEPENDENCY * PEDecoder::GetNativeDependencies(COUNT_T *pCount) const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + IMAGE_DATA_DIRECTORY *pDir = &GetNativeHeader()->Dependencies; + + if (pCount != NULL) + *pCount = VAL32(pDir->Size)/sizeof(CORCOMPILE_DEPENDENCY); + + return (CORCOMPILE_DEPENDENCY *) GetDirectoryData(pDir); +} + +#endif // FEATURE_PREJIT + +// static +inline PTR_IMAGE_SECTION_HEADER PEDecoder::FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return dac_cast( + dac_cast(pNTHeaders) + + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + + VAL16(pNTHeaders->FileHeader.SizeOfOptionalHeader)); +} + +inline COUNT_T PEDecoder::GetNumberOfSections() const +{ + CONTRACTL + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return VAL16(FindNTHeaders()->FileHeader.NumberOfSections); +} + + +inline DWORD PEDecoder::GetImageIdentity() const +{ + WRAPPER_NO_CONTRACT; + return GetTimeDateStamp() ^ GetCheckSum() ^ DWORD( GetVirtualSize() ); +} + + +inline PTR_IMAGE_SECTION_HEADER PEDecoder::FindFirstSection() const +{ + CONTRACT(IMAGE_SECTION_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN FindFirstSection(FindNTHeaders()); +} + +inline IMAGE_NT_HEADERS *PEDecoder::FindNTHeaders() const +{ + CONTRACT(IMAGE_NT_HEADERS *) + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN PTR_IMAGE_NT_HEADERS(m_base + VAL32(PTR_IMAGE_DOS_HEADER(m_base)->e_lfanew)); +} + +inline IMAGE_COR20_HEADER *PEDecoder::FindCorHeader() const +{ + CONTRACT(IMAGE_COR20_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(HasCorHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + const IMAGE_COR20_HEADER * pCor=PTR_IMAGE_COR20_HEADER(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_COMHEADER)); + RETURN ((IMAGE_COR20_HEADER*)pCor); +} + +inline CORCOMPILE_HEADER *PEDecoder::FindNativeHeader() const +{ + CONTRACT(CORCOMPILE_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(HasNativeHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN PTR_CORCOMPILE_HEADER(GetDirectoryData(&GetCorHeader()->ManagedNativeHeader)); +} + +inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(rva >= rangeBase); + CHECK(rva <= rangeBase + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(CheckOverflow(rva, size)); + CHECK(rva >= rangeBase); + CHECK(rva + size <= rangeBase + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); + CHECK(dac_cast(pointer) >= dac_cast(rangeBase)); + CHECK(dac_cast(pointer) <= dac_cast(rangeBase) + rangeSize); + CHECK_OK; +} + +inline CHECK PEDecoder::CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + CHECK(CheckOverflow(rangeBase, rangeSize)); + CHECK(CheckOverflow(pointer, size)); + CHECK(dac_cast(pointer) >= dac_cast(rangeBase)); + CHECK(dac_cast(pointer) + size <= dac_cast(rangeBase) + rangeSize); + CHECK_OK; +} + +inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + DWORD dwKind=0,dwMachine=0; + if(HasContents() && HasNTHeaders()) + { + dwMachine = GetMachine(); + + BOOL fIsPE32Plus = !Has32BitNTHeaders(); + + if (fIsPE32Plus) + dwKind |= (DWORD)pe32Plus; + + if (HasCorHeader()) + { + IMAGE_COR20_HEADER * pCorHdr = GetCorHeader(); + if(pCorHdr != NULL) + { + DWORD dwCorFlags = pCorHdr->Flags; + + if (dwCorFlags & VAL32(COMIMAGE_FLAGS_ILONLY)) + { + dwKind |= (DWORD)peILonly; +#ifdef _WIN64 + // compensate for shim promotion of PE32/ILONLY headers to PE32+ on WIN64 + if (fIsPE32Plus && (GetMachine() == IMAGE_FILE_MACHINE_I386)) + dwKind &= ~((DWORD)pe32Plus); +#endif + } + + if (COR_IS_32BIT_REQUIRED(dwCorFlags)) + dwKind |= (DWORD)pe32BitRequired; + else if (COR_IS_32BIT_PREFERRED(dwCorFlags)) + dwKind |= (DWORD)pe32BitPreferred; + + // compensate for MC++ peculiarity + if(dwKind == 0) + dwKind = (DWORD)pe32BitRequired; + } + else + { + dwKind |= (DWORD)pe32Unmanaged; + } + + if (HasReadyToRunHeader()) + { + if (dwMachine == IMAGE_FILE_MACHINE_NATIVE_NI) + { + // Supply the original machine type to the assembly binder + dwMachine = IMAGE_FILE_MACHINE_NATIVE; + } + + if ((GetReadyToRunHeader()->Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) + { + // Supply the original PEKind/Machine to the assembly binder to make the full assembly name look like the original + dwKind = peILonly; + dwMachine = IMAGE_FILE_MACHINE_I386; + } + } + } + else + { + dwKind |= (DWORD)pe32Unmanaged; + } + } + + *pdwPEKind = dwKind; + *pdwMachine = dwMachine; +} + +inline BOOL PEDecoder::IsPlatformNeutral() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + DWORD dwKind, dwMachine; + GetPEKindAndMachine(&dwKind, &dwMachine); + return ((dwKind & (peILonly | pe32Plus | pe32BitRequired)) == peILonly) && (dwMachine == IMAGE_FILE_MACHINE_I386); +} + +inline BOOL PEDecoder::HasReadyToRunHeader() const +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + if (m_flags & FLAG_HAS_NO_READYTORUN_HEADER) + return FALSE; + + if (m_pReadyToRunHeader != NULL) + return TRUE; + + return FindReadyToRunHeader() != NULL; +} + +inline READYTORUN_HEADER * PEDecoder::GetReadyToRunHeader() const +{ + CONTRACT(READYTORUN_HEADER *) + { + INSTANCE_CHECK; + PRECONDITION(CheckNTHeaders()); + PRECONDITION(HasCorHeader()); + PRECONDITION(HasReadyToRunHeader()); + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(CheckPointer(RETVAL)); + SUPPORTS_DAC; + CANNOT_TAKE_LOCK; + } + CONTRACT_END; + + if (m_pReadyToRunHeader != NULL) + RETURN m_pReadyToRunHeader; + + RETURN FindReadyToRunHeader(); +} + +#endif // _PEDECODER_INL_ diff --git a/lib/coreclr/src/inc/peinformation.h b/lib/coreclr/src/inc/peinformation.h new file mode 100644 index 0000000000..8b5ac19c5a --- /dev/null +++ b/lib/coreclr/src/inc/peinformation.h @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// PEInformation.h +// + +// -------------------------------------------------------------------------------- + +#ifndef PEINFORMATION_H +#define PEINFORMATION_H + +#ifndef PEKIND_ENUM_DEFINED +#define PEKIND_ENUM_DEFINED +// This must match the definition of pekind in fusion.idl +typedef enum _tagPEKIND +{ + peNone = 0x00000000, + peMSIL = 0x00000001, + peI386 = 0x00000002, + peIA64 = 0x00000003, + peAMD64 = 0x00000004, + peARM = 0x00000005, + peARM64 = 0x00000006, + peInvalid = 0xffffffff +} PEKIND; + +#endif + + +inline bool IsPE64(PEKIND x) +{ + return ( (x == peIA64) || (x == peAMD64) || (x == peARM64) ); +} + +inline bool IsPE32(PEKIND x) +{ + return ( (x == peI386) || (x == peARM) ); +} + +inline bool IsPEMSIL(PEKIND x) +{ + return ( (x == peMSIL) ); +} + +#ifdef _WIN64 +inline bool IsProcess32() { return false; } +#else +inline bool IsProcess32() { return true; } +#endif + +#if defined(_TARGET_X86_) +inline PEKIND TargetNativePEKIND() { return peI386; } +#elif defined(_TARGET_AMD64_) +inline PEKIND TargetNativePEKIND() { return peAMD64; } +#elif defined(_TARGET_ARM_) +inline PEKIND TargetNativePEKIND() { return peARM; } +#elif defined(_TARGET_ARM64_) +inline PEKIND TargetNativePEKIND() { return peARM64; } +#else +#error Need to define valid TargetNativePEKIND() +#endif + +STDAPI RuntimeIsValidAssemblyOnThisPlatform_CheckProcessorArchitecture(PEKIND processorArchitecture, BOOL bForInstall); + +//***************************************************************************** +// Intreprets CLRPeKind and dwImageType to get PeKind as per the CLRBitness +// API, CLRPeKind and dwImageType can be recoved from GetPEKind() if you +// have the metadata, or retrieved directly from the headers as per the +// implementation in shim.cpp:_CorValidateImage. +//***************************************************************************** +HRESULT TranslatePEToArchitectureType(CorPEKind CLRPeKind, DWORD dwImageType, PEKIND * PeKind); +HRESULT TranslatePEToArchitectureType(CorPEKind CLRPeKind, DWORD dwImageType, DWORD dwAssemblyFlags, PEKIND * PeKind); + +#endif // PEINFORMATION_H diff --git a/lib/coreclr/src/inc/perflog.h b/lib/coreclr/src/inc/perflog.h new file mode 100644 index 0000000000..84578d36a8 --- /dev/null +++ b/lib/coreclr/src/inc/perflog.h @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- +// PerfLog.h + +// Internal interface for logging perfromance data. Currently, two types of logging +// formats are supported, Pretty print for stdout and perf automation friendly +// format. +// The logging code is compiled in for retail builds but logs are generated only if +// PERF_OUTPUT environment variable is set. (This can be changed to a registry entry +// if we want perf logs on CE or other platforms that don't supprt env vars.)) +//----------------------------------------------------------------------------- + +#include "contract.h" + +#ifndef _PERFLOG_H_ +#define _PERFLOG_H_ + +#if !defined(_WIN64) && !defined(DACCESS_COMPILE) +#define ENABLE_PERF_LOG +#else +#undef ENABLE_PERF_LOG +#endif + +// Also disable Perf logging code if there's a explicite define to do so in SOURCES +// file or another hdr file. This provides one point where all perf log related baggage +// can be avoided in the build. +#if defined(DISABLE_PERF_LOG) +#undef ENABLE_PERF_LOG +#endif + + +//----------------------------------------------------------------------------- +// PERFLOG is the public interface that should be used from EE source to log perf data. +// If +#if !defined (ENABLE_PERF_LOG) +#define PERFLOG(x) +#else +#define PERFLOG(x) do {if (PerfLog::PerfLoggingEnabled()) PerfLog::Log x;} while (0) +#endif + +//============================================================================= +// ALL THE PERF LOG CODE IS COMPILED ONLY IF THE ENABLE_PERF_LOG WAS DEFINED. +#if defined (ENABLE_PERF_LOG) +//============================================================================= +//----------------------------------------------------------------------------- +// Static allocation of logging related memory, avoid dynamic allocation to +// skew perf numbers. +#define PRINT_STR_LEN 256 // Temp work space +#define MAX_CHARS_UNIT 20 +#define MAX_CHARS_DIRECTION 6 + +//----------------------------------------------------------------------------- +// ENUM of units for all kinds of perf data the we might get. Grow this as needed. +// **keep in sync *** with the array of strings defined in PerfLog.cpp +typedef enum +{ + COUNT = 0, + SECONDS, + BYTES, + KBYTES, + KBYTES_PER_SEC, + CYCLES, + MAX_UNITS_OF_MEASURE +} UnitOfMeasure; + +//----------------------------------------------------------------------------- +// Widechar strings representing the above units. *** Keep in sync *** with the +// array defined in PerfLog.cpp +extern const wchar_t * const wszUnitOfMeasureDescr[MAX_UNITS_OF_MEASURE]; + +//----------------------------------------------------------------------------- +// Widechar strings representing the "direction" property of above units. +// *** Keep in sync *** with the array defined in PerfLog.cpp +// "Direction" property is false if an increase in the value of the counter indicates +// a degrade. +// "Direction" property is true if an increase in the value of the counter indicates +// an improvement. +extern const wchar_t * const wszIDirection[MAX_UNITS_OF_MEASURE]; + +//----------------------------------------------------------------------------- +// Namespace for perf log. Don't create perf log objects (private ctor). +class PerfLog +{ +public: + + // Called during EEStartup + static void PerfLogInitialize(); + + // Called during EEShutdown + static void PerfLogDone(); + + // Perf logging is enabled if the env var PERF_LOG is set. + static int PerfLoggingEnabled () { LIMITED_METHOD_CONTRACT; return m_fLogPerfData; } + + // Perf automation format is desired. + static bool PerfAutomationFormat () { LIMITED_METHOD_CONTRACT; return m_perfAutomationFormat; } + + // CSV format is desired. + static bool CommaSeparatedFormat () { LIMITED_METHOD_CONTRACT; return m_commaSeparatedFormat; } + + // Overloaded member functions to print different data types. Grow as needed. + // wszName is the name of thet perf counter, val is the perf counter value, + static void Log(__in_z wchar_t const *wszName, UINT val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); + static void Log(__in_z wchar_t const *wszName, UINT64 val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); + static void Log(__in_z wchar_t const *wszName, double val, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); + +private: + PerfLog(); + ~PerfLog(); + + // Helper routine to hide some details of the perf automation + static void OutToPerfFile(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); + + // Helper routine to hide some details of output to stdout + static void OutToStdout(__in_z const wchar_t *wszName, UnitOfMeasure unit, __in_opt const wchar_t *wszDescr = 0); + + // Perf log initialized ? + static bool m_perfLogInit; + + // Output in perf automation format ? + static bool m_perfAutomationFormat; + + // Output in csv format ? + static bool m_commaSeparatedFormat; + + // Temp storage to convert wide char to multibyte for file IO. + static wchar_t m_wszOutStr_1[PRINT_STR_LEN]; + static DWORD m_dwWriteByte; + + // State of the env var PERF_OUTPUT + static int m_fLogPerfData; + + // Open handle of the file which is used by the perf auotmation. (Currently + // its at C:\PerfData.data + static HANDLE m_hPerfLogFileHandle; +}; + +#endif // ENABLE_PERF_LOG + +#endif //_PERFLOG_H_ diff --git a/lib/coreclr/src/inc/pesectionman.h b/lib/coreclr/src/inc/pesectionman.h new file mode 100644 index 0000000000..f031ca34bf --- /dev/null +++ b/lib/coreclr/src/inc/pesectionman.h @@ -0,0 +1,213 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// Section Manager for portable executables +// Common to both Memory Only and Static (EXE making) code + + +#ifndef PESectionMan_H +#define PESectionMan_H + +#include "windef.h" + +#include "ceegen.h" +#include "blobfetcher.h" + +class PESection; +struct PESectionReloc; + +struct _IMAGE_SECTION_HEADER; + +class PESectionMan +{ +public: + + virtual ~PESectionMan() {} + + HRESULT Init(); + HRESULT Cleanup(); + + // Finds section with given name, or creates a new one + HRESULT getSectionCreate( + const char *name, + unsigned flags, // IMAGE_SCN_* flags. eg. IMAGE_SCN_CNT_INITIALIZED_DATA + PESection **section); + + // Since we allocate, we must delete (Bug in VC, see knowledge base Q122675) + void sectionDestroy(PESection **section); + + // Apply all the relocs for in memory conversion + HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); + + HRESULT cloneInstance(PESectionMan *destination); + +protected: + + // Finds section with given name. returns 0 if not found + virtual PESection *getSection(const char *name); + + // Create a new section + virtual HRESULT newSection( + const char *name, + PESection **section, + unsigned flags = sdNone, + unsigned estSize = 0x10000, + unsigned estRelocs = 1); + + // Keep proctected & no accessors, so that derived class PEWriter + // is the ONLY one with access + + PESection **sectStart; + PESection **sectCur; + PESection **sectEnd; +}; // class PESectionMan + +/*************************************************************** + * This represents a section of a ICeeFileGen. Multiple sections + * can be created with pointers to one another. These will + * automatically get fixed up when the ICeeFileGen is "baked". + * + * It is implemented using CBlobFetcher as a list of blobs. + * Thus it can grow arbitrarily. At the same time, it can appear + * as a flat consecutive piece of memory which can be indexed into + * using offsets. + */ + +class PESection : public CeeSectionImpl { + public: + // bytes in this section at present + unsigned dataLen(); + + // Apply all the relocs for in memory conversion + HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); + + // get a block to write on (use instead of write to avoid copy) + char* getBlock(unsigned len, unsigned align=1); + + // writes 'val' (which is offset into section 'relativeTo') + // and adds a relocation fixup for that section + void writeSectReloc(unsigned val, CeeSection& relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // Indicates that the DWORD at 'offset' in the current section should + // have the base of section 'relativeTo' added to it + HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // If relativeTo is NULL, it is treated as a base reloc. + // ie. the value only needs to be fixed at load time if the module gets rebased. + HRESULT addSectReloc(unsigned offset, PESection *relativeTo, + CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra=0); + + // Add a base reloc for the given offset in the current section + HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, + CeeSectionRelocExtra *extra = 0); + + // section name + unsigned char *name() { + LIMITED_METHOD_CONTRACT; + return (unsigned char *) m_name; + } + + // section flags + unsigned flags() { + LIMITED_METHOD_CONTRACT; + return m_flags; + } + + // virtual base + unsigned getBaseRVA() { + LIMITED_METHOD_CONTRACT; + return m_baseRVA; + } + + // return the dir entry for this section + int getDirEntry() { + LIMITED_METHOD_CONTRACT; + return dirEntry; + } + // this section will be directory entry 'num' + HRESULT directoryEntry(unsigned num); + + // Indexes offset as if this were an array + // Returns a pointer into the correct blob + virtual char * computePointer(unsigned offset) const; + + // Checks to see if pointer is in section + virtual BOOL containsPointer(__in char *ptr) const; + + // Given a pointer pointing into this section, + // computes an offset as if this were an array + virtual unsigned computeOffset(__in char *ptr) const; + + // Make 'destination' a copy of the current PESection + HRESULT cloneInstance(PESection *destination); + + // Cause the section to allocate memory in smaller chunks + void SetInitialGrowth(unsigned growth); + + virtual ~PESection(); +private: + + // purposely not defined, + PESection(); + + // purposely not defined, + PESection(const PESection&); + + // purposely not defined, + PESection& operator=(const PESection& x); + + // this dir entry points to this section + int dirEntry; + +protected: + friend class PEWriter; + friend class PEWriterSection; + friend class PESectionMan; + + PESection(const char* name, unsigned flags, + unsigned estSize, unsigned estRelocs); + + // Blob fetcher handles getBlock() and fetching binary chunks. + CBlobFetcher m_blobFetcher; + + PESectionReloc* m_relocStart; + PESectionReloc* m_relocCur; + PESectionReloc* m_relocEnd; + + // These will be set while baking (finalizing) the file + unsigned m_baseRVA; // RVA into the file of this section. + unsigned m_filePos; // Start offset into the file (treated as a data image) + unsigned m_filePad; // Padding added to the end of the section for alignment + + char m_name[8+6]; // extra room for digits + unsigned m_flags; + + struct _IMAGE_SECTION_HEADER* m_header; // Corresponding header. Assigned after link() +}; + +/***************************************************************/ +/* implementation section */ + +inline HRESULT PESection::directoryEntry(unsigned num) { + WRAPPER_NO_CONTRACT; + TESTANDRETURN(num < 16, E_INVALIDARG); + dirEntry = num; + return S_OK; +} + +// This remembers the location where a reloc needs to be applied. +// It is relative to the contents of a PESection + +struct PESectionReloc { + CeeSectionRelocType type; // type of reloc + unsigned offset; // offset within the current PESection where the reloc is to be applied + CeeSectionRelocExtra extra; + PESection* section; // target PESection. NULL implies that the target is a fixed address outside the module +}; + +#endif // #define PESectionMan_H diff --git a/lib/coreclr/src/inc/posterror.h b/lib/coreclr/src/inc/posterror.h new file mode 100644 index 0000000000..816d14e096 --- /dev/null +++ b/lib/coreclr/src/inc/posterror.h @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// UtilCode.h +// +// Utility functions implemented in UtilCode.lib. +// + +//***************************************************************************** + +#ifndef __PostError_h__ +#define __PostError_h__ + +#include "switches.h" + +//***************************************************************************** +// This function will post an error for the client. If the LOWORD(hrRpt) can +// be found as a valid error message, then it is loaded and formatted with +// the arguments passed in. If it cannot be found, then the error is checked +// against FormatMessage to see if it is a system error. System errors are +// not formatted so no add'l parameters are required. If any errors in this +// process occur, hrRpt is returned for the client with no error posted. +//***************************************************************************** +extern "C" +HRESULT __cdecl PostError( // Returned error. + HRESULT hrRpt, // Reported error. + ...); // Error arguments. + +extern "C" +HRESULT __cdecl PostErrorVA( // Returned error. + HRESULT hrRpt, // Reported error. + va_list marker); // Error arguments. + +//***************************************************************************** +// This function formats an error message, but doesn't fill the IErrorInfo. +//***************************************************************************** +HRESULT __cdecl FormatRuntimeErrorVa( + __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format. + ULONG cchMsg, // Size of buffer, characters. + HRESULT hrRpt, // The HR to report. + va_list marker); // Optional args. + +HRESULT __cdecl FormatRuntimeError( + __out_ecount(cchMsg) WCHAR *rcMsg, // Buffer into which to format. + ULONG cchMsg, // Size of buffer, characters. + HRESULT hrRpt, // The HR to report. + ...); // Optional args. + +#endif // __PostError_h__ diff --git a/lib/coreclr/src/inc/predeftlsslot.h b/lib/coreclr/src/inc/predeftlsslot.h new file mode 100644 index 0000000000..c2c59f2adb --- /dev/null +++ b/lib/coreclr/src/inc/predeftlsslot.h @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +#ifndef __PREDEFTLSSLOT_H__ +#define __PREDEFTLSSLOT_H__ + +// ****************************************************************************** +// WARNING!!!: These enums are used by SOS in the diagnostics repo. Values should +// added or removed in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/predeftlsslot.h +// ****************************************************************************** + +// And here are the predefined slots for accessing TLS from various DLLs of the CLR. +// Note that we want to support combinations of Debug and Retail DLLs for testing +// purposes, so we burn the slots into the retail EE even if a debug CLR dll needs +// them. +enum PredefinedTlsSlots +{ + TlsIdx_StrongName, + TlsIdx_JitPerf, + TlsIdx_JitX86Perf, + TlsIdx_JitLogEnv, + TlsIdx_AssertDlgStatus, // Whether the thread is displaying an assert dialog + TlsIdx_StressLog, + TlsIdx_CantStopCount, // Can't-stop counter for any thread + TlsIdx_Check, + TlsIdx_ForbidGCLoaderUseCount, + TlsIdx_ClrDebugState, // Pointer to ClrDebugState* structure + TlsIdx_StressThread, + + // Add more indices here. + TlsIdx_ThreadType, // bit flags to indicate special thread's type + TlsIdx_OwnedCrstsChain, // slot to store the Crsts owned by this thread + TlsIdx_CantAllocCount, //Can't allocate memory on heap in this thread + + // A transient thread value that indicates this thread is currently walking its stack + // or the stack of another thread. This value is useful to help short-circuit + // some problematic checks in the loader, guarantee that types & assemblies + // encountered during the walk must already be loaded, and provide information to control + // assembly loading behavior during stack walks. + // + // This value is set around the main portions of the stack walk (as those portions may + // enter the type & assembly loaders). This is also explicitly cleared while the + // walking thread calls the stackwalker callback or needs to execute managed code, as + // such calls may execute arbitrary code unrelated to the actual stack walking, and + // may never return, in the case of exception stackwalk callbacks. + TlsIdx_StackWalkerWalkingThread, // Thread* that the stack walker is currently walking. + + // Save the last exception info. Sometimes we need this info in our EX_CATCH, such as for SO. + // It will be better if VC can supply this in catch(...) block. + // !!! These data may become stale. Use it only inside exception handling code. + // !!! Please access these fields through GetCurrentExceptionPointers which validates the data to some level. + TlsIdx_EXCEPTION_CODE, + TlsIdx_PEXCEPTION_RECORD, + TlsIdx_PCONTEXT, + + MAX_PREDEFINED_TLS_SLOT +}; + +enum TlsThreadTypeFlag // flag used for thread type in Tls data +{ + ThreadType_GC = 0x00000001, + ThreadType_Timer = 0x00000002, + ThreadType_Gate = 0x00000004, + ThreadType_DbgHelper = 0x00000008, + ThreadType_Shutdown = 0x00000010, + ThreadType_DynamicSuspendEE = 0x00000020, + ThreadType_Finalizer = 0x00000040, + ThreadType_ADUnloadHelper = 0x00000200, + ThreadType_ShutdownHelper = 0x00000400, + ThreadType_Threadpool_IOCompletion = 0x00000800, + ThreadType_Threadpool_Worker = 0x00001000, + ThreadType_Wait = 0x00002000, + ThreadType_ProfAPI_Attach = 0x00004000, + ThreadType_ProfAPI_Detach = 0x00008000, + ThreadType_ETWRundownThread = 0x00010000, + ThreadType_GenericInstantiationCompare= 0x00020000, // Used to indicate that the thread is determining if a generic instantiation in an ngen image matches a lookup. +}; + +static_assert(TlsIdx_ThreadType == 11, "SOS in diagnostics repo has a dependency on this value."); + +#endif + diff --git a/lib/coreclr/src/inc/prettyprintsig.h b/lib/coreclr/src/inc/prettyprintsig.h new file mode 100644 index 0000000000..adab46ee0f --- /dev/null +++ b/lib/coreclr/src/inc/prettyprintsig.h @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +//***************************************************************************** +// This code supports formatting a method and it's signature in a friendly +// and consistent format. +// +//***************************************************************************** + +#ifndef __PrettyPrintSig_h__ +#define __PrettyPrintSig_h__ + +#include + +class CQuickBytes; + +// +// The return value is either NULL or a null-terminated ASCII string +// + +//--------------------------------------------------------------------------------------- +// +// Prints a signature in a human readable format. +// No one should use this function. This exists strictly for backwards compatibility with external formats. +// +// Arguments: +// sigPtr - Method/field sig to convert +// sigLen - length of sig +// name - the name of the method for this sig. Can be L"" +// scratch - scratch buffer to use +// pIMDI - Import api to use. +// +// Return Value: +// The formatted string. +// +// Assumptions: +// None +// +// Notes: +// Dev's SHOULD NOT create new callers to this function. Use +// code:PrettyPrintSig in formatype.h instead. This function exists for +// legacy support in the CLR. There are places that depend on the format +// of this string. +// + +LPCWSTR PrettyPrintSigLegacy( + PCCOR_SIGNATURE sigPtr, // Method/field sig to convert + unsigned sigLen, // length of sig + LPCWSTR name, // the name of the method for this sig. Can be L"" + CQuickBytes *scratch, // scratch buffer to use + IMetaDataImport *pIMDI); // Import api to use. + +struct IMDInternalImport; + +//--------------------------------------------------------------------------------------- +// +// Prints a signature in a human readable format. +// No one should use this function. This exists strictly for backwards compatibility with external formats. +// +// Arguments: +// sigPtr - Method/field sig to convert +// sigLen - length of sig +// name - the name of the method for this sig. Can be L"" +// out - The buffer in which to write the pretty printed string. +// pIMDI - Import api to use. +// +// Return Value: +// An HRESULT and the formatted string is in out as a unicode string. +// +// Assumptions: +// None +// +// Notes: +// Dev's SHOULD NOT create new callers to this function. Use +// code:PrettyPrintSig in formattype.h instead. This function exists for +// legacy support in the CLR. There are places that depend on the format +// of this string. +// +HRESULT PrettyPrintSigInternalLegacy( // S_OK or error. + PCCOR_SIGNATURE sigPtr, // sig to convert, + unsigned sigLen, // length of sig + LPCSTR name, // can be "", the name of the method for this sig + CQuickBytes *out, // where to put the pretty printed string + IMDInternalImport *pIMDI); // Import api to use. + +// +// On success, the null-terminated ASCII string is in "out.Ptr()" +// + +#endif // __PrettyPrintSig_h__ diff --git a/lib/coreclr/src/inc/profilepriv.h b/lib/coreclr/src/inc/profilepriv.h new file mode 100644 index 0000000000..acec829b15 --- /dev/null +++ b/lib/coreclr/src/inc/profilepriv.h @@ -0,0 +1,162 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// ProfilePriv.h +// + +// +// Structures, etc. used by the Profiling API and throughout the EE +// + +// ====================================================================================== + +#ifndef _ProfilePriv_h_ +#define _ProfilePriv_h_ + + +// Forward declarations +class EEToProfInterfaceImpl; +class Object; +struct ScanContext; + +#if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) +#ifndef PROFILING_SUPPORTED_DATA +#define PROFILING_SUPPORTED_DATA 1 +#endif // PROFILING_SUPPORTED_DATA + +#include "corprof.h" + +//--------------------------------------------------------------------------------------- +// Enumerates the various init states of profiling. +// +// *** NOTE: The order is important here, as some of the status checks (e.g., +// CORProfilerPresentOrInitializing) use ">" with these enum values. *** + +enum ProfilerStatus +{ + kProfStatusNone = 0, // No profiler running. + kProfStatusDetaching = 1, // Prof was running, is now detaching, but still loaded + kProfStatusInitializingForStartupLoad = 2, // Prof ready for (or in) its Initialize callback + kProfStatusInitializingForAttachLoad = 3, // Prof ready for (or in) its InitializeForAttach callback + kProfStatusActive = 4, // Prof completed initialization and is actively running + kProfStatusPreInitialize = 5, // Prof is in LoadProfiler, but initialization has yet to occur +}; + +class CurrentProfilerStatus +{ +private: + // Why volatile? + // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization + Volatile m_profStatus; + +public: + void Init(); + ProfilerStatus Get(); + void Set(ProfilerStatus profStatus); +}; + +// --------------------------------------------------------------------------------------- +// Global struct that lets the EE see the load status of the profiler, and provides a +// pointer (pProfInterface) through which profiler calls can be made +// +// When you are adding new session, please refer to +// code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details. +struct ProfControlBlock +{ + // **** IMPORTANT!! **** + // All uses of pProfInterface must be properly synchronized to avoid the profiler + // from detaching while the EE attempts to call into it. The recommended way to do + // this is to use the (lockless) BEGIN_PIN_PROFILER / END_PIN_PROFILER macros. See + // code:BEGIN_PIN_PROFILER for instructions. For full details on how the + // synchronization works, see + // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization + VolatilePtr pProfInterface; + // **** IMPORTANT!! **** + + DWORD dwEventMask; // Original low event mask bits + DWORD dwEventMaskHigh; // New high event mask bits + CurrentProfilerStatus curProfStatus; + BOOL fGCInProgress; + BOOL fBaseSystemClassesLoaded; + +#ifdef PROF_TEST_ONLY_FORCE_ELT_DATA + // #TestOnlyELT This implements a test-only (and debug-only) hook that allows a test + // profiler to ensure enter/leave/tailcall is enabled on startup even though no + // profiler is loaded on startup. This allows an attach profiler to use ELT to build + // shadow stacks for the sole purpose of verifying OTHER areas of the profiling API + // (e.g., stack walking). When this BOOL is TRUE, the JIT will insert calls to the + // slow-path profiling API enter/leave/tailcall hooks, which will forward the call to + // a profiler if one is loaded (and do nothing otherwise). + // + // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information + // on how the test hooks lift restrictions normally in place for the Info functions. + BOOL fTestOnlyForceEnterLeave; +#endif + +#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA + // #TestOnlyObjectAllocated This implements a test-only (and debug-only) hook that allows + // a test profiler to ensure ObjectAllocated callback is enabled on startup even though no + // profiler is loaded on startup. This allows an attach profiler to use ObjectAllocated + // callback for the sole purpose of verifying OTHER GC areas of the profiling API + // (e.g., constructing a object graph). When this BOOL is TRUE, the JIT will use special + // version of new allocators that issue object allocation notifications, which will forward + // the notifications to a profiler if one is loaded (and do nothing otherwise). + // + // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information + // on how the test hooks lift restrictions normally in place for the Info functions. + BOOL fTestOnlyForceObjectAllocated; +#endif + +#ifdef _DEBUG + // Test-only, debug-only code to allow attaching profilers to call ICorProfilerInfo inteface, + // which would otherwise be disallowed for attaching profilers + BOOL fTestOnlyEnableICorProfilerInfo; +#endif // _DEBUG + + // Whether we've turned off concurrent GC during attach + BOOL fConcurrentGCDisabledForAttach; + + Volatile fProfControlBlockInitialized; + + Volatile fProfilerRequestedRuntimeSuspend; + + void Init(); + void ResetPerSessionStatus(); +}; + + +GVAL_DECL(ProfControlBlock, g_profControlBlock); + +// Provides definitions of the CORProfilerTrack* functions that test whether a profiler +// is active and responding to various callbacks +#include "profilepriv.inl" + +//--------------------------------------------------------------- +// Bit flags used to track profiler callback execution state, such as which +// ICorProfilerCallback method we're currently executing. These help us enforce the +// invariants of which calls a profiler is allowed to make at given times. These flags +// are stored in Thread::m_profilerCallbackState. +// +// For now, we ensure: +// * Only asynchronous-safe calls are made asynchronously (i.e., are made from +// outside of profiler callbacks). +// * GC_TRIGGERS info methods are not called from GC_NOTRIGGER callbacks +// +// Later, we may choose to enforce even more refined call trees and add more flags. +#define COR_PRF_CALLBACKSTATE_INCALLBACK 0x1 +#define COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE 0x2 +#define COR_PRF_CALLBACKSTATE_FORCEGC_WAS_CALLED 0x4 +#define COR_PRF_CALLBACKSTATE_REJIT_WAS_CALLED 0x8 +// +//--------------------------------------------------------------- + +#endif // defined(PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) + +// This is the helper callback that the gc uses when walking the heap. +bool HeapWalkHelper(Object* pBO, void* pv); +void ScanRootsHelper(Object* pObj, Object** ppRoot, ScanContext *pSC, uint32_t dwUnused); +bool AllocByClassHelper(Object* pBO, void* pv); + +#endif // _ProfilePriv_h_ + diff --git a/lib/coreclr/src/inc/profilepriv.inl b/lib/coreclr/src/inc/profilepriv.inl new file mode 100644 index 0000000000..5a0513f4a3 --- /dev/null +++ b/lib/coreclr/src/inc/profilepriv.inl @@ -0,0 +1,864 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// ProfilePriv.inl +// + +// +// Inlined functions used by the Profiling API and throughout the EE. Most notably are +// the CORProfilerTrack* functions that test whether a profiler is active and responding +// to various callbacks +// + +// ====================================================================================== +#ifndef _ProfilePriv_inl_ +#define _ProfilePriv_inl_ + +#include "eetoprofinterfaceimpl.h" +#ifdef PROFILING_SUPPORTED +#include "profilinghelper.h" +BOOL CORProfilerBypassSecurityChecks(); +#endif // PROFILING_SUPPORTED + +//--------------------------------------------------------------------------------------- +// CurrentProfilerStatus +//--------------------------------------------------------------------------------------- + +inline void CurrentProfilerStatus::Init() +{ + LIMITED_METHOD_CONTRACT; + m_profStatus = kProfStatusNone; +} + +inline ProfilerStatus CurrentProfilerStatus::Get() +{ + LIMITED_METHOD_DAC_CONTRACT; + return m_profStatus; +} + +//--------------------------------------------------------------------------------------- +// ProfControlBlock +//--------------------------------------------------------------------------------------- + +inline void ProfControlBlock::Init() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + curProfStatus.Init(); + + fGCInProgress = FALSE; + fBaseSystemClassesLoaded = FALSE; +#ifdef PROF_TEST_ONLY_FORCE_ELT + fTestOnlyForceEnterLeave = FALSE; +#endif + +#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED + fTestOnlyForceObjectAllocated = FALSE; +#endif + +#ifdef _DEBUG + fTestOnlyEnableICorProfilerInfo = FALSE; +#endif // _DEBUG + + fConcurrentGCDisabledForAttach = FALSE; + + ResetPerSessionStatus(); + + fProfControlBlockInitialized = TRUE; + + fProfilerRequestedRuntimeSuspend = FALSE; +} + +// Reset those variables that is only for the current attach session +inline void ProfControlBlock::ResetPerSessionStatus() +{ + LIMITED_METHOD_CONTRACT; + + pProfInterface = NULL; + dwEventMask = COR_PRF_MONITOR_NONE; + dwEventMaskHigh = COR_PRF_HIGH_MONITOR_NONE; +} + +//--------------------------------------------------------------------------------------- +// Inlined helpers used throughout the runtime to check for the profiler's load status +// and what features it enabled callbacks for. +//--------------------------------------------------------------------------------------- + + +// CORProfilerPresent() returns whether or not a CLR Profiler is actively loaded +// (meaning it's initialized and ready to receive callbacks). +inline BOOL CORProfilerPresent() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return ((&g_profControlBlock)->curProfStatus.Get() == kProfStatusActive); +} + +// These return whether a CLR Profiler is actively loaded AND has requested the +// specified callback or functionality + +inline BOOL CORProfilerFunctionIDMapperEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ( + ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper() != NULL) || + ((&g_profControlBlock)->pProfInterface->GetFunctionIDMapper2() != NULL) + )); +} + +inline BOOL CORProfilerTrackJITInfo() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_JIT_COMPILATION)); +} + +inline BOOL CORProfilerTrackCacheSearches() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CACHE_SEARCHES)); +} + +inline BOOL CORProfilerTrackModuleLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_MODULE_LOADS)); +} + +inline BOOL CORProfilerTrackAssemblyLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ASSEMBLY_LOADS)); +} + +inline BOOL CORProfilerTrackAppDomainLoads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_APPDOMAIN_LOADS)); +} + +inline BOOL CORProfilerTrackThreads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_THREADS)); +} + +inline BOOL CORProfilerTrackClasses() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLASS_LOADS)); +} + +inline BOOL CORProfilerTrackGC() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_GC)); +} + +inline BOOL CORProfilerTrackAllocationsEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return + ( +#ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED + (&g_profControlBlock)->fTestOnlyForceObjectAllocated || +#endif + (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_OBJECT_ALLOCATED)) + ); +} + +inline BOOL CORProfilerTrackAllocations() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return + (CORProfilerTrackAllocationsEnabled() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED)); +} + +inline BOOL CORProfilerTrackLargeAllocations() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return + (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); +} + +inline BOOL CORProfilerEnableRejit() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_REJIT)); +} + +inline BOOL CORProfilerTrackExceptions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_EXCEPTIONS)); +} + +inline BOOL CORProfilerTrackCLRExceptions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CLR_EXCEPTIONS)); +} + +inline BOOL CORProfilerTrackTransitions() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CODE_TRANSITIONS)); +} + +inline BOOL CORProfilerTrackEnterLeave() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + +#ifdef PROF_TEST_ONLY_FORCE_ELT + if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) + return TRUE; +#endif // PROF_TEST_ONLY_FORCE_ELT + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_ENTERLEAVE)); +} + +inline BOOL CORProfilerTrackCCW() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_CCW)); +} + +inline BOOL CORProfilerTrackRemoting() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING)); +} + +inline BOOL CORProfilerTrackRemotingCookie() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return + (CORProfilerPresent() && + (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_COOKIE) + == COR_PRF_MONITOR_REMOTING_COOKIE)); +} + +inline BOOL CORProfilerTrackRemotingAsync() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return + (CORProfilerPresent() && + (((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_REMOTING_ASYNC) + == COR_PRF_MONITOR_REMOTING_ASYNC)); +} + +inline BOOL CORProfilerTrackSuspends() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_SUSPENDS)); +} + +inline BOOL CORProfilerDisableInlining() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_INLINING)); +} + +inline BOOL CORProfilerJITMapEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_JIT_MAPS)); +} + +inline BOOL CORProfilerDisableOptimizations() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_OPTIMIZATIONS)); +} + +inline BOOL CORProfilerUseProfileImages() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + +#ifdef PROF_TEST_ONLY_FORCE_ELT + if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) + return TRUE; +#endif // PROF_TEST_ONLY_FORCE_ELT + + if (!CORProfilerPresent()) + return FALSE; + + if (((&g_profControlBlock)->dwEventMask & + COR_PRF_REQUIRE_PROFILE_IMAGE) == 0) + return FALSE; + + return TRUE; +} + +inline BOOL CORProfilerDisableAllNGenImages() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_DISABLE_ALL_NGEN_IMAGES)); +} + +inline BOOL CORProfilerTrackConditionalWeakTableElements() +{ + LIMITED_METHOD_DAC_CONTRACT; + + return CORProfilerTrackGC() && (&g_profControlBlock)->pProfInterface->IsCallback5Supported(); +} + +// CORProfilerPresentOrInitializing() returns nonzero iff a CLR Profiler is actively +// loaded and ready to receive callbacks OR a CLR Profiler has loaded just enough that it +// is ready to receive (or is currently executing inside) its Initialize() callback. +// Typically, you'll want to use code:CORProfilerPresent instead of this. But there is +// some internal profiling API code that wants to test for event flags for a profiler +// that may still be initializing, and this function is appropriate for that code. +inline BOOL CORProfilerPresentOrInitializing() +{ + LIMITED_METHOD_DAC_CONTRACT; + return ((&g_profControlBlock)->curProfStatus.Get() > kProfStatusDetaching); +} + +// These return whether a CLR Profiler has requested the specified functionality. +// +// Note that, unlike the above functions, a profiler that's not done loading (and is +// still somewhere in the initialization phase) still counts. This is only safe because +// these functions are not used to determine whether to issue a callback. These functions +// are used primarily during the initialization path to choose between slow / fast-path +// ELT hooks (and later on as part of asserts). + +inline BOOL CORProfilerELT3SlowPathEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathEnterEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathLeaveEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT3SlowPathTailcallEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_FRAME_INFO))); +} + +inline BOOL CORProfilerELT2FastPathEnterEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerELT2FastPathLeaveEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerELT2FastPathTailcallEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + (!((&g_profControlBlock)->dwEventMask & (COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO)))); +} + +inline BOOL CORProfilerFunctionArgsEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_ARGS)); +} + +inline BOOL CORProfilerFunctionReturnValueEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FUNCTION_RETVAL)); +} + +inline BOOL CORProfilerFrameInfoEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_FRAME_INFO)); +} + +inline BOOL CORProfilerStackSnapshotEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresentOrInitializing() && + ((&g_profControlBlock)->dwEventMask & COR_PRF_ENABLE_STACK_SNAPSHOT)); +} + +inline BOOL CORProfilerAddsAssemblyReferences() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES)); +} + +inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED)); +} + +inline BOOL CORProfilerIsMonitoringDynamicFunctionUnloads() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS)); +} + +inline BOOL CORProfilerDisableTieredCompilation() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_DISABLE_TIERED_COMPILATION)); +} + +inline BOOL CORProfilerTrackBasicGC() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_BASIC_GC)); +} + +inline BOOL CORProfilerTrackGCMovedObjects() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + } + CONTRACTL_END; + + return (CORProfilerPresent() && + ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS)); +} + +#if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE) + +#if defined(FEATURE_PROFAPI_ATTACH_DETACH) + +//--------------------------------------------------------------------------------------- +// When EE calls into the profiler, an EvacuationCounterHolder object is instantiated on +// the stack to increment the evacuation counter inside the EE Thread. Upon returning to +// EE, this EvacuationCounterHolder object when being destroyed decreases the evacuation +// counter by one. +// +// Do not use this object directly. Use BEGIN_PIN_PROFILER / END_PIN_PROFILER defined +// below. +// +// See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization. +// +typedef Wrapper> EvacuationCounterHolder; + + +//--------------------------------------------------------------------------------------- +// These macros must be placed around any access to g_profControlBlock.pProfInterface by +// the EE. Example: +// { +// BEGIN_PIN_PROFILER(CORProfilerTrackAppDomainLoads()); +// g_profControlBlock.pProfInterface->AppDomainCreationStarted(MyAppDomainID); +// END_PIN_PROFILER(); +// } +// The parameter to the BEGIN_PIN_PROFILER is the condition you want to check for, to +// determine whether the profiler is loaded and requesting the callback you're about to +// issue. Typically, this will be a call to one of the inline functions in +// profilepriv.inl. If the condition is true, the macro will increment an evacuation +// counter that effectively pins the profiler, recheck the condition, and (if still +// true), execute whatever code you place inside the BEGIN/END_PIN_PROFILER block. If +// your condition is more complex than a simple profiler status check, then place the +// profiler status check as parameter to the macro, and add a separate if inside the +// block. Example: +// +// { +// BEGIN_PIN_PROFILER(CORProfilerTrackTransitions()); +// if (!pNSL->pMD->IsQCall()) +// { +// g_profControlBlock.pProfInterface-> +// ManagedToUnmanagedTransition((FunctionID) pNSL->pMD, +// COR_PRF_TRANSITION_CALL); +// } +// END_PIN_PROFILER(); +// } +// +// This ensures that the extra condition check (in this case "if +// (!pNSL->pMD->IsQCall())") is only evaluated if the profiler is loaded. That way, we're +// not executing extra, unnecessary instructions when no profiler is present. +// +// See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization +// for more details about how the synchronization works. +#define BEGIN_PIN_PROFILER(condition) \ + /* Do a cheap check of the condition (dirty-read) */ \ + if (condition) \ + { \ + EvacuationCounterHolder __evacuationCounter(GetThreadNULLOk()); \ + /* Now that the evacuation counter is incremented, the condition re-check */ \ + /* below is a clean read. There's no MemoryBarrier() here, but that's ok */ \ + /* as writes to the profiler status force a FlushStoreBuffers(). */ \ + if (condition) \ + { +#define END_PIN_PROFILER() } } + +#else // FEATURE_PROFAPI_ATTACH_DETACH + +// For builds that include profiling but not attach / detach (e.g., Silverlight 2), the +// *PIN_PROFILER macros should just check the condition without using the evacuation +// counters. + +#define BEGIN_PIN_PROFILER(condition) if (condition) { +#define END_PIN_PROFILER() } + +#endif // FEATURE_PROFAPI_ATTACH_DETACH + +#else // PROFILING_SUPPORTED && !CROSSGEN_COMPILE + +// Profiling feature not supported + +#define BEGIN_PIN_PROFILER(condition) if (false) { +#define END_PIN_PROFILER() } + +#endif // PROFILING_SUPPORTED && !CROSSGEN_COMPILE + +#endif // _ProfilePriv_inl_ + diff --git a/lib/coreclr/src/inc/random.h b/lib/coreclr/src/inc/random.h new file mode 100644 index 0000000000..cbf2d21c4e --- /dev/null +++ b/lib/coreclr/src/inc/random.h @@ -0,0 +1,279 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// random.h +// + +// +// Defines a random number generator, initially from the System.Random code in the BCL. If you notice any problems, +// please compare to the implementation in src\mscorlib\src\system\random.cs. +// +// Main advantages over rand() are: +// +// 1) It generates better random numbers +// 2) It can have multiple instantiations with different seeds +// 3) It behaves the same regardless of whether we build with VC++ or GCC +// +// If you are working in the VM, we have a convenience method: code:GetRandomInt. This usess a thread-local +// Random instance if a Thread object is available, and otherwise falls back to a global instance +// with a spin-lock. +// + +#ifndef _CLRRANDOM_H_ +#define _CLRRANDOM_H_ + +#include + +// +// Forbid the use of srand()/rand(), as these are globally shared facilities and our use of them would +// interfere with native user code in the same process. This override is not compatible with stl headers. +// +#if !defined(DO_NOT_DISABLE_RAND) && !defined(USE_STL) + +#ifdef srand +#undef srand +#endif +#define srand Do_not_use_srand + +#ifdef rand +#undef rand +#endif +#define rand Do_not_use_rand + +#endif //!DO_NOT_DISABLE_RAND && !USE_STL + + +class CLRRandom +{ +private: + // + // Private Constants + // + static const int MBIG = INT_MAX; + static const int MSEED = 161803398; + static const int MZ = 0; + + + // + // Member Variables + // + int inext; + int inextp; + int SeedArray[56]; + + bool initialized; + +public: + // + // Constructors + // + + CLRRandom() + { + LIMITED_METHOD_CONTRACT; + initialized = false; + } + + void Init() + { + LIMITED_METHOD_CONTRACT; + LARGE_INTEGER time; + if (!QueryPerformanceCounter(&time)) + time.QuadPart = GetTickCount(); + Init((int)time.u.LowPart ^ GetCurrentThreadId() ^ GetCurrentProcessId()); + } + + void Init(int Seed) + { + LIMITED_METHOD_CONTRACT; + + int ii; + int mj, mk; + + //Initialize our Seed array. + mj = MSEED - abs(Seed); + SeedArray[55]=mj; + mk=1; + for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position. + ii = (21*i)%55; + SeedArray[ii]=mk; + mk = mj - mk; + if (mk<0) mk+=MBIG; + mj=SeedArray[ii]; + } + for (int k=1; k<5; k++) { + for (int i=1; i<56; i++) { + SeedArray[i] -= SeedArray[1+(i+30)%55]; + if (SeedArray[i]<0) SeedArray[i]+=MBIG; + } + } + inext=0; + inextp = 21; + Seed = 1; + + initialized = true; + } + + bool IsInitialized() + { + LIMITED_METHOD_CONTRACT; + return initialized; + } + +private: + // + // Package Private Methods + // + + /*====================================Sample==================================== + **Action: Return a new random number [0..1) and reSeed the Seed array. + **Returns: A double [0..1) + **Arguments: None + **Exceptions: None + ==============================================================================*/ + double Sample() + { + LIMITED_METHOD_CONTRACT; + + //Including this division at the end gives us significantly improved + //random number distribution. + return (InternalSample()*(1.0/MBIG)); + } + + int InternalSample() + { + LIMITED_METHOD_CONTRACT; + + int retVal; + int locINext = inext; + int locINextp = inextp; + + if (++locINext >=56) locINext=1; + if (++locINextp>= 56) locINextp = 1; + + retVal = SeedArray[locINext]-SeedArray[locINextp]; + + if (retVal == MBIG) retVal--; + if (retVal<0) retVal+=MBIG; + + SeedArray[locINext]=retVal; + + inext = locINext; + inextp = locINextp; + + return retVal; + } + + double GetSampleForLargeRange() + { + LIMITED_METHOD_CONTRACT; + + // The distribution of double value returned by Sample + // is not distributed well enough for a large range. + // If we use Sample for a range [Int32.MinValue..Int32.MaxValue) + // We will end up getting even numbers only. + + int result = InternalSample(); + // Note we can't use addition here. The distribution will be bad if we do that. + bool negative = (InternalSample()%2 == 0) ? true : false; // decide the sign based on second sample + if( negative) { + result = -result; + } + double d = result; + d += (INT_MAX - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1) + d /= 2*(unsigned int)INT_MAX - 1 ; + return d; + } + +public: + // + // Public Instance Methods + // + + + /*=====================================Next===================================== + **Returns: An int [0..Int32.MaxValue) + **Arguments: None + **Exceptions: None. + ==============================================================================*/ + int Next() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(initialized); + return InternalSample(); + } + + + /*=====================================Next===================================== + **Returns: An int [minvalue..maxvalue) + **Arguments: minValue -- the least legal value for the Random number. + ** maxValue -- One greater than the greatest legal return value. + **Exceptions: None. + ==============================================================================*/ + int Next(int minValue, int maxValue) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(initialized); + _ASSERTE(minValue < maxValue); + + LONGLONG range = (LONGLONG)maxValue-minValue; + double result; + + if( range <= (LONGLONG)INT_MAX) + result = (Sample() * range) + minValue; + else + result = (GetSampleForLargeRange() * range) + minValue; + + _ASSERTE(result >= minValue && result < maxValue); + return (int)result; + } + + + /*=====================================Next===================================== + **Returns: An int [0..maxValue) + **Arguments: maxValue -- One more than the greatest legal return value. + **Exceptions: None. + ==============================================================================*/ + int Next(int maxValue) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(initialized); + double result = Sample()*maxValue; + _ASSERTE(result >= 0 && result < maxValue); + return (int)result; + } + + + /*=====================================Next===================================== + **Returns: A double [0..1) + **Arguments: None + **Exceptions: None + ==============================================================================*/ + double NextDouble() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(initialized); + double result = Sample(); + _ASSERTE(result >= 0 && result < 1); + return result; + } + + + /*==================================NextBytes=================================== + **Action: Fills the byte array with random bytes [0..0x7f]. The entire array is filled. + **Returns:Void + **Arguments: buffer -- the array to be filled. + **Exceptions: None + ==============================================================================*/ + void NextBytes(__out_ecount(length) BYTE buffer[], int length) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(initialized); + for (int i=0; i>1)+1))]; + } + + public: + BOOL IsIntermediate() { return isIntermediate; } + void IsIntermediate(BOOL value) { isIntermediate = value; } + SIZE_T GetStart() { return start; } + SIZE_T GetEnd() { return end; } + }; + + friend struct Node; + + RangeTree(); + + Node *Lookup(SIZE_T address) const; + Node *LookupEndInclusive(SIZE_T nonStartingAddress); + BOOL Overlaps(SIZE_T start, SIZE_T end); + HRESULT AddNode(Node *addNode, SIZE_T start, SIZE_T end); + HRESULT RemoveNode(Node *removeNode); + void RemoveRange(SIZE_T start, SIZE_T end); + + typedef void (*IterationCallback)(Node *next, void *context); + + void Iterate(IterationCallback pCallback, void *context = NULL); + void IterateRange(SIZE_T start, SIZE_T end, IterationCallback pCallback, void *context = NULL); + + private: + + Node * m_root; + MemoryPool m_pool; +#ifdef _DEBUG + DWORD m_nodeCount; +#endif + + Node *AddIntermediateNode(Node *node0, Node *node1); + Node *AllocateIntermediate(); + void FreeIntermediate(Node *node); + + void IterateNode(Node *node, IterationCallback pCallback, void *context); + void IterateRangeNode(Node *node, SIZE_T start, SIZE_T end, SIZE_T mask, IterationCallback pCallback, void *context); + BOOL OverlapsNode(Node *node, SIZE_T start, SIZE_T end, SIZE_T mask); + void RemoveRangeNode(Node **nodePtr, SIZE_T start, SIZE_T end, SIZE_T mask); + + static SIZE_T GetRangeCommonMask(SIZE_T start, SIZE_T end); +}; + +#endif // _RANGETREE_ diff --git a/lib/coreclr/src/inc/readytorun.h b/lib/coreclr/src/inc/readytorun.h new file mode 100644 index 0000000000..7745ad6e2f --- /dev/null +++ b/lib/coreclr/src/inc/readytorun.h @@ -0,0 +1,363 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// readytorun.h +// + +// +// Contains definitions for the Ready to Run file format +// + +#ifndef __READYTORUN_H__ +#define __READYTORUN_H__ + +#define READYTORUN_SIGNATURE 0x00525452 // 'RTR' + +#define READYTORUN_MAJOR_VERSION 0x0003 +#define READYTORUN_MINOR_VERSION 0x0001 +#define MINIMUM_READYTORUN_MAJOR_VERSION 0x003 +// R2R Version 2.1 adds the READYTORUN_SECTION_INLINING_INFO section +// R2R Version 2.2 adds the READYTORUN_SECTION_PROFILEDATA_INFO section +// R2R Version 3.0 changes calling conventions to correctly handle explicit structures to spec. +// R2R 3.0 is not backward compatible with 2.x. + +struct READYTORUN_HEADER +{ + DWORD Signature; // READYTORUN_SIGNATURE + USHORT MajorVersion; // READYTORUN_VERSION_XXX + USHORT MinorVersion; + + DWORD Flags; // READYTORUN_FLAG_XXX + + DWORD NumberOfSections; + + // Array of sections follows. The array entries are sorted by Type + // READYTORUN_SECTION Sections[]; +}; + +struct READYTORUN_SECTION +{ + DWORD Type; // READYTORUN_SECTION_XXX + IMAGE_DATA_DIRECTORY Section; +}; + +enum ReadyToRunFlag +{ + // Set if the original IL assembly was platform-neutral + READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE = 0x00000001, + READYTORUN_FLAG_SKIP_TYPE_VALIDATION = 0x00000002, + // Set of methods with native code was determined using profile data + READYTORUN_FLAG_PARTIAL = 0x00000004, +}; + +enum ReadyToRunSectionType +{ + READYTORUN_SECTION_COMPILER_IDENTIFIER = 100, + READYTORUN_SECTION_IMPORT_SECTIONS = 101, + READYTORUN_SECTION_RUNTIME_FUNCTIONS = 102, + READYTORUN_SECTION_METHODDEF_ENTRYPOINTS = 103, + READYTORUN_SECTION_EXCEPTION_INFO = 104, + READYTORUN_SECTION_DEBUG_INFO = 105, + READYTORUN_SECTION_DELAYLOAD_METHODCALL_THUNKS = 106, + // 107 used by an older format of READYTORUN_SECTION_AVAILABLE_TYPES + READYTORUN_SECTION_AVAILABLE_TYPES = 108, + READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS = 109, + READYTORUN_SECTION_INLINING_INFO = 110, // Added in V2.1 + READYTORUN_SECTION_PROFILEDATA_INFO = 111, // Added in V2.2 + READYTORUN_SECTION_MANIFEST_METADATA = 112, // Added in V2.3 + READYTORUN_SECTION_ATTRIBUTEPRESENCE = 113, // Added in V3.1 + + // If you add a new section consider whether it is a breaking or non-breaking change. + // Usually it is non-breaking, but if it is preferable to have older runtimes fail + // to load the image vs. ignoring the new section it could be marked breaking. + // Increment the READYTORUN_MINOR_VERSION (non-breaking) or READYTORUN_MAJOR_VERSION + // (breaking) as appropriate. +}; + +// +// READYTORUN_IMPORT_SECTION describes image range with references to code or runtime data structures +// +// There is number of different types of these ranges: eagerly initialized at image load vs. lazily initialized at method entry +// vs. lazily initialized on first use; handles vs. code pointers, etc. +// +struct READYTORUN_IMPORT_SECTION +{ + IMAGE_DATA_DIRECTORY Section; // Section containing values to be fixed up + USHORT Flags; // One or more of ReadyToRunImportSectionFlags + BYTE Type; // One of ReadyToRunImportSectionType + BYTE EntrySize; + DWORD Signatures; // RVA of optional signature descriptors + DWORD AuxiliaryData; // RVA of optional auxiliary data (typically GC info) +}; + +enum ReadyToRunImportSectionType +{ + READYTORUN_IMPORT_SECTION_TYPE_UNKNOWN = 0, +}; + +enum ReadyToRunImportSectionFlags +{ + READYTORUN_IMPORT_SECTION_FLAGS_EAGER = 0x0001, +}; + +// +// Constants for method and field encoding +// + +enum ReadyToRunMethodSigFlags +{ + READYTORUN_METHOD_SIG_UnboxingStub = 0x01, + READYTORUN_METHOD_SIG_InstantiatingStub = 0x02, + READYTORUN_METHOD_SIG_MethodInstantiation = 0x04, + READYTORUN_METHOD_SIG_SlotInsteadOfToken = 0x08, + READYTORUN_METHOD_SIG_MemberRefToken = 0x10, + READYTORUN_METHOD_SIG_Constrained = 0x20, + READYTORUN_METHOD_SIG_OwnerType = 0x40, +}; + +enum ReadyToRunFieldSigFlags +{ + READYTORUN_FIELD_SIG_IndexInsteadOfToken = 0x08, + READYTORUN_FIELD_SIG_MemberRefToken = 0x10, + READYTORUN_FIELD_SIG_OwnerType = 0x40, +}; + +enum ReadyToRunTypeLayoutFlags +{ + READYTORUN_LAYOUT_HFA = 0x01, + READYTORUN_LAYOUT_Alignment = 0x02, + READYTORUN_LAYOUT_Alignment_Native = 0x04, + READYTORUN_LAYOUT_GCLayout = 0x08, + READYTORUN_LAYOUT_GCLayout_Empty = 0x10, +}; + +// +// Constants for fixup signature encoding +// + +enum ReadyToRunFixupKind +{ + READYTORUN_FIXUP_ThisObjDictionaryLookup = 0x07, + READYTORUN_FIXUP_TypeDictionaryLookup = 0x08, + READYTORUN_FIXUP_MethodDictionaryLookup = 0x09, + + READYTORUN_FIXUP_TypeHandle = 0x10, + READYTORUN_FIXUP_MethodHandle = 0x11, + READYTORUN_FIXUP_FieldHandle = 0x12, + + READYTORUN_FIXUP_MethodEntry = 0x13, /* For calling a method entry point */ + READYTORUN_FIXUP_MethodEntry_DefToken = 0x14, /* Smaller version of MethodEntry - method is def token */ + READYTORUN_FIXUP_MethodEntry_RefToken = 0x15, /* Smaller version of MethodEntry - method is ref token */ + + READYTORUN_FIXUP_VirtualEntry = 0x16, /* For invoking a virtual method */ + READYTORUN_FIXUP_VirtualEntry_DefToken = 0x17, /* Smaller version of VirtualEntry - method is def token */ + READYTORUN_FIXUP_VirtualEntry_RefToken = 0x18, /* Smaller version of VirtualEntry - method is ref token */ + READYTORUN_FIXUP_VirtualEntry_Slot = 0x19, /* Smaller version of VirtualEntry - type & slot */ + + READYTORUN_FIXUP_Helper = 0x1A, /* Helper */ + READYTORUN_FIXUP_StringHandle = 0x1B, /* String handle */ + + READYTORUN_FIXUP_NewObject = 0x1C, /* Dynamically created new helper */ + READYTORUN_FIXUP_NewArray = 0x1D, + + READYTORUN_FIXUP_IsInstanceOf = 0x1E, /* Dynamically created casting helper */ + READYTORUN_FIXUP_ChkCast = 0x1F, + + READYTORUN_FIXUP_FieldAddress = 0x20, /* For accessing a cross-module static fields */ + READYTORUN_FIXUP_CctorTrigger = 0x21, /* Static constructor trigger */ + + READYTORUN_FIXUP_StaticBaseNonGC = 0x22, /* Dynamically created static base helpers */ + READYTORUN_FIXUP_StaticBaseGC = 0x23, + READYTORUN_FIXUP_ThreadStaticBaseNonGC = 0x24, + READYTORUN_FIXUP_ThreadStaticBaseGC = 0x25, + + READYTORUN_FIXUP_FieldBaseOffset = 0x26, /* Field base offset */ + READYTORUN_FIXUP_FieldOffset = 0x27, /* Field offset */ + + READYTORUN_FIXUP_TypeDictionary = 0x28, + READYTORUN_FIXUP_MethodDictionary = 0x29, + + READYTORUN_FIXUP_Check_TypeLayout = 0x2A, /* size, alignment, HFA, reference map */ + READYTORUN_FIXUP_Check_FieldOffset = 0x2B, + + READYTORUN_FIXUP_DelegateCtor = 0x2C, /* optimized delegate ctor */ + READYTORUN_FIXUP_DeclaringTypeHandle = 0x2D, + + READYTORUN_FIXUP_IndirectPInvokeTarget = 0x2E, /* Target of an inlined pinvoke */ +}; + +// +// Intrinsics and helpers +// + +enum ReadyToRunHelper +{ + READYTORUN_HELPER_Invalid = 0x00, + + // Not a real helper - handle to current module passed to delay load helpers. + READYTORUN_HELPER_Module = 0x01, + READYTORUN_HELPER_GSCookie = 0x02, + + // + // Delay load helpers + // + + // All delay load helpers use custom calling convention: + // - scratch register - address of indirection cell. 0 = address is inferred from callsite. + // - stack - section index, module handle + READYTORUN_HELPER_DelayLoad_MethodCall = 0x08, + + READYTORUN_HELPER_DelayLoad_Helper = 0x10, + READYTORUN_HELPER_DelayLoad_Helper_Obj = 0x11, + READYTORUN_HELPER_DelayLoad_Helper_ObjObj = 0x12, + + // JIT helpers + + // Exception handling helpers + READYTORUN_HELPER_Throw = 0x20, + READYTORUN_HELPER_Rethrow = 0x21, + READYTORUN_HELPER_Overflow = 0x22, + READYTORUN_HELPER_RngChkFail = 0x23, + READYTORUN_HELPER_FailFast = 0x24, + READYTORUN_HELPER_ThrowNullRef = 0x25, + READYTORUN_HELPER_ThrowDivZero = 0x26, + + // Write barriers + READYTORUN_HELPER_WriteBarrier = 0x30, + READYTORUN_HELPER_CheckedWriteBarrier = 0x31, + READYTORUN_HELPER_ByRefWriteBarrier = 0x32, + + // Array helpers + READYTORUN_HELPER_Stelem_Ref = 0x38, + READYTORUN_HELPER_Ldelema_Ref = 0x39, + + READYTORUN_HELPER_MemSet = 0x40, + READYTORUN_HELPER_MemCpy = 0x41, + + // PInvoke helpers + READYTORUN_HELPER_PInvokeBegin = 0x42, + READYTORUN_HELPER_PInvokeEnd = 0x43, + + // Get string handle lazily + READYTORUN_HELPER_GetString = 0x50, + + // Used by /Tuning for Profile optimizations + READYTORUN_HELPER_LogMethodEnter = 0x51, + + // Reflection helpers + READYTORUN_HELPER_GetRuntimeTypeHandle = 0x54, + READYTORUN_HELPER_GetRuntimeMethodHandle = 0x55, + READYTORUN_HELPER_GetRuntimeFieldHandle = 0x56, + + READYTORUN_HELPER_Box = 0x58, + READYTORUN_HELPER_Box_Nullable = 0x59, + READYTORUN_HELPER_Unbox = 0x5A, + READYTORUN_HELPER_Unbox_Nullable = 0x5B, + READYTORUN_HELPER_NewMultiDimArr = 0x5C, + READYTORUN_HELPER_NewMultiDimArr_NonVarArg = 0x5D, + + // Helpers used with generic handle lookup cases + READYTORUN_HELPER_NewObject = 0x60, + READYTORUN_HELPER_NewArray = 0x61, + READYTORUN_HELPER_CheckCastAny = 0x62, + READYTORUN_HELPER_CheckInstanceAny = 0x63, + READYTORUN_HELPER_GenericGcStaticBase = 0x64, + READYTORUN_HELPER_GenericNonGcStaticBase = 0x65, + READYTORUN_HELPER_GenericGcTlsBase = 0x66, + READYTORUN_HELPER_GenericNonGcTlsBase = 0x67, + READYTORUN_HELPER_VirtualFuncPtr = 0x68, + + // Long mul/div/shift ops + READYTORUN_HELPER_LMul = 0xC0, + READYTORUN_HELPER_LMulOfv = 0xC1, + READYTORUN_HELPER_ULMulOvf = 0xC2, + READYTORUN_HELPER_LDiv = 0xC3, + READYTORUN_HELPER_LMod = 0xC4, + READYTORUN_HELPER_ULDiv = 0xC5, + READYTORUN_HELPER_ULMod = 0xC6, + READYTORUN_HELPER_LLsh = 0xC7, + READYTORUN_HELPER_LRsh = 0xC8, + READYTORUN_HELPER_LRsz = 0xC9, + READYTORUN_HELPER_Lng2Dbl = 0xCA, + READYTORUN_HELPER_ULng2Dbl = 0xCB, + + // 32-bit division helpers + READYTORUN_HELPER_Div = 0xCC, + READYTORUN_HELPER_Mod = 0xCD, + READYTORUN_HELPER_UDiv = 0xCE, + READYTORUN_HELPER_UMod = 0xCF, + + // Floating point conversions + READYTORUN_HELPER_Dbl2Int = 0xD0, + READYTORUN_HELPER_Dbl2IntOvf = 0xD1, + READYTORUN_HELPER_Dbl2Lng = 0xD2, + READYTORUN_HELPER_Dbl2LngOvf = 0xD3, + READYTORUN_HELPER_Dbl2UInt = 0xD4, + READYTORUN_HELPER_Dbl2UIntOvf = 0xD5, + READYTORUN_HELPER_Dbl2ULng = 0xD6, + READYTORUN_HELPER_Dbl2ULngOvf = 0xD7, + + // Floating point ops + READYTORUN_HELPER_DblRem = 0xE0, + READYTORUN_HELPER_FltRem = 0xE1, + READYTORUN_HELPER_DblRound = 0xE2, + READYTORUN_HELPER_FltRound = 0xE3, + +#ifdef WIN64EXCEPTIONS + // Personality rountines + READYTORUN_HELPER_PersonalityRoutine = 0xF0, + READYTORUN_HELPER_PersonalityRoutineFilterFunclet = 0xF1, +#endif + + // Synchronized methods + READYTORUN_HELPER_MonitorEnter = 0xF8, + READYTORUN_HELPER_MonitorExit = 0xF9, + + // + // Deprecated/legacy + // + + // JIT32 x86-specific write barriers + READYTORUN_HELPER_WriteBarrier_EAX = 0x100, + READYTORUN_HELPER_WriteBarrier_EBX = 0x101, + READYTORUN_HELPER_WriteBarrier_ECX = 0x102, + READYTORUN_HELPER_WriteBarrier_ESI = 0x103, + READYTORUN_HELPER_WriteBarrier_EDI = 0x104, + READYTORUN_HELPER_WriteBarrier_EBP = 0x105, + READYTORUN_HELPER_CheckedWriteBarrier_EAX = 0x106, + READYTORUN_HELPER_CheckedWriteBarrier_EBX = 0x107, + READYTORUN_HELPER_CheckedWriteBarrier_ECX = 0x108, + READYTORUN_HELPER_CheckedWriteBarrier_ESI = 0x109, + READYTORUN_HELPER_CheckedWriteBarrier_EDI = 0x10A, + READYTORUN_HELPER_CheckedWriteBarrier_EBP = 0x10B, + + // JIT32 x86-specific exception handling + READYTORUN_HELPER_EndCatch = 0x110, +}; + +// +// Exception info +// + +struct READYTORUN_EXCEPTION_LOOKUP_TABLE_ENTRY +{ + DWORD MethodStart; + DWORD ExceptionInfo; +}; + +struct READYTORUN_EXCEPTION_CLAUSE +{ + CorExceptionFlag Flags; + DWORD TryStartPC; + DWORD TryEndPC; + DWORD HandlerStartPC; + DWORD HandlerEndPC; + union { + mdToken ClassToken; + DWORD FilterOffset; + }; +}; + +#endif // __READYTORUN_H__ diff --git a/lib/coreclr/src/inc/readytorunhelpers.h b/lib/coreclr/src/inc/readytorunhelpers.h new file mode 100644 index 0000000000..c677f3787a --- /dev/null +++ b/lib/coreclr/src/inc/readytorunhelpers.h @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// ReadyToRunHelpers.h +// + +// +// Mapping between regular JIT helpers and ready to run helpers +// + +#ifndef OPTIMIZEFORSPEED +#define OPTIMIZEFORSPEED +#endif + +HELPER(READYTORUN_HELPER_Throw, CORINFO_HELP_THROW, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_Rethrow, CORINFO_HELP_RETHROW, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_Overflow, CORINFO_HELP_OVERFLOW, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_RngChkFail, CORINFO_HELP_RNGCHKFAIL, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_FailFast, CORINFO_HELP_FAIL_FAST, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_ThrowNullRef, CORINFO_HELP_THROWNULLREF, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_ThrowDivZero, CORINFO_HELP_THROWDIVZERO, OPTIMIZEFORSIZE) + +HELPER(READYTORUN_HELPER_WriteBarrier, CORINFO_HELP_ASSIGN_REF, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier, CORINFO_HELP_CHECKED_ASSIGN_REF, ) +HELPER(READYTORUN_HELPER_ByRefWriteBarrier, CORINFO_HELP_ASSIGN_BYREF, ) + +HELPER(READYTORUN_HELPER_Stelem_Ref, CORINFO_HELP_ARRADDR_ST, ) +HELPER(READYTORUN_HELPER_Ldelema_Ref, CORINFO_HELP_LDELEMA_REF, ) + +HELPER(READYTORUN_HELPER_MemSet, CORINFO_HELP_MEMSET, ) +HELPER(READYTORUN_HELPER_MemCpy, CORINFO_HELP_MEMCPY, ) + +HELPER(READYTORUN_HELPER_LogMethodEnter, CORINFO_HELP_BBT_FCN_ENTER, ) + +HELPER(READYTORUN_HELPER_GetRuntimeTypeHandle, CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, ) +HELPER(READYTORUN_HELPER_GetRuntimeMethodHandle, CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, ) +HELPER(READYTORUN_HELPER_GetRuntimeFieldHandle, CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, ) + +HELPER(READYTORUN_HELPER_Box, CORINFO_HELP_BOX, ) +HELPER(READYTORUN_HELPER_Box_Nullable, CORINFO_HELP_BOX_NULLABLE, ) +HELPER(READYTORUN_HELPER_Unbox, CORINFO_HELP_UNBOX, ) +HELPER(READYTORUN_HELPER_Unbox_Nullable, CORINFO_HELP_UNBOX_NULLABLE, ) +HELPER(READYTORUN_HELPER_NewMultiDimArr, CORINFO_HELP_NEW_MDARR, ) +HELPER(READYTORUN_HELPER_NewMultiDimArr_NonVarArg, CORINFO_HELP_NEW_MDARR_NONVARARG, ) + +HELPER(READYTORUN_HELPER_NewObject, CORINFO_HELP_NEWFAST, ) +HELPER(READYTORUN_HELPER_NewArray, CORINFO_HELP_NEWARR_1_R2R_DIRECT, ) +HELPER(READYTORUN_HELPER_CheckCastAny, CORINFO_HELP_CHKCASTANY, ) +HELPER(READYTORUN_HELPER_CheckInstanceAny, CORINFO_HELP_ISINSTANCEOFANY, ) + +HELPER(READYTORUN_HELPER_GenericGcStaticBase, CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, ) +HELPER(READYTORUN_HELPER_GenericNonGcStaticBase, CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, ) +HELPER(READYTORUN_HELPER_GenericGcTlsBase, CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, ) +HELPER(READYTORUN_HELPER_GenericNonGcTlsBase, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE,) + +HELPER(READYTORUN_HELPER_VirtualFuncPtr, CORINFO_HELP_VIRTUAL_FUNC_PTR, ) + +HELPER(READYTORUN_HELPER_LMul, CORINFO_HELP_LMUL, ) +HELPER(READYTORUN_HELPER_LMulOfv, CORINFO_HELP_LMUL_OVF, ) +HELPER(READYTORUN_HELPER_ULMulOvf, CORINFO_HELP_ULMUL_OVF, ) +HELPER(READYTORUN_HELPER_LDiv, CORINFO_HELP_LDIV, ) +HELPER(READYTORUN_HELPER_LMod, CORINFO_HELP_LMOD, ) +HELPER(READYTORUN_HELPER_ULDiv, CORINFO_HELP_ULDIV, ) +HELPER(READYTORUN_HELPER_ULMod, CORINFO_HELP_ULMOD, ) +HELPER(READYTORUN_HELPER_LLsh, CORINFO_HELP_LLSH, ) +HELPER(READYTORUN_HELPER_LRsh, CORINFO_HELP_LRSH, ) +HELPER(READYTORUN_HELPER_LRsz, CORINFO_HELP_LRSZ, ) +HELPER(READYTORUN_HELPER_Lng2Dbl, CORINFO_HELP_LNG2DBL, ) +HELPER(READYTORUN_HELPER_ULng2Dbl, CORINFO_HELP_ULNG2DBL, ) + +HELPER(READYTORUN_HELPER_Div, CORINFO_HELP_DIV, ) +HELPER(READYTORUN_HELPER_Mod, CORINFO_HELP_MOD, ) +HELPER(READYTORUN_HELPER_UDiv, CORINFO_HELP_UDIV, ) +HELPER(READYTORUN_HELPER_UMod, CORINFO_HELP_UMOD, ) + +HELPER(READYTORUN_HELPER_Dbl2Int, CORINFO_HELP_DBL2INT, ) +HELPER(READYTORUN_HELPER_Dbl2IntOvf, CORINFO_HELP_DBL2INT_OVF, ) +HELPER(READYTORUN_HELPER_Dbl2Lng, CORINFO_HELP_DBL2LNG, ) +HELPER(READYTORUN_HELPER_Dbl2LngOvf, CORINFO_HELP_DBL2LNG_OVF, ) +HELPER(READYTORUN_HELPER_Dbl2UInt, CORINFO_HELP_DBL2UINT, ) +HELPER(READYTORUN_HELPER_Dbl2UIntOvf, CORINFO_HELP_DBL2UINT_OVF, ) +HELPER(READYTORUN_HELPER_Dbl2ULng, CORINFO_HELP_DBL2ULNG, ) +HELPER(READYTORUN_HELPER_Dbl2ULngOvf, CORINFO_HELP_DBL2ULNG_OVF, ) + +HELPER(READYTORUN_HELPER_FltRem, CORINFO_HELP_FLTREM, ) +HELPER(READYTORUN_HELPER_DblRem, CORINFO_HELP_DBLREM, ) +HELPER(READYTORUN_HELPER_FltRound, CORINFO_HELP_FLTROUND, ) +HELPER(READYTORUN_HELPER_DblRound, CORINFO_HELP_DBLROUND, ) + +#ifndef _TARGET_X86_ +HELPER(READYTORUN_HELPER_PersonalityRoutine, CORINFO_HELP_EE_PERSONALITY_ROUTINE, OPTIMIZEFORSIZE) +HELPER(READYTORUN_HELPER_PersonalityRoutineFilterFunclet, CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, OPTIMIZEFORSIZE) +#endif + +#ifdef _TARGET_X86_ +HELPER(READYTORUN_HELPER_WriteBarrier_EAX, CORINFO_HELP_ASSIGN_REF_EAX, ) +HELPER(READYTORUN_HELPER_WriteBarrier_EBX, CORINFO_HELP_ASSIGN_REF_EBX, ) +HELPER(READYTORUN_HELPER_WriteBarrier_ECX, CORINFO_HELP_ASSIGN_REF_ECX, ) +HELPER(READYTORUN_HELPER_WriteBarrier_ESI, CORINFO_HELP_ASSIGN_REF_ESI, ) +HELPER(READYTORUN_HELPER_WriteBarrier_EDI, CORINFO_HELP_ASSIGN_REF_EDI, ) +HELPER(READYTORUN_HELPER_WriteBarrier_EBP, CORINFO_HELP_ASSIGN_REF_EBP, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_EAX, CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_EBX, CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_ECX, CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_ESI, CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_EDI, CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, ) +HELPER(READYTORUN_HELPER_CheckedWriteBarrier_EBP, CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, ) + +HELPER(READYTORUN_HELPER_EndCatch, CORINFO_HELP_ENDCATCH, OPTIMIZEFORSIZE) +#endif + +HELPER(READYTORUN_HELPER_PInvokeBegin, CORINFO_HELP_JIT_PINVOKE_BEGIN, ) +HELPER(READYTORUN_HELPER_PInvokeEnd, CORINFO_HELP_JIT_PINVOKE_END, ) + +HELPER(READYTORUN_HELPER_MonitorEnter, CORINFO_HELP_MON_ENTER, ) +HELPER(READYTORUN_HELPER_MonitorExit, CORINFO_HELP_MON_EXIT, ) + +#undef HELPER +#undef OPTIMIZEFORSPEED diff --git a/lib/coreclr/src/inc/regdisp.h b/lib/coreclr/src/inc/regdisp.h new file mode 100644 index 0000000000..7875edf653 --- /dev/null +++ b/lib/coreclr/src/inc/regdisp.h @@ -0,0 +1,551 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __REGDISP_H +#define __REGDISP_H + + +#ifdef DEBUG_REGDISPLAY +class Thread; +struct REGDISPLAY; +void CheckRegDisplaySP (REGDISPLAY *pRD); +#endif // DEBUG_REGDISPLAY + +struct REGDISPLAY_BASE { + PT_CONTEXT pContext; // This is the context of the active call frame; + // either returned by GetContext or provided at + // exception time. + // + // This will be used to resume execution, so + // do NOT trash it! But DO update any static + // registers here. + +#ifdef WIN64EXCEPTIONS + PT_CONTEXT pCurrentContext; // [trashed] points to current Context of stackwalk + PT_CONTEXT pCallerContext; // [trashed] points to the Context of the caller during stackwalk -- used for GC crawls + + // [trashed] points to current context pointers of stackwalk + T_KNONVOLATILE_CONTEXT_POINTERS *pCurrentContextPointers; + // [trashed] points to the context pointers of the caller during stackwalk -- used for GC crawls + T_KNONVOLATILE_CONTEXT_POINTERS *pCallerContextPointers; + + BOOL IsCallerContextValid; // TRUE if pCallerContext really contains the caller's context + BOOL IsCallerSPValid; // Don't add usage of this field. This is only temporary. + + T_CONTEXT ctxOne; // used by stackwalk + T_CONTEXT ctxTwo; // used by stackwalk + + T_KNONVOLATILE_CONTEXT_POINTERS ctxPtrsOne; // used by stackwalk + T_KNONVOLATILE_CONTEXT_POINTERS ctxPtrsTwo; // used by stackwalk +#endif // WIN64EXCEPTIONS + +#ifdef DEBUG_REGDISPLAY + Thread *_pThread; +#endif // DEBUG_REGDISPLAY + + TADDR SP; + TADDR ControlPC; +}; + +inline PCODE GetControlPC(REGDISPLAY_BASE *pRD) { + LIMITED_METHOD_DAC_CONTRACT; + return (PCODE)(pRD->ControlPC); +} + +inline TADDR GetRegdisplaySP(REGDISPLAY_BASE *pRD) { + LIMITED_METHOD_DAC_CONTRACT; + + return pRD->SP; +} + +inline void SetRegdisplaySP(REGDISPLAY_BASE *pRD, LPVOID sp) { + LIMITED_METHOD_DAC_CONTRACT; + + pRD->SP = (TADDR)sp; +} + +#if defined(_TARGET_X86_) + +struct REGDISPLAY : public REGDISPLAY_BASE { + +#ifndef WIN64EXCEPTIONS + // TODO: Unify with pCurrentContext / pCallerContext used on 64-bit + PCONTEXT pContextForUnwind; // scratch context for unwinding + // used to preserve context saved in the frame that + // could be otherwise wiped by the unwinding + + DWORD * pEdi; + DWORD * pEsi; + DWORD * pEbx; + DWORD * pEdx; + DWORD * pEcx; + DWORD * pEax; + + DWORD * pEbp; +#endif // !WIN64EXCEPTIONS + +#ifndef WIN64EXCEPTIONS + +#define REG_METHODS(reg) \ + inline PDWORD Get##reg##Location(void) { return p##reg; } \ + inline void Set##reg##Location(PDWORD p##reg) { this->p##reg = p##reg; } + +#else // !WIN64EXCEPTIONS + +#define REG_METHODS(reg) \ + inline PDWORD Get##reg##Location(void) { return pCurrentContextPointers->reg; } \ + inline void Set##reg##Location(PDWORD p##reg) { pCurrentContextPointers->reg = p##reg; } + +#endif // WIN64EXCEPTIONS + + REG_METHODS(Eax) + REG_METHODS(Ecx) + REG_METHODS(Edx) + + REG_METHODS(Ebx) + REG_METHODS(Esi) + REG_METHODS(Edi) + REG_METHODS(Ebp) + +#undef REG_METHODS + + TADDR PCTAddr; +}; + +inline TADDR GetRegdisplayFP(REGDISPLAY *display) { + LIMITED_METHOD_DAC_CONTRACT; + + return (TADDR)*display->GetEbpLocation(); +} + +inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { + LIMITED_METHOD_CONTRACT; + + return (LPVOID)display->GetEbpLocation(); +} + + +// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame +inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { + LIMITED_METHOD_CONTRACT; + +#ifdef WIN64EXCEPTIONS + return stackPointer < ((LPVOID)(display->SP)); +#else + return (TADDR)stackPointer < display->PCTAddr; +#endif +} +inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { + LIMITED_METHOD_DAC_CONTRACT; + +#ifdef WIN64EXCEPTIONS + _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); + return GetRegdisplaySP(display); +#else + return display->PCTAddr; +#endif +} + +#elif defined(_TARGET_64BIT_) + +#if defined(_TARGET_ARM64_) +typedef struct _Arm64VolatileContextPointer +{ + union { + struct { + PDWORD64 X0; + PDWORD64 X1; + PDWORD64 X2; + PDWORD64 X3; + PDWORD64 X4; + PDWORD64 X5; + PDWORD64 X6; + PDWORD64 X7; + PDWORD64 X8; + PDWORD64 X9; + PDWORD64 X10; + PDWORD64 X11; + PDWORD64 X12; + PDWORD64 X13; + PDWORD64 X14; + PDWORD64 X15; + PDWORD64 X16; + PDWORD64 X17; + //X18 is reserved by OS, in userspace it represents TEB + }; + PDWORD64 X[18]; + }; +} Arm64VolatileContextPointer; +#endif //_TARGET_ARM64_ +struct REGDISPLAY : public REGDISPLAY_BASE { +#ifdef _TARGET_ARM64_ + Arm64VolatileContextPointer volatileCurrContextPointers; +#endif + + REGDISPLAY() + { + // Initialize + memset(this, 0, sizeof(REGDISPLAY)); + } +}; + + +inline TADDR GetRegdisplayFP(REGDISPLAY *display) { + LIMITED_METHOD_CONTRACT; + return NULL; +} + +inline TADDR GetRegdisplayFPAddress(REGDISPLAY *display) { + LIMITED_METHOD_CONTRACT; + return NULL; +} + +// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame +inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) +{ + LIMITED_METHOD_CONTRACT; + return stackPointer < ((LPVOID)(display->SP)); +} + +inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) +{ +#if defined(_TARGET_AMD64_) + // On AMD64, the MemoryStackFp value is the current sp (i.e. the sp value when calling another method). + _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); + return GetRegdisplaySP(display); + +#elif defined(_TARGET_ARM64_) + + _ASSERTE(display->IsCallerContextValid); + return GetSP(display->pCallerContext); + +#else // _TARGET_AMD64_ + PORTABILITY_ASSERT("GetRegdisplayStackMark NYI for this platform (Regdisp.h)"); + return NULL; +#endif // _TARGET_AMD64_ +} + +#elif defined(_TARGET_ARM_) + +// ResumableFrame is pushed on the stack before +// starting the GC. registers r0-r3 in ResumableFrame can +// contain roots which might need to be updated if they are +// relocated. On Stack walking the addresses of the registers in the +// resumable Frame are passed to GC using pCurrentContextPointers +// member in _REGDISPLAY. However On ARM KNONVOLATILE_CONTEXT_POINTERS +// does not contain pointers for volatile registers. Therefore creating +// this structure to store pointers to volatile registers and adding an object +// as member in _REGDISPLAY +typedef struct _ArmVolatileContextPointer +{ + PDWORD R0; + PDWORD R1; + PDWORD R2; + PDWORD R3; + PDWORD R12; +} ArmVolatileContextPointer; + +struct REGDISPLAY : public REGDISPLAY_BASE { + ArmVolatileContextPointer volatileCurrContextPointers; + + DWORD * pPC; // processor neutral name +#ifndef CROSSGEN_COMPILE + REGDISPLAY() + { + // Initialize regdisplay + memset(this, 0, sizeof(REGDISPLAY)); + + // Setup the pointer to ControlPC field + pPC = &ControlPC; + } +#else +private: + REGDISPLAY(); +#endif +}; + +// This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame +inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { + LIMITED_METHOD_CONTRACT; + return stackPointer < ((LPVOID)(TADDR)(display->SP)); +} + +inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { + LIMITED_METHOD_CONTRACT; + // ARM uses the establisher frame as the marker + _ASSERTE(display->IsCallerContextValid); + return GetSP(display->pCallerContext); +} + +#else // none of the above processors +#error "RegDisplay functions are not implemented on this platform." +#endif + +#if defined(_TARGET_64BIT_) || defined(_TARGET_ARM_) || (defined(_TARGET_X86_) && defined(WIN64EXCEPTIONS)) +// This needs to be implemented for platforms that have funclets. +inline LPVOID GetRegdisplayReturnValue(REGDISPLAY *display) +{ + LIMITED_METHOD_CONTRACT; + +#if defined(_TARGET_AMD64_) + return (LPVOID)display->pCurrentContext->Rax; +#elif defined(_TARGET_ARM64_) + return (LPVOID)display->pCurrentContext->X0; +#elif defined(_TARGET_ARM_) + return (LPVOID)((TADDR)display->pCurrentContext->R0); +#elif defined(_TARGET_X86_) + return (LPVOID)display->pCurrentContext->Eax; +#else + PORTABILITY_ASSERT("GetRegdisplayReturnValue NYI for this platform (Regdisp.h)"); + return NULL; +#endif +} + +inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) +{ + LIMITED_METHOD_CONTRACT; + +#if defined(_TARGET_64BIT_) + pRD->SP = (INT_PTR)GetSP(pRD->pCurrentContext); + pRD->ControlPC = INT_PTR(GetIP(pRD->pCurrentContext)); +#elif defined(_TARGET_ARM_) + pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); + pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); +#elif defined(_TARGET_X86_) + pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); + pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); +#else // _TARGET_X86_ + PORTABILITY_ASSERT("SyncRegDisplayToCurrentContext"); +#endif + +#ifdef DEBUG_REGDISPLAY + CheckRegDisplaySP(pRD); +#endif // DEBUG_REGDISPLAY +} +#endif // _TARGET_64BIT_ || _TARGET_ARM_ || (_TARGET_X86_ && WIN64EXCEPTIONS) + +typedef REGDISPLAY *PREGDISPLAY; + +#ifdef WIN64EXCEPTIONS +inline void FillContextPointers(PT_KNONVOLATILE_CONTEXT_POINTERS pCtxPtrs, PT_CONTEXT pCtx) +{ +#ifdef _TARGET_AMD64_ + for (int i = 0; i < 16; i++) + { + *(&pCtxPtrs->Rax + i) = (&pCtx->Rax + i); + } +#elif defined(_TARGET_ARM64_) // _TARGET_AMD64_ + for (int i = 0; i < 12; i++) + { + *(&pCtxPtrs->X19 + i) = (&pCtx->X19 + i); + } +#elif defined(_TARGET_ARM_) // _TARGET_ARM64_ + // Copy over the nonvolatile integer registers (R4-R11) + for (int i = 0; i < 8; i++) + { + *(&pCtxPtrs->R4 + i) = (&pCtx->R4 + i); + } +#elif defined(_TARGET_X86_) // _TARGET_ARM_ + for (int i = 0; i < 7; i++) + { + *(&pCtxPtrs->Edi + i) = (&pCtx->Edi + i); + } +#else // _TARGET_X86_ + PORTABILITY_ASSERT("FillContextPointers"); +#endif // _TARGET_???_ (ELSE) +} +#endif // WIN64EXCEPTIONS + +inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pCallerCtx = NULL) +{ + WRAPPER_NO_CONTRACT; + + SUPPORTS_DAC; + +#ifndef WIN64EXCEPTIONS +#ifdef _TARGET_X86_ + pRD->pContext = pctx; + pRD->pContextForUnwind = NULL; + pRD->pEdi = &(pctx->Edi); + pRD->pEsi = &(pctx->Esi); + pRD->pEbx = &(pctx->Ebx); + pRD->pEbp = &(pctx->Ebp); + pRD->pEax = &(pctx->Eax); + pRD->pEcx = &(pctx->Ecx); + pRD->pEdx = &(pctx->Edx); + pRD->SP = pctx->Esp; + pRD->ControlPC = (PCODE)(pctx->Eip); + pRD->PCTAddr = (UINT_PTR)&(pctx->Eip); +#else // _TARGET_X86_ + PORTABILITY_ASSERT("FillRegDisplay"); +#endif // _TARGET_???_ (ELSE) + +#else // !WIN64EXCEPTIONS + pRD->pContext = pctx; + + // Setup the references + pRD->pCurrentContextPointers = &pRD->ctxPtrsOne; + pRD->pCallerContextPointers = &pRD->ctxPtrsTwo; + + pRD->pCurrentContext = &(pRD->ctxOne); + pRD->pCallerContext = &(pRD->ctxTwo); + + // copy the active context to initialize our stackwalk + *(pRD->pCurrentContext) = *(pctx); + + // copy the caller context as well if it's specified + if (pCallerCtx == NULL) + { + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. + } + else + { + *(pRD->pCallerContext) = *(pCallerCtx); + pRD->IsCallerContextValid = TRUE; + pRD->IsCallerSPValid = TRUE; // Don't add usage of this field. This is only temporary. + } + + FillContextPointers(&pRD->ctxPtrsOne, pctx); + +#if defined(_TARGET_ARM_) + // Fill volatile context pointers. They can be used by GC in the case of the leaf frame + pRD->volatileCurrContextPointers.R0 = &pctx->R0; + pRD->volatileCurrContextPointers.R1 = &pctx->R1; + pRD->volatileCurrContextPointers.R2 = &pctx->R2; + pRD->volatileCurrContextPointers.R3 = &pctx->R3; + pRD->volatileCurrContextPointers.R12 = &pctx->R12; + + pRD->ctxPtrsOne.Lr = &pctx->Lr; + pRD->pPC = &pRD->pCurrentContext->Pc; +#elif defined(_TARGET_ARM64_) // _TARGET_ARM_ + // Fill volatile context pointers. They can be used by GC in the case of the leaf frame + for (int i=0; i < 18; i++) + pRD->volatileCurrContextPointers.X[i] = &pctx->X[i]; +#endif // _TARGET_ARM64_ + +#ifdef DEBUG_REGDISPLAY + pRD->_pThread = NULL; +#endif // DEBUG_REGDISPLAY + + // This will setup the PC and SP + SyncRegDisplayToCurrentContext(pRD); +#endif // !WIN64EXCEPTIONS +} + +// Initialize a new REGDISPLAY/CONTEXT pair from an existing valid REGDISPLAY. +inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEXT *pOutCtx) +{ + WRAPPER_NO_CONTRACT; + + // The general strategy is to extract the register state from the input REGDISPLAY + // into the new CONTEXT then simply call FillRegDisplay. + + T_CONTEXT* pOutCallerCtx = NULL; + +#ifndef WIN64EXCEPTIONS + +#if defined(_TARGET_X86_) + if (pInRD->pEdi != NULL) {pOutCtx->Edi = *pInRD->pEdi;} else {pInRD->pEdi = NULL;} + if (pInRD->pEsi != NULL) {pOutCtx->Esi = *pInRD->pEsi;} else {pInRD->pEsi = NULL;} + if (pInRD->pEbx != NULL) {pOutCtx->Ebx = *pInRD->pEbx;} else {pInRD->pEbx = NULL;} + if (pInRD->pEbp != NULL) {pOutCtx->Ebp = *pInRD->pEbp;} else {pInRD->pEbp = NULL;} + if (pInRD->pEax != NULL) {pOutCtx->Eax = *pInRD->pEax;} else {pInRD->pEax = NULL;} + if (pInRD->pEcx != NULL) {pOutCtx->Ecx = *pInRD->pEcx;} else {pInRD->pEcx = NULL;} + if (pInRD->pEdx != NULL) {pOutCtx->Edx = *pInRD->pEdx;} else {pInRD->pEdx = NULL;} + pOutCtx->Esp = pInRD->SP; + pOutCtx->Eip = pInRD->ControlPC; +#else // _TARGET_X86_ + PORTABILITY_ASSERT("CopyRegDisplay"); +#endif // _TARGET_???_ + +#else // WIN64EXCEPTIONS + + *pOutCtx = *(pInRD->pCurrentContext); + if (pInRD->IsCallerContextValid) + { + pOutCallerCtx = pInRD->pCallerContext; + } + +#endif // WIN64EXCEPTIONS + + if (pOutRD) + FillRegDisplay(pOutRD, pOutCtx, pOutCallerCtx); +} + +// Get address of a register in a CONTEXT given the reg number. For X86, +// the reg number is the R/M number from ModR/M byte or base in SIB byte +inline size_t * getRegAddr (unsigned regNum, PTR_CONTEXT regs) +{ +#ifdef _TARGET_X86_ + _ASSERTE(regNum < 8); + + static const SIZE_T OFFSET_OF_REGISTERS[] = + { + offsetof(CONTEXT, Eax), + offsetof(CONTEXT, Ecx), + offsetof(CONTEXT, Edx), + offsetof(CONTEXT, Ebx), + offsetof(CONTEXT, Esp), + offsetof(CONTEXT, Ebp), + offsetof(CONTEXT, Esi), + offsetof(CONTEXT, Edi), + }; + + return (PTR_size_t)(PTR_BYTE(regs) + OFFSET_OF_REGISTERS[regNum]); +#elif defined(_TARGET_AMD64_) + _ASSERTE(regNum < 16); + return ®s->Rax + regNum; +#elif defined(_TARGET_ARM_) + _ASSERTE(regNum < 16); + return (size_t *)®s->R0 + regNum; +#elif defined(_TARGET_ARM64_) + _ASSERTE(regNum < 31); + return (size_t *)®s->X0 + regNum; +#else + _ASSERTE(!"@TODO Port - getRegAddr (Regdisp.h)"); +#endif + return(0); +} + +//--------------------------------------------------------------------------------------- +// +// This is just a simpler helper function to convert a REGDISPLAY to a CONTEXT. +// +// Arguments: +// pRegDisp - the REGDISPLAY to be converted +// pContext - the buffer for storing the converted CONTEXT +// +inline void UpdateContextFromRegDisp(PREGDISPLAY pRegDisp, PT_CONTEXT pContext) +{ + _ASSERTE((pRegDisp != NULL) && (pContext != NULL)); + +#ifndef WIN64EXCEPTIONS + +#if defined(_TARGET_X86_) + pContext->ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); + pContext->Edi = *pRegDisp->pEdi; + pContext->Esi = *pRegDisp->pEsi; + pContext->Ebx = *pRegDisp->pEbx; + pContext->Ebp = *pRegDisp->pEbp; + pContext->Eax = *pRegDisp->pEax; + pContext->Ecx = *pRegDisp->pEcx; + pContext->Edx = *pRegDisp->pEdx; + pContext->Esp = pRegDisp->SP; + pContext->Eip = pRegDisp->ControlPC; +#else // _TARGET_X86_ + PORTABILITY_ASSERT("UpdateContextFromRegDisp"); +#endif // _TARGET_???_ + +#else // WIN64EXCEPTIONS + + *pContext = *pRegDisp->pCurrentContext; + +#endif // WIN64EXCEPTIONS +} + + +#endif // __REGDISP_H + + diff --git a/lib/coreclr/src/inc/regex_base.h b/lib/coreclr/src/inc/regex_base.h new file mode 100644 index 0000000000..28097b2e27 --- /dev/null +++ b/lib/coreclr/src/inc/regex_base.h @@ -0,0 +1,973 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// Provides basic interpreted regular expression matching. This is meant as a debugging tool, +// and if regular expressions become necessary in a non-debug scenario great care should be +// used to ensure that performance is not impaired, and a more thorough review of this could +// would also be a good thing. This file does not include any concrete instantiations but +// instead provides the basic building blocks. Some concrete instantiations can be found in +// regex_util.h. +// +// NOTE: See code:clr::regex::RegExBase (below) for description of supported regex language. +// +// NOTE: we had to forego standard options such as tr1::regex +// (http://en.wikipedia.org/wiki/Technical_Report_1#Regular_Expressions) and Microsoft's +// internal GRETA regular expressions (http://toolbox/sites/987/default.aspx) because they +// both rely heavily on the STL, which can not currently be used within the CLR. +// +// NOTE: If this becomes non-debug-only, then read the comment on WCHARItemTraits for what +// what needs fixing. +// + +// + +#ifndef _REGEX_BASE_H_ +#define _REGEX_BASE_H_ + +// Forward declare namespace so that it is not debug-only (even if currently there is nothing +// but debug-only code in the namespace). This enables a "using namespace clr;" line in a +// header file without having to worry about whether or not it's in a debug-only block. +namespace clr {} + +#ifdef _DEBUG + +#include "utilcode.h" // for string hash functions +#include "sstring.h" + +namespace clr { +namespace regex { + +// Implementation details. Code contained in any "imp" namespace should never be directly used +// by clients of RegEx. +namespace imp { + + //=================================================================================================== + // Helper for clr::regex::RegExBase. See class definition for clr::regex::RegExBase below for more + // information. + + template + class RegExBaseHelper : protected ITEM_TRAITS + { + public: + typedef typename ITEM_TRAITS::RegexIterator RegexIterator; + typedef typename ITEM_TRAITS::InputIterator InputIterator; + + typedef typename ITEM_TRAITS::MatchFlags MatchFlags; + static const MatchFlags DefaultMatchFlags = ITEM_TRAITS::DefaultMatchFlags; + + // Arguments: + // regex : marks the start of the regular expression string. + // regexEnd : marks the end of the regular expression string. + // input : marks the start of the input string against which regex will be matched. + // inputEnd : marks the end of the input string. + // groups : recipient of regular expression groups. + // + // Returns true if the regular expression was successfully matched against the input string; + // otherwise false. + + RegExBaseHelper(const RegexIterator& regex, + const RegexIterator& regexEnd, + const InputIterator& input, + const InputIterator& inputEnd, + GROUP_CONTAINER& groups, + const MatchFlags flags = DefaultMatchFlags); + + // The main entrypoint to RegExBaseHelper, Match will attempt to match the regular expression + // defined by [regex,regexEnd) against the input defined by [input,inputEnd). + bool Match() + { WRAPPER_NO_CONTRACT; return DoMatch(m_regex, m_input); } + + protected: + typedef typename ITEM_TRAITS::Item Item; + typedef typename ITEM_TRAITS::ItemType ItemType; + + // Try to match regex at any point within input, starting with the first character and moving + // along one at a time until a match is found or the end of the input is encountered, whichever + // comes first. + bool DoMatch( + const RegexIterator& regex, + InputIterator input); + + // Try to match regex starting exactly at input. + bool DoMatchHere( + const RegexIterator& regex, + const InputIterator& input); + + // The function returns true if a match is found consisting of zero or more items c followed by a + // successful match of regex on the remaining input; otherwise false is returned. This is a + // conservative match, so it starts with trying to match zero items followed by regex, + // and will then try to match one item followed by regex. + bool DoMatchStar( + const Item& c, + const RegexIterator& regex, + InputIterator input); + + // The function returns true if a match is found consisting of zero or more items c followed by a + // successful match of regex on the remaining input; otherwise false is returned. This is a + // greedy match, so it starts with trying to match as many items as it can followed by regex, + // and on failure will try again with one less items matched. + bool DoMatchStarEagerly( + const Item& c, + const RegexIterator& regex, + InputIterator input); + + // Convenience method. + Item GetItem( + const RegexIterator ®ex) + { WRAPPER_NO_CONTRACT; return ITEM_TRAITS::GetItem(regex, m_regexEnd, m_flags); } + + // Convenience method. + bool MatchItem( + const Item& c, + const InputIterator& input) + { WRAPPER_NO_CONTRACT; return ITEM_TRAITS::MatchItem(c, input, m_inputEnd, m_flags); } + + // Declared as protected to prevent direct instantiation. + RegExBaseHelper() + {} + + RegexIterator m_regex; + RegexIterator m_regexEnd; + InputIterator m_input; + InputIterator m_inputEnd; + GROUP_CONTAINER& m_groups; + MatchFlags m_flags; + }; + + //--------------------------------------------------------------------------------------------------- + // This method simply stores the end iterators for the regular expression and the input strings, as + // well as the group collection object and flags, and forwards the call to DoMatch. + + template + RegExBaseHelper::RegExBaseHelper( + const RegexIterator& regex, + const RegexIterator& regexEnd, + const InputIterator& input, + const InputIterator& inputEnd, + GROUP_CONTAINER& groups, + const MatchFlags flags) + : m_regex(regex), + m_regexEnd(regexEnd), + m_input(input), + m_inputEnd(inputEnd), + m_groups(groups), + m_flags(flags) + { WRAPPER_NO_CONTRACT; } + + //--------------------------------------------------------------------------------------------------- + // This method checks if the regular expression starts with a caret, indicating that any match must + // be anchored at the start of the input string. If such a caret exists, one match attempt is made + // on the input starting with the first character and the result is returned. If the regex does not + // start with a caret, the method attempts to match against the input string, starting at the first + // character and moving one character over for each successive attempt, until a match is found or + // the end of the input is encountered, whichever comes first. + + template + inline bool + RegExBaseHelper::DoMatch( + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + + if (GetItem(regex).GetType() == ITEM_TRAITS::CARET) + { // Match must occur from the beginning of the line + m_groups.OpenGroup(input, m_inputEnd); + bool res = DoMatchHere(regex+1, input); + if (!res) + m_groups.CancelGroup(); + return res; + } + else + { // Match can happen anywhere in the string + do + { // Attempt to match against each substring [x,inputEnd) for x = 0...inputEnd + + // Begin the group that contains the entire match. + m_groups.OpenGroup(input, m_inputEnd); + + if (DoMatchHere(regex, input)) + { // Success. Note that the entire match group is closed elsewhere on a + // successful match. + return true; + } + + // On failure, cancel the group so that it can be reopened on the new substring + m_groups.CancelGroup(); + } while (input++ != m_inputEnd); + } + + // No successful match found. + return false; + } + + //------------------------------------------------------------------------------------------------------- + // This is the main loop, which handles grouping constructs, repetition directives (*, *?, +, +?), and + // EOL matches ($), delegating all character matching to ITEM_TRAITS::MatchItem + // The general algorithm is: + // 1. Get the next item. + // 2. If the item is a DOLLAR type, check to see if we're at the end of the retular expression and + // the input string, and if so return success. + // 3. If the item is a grouping construct, open or close the appropriate group and continue matching. + // On failure, roll back the grouping change so that subsequent attemts will have correct state. + // 4. Check to see if the item following the current is a repetition directive, and if so take the + // appropriate action. + // 5. Otherwise defer to ITEM_TRAITS::MatchItem and if successful continue to match the remaining + // regular expression and input string; otherwise return failure. + + template + inline bool + RegExBaseHelper::DoMatchHere( + const RegexIterator& regex, + const InputIterator& input) + { + WRAPPER_NO_CONTRACT; + + if (regex == m_regexEnd) + { // Reached the end of the regular expression without ever returning false, + // implying a successful match. Close the overall match group and return. + m_groups.CloseGroup(input); + return true; + } + + Item c0 = GetItem(regex); + if (c0.GetType() == ITEM_TRAITS::DOLLAR && (c0.GetNext() == m_regexEnd)) + { // Matches EOL if a '$' is encountered at the end of the input. + m_groups.CloseGroup(input); + // Success only if we're actually at the end of the input string. + return input == m_inputEnd; + } + if (c0.GetType() == ITEM_TRAITS::PAREN_OPEN) + { // Encountered an open parenthesis ('('); open a new grouping. + m_groups.OpenGroup(input, m_inputEnd); + bool res = DoMatchHere(c0.GetNext(), input); + if (!res) + { // If a match fails, there could be further attempts (such as if + // there is an active repetition matching frame beneath us), so + // need to cancel the group we just opened so that the grouping + // structure remains consistent. + m_groups.CancelGroup(); + } + return res; + } + if (c0.GetType() == ITEM_TRAITS::PAREN_CLOSE) + { // Close the most recent open grouping. + COUNT_T i = m_groups.CloseGroup(input); + bool res = DoMatchHere(c0.GetNext(), input); + if (!res) + { // For the same reasons as the need to cancel an opened group + // explained above, we need to reopen the closed group if a + // match fails. + m_groups.ReopenGroup(i, m_inputEnd); + } + return res; + } + + if (c0.GetNext() != m_regexEnd) + { // If there is another item in the regex string following the current one, get + // it to see if it is a repetition matching directive. + Item c1 = GetItem(c0.GetNext()); + if (c1.GetType() == ITEM_TRAITS::STAR) + { // '*' matching directive encountered + if (c1.GetNext() != m_regexEnd) + { + Item c2 = GetItem(c1.GetNext()); + if (c2.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // conservative matching semantics requested + return DoMatchStar(c0, c2.GetNext(), input); + } + } + // Eager matching + return DoMatchStarEagerly(c0, c1.GetNext(), input); + } + if (c1.GetType() == ITEM_TRAITS::PLUS) + { // '+' matching directive encountered. + if (c1.GetNext() != m_regexEnd) + { + Item c2 = GetItem(c1.GetNext()); + if (c2.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // conservative matching semantics requested + return MatchItem(c0, input) && DoMatchStar(c0, c2.GetNext(), input+1); + } + } + // Eager matching + return MatchItem(c0, input) && DoMatchStarEagerly(c0, c1.GetNext(), input+1); + } + if (c1.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // '?' matching directive encountered + return (MatchItem(c0, input) && DoMatchHere(c1.GetNext(), input+1)) || DoMatchHere(c1.GetNext(), input); + } + } + + // No special matching semantics encountered, delegate the matching to ITEM_TRAITS::MatchItem + return MatchItem(c0, input) && DoMatchHere(c0.GetNext(), input+1); + } + + //------------------------------------------------------------------------------------------------------- + // Conservative '*' repetition matching. This attempts to match zero items c followed by a match of + // regex. If this fails, attempt to match one item c followed by a match of regex. Repeat until item c + // does not match or a successful match is found. + + template + inline bool + RegExBaseHelper::DoMatchStar( + const Item& c, + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(input != m_inputEnd); + + do { + if (DoMatchHere(regex, input)) + { // A successful match is found! + return true; + } + // No successful match, so try to match one more item and then attempt to match regex on the + // remaining input. + } while (input != m_inputEnd && MatchItem(c, input++)); + return false; + } + + //------------------------------------------------------------------------------------------------------- + // Similar to DoMatchStar above, except this algorithm matches as many items c as possible first followed + // by regex on the remaining input, and on failure tries again with a match against one less item c + // followed by regex on the remaining input, and repeats until there are no items c remaining to match + // and the zero item match followed by a match of regex on the entire remaining input fails. If any of + // the match attempts succeed, return success. + + template + inline bool + RegExBaseHelper::DoMatchStarEagerly( + const Item& c, + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + + // Make sure we keep a hold of how far back we can unwind. + InputIterator inputOrig = input; + + // First, determine the maximum number of matches against item c. + while (input != m_inputEnd && MatchItem(c, input)) + { + ++input; + } + + do + { // Work backwards from the maximum number of matches of item c until a match is found + // or until we have backed right up to the starting value of input (saved in inputOrig), + // at which time we admit failure. + if (DoMatchHere(regex, input)) + return true; + } while (inputOrig != input--); + return false; + } + +} // namespace imp + +//======================================================================================================= +// Represents a matched group using iterators to denote the string contained by [Begin(),End()). + +template +class Group +{ +public: + typedef INPUT_ITERATOR InputIterator; + + // + // Functions for accessing group properties + // + + // Returns the iterator indicating the start of the group + const InputIterator& Begin() const + { LIMITED_METHOD_CONTRACT; return m_begin; } + + // Returns the iterator indicating the first non-member of the group + const InputIterator& End() const + { LIMITED_METHOD_CONTRACT; return m_end; } + + // It is possible that m_end - m_begin could be greater than the maximum of COUNT_T. m_end and + // m_begin are the end and start of a string, so is entirely unlikely to overflow a COUNT_T. + // Conbined with the fact that this is debug-only code, opting not to replace all COUNT_T + // uses with SIZE_T. + COUNT_T Length() const + { WRAPPER_NO_CONTRACT; return static_cast(m_end - m_begin); } + + // + // Functions used by RegExBaseHelper to create grouping constructs. + // + + Group() + : m_isClosed(false), m_begin(), m_end() + { WRAPPER_NO_CONTRACT; } + + Group(const InputIterator& start, const InputIterator& end, bool isClosed = false) + : m_isClosed(isClosed), m_begin(start), m_end(end) + { WRAPPER_NO_CONTRACT; } + + void SetBegin(const InputIterator& start) + { WRAPPER_NO_CONTRACT; m_begin = start; } + + void SetEnd(const InputIterator& end) + { WRAPPER_NO_CONTRACT; m_end = end; } + + bool IsClosed() const + { LIMITED_METHOD_CONTRACT; return m_isClosed; } + + void SetIsClosed(bool isClosed) + { WRAPPER_NO_CONTRACT; m_isClosed = isClosed; } + +protected: + bool m_isClosed; + InputIterator m_begin; + InputIterator m_end; +}; + +//======================================================================================================= +// Represents a generic container of groups, defaulting to using Group as its element +// type. This container satisfies the method requrements of RegExBase. When a match is successful, the +// match groups may be accessed using the index operator or the iterators definin the matched groups +// [Begin(), End()). + +template > +class GroupContainer +{ +public: + typedef typename SArray::Iterator Iterator; + + // + // Functions for enumerating groups + // + + GROUP_TYPE & operator[](COUNT_T idx) + { + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(((COUNT_T)(COUNT_T)idx) == idx); + return m_array[idx]; + } + + // Returns an iterator to the first matched group (which is always the string for the + // entire successfully matched string. Specific groups start at Begin()+1 and continue + // to End()-1. + Iterator Begin() + { WRAPPER_NO_CONTRACT; return m_array.Begin(); } + + // Returns the first invalid iterator value. + Iterator End() + { WRAPPER_NO_CONTRACT; return m_array.End(); } + + // + COUNT_T Count() const + { WRAPPER_NO_CONTRACT; return m_array.GetCount(); } + + // + // Functions used by RegExBaseHelper to create grouping constructs. + // + + // Note: OpenGroup takes an end iterator so that the group will have a valid (if possibly + // incorrect) endpoint in the case that the regular expression has unbalanced grouping + // parentheses. + void OpenGroup(const INPUT_ITERATOR& start, const INPUT_ITERATOR& end) + { WRAPPER_NO_CONTRACT; m_array.Append(GROUP_TYPE(start, end, false)); } + + COUNT_T CloseGroup(const INPUT_ITERATOR& end); + + void ReopenGroup(COUNT_T i, const INPUT_ITERATOR& end); + + void CancelGroup() + { WRAPPER_NO_CONTRACT; m_array.Delete(m_array.End() - 1); } + +private: + SArray m_array; +}; + +//------------------------------------------------------------------------------------------------------- +// Works backwards from the most recently created group looking for an open group to close. Returns +// the index of the group that was closed, which is used in the event that a group needs to be +// reopened. + +template +COUNT_T +GroupContainer::CloseGroup( + const INPUT_ITERATOR& end) +{ + WRAPPER_NO_CONTRACT; + + for (COUNT_T i = (COUNT_T)Count(); i > 0; --i) + { + if (!m_array[i-1].IsClosed()) + { + m_array[i-1].SetEnd(end); + m_array[i-1].SetIsClosed(true); + return i-1; + } + } + + _ASSERTE(!"Unmatched grouping constructs!"); + return 0; +} + +//------------------------------------------------------------------------------------------------------- +// Reopen a group at the given index, using 'end' to overwrite the current end. + +template +void +GroupContainer::ReopenGroup( + COUNT_T i, + const INPUT_ITERATOR& end) +{ + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(i > 0 && i < Count()); + + if (i > 0 && i < Count()) + { + m_array[i].SetEnd(end); + m_array[i].SetIsClosed(false); + } +} + +//======================================================================================================= +// Empty group container that satisfies the method requirements of RegExBase but has empty bodies. This +// allows for non-allocating matches when grouping is not required. + +template +class NullGroupContainer +{ +public: + void OpenGroup(INPUT_ITERATOR, INPUT_ITERATOR) {} + COUNT_T CloseGroup(INPUT_ITERATOR) { return 0; } + void ReopenGroup(COUNT_T, INPUT_ITERATOR) {} + void CancelGroup() {} +}; + +//======================================================================================================= +// This mini-implementation of regular expression matching supports the +// following constructs: +// ^ matches the beginning of the input string +// $ matches the end of the input string +// * matches zero or more occurrences of the previous item eagerly +// *? matches zero or more occurrences of the previous item conservatively +// + matches 1 or more occurrences of the previous item eagerly +// +? matches 1 or more occurrences of the previous item conservatively +// ? matches 0 or 1 occurences of the previous item +// ( starts a grouping +// ) ends a grouping +// +// IMPORTANT: These are just anchoring and grouping constructs. See the definition for ItemTraitsBase +// below for information on the default character classes that are supported. (The intent of +// this separation is to allow customization of the character classes where required.) + +// ITEM_TRAITS provides traits for individual tokens in a regular expression, as well as a mechanism for +// matching said individual components with the target string. RegexBase derives from ITEM_TRAITS in a +// protected fashion, and is responsible for providing the following: +// 1. "RegexIterator" typedef +// Used as an iterator into the regular expression, and used as arguments to indicate the start +// and the end of the regular expression string. +// 2. "InputIterator" typedef +// Used as an iterator into the input string, and used as arguments to indicate the start +// and the end of the input string. +// (NOTE: RegexIterator and InputIterator are often typedef'ed to be the same thing.) +// 3. "Item" typedef. +// This will be used with methods GetItem and MatchItem (see below). Item must +// define the the following methods: +// ItemType GetType() : returns the type of the item. See below for explanation of ItemType +// const RegexIterator& GetNext() : iterator pointing to the start of the next item. +// 4. "MatchFlags" typedef, and "static const DefaultMatchFlags" value. +// Provided for calls to "Match" and "Matches", and passed on to calls "GetItem" and "MatchItem". +// 5. enum ItemType +// Defines the following minimum values: +// DOT +// CARET +// DOLLAR +// STAR +// QUESTION_MARK +// PLUS +// PAREN_OPEN +// PAREN_CLOSE +// ItemType may include more values, and may even choose to ignore the above enum types, all of +// which must be recognized by GetItem and MatchItem (see below). +// 6. static Item GetItem(const RegexIterator& regex, +// const RegexIterator& regexEnd, +// const MatchFlags& flags) +// This method takes a regular expression iterator and returns the next regular expression +// element (Item) pointed to by the iterator. +// 7. static bool MatchItem(const Item& c, +// const InputIterator& input, +// const InputIterator& inputEnd, +// const MatchFlags &flags) + +// GROUP_CONTAINER provides functionality for keeping track of regular expression groups. This is a generic +// argument to Match, and the type of the object must support the following methods: +// 1. void OpenGroup(const InputIterator& start, const InputIterator& end); +// Called when a PAREN_OPEN item is encountered. +// 2. COUNT_T CloseGroup(const InputIterator& end); +// Called when a PAREN_CLOSE item is encountered. Returns the index of the group that was closed. +// 3. void ReopenGroup(COUNT_T i, const InputIterator& end); +// Called when a match following a call to CloseGroup fails, essentially requesting a rollback +// of the call to CloseGroup. +// 4. void CancelGroup(); +// Called when a match following a call to OpenGroup fails, essentially requesting a rollback +// of the call to OpenGroup. + +template +class RegExBase : public ITEM_TRAITS +{ +public: + typedef typename ITEM_TRAITS::RegexIterator RegexIterator; + typedef typename ITEM_TRAITS::InputIterator InputIterator; + + // This is a convenience typedef that allows a caller to easily declare a grouping container + // to be passed to a call to Match. An example would be (see regex_util.h for a definition of + // SStringRegEx): + // + // SString input(SL"Simmons"); + // SStringRegEx::GroupingContainer container; + // if (SStringRegEx::Match(SL"(Sim+on)", input, container)) { + // printf("%S", container[1].GetSString(input).GetUnicode()); + // } + // + typedef GroupContainer > GroupingContainer; + + // Pulls down the typedef for MatchFlags and initialized a static representing the default flags. + typedef typename ITEM_TRAITS::MatchFlags MatchFlags; + static const MatchFlags DefaultMatchFlags = ITEM_TRAITS::DefaultMatchFlags; + + template + static bool Match(RegexIterator regex, + RegexIterator regexEnd, + InputIterator input, + InputIterator inputEnd, + GROUP_CONTAINER& groups, + MatchFlags flags = DefaultMatchFlags) + { + imp::RegExBaseHelper + re(regex, regexEnd, input, inputEnd, groups, flags); + return re.Match(); + } + + static bool Matches(RegexIterator regex, + RegexIterator regexEnd, + InputIterator input, + InputIterator inputEnd, + MatchFlags flags = DefaultMatchFlags) + { + NullGroupContainer ngc; + return Match(regex, regexEnd, input, inputEnd, ngc, flags); + } +}; + +//======================================================================================================= +// In addition to requirements specified on RegExBase, StandardItemTraits provides the following +// additinal regular expression item types. +// c matches any literal character c +// . matches any single character +// \d any literal digit character +// \w any alpha character +// \s any whitespace character +// +// Child types of ItemTraitsBase must implement GetItem and MatchItem (see below for full +// signature requirements). Current child type implementations permit a backslash ('\') to escape +// special characters ('.', '$', '*', etc.) and allow them to be interpreted as literal characters. +// +// This type describes a particular behaviour, but must be subtyped for the particular target character +// needed, and GetItem and MatchItem must be implemented. +// + +template +class ItemTraitsBase +{ +public: + typedef ITERATOR_TYPE RegexIterator; + typedef ITERATOR_TYPE InputIterator; + + enum MatchFlags + { + MF_NONE = 0x00, + MF_CASE_INSENSITIVE = 0x01 // Match character literals as case insensitive. + }; + + static const MatchFlags DefaultMatchFlags = MF_NONE; + +protected: + ItemTraitsBase() + {} + + enum ItemType + { + // REQUIRED, as described in RegExBase + CARET, + DOLLAR, + STAR, + QUESTION_MARK, + PLUS, + PAREN_OPEN, + PAREN_CLOSE, + // ADDITIONAL + DOT, // any literal character + DIGIT, // any digit + ALPHA, // any alpha character, upper or lower case + WHITESPACE, // any whitespace character + NON_WHITESPACE, // any non-whitespace character + CHARACTER, // a specific literal character + }; + + class Item + { + public: + Item(ItemType type, CHAR_TYPE val, const RegexIterator& next) + : m_type(type), m_val(val), m_next(next) + { WRAPPER_NO_CONTRACT; } + + Item(ItemType type, const RegexIterator& next) + : m_type(type), m_val(0), m_next(next) + { WRAPPER_NO_CONTRACT; } + + ItemType GetType() const + { LIMITED_METHOD_CONTRACT; return m_type; } + + const RegexIterator& GetNext() const + { LIMITED_METHOD_CONTRACT; return m_next; } + + CHAR_TYPE GetValue() const + { LIMITED_METHOD_CONTRACT; return m_val; } + + protected: + ItemType m_type; + CHAR_TYPE m_val; + RegexIterator m_next; + }; + + // All deriving types must add the following methods: + // static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd); + // static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd); +}; + +//======================================================================================================= +// Implements ItemTraitsBase, provides matching for UNICODE characters. +// +// !!!IMPORTANT!!! +// This is not a complete unicode implementation - only the equivalent of ASCII alpha characters are +// consider to be part of the alpha set, and this is also the only set on which case insensitive +// operations will correctly work. If RegEx is moved out of DEBUG ONLY, then this will have to be fixed +// to properly address these issues. +// !!!IMPORTANT!!! + +template +class WCHARItemTraits : public ItemTraitsBase +{ +public: + typedef ItemTraitsBase PARENT_TYPE; + typedef typename PARENT_TYPE::RegexIterator RegexIterator; + typedef typename PARENT_TYPE::InputIterator InputIterator; + typedef typename PARENT_TYPE::Item Item; + typedef typename PARENT_TYPE::MatchFlags MatchFlags; + + static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd, MatchFlags flags); + static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd, MatchFlags flags); + +protected: + WCHARItemTraits() + {} + +private: + static inline bool IS_UPPER_A_TO_Z(WCHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= W('A')) && ((x) <= W('Z'))); } + + static inline bool IS_LOWER_A_TO_Z(WCHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= W('a')) && ((x) <= W('z'))); } + + static inline WCHAR UPCASE(WCHAR x) + { WRAPPER_NO_CONTRACT; return (IS_LOWER_A_TO_Z(x) ? ((x) - W('a') + W('A')) : (x)); } + + static inline WCHAR DOWNCASE(WCHAR x) + { WRAPPER_NO_CONTRACT; return (IS_UPPER_A_TO_Z(x) ? ((x) - W('A') + W('a')) : (x)); } + + static bool MatchCharacter(WCHAR c1, WCHAR c2, MatchFlags flags) + { WRAPPER_NO_CONTRACT; return (flags & PARENT_TYPE::MF_CASE_INSENSITIVE) ? (DOWNCASE(c1) == DOWNCASE(c2)) : (c1 == c2); } +}; + +//------------------------------------------------------------------------------------------------------- +// Reads the next item from regex, recognizing special characters outlined in ItemTraitsBase. + +template +typename WCHARItemTraits::Item +WCHARItemTraits::GetItem( + const RegexIterator& regex, + const RegexIterator& regexEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (*regex == W('\\')) + { + const RegexIterator regexNext = regex+1; + if (regexNext == regexEnd) + return Item(PARENT_TYPE::CHARACTER, W('\\'), regexNext); + if (*regexNext == W('d')) + return Item(PARENT_TYPE::DIGIT, regexNext+1); + if (*regexNext == W('w')) + return Item(PARENT_TYPE::ALPHA, regexNext+1); + if (*regexNext == W('s')) + return Item(PARENT_TYPE::WHITESPACE, regexNext+1); + if (*regexNext == W('S')) + return Item(PARENT_TYPE::NON_WHITESPACE, regexNext+1); + return Item(PARENT_TYPE::CHARACTER, *regexNext, regexNext+1); + } + else if (*regex == W('.')) + return Item(PARENT_TYPE::DOT, W('.'), regex+1); + else if (*regex == W('^')) + return Item(PARENT_TYPE::CARET, W('^'), regex+1); + else if (*regex == W('$')) + return Item(PARENT_TYPE::DOLLAR, W('$'), regex+1); + else if (*regex == W('*')) + return Item(PARENT_TYPE::STAR, W('*'), regex+1); + else if (*regex == W('?')) + return Item(PARENT_TYPE::QUESTION_MARK, W('?'), regex+1); + else if (*regex == W('+')) + return Item(PARENT_TYPE::PLUS, W('+'), regex+1); + else if (*regex == W('(')) + return Item(PARENT_TYPE::PAREN_OPEN, W('('), regex+1); + else if (*regex == W(')')) + return Item(PARENT_TYPE::PAREN_CLOSE, W(')'), regex+1); + else + return Item(PARENT_TYPE::CHARACTER, *regex, regex + 1); +} + +//------------------------------------------------------------------------------------------------------- +// Returns true if the next character point to by input matches the character class described by c. + +template +bool +WCHARItemTraits::MatchItem( + const Item& c, + const InputIterator& input, + const InputIterator& inputEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (c.GetType() == PARENT_TYPE::DIGIT) + return *input >= W('0') && *input <= W('9'); + else if (c.GetType() == PARENT_TYPE::ALPHA) + return (*input >= W('a') && *input <= W('z')) || (*input >= W('A') && *input <= W('Z')); + else if (c.GetType() == PARENT_TYPE::WHITESPACE) + return *input == W(' ') || *input == W('\t'); + else if (c.GetType() == PARENT_TYPE::NON_WHITESPACE) + return !(*input == W(' ') || *input == W('\t')); + else + return c.GetType() == PARENT_TYPE::DOT || MatchCharacter(c.GetValue(), *input, flags); +} + +//======================================================================================================= +// Implements ItemTraitsBase, provides matching for ASCII (*not* UTF8) characters. + +template +class CHARItemTraits : public ItemTraitsBase +{ +public: + typedef ItemTraitsBase PARENT_TYPE; + typedef typename PARENT_TYPE::RegexIterator RegexIterator; + typedef typename PARENT_TYPE::InputIterator InputIterator; + typedef typename PARENT_TYPE::Item Item; + typedef typename PARENT_TYPE::MatchFlags MatchFlags; + + static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd, MatchFlags flags); + static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd, MatchFlags flags); + +protected: + CHARItemTraits() + {} + +private: + static inline bool IS_UPPER_A_TO_Z(CHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= 'A') && ((x) <= 'Z')); } + + static inline bool IS_LOWER_A_TO_Z(CHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= 'a') && ((x) <= 'z')); } + + static inline CHAR UPCASE(CHAR x) + { WRAPPER_NO_CONTRACT; return (IS_LOWER_A_TO_Z(x) ? ((x) - 'a' + 'A') : (x)); } + + static inline CHAR DOWNCASE(CHAR x) + { WRAPPER_NO_CONTRACT; return (IS_UPPER_A_TO_Z(x) ? ((x) - 'A' + 'a') : (x)); } + + static bool MatchCharacter(CHAR c1, CHAR c2, MatchFlags flags) + { WRAPPER_NO_CONTRACT; return (flags & PARENT_TYPE::MF_CASE_INSENSITIVE) ? (DOWNCASE(c1) == DOWNCASE(c2)) : (c1 == c2); } +}; + +//------------------------------------------------------------------------------------------------------- +// Reads the next item from regex, recognizing special characters outlined in ItemTraitsBase. + +template +typename CHARItemTraits::Item +CHARItemTraits::GetItem( + const RegexIterator& regex, + const RegexIterator& regexEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (*regex == '\\') + { + const RegexIterator regexNext = regex+1; + if (regexNext == regexEnd) + return Item(PARENT_TYPE::CHARACTER, W('\\'), regexNext); + if (*regexNext == 'd') + return Item(PARENT_TYPE::DIGIT, regexNext+1); + if (*regexNext == 'w') + return Item(PARENT_TYPE::ALPHA, regexNext+1); + if (*regexNext == 's') + return Item(PARENT_TYPE::WHITESPACE, regexNext+1); + return Item(PARENT_TYPE::CHARACTER, *regexNext, regexNext+1); + } + else if (*regex == '.') + return Item(PARENT_TYPE::DOT, '.', regex+1); + else if (*regex == '^') + return Item(PARENT_TYPE::CARET, '^', regex+1); + else if (*regex == '$') + return Item(PARENT_TYPE::DOLLAR, '$', regex+1); + else if (*regex == '*') + return Item(PARENT_TYPE::STAR, '*', regex+1); + else if (*regex == '?') + return Item(PARENT_TYPE::QUESTION_MARK, '?', regex+1); + else if (*regex == '+') + return Item(PARENT_TYPE::PLUS, '+', regex+1); + else if (*regex == '(') + return Item(PARENT_TYPE::PAREN_OPEN, '(', regex+1); + else if (*regex == ')') + return Item(PARENT_TYPE::PAREN_CLOSE, ')', regex+1); + else + return Item(PARENT_TYPE::CHARACTER, *regex, regex + 1); +} + +//------------------------------------------------------------------------------------------------------- +// Returns true if the next character point to by input matches the character class described by c. + +template +bool +CHARItemTraits::MatchItem( + const Item& c, + const InputIterator& input, + const InputIterator& inputEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (c.GetType() == PARENT_TYPE::DIGIT) + return *input >= W('0') && *input <= W('9'); + else if (c.GetType() == PARENT_TYPE::ALPHA) + return (*input >= W('a') && *input <= W('z')) || (*input >= W('A') && *input <= W('Z')); + else if (c.GetType() == PARENT_TYPE::WHITESPACE) + return *input == W(' ') || *input == W('\t'); + else + return c.GetType() == PARENT_TYPE::DOT || MatchCharacter(c.GetValue(), *input, flags); +} + +} /* namespace regex */ +} /* namespace clr */ + +#endif // _DEBUG + +#endif // _REGEX_BASE_H_ diff --git a/lib/coreclr/src/inc/regex_util.h b/lib/coreclr/src/inc/regex_util.h new file mode 100644 index 0000000000..438c8b133a --- /dev/null +++ b/lib/coreclr/src/inc/regex_util.h @@ -0,0 +1,209 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// See regex_base.h for more information. +// +// This header creates some concrete instantiations of RegExBase for commonly used scenarios. In +// particular, basic regular expression matching base on the regular expression language described in +// clr::regex::ItemTraitsBase (found in regex_base.h) is instantiated for use with SString, ASCII and +// UNICODE strings (clr::regex::SStringRegex, clr::regex::WSTRRegEx, and clr::regex::STRRegEx +// respectively). Each type definition includes an example of its use. +// + +// + +#ifndef _REGEX_UTIL_H_ +#define _REGEX_UTIL_H_ + +#ifndef MODE_ANY +#define MODE_ANY +#endif + +#include "regex_base.h" + +#ifdef _DEBUG + +namespace clr +{ +namespace regex +{ + +//======================================================================================================= +// Derives from Group to provide two additional convenience methods (GetSString variants). + +class SStringGroup : public Group +{ +public: + SStringGroup() + : Group() + { WRAPPER_NO_CONTRACT; } + + SStringGroup(const InputIterator& _start, const InputIterator& _end, bool _isClosed = false) + : Group(_start, _end, _isClosed) + { WRAPPER_NO_CONTRACT; } + + // Since SStrings constructed from ranges require the original source string, this is a required + // input argument. Returns the input substring that matches the corresponding grouping. + SString GetSString(const SString& src) + { WRAPPER_NO_CONTRACT; return SString(src, Begin(), End()); } + + // Since SStrings constructed from ranges require the original source string, this is a required + // input argument. This version takes a target SString as a buffer, and also returns this buffer + // as a reference. Returns the input substring that matches the corresponding grouping. + SString& GetSString(const SString& src, SString& tgt) + { WRAPPER_NO_CONTRACT; tgt.Set(src, Begin(), End()); return tgt; } +}; + +//======================================================================================================= +typedef WCHARItemTraits SStringItemTraits; + +//======================================================================================================= +// Regular expression matching with SStrings. +// +// Here is an example of how to use SStringRegEx with grouping enabled. +// +// using namespace clr::regex; +// SString input(SL"Simmons"); // usually this is derived from some variable source +// SStringRegEx::GroupingContainer container; +// if (SStringRegEx::Match(SL"(Sim+on)", input, container)) { +// printf("%S", container[1].GetSString(input).GetUnicode()); +// } +// +// This sample should result in "Simmon" being printed. + + +class SStringRegEx : public RegExBase +{ + typedef RegExBase PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + typedef PARENT_TYPE::InputIterator InputIterator; + + typedef GroupContainer GroupingContainer; + + static bool Match( + const SString& regex, + const SString& input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex.Begin(), regex.End(), input.Begin(), input.End(), groups, flags); + } + + static bool Matches( + const SString& regex, + const SString& input, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Matches(regex.Begin(), regex.End(), input.Begin(), input.End(), flags); + } + +}; + +//======================================================================================================= +// Regular expression matching with UNICODE strings. +// +// Here is an example of how to use WSTRRegEx to match against a null-terminated string without grouping. +// +// using namespace clr::regex; +// LPCWSTR input = L"Simmons"; +// if (WSTRRegEx::Matches(L"Sim+on", input)) +// printf("Match succeeded"); +// else +// printf("Match failed"); +// +// This sample should result in "Match succeeded" being printed. + +class WSTRRegEx : public RegExBase > +{ + typedef RegExBase > PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + static bool Match( + LPCWSTR regex, + LPCWSTR input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex, regex + wcslen(regex), input, input + wcslen(input), groups, flags); + } + + static bool Matches( + LPCWSTR regex, + LPCWSTR input, + MatchFlags flags = DefaultMatchFlags) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + return Matches(regex, regex + wcslen(regex), input, input + wcslen(input), flags); + } +}; + +//======================================================================================================= +// Regular expression matching with ASCII strings. +// +// Here is an example of how to use STRRegEx to match against a substring based on begin and end range +// pointers, with grouping disabled and case insensitivity enabled. +// +// using namespace clr::regex; +// LPCSTR input = "123Simmons456"; +// if (STRRegEx::Matches("Sim+on", input+3, input+10, STRRegEx::MF_CASE_INSENSITIVE)) +// printf("Match succeeded"); +// else +// printf("Match failed"); +// +// This sample should result in "Match succeeded" being printed. + +class STRRegEx : public RegExBase > +{ + typedef RegExBase > PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + static bool Match( + LPCSTR regex, + LPCSTR input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex, regex + strlen(regex), input, input + strlen(input), groups, flags); + } + + static bool Matches( + LPCSTR regex, + LPCSTR input, + MatchFlags flags = DefaultMatchFlags) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + return Matches(regex, regex + strlen(regex), input, input + strlen(input), flags); + } +}; + +} // namespace regex +} // namespace clr + +#endif // _DEBUG + +#endif // _REGEX_UTIL_H_ diff --git a/lib/coreclr/src/inc/registrywrapper.h b/lib/coreclr/src/inc/registrywrapper.h new file mode 100644 index 0000000000..0fbeee2356 --- /dev/null +++ b/lib/coreclr/src/inc/registrywrapper.h @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// File: registrywrapper.h +// +// Wrapper around Win32 Registry Functions allowing redirection of .NET +// Framework root registry location +// +//***************************************************************************** +#ifndef __REGISTRYWRAPPER_H +#define __REGISTRYWRAPPER_H + + +#define ClrRegCreateKeyEx RegCreateKeyExW +#define ClrRegOpenKeyEx RegOpenKeyExW +#define IsNgenOffline() false + + +#endif // __REGISTRYWRAPPER_H diff --git a/lib/coreclr/src/inc/releaseholder.h b/lib/coreclr/src/inc/releaseholder.h new file mode 100644 index 0000000000..b2c42e3928 --- /dev/null +++ b/lib/coreclr/src/inc/releaseholder.h @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// This class acts a smart pointer which calls the Release method on any object +// you place in it when the ReleaseHolder class falls out of scope. You may use it +// just like you would a standard pointer to a COM object (including if (foo), +// if (!foo), if (foo == 0), etc) except for two caveats: +// 1. This class never calls AddRef and it always calls Release when it +// goes out of scope. +// 2. You should never use & to try to get a pointer to a pointer unless +// you call Release first, or you will leak whatever this object contains +// prior to updating its internal pointer. +template +class ReleaseHolder +{ +public: + ReleaseHolder() + : m_ptr(NULL) + {} + + ReleaseHolder(T* ptr) + : m_ptr(ptr) + {} + + ~ReleaseHolder() + { + Release(); + } + + void operator=(T *ptr) + { + Release(); + + m_ptr = ptr; + } + + T* operator->() + { + return m_ptr; + } + + operator T*() + { + return m_ptr; + } + + T** operator&() + { + return &m_ptr; + } + + T* GetPtr() const + { + return m_ptr; + } + + T* Detach() + { + T* pT = m_ptr; + m_ptr = NULL; + return pT; + } + + void Release() + { + if (m_ptr != NULL) + { + m_ptr->Release(); + m_ptr = NULL; + } + } + +private: + T* m_ptr; +}; + diff --git a/lib/coreclr/src/inc/safemath.h b/lib/coreclr/src/inc/safemath.h new file mode 100644 index 0000000000..473e8467af --- /dev/null +++ b/lib/coreclr/src/inc/safemath.h @@ -0,0 +1,858 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// safemath.h +// +// overflow checking infrastructure +// --------------------------------------------------------------------------- + + +#ifndef SAFEMATH_H_ +#define SAFEMATH_H_ + +// This file is included from several places outside the CLR, so we can't +// pull in files like DebugMacros.h. However, we assume that the standard +// clrtypes (UINT32 etc.) are defined. +#include "debugmacrosext.h" + +#ifndef _ASSERTE_SAFEMATH +#ifdef _ASSERTE +// Use _ASSERTE if we have it (should always be the case in the CLR) +#define _ASSERTE_SAFEMATH _ASSERTE +#else +// Otherwise (eg. we're being used from a tool like SOS) there isn't much +// we can rely on that is available everywhere. In +// several other tools we just take the recourse of disabling asserts, +// we'll do the same here. +// Ideally we'd have a collection of common utilities available evererywhere. +#define _ASSERTE_SAFEMATH(a) +#endif +#endif + +#include "static_assert.h" + +#ifdef PAL_STDCPP_COMPAT +#include +#else +#include "clr_std/type_traits" +#endif + +//================================================================== +// Semantics: if val can be represented as the exact same value +// when cast to Dst type, then FitsIn(val) will return true; +// otherwise FitsIn returns false. +// +// Dst and Src must both be integral types. +// +// It's important to note that most of the conditionals in this +// function are based on static type information and as such will +// be optimized away. In particular, the case where the signs are +// identical will result in no code branches. + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6326) // PREfast warning: Potential comparison of a constant with another constant +#endif // _PREFAST_ + +template +inline bool FitsIn(Src val) +{ +#ifdef _MSC_VER + static_assert_no_msg(!__is_class(Dst)); + static_assert_no_msg(!__is_class(Src)); +#endif + + if (std::is_signed::value == std::is_signed::value) + { // Src and Dst are equally signed + if (sizeof(Src) <= sizeof(Dst)) + { // No truncation is possible + return true; + } + else + { // Truncation is possible, requiring runtime check + return val == (Src)((Dst)val); + } + } + else if (std::is_signed::value) + { // Src is signed, Dst is unsigned +#ifdef __GNUC__ + // Workaround for GCC warning: "comparison is always + // false due to limited range of data type." + if (!(val == 0 || val > 0)) +#else + if (val < 0) +#endif + { // A negative number cannot be represented by an unsigned type + return false; + } + else + { + if (sizeof(Src) <= sizeof(Dst)) + { // No truncation is possible + return true; + } + else + { // Truncation is possible, requiring runtime check + return val == (Src)((Dst)val); + } + } + } + else + { // Src is unsigned, Dst is signed + if (sizeof(Src) < sizeof(Dst)) + { // No truncation is possible. Note that Src is strictly + // smaller than Dst. + return true; + } + else + { // Truncation is possible, requiring runtime check +#ifdef __GNUC__ + // Workaround for GCC warning: "comparison is always + // true due to limited range of data type." If in fact + // Dst were unsigned we'd never execute this code + // anyway. + return ((Dst)val > 0 || (Dst)val == 0) && +#else + return ((Dst)val >= 0) && +#endif + (val == (Src)((Dst)val)); + } + } +} + +// Requires that Dst is an integral type, and that DstMin and DstMax are the +// minimum and maximum values of that type, respectively. Returns "true" iff +// "val" can be represented in the range [DstMin..DstMax] (allowing loss of precision, but +// not truncation). +template +inline bool FloatFitsInIntType(float val) +{ + float DstMinF = static_cast(DstMin); + float DstMaxF = static_cast(DstMax); + return DstMinF <= val && val <= DstMaxF; +} + +template +inline bool DoubleFitsInIntType(double val) +{ + double DstMinD = static_cast(DstMin); + double DstMaxD = static_cast(DstMax); + return DstMinD <= val && val <= DstMaxD; +} + +#ifdef _PREFAST_ +#pragma warning(pop) +#endif //_PREFAST_ + +#define ovadd_lt(a, b, rhs) (((a) + (b) < (rhs) ) && ((a) + (b) >= (a))) +#define ovadd_le(a, b, rhs) (((a) + (b) <= (rhs) ) && ((a) + (b) >= (a))) +#define ovadd_gt(a, b, rhs) (((a) + (b) > (rhs) ) || ((a) + (b) < (a))) +#define ovadd_ge(a, b, rhs) (((a) + (b) >= (rhs) ) || ((a) + (b) < (a))) + +#define ovadd3_gt(a, b, c, rhs) (((a) + (b) + (c) > (rhs)) || ((a) + (b) < (a)) || ((a) + (b) + (c) < (c))) + + + //----------------------------------------------------------------------------- +// +// Liberally lifted from the Office example on MSDN and modified. +// http://msdn.microsoft.com/library/en-us/dncode/html/secure01142004.asp +// +// Modified to track an overflow bit instead of throwing exceptions. In most +// cases the Visual C++ optimizer (Whidbey beta1 - v14.00.40607) is able to +// optimize the bool away completely. +// Note that using a sentinal value (IntMax for example) to represent overflow +// actually results in poorer code-gen. +// +// This has also been simplified significantly to remove functionality we +// don't currently want (division, implicit conversions, many additional operators etc.) +// +// Example: +// unsafe: UINT32 bufSize = headerSize + elementCount * sizeof(void*); +// becomes: +// S_UINT32 bufSize = S_UINT32(headerSize) + S_UINT32(elementCount) * +// S_UINT32( sizeof(void*) ); +// if( bufSize.IsOverflow() ) { } +// else { use bufSize.Value() } +// or: +// UINT32 tmp, bufSize; +// if( !ClrSafeInt::multiply( elementCount, sizeof(void*), tmp ) || +// !ClrSafeInt::addition( tmp, headerSize, bufSize ) ) +// { } +// else { use bufSize } +// +//----------------------------------------------------------------------------- +// TODO: Any way to prevent unintended instantiations? This is only designed to +// work with unsigned integral types (signed types will work but we probably +// don't need signed support). +template class ClrSafeInt +{ +public: + // Default constructor - 0 value by default + ClrSafeInt() : + m_value(0), + m_overflow(false) + COMMA_INDEBUG( m_checkedOverflow( false ) ) + { + } + + // Value constructor + // This is explicit because otherwise it would be harder to + // differentiate between checked and unchecked usage of an operator. + // I.e. si + x + y vs. si + ( x + y ) + // + // Set the m_checkedOverflow bit to true since this is being initialized + // with a constant value and we know that it is valid. A scenario in + // which this is useful is when an overflow causes a fallback value to + // be used: + // if (val.IsOverflow()) + // val = ClrSafeInt(some_value); + explicit ClrSafeInt( T v ) : + m_value(v), + m_overflow(false) + COMMA_INDEBUG( m_checkedOverflow( true ) ) + { + } + + template + explicit ClrSafeInt(U u) : + m_value(0), + m_overflow(false) + COMMA_INDEBUG( m_checkedOverflow( false ) ) + { + if (!FitsIn(u)) + { + m_overflow = true; + } + else + { + m_value = (T)u; + } + } + + template + ClrSafeInt(ClrSafeInt u) : + m_value(0), + m_overflow(false) + COMMA_INDEBUG( m_checkedOverflow( false ) ) + { + if (u.IsOverflow() || !FitsIn(u.Value())) + { + m_overflow = true; + } + else + { + m_value = (T)u.Value(); + } + } + + // Note: compiler-generated copy constructor and assignment operator + // are correct for our purposes. + + // Note: The MS compiler will sometimes silently perform value-destroying + // conversions when calling the operators below. + // Eg. "ClrSafeInt s(0); s += int(-1);" will result in s + // having the value 0xffffffff without generating a compile-time warning. + // Narrowing conversions are generally level 4 warnings so may or may not + // be visible. + // + // In the original SafeInt class, all operators have an + // additional overload that takes an arbitrary type U and then safe + // conversions are performed (resulting in overflow whenever the value + // cannot be preserved). + // We could do the same thing, but currently don't because: + // - we don't believe there are common cases where this would result in a + // security hole. + // - the extra complexity isn't worth the benefits + // - it would prevent compiler warnings in the cases we do get warnings for. + + + // true if there has been an overflow leading up to the creation of this + // value, false otherwise. + // Note that in debug builds we track whether our client called this, + // so we should not be calling this method ourselves from within this class. + inline bool IsOverflow() const + { + INDEBUG( m_checkedOverflow = true; ) + return m_overflow; + } + + // Get the value of this integer. + // Must only be called when IsOverflow()==false. If this is called + // on overflow we'll assert in Debug and return 0 in release. + inline T Value() const + { + _ASSERTE_SAFEMATH( m_checkedOverflow ); // Ensure our caller first checked the overflow bit + _ASSERTE_SAFEMATH( !m_overflow ); + return m_value; + } + + // force the value into the overflow state. + inline void SetOverflow() + { + INDEBUG( this->m_checkedOverflow = false; ) + this->m_overflow = true; + // incase someone manages to call Value in release mode - should be optimized out + this->m_value = 0; + } + + + // + // OPERATORS + // + + // Addition and multiplication. Only permitted when both sides are explicitly + // wrapped inside of a ClrSafeInt and when the types match exactly. + // If we permitted a RHS of type 'T', then there would be differences + // in correctness between mathematically equivalent expressions such as + // "si + x + y" and "si + ( x + y )". Unfortunately, not permitting this + // makes expressions involving constants tedius and ugly since the constants + // must be wrapped in ClrSafeInt instances. If we become confident that + // our tools (PreFast) will catch all integer overflows, then we can probably + // safely add this. + inline ClrSafeInt operator +(ClrSafeInt rhs) const + { + ClrSafeInt result; // value is initialized to 0 + if( this->m_overflow || + rhs.m_overflow || + !addition( this->m_value, rhs.m_value, result.m_value ) ) + { + result.m_overflow = true; + } + + return result; + } + + inline ClrSafeInt operator -(ClrSafeInt rhs) const + { + ClrSafeInt result; // value is initialized to 0 + if( this->m_overflow || + rhs.m_overflow || + !subtraction( this->m_value, rhs.m_value, result.m_value ) ) + { + result.m_overflow = true; + } + + return result; + } + + inline ClrSafeInt operator *(ClrSafeInt rhs) const + { + ClrSafeInt result; // value is initialized to 0 + if( this->m_overflow || + rhs.m_overflow || + !multiply( this->m_value, rhs.m_value, result.m_value ) ) + { + result.m_overflow = true; + } + + return result; + } + + // Accumulation operators + // Here it's ok to have versions that take a value of type 'T', however we still + // don't allow any mixed-type operations. + inline ClrSafeInt& operator +=(ClrSafeInt rhs) + { + INDEBUG( this->m_checkedOverflow = false; ) + if( this->m_overflow || + rhs.m_overflow || + !ClrSafeInt::addition( this->m_value, rhs.m_value, this->m_value ) ) + { + this->SetOverflow(); + } + return *this; + } + + inline ClrSafeInt& operator +=(T rhs) + { + INDEBUG( this->m_checkedOverflow = false; ) + if( this->m_overflow || + !ClrSafeInt::addition( this->m_value, rhs, this->m_value ) ) + { + this->SetOverflow(); + } + return *this; + } + + inline ClrSafeInt& operator *=(ClrSafeInt rhs) + { + INDEBUG( this->m_checkedOverflow = false; ) + if( this->m_overflow || + rhs.m_overflow || + !ClrSafeInt::multiply( this->m_value, rhs.m_value, this->m_value ) ) + { + this->SetOverflow(); + } + return *this; + } + + inline ClrSafeInt& operator *=(T rhs) + { + INDEBUG( this->m_checkedOverflow = false; ) + if( this->m_overflow || + !ClrSafeInt::multiply( this->m_value, rhs, this->m_value ) ) + { + this->SetOverflow(); + } + + return *this; + } + + // + // STATIC HELPER METHODS + //these compile down to something as efficient as macros and allow run-time testing + //of type by the developer + // + + template static bool IsSigned(U) + { + return std::is_signed::value; + } + + static bool IsSigned() + { + return std::is_signed::value; + } + + static bool IsMixedSign(T lhs, T rhs) + { + return ((lhs ^ rhs) < 0); + } + + static unsigned char BitCount(){return (sizeof(T)*8);} + + static bool Is64Bit(){return sizeof(T) == 8;} + static bool Is32Bit(){return sizeof(T) == 4;} + static bool Is16Bit(){return sizeof(T) == 2;} + static bool Is8Bit(){return sizeof(T) == 1;} + + //both of the following should optimize away + static T MaxInt() + { + if(IsSigned()) + { + return (T)~((T)1 << (BitCount()-1)); + } + //else + return (T)(~(T)0); + } + + static T MinInt() + { + if(IsSigned()) + { + return (T)((T)1 << (BitCount()-1)); + } + else + { + return ((T)0); + } + } + + // Align a value up to the nearest boundary, which must be a power of 2 + inline void AlignUp( T alignment ) + { + _ASSERTE_SAFEMATH( IsPowerOf2( alignment ) ); + *this += (alignment - 1); + if( !this->m_overflow ) + { + m_value &= ~(alignment - 1); + } + } + + // + // Arithmetic implementation functions + // + + //note - this looks complex, but most of the conditionals + //are constant and optimize away + //for example, a signed 64-bit check collapses to: +/* + if(lhs == 0 || rhs == 0) + return 0; + + if(MaxInt()/+lhs < +rhs) + { + //overflow + throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW); + } + //ok + return lhs * rhs; + + Which ought to inline nicely +*/ + // Returns true if safe, false for overflow. + static bool multiply(T lhs, T rhs, T &result) + { + if(Is64Bit()) + { + //fast track this one - and avoid DIV_0 below + if(lhs == 0 || rhs == 0) + { + result = 0; + return true; + } + + //we're 64 bit - slow, but the only way to do it + if(IsSigned()) + { + if(!IsMixedSign(lhs, rhs)) + { + //both positive or both negative + //result will be positive, check for lhs * rhs > MaxInt + if(lhs > 0) + { + //both positive + if(MaxInt()/lhs < rhs) + { + //overflow + return false; + } + } + else + { + //both negative + + //comparison gets tricky unless we force it to positive + //EXCEPT that -MinInt is undefined - can't be done + //And MinInt always has a greater magnitude than MaxInt + if(lhs == MinInt() || rhs == MinInt()) + { + //overflow + return false; + } + +#ifdef _MSC_VER +#pragma warning( disable : 4146 ) // unary minus applied to unsigned is still unsigned +#endif + if(MaxInt()/(-lhs) < (-rhs) ) + { + //overflow + return false; + } +#ifdef _MSC_VER +#pragma warning( default : 4146 ) +#endif + } + } + else + { + //mixed sign - this case is difficult + //test case is lhs * rhs < MinInt => overflow + //if lhs < 0 (implies rhs > 0), + //lhs < MinInt/rhs is the correct test + //else if lhs > 0 + //rhs < MinInt/lhs is the correct test + //avoid dividing MinInt by a negative number, + //because MinInt/-1 is a corner case + + if(lhs < 0) + { + if(lhs < MinInt()/rhs) + { + //overflow + return false; + } + } + else + { + if(rhs < MinInt()/lhs) + { + //overflow + return false; + } + } + } + + //ok + result = lhs * rhs; + return true; + } + else + { + //unsigned, easy case + if(MaxInt()/lhs < rhs) + { + //overflow + return false; + } + //ok + result = lhs * rhs; + return true; + } + } + else if(Is32Bit()) + { + //we're 32-bit + if(IsSigned()) + { + INT64 tmp = (INT64)lhs * (INT64)rhs; + + //upper 33 bits must be the same + //most common case is likely that both are positive - test first + if( (tmp & 0xffffffff80000000LL) == 0 || + (tmp & 0xffffffff80000000LL) == 0xffffffff80000000LL) + { + //this is OK + result = (T)tmp; + return true; + } + + //overflow + return false; + + } + else + { + UINT64 tmp = (UINT64)lhs * (UINT64)rhs; + if (tmp & 0xffffffff00000000ULL) //overflow + { + //overflow + return false; + } + result = (T)tmp; + return true; + } + } + else if(Is16Bit()) + { + //16-bit + if(IsSigned()) + { + INT32 tmp = (INT32)lhs * (INT32)rhs; + //upper 17 bits must be the same + //most common case is likely that both are positive - test first + if( (tmp & 0xffff8000) == 0 || (tmp & 0xffff8000) == 0xffff8000) + { + //this is OK + result = (T)tmp; + return true; + } + + //overflow + return false; + } + else + { + UINT32 tmp = (UINT32)lhs * (UINT32)rhs; + if (tmp & 0xffff0000) //overflow + { + return false; + } + result = (T)tmp; + return true; + } + } + else //8-bit + { + _ASSERTE_SAFEMATH(Is8Bit()); + + if(IsSigned()) + { + INT16 tmp = (INT16)lhs * (INT16)rhs; + //upper 9 bits must be the same + //most common case is likely that both are positive - test first + if( (tmp & 0xff80) == 0 || (tmp & 0xff80) == 0xff80) + { + //this is OK + result = (T)tmp; + return true; + } + + //overflow + return false; + } + else + { + UINT16 tmp = ((UINT16)lhs) * ((UINT16)rhs); + + if (tmp & 0xff00) //overflow + { + return false; + } + result = (T)tmp; + return true; + } + } + } + + // Returns true if safe, false on overflow + static inline bool addition(T lhs, T rhs, T &result) + { + if(IsSigned()) + { + //test for +/- combo + if(!IsMixedSign(lhs, rhs)) + { + //either two negatives, or 2 positives +#ifdef __GNUC__ + // Workaround for GCC warning: "comparison is always + // false due to limited range of data type." + if (!(rhs == 0 || rhs > 0)) +#else + if(rhs < 0) +#endif // __GNUC__ else + { + //two negatives + if(lhs < (T)(MinInt() - rhs)) //remember rhs < 0 + { + return false; + } + //ok + } + else + { + //two positives + if((T)(MaxInt() - lhs) < rhs) + { + return false; + } + //OK + } + } + //else overflow not possible + result = lhs + rhs; + return true; + } + else //unsigned + { + if((T)(MaxInt() - lhs) < rhs) + { + return false; + + } + result = lhs + rhs; + return true; + } + } + + // Returns true if safe, false on overflow + static inline bool subtraction(T lhs, T rhs, T& result) + { + T tmp = lhs - rhs; + + if(IsSigned()) + { + if(IsMixedSign(lhs, rhs)) //test for +/- combo + { + //mixed positive and negative + //two cases - +X - -Y => X + Y - check for overflow against MaxInt() + // -X - +Y - check for overflow against MinInt() + + if(lhs >= 0) //first case + { + //test is X - -Y > MaxInt() + //equivalent to X > MaxInt() - |Y| + //Y == MinInt() creates special case + //Even 0 - MinInt() can't be done + //note that the special case collapses into the general case, due to the fact + //MaxInt() - MinInt() == -1, and lhs is non-negative + //OR tmp should be GTE lhs + + // old test - leave in for clarity + //if(lhs > (T)(MaxInt() + rhs)) //remember that rhs is negative + if(tmp < lhs) + { + return false; + } + //fall through to return value + } + else + { + //second case + //test is -X - Y < MinInt() + //or -X < MinInt() + Y + //we do not have the same issues because abs(MinInt()) > MaxInt() + //tmp should be LTE lhs + + //if(lhs < (T)(MinInt() + rhs)) // old test - leave in for clarity + if(tmp > lhs) + { + return false; + } + //fall through to return value + } + } + // else + //both negative, or both positive + //no possible overflow + result = tmp; + return true; + } + else + { + //easy unsigned case + if(lhs < rhs) + { + return false; + } + result = tmp; + return true; + } + } + +private: + // Private helper functions + // Note that's it occasionally handy to call the arithmetic implementation + // functions above so we leave them public, even though we almost always use + // the operators instead. + + // True if the specified value is a power of two. + static inline bool IsPowerOf2( T x ) + { + // find the smallest power of 2 >= x + T testPow = 1; + while( testPow < x ) + { + testPow = testPow << 1; // advance to next power of 2 + if( testPow <= 0 ) + { + return false; // overflow + } + } + + return( testPow == x ); + } + + // + // Instance data + // + + // The integer value this instance represents, or 0 if overflow. + T m_value; + + // True if overflow has been reached. Once this is set, it cannot be cleared. + bool m_overflow; + + // In debug builds we verify that our caller checked the overflow bit before + // accessing the value. This flag is cleared on initialization, and whenever + // m_value or m_overflow changes, and set only when IsOverflow + // is called. + INDEBUG( mutable bool m_checkedOverflow; ) +}; + +// Allows creation of a ClrSafeInt corresponding to the type of the argument. +template +ClrSafeInt AsClrSafeInt(T t) +{ + return ClrSafeInt(t); +} + +template +ClrSafeInt AsClrSafeInt(ClrSafeInt t) +{ + return t; +} + +// Convenience safe-integer types. Currently these are the only types +// we are using ClrSafeInt with. We may want to add others. +// These type names are based on our standardized names in clrtypes.h +typedef ClrSafeInt S_UINT8; +typedef ClrSafeInt S_UINT16; +//typedef ClrSafeInt S_UINT32; +#define S_UINT32 ClrSafeInt +typedef ClrSafeInt S_UINT64; +typedef ClrSafeInt S_SIZE_T; + + #endif // SAFEMATH_H_ diff --git a/lib/coreclr/src/inc/safewrap.h b/lib/coreclr/src/inc/safewrap.h new file mode 100644 index 0000000000..f489999f68 --- /dev/null +++ b/lib/coreclr/src/inc/safewrap.h @@ -0,0 +1,171 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// SafeWrap.h +// + +// +// This file contains wrapper functions for Win32 API's that take SStrings +// and use CLR-safe holders. +//***************************************************************************** + + +/* + Guidelines for SafeWrapper APIs: +Most of these are 'common-sense', plus a few arbitrary decisions thrown in for +consistency's sake. + +- THROWING: Throw on oom, but return all other failure codes. + The rationale here is that SString operations already throw, so to make these APIs + non-throwing would require an extra EX_TRY/EX_CATCH. Most callees will want to throw + on OOM anyways. So making these APIs non-throwing would mean an extra try/catch in + the caller + an extra check at the callee. We can eliminate that overhead and just make + it throwing. + + Return non-oom failure codes because callees actually freqeuntly expect an API to fail. + For example, the callee will have special handling for file-not-found. + + For convenience, you could add a no-throwing wrapper version of the API: + ClrGetEnvironmentVariable <-- default throws on oom. + ClrGetEnvironmentVariableNoThrow <-- never throws. + +- NAMING: Prefix the name with 'Clr', just like we do for win32 APIs going through hosting. + +- DON'T FORGET CONTRACTS: Most of these APIs will likely be Throws/GC_Notrigger. + Also use PRECONDITIONs + POSTCONDITIONS when possible. + +- SIGNATURES: Keep the method signture as close the the original win32 API as possible. + - Preserve the return type + value. (except allow it to throw on oom). If the return value + should be a holder, then use that as an out-parameter at the end of the argument list. + We don't want to return holders because that will cause the dtors to be called. + - For input strings use 'const SString &' instead of 'LPCWSTR'. + - Change ('out' string, length) pairs to 'SString &' (this is the convention the rest of the CLR uses for SStrings) + - Use Holders where appropriate. + - Preserve other parameters. + +- USE SSTRINGS TO AVOID BUFFER OVERRUN ISSUES: Repeated here for emphasis. Use SStrings when + applicable to make it very easy to verify the code does not have buffer overruns. + This will also simplify callsites from having to figure out the length of the output string. + +- USE YOUR BEST JUDGEMENT: The primary goal of these API wrappers is to embrace 'security-safe' practices. + Certainly take any additional steps to that goal. For example, it may make sense to eliminate + corner case inputs for a given API or to break a single confusing API up into several discrete and + move obvious APIs. + +*/ +#ifndef _safewrap_h_ +#define _safewrap_h_ + +#include "holder.h" + +class SString; +bool ClrGetEnvironmentVariable(LPCSTR szEnvVarName, SString & value); +bool ClrGetEnvironmentVariableNoThrow(LPCSTR szEnvVarName, SString & value); +void ClrGetModuleFileName(HMODULE hModule, SString & value); +bool ClrGetModuleFileNameNoThrow(HMODULE hModule, SString & value); + +void ClrGetCurrentDirectory(SString & value); +bool ClrGetCurrentDirectoryNoThrow(SString & value); + + +/* --------------------------------------------------------------------------- * + * Simple wrapper around WszFindFirstFile/WszFindNextFile + * --------------------------------------------------------------------------- */ +class ClrDirectoryEnumerator +{ + WIN32_FIND_DATAW data; + FindHandleHolder dirHandle; + BOOL fFindNext; // Skip FindNextFile first time around + +public: + ClrDirectoryEnumerator(LPCWSTR pBaseDirectory, LPCWSTR pMask = W("*")); + bool Next(); + + LPCWSTR GetFileName() + { + return data.cFileName; + } + + DWORD GetFileAttributes() + { + return data.dwFileAttributes; + } + + void Close() + { + dirHandle.Clear(); + } +}; + +// Read a REG_SZ (null-terminated string) value from the registry. Throws. +void ClrRegReadString(HKEY hKey, const SString & szValueName, SString & value); + +/* --------------------------------------------------------------------------- * + * Simple wrapper around RegisterEventSource/ReportEvent/DeregisterEventSource + * --------------------------------------------------------------------------- */ +// Returns ERROR_SUCCESS if succeessful in reporting to event log, or +// Windows error code to indicate the specific error. +DWORD ClrReportEvent( + LPCWSTR pEventSource, + WORD wType, + WORD wCategory, + DWORD dwEventID, + PSID lpUserSid, + WORD wNumStrings, + LPCWSTR *lpStrings, + DWORD dwDataSize = 0, + LPVOID lpRawData = NULL); + +DWORD ClrReportEvent( + LPCWSTR pEventSource, + WORD wType, + WORD wCategory, + DWORD dwEventID, + PSID lpUserSid, + LPCWSTR pMessage); + +//***************************************************************************** +// This provides a wrapper around GetFileSize() that forces it to fail +// if the file is >4g and pdwHigh is NULL. Other than that, it acts like +// the genuine GetFileSize(). +// +// +//***************************************************************************** +DWORD inline SafeGetFileSize(HANDLE hFile, DWORD *pdwHigh) +{ + if (pdwHigh != NULL) + { + return ::GetFileSize(hFile, pdwHigh); + } + else + { + DWORD hi; + DWORD lo = ::GetFileSize(hFile, &hi); + if (lo == 0xffffffff && GetLastError() != NO_ERROR) + { + return lo; + } + // api succeeded. is the file too large? + if (hi != 0) + { + // there isn't really a good error to set here... + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0xffffffff; + } + + if (lo == 0xffffffff) + { + // note that a success return of (hi=0,lo=0xffffffff) will be + // treated as an error by the caller. Again, that's part of the + // price of being a slacker and not handling the high dword. + // We'll set a lasterror for him to pick up. + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + } + + return lo; + } + +} + +#endif // _safewrap_h_ diff --git a/lib/coreclr/src/inc/sarray.h b/lib/coreclr/src/inc/sarray.h new file mode 100644 index 0000000000..ac361cf401 --- /dev/null +++ b/lib/coreclr/src/inc/sarray.h @@ -0,0 +1,229 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// SArray.h +// -------------------------------------------------------------------------------- + + +#ifndef _SARRAY_H_ +#define _SARRAY_H_ + +#include "sbuffer.h" + +// -------------------------------------------------------------------------------- +// SArray is a typed array wrapper around an SBuffer. It manages individual +// constructors and destructors of array elements if avaiable, as well as providing +// typed access. +// -------------------------------------------------------------------------------- + +template +class SArray +{ + private: + + SBuffer m_buffer; + + static COUNT_T VerifySizeRange(ELEMENT * begin, ELEMENT * end); + + public: + + class Iterator; + friend class Iterator; + + SArray(); + SArray(COUNT_T count); + SArray(ELEMENT * begin, ELEMENT * end); + ~SArray(); + + void Clear(); + void Set(const SArray &array); + + COUNT_T GetCount() const; + BOOL IsEmpty() const; + + void SetCount(COUNT_T count); + + COUNT_T GetAllocation() const; + + void Preallocate(int count) const; + void Trim() const; + + void Copy(const Iterator &to, const Iterator &from, COUNT_T size); + void Move(const Iterator &to, const Iterator &from, COUNT_T size); + + void Copy(const Iterator &i, const ELEMENT *source, COUNT_T size); + void Copy(void *dest, const Iterator &i, COUNT_T size); + + Iterator Append() + { + WRAPPER_NO_CONTRACT; + + COUNT_T count = GetCount(); + if ( GetAllocation() == count ) + Preallocate( 2 * count ); + + Iterator i = End(); + Insert(i); + return i; + } + + void Append(ELEMENT elem) + { + WRAPPER_NO_CONTRACT; + *Append() = elem; + } + + ELEMENT AppendEx(ELEMENT elem) + { + WRAPPER_NO_CONTRACT; + + *Append() = elem; + return elem; + } + + void Insert(const Iterator &i); + void Delete(const Iterator &i); + + void Insert(const Iterator &i, COUNT_T count); + void Delete(const Iterator &i, COUNT_T count); + + void Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount); + + ELEMENT *OpenRawBuffer(COUNT_T maxElementCount); + ELEMENT *OpenRawBuffer(); + void CloseRawBuffer(COUNT_T actualElementCount); + void CloseRawBuffer(); + + Iterator Begin() + { + WRAPPER_NO_CONTRACT; + return Iterator(this, 0); + } + + Iterator End() + { + WRAPPER_NO_CONTRACT; + return Iterator(this, GetCount()); + } + + Iterator operator+(COUNT_T index) + { + return Iterator(this, index); + } + + ELEMENT & operator[] (int index); + const ELEMENT & operator[] (int index) const; + + ELEMENT & operator[] (COUNT_T index); + const ELEMENT & operator[] (COUNT_T index) const; + + protected: + SArray(void *prealloc, COUNT_T size); + + public: + + class Iterator : public CheckedIteratorBase >, + public Indexer + { + friend class SArray; + friend class Indexer; + + SBuffer::Iterator m_i; + + public: + + Iterator(SArray *array, SCOUNT_T index) + : CheckedIteratorBase >(array) + { + WRAPPER_NO_CONTRACT; + m_i = array->m_buffer.Begin() + index*sizeof(ELEMENT); + } + + protected: + + ELEMENT &GetAt(SCOUNT_T delta) const + { + LIMITED_METHOD_CONTRACT; + return * (ELEMENT *) &m_i[delta*sizeof(ELEMENT)]; + } + + void Skip(SCOUNT_T delta) + { + LIMITED_METHOD_CONTRACT; + m_i += delta*sizeof(ELEMENT); + } + + COUNT_T Subtract(const Iterator &i) const + { + LIMITED_METHOD_CONTRACT; + return (m_i - i.m_i)/sizeof(ELEMENT); + } + + CHECK DoCheck(SCOUNT_T delta) const + { + WRAPPER_NO_CONTRACT; + return m_i.CheckIndex(delta*sizeof(ELEMENT)); + } + + public: + + CHECK Check() const + { + WRAPPER_NO_CONTRACT; + return m_i.Check(); + } + }; + + ELEMENT *GetElements() const; + + private: + + //-------------------------------------------------------------------- + // Routines for managing the buffer content. + //-------------------------------------------------------------------- + + void ConstructBuffer(const Iterator &i, COUNT_T size); + void CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from); + void DestructBuffer(const Iterator &i, COUNT_T size); +}; + +// ================================================================================ +// InlineSArray : Tempate for an SArray with preallocated element space +// ================================================================================ + +template +class InlineSArray : public SArray +{ + private: +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) // zero sized array +#pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads + DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[SIZE*sizeof(ELEMENT)]; +#pragma warning(pop) +#else + // use UINT64 to get maximum alignment of the memory + UINT64 m_prealloc[ALIGN(SIZE*sizeof(ELEMENT),sizeof(UINT64))/sizeof(UINT64)]; +#endif // _MSC_VER + + public: + InlineSArray(); +}; + +// ================================================================================ +// StackSArray : SArray with relatively large preallocated buffer for stack use +// ================================================================================ + +template +class StackSArray : public InlineSArray +{ +}; + +// ================================================================================ +// Inline definitions +// ================================================================================ + +#include "sarray.inl" + +#endif // _SARRAY_H_ diff --git a/lib/coreclr/src/inc/sarray.inl b/lib/coreclr/src/inc/sarray.inl new file mode 100644 index 0000000000..102b3c578a --- /dev/null +++ b/lib/coreclr/src/inc/sarray.inl @@ -0,0 +1,376 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// SArray.inl +// -------------------------------------------------------------------------------- + +#ifndef _SARRAY_INL_ +#define _SARRAY_INL_ + +#include "sarray.h" + +template +inline SArray::SArray() + : m_buffer() +{ + LIMITED_METHOD_CONTRACT; +} + +template +inline SArray::SArray(COUNT_T count) + : m_buffer(count * sizeof(ELEMENT)) +{ + WRAPPER_NO_CONTRACT; + ConstructBuffer(Begin(), count); +} + +template +inline COUNT_T SArray::VerifySizeRange(ELEMENT * begin, ELEMENT *end) +{ + WRAPPER_NO_CONTRACT; + + if (end < begin) + ThrowHR(COR_E_OVERFLOW); + + SIZE_T bufferSize = (end - begin) * sizeof(ELEMENT); + if (!FitsIn(bufferSize)) + ThrowHR(COR_E_OVERFLOW); + + return static_cast(bufferSize); +} + +template +inline SArray::SArray(ELEMENT * begin, ELEMENT * end) + : m_buffer(VerifySizeRange(begin, end)) +{ + WRAPPER_NO_CONTRACT; + + CopyConstructBuffer(Begin(), static_cast(end - begin), begin); +} + +template +inline SArray::SArray(void *prealloc, COUNT_T count) + : m_buffer(SBuffer::Prealloc, prealloc, count*sizeof(ELEMENT)) +{ + LIMITED_METHOD_CONTRACT; +} + +template +SArray::~SArray() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + // Cannot call Clear because DestructBuffer has THROWS in its contract + if (!BITWISE_COPY) + { + COUNT_T elementCount = GetCount(); + for (COUNT_T i = 0; i < elementCount; i++) + { + (&((*this)[i]))->~ELEMENT(); + } + } +} + +template +inline void SArray::Clear() +{ + WRAPPER_NO_CONTRACT; + DestructBuffer(Begin(), GetCount()); + m_buffer.Clear(); +} + +template +inline ELEMENT* SArray::OpenRawBuffer(COUNT_T elementCount) +{ + WRAPPER_NO_CONTRACT; + return (ELEMENT*)m_buffer.OpenRawBuffer(elementCount * sizeof(ELEMENT)); +} + +template +inline ELEMENT* SArray::OpenRawBuffer() +{ + WRAPPER_NO_CONTRACT; + return (ELEMENT*)m_buffer.OpenRawBuffer(GetCount() * sizeof(ELEMENT)); +} + +template +inline void SArray::CloseRawBuffer(COUNT_T finalElementCount) +{ + WRAPPER_NO_CONTRACT; + m_buffer.CloseRawBuffer(finalElementCount * sizeof(ELEMENT)); +} + +template +inline void SArray::CloseRawBuffer() +{ + WRAPPER_NO_CONTRACT; + m_buffer.CloseRawBuffer(); +} + +template +inline void SArray::Set(const SArray &array) +{ + WRAPPER_NO_CONTRACT; + if (BITWISE_COPY) + { + m_buffer.Set(array.m_buffer); + } + else + { + DestructBuffer(Begin(), GetCount()); + m_buffer.SetSize(0); + m_buffer.SetSize(array.m_buffer.GetSize()); + CopyConstructBuffer(Begin(), GetCount(), array.GetElements()); + } +} + +template +inline COUNT_T SArray::GetCount() const +{ + WRAPPER_NO_CONTRACT; + return m_buffer.GetSize()/sizeof(ELEMENT); +} + +template +inline BOOL SArray::IsEmpty() const +{ + WRAPPER_NO_CONTRACT; + return GetCount() == 0; +} + +template +inline void SArray::SetCount(COUNT_T count) +{ + WRAPPER_NO_CONTRACT; + COUNT_T oldCount = GetCount(); + if (count > oldCount) + ConstructBuffer(Begin() + oldCount, count - oldCount); + + m_buffer.SetSize(count*sizeof(ELEMENT)); + + if (oldCount > count) + DestructBuffer(Begin() + count, oldCount - count); +} + +template +inline COUNT_T SArray::GetAllocation() const +{ + WRAPPER_NO_CONTRACT; + return m_buffer.GetAllocation() / sizeof(ELEMENT); +} + +template +inline void SArray::Preallocate(int count) const +{ + WRAPPER_NO_CONTRACT; + m_buffer.Preallocate(count * sizeof(ELEMENT)); +} + +template +inline void SArray::Trim() const +{ + WRAPPER_NO_CONTRACT; + m_buffer.Trim(); +} + +template +inline void SArray::Copy(const Iterator &to, const Iterator &from, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + // @todo: destruction/construction semantics are broken on overlapping copies + + DestructBuffer(to, size); + + CopyConstructBuffer(to, size, from); +} + +template +inline void SArray::Move(const Iterator &to, const Iterator &from, COUNT_T size) +{ + // @todo: destruction/construction semantics are broken on overlapping moves + + DestructBuffer(to, size); + + m_buffer.Move(to, from, size*sizeof(ELEMENT)); + + ConstructBuffer(from, size); +} + +template +inline void SArray::Copy(const Iterator &i, const ELEMENT *source, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + DestructBuffer(i, size); + + CopyConstructBuffer(i, size, source); +} + +template +inline void SArray::Copy(void *dest, const Iterator &i, COUNT_T size) +{ + WRAPPER_NO_CONTRACT; + // @todo: destruction/construction semantics are unclear + + m_buffer.Copy(dest, i.m_i, size*sizeof(ELEMENT)); +} + +template +inline void SArray::Insert(const Iterator &i) +{ + WRAPPER_NO_CONTRACT; + Replace(i, 0, 1); +} + +template +inline void SArray::Delete(const Iterator &i) +{ + WRAPPER_NO_CONTRACT; + Replace(i, 1, 0); +} + +template +inline void SArray::Insert(const Iterator &i, COUNT_T count) +{ + WRAPPER_NO_CONTRACT; + Replace(i, 0, count); +} + +template +inline void SArray::Delete(const Iterator &i, COUNT_T count) +{ + Delete(i, 0, count); +} + +template +inline void SArray:: Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount) +{ + WRAPPER_NO_CONTRACT; + DestructBuffer(i, deleteCount); + + m_buffer.Replace(i.m_i, deleteCount*sizeof(ELEMENT), insertCount*sizeof(ELEMENT)); + + ConstructBuffer(i, insertCount); +} + +template +inline ELEMENT &SArray::operator[](int index) +{ + WRAPPER_NO_CONTRACT; + return *(GetElements() + index); +} + +template +inline const ELEMENT &SArray::operator[](int index) const +{ + WRAPPER_NO_CONTRACT; + return *(GetElements() + index); +} + +template +inline ELEMENT &SArray::operator[](COUNT_T index) +{ + WRAPPER_NO_CONTRACT; + return *(GetElements() + index); +} + +template +inline const ELEMENT &SArray::operator[](COUNT_T index) const +{ + return *(GetElements() + index); +} + +template +inline ELEMENT *SArray::GetElements() const +{ + LIMITED_METHOD_CONTRACT; + return (ELEMENT *) (const BYTE *) m_buffer; +} + +template +inline void SArray::ConstructBuffer(const Iterator &i, COUNT_T size) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (!BITWISE_COPY) + { + ELEMENT *start = GetElements() + (i - Begin()); + ELEMENT *end = start + size; + + while (start < end) + { + new (start) ELEMENT(); + start++; + } + } +} + +template +inline void SArray::CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from) +{ + ptrdiff_t start_offset = i - Begin(); + ELEMENT *p = (ELEMENT *) m_buffer.OpenRawBuffer(m_buffer.GetSize()) + start_offset; + + if (BITWISE_COPY) + { + memmove(p, from, size * sizeof(ELEMENT)); + } + else + { + ELEMENT *start = (ELEMENT *) p; + ELEMENT *end = (ELEMENT *) (p + size); + + while (start < end) + { + new (start) ELEMENT(*from); + + start++; + from++; + } + } + + m_buffer.CloseRawBuffer(); +} + +template +inline void SArray::DestructBuffer(const Iterator &i, COUNT_T size) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + + if (!BITWISE_COPY) + { + ELEMENT *start = GetElements() + (i - Begin()); + ELEMENT *end = start + size; + + while (start < end) + { + start->ELEMENT::~ELEMENT(); + + start++; + } + } +} + +template +inline InlineSArray::InlineSArray() + : SArray((void*)m_prealloc, SIZE) +{ + LIMITED_METHOD_CONTRACT; +} + +#endif // _SARRAY_INL_ diff --git a/lib/coreclr/src/inc/sbuffer.h b/lib/coreclr/src/inc/sbuffer.h new file mode 100644 index 0000000000..e56322ac88 --- /dev/null +++ b/lib/coreclr/src/inc/sbuffer.h @@ -0,0 +1,575 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// -------------------------------------------------------------------------------- +// SBuffer.h (Safe Buffer) +// + +// -------------------------------------------------------------------------------- + +// -------------------------------------------------------------------------------- +// SBuffer is a relatively safe way to manipulate a dynamically +// allocated data buffer. An SBuffer is conceptually a simple array +// of bytes. It maintains both a conceptual size and an actual allocated size. +// +// SBuffer provides safe access to the data buffer by providing rich high +// level functionality (like insertion, deleteion, copying, comparison, and +// iteration) without exposing direct pointers to its buffers. +// +// For interoperability, SBuffers can expose their buffers - either as readonly +// by BYTE * or void * cases, or as writable by the OpenRawBuffer/CloseRawBuffer +// entry points. Use of these should be limited wherever possible though; as there +// is always a possibilility of buffer overrun. +// +// To mimimize heap allocations, the InlineSBuffer template will preallocate a fixed +// size buffer inline with the SBuffer object itself. It will use this buffer unless +// it needs a bigger one, in which case it transparently moves on to using the heap. +// The StackSBuffer class instatiates the InlineSBuffer with a standard heuristic +// stack preallocation size. +// +// SBuffer is "subclassable" to add content typeing to the buffer. See SArray and +// SString for examples. +// -------------------------------------------------------------------------------- + + +#ifndef _SBUFFER_H_ +#define _SBUFFER_H_ + +#include "clrtypes.h" +#include "iterator.h" +#include "check.h" +#include "daccess.h" +#include "memoryrange.h" + +// ================================================================================ +// Macros for computing padding +// ================================================================================ + +#define ALIGNMENT(size) \ + (( (size^(size-1)) >> 1) +1) + +#define ALIGN(size, align) \ + (((size)+((align)-1)) & ~((align)-1)) + +#define PAD(size, align) \ + (ALIGN((size), (align)) - (size)) + +// ================================================================================ +// SBuffer : base class for safe buffers +// ================================================================================ + +typedef DPTR(class SBuffer) PTR_SBuffer; + +class SBuffer +{ + public: + //-------------------------------------------------------------------- + // Flags and constants + //-------------------------------------------------------------------- + + enum ImmutableFlag + { + Immutable + }; + + enum PreallocFlag + { + Prealloc + }; + + //-------------------------------------------------------------------- + // Types + //-------------------------------------------------------------------- + + public: + class CIterator; + friend class CIterator; + + class Iterator; + friend class Iterator; + + //-------------------------------------------------------------------- + // Initializers and constructors + //-------------------------------------------------------------------- + + public: + // Constructors + SBuffer(); + SBuffer(COUNT_T size); + SBuffer(const BYTE *buffer, COUNT_T size); + explicit SBuffer(const SBuffer &buffer); + + // Immutable constructor should ONLY be used if buffer will + // NEVER BE FREED OR MODIFIED. PERIOD. . + SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T size); + + // Prealloc should be allocated inline with SBuffer - it must have the same + // lifetime as SBuffer's memory. + SBuffer(PreallocFlag prealloc, void *buffer, COUNT_T size); + + ~SBuffer(); + + void Clear(); + + void Set(const SBuffer &buffer); + void Set(const BYTE *buffer, COUNT_T size); + void SetImmutable(const BYTE *buffer, COUNT_T size); + + //-------------------------------------------------------------------- + // Buffer size routines. A buffer has an externally visible size, but + // it also has an internal allocation size which may be larger. + //-------------------------------------------------------------------- + + // Get and set size of buffer. Note that the actual size of the + // internally allocated memory block may be bigger. + COUNT_T GetSize() const; + void SetSize(COUNT_T count); + + // Grow size of buffer to maximum amount without reallocating. + void MaximizeSize(); + + //-------------------------------------------------------------------- + // Buffer allocation routines + //-------------------------------------------------------------------- + + // Return the current available allocation space of the buffer. + COUNT_T GetAllocation() const; + + // Preallocate some memory you expect to use. This can prevent + // multiple reallocations. Note this does not change the visible + // size of the buffer. + void Preallocate(COUNT_T allocation) const; + + // Shrink memory usage of buffer to minimal amount. Note that + // this does not change the visible size of the buffer. + void Trim() const; + + //-------------------------------------------------------------------- + // Content manipulation routines + //-------------------------------------------------------------------- + + void Zero(); + void Fill(BYTE value); + void Fill(const Iterator &to, BYTE value, COUNT_T size); + + // Internal copy. "Copy" leaves from range as is; "Move" + // leaves from range in uninitialized state. + // (This distinction is more important when using from a + // typed wrapper than in the base SBuffer class.) + // + // NOTE: Copy vs Move is NOT based on whether ranges overlap + // or not. Ranges may overlap in either case. + // + // Note that both Iterators must be on THIS buffer. + void Copy(const Iterator &to, const CIterator &from, COUNT_T size); + void Move(const Iterator &to, const CIterator &from, COUNT_T size); + + // External copy. + void Copy(const Iterator &i, const SBuffer &source); + void Copy(const Iterator &i, const void *source, COUNT_T size); + void Copy(void *dest, const CIterator &i, COUNT_T size); + + // Insert bytes at the given iterator location. + void Insert(const Iterator &i, const SBuffer &source); + void Insert(const Iterator &i, COUNT_T size); + + // Delete bytes at the given iterator location + void Delete(const Iterator &i, COUNT_T size); + + // Replace bytes at the given iterator location + void Replace(const Iterator &i, COUNT_T deleteSize, const SBuffer &insert); + void Replace(const Iterator &i, COUNT_T deleteSize, COUNT_T insertSize); + + // Compare entire buffer; return -1, 0, 1 + int Compare(const SBuffer &compare) const; + int Compare(const BYTE *match, COUNT_T size) const; + + // Compare entire buffer; return TRUE or FALSE + BOOL Equals(const SBuffer &compare) const; + BOOL Equals(const BYTE *match, COUNT_T size) const; + + // Match portion of this buffer to given bytes; return TRUE or FALSE + BOOL Match(const CIterator &i, const SBuffer &match) const; + BOOL Match(const CIterator &i, const BYTE *match, COUNT_T size) const; + + //-------------------------------------------------------------------- + // Iterators + // + // Note that any iterator returned is not + // valid after any operation which may resize the buffer, unless + // the operation was performed on that particular iterator. + //-------------------------------------------------------------------- + + CIterator Begin() const; + CIterator End() const; + + Iterator Begin(); + Iterator End(); + + BYTE & operator[] (int index); + const BYTE & operator[] (int index) const; + + //-------------------------------------------------------------------- + // Raw buffer access + // + // Accessing a raw buffer via pointer is inherently more dangerous than + // other uses of this API, and should be avoided if at all possible. + // It is primarily provided for compatibility with existing APIs. + // + // Note that any buffer pointer returned is not + // valid after any operation which may resize the buffer. + //-------------------------------------------------------------------- + + // Casting operators return the existing buffer as + // a raw const pointer. Note that the pointer is valid only + // until the buffer is modified via an API. + operator const void *() const; + operator const BYTE *() const; + + // To write directly to the SString's underlying buffer: + // 1) Call OpenRawBuffer() and pass it the count of bytes + // you need. + // 2) That returns a pointer to the raw buffer which you can write to. + // 3) When you are done writing to the pointer, call CloseBuffer() + // and pass it the count of bytes you actually wrote. + // The pointer from step 1 is now invalid. + + // example usage: + // void GetInfo(SBuffer &buf) + // { + // BYTE *p = buf.OpenRawBuffer(3); + // OSGetSomeInfo(p, 3); + // buf.CloseRawBuffer(); + // } + + // You should open the buffer, write the data, and immediately close it. + // No sbuffer operations are valid while the buffer is opened. + // + // In a debug build, Open/Close will do lots of little checks to make sure + // you don't buffer overflow while it's opened. In a retail build, this + // is a very streamlined action. + + // Open the raw buffer for writing count bytes + BYTE *OpenRawBuffer(COUNT_T maxCount); + + // Call after OpenRawBuffer(). + + // Provide the count of bytes actually used. This will make sure the + // SBuffer's size is correct. + void CloseRawBuffer(COUNT_T actualCount); + + // Close the buffer. Assumes that we completely filled the buffer + // that OpenRawBuffer() gave back. + void CloseRawBuffer(); + + //-------------------------------------------------------------------- + // Check routines. These are typically used internally, but may be + // called externally if desired. + //-------------------------------------------------------------------- + + CHECK CheckBufferClosed() const; + static CHECK CheckSize(COUNT_T size); + static CHECK CheckAllocation(COUNT_T allocation); + CHECK CheckIteratorRange(const CIterator &i) const; + CHECK CheckIteratorRange(const CIterator &i, COUNT_T size) const; + + CHECK Check() const; + CHECK Invariant() const; + CHECK InternalInvariant() const; + + protected: + + //-------------------------------------------------------------------- + // Internal helper routines + //-------------------------------------------------------------------- + + // Preserve = preserve contents while reallocating + typedef enum + { + DONT_PRESERVE = 0, + PRESERVE = 1, + } Preserve; + + void Resize(COUNT_T size, Preserve preserve = PRESERVE); + void ResizePadded(COUNT_T size, Preserve preserve = PRESERVE); + void TweakSize(COUNT_T size); + void ReallocateBuffer(COUNT_T allocation, Preserve preserve); + void EnsureMutable() const; + + //-------------------------------------------------------------------- + // We define some extra flags and fields for subclasses (these are specifically + // designed for SString, but use otherwise if desired.) + //-------------------------------------------------------------------- + + BOOL IsFlag1() const; + void SetFlag1(); + void ClearFlag1(); + + BOOL IsFlag2() const; + void SetFlag2(); + void ClearFlag2(); + + BOOL IsFlag3() const; + void SetFlag3(); + void ClearFlag3(); + + INT GetRepresentationField() const; + void SetRepresentationField(int value); + + protected: + + //-------------------------------------------------------------------- + // Flag access + //-------------------------------------------------------------------- + + BOOL IsAllocated() const; + void SetAllocated(); + void ClearAllocated(); + + BOOL IsImmutable() const; + void SetImmutable(); + void ClearImmutable(); + +#if _DEBUG + BOOL IsOpened() const; + void SetOpened(); + void ClearOpened(); +#endif + + //-------------------------------------------------------------------- + // Buffer management routines + //-------------------------------------------------------------------- + + // Allocate and free a memory buffer + BYTE *NewBuffer(COUNT_T allocation); + void DeleteBuffer(BYTE *buffer, COUNT_T allocation); + + // Use existing buffer + BYTE *UseBuffer(BYTE *buffer, COUNT_T *allocation); + + CHECK CheckBuffer(const BYTE* buffer, COUNT_T allocation) const; + + // Manipulates contents of the buffer via the plugins below, but + // adds some debugging checks. Should always call through here rather + // than directly calling the extensibility points. + void DebugMoveBuffer(__out_bcount(size) BYTE *to, BYTE *from, COUNT_T size); + void DebugCopyConstructBuffer(__out_bcount(size) BYTE *to, const BYTE *from, COUNT_T size); + void DebugConstructBuffer(BYTE *buffer, COUNT_T size); + void DebugDestructBuffer(BYTE *buffer, COUNT_T size); + + void DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size); +#ifdef _DEBUG + static BOOL EnsureGarbageCharOnly(const BYTE *buffer, COUNT_T size); +#endif + CHECK CheckUnusedBuffer(const BYTE *buffer, COUNT_T size) const; + +#ifdef DACCESS_COMPILE +public: + + // Expose the raw Target address of the buffer to DAC. + // This does not do any marshalling. This can be useful if the caller wants to allocate the buffer on + // its own heap so that it can survive Flush calls. + MemoryRange DacGetRawBuffer() const + { + SUPPORTS_DAC; + PTR_VOID p = dac_cast((TADDR) m_buffer); + return MemoryRange(p, GetSize()); + } + +protected: + + // Return a host copy of the buffer, allocated on the DAC heap (and thus invalidated at the next call to Flush). + void* DacGetRawContent(void) const + { + SUPPORTS_DAC; + + // SBuffers are used in DAC in two ways - buffers in the host, and marshalled buffers from the target. + // This is a problem - we can't reason about the address space of the buffer statically, and instead rely on + // the dynamic usage (i.e. the methods are basically bifurcated into those you can use on host instances, + // and those you can use on marshalled copies). + // Ideally we'll have two versions of the SBuffer code - one that's marshalled (normal DACization) and one + // that isn't (host-only utility). This is the "dual-mode DAC problem". + // But this only affects a couple classes, and so for now we'll ignore the problem - causing a bunch of DacCop + // violations. + DACCOP_IGNORE(CastBetweenAddressSpaces, "SBuffer has the dual-mode DAC problem"); + DACCOP_IGNORE(FieldAccess, "SBuffer has the dual-mode DAC problem"); + TADDR bufAddr = (TADDR)m_buffer; + + return DacInstantiateTypeByAddress(bufAddr, m_size, true); + } + + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) const + { + SUPPORTS_DAC; + + if (flags != CLRDATA_ENUM_MEM_TRIAGE) + { + DacEnumMemoryRegion((TADDR)m_buffer, m_size); + } + } +#endif + + //---------------------------------------------------------------------------- + // Iterator base class + //---------------------------------------------------------------------------- + + friend class CheckedIteratorBase; + + class Index : public CheckedIteratorBase + { + friend class SBuffer; + + friend class CIterator; + friend class Indexer; + + friend class Iterator; + friend class Indexer; + + protected: + BYTE* m_ptr; + + Index(); + Index(SBuffer *container, SCOUNT_T index); + BYTE &GetAt(SCOUNT_T delta) const; + void Skip(SCOUNT_T delta); + SCOUNT_T Subtract(const Index &i) const; + + CHECK DoCheck(SCOUNT_T delta) const; + + void Resync(const SBuffer *container, BYTE *value) const; + }; + + public: + + class CIterator : public Index, public Indexer + { + friend class SBuffer; + + public: + CIterator() + { + } + + CIterator(const SBuffer *buffer, int index) + : Index(const_cast(buffer), index) + { + } + }; + + class Iterator : public Index, public Indexer + { + friend class SBuffer; + + public: + operator const CIterator &() const + { + return *(const CIterator *)this; + } + + operator CIterator &() + { + return *(CIterator *)this; + } + + Iterator() + { + } + + Iterator(SBuffer *buffer, int index) + : Index(buffer, index) + { + } + + }; + + + //---------------------------------------------------------------------------- + // Member and data declarations + //---------------------------------------------------------------------------- + + private: + enum + { + REPRESENTATION_MASK = 0x07, + ALLOCATED = 0x08, + IMMUTABLE = 0x10, + OPENED = 0x20, + FLAG1 = 0x40, + FLAG2 = 0x80, + FLAG3 = 0x100, + }; + + COUNT_T m_size; // externally visible size + COUNT_T m_allocation; // actual allocated size + UINT32 m_flags; // @todo: steal flags from sizes + + protected: + union { + BYTE *m_buffer; + wchar_t *m_asStr; // For debugging, view as a unicode string + }; + +#if _DEBUG + protected: + // We will update the "revision" of the buffer every time it is potentially reallocation, + // so we can tell when iterators are no longer valid. + int m_revision; +#endif +}; + +// ================================================================================ +// InlineSBuffer : Tlempate for an SBuffer with preallocated buffer space +// ================================================================================ + +#define BUFFER_ALIGNMENT 4 + +template +class InlineSBuffer : public SBuffer +{ + private: +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) // zero sized array +#pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads + DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[size]; +#pragma warning(pop) +#else + // use UINT64 to get maximum alignment of the memory + UINT64 m_prealloc[ALIGN(size,sizeof(UINT64))/sizeof(UINT64)]; +#endif // _MSC_VER + + public: + InlineSBuffer() + : SBuffer(Prealloc, (BYTE*)m_prealloc, size) + { + WRAPPER_NO_CONTRACT; + } +}; + + +// a 1K sized buffer filled with $ that we'll use in debug builds for verification +#define GARBAGE_FILL_DWORD 0x24242424 // $$$$ +#define GARBAGE_FILL_BUFFER_ITEMS 16 +#define GARBAGE_FILL_BUFFER_SIZE GARBAGE_FILL_BUFFER_ITEMS*sizeof(DWORD) +// ================================================================================ +// StackSBuffer : SBuffer with relatively large preallocated buffer for stack use +// ================================================================================ + +#define STACK_ALLOC 256 + +typedef InlineSBuffer StackSBuffer; + +// ================================================================================ +// Inline definitions +// ================================================================================ + +/// a wrapper for templates and such, that use "==". +/// more expensive than a typical "==", though +inline BOOL operator == (const SBuffer& b1,const SBuffer& b2) +{ + return b1.Equals(b2); +}; + +#include + +#endif // _SBUFFER_H_ diff --git a/lib/coreclr/src/inc/sbuffer.inl b/lib/coreclr/src/inc/sbuffer.inl new file mode 100644 index 0000000000..30c93c831e --- /dev/null +++ b/lib/coreclr/src/inc/sbuffer.inl @@ -0,0 +1,1698 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +#ifndef _SBUFFER_INL_ +#define _SBUFFER_INL_ + +#include "sbuffer.h" + +#if defined(_MSC_VER) +#pragma inline_depth (20) +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4702) // Disable bogus unreachable code warning +#endif // _MSC_VER + +inline SBuffer::SBuffer(PreallocFlag flag, void *buffer, COUNT_T size) + : m_size(0), + m_allocation(NULL), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + m_buffer = UseBuffer((BYTE *) buffer, &size); + m_allocation = size; + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + +inline SBuffer::SBuffer() + : m_size(0), + m_allocation(0), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + +inline SBuffer::SBuffer(COUNT_T size) + : m_size(0), + m_allocation(0), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + {; + CONSTRUCTOR_CHECK; + PRECONDITION(CheckSize(size)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Resize(size); + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + +inline SBuffer::SBuffer(const SBuffer &buffer) + : m_size(0), + m_allocation(0), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + PRECONDITION(buffer.Check()); + POSTCONDITION(Equals(buffer)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Set(buffer); + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + +inline SBuffer::SBuffer(const BYTE *buffer, COUNT_T size) + : m_size(0), + m_allocation(0), + m_flags(0), + m_buffer(NULL) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(Equals(buffer, size)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Set(buffer, size); + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + + +inline SBuffer::SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T size) + : m_size(size), + m_allocation(size), + m_flags(IMMUTABLE), + m_buffer(const_cast(buffer)) +{ + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(Equals(buffer, size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#ifdef _DEBUG + m_revision = 0; +#endif + + RETURN; +} + +inline SBuffer::~SBuffer() +{ + CONTRACT_VOID + { + NOTHROW; + DESTRUCTOR_CHECK; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (IsAllocated()) + { + DeleteBuffer(m_buffer, m_allocation); + } + + RETURN; +} + +inline void SBuffer::Set(const SBuffer &buffer) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(buffer.Check()); + POSTCONDITION(Equals(buffer)); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (buffer.IsImmutable() + && (IsImmutable() || m_allocation < buffer.GetSize())) + { + // Share immutable block rather than reallocate and copy + // (Note that we prefer to copy to our buffer if we + // don't have to reallocate it.) + + if (IsAllocated()) + DeleteBuffer(m_buffer, m_allocation); + + m_size = buffer.m_size; + m_allocation = buffer.m_allocation; + m_buffer = buffer.m_buffer; + m_flags = buffer.m_flags; + +#if _DEBUG + // Increment our revision to invalidate iterators + m_revision++; +#endif + + } + else + { + Resize(buffer.m_size, DONT_PRESERVE); + EnsureMutable(); + + // PreFix seems to think it can choose m_allocation==0 and buffer.m_size > 0 here. + // From the code for Resize and EnsureMutable, this is clearly impossible. + PREFIX_ASSUME( (this->m_buffer != NULL) || (buffer.m_size == 0) ); + + MoveMemory(m_buffer, buffer.m_buffer, buffer.m_size); + } + + RETURN; +} + +inline void SBuffer::Set(const BYTE *buffer, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(Equals(buffer, size)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Resize(size); + EnsureMutable(); + + // PreFix seems to think it can choose m_allocation==0 and size > 0 here. + // From the code for Resize, this is clearly impossible. + PREFIX_ASSUME( (this->m_buffer != NULL) || (size == 0) ); + + MoveMemory(m_buffer, buffer, size); + + RETURN; +} + +inline void SBuffer::SetImmutable(const BYTE *buffer, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(Equals(buffer, size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + + } + CONTRACT_END; + + SBuffer temp(Immutable, buffer, size); + + { + // This can't really throw + CONTRACT_VIOLATION(ThrowsViolation); + Set(temp); + } + + RETURN; +} + +inline COUNT_T SBuffer::GetSize() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return m_size; +} + +inline void SBuffer::SetSize(COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckSize(size)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Resize(size); + + RETURN; +} + +inline void SBuffer::MaximizeSize() +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (!IsImmutable()) + Resize(m_allocation); + + RETURN; +} + +inline COUNT_T SBuffer::GetAllocation() const +{ + CONTRACT(COUNT_T) + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACT_END; + + RETURN m_allocation; +} + +inline void SBuffer::Preallocate(COUNT_T allocation) const +{ + CONTRACT_VOID + { + if (allocation) THROWS; else NOTHROW; + INSTANCE_CHECK; + PRECONDITION(CheckAllocation(allocation)); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (allocation > m_allocation) + const_cast(this)->ReallocateBuffer(allocation, PRESERVE); + + RETURN; +} + +inline void SBuffer::Trim() const +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (!IsImmutable()) + const_cast(this)->ReallocateBuffer(m_size, PRESERVE); + + RETURN; +} + +inline void SBuffer::Zero() +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + ZeroMemory(m_buffer, m_size); + + RETURN; +} + +inline void SBuffer::Fill(BYTE value) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + memset(m_buffer, value, m_size); + + RETURN; +} + +inline void SBuffer::Fill(const Iterator &i, BYTE value, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i, size)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + memset(i.m_ptr, value, size); + + RETURN; +} + +inline void SBuffer::Copy(const Iterator &to, const CIterator &from, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(to, size)); + PRECONDITION(CheckIteratorRange(from, size)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + DebugDestructBuffer(to.m_ptr, size); + + DebugCopyConstructBuffer(to.m_ptr, from.m_ptr, size); + + RETURN; +} + +inline void SBuffer::Move(const Iterator &to, const CIterator &from, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(to, size)); + PRECONDITION(CheckIteratorRange(from, size)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + DebugDestructBuffer(to.m_ptr, size); + + DebugMoveBuffer(to.m_ptr, from.m_ptr, size); + + DebugConstructBuffer(from.m_ptr, size); + + RETURN; +} + +inline void SBuffer::Copy(const Iterator &i, const SBuffer &source) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i, source.GetSize())); + PRECONDITION(source.Check()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + DebugDestructBuffer(i.m_ptr, source.m_size); + + DebugCopyConstructBuffer(i.m_ptr, source.m_buffer, source.m_size); + + RETURN; +} + +inline void SBuffer::Copy(const Iterator &i, const void *source, COUNT_T size) +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckSize(size)); + PRECONDITION(CheckIteratorRange(i, size)); + PRECONDITION(CheckPointer(source, size == 0 ? NULL_OK : NULL_NOT_OK)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + CONTRACT_END; + + DebugDestructBuffer(i.m_ptr, size); + + DebugCopyConstructBuffer(i.m_ptr, (const BYTE *) source, size); + + RETURN; +} + +inline void SBuffer::Copy(void *dest, const CIterator &i, COUNT_T size) +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckSize(size)); + PRECONDITION(CheckIteratorRange(i, size)); + PRECONDITION(CheckPointer(dest, size == 0 ? NULL_OK : NULL_NOT_OK)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + memcpy(dest, i.m_ptr, size); + + RETURN; +} + +inline void SBuffer::Insert(const Iterator &i, const SBuffer &source) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + THROWS; + PRECONDITION(CheckIteratorRange(i,0)); + GC_NOTRIGGER; + } + CONTRACT_END; + + Replace(i, 0, source.GetSize()); + Copy(i, source, source.GetSize()); + + RETURN; +} + +inline void SBuffer::Insert(const Iterator &i, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + THROWS; + PRECONDITION(CheckIteratorRange(i,0)); + GC_NOTRIGGER; + } + CONTRACT_END; + + Replace(i, 0, size); + + RETURN; +} + +inline void SBuffer::Clear() +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Delete(Begin(), GetSize()); + + RETURN; +} + +inline void SBuffer::Delete(const Iterator &i, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i, size)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Replace(i, size, 0); + + RETURN; +} + +inline void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, const SBuffer &insert) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i, deleteSize)); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Replace(i, deleteSize, insert.GetSize()); + Copy(i, insert, insert.GetSize()); + + RETURN; +} + +inline int SBuffer::Compare(const SBuffer &compare) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(compare.Check()); + POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN Compare(compare.m_buffer, compare.m_size); +} + +inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(compare)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + COUNT_T smaller; + int equals; + int result; + + if (m_size < size) + { + smaller = m_size; + equals = -1; + } + else if (m_size > size) + { + smaller = size; + equals = 1; + } + else + { + smaller = size; + equals = 0; + } + + result = memcmp(m_buffer, compare, size); + + if (result == 0) + RETURN equals; + else + RETURN result; +} + +inline BOOL SBuffer::Equals(const SBuffer &compare) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(compare.Check()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN Equals(compare.m_buffer, compare.m_size); +} + +inline BOOL SBuffer::Equals(const BYTE *compare, COUNT_T size) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(compare)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (m_size != size) + RETURN FALSE; + else + RETURN (memcmp(m_buffer, compare, size) == 0); +} + +inline BOOL SBuffer::Match(const CIterator &i, const SBuffer &match) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(match.Check()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN Match(i, match.m_buffer, match.m_size); +} + +inline BOOL SBuffer::Match(const CIterator &i, const BYTE *match, COUNT_T size) const +{ + CONTRACT(int) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(match)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + COUNT_T remaining = (COUNT_T) (m_buffer + m_size - i.m_ptr); + + if (remaining < size) + RETURN FALSE; + + RETURN (memcmp(i.m_ptr, match, size) == 0); +} + +//---------------------------------------------------------------------------- +// EnsureMutable +// Ensures that the buffer is mutable +//---------------------------------------------------------------------------- +inline void SBuffer::EnsureMutable() const +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckBufferClosed()); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (IsImmutable()) + const_cast(this)->ReallocateBuffer(m_allocation, PRESERVE); + + RETURN; +} + +//---------------------------------------------------------------------------- +// Resize +// Change the visible size of the buffer; realloc if necessary +//---------------------------------------------------------------------------- +FORCEINLINE void SBuffer::Resize(COUNT_T size, Preserve preserve) +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(GetSize() == size); + POSTCONDITION(m_allocation >= GetSize()); + POSTCONDITION(CheckInvariant(*this)); + if (size > 0) THROWS; else NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#ifdef _DEBUG + // Change our revision + m_revision++; +#endif + + SCOUNT_T delta = size - m_size; + + if (delta < 0) + DebugDestructBuffer(m_buffer + size, -delta); + + // Only actually allocate if we are growing + if (size > m_allocation) + ReallocateBuffer(size, preserve); + + if (delta > 0) + DebugConstructBuffer(m_buffer + m_size, delta); + + m_size = size; + + RETURN; +} + +//---------------------------------------------------------------------------- +// ResizePadded +// Change the visible size of the buffer; realloc if necessary +// add extra space to minimize further growth +//---------------------------------------------------------------------------- +inline void SBuffer::ResizePadded(COUNT_T size, Preserve preserve) +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckSize(size)); + POSTCONDITION(GetSize() == size); + POSTCONDITION(m_allocation >= GetSize()); + POSTCONDITION(CheckInvariant(*this)); + if (size > 0) THROWS; else NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#ifdef _DEBUG + // Change our revision + m_revision++; +#endif + + SCOUNT_T delta = size - m_size; + + if (delta < 0) + DebugDestructBuffer(m_buffer + size, -delta); + + // Only actually allocate if we are growing + if (size > m_allocation) + { + COUNT_T padded = (size*3)/2; + + ReallocateBuffer(padded, preserve); + } + + if (delta > 0) + DebugConstructBuffer(m_buffer + m_size, delta); + + m_size = size; + + RETURN; +} + +//---------------------------------------------------------------------------- +// TweakSize +// An optimized form of Resize, which can only adjust the size within the +// currently allocated range, and never reallocates +//---------------------------------------------------------------------------- +inline void SBuffer::TweakSize(COUNT_T size) +{ + CONTRACT_VOID + { + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckSize(size)); + PRECONDITION(size <= GetAllocation()); + POSTCONDITION(GetSize() == size); + POSTCONDITION(CheckInvariant(*this)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#ifdef _DEBUG + // Change our revision + m_revision++; +#endif + + SCOUNT_T delta = size - m_size; + + if (delta < 0) + DebugDestructBuffer(m_buffer + size, -delta); + else + DebugConstructBuffer(m_buffer + m_size, delta); + + m_size = size; + + RETURN; +} + +//----------------------------------------------------------------------------- +// SBuffer allocates all memory via NewBuffer & DeleteBuffer members. +// If SBUFFER_CANARY_CHECKS is defined, NewBuffer will place Canaries at the start +// and end of the buffer to detect overflows. +//----------------------------------------------------------------------------- + +#ifdef _DEBUG +#define SBUFFER_CANARY_CHECKS 1 +#endif + +#ifdef SBUFFER_CANARY_CHECKS + +// The value we place at the start/end of the buffer, +static const UINT64 SBUFFER_CANARY_VALUE = UI64(0xD00BED00BED00BAA); + +// Expose the quantity of padding needed when providing a prealloced +// buffer. This is an unrolled version of the actualAllocation calculated +// below for use as a constant value for InlineSString to use. It is +// padded with one additional sizeof(SBUFFER_CANARY_VALUE) to account for +// possible alignment problems issues (pre- and post-padding). +#define SBUFFER_PADDED_SIZE(desiredUsefulSize) \ + ((((SIZE_T)(desiredUsefulSize) + sizeof(SBUFFER_CANARY_VALUE) - 1) & \ + ~(sizeof(SBUFFER_CANARY_VALUE)-1)) + 3 * sizeof(SBUFFER_CANARY_VALUE)) + +#else // SBUFFER_CANARY_CHECKS + +#define SBUFFER_PADDED_SIZE(desiredUsefulSize) (desiredUsefulSize) + +#endif // SBUFFER_CANARY_CHECKS else + +// Must match expected guaranteed alignment of new [] +#ifdef ALIGN_ACCESS +static const int SBUFFER_ALIGNMENT = ALIGN_ACCESS; +#else +// This is only 4 bytes on win98 and below +static const int SBUFFER_ALIGNMENT = 4; +#endif + +//---------------------------------------------------------------------------- +// Allocate memory, use canaries. +//---------------------------------------------------------------------------- +inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) +{ + CONTRACT(BYTE*) + { + PRECONDITION(CheckSize(allocation)); + PRECONDITION(allocation > 0); + POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#ifdef SBUFFER_CANARY_CHECKS + + COUNT_T alignPadding = AlignmentPad(allocation, sizeof(SBUFFER_CANARY_VALUE)); + COUNT_T actualAllocation= sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding + sizeof(SBUFFER_CANARY_VALUE); + BYTE *raw = new BYTE [actualAllocation]; + + *(UINT64*) raw = SBUFFER_CANARY_VALUE; + *(UINT64*) (raw + sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding) = SBUFFER_CANARY_VALUE; + + BYTE *buffer = raw + sizeof(SBUFFER_CANARY_VALUE); + +#else + + BYTE *buffer = new BYTE [allocation]; + +#endif + + DebugStompUnusedBuffer(buffer, allocation); + + CONSISTENCY_CHECK(CheckBuffer(buffer, allocation)); + + RETURN buffer; +} + +//---------------------------------------------------------------------------- +// Use existing memory, use canaries. +//---------------------------------------------------------------------------- +inline BYTE *SBuffer::UseBuffer(BYTE *buffer, COUNT_T *allocation) +{ + CONTRACT(BYTE*) + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC_HOST_ONLY; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckSize(*allocation)); +// POSTCONDITION(CheckPointer(RETVAL)); + POSTCONDITION(CheckSize(*allocation)); + } + CONTRACT_END; + +#ifdef SBUFFER_CANARY_CHECKS + + COUNT_T prepad = AlignmentPad((SIZE_T) buffer, sizeof(SBUFFER_CANARY_VALUE)); + COUNT_T postpad = AlignmentTrim((SIZE_T) buffer+*allocation, sizeof(SBUFFER_CANARY_VALUE)); + + SCOUNT_T usableAllocation = *allocation - prepad - sizeof(SBUFFER_CANARY_VALUE) - sizeof(SBUFFER_CANARY_VALUE) - postpad; + if (usableAllocation <= 0) + { + buffer = NULL; + *allocation = 0; + } + else + { + BYTE *result = buffer + prepad + sizeof(SBUFFER_CANARY_VALUE); + + *(UINT64*) (buffer + prepad) = SBUFFER_CANARY_VALUE; + *(UINT64*) (buffer + prepad + sizeof(SBUFFER_CANARY_VALUE) + usableAllocation) = SBUFFER_CANARY_VALUE; + + buffer = result; + *allocation = usableAllocation; + } + +#endif + + DebugStompUnusedBuffer(buffer, *allocation); + + CONSISTENCY_CHECK(CheckBuffer(buffer, *allocation)); + + RETURN buffer; +} + +//---------------------------------------------------------------------------- +// Free memory allocated by NewHelper +//---------------------------------------------------------------------------- +inline void SBuffer::DeleteBuffer(BYTE *buffer, COUNT_T allocation) +{ + CONTRACT_VOID + { + PRECONDITION(CheckSize(allocation)); + POSTCONDITION(CheckPointer(buffer)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + CONSISTENCY_CHECK(CheckBuffer(buffer, allocation)); + +#ifdef SBUFFER_CANARY_CHECKS + + delete [] (buffer - sizeof(SBUFFER_CANARY_VALUE)); + +#else + + delete [] buffer; + +#endif + + RETURN; +} + +//---------------------------------------------------------------------------- +// Check the buffer at the given address. The memory must have been a pointer +// returned by NewHelper. +//---------------------------------------------------------------------------- +inline CHECK SBuffer::CheckBuffer(const BYTE *buffer, COUNT_T allocation) const +{ + CONTRACT_CHECK + { + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + PRECONDITION(CheckPointer(buffer)); + } + CONTRACT_CHECK_END; + + if (allocation > 0) + { +#ifdef SBUFFER_CANARY_CHECKS + const BYTE *raw = buffer - sizeof(SBUFFER_CANARY_VALUE); + + COUNT_T alignPadding = ((allocation + (sizeof(SBUFFER_CANARY_VALUE) - 1)) & ~((sizeof(SBUFFER_CANARY_VALUE) - 1))) - allocation; + + CHECK_MSG(*(UINT64*) raw == SBUFFER_CANARY_VALUE, "SBuffer underflow"); + CHECK_MSG(*(UINT64*) (raw + sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding) == SBUFFER_CANARY_VALUE, "SBuffer overflow"); + +#endif + + CHECK_MSG((((SIZE_T)buffer) & (SBUFFER_ALIGNMENT-1)) == 0, "SBuffer not properly aligned"); + } + + CHECK_OK; +} + + +inline BYTE *SBuffer::OpenRawBuffer(COUNT_T size) +{ + CONTRACT(BYTE*) + { +#if _DEBUG + PRECONDITION_MSG(!IsOpened(), "Can't nest calls to OpenBuffer()"); +#endif + PRECONDITION(CheckSize(size)); + POSTCONDITION(GetSize() == size); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + Resize(size); + EnsureMutable(); + +#if _DEBUG + SetOpened(); +#endif + + RETURN m_buffer; +} + +//---------------------------------------------------------------------------- +// Close an open buffer. Assumes that we wrote exactly number of characters +// we requested in OpenBuffer. +//---------------------------------------------------------------------------- +inline void SBuffer::CloseRawBuffer() +{ + CONTRACT_VOID + { +#if _DEBUG + PRECONDITION(IsOpened()); +#endif + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + CloseRawBuffer(m_size); + + RETURN; +} + +//---------------------------------------------------------------------------- +// CloseBuffer() tells the SBuffer that we're done using the unsafe buffer. +// finalSize is the count of bytes actually used (so we can set m_count). +// This is important if we request a buffer larger than what we actually +// used. +//---------------------------------------------------------------------------- +inline void SBuffer::CloseRawBuffer(COUNT_T finalSize) +{ + CONTRACT_VOID + { +#if _DEBUG + PRECONDITION_MSG(IsOpened(), "Can only CloseRawBuffer() after a call to OpenRawBuffer()"); +#endif + PRECONDITION(CheckSize(finalSize)); + PRECONDITION_MSG(finalSize <= GetSize(), "Can't use more characters than requested via OpenRawBuffer()"); + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + +#if _DEBUG + ClearOpened(); +#endif + + TweakSize(finalSize); + + CONSISTENCY_CHECK(CheckBuffer(m_buffer, m_allocation)); + + RETURN; +} + +inline SBuffer::operator const void *() const +{ + LIMITED_METHOD_CONTRACT; + + return (void *) m_buffer; +} + +inline SBuffer::operator const BYTE *() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return m_buffer; +} + +inline BYTE &SBuffer::operator[](int index) +{ + LIMITED_METHOD_CONTRACT; + + return m_buffer[index]; +} + +inline const BYTE &SBuffer::operator[](int index) const +{ + LIMITED_METHOD_CONTRACT; + + return m_buffer[index]; +} + +inline SBuffer::Iterator SBuffer::Begin() +{ + CONTRACT(SBuffer::Iterator) + { + INSTANCE_CHECK; + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + // This is a bit unfortunate to have to do here, but it's our + // last opportunity before possibly doing a *i= with the iterator + EnsureMutable(); + + RETURN Iterator(this, 0); +} + +inline SBuffer::Iterator SBuffer::End() +{ + CONTRACT(SBuffer::Iterator) + { + INSTANCE_CHECK; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + // This is a bit unfortunate to have to do here, but it's our + // last opportunity before possibly doing a *i= with the iterator + EnsureMutable(); + + RETURN Iterator(this, m_size); +} + +inline SBuffer::CIterator SBuffer::Begin() const +{ + CONTRACT(SBuffer::CIterator) + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN SBuffer::CIterator(this, 0); +} + +inline SBuffer::CIterator SBuffer::End() const +{ + CONTRACT(SBuffer::CIterator) + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN CIterator(const_cast(this), m_size); +} + +inline BOOL SBuffer::IsAllocated() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (m_flags & ALLOCATED) != 0; +} + +inline void SBuffer::SetAllocated() +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_flags |= ALLOCATED; +} + +inline void SBuffer::ClearAllocated() +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_flags &= ~ALLOCATED; +} + +inline BOOL SBuffer::IsImmutable() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (m_flags & IMMUTABLE) != 0; +} + +inline void SBuffer::SetImmutable() +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_flags |= IMMUTABLE; +} + +inline void SBuffer::ClearImmutable() +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_flags &= ~IMMUTABLE; +} + +inline BOOL SBuffer::IsFlag1() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (m_flags & FLAG1) != 0; +} + +inline void SBuffer::SetFlag1() +{ + LIMITED_METHOD_DAC_CONTRACT; + + m_flags |= FLAG1; +} + +inline void SBuffer::ClearFlag1() +{ + LIMITED_METHOD_CONTRACT; + + m_flags &= ~FLAG1; +} + +inline BOOL SBuffer::IsFlag2() const +{ + LIMITED_METHOD_CONTRACT; + + return (m_flags & FLAG2) != 0; +} + +inline void SBuffer::SetFlag2() +{ + LIMITED_METHOD_CONTRACT; + + m_flags |= FLAG2; +} + +inline void SBuffer::ClearFlag2() +{ + LIMITED_METHOD_CONTRACT; + + m_flags &= ~FLAG2; +} + +inline BOOL SBuffer::IsFlag3() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (m_flags & FLAG3) != 0; +} + +inline void SBuffer::SetFlag3() +{ + LIMITED_METHOD_CONTRACT; + + m_flags |= FLAG3; +} + +inline void SBuffer::ClearFlag3() +{ + LIMITED_METHOD_DAC_CONTRACT; + + m_flags &= ~FLAG3; +} + +inline int SBuffer::GetRepresentationField() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + return (m_flags & REPRESENTATION_MASK); +} + +inline void SBuffer::SetRepresentationField(int value) +{ + CONTRACT_VOID + { + PRECONDITION((value & ~REPRESENTATION_MASK) == 0); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + m_flags &= ~REPRESENTATION_MASK; + m_flags |= value; + + RETURN; +} + +#if _DEBUG +inline BOOL SBuffer::IsOpened() const +{ + LIMITED_METHOD_CONTRACT; + + return (m_flags & OPENED) != 0; +} + +inline void SBuffer::SetOpened() +{ + LIMITED_METHOD_CONTRACT; + + m_flags |= OPENED; +} + +inline void SBuffer::ClearOpened() +{ + LIMITED_METHOD_CONTRACT; + + m_flags &= ~OPENED; +} +#endif + +inline void SBuffer::DebugMoveBuffer(__out_bcount(size) BYTE *to, BYTE *from, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(to, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckPointer(from, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (size == 0) // special case + RETURN; + + // Handle overlapping ranges + if (to > from && to < from + size) + CONSISTENCY_CHECK(CheckUnusedBuffer(from + size, (COUNT_T) (to - from))); + else if (to < from && to + size > from) + CONSISTENCY_CHECK(CheckUnusedBuffer(to, (COUNT_T) (from - to))); + else + CONSISTENCY_CHECK(CheckUnusedBuffer(to, size)); + + memmove(to, from, size); + + // Handle overlapping ranges + if (to > from && to < from + size) + DebugStompUnusedBuffer(from, (COUNT_T) (to - from)); + else if (to < from && to + size > from) + DebugStompUnusedBuffer(to + size, (COUNT_T) (from - to)); + else + DebugStompUnusedBuffer(from, size); + + RETURN; +} + +inline void SBuffer::DebugCopyConstructBuffer(__out_bcount(size) BYTE *to, const BYTE *from, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(to, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckPointer(from, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (size != 0) { + CONSISTENCY_CHECK(CheckUnusedBuffer(to, size)); + memmove(to, from, size); + } + + RETURN; +} + +inline void SBuffer::DebugConstructBuffer(BYTE *buffer, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC; + DEBUG_ONLY; + } + CONTRACT_END; + + if (size != 0) { + CONSISTENCY_CHECK(CheckUnusedBuffer(buffer, size)); + } + + RETURN; +} + +inline void SBuffer::DebugDestructBuffer(BYTE *buffer, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + DEBUG_ONLY; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + if (size != 0) + { + DebugStompUnusedBuffer(buffer, size); + } + + RETURN; +} + +static const BYTE GARBAGE_FILL_CHARACTER = '$'; + +extern const DWORD g_garbageFillBuffer[]; + +inline void SBuffer::DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size) +{ + CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); + PRECONDITION(CheckSize(size)); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + DEBUG_ONLY; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + +#if _DEBUG + if (!IsImmutable() + || buffer < m_buffer || buffer > m_buffer + m_allocation) // Allocating a new buffer + { + // Whack the memory + if (size > GARBAGE_FILL_BUFFER_SIZE) size = GARBAGE_FILL_BUFFER_SIZE; + memset(buffer, GARBAGE_FILL_CHARACTER, size); + } +#endif + + RETURN; +} + +#if _DEBUG +inline BOOL SBuffer::EnsureGarbageCharOnly(const BYTE *buffer, COUNT_T size) +{ + LIMITED_METHOD_CONTRACT; + BOOL bRet = TRUE; + if (size > GARBAGE_FILL_BUFFER_SIZE) + { + size = GARBAGE_FILL_BUFFER_SIZE; + } + if (bRet && size > 0) + { + bRet &= (memcmp(buffer, g_garbageFillBuffer, size) == 0); + } + return bRet; +} +#endif + +inline CHECK SBuffer::CheckUnusedBuffer(const BYTE *buffer, COUNT_T size) const +{ + WRAPPER_NO_CONTRACT; + // This check is too expensive. +#if 0 // _DEBUG + if (!IsImmutable() + || buffer < m_buffer || buffer > m_buffer + m_allocation) // Allocating a new buffer + { + if (!SBuffer::EnsureGarbageCharOnly(buffer, size)) + { + CHECK_FAIL("Overwrite of unused buffer region found"); + } + } +#endif + CHECK_OK; +} + +inline CHECK SBuffer::Check() const +{ + WRAPPER_NO_CONTRACT; + CHECK(CheckBufferClosed()); + CHECK_OK; +} + +inline CHECK SBuffer::Invariant() const +{ + LIMITED_METHOD_CONTRACT; + + CHECK_OK; +} + +inline CHECK SBuffer::InternalInvariant() const +{ + WRAPPER_NO_CONTRACT; + CHECK(m_size <= m_allocation); + + CHECK(CheckUnusedBuffer(m_buffer + m_size, m_allocation - m_size)); + + if (IsAllocated()) + CHECK(CheckBuffer(m_buffer, m_allocation)); + + CHECK_OK; +} + +inline CHECK SBuffer::CheckBufferClosed() const +{ + WRAPPER_NO_CONTRACT; +#if _DEBUG + CHECK_MSG(!IsOpened(), "Cannot use buffer API while raw open is in progress"); +#endif + CHECK_OK; +} + +inline CHECK SBuffer::CheckSize(COUNT_T size) +{ + LIMITED_METHOD_CONTRACT; + // !todo: add any range checking here + CHECK_OK; +} + +inline CHECK SBuffer::CheckAllocation(COUNT_T size) +{ + LIMITED_METHOD_CONTRACT; + + // !todo: add any range checking here + CHECK_OK; +} + +inline CHECK SBuffer::CheckIteratorRange(const CIterator &i) const +{ + WRAPPER_NO_CONTRACT; + CHECK(i.Check()); + CHECK(i.CheckContainer(this)); + CHECK(i >= Begin()); + CHECK(i < End()); + CHECK_OK; +} + +inline CHECK SBuffer::CheckIteratorRange(const CIterator &i, COUNT_T size) const +{ + WRAPPER_NO_CONTRACT; + CHECK(i.Check()); + CHECK(i.CheckContainer(this)); + CHECK(i >= Begin()); + CHECK(i + size <= End()); + CHECK_OK; +} + +inline SBuffer::Index::Index() +{ + LIMITED_METHOD_DAC_CONTRACT; + + m_ptr = NULL; +} + +inline SBuffer::Index::Index(SBuffer *container, SCOUNT_T index) + : CheckedIteratorBase(container) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_ptr = container->m_buffer + index; +} + +inline BYTE &SBuffer::Index::GetAt(SCOUNT_T delta) const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return m_ptr[delta]; +} + +inline void SBuffer::Index::Skip(SCOUNT_T delta) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + m_ptr += delta; +} + +inline SCOUNT_T SBuffer::Index::Subtract(const Index &i) const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + return (SCOUNT_T) (m_ptr - i.m_ptr); +} + +inline CHECK SBuffer::Index::DoCheck(SCOUNT_T delta) const +{ + WRAPPER_NO_CONTRACT; +#if _DEBUG + CHECK(m_ptr + delta >= GetContainerDebug()->m_buffer); + CHECK(m_ptr + delta < GetContainerDebug()->m_buffer + GetContainerDebug()->m_size); +#endif + CHECK_OK; +} + +inline void SBuffer::Index::Resync(const SBuffer *buffer, BYTE *value) const +{ + CONTRACT_VOID + { + // INSTANCE_CHECK - Iterator is out of sync with its object now by definition + POSTCONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(buffer)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + CONTRACT_END; + + const_cast(this)->CheckedIteratorBase::Resync(const_cast(buffer)); + const_cast(this)->m_ptr = value; + + RETURN; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // _SBUFFER_INL_ diff --git a/lib/coreclr/src/inc/securityutil.h b/lib/coreclr/src/inc/securityutil.h new file mode 100644 index 0000000000..2278495bc5 --- /dev/null +++ b/lib/coreclr/src/inc/securityutil.h @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef SECURITYUTIL_H +#define SECURITYUTIL_H + +#include "winnt.h" + +// Security utility class. This is currently used by the debugger right-side and dbgshim to figure out the +// SECURITY_ATTRIBUTES to use on various IPC objects (named events, etc.). +// This is pretty debugger specific, and so perhaps doesn't actually belong in utilcode (that's just the most +// convenient way to share it between mscordbi and dbgshim.dll). This is also a pretty big mess. All of +// this ACL craziness is already gone in Arrowhead, so it's not a high priority to clean this up. +class SecurityUtil +{ +public: + + // + // This will generate ACL containing the current process and + // an allowed ACE on the target process of the given pid. + // + // Host should free returned *ppACL by calling FreeACL + // + static HRESULT GetACLOfPid(DWORD pid, PACL *ppACL); + + static void FreeACL(PACL pACL); + + static HRESULT GetMandatoryLabelFromProcess(HANDLE hProcess, LPBYTE * ppbLabel); + static DWORD * GetIntegrityLevelFromMandatorySID(PSID psidIntegrityLevelLabel); + + // instance functions. SecurityUtil is used to minimized memory allocation when converting + // pACL to SECURITY_ATTRIBUTES + // The needed memory to hold SECURITY_ATTRIBUTES and SECURITY_DESCRIPTOR are embedded + // in the SecurityUtil instance. + // + SecurityUtil(PACL pACL); + ~SecurityUtil(); + HRESULT Init(); + HRESULT Init(HANDLE pid); + HRESULT GetSA(SECURITY_ATTRIBUTES **PPSA); +private: + HRESULT SetSecurityDescriptorMandatoryLabel(PSID psidIntegrityLevelLabel); + SECURITY_ATTRIBUTES m_SA; + SECURITY_DESCRIPTOR m_SD; + PACL m_pACL; + // Saved by SetSecurityDescriptorMandatoryLabel so that the memory can be deleted properly + PACL m_pSacl; + bool m_fInitialized; +}; + +#endif // !SECURITYUTIL_H diff --git a/lib/coreclr/src/inc/securitywrapper.h b/lib/coreclr/src/inc/securitywrapper.h new file mode 100644 index 0000000000..1dad3a6cf5 --- /dev/null +++ b/lib/coreclr/src/inc/securitywrapper.h @@ -0,0 +1,103 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// File: SecurityWrapper.h +// +// Wrapper around Win32 Security functions +// +//***************************************************************************** + + +#ifndef _SECURITY_WRAPPER_H +#define _SECURITY_WRAPPER_H + +#ifdef FEATURE_PAL +#error This file should not be included on non-Windows platforms. +#endif + +//----------------------------------------------------------------------------- +// Wrapper around a PSID. +// This class does not own the memory. +//----------------------------------------------------------------------------- +class Sid +{ +public: + // Initial the Sid wrapper around an existing SID. + Sid(PSID pSid); + static bool Equals(const Sid & a, const Sid & b) { return Equals(a.m_pSid, b.m_pSid); } + static bool Equals(const Sid & a, PSID b) { return Equals(a.m_pSid, b); } + static bool Equals(PSID a, const Sid & b) { return Equals(a, b.m_pSid); } + static bool Equals(PSID a, PSID b); + + PSID RawSid() { return m_pSid; } +protected: + // Pointer to Sid buffer. We don't owner the data. + PSID m_pSid; +}; + +//----------------------------------------------------------------------------- +// Wrapper around a PSID with buffer. +//----------------------------------------------------------------------------- +class SidBuffer +{ +public: + SidBuffer(); + ~SidBuffer(); + + // Get the underlying sid + Sid GetSid(); + + // Do we not have a sid? This will be true if init fails. + bool IsNull() { return m_pBuffer == NULL; } + + // Go to definitions to see detailed comments + HRESULT InitFromProcessNoThrow(DWORD pid); + void InitFromProcess(DWORD pid); // throws + HRESULT InitFromProcessUserNoThrow(DWORD pid); + void InitFromProcessUser(DWORD pid); // throws + HRESULT InitFromProcessAppContainerSidNoThrow(DWORD pid); + +protected: + BYTE * m_pBuffer; +}; + +//----------------------------------------------------------------------------- +// Access Control List. +//----------------------------------------------------------------------------- +class Dacl +{ +public: + Dacl(PACL pAcl); + + SIZE_T GetAceCount(); + ACE_HEADER * GetAce(SIZE_T dwAceIndex); +protected: + PACL m_acl; +}; + +//----------------------------------------------------------------------------- +// Represent a win32 SECURITY_DESCRIPTOR object. +// (Note there's a "SecurityDescriptor" class in the VM for managed goo, +// so we prefix this with "Win32" to avoid a naming collision.) +//----------------------------------------------------------------------------- +class Win32SecurityDescriptor +{ +public: + Win32SecurityDescriptor(); + ~Win32SecurityDescriptor(); + + HRESULT InitFromHandleNoThrow(HANDLE h); + void InitFromHandle(HANDLE h); // throws + + // Gets the owner SID from this SecurityDescriptor. + HRESULT GetOwnerNoThrow( PSID* ppSid ); + Sid GetOwner(); // throws + Dacl GetDacl(); // throws + +protected: + PSECURITY_DESCRIPTOR m_pDesc; +}; + + +#endif // _SECURITY_WRAPPER_H diff --git a/lib/coreclr/src/inc/shash.h b/lib/coreclr/src/inc/shash.h new file mode 100644 index 0000000000..05a8a9d1e0 --- /dev/null +++ b/lib/coreclr/src/inc/shash.h @@ -0,0 +1,1106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _SHASH_H_ +#define _SHASH_H_ + +#include "utilcode.h" // for string hash functions +#include "clrtypes.h" +#include "check.h" +#include "iterator.h" + +// SHash is a templated closed chaining hash table of pointers. It provides +// for multiple entries under the same key, and also for deleting elements. + +// Synchronization: +// Synchronization requirements depend on use. There are several properties to take into account: +// +// - Lookups may be asynchronous with each other +// - Lookups must be exclusive with Add operations +// (@todo: this can be remedied by delaying destruction of old tables during reallocation, e.g. during GC) +// - Remove operations may be asynchronous with Lookup/Add, unless elements are also deallocated. (In which +// case full synchronization is required) + +// Common "gotchas": +// - The Add method never replaces an element. The new element will be added even if an element with the same +// key is already present. If you don't want this, use AddOrReplace. +// - You need special sentinel values for the element to represent Null and Deleted. 0 and -1 are the default +// choices but you will need something else if elements can legally have any of these two values. +// - Deriving directly from the general purpose classes (such as SHash itself) requires implementing a +// TRAITS class which can be daunting. Consider using one of the specialized classes (e.g. WStringSHash) first. + +// A SHash is templated by a class of TRAITS. These traits define the various specifics of the +// particular hash table. +// The required traits are: +// +// element_t Type of elements in the hash table. These elements are stored +// by value in the hash table. Elements must look more or less +// like primitives - they must support assignment relatively +// efficiently. There are 2 required sentinel values: +// Null and Deleted (described below). (Note that element_t is +// very commonly a pointer type.) +// +// The key must be derivable from the element; if your +// table's keys are independent of the stored values, element_t +// should be a key/value pair. +// +// key_t Type of the lookup key. The key is used for identity +// comparison between elements, and also as a key for lookup. +// This is also used by value and should support +// efficient assignment. +// +// count_t integral type for counts. Typically inherited by default +// Traits (COUNT_T). +// +// static key_t GetKey(const element_t &e) Get key from element. Should be stable for a given e. +// static BOOL Equals(key_t k1, key_t k2) Compare 2 keys for equality. Again, should be stable. +// static count_t Hash(key_t k) Compute hash from a key. For efficient operation, the hashes +// for a set of elements should have random uniform distribution. +// +// static const bool s_NoThrow TRUE if GetKey, Equals, and hash are NOTHROW functions. +// Affects the THROWS clauses of several SHash functions. +// (Note that the Null- and Deleted-related functions below +// are not affected by this and must always be NOTHROW.) +// +// static element_t Null() Return the Null sentinal value. May be inherited from +// default traits if it can be assigned from 0. +// static element_t Deleted() Return the Deleted sentinal value. May be inherited from the +// default traits if it can be assigned from -1. +// static const bool IsNull(const ELEMENT &e) Compare element with Null sentinal value. May be inherited from +// default traits if it can be assigned from 0. +// static const bool IsDeleted(const ELEMENT &e) Compare element with Deleted sentinal value. May be inherited from the +// default traits if it can be assigned from -1. +// +// static void OnDestructPerEntryCleanupAction(ELEMENT& e) Called on every element when in hashtable destructor. +// s_DestructPerEntryCleanupAction must be set to true if implemented. +// +// s_growth_factor_numerator +// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). +// Typically inherited from default traits (3/2) +// +// s_density_factor_numerator +// s_density_factor_denominator Maxium occupied density of table before growth +// occurs (num/denom). Typically inherited (3/4). +// +// s_minimum_allocation Minimum table allocation count (size on first growth.) It is +// probably preferable to call Reallocate on initialization rather +// than override his from the default traits. (7) +// +// s_supports_remove Set to false for a slightly faster implementation that does not +// support deletes. There is a downside to the s_supports_remove flag, +// in that there may be more copies of the template instantiated through +// the system as different variants are used. +// +// s_DestructPerEntryCleanupAction Set to true if OnDestructPerEntryCleanupAction has non-empty implementation. +// +// DefaultHashTraits provides defaults for seldomly customized values in traits classes. + +template < typename ELEMENT > +class DefaultSHashTraits +{ + public: + typedef COUNT_T count_t; + typedef ELEMENT element_t; + typedef DPTR(element_t) PTR_element_t; // by default SHash is DAC-aware. For RS + // only SHash use NonDacAwareSHashTraits + // (which typedefs element_t* PTR_element_t) + + static const COUNT_T s_growth_factor_numerator = 3; + static const COUNT_T s_growth_factor_denominator = 2; + + static const COUNT_T s_density_factor_numerator = 3; + static const COUNT_T s_density_factor_denominator = 4; + + static const COUNT_T s_minimum_allocation = 7; + + static const bool s_supports_remove = true; + + static ELEMENT Null() { return (const ELEMENT) 0; } + static ELEMENT Deleted() { return (const ELEMENT) -1; } + static bool IsNull(const ELEMENT &e) { return e == (const ELEMENT) 0; } + static bool IsDeleted(const ELEMENT &e) { return e == (const ELEMENT) -1; } + + static inline void OnDestructPerEntryCleanupAction(const ELEMENT& e) { /* Do nothing */ } + static const bool s_DestructPerEntryCleanupAction = false; + + static const bool s_NoThrow = true; + + // No defaults - must specify: + // + // typedef key_t; + // static key_t GetKey(const element_t &i); + // static BOOL Equals(key_t k1, key_t k2); + // static count_t Hash(key_t k); +}; + +// Hash table class definition + +template +class SHash : public TRAITS + , private noncopyable +{ + friend class VerifyLayoutsMD; // verifies class layout doesn't accidentally change + + public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef typename TRAITS::element_t element_t; + typedef typename TRAITS::PTR_element_t PTR_element_t; + typedef typename TRAITS::key_t key_t; + typedef typename TRAITS::count_t count_t; + + class Index; + friend class Index; + class Iterator; + + class KeyIndex; + friend class KeyIndex; + class KeyIterator; + + // Constructor/destructor. SHash tables always start out empty, with no + // allocation overhead. Call Reallocate to prime with an initial size if + // desired. + + SHash(); + + ~SHash(); + + // Lookup an element in the table by key. Returns NULL if no element in the table + // has the given key. Note that multiple entries for the same key may be stored - + // this will return the first element added. Use KeyIterator to find all elements + // with a given key. + + element_t Lookup(key_t key) const; + + // Pointer-based flavor of Lookup (allows efficient access to tables of structures) + + const element_t* LookupPtr(key_t key) const; + + // Add an element to the hash table. This will never replace an element; multiple + // elements may be stored with the same key. + + void Add(const element_t &element); + + // Add a new element to the hash table, if no element with the same key is already + // there. Otherwise, it will replace the existing element. This has the effect of + // updating an element rather than adding a duplicate. + void AddOrReplace(const element_t & element); + + // Remove the first element matching the key from the hash table. + + void Remove(key_t key); + + // Remove the specific element. + + void Remove(Iterator& i); + void Remove(KeyIterator& i); + + // Pointer-based flavor of Remove (allows efficient access to tables of structures) + + void RemovePtr(element_t * element); + + // Remove all elements in the hashtable + + void RemoveAll(); + + // Begin and End pointers for iteration over entire table. + + Iterator Begin() const; + Iterator End() const; + + // Begin and End pointers for iteration over all elements with a given key. + + KeyIterator Begin(key_t key) const; + KeyIterator End(key_t key) const; + + // Return the number of elements currently stored in the table + + count_t GetCount() const; + + // Resizes a hash table for growth. The new size is computed based + // on the current population, growth factor, and maximum density factor. + + void Grow(); + + // Reallocates a hash table to a specific size. The size must be big enough + // to hold all elements in the table appropriately. + // + // Note that the actual table size must always be a prime number; the number + // passed in will be upward adjusted if necessary. + + void Reallocate(count_t newTableSize); + + // Makes a call on the Functor for each element in the hash table, passing + // the element as an argument. Functor is expected to look like this: + // + // class Functor + // { + // public: + // void operator() (element_t &element) { ... } + // } + + template void ForEach(Functor &functor); + + private: + + // See if it is OK to grow the hash table by one element. If not, reallocate + // the hash table. + BOOL CheckGrowth(); + + // See if it is OK to grow the hash table by one element. If not, allocate new + // hash table and return it together with its size *pcNewSize (used by code:AddPhases). + // Returns NULL if there already is space for one element. + element_t * CheckGrowth_OnlyAllocateNewTable(count_t * pcNewSize); + + // Allocates new resized hash table for growth. Does not update the hash table on the object. + // The new size is computed based on the current population, growth factor, and maximum density factor. + element_t * Grow_OnlyAllocateNewTable(count_t * pcNewSize); + + // Utility function to allocate new table (does not copy the values into it yet). Returns the size of new table in + // *pcNewTableSize (finds next prime). + // Phase 1 of code:Reallocate - it is split to support code:AddPhases. + element_t * AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize); + + // Utility function to replace old table with newly allocated table (as allocated by + // code:AllocateNewTable). Copies all 'old' values into the new table first. + // Returns the old table. Caller is expected to delete it (via code:DeleteOldTable). + // Phase 2 of code:Reallocate - it is split to support code:AddPhases. + element_t * ReplaceTable(element_t * newTable, count_t newTableSize); + + // Utility function to delete old table (as returned by code:ReplaceTable). + // Phase 3 of code:Reallocate - it is split to support code:AddPhases. + void DeleteOldTable(element_t * oldTable); + + // Utility function that does not call code:CheckGrowth. + // Add an element to the hash table. This will never replace an element; multiple + // elements may be stored with the same key. + void Add_GrowthChecked(const element_t & element); + + // Utility function to add a new element to the hash table. Note that + // it is perfectly fine for the element to be a duplicate - if so it + // is added an additional time. Returns TRUE if a new empty spot was used; + // FALSE if an existing deleted slot. + static BOOL Add(element_t *table, count_t tableSize, const element_t &element); + + // Utility function to add a new element to the hash table, if no element with the same key + // is already there. Otherwise, it will replace the existing element. This has the effect of + // updating an element rather than adding a duplicate. + void AddOrReplace(element_t *table, count_t tableSize, const element_t &element); + + // Utility function to find the first element with the given key in + // the hash table. + + static const element_t* Lookup(PTR_element_t table, count_t tableSize, key_t key); + + // Utility function to remove the first element with the given key + // in the hash table. + + void Remove(element_t *table, count_t tableSize, key_t key); + + // Utility function to remove the specific element. + + void RemoveElement(element_t *table, count_t tableSize, element_t *element); + + // Index for whole table iterator. This is also the base for the keyed iterator. + + public: + + class Index +#ifdef _DEBUG + // CheckedIteratorBase is a no-op in RET builds. having it as an empty base-class + // causes differences in the sizeof(SHash::Iterator) in DAC vs. non-DAC builds. + // avoid the issue by not specifying it as a base class in RET builds + : public CheckedIteratorBase< SHash > +#endif + { + friend class SHash; + friend class Iterator; + friend class Enumerator; + + // The methods implementation has to be here for portability + // Some compilers won't compile the separate implementation in shash.inl + protected: + + PTR_element_t m_table; + count_t m_tableSize; + count_t m_index; + + + Index(const SHash *hash, BOOL begin) + : m_table(hash->m_table), + m_tableSize(hash->m_tableSize), + m_index(begin ? 0 : m_tableSize) + { + LIMITED_METHOD_CONTRACT; + } + + const element_t &Get() const + { + LIMITED_METHOD_CONTRACT; + + return m_table[m_index]; + } + + void First() + { + LIMITED_METHOD_CONTRACT; + + if (m_index < m_tableSize) + if (TRAITS::IsNull(m_table[m_index]) || TRAITS::IsDeleted(m_table[m_index])) + Next(); + } + + void Next() + { + LIMITED_METHOD_CONTRACT; + + if (m_index >= m_tableSize) + return; + + for (;;) + { + m_index++; + if (m_index >= m_tableSize) + break; + if (!TRAITS::IsNull(m_table[m_index]) && !TRAITS::IsDeleted(m_table[m_index])) + break; + } + } + + bool Equal(const Index &i) const + { + LIMITED_METHOD_CONTRACT; + + return i.m_index == m_index; + } + + CHECK DoCheck() const + { + CHECK_OK; + } + }; + + class Iterator : public Index, public Enumerator + { + friend class SHash; + + public: + Iterator(const SHash *hash, BOOL begin) + : Index(hash, begin) + { + } + }; + + // Index for iterating elements with a given key. + // + // Note that the m_index field + // is artificially bumped to m_tableSize when the end of iteration is reached. + // This allows a canonical End iterator to be used. + + class KeyIndex : public Index + { + friend class SHash; + friend class KeyIterator; + friend class Enumerator; + + // The methods implementation has to be here for portability + // Some compilers won't compile the separate implementation in shash.inl + protected: + key_t m_key; + count_t m_increment; + + KeyIndex(const SHash *hash, BOOL begin) + : Index(hash, begin), + m_increment(0) + { + LIMITED_METHOD_CONTRACT; + } + + void SetKey(key_t key) + { + LIMITED_METHOD_CONTRACT; + + if (Index::m_tableSize > 0) + { + m_key = key; + count_t hash = TRAITS::Hash(key); + + this->m_index = hash % this->m_tableSize; + m_increment = (hash % (this->m_tableSize-1)) + 1; + + // Find first valid element + if (TRAITS::IsNull(this->m_table[this->m_index])) + this->m_index = this->m_tableSize; + else if (TRAITS::IsDeleted(this->m_table[this->m_index]) + || !TRAITS::Equals(m_key, TRAITS::GetKey(this->m_table[this->m_index]))) + Next(); + } + } + + void Next() + { + LIMITED_METHOD_CONTRACT; + + while (TRUE) + { + this->m_index += m_increment; + if (this->m_index >= this->m_tableSize) + this->m_index -= this->m_tableSize; + + if (TRAITS::IsNull(this->m_table[this->m_index])) + { + this->m_index = this->m_tableSize; + break; + } + + if (!TRAITS::IsDeleted(this->m_table[this->m_index]) + && TRAITS::Equals(m_key, TRAITS::GetKey(this->m_table[this->m_index]))) + { + break; + } + } + } + }; + + class KeyIterator : public KeyIndex, public Enumerator + { + friend class SHash; + + public: + + operator Iterator &() + { + return *(Iterator*)this; + } + + operator const Iterator &() + { + return *(const Iterator*)this; + } + + KeyIterator(const SHash *hash, BOOL begin) + : KeyIndex(hash, begin) + { + } + }; + + // Wrapper and holder for adding an element to the hash table. Useful for Add operations that have to happen + // under a rare lock that does not allow call out into host. + // There are 3 phases: + // 1. code:PreallocateForAdd ... Can allocate memory (calls into host). + // 2. code:Add ... Adds one element (does NOT call into host). + // or code:AddNothing_PublishPreallocatedTable ... Publishes the pre-allocated memory from step #1 (if any). + // 3. code:DeleteOldTable (or destructor) ... Can delete the old memory (calls into host). + // Example: + // CrstHolder lockAdd(&crstLockForAdd); // Serialize all Add operations. + // HostAssemblyMap::AddPhases addCall; + // addCall.PreallocateForAdd(&shash); // 1. Allocates memory for one Add call (if needed). addCall serves as holder for the allocated memory. + // { + // // We cannot call out into host from ForbidSuspend region (i.e. no allocations/deallocations). + // ForbidSuspendThreadHolder suspend; // Required by the 'special' read-lock + // { + // CrstHolder lock(&crstLock); + // if (some_condition) + // { // 2a. Add item. This may replace SHash inner table with the one pre-allocated in step 1. + // addCall.Add(shashItem); + // } + // else + // { // 2b. Skip adding item. This may replace SHash inner table with the one pre-allocated in step 1. + // addCall.AddNothing_PublishPreallocatedTable(); + // } + // } + // } + // addCall.DeleteOldTable(); // 3. Cleanup old table memory from shash (if it was replaced by pre-allocated table in step 2). + // // Note: addCall destructor would take care of deleting the memory as well. + class AddPhases + { + public: + AddPhases(); + ~AddPhases(); + + // Prepares object for one call to code:Add. Pre-allocates new table memory if needed, does not publish + // the table yet (it is kept ready only in this holder for call to code:Add). + // Calls out into host. + void PreallocateForAdd(SHash * pHash); + + // Add an element to the hash table. This will never replace an element; multiple elements may be stored + // with the same key. + // Will use/publish pre-allocated memory from code:PreallocateForAdd. + // Does not call out into host. + // Only one Add* method can be called once per object! (Create a new object for each call) + void Add(const element_t & element); + + // Element will not be added to the hash table. + // Will use/publish pre-allocated memory from code:PreallocateForAdd. + // Does not call out into host. + // Only one Add* method can be called once per object! (Create a new object for each call) + void AddNothing_PublishPreallocatedTable(); + + // Deletes old table if it was replaced by call to code:Add or code:AddNothing_PublishPreallocatedTable. + // Calls out into host. + void DeleteOldTable(); + + private: + SHash * m_pHash; + element_t * m_newTable; + count_t m_newTableSize; + element_t * m_oldTable; + + #ifdef _DEBUG + PTR_element_t dbg_m_table; + count_t dbg_m_tableSize; + count_t dbg_m_tableCount; + count_t dbg_m_tableOccupied; + count_t dbg_m_tableMax; + BOOL dbg_m_fAddCalled; + #endif //_DEBUG + }; // class SHash::AddPhases + + // Adds an entry to the hash table according to the guidelines above for + // avoiding a callout to the host while the read lock is held. + // Returns true if elem was added to the map, otherwise false. + // When elem was not added (false is returned), and if ppStoredElem is non-null, + // then it is set to point to the value in the map. + template + bool CheckAddInPhases( + element_t const & elem, + LockT & lock, + AddLockT & addLock, + IUnknown * addRefObject = nullptr); + + private: + + // Test for prime number. + static BOOL IsPrime(COUNT_T number); + + // Find the next prime number >= the given value. + + static COUNT_T NextPrime(COUNT_T number); + + // Instance members + + PTR_element_t m_table; // pointer to table + count_t m_tableSize; // allocated size of table + count_t m_tableCount; // number of elements in table + count_t m_tableOccupied; // number, includes deleted slots + count_t m_tableMax; // maximum occupied count before reallocating +}; // class SHash + +// disables support for DAC marshaling. Useful for defining right-side only SHashes +template +class NonDacAwareSHashTraits : public PARENT +{ +public: + typedef typename PARENT::element_t element_t; + typedef element_t * PTR_element_t; +}; + +// disables support for removing elements - produces slightly faster implementation + +template +class NoRemoveSHashTraits : public PARENT +{ +public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef typename PARENT::element_t element_t; + typedef typename PARENT::count_t count_t; + + static const bool s_supports_remove = false; + static element_t Deleted() { UNREACHABLE(); } + static bool IsDeleted(const element_t &e) { LIMITED_METHOD_DAC_CONTRACT; return false; } +}; + +// PtrHashTraits is a template to provides useful defaults for pointer hash tables +// It relies on methods GetKey and Hash defined on ELEMENT + +template +class PtrSHashTraits : public DefaultSHashTraits +{ + public: + + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef DefaultSHashTraits PARENT; + typedef typename PARENT::element_t element_t; + typedef typename PARENT::count_t count_t; + + typedef KEY key_t; + + static key_t GetKey(const element_t &e) + { + WRAPPER_NO_CONTRACT; + return e->GetKey(); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return k1 == k2; + } + static count_t Hash(key_t k) + { + WRAPPER_NO_CONTRACT; + return ELEMENT::Hash(k); + } +}; + +template +class PtrSHash : public SHash< PtrSHashTraits > +{ +}; + +template +class PtrSHashWithCleanupTraits + : public PtrSHashTraits +{ +public: + void OnDestructPerEntryCleanupAction(ELEMENT * elem) + { + delete elem; + } + static const bool s_DestructPerEntryCleanupAction = true; +}; + +// a class that automatically deletes data referenced by the pointers (so effectively it takes ownership of the data) +// since I was too lazy to implement Remove() APIs properly, removing entries is disallowed +template +class PtrSHashWithCleanup : public SHash< NoRemoveSHashTraits< PtrSHashWithCleanupTraits > > +{ +}; + +// Provides case-sensitive comparison and hashing functionality through static +// and functor object methods. Can be instantiated with CHAR or WCHAR. +template +struct CaseSensitiveStringCompareHash +{ +private: + typedef CharT const * str_t; + + static size_t _strcmp(CHAR const *left, CHAR const *right) + { + return ::strcmp(left, right); + } + + static size_t _strcmp(WCHAR const *left, WCHAR const *right) + { + return ::wcscmp(left, right); + } + + static size_t _hash(CHAR const *str) + { + return HashStringA(str); + } + + static size_t _hash(WCHAR const *str) + { + return HashString(str); + } + +public: + static size_t compare(str_t left, str_t right) + { + return _strcmp(left, right); + } + + size_t operator()(str_t left, str_t right) + { + return compare(left, right); + } + + static size_t hash(str_t str) + { + return _hash(str); + } + + size_t operator()(str_t str) + { + return hash(str); + } +}; + +// Provides case-insensitive comparison and hashing functionality through static +// and functor object methods. Can be instantiated with CHAR or WCHAR. +template +struct CaseInsensitiveStringCompareHash +{ +private: + typedef CharT const * str_t; + + static size_t _strcmp(str_t left, str_t right) + { + return ::SString::_tstricmp(left, right); + } + + static size_t _hash(CHAR const *str) + { + return HashiStringA(str); + } + + static size_t _hash(WCHAR const *str) + { + return HashiString(str); + } + +public: + static size_t compare(str_t left, str_t right) + { + return _strcmp(left, right); + } + + size_t operator()(str_t left, str_t right) + { + return compare(left, right); + } + + static size_t hash(str_t str) + { + return _hash(str); + } + + size_t operator()(str_t str) + { + return hash(str); + } +}; + +// StringSHashTraits is a traits class useful for string-keyed +// pointer hash tables. + +template > +class StringSHashTraits : public PtrSHashTraits +{ +public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef PtrSHashTraits PARENT; + typedef typename PARENT::element_t element_t; + typedef typename PARENT::key_t key_t; + typedef typename PARENT::count_t count_t; + + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + + if (k1 == NULL && k2 == NULL) + return TRUE; + if (k1 == NULL || k2 == NULL) + return FALSE; + return ComparerT::compare(k1, k2) == 0; + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + + if (k == NULL) + return 0; + else + return (count_t)ComparerT::hash(k); + } +}; + +template // Could use IUnknown but would rather take advantage of C++ type checking +struct StringHashElement +{ + const CharT *GetKey() + { + return String; + } + + COMINTERFACE *Object; + CharT *String; +}; + +template > +class StringHashWithCleanupTraits : public StringSHashTraits, CharT, ComparerT> +{ +public: + void OnDestructPerEntryCleanupAction(StringHashElement * e) + { + if (e->String != NULL) + { + delete[] e->String; + } + + if (e->Object != NULL) + { + e->Object->Release(); + } + } + static const bool s_DestructPerEntryCleanupAction = true; +}; + +template > +class StringSHashWithCleanup : public SHash< StringHashWithCleanupTraits > +{ +}; + +template +class StringSHash : public SHash< StringSHashTraits > +{ +}; + +template +class WStringSHash : public SHash< StringSHashTraits > +{ +}; + +template +class SStringSHashTraits : public PtrSHashTraits +{ + public: + typedef PtrSHashTraits PARENT; + typedef typename PARENT::element_t element_t; + typedef typename PARENT::key_t key_t; + typedef typename PARENT::count_t count_t; + + static const bool s_NoThrow = false; + + static BOOL Equals(const key_t &k1, const key_t &k2) + { + WRAPPER_NO_CONTRACT; + return k1.Equals(k2); + } + static count_t Hash(const key_t &k) + { + WRAPPER_NO_CONTRACT; + return k.Hash(); + } +}; + +template +class SStringSHash : public SHash< SStringSHashTraits > +{ +}; + +template +class SetSHashTraits : public DefaultSHashTraits +{ +public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef typename DefaultSHashTraits::element_t element_t; + typedef typename DefaultSHashTraits::count_t count_t; + + typedef ELEMENT key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e; + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return k1 == k2; + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return (count_t)(size_t)k; + } +}; + +template > > +class SetSHash : public SHash< TRAITS > +{ + typedef SHash PARENT; + +public: + BOOL Contains(ELEMENT key) const + { + return PARENT::LookupPtr(key) != NULL; + } +}; + +template +class PtrSetSHashTraits : public SetSHashTraits +{ + public: + + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef SetSHashTraits PARENT; + typedef typename PARENT::element_t element_t; + typedef typename PARENT::key_t key_t; + typedef typename PARENT::count_t count_t; + + static count_t Hash(key_t k) + { + WRAPPER_NO_CONTRACT; + return (count_t)(size_t)k >> 2; + } +}; + +template +class DeleteElementsOnDestructSHashTraits : public PARENT_TRAITS +{ +public: + static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e) + { + delete e; + } + static const bool s_DestructPerEntryCleanupAction = true; +}; + +#if !defined(CC_JIT) // workaround: Key is redefined in JIT64 + +template +class KeyValuePair { + KEY key; + VALUE value; + +public: + KeyValuePair() + { + } + + KeyValuePair(const KEY& k, const VALUE& v) + : key(k), value(v) + { + } + + KEY const & Key() const + { + LIMITED_METHOD_CONTRACT; + return key; + } + + VALUE const & Value() const + { + LIMITED_METHOD_CONTRACT; + return value; + } +}; + +template +class MapSHashTraits : public DefaultSHashTraits< KeyValuePair > +{ +public: + // explicitly declare local typedefs for these traits types, otherwise + // the compiler may get confused + typedef typename DefaultSHashTraits< KeyValuePair >::element_t element_t; + typedef typename DefaultSHashTraits< KeyValuePair >::count_t count_t; + + typedef KEY key_t; + + static key_t GetKey(element_t e) + { + LIMITED_METHOD_CONTRACT; + return e.Key(); + } + static BOOL Equals(key_t k1, key_t k2) + { + LIMITED_METHOD_CONTRACT; + return k1 == k2; + } + static count_t Hash(key_t k) + { + LIMITED_METHOD_CONTRACT; + return (count_t)(size_t)k; + } + + static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(KEY(),VALUE()); } + static const element_t Deleted() { LIMITED_METHOD_CONTRACT; return element_t(KEY(-1), VALUE()); } + static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.Key() == KEY(); } + static bool IsDeleted(const element_t &e) { return e.Key() == KEY(-1); } +}; + +template > > +class MapSHash : public SHash< TRAITS > +{ + typedef SHash< TRAITS > PARENT; + +public: + void Add(KEY key, VALUE value) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + PRECONDITION(key != (KEY)0); + } + CONTRACTL_END; + + PARENT::Add(KeyValuePair(key, value)); + } + + BOOL Lookup(KEY key, VALUE* pValue) const + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(key != (KEY)0); + } + CONTRACTL_END; + + const KeyValuePair *pRet = PARENT::LookupPtr(key); + if (pRet == NULL) + return FALSE; + + *pValue = pRet->Value(); + return TRUE; + } +}; + +template +class MapSHashWithRemove : public SHash< MapSHashTraits > +{ + typedef SHash< MapSHashTraits > PARENT; + +public: + void Add(KEY key, VALUE value) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + PRECONDITION(key != (KEY)0 && key != (KEY)-1); + } + CONTRACTL_END; + + PARENT::Add(KeyValuePair(key, value)); + } + + BOOL Lookup(KEY key, VALUE* pValue) const + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(key != (KEY)0 && key != (KEY)-1); + } + CONTRACTL_END; + + const KeyValuePair *pRet = PARENT::LookupPtr(key); + if (pRet == NULL) + return FALSE; + + *pValue = pRet->Value(); + return TRUE; + } + + void Remove(KEY key) + { + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + PRECONDITION(key != (KEY)0 && key != (KEY)-1); + } + CONTRACTL_END; + + PARENT::Remove(key); + } +}; + +#endif // CC_JIT + +#include "shash.inl" + +#endif // _SHASH_H_ diff --git a/lib/coreclr/src/inc/shash.inl b/lib/coreclr/src/inc/shash.inl new file mode 100644 index 0000000000..c43e91f0ed --- /dev/null +++ b/lib/coreclr/src/inc/shash.inl @@ -0,0 +1,943 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _SHASH_INL_ +#define _SHASH_INL_ + +// Many SHash functions do not throw on their own, but may propagate an exception +// from Hash, Equals, or GetKey. +#define NOTHROW_UNLESS_TRAITS_THROWS if (TRAITS::s_NoThrow) NOTHROW; else THROWS + +void DECLSPEC_NORETURN ThrowOutOfMemory(); + +template +SHash::SHash() + : m_table(nullptr), + m_tableSize(0), + m_tableCount(0), + m_tableOccupied(0), + m_tableMax(0) +{ + LIMITED_METHOD_CONTRACT; + +#ifndef __GNUC__ // these crash GCC + static_assert_no_msg(SHash::s_growth_factor_numerator > SHash::s_growth_factor_denominator); + static_assert_no_msg(SHash::s_density_factor_numerator < SHash::s_density_factor_denominator); +#endif +} + +template +SHash::~SHash() +{ + LIMITED_METHOD_CONTRACT; + + if (TRAITS::s_DestructPerEntryCleanupAction) + { + for (Iterator i = Begin(); i != End(); i++) + { + TRAITS::OnDestructPerEntryCleanupAction(*i); + } + } + + delete [] m_table; +} + +template +typename SHash::count_t SHash::GetCount() const +{ + LIMITED_METHOD_CONTRACT; + + return m_tableCount; +} + +template +typename SHash::element_t SHash::Lookup(key_t key) const +{ + CONTRACT(element_t) + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + POSTCONDITION(TRAITS::IsNull(RETVAL) || TRAITS::Equals(key, TRAITS::GetKey(RETVAL))); + SUPPORTS_DAC_WRAPPER; + } + CONTRACT_END; + + const element_t *pRet = Lookup(m_table, m_tableSize, key); + RETURN ((pRet != NULL) ? (*pRet) : TRAITS::Null()); +} + +template +const typename SHash::element_t * SHash::LookupPtr(key_t key) const +{ + CONTRACT(const element_t *) + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + POSTCONDITION(RETVAL == NULL || TRAITS::Equals(key, TRAITS::GetKey(*RETVAL))); + } + CONTRACT_END; + + RETURN Lookup(m_table, m_tableSize, key); +} + +template +void SHash::Add(const element_t & element) +{ + CONTRACT_VOID + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); + } + CONTRACT_END; + + CheckGrowth(); + + Add_GrowthChecked(element); + + RETURN; +} + +template +void SHash::Add_GrowthChecked(const element_t & element) +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); + } + CONTRACT_END; + + if (Add(m_table, m_tableSize, element)) + m_tableOccupied++; + m_tableCount++; + + RETURN; +} + +template +void SHash::AddOrReplace(const element_t &element) +{ + CONTRACT_VOID + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + static_assert(!TRAITS::s_supports_remove, "SHash::AddOrReplace is not implemented for SHash with support for remove operations."); + POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); + } + CONTRACT_END; + + CheckGrowth(); + + AddOrReplace(m_table, m_tableSize, element); + + RETURN; +} + +template +void SHash::Remove(key_t key) +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(!(TRAITS::IsNull(Lookup(key)))); + } + CONTRACT_END; + + Remove(m_table, m_tableSize, key); + + RETURN; +} + +template +void SHash::Remove(Iterator& i) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + INSTANCE_CHECK; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(!(TRAITS::IsNull(*i))); + PRECONDITION(!(TRAITS::IsDeleted(*i))); + } + CONTRACT_END; + + RemoveElement(m_table, m_tableSize, (element_t*)&(*i)); + + RETURN; +} + +template +void SHash::Remove(KeyIterator& i) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + INSTANCE_CHECK; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(!(TRAITS::IsNull(*i))); + PRECONDITION(!(TRAITS::IsDeleted(*i))); + } + CONTRACT_END; + + RemoveElement(m_table, m_tableSize, (element_t*)&(*i)); + + RETURN; +} + +template +void SHash::RemovePtr(element_t * p) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + INSTANCE_CHECK; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(!(TRAITS::IsNull(*p))); + PRECONDITION(!(TRAITS::IsDeleted(*p))); + } + CONTRACT_END; + + RemoveElement(m_table, m_tableSize, p); + + RETURN; +} + +template +void SHash::RemoveAll() +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + if (TRAITS::s_DestructPerEntryCleanupAction) + { + for (Iterator i = Begin(); i != End(); i++) + { + TRAITS::OnDestructPerEntryCleanupAction(*i); + } + } + + delete [] m_table; + + m_table = NULL; + m_tableSize = 0; + m_tableCount = 0; + m_tableOccupied = 0; + m_tableMax = 0; + + RETURN; +} + +template +typename SHash::Iterator SHash::Begin() const +{ + LIMITED_METHOD_CONTRACT; + + Iterator i(this, TRUE); + i.First(); + return i; +} + +template +typename SHash::Iterator SHash::End() const +{ + LIMITED_METHOD_CONTRACT; + + return Iterator(this, FALSE); +} + +template +typename SHash::KeyIterator SHash::Begin(key_t key) const +{ + LIMITED_METHOD_CONTRACT; + + KeyIterator k(this, TRUE); + k.SetKey(key); + return k; +} + +template +typename SHash::KeyIterator SHash::End(key_t key) const +{ + LIMITED_METHOD_CONTRACT; + + return KeyIterator(this, FALSE); +} + +template +BOOL SHash::CheckGrowth() +{ + CONTRACT(BOOL) + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + if (m_tableOccupied == m_tableMax) + { + Grow(); + RETURN TRUE; + } + + RETURN FALSE; +} + +template +typename SHash::element_t * +SHash::CheckGrowth_OnlyAllocateNewTable(count_t * pcNewSize) +{ + CONTRACT(element_t *) + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + if (m_tableOccupied == m_tableMax) + { + RETURN Grow_OnlyAllocateNewTable(pcNewSize); + } + + RETURN NULL; +} + +template +void SHash::Grow() +{ + CONTRACT_VOID + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + count_t newSize; + element_t * newTable = Grow_OnlyAllocateNewTable(&newSize); + element_t * oldTable = ReplaceTable(newTable, newSize); + DeleteOldTable(oldTable); + + RETURN; +} + +template +typename SHash::element_t * +SHash::Grow_OnlyAllocateNewTable(count_t * pcNewSize) +{ + CONTRACT(element_t *) + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + count_t newSize = (count_t) (m_tableCount + * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator + * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator); + if (newSize < TRAITS::s_minimum_allocation) + newSize = TRAITS::s_minimum_allocation; + + // handle potential overflow + if (newSize < m_tableCount) + ThrowOutOfMemory(); + + RETURN AllocateNewTable(newSize, pcNewSize); +} + +template +void SHash::Reallocate(count_t requestedSize) +{ + CONTRACT_VOID + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACT_END; + + count_t newTableSize; + element_t * newTable = AllocateNewTable(requestedSize, &newTableSize); + element_t * oldTable = ReplaceTable(newTable, newTableSize); + DeleteOldTable(oldTable); + + RETURN; +} + +template +template +void SHash::ForEach(Functor &functor) +{ + WRAPPER_NO_CONTRACT; // LIMITED_METHOD_CONTRACT + Functor + + for (count_t i = 0; i < m_tableSize; i++) + { + element_t element = m_table[i]; + if (!TRAITS::IsNull(element) && !TRAITS::IsDeleted(element)) + { + functor(element); + } + } +} + +template +typename SHash::element_t * +SHash::AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize) +{ + CONTRACT(element_t *) + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(requestedSize >= + (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); + } + CONTRACT_END; + + // Allocation size must be a prime number. This is necessary so that hashes uniformly + // distribute to all indices, and so that chaining will visit all indices in the hash table. + *pcNewTableSize = NextPrime(requestedSize); + + element_t * newTable = new element_t [*pcNewTableSize]; + + element_t * p = newTable; + element_t * pEnd = newTable + *pcNewTableSize; + while (p < pEnd) + { + *p = TRAITS::Null(); + p++; + } + + RETURN newTable; +} + +template +typename SHash::element_t * +SHash::ReplaceTable(element_t * newTable, count_t newTableSize) +{ + CONTRACT(element_t *) + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(newTableSize >= + (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); + } + CONTRACT_END; + + element_t * oldTable = m_table; + + // Move all entries over to new table. + for (Iterator i = Begin(), end = End(); i != end; i++) + { + const element_t & cur = (*i); + if (!TRAITS::IsNull(cur) && !TRAITS::IsDeleted(cur)) + Add(newTable, newTableSize, cur); + } + + m_table = PTR_element_t(newTable); + m_tableSize = newTableSize; + m_tableMax = (count_t) (newTableSize * TRAITS::s_density_factor_numerator / TRAITS::s_density_factor_denominator); + m_tableOccupied = m_tableCount; + + RETURN oldTable; +} + +template +void +SHash::DeleteOldTable(element_t * oldTable) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + // @todo: + // We might want to try to delay this cleanup to allow asynchronous readers + if (oldTable != NULL) + delete [] oldTable; + + RETURN; +} + +template +const typename SHash::element_t * SHash::Lookup(PTR_element_t table, count_t tableSize, key_t key) +{ + CONTRACT(const element_t *) + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + POSTCONDITION(RETVAL == NULL || TRAITS::Equals(key, TRAITS::GetKey(*RETVAL))); + SUPPORTS_DAC_WRAPPER; // supports DAC only if the traits class does + } + CONTRACT_END; + + if (tableSize == 0) + RETURN NULL; + + count_t hash = TRAITS::Hash(key); + count_t index = hash % tableSize; + count_t increment = 0; // delay computation + + while (TRUE) + { + element_t& current = table[index]; + + if (TRAITS::IsNull(current)) + RETURN NULL; + + if (!TRAITS::IsDeleted(current) + && TRAITS::Equals(key, TRAITS::GetKey(current))) + { + RETURN ¤t; + } + + if (increment == 0) + increment = (hash % (tableSize-1)) + 1; + + index += increment; + if (index >= tableSize) + index -= tableSize; + } +} + +template +BOOL SHash::Add(element_t * table, count_t tableSize, const element_t & element) +{ + CONTRACT(BOOL) + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*Lookup(table, tableSize, TRAITS::GetKey(element))))); + } + CONTRACT_END; + + key_t key = TRAITS::GetKey(element); + + count_t hash = TRAITS::Hash(key); + count_t index = hash % tableSize; + count_t increment = 0; // delay computation + + while (TRUE) + { + element_t & current = table[index]; + + if (TRAITS::IsNull(current)) + { + table[index] = element; + RETURN TRUE; + } + + if (TRAITS::IsDeleted(current)) + { + table[index] = element; + RETURN FALSE; + } + + if (increment == 0) + increment = (hash % (tableSize-1)) + 1; + + index += increment; + if (index >= tableSize) + index -= tableSize; + } +} + +template +void SHash::AddOrReplace(element_t *table, count_t tableSize, const element_t &element) +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + static_assert(!TRAITS::s_supports_remove, "SHash::AddOrReplace is not implemented for SHash with support for remove operations."); + POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*Lookup(table, tableSize, TRAITS::GetKey(element))))); + } + CONTRACT_END; + + key_t key = TRAITS::GetKey(element); + + count_t hash = TRAITS::Hash(key); + count_t index = hash % tableSize; + count_t increment = 0; // delay computation + + while (TRUE) + { + element_t& current = table[index]; + _ASSERTE(!TRAITS::IsDeleted(current)); + + if (TRAITS::IsNull(current)) + { + table[index] = element; + m_tableCount++; + m_tableOccupied++; + RETURN; + } + else if (TRAITS::Equals(key, TRAITS::GetKey(current))) + { + table[index] = element; + RETURN; + } + + if (increment == 0) + increment = (hash % (tableSize-1)) + 1; + + index += increment; + if (index >= tableSize) + index -= tableSize; + } +} + +template +void SHash::Remove(element_t *table, count_t tableSize, key_t key) +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(Lookup(table, tableSize, key) != NULL); + } + CONTRACT_END; + + count_t hash = TRAITS::Hash(key); + count_t index = hash % tableSize; + count_t increment = 0; // delay computation + + while (TRUE) + { + element_t& current = table[index]; + + if (TRAITS::IsNull(current)) + RETURN; + + if (!TRAITS::IsDeleted(current) + && TRAITS::Equals(key, TRAITS::GetKey(current))) + { + table[index] = TRAITS::Deleted(); + m_tableCount--; + RETURN; + } + + if (increment == 0) + increment = (hash % (tableSize-1)) + 1; + + index += increment; + if (index >= tableSize) + index -= tableSize; + } +} + +template +void SHash::RemoveElement(element_t *table, count_t tableSize, element_t *element) +{ + CONTRACT_VOID + { + NOTHROW; + GC_NOTRIGGER; + static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); + PRECONDITION(table <= element && element < table + tableSize); + PRECONDITION(!TRAITS::IsNull(*element) && !TRAITS::IsDeleted(*element)); + } + CONTRACT_END; + + *element = TRAITS::Deleted(); + m_tableCount--; + RETURN; +} + +template +BOOL SHash::IsPrime(COUNT_T number) +{ + CONTRACT(BOOL) + { + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + // This is a very low-tech check for primality, which doesn't scale very well. + // There are more efficient tests if this proves to be burdensome for larger + // tables. + + if ((number & 1) == 0) + RETURN FALSE; + + COUNT_T factor = 3; + while (factor * factor <= number) + { + if ((number % factor) == 0) + RETURN FALSE; + factor += 2; + } + + RETURN TRUE; +} + +// allow coexistence with simplerhash.inl +#ifndef _HASH_PRIMES_DEFINED +#define _HASH_PRIMES_DEFINED + +namespace +{ + const COUNT_T g_shash_primes[] = { + 11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919, + 1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591, + 17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363, + 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, + 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, + 4999559, 5999471, 7199369 }; +} + +#endif //_HASH_PRIMES_DEFINED + +template +COUNT_T SHash::NextPrime(COUNT_T number) +{ + CONTRACT(COUNT_T) + { + NOTHROW; + GC_NOTRIGGER; + POSTCONDITION(IsPrime(RETVAL)); + } + CONTRACT_END; + + for (int i = 0; i < (int) (sizeof(g_shash_primes) / sizeof(g_shash_primes[0])); i++) { + if (g_shash_primes[i] >= number) + RETURN g_shash_primes[i]; + } + + if ((number&1) == 0) + number++; + + while (number != 1) { + if (IsPrime(number)) + RETURN number; + number +=2; + } + + // overflow + ThrowOutOfMemory(); +} + +template +SHash::AddPhases::AddPhases() +{ + LIMITED_METHOD_CONTRACT; + + m_pHash = NULL; + m_newTable = NULL; + m_newTableSize = 0; + m_oldTable = NULL; + + INDEBUG(dbg_m_fAddCalled = FALSE;) +} + +template +SHash::AddPhases::~AddPhases() +{ + LIMITED_METHOD_CONTRACT; + + if (m_newTable != NULL) + { // The new table was not applied to the hash yet + _ASSERTE((m_pHash != NULL) && (m_newTableSize != 0) && (m_oldTable == NULL)); + + delete [] m_newTable; + } + DeleteOldTable(); +} + +template +void SHash::AddPhases::PreallocateForAdd(SHash * pHash) +{ + CONTRACT_VOID + { + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + _ASSERTE((m_pHash == NULL) && (m_newTable == NULL) && (m_newTableSize == 0) && (m_oldTable == NULL)); + + m_pHash = pHash; + // May return NULL if the allocation was not needed + m_newTable = m_pHash->CheckGrowth_OnlyAllocateNewTable(&m_newTableSize); + +#ifdef _DEBUG + dbg_m_table = pHash->m_table; + dbg_m_tableSize = pHash->m_tableSize; + dbg_m_tableCount = pHash->m_tableCount; + dbg_m_tableOccupied = pHash->m_tableOccupied; + dbg_m_tableMax = pHash->m_tableMax; +#endif //_DEBUG + + RETURN; +} + +template +void SHash::AddPhases::Add(const element_t & element) +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + _ASSERTE((m_pHash != NULL) && (m_oldTable == NULL)); + // Add can be called only once on this object + _ASSERTE(!dbg_m_fAddCalled); + + // Check that the hash table didn't change since call to code:PreallocateForAdd + _ASSERTE(dbg_m_table == m_pHash->m_table); + _ASSERTE(dbg_m_tableSize == m_pHash->m_tableSize); + _ASSERTE(dbg_m_tableCount >= m_pHash->m_tableCount); // Remove operation might have removed elements + _ASSERTE(dbg_m_tableOccupied == m_pHash->m_tableOccupied); + _ASSERTE(dbg_m_tableMax == m_pHash->m_tableMax); + + if (m_newTable != NULL) + { // We have pre-allocated table from code:PreallocateForAdd, use it. + _ASSERTE(m_newTableSize != 0); + + // May return NULL if there was not table allocated yet + m_oldTable = m_pHash->ReplaceTable(m_newTable, m_newTableSize); + + m_newTable = NULL; + m_newTableSize = 0; + } + // We know that we have enough space, direcly add the element + m_pHash->Add_GrowthChecked(element); + + INDEBUG(dbg_m_fAddCalled = TRUE;) + + RETURN; +} + +template +void SHash::AddPhases::AddNothing_PublishPreallocatedTable() +{ + CONTRACT_VOID + { + NOTHROW_UNLESS_TRAITS_THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + _ASSERTE((m_pHash != NULL) && (m_oldTable == NULL)); + // Add can be called only once on this object + _ASSERTE(!dbg_m_fAddCalled); + + // Check that the hash table didn't change since call to code:PreallocateForAdd + _ASSERTE(dbg_m_table == m_pHash->m_table); + _ASSERTE(dbg_m_tableSize == m_pHash->m_tableSize); + _ASSERTE(dbg_m_tableCount >= m_pHash->m_tableCount); // Remove operation might have removed elements + _ASSERTE(dbg_m_tableOccupied == m_pHash->m_tableOccupied); + _ASSERTE(dbg_m_tableMax == m_pHash->m_tableMax); + + if (m_newTable != NULL) + { // We have pre-allocated table from code:PreallocateForAdd, use it. + _ASSERTE(m_newTableSize != 0); + + // May return NULL if there was not table allocated yet + m_oldTable = m_pHash->ReplaceTable(m_newTable, m_newTableSize); + + m_newTable = NULL; + m_newTableSize = 0; + } + + INDEBUG(dbg_m_fAddCalled = TRUE;) + + RETURN; +} + +template +void SHash::AddPhases::DeleteOldTable() +{ + LIMITED_METHOD_CONTRACT; + + if (m_oldTable != NULL) + { + _ASSERTE((m_pHash != NULL) && (m_newTable == NULL) && (m_newTableSize == 0)); + + delete [] m_oldTable; + m_oldTable = NULL; + } +} + +template +template +bool SHash::CheckAddInPhases( + element_t const & elem, + LockT & lock, + AddLockT & addLock, + IUnknown * addRefObject) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + INSTANCE_CHECK; + } + CONTRACTL_END; + + AddLockHolderT hAddLock(&addLock); + AddPhases addCall; + + // 1. Preallocate one element + addCall.PreallocateForAdd(this); + { + // 2. Take the reader lock. Host callouts now forbidden. + LockHolderT hLock(&lock); + + element_t const * pEntry = LookupPtr(TRAITS::GetKey(elem)); + if (pEntry != nullptr) + { + // 3a. Use the newly allocated table (if any) to avoid later redundant allocation. + addCall.AddNothing_PublishPreallocatedTable(); + return false; + } + else + { + // 3b. Add the element to the hash table. + addCall.Add(elem); + + if (addRefObject != nullptr) + { + clr::SafeAddRef(addRefObject); + } + + return true; + } + } + + // 4. addCall's destructor will take care of any required cleanup. +} + + +#endif // _SHASH_INL_ diff --git a/lib/coreclr/src/inc/shim/locationinfo.h b/lib/coreclr/src/inc/shim/locationinfo.h new file mode 100644 index 0000000000..d6a1b6d0b4 --- /dev/null +++ b/lib/coreclr/src/inc/shim/locationinfo.h @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// locationinfo.h +// +// Enum describing different types of locations for coreCLR +// +// Note: must be platform independent +// +// ====================================================================================== + + +#ifndef LOCATIONINFO_H +#define LOCATIONINFO_H + + +// in order of preference, smaller is better +enum LocationInfo +{ + Loc_System=1, + Loc_Machine=2, + Loc_User=3, + Loc_Network=4, + Loc_Undefined =0xffff +}; + +// Returns the more preferred of two locations +// +// Assumptions: LocationInfo is defined in a manner that a smaller value is better +// +// Input: +// locations to compare +// +// Output: +// the preferred location +inline LocationInfo BetterLocation(LocationInfo l1, LocationInfo l2) +{ + return l1 version.Major()) + return 1; + if (Major() < version.Major()) + return -1; + if (Minor() > version.Minor()) + return 1; + if (Minor() < version.Minor()) + return -1; + if (Build() > version.Build()) + return 1; + if (Build() < version.Build()) + return -1; + if (Revision() > version.Revision()) + return 1; + if (Revision() < version.Revision()) + return -1; + return 0; +} + + +// Parses the given string into VersionInfo +// +// Input: +// szString - the string to parse, "x.x.x.x" +// +// Output: +// return value: count of fields parsed (<=4) or -1 if an error +inline int VersionInfo::Parse(LPCTSTR szString, VersionInfo* result) +{ + // sscanf is nice but we need an exact format match and no 0s + size_t iLen = _tcslen(szString); + + unsigned short wVersion[4] = {0}; + int iVerIdx = 0; + unsigned int dwCurrentValue = 0; + bool bFirstChar = true; + + for (size_t i=0; i<= iLen; i++) + { + if(szString[i] == _T('\0')) + { + if(!bFirstChar) + wVersion[iVerIdx++] = (unsigned short)(dwCurrentValue & 0xffff); + break; + } + else + if (szString[i] == _T('.') ) + { + if(bFirstChar) + return -1; + + // fill in + wVersion[iVerIdx++] = (unsigned short)(dwCurrentValue & 0xffff); + + //check for extra characters + if (iVerIdx > sizeof(wVersion)/sizeof(wVersion[0])) + { + if (szString[i+1] == _T('\0')) + break; + else + return -1; + } + + //reset + dwCurrentValue=0; + bFirstChar=true; + continue; + } + else + if (szString[i] < _T('0')) + { + return -1; + } + else + if (szString[i] > _T('9')) + { + return -1; + } + else + if (szString[i] == _T('0') && bFirstChar && szString[i+1]!= _T('.') && szString[i+1]!= _T('\0') ) + { + return -1; + } + + // the character is a digit + dwCurrentValue=dwCurrentValue*10+szString[i]-_T('0'); + if(dwCurrentValue > 0xffff) + return -1; + + bFirstChar=false; + + } + + //successfully parsed + *result = VersionInfo(wVersion[0], wVersion[1], wVersion[2], wVersion[3]); + return iVerIdx; + +} + diff --git a/lib/coreclr/src/inc/shimload.h b/lib/coreclr/src/inc/shimload.h new file mode 100644 index 0000000000..a2651d1aff --- /dev/null +++ b/lib/coreclr/src/inc/shimload.h @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*============================================================ +** +** Header: ShimLoad.hpp +** +** Purpose: Delay load hook used to images to bind to +** dll's shim shipped with the EE +** +** +===========================================================*/ +#ifndef _SHIMLOAD_H +#define _SHIMLOAD_H + + +//***************************************************************************** +// Sets/Gets the directory based on the location of the module. This routine +// is called at COR setup time. Set is called during EEStartup and by the +// MetaData dispenser. +//***************************************************************************** +HRESULT SetInternalSystemDirectory(); +HRESULT GetInternalSystemDirectory(__out_ecount_opt(*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength); + +#endif + diff --git a/lib/coreclr/src/inc/sigbuilder.h b/lib/coreclr/src/inc/sigbuilder.h new file mode 100644 index 0000000000..6d7cbf27ba --- /dev/null +++ b/lib/coreclr/src/inc/sigbuilder.h @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#ifndef _SIGBUILDER_H_ +#define _SIGBUILDER_H_ + +#include "contract.h" + +// +// Simple signature builder +// + +class SigBuilder +{ + PBYTE m_pBuffer; + DWORD m_dwLength; + DWORD m_dwAllocation; + + // Preallocate space for small signatures + BYTE m_prealloc[64]; + + // Grow the buffer to get at least cbMin of free space + void Grow(SIZE_T cbMin); + + // Ensure that the buffer has at least cbMin of free space + FORCEINLINE void Ensure(SIZE_T cb) + { + if (m_dwAllocation - m_dwLength < cb) + Grow(cb); + } + +public: + SigBuilder() + : m_pBuffer(m_prealloc), m_dwLength(0), m_dwAllocation(sizeof(m_prealloc)) + { + LIMITED_METHOD_CONTRACT; + } + + ~SigBuilder(); + + SigBuilder(DWORD cbPreallocationSize); + + PVOID GetSignature(DWORD * pdwLength) + { + LIMITED_METHOD_CONTRACT; + *pdwLength = m_dwLength; + return m_pBuffer; + } + + DWORD GetSignatureLength() + { + LIMITED_METHOD_CONTRACT; + return m_dwLength; + } + + void AppendByte(BYTE b); + + void AppendData(ULONG data); + + void AppendElementType(CorElementType etype) + { + WRAPPER_NO_CONTRACT; + AppendByte(static_cast(etype)); + } + + void AppendToken(mdToken tk); + + void AppendPointer(void * ptr) + { + WRAPPER_NO_CONTRACT; + AppendBlob(&ptr, sizeof(ptr)); + } + + void AppendBlob(const PVOID pBlob, SIZE_T cbBlob); +}; + +#endif // _SIGBUILDER_H_ diff --git a/lib/coreclr/src/inc/sigparser.h b/lib/coreclr/src/inc/sigparser.h new file mode 100644 index 0000000000..2c8cf8b165 --- /dev/null +++ b/lib/coreclr/src/inc/sigparser.h @@ -0,0 +1,985 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// sigparser.h +// + +// + +#ifndef _H_SIGPARSER +#define _H_SIGPARSER + +#include "utilcode.h" +#include "corhdr.h" +#include "corinfo.h" +#include "corpriv.h" + +//--------------------------------------------------------------------------------------- +// These macros define how arguments are mapped to the stack in the managed calling convention. +// We assume to be walking a method's signature left-to-right, in the virtual calling convention. +// See MethodDesc::Call for details on this virtual calling convention. +// These macros tell us whether the arguments we see as we proceed with the signature walk are mapped +// to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack. +//--------------------------------------------------------------------------------------- +#if defined(_TARGET_X86_) +#define STACK_GROWS_DOWN_ON_ARGS_WALK +#else +#define STACK_GROWS_UP_ON_ARGS_WALK +#endif + + +//------------------------------------------------------------------------ +// Encapsulates how compressed integers and typeref tokens are encoded into +// a bytestream. +// +// As you use this class please understand the implicit normalizations +// on the CorElementType's returned by the various methods, especially +// for variable types (e.g. !0 in generic signatures), string types +// (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types +// (e.g. List) and enums. +//------------------------------------------------------------------------ +class SigParser +{ + protected: + // This type is performance critical - do not add fields to it. + // (If you must, check for managed types that may use a SigParser or SigPointer inline, like ArgIterator.) + PCCOR_SIGNATURE m_ptr; + DWORD m_dwLen; + + //------------------------------------------------------------------------ + // Skips specified number of bytes WITHOUT VALIDATION. Only to be used + // when it is known that it won't overflow the signature buffer. + //------------------------------------------------------------------------ + FORCEINLINE void SkipBytes(ULONG cb) + { + SUPPORTS_DAC; + _ASSERT(cb <= m_dwLen); + m_ptr += cb; + m_dwLen -= cb; + } + + public: + //------------------------------------------------------------------------ + // Constructor. + //------------------------------------------------------------------------ + SigParser() { + LIMITED_METHOD_DAC_CONTRACT; + m_ptr = NULL; + m_dwLen = 0; + } + + SigParser(const SigParser &sig); + + //------------------------------------------------------------------------ + // Initialize + //------------------------------------------------------------------------ + FORCEINLINE SigParser(PCCOR_SIGNATURE ptr) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + // We don't know the size of the signature, so we'll say it's "big enough" + m_dwLen = 0xffffffff; + } + + FORCEINLINE SigParser(PCCOR_SIGNATURE ptr, DWORD len) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + m_dwLen = len; + } + + inline void SetSig(PCCOR_SIGNATURE ptr) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + // We don't know the size of the signature, so we'll say it's "big enough" + m_dwLen = 0xffffffff; + } + + inline void SetSig(PCCOR_SIGNATURE ptr, DWORD len) + { + LIMITED_METHOD_CONTRACT; + + m_ptr = ptr; + m_dwLen = len; + } + + + inline BOOL IsNull() const + { + LIMITED_METHOD_CONTRACT; + + return (m_ptr == NULL); + } + + // Returns represented signature as pointer and size. + void + GetSignature( + PCCOR_SIGNATURE * pSig, + DWORD * pcbSigSize) + { + *pSig = m_ptr; + *pcbSigSize = m_dwLen; + } + + + //========================================================================= + // The RAW interface for reading signatures. You see exactly the signature, + // apart from custom modifiers which for historical reasons tend to get eaten. + // + // DO NOT USE THESE METHODS UNLESS YOU'RE TOTALLY SURE YOU WANT + // THE RAW signature. You nearly always want GetElemTypeClosed() or + // PeekElemTypeClosed() or one of the MetaSig functions. See the notes above. + // These functions will return E_T_INTERNAL, E_T_VAR, E_T_MVAR and such + // so the caller must be able to deal with those + //========================================================================= + + //------------------------------------------------------------------------ + // Remove one compressed integer (using CorSigUncompressData) from + // the head of the stream and return it. + //------------------------------------------------------------------------ + __checkReturn + FORCEINLINE HRESULT GetData(ULONG* data) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + ULONG sizeOfData = 0; + ULONG tempData; + + if (data == NULL) + data = &tempData; + + HRESULT hr = CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); + + if (SUCCEEDED(hr)) + { + SkipBytes(sizeOfData); + } + + return hr; + } + + + //------------------------------------------------------------------------- + // Remove one byte and return it. + //------------------------------------------------------------------------- + __checkReturn + FORCEINLINE HRESULT GetByte(BYTE *data) + { + LIMITED_METHOD_CONTRACT; + + if (m_dwLen > 0) + { + if (data != NULL) + *data = *m_ptr; + + SkipBytes(1); + + return S_OK; + } + + if (data != NULL) + *data = 0; + return META_E_BAD_SIGNATURE; + } + + //------------------------------------------------------------------------- + // Peek at value of one byte and return it. + //------------------------------------------------------------------------- + __checkReturn + FORCEINLINE HRESULT PeekByte(BYTE *data) + { + LIMITED_METHOD_CONTRACT; + + if (m_dwLen > 0) + { + if (data != NULL) + *data = *m_ptr; + + return S_OK; + } + + if (data != NULL) + *data = 0; + return META_E_BAD_SIGNATURE; + } + + //------------------------------------------------------------------------- + // The element type as defined in CorElementType. No normalization for + // generics (E_T_VAR, E_T_MVAR,..) or dynamic methods (E_T_INTERNAL occurs) + //------------------------------------------------------------------------- + __checkReturn + HRESULT GetElemTypeSlow(CorElementType * etype) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + CorElementType tmpEType; + + if (etype == NULL) + etype = &tmpEType; + + SigParser sigTemp(*this); + + HRESULT hr = sigTemp.SkipCustomModifiers(); + + if (SUCCEEDED(hr)) + { + BYTE bElemType = 0; + hr = sigTemp.GetByte(&bElemType); + *etype = (CorElementType)bElemType; + + if (SUCCEEDED(hr)) + { + *this = sigTemp; + return S_OK; + } + } + + *etype = ELEMENT_TYPE_END; + + return META_E_BAD_SIGNATURE; + } + + // Inlined version + __checkReturn + FORCEINLINE HRESULT GetElemType(CorElementType * etype) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (m_dwLen > 0) + { + CorElementType typ = (CorElementType) * m_ptr; + + if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte + { + if (etype != NULL) + { + * etype = typ; + } + + SkipBytes(1); + + return S_OK; + } + } + + // Slower/normal path + return GetElemTypeSlow(etype); + } + + // Note: Calling convention is always one byte, not four bytes + __checkReturn + HRESULT GetCallingConvInfo(ULONG * data) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + ULONG tmpData; + + if (data == NULL) + data = &tmpData; + + HRESULT hr = CorSigUncompressCallingConv(m_ptr, m_dwLen, data); + if (SUCCEEDED(hr)) + { + SkipBytes(1); + } + + return hr; + } + + __checkReturn + HRESULT GetCallingConv(ULONG* data) // @REVISIT_TODO: Calling convention is one byte, not four. + { + WRAPPER_NO_CONTRACT; + ULONG info; + HRESULT hr = GetCallingConvInfo(&info); + + if (SUCCEEDED(hr) && data != NULL) + { + *data = IMAGE_CEE_CS_CALLCONV_MASK & info; + } + + return hr; + } + + //------------------------------------------------------------------------ + // Non-destructive read of compressed integer. + //------------------------------------------------------------------------ + __checkReturn + HRESULT PeekData(ULONG *data) const + { + WRAPPER_NO_CONTRACT; + _ASSERTE(data != NULL); + + ULONG sizeOfData = 0; + return CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); + } + + + //------------------------------------------------------------------------ + // Non-destructive read of element type. + // + // This routine makes it look as if the String type is encoded + // via ELEMENT_TYPE_CLASS followed by a token for the String class, + // rather than the ELEMENT_TYPE_STRING. This is partially to avoid + // rewriting client code which depended on this behavior previously. + // But it also seems like the right thing to do generally. + // No normalization for generics (E_T_VAR, E_T_MVAR,..) or + // dynamic methods (E_T_INTERNAL occurs) + //------------------------------------------------------------------------ + __checkReturn + HRESULT PeekElemTypeSlow(CorElementType *etype) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(etype != NULL); + + SigParser sigTemp(*this); + HRESULT hr = sigTemp.GetElemType(etype); + if (SUCCEEDED(hr) && (*etype == ELEMENT_TYPE_STRING || *etype == ELEMENT_TYPE_OBJECT)) + *etype = ELEMENT_TYPE_CLASS; + + return hr; + } + + // inline version + __checkReturn + FORCEINLINE HRESULT PeekElemType(CorElementType *etype) const + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + _ASSERTE(etype != NULL); + + if (m_dwLen > 0) + { + CorElementType typ = (CorElementType) * m_ptr; + + if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte + { + if ((typ == ELEMENT_TYPE_STRING) || (typ == ELEMENT_TYPE_OBJECT)) + { + *etype = ELEMENT_TYPE_CLASS; + } + else + { + *etype = typ; + } + + return S_OK; + } + } + + return PeekElemTypeSlow(etype); + } + + //------------------------------------------------------------------------- + // Returns the raw size of the type next in the signature, or returns + // E_INVALIDARG for base types that have variables sizes. + //------------------------------------------------------------------------- + __checkReturn + HRESULT PeekElemTypeSize(ULONG *pSize) + { + WRAPPER_NO_CONTRACT; + HRESULT hr = S_OK; + + DWORD dwSize = 0; + + if (pSize == NULL) + { + pSize = &dwSize; + } + + SigParser sigTemp(*this); + + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + *pSize = 0; + + BYTE bElementType = 0; + hr = sigTemp.GetByte(&bElementType); + + if (FAILED(hr)) + { + return hr; + } + + switch (bElementType) + { + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R8: + #ifdef _WIN64 + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + #endif // WIN64 + + *pSize = 8; + break; + + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_R4: + #ifndef _WIN64 + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + #endif // _WIN64 + + *pSize = 4; + break; + + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_CHAR: + *pSize = 2; + break; + + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_BOOLEAN: + *pSize = 1; + break; + + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_BYREF: + case ELEMENT_TYPE_CLASS: + case ELEMENT_TYPE_OBJECT: + case ELEMENT_TYPE_FNPTR: + case ELEMENT_TYPE_TYPEDBYREF: + case ELEMENT_TYPE_ARRAY: + case ELEMENT_TYPE_SZARRAY: + *pSize = sizeof(void *); + break; + + case ELEMENT_TYPE_VOID: + break; + + case ELEMENT_TYPE_END: + case ELEMENT_TYPE_CMOD_REQD: + case ELEMENT_TYPE_CMOD_OPT: + _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); + return E_INVALIDARG; + + case ELEMENT_TYPE_VALUETYPE: + _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); + return E_INVALIDARG; + + default: + + _ASSERTE( !"CorSigGetElementTypeSize given invalid signature to size!" ); + return META_E_BAD_SIGNATURE; + } + + return hr; + } + + //------------------------------------------------------------------------ + // Is this at the Sentinal (the ... in a varargs signature) that marks + // the begining of varguments that are not decared at the target + + bool AtSentinel() const + { + if (m_dwLen > 0) + return *m_ptr == ELEMENT_TYPE_SENTINEL; + else + return false; + } + + //------------------------------------------------------------------------ + // Removes a compressed metadata token and returns it. + // WARNING: dynamic methods do not have tokens so this api is completely + // broken in that case. Make sure you call this function if + // you are absolutely sure E_T_INTERNAL was not in the sig + //------------------------------------------------------------------------ + __checkReturn + FORCEINLINE + HRESULT GetToken(mdToken * token) + { + WRAPPER_NO_CONTRACT; + DWORD dwLen; + mdToken tempToken; + + if (token == NULL) + token = &tempToken; + + HRESULT hr = CorSigUncompressToken(m_ptr, m_dwLen, token, &dwLen); + + if (SUCCEEDED(hr)) + { + SkipBytes(dwLen); + } + + return hr; + } + + //------------------------------------------------------------------------ + // Removes a pointer value and returns it. Used for ELEMENT_TYPE_INTERNAL. + __checkReturn + FORCEINLINE + HRESULT GetPointer(void ** pPtr) + { + WRAPPER_NO_CONTRACT; + + if (m_dwLen < sizeof(void *)) + { // Not enough data to read a pointer + if (pPtr != NULL) + { + *pPtr = NULL; + } + return META_E_BAD_SIGNATURE; + } + if (pPtr != NULL) + { + *pPtr = *(void * UNALIGNED *)m_ptr; + } + SkipBytes(sizeof(void *)); + + return S_OK; + } + + //------------------------------------------------------------------------ + // Tests if two SigParsers point to the same location in the stream. + //------------------------------------------------------------------------ + FORCEINLINE BOOL Equals(SigParser sp) const + { + LIMITED_METHOD_CONTRACT; + + return m_ptr == sp.m_ptr; + } + + __checkReturn + HRESULT SkipCustomModifiers() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + HRESULT hr = S_OK; + + SigParser sigTemp(*this); + + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + BYTE bElementType = 0; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + while ((ELEMENT_TYPE_CMOD_REQD == bElementType) || + (ELEMENT_TYPE_CMOD_OPT == bElementType)) + { + sigTemp.SkipBytes(1); + + mdToken token; + + hr = sigTemp.GetToken(&token); + + if (FAILED(hr)) + return hr; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + } + + // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types + // that we support while parsing various signatures + if (bElementType >= ELEMENT_TYPE_MAX) + { + switch (bElementType) + { + case ELEMENT_TYPE_VAR_ZAPSIG: + case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: + case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: + case ELEMENT_TYPE_CANON_ZAPSIG: + case ELEMENT_TYPE_MODULE_ZAPSIG: + case ELEMENT_TYPE_PINNED: + break; + default: + return META_E_BAD_SIGNATURE; + } + } + + *this = sigTemp; + return hr; + }// SkipCustomModifiers + + __checkReturn + HRESULT SkipFunkyAndCustomModifiers() + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + SigParser sigTemp(*this); + HRESULT hr = S_OK; + hr = sigTemp.SkipAnyVASentinel(); + + if (FAILED(hr)) + { + return hr; + } + + BYTE bElementType = 0; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + while (ELEMENT_TYPE_CMOD_REQD == bElementType || + ELEMENT_TYPE_CMOD_OPT == bElementType || + ELEMENT_TYPE_MODIFIER == bElementType || + ELEMENT_TYPE_PINNED == bElementType) + { + sigTemp.SkipBytes(1); + + mdToken token; + + hr = sigTemp.GetToken(&token); + + if (FAILED(hr)) + return hr; + + hr = sigTemp.PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + } + + // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types + // that we support while parsing various signatures + if (bElementType >= ELEMENT_TYPE_MAX) + { + switch (bElementType) + { + case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: + case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: + case ELEMENT_TYPE_CANON_ZAPSIG: + case ELEMENT_TYPE_MODULE_ZAPSIG: + case ELEMENT_TYPE_PINNED: + break; + default: + return META_E_BAD_SIGNATURE; + } + } + + *this = sigTemp; + return hr; + }// SkipFunkyAndCustomModifiers + + + __checkReturn + HRESULT SkipAnyVASentinel() + { + WRAPPER_NO_CONTRACT; + + HRESULT hr = S_OK; + BYTE bElementType = 0; + + hr = PeekByte(&bElementType); + if (FAILED(hr)) + return hr; + + if (bElementType == ELEMENT_TYPE_SENTINEL) + { + SkipBytes(1); + } + + return hr; + }// SkipAnyVASentinel + + //------------------------------------------------------------------------ + // Assumes that the SigParser points to the start of an element type + // (i.e. function parameter, function return type or field type.) + // Advances the pointer to the first data after the element type. + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipExactlyOne(); + + //------------------------------------------------------------------------ + // Skip only the method header of the signature, not the signature of + // the arguments. + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipMethodHeaderSignature(ULONG *pcArgs); + + //------------------------------------------------------------------------ + // Skip a sub signature (as immediately follows an ELEMENT_TYPE_FNPTR). + //------------------------------------------------------------------------ + __checkReturn + HRESULT SkipSignature(); + +public: + + //------------------------------------------------------------------------ + // Return pointer + // PLEASE DON'T USE THIS. + // + // Return the internal pointer. It's hard to resist, but please try + // not to use this. Certainly don't use it if there's any chance of the + // signature containing generic type variables. + // + // It's currently only used for working on the + // signatures stored in TypeSpec tokens (we should add a new abstraction, + // i.e. on MetaSig for this) and a couple of places to do with COM + // and native interop signature parsing. + // We should try to get rid of these uses as well. + //------------------------------------------------------------------------ + PCCOR_SIGNATURE GetPtr() const + { + LIMITED_METHOD_DAC_CONTRACT; + return m_ptr; + } + +}; // class SigParser + +//------------------------------------------------------------------------ +FORCEINLINE +SigParser::SigParser( + const SigParser &sig) + : m_ptr(sig.m_ptr), m_dwLen(sig.m_dwLen) +{ + LIMITED_METHOD_DAC_CONTRACT; +} + +/*****************************************************************/ +/* CorTypeInfo is a single global table that you can hang information + about ELEMENT_TYPE_* */ + +class CorTypeInfo +{ +protected: + struct CorTypeInfoEntry + { + LPCUTF8 nameSpace; + LPCUTF8 className; + CorElementType type : 8; + unsigned size : 8; + CorInfoGCType gcType : 3; + unsigned isArray : 1; + unsigned isPrim : 1; + unsigned isFloat : 1; + unsigned isModifier : 1; + unsigned isGenVar : 1; + // 1 more byte here to use for 32-bit + }; + +protected: + FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo(CorElementType type) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; +#ifdef MODE_ANY + MODE_ANY; +#endif + } + CONTRACTL_END; + + if (type >= (CorElementType)_countof(info)) + { + ThrowHR(COR_E_BADIMAGEFORMAT); + } + return info[type]; + } + FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo_NoThrow(CorElementType type) + { + LIMITED_METHOD_DAC_CONTRACT; + + if (type >= (CorElementType)_countof(info)) + { + return info[ELEMENT_TYPE_END]; + } + return info[type]; + } + +public: + + FORCEINLINE static LPCUTF8 GetName(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).className; + } + + FORCEINLINE static LPCUTF8 GetNamespace(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).nameSpace; + } + + static void CheckConsistency() + { + LIMITED_METHOD_CONTRACT; + + for (int i = 0; i < (int)_countof(info); i++) + { + _ASSERTE(info[i].type == i); + } + } + + FORCEINLINE static CorInfoGCType GetGCType(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).gcType; + } + FORCEINLINE static CorInfoGCType GetGCType_NoThrow(CorElementType type) + { + LIMITED_METHOD_DAC_CONTRACT; + + return GetTypeInfo_NoThrow(type).gcType; + } + + static BOOL IsObjRef(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType(type) == TYPE_GC_REF); + } + static BOOL IsObjRef_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return (GetGCType_NoThrow(type) == TYPE_GC_REF); + } + + FORCEINLINE static BOOL IsGenericVariable(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isGenVar; + } + FORCEINLINE static BOOL IsGenericVariable_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isGenVar; + } + + FORCEINLINE static BOOL IsArray(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isArray; + } + FORCEINLINE static BOOL IsArray_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isArray; + } + + FORCEINLINE static BOOL IsFloat(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isFloat; + } + FORCEINLINE static BOOL IsFloat_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isFloat; + } + + FORCEINLINE static BOOL IsModifier(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isModifier; + } + FORCEINLINE static BOOL IsModifier_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isModifier; + } + + FORCEINLINE static BOOL IsPrimitiveType(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).isPrim; + } + FORCEINLINE static BOOL IsPrimitiveType_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).isPrim; + } + + FORCEINLINE static unsigned Size(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo(type).size; + } + FORCEINLINE static unsigned Size_NoThrow(CorElementType type) + { + WRAPPER_NO_CONTRACT; + + return GetTypeInfo_NoThrow(type).size; + } + + static CorElementType FindPrimitiveType(LPCUTF8 name); + +protected: + static const CorTypeInfoEntry info[ELEMENT_TYPE_MAX]; + +}; // class CorTypeInfo + + +// Returns the address of the payload inside the stackelem +inline void* StackElemEndianessFixup(void* pStackElem, UINT cbSize) { + LIMITED_METHOD_CONTRACT; + + BYTE *pRetVal = (BYTE*)pStackElem; + +#if BIGENDIAN + switch (cbSize) + { + case 1: + pRetVal += sizeof(void*)-1; + break; + case 2: + pRetVal += sizeof(void*)-2; + break; +#ifdef _WIN64 + case 4: + pRetVal += sizeof(void*)-4; + break; +#endif + default: + // nothing to do + break; + } +#endif + + return pRetVal; +} + +#endif /* _H_SIGINFOBASE */ diff --git a/lib/coreclr/src/inc/simplerhash.h b/lib/coreclr/src/inc/simplerhash.h new file mode 100644 index 0000000000..eb0f80d013 --- /dev/null +++ b/lib/coreclr/src/inc/simplerhash.h @@ -0,0 +1,423 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _SIMPLERHASHTABLE_H_ +#define _SIMPLERHASHTABLE_H_ + +#include "iallocator.h" + +// SimplerHashTable implements a mapping from a Key type to a Value type, +// via a hash table. + +// Synchronization is the responsibility of the caller: if a +// SimplerHash is used in a multithreaded context, the table should be +// associated with a lock. + +// SimplerHashTable actually takes four template arguments: Key, +// KeyFuncs, Value, and Behavior. We don't assume that Key has hash or equality +// functions specific names; rather, we assume that KeyFuncs has +// statics methods +// int GetHashCode(Key) +// and +// bool Equals(Key, Key) +// and use those. An +// instantiator can thus make a small "adaptor class" to invoke +// existing instance method hash and/or equality functions. If the +// implementor of a candidate Key class K understands this convention, +// these static methods can be implemented by K, so that K can be used +// as the actual arguments for the both Key and KeyTrait classes. +// +// The "Behavior" argument provides the following static members: +// +// s_growth_factor_numerator +// s_growth_factor_denominator Factor to grow allocation (numerator/denominator). +// Typically inherited from default traits (3/2) +// +// s_density_factor_numerator +// s_density_factor_denominator Maxium occupied density of table before growth +// occurs (num/denom). Typically inherited (3/4). +// +// s_minimum_allocation Minimum table allocation count (size on first growth.) It is +// probably preferable to call Reallocate on initialization rather +// than override his from the default traits. (7) +// +// NoMemory() Called when the hash table is unable to grow due to potential +// overflow or the lack of a sufficiently large prime. + +void DECLSPEC_NORETURN ThrowOutOfMemory(); + +class DefaultSimplerHashBehavior +{ +public: + static const unsigned s_growth_factor_numerator = 3; + static const unsigned s_growth_factor_denominator = 2; + + static const unsigned s_density_factor_numerator = 3; + static const unsigned s_density_factor_denominator = 4; + + static const unsigned s_minimum_allocation = 7; + + inline static void DECLSPEC_NORETURN NoMemory() + { + ::ThrowOutOfMemory(); + } +}; + +// Stores info about primes, including the magic number and shift amount needed +// to implement a divide without using the divide instruction +class PrimeInfo +{ +public: + PrimeInfo() : prime(0), magic(0), shift(0) {} + PrimeInfo(unsigned p, unsigned m, unsigned s) : prime(p), magic(m), shift(s) {} + unsigned prime; + unsigned magic; + unsigned shift; +}; + + +// Hash table class definition + +template +class SimplerHashTable +{ +public: + // Forward declaration. + class KeyIterator; + + // Constructor/destructor. SHash tables always start out empty, with no + // allocation overhead. Call Reallocate to prime with an initial size if + // desired. Pass NULL as the IAllocator* if you want to use DefaultAllocator + // (basically, operator new/delete). + + SimplerHashTable(IAllocator* alloc); + ~SimplerHashTable(); + + // operators new/delete when an IAllocator is to be used. + void * operator new(size_t sz, IAllocator * alloc); + void * operator new[](size_t sz, IAllocator * alloc); + void operator delete(void * p, IAllocator * alloc); + void operator delete[](void * p, IAllocator * alloc); + + // If the table contains a mapping for "key", returns "true" and + // sets "*pVal" to the value to which "key" maps. Otherwise, + // returns false, and does not modify "*pVal". + bool Lookup(Key k, Value* pVal = NULL) const; + + Value *LookupPointer(Key k) const; + + // Causes the table to map "key" to "val". Returns "true" if + // "key" had already been mapped by the table, "false" otherwise. + bool Set(Key k, Value val); + + // Ensures that "key" is not mapped to a value by the "table." + // Returns "true" iff it had been mapped. + bool Remove(Key k); + + // Remove all mappings in the table. + void RemoveAll(); + + // Begin and End pointers for iteration over entire table. + KeyIterator Begin() const; + KeyIterator End() const; + + // Return the number of elements currently stored in the table + unsigned GetCount() const; + +private: + // Forward declaration of the linked-list node class. + struct Node; + + unsigned GetIndexForKey(Key k) const; + + // If the table has a mapping for "k", return the node containing + // that mapping, else "NULL". + Node* FindNode(Key k) const; + + // Resizes a hash table for growth. The new size is computed based + // on the current population, growth factor, and maximum density factor. + void Grow(); + + // See if it is OK to grow the hash table by one element. If not, reallocate + // the hash table. + void CheckGrowth(); + +public: + // Reallocates a hash table to a specific size. The size must be big enough + // to hold all elements in the table appropriately. + // + // Note that the actual table size must always be a prime number; the number + // passed in will be upward adjusted if necessary. + void Reallocate(unsigned newTableSize); + + // For iteration, we use a pattern similar to the STL "forward + // iterator" pattern. It basically consists of wrapping an + // "iteration variable" in an object, and providing pointer-like + // operators on the iterator. Example usage: + // + // for (SimplerHashTable::KeyIterator iter = foo->Begin(), end = foo->End(); !iter.Equal(end); iter++) + // { + // // use foo, iter. + // } + // iter.Get() will yield (a reference to) the + // current key. It will assert the equivalent of "iter != end." + class KeyIterator + { + private: + friend class SimplerHashTable; + + // The method implementations have to be here for portability. + // Some compilers won't compile the separate implementation in shash.inl + + Node** m_table; + Node* m_node; + unsigned m_tableSize; + unsigned m_index; + + public: + KeyIterator(const SimplerHashTable *hash, BOOL begin) + : m_table(hash->m_table), + m_node(NULL), + m_tableSize(hash->m_tableSizeInfo.prime), + m_index(begin ? 0 : m_tableSize) + { + if (begin && hash->m_tableCount > 0) + { + assert(m_table != NULL); + while (m_index < m_tableSize && m_table[m_index] == NULL) + m_index++; + + if (m_index >= m_tableSize) + { + return; + } + else + { + m_node = m_table[m_index]; + } + assert(m_node != NULL); + } + } + + const Key& Get() const + { + assert(m_node != NULL); + + return m_node->m_key; + } + + const Value& GetValue() const + { + assert(m_node != NULL); + + return m_node->m_val; + } + + void SetValue(const Value & value) const + { + assert(m_node != NULL); + + m_node->m_val = value; + } + + void Next() + { + if (m_node != NULL) + { + m_node = m_node->m_next; + if (m_node != NULL) + { + return; + } + + // Otherwise... + m_index++; + } + while (m_index < m_tableSize && m_table[m_index] == NULL) + m_index++; + + if (m_index >= m_tableSize) + { + m_node = NULL; + return; + } + else + { + m_node = m_table[m_index]; + } + assert(m_node != NULL); + } + + bool Equal(const KeyIterator &i) const + { + return i.m_node == m_node; + } + + void operator++() { + Next(); + } + + void operator++(int) { + Next(); + } + }; + + // HashTableRef only exists to support operator[] + // operator[] returns a HashTableRef which enables operator[] to support reading and writing + // in a normal array, it just returns a ref an actual element, which is not possible here. + class HashTableRef + { + public: + // this is really the getter for the array. + operator Value() + { + + Value result; + table->Lookup(key, &result); + return result; + } + + void operator =(const Value v) + { + table->Set(key, v); + } + + friend class SimplerHashTable; + + protected: + HashTableRef(SimplerHashTable *t, Key k) + { + table = t; + key = k; + } + + SimplerHashTable *table; + Key key; + }; + + Value &operator[](Key k) const + { + Value* p = LookupPointer(k); + assert(p); + return *p; + } + + private: + // Find the next prime number >= the given value. + static PrimeInfo NextPrime(unsigned number); + + // Instance members + IAllocator* m_alloc; // IAllocator to use in this + // table. + // The node type. + struct Node { + Node* m_next; // Assume that the alignment requirement of Key and Value are no greater than Node*, so put m_next to avoid unnecessary padding. + Key m_key; + Value m_val; + + Node(Key k, Value v, Node* next) : m_next(next), m_key(k), m_val(v) {} + + void* operator new(size_t sz, IAllocator* alloc) + { + return alloc->Alloc(sz); + } + + void operator delete(void* p, IAllocator* alloc) + { + alloc->Free(p); + } + }; + + Node** m_table; // pointer to table + PrimeInfo m_tableSizeInfo; // size of table (a prime) and information about it + unsigned m_tableCount; // number of elements in table + unsigned m_tableMax; // maximum occupied count +}; + +#include "simplerhash.inl" + +// A few simple KeyFuncs types... + +// Base class for types whose equality function is the same as their "==". +template +struct KeyFuncsDefEquals +{ + static bool Equals(const T& x, const T& y) + { + return x == y; + } +}; + +template +struct PtrKeyFuncs: public KeyFuncsDefEquals +{ +public: + static unsigned GetHashCode(const T* ptr) + { + // Hmm. Maybe (unsigned) ought to be "ssize_t" -- or this ought to be ifdef'd by size. + return static_cast(reinterpret_cast(ptr)); + } +}; + +template // Must be coercable to "unsigned" with no loss of information. +struct SmallPrimitiveKeyFuncs: public KeyFuncsDefEquals +{ + static unsigned GetHashCode(const T& val) + { + return static_cast(val); + } +}; + +template // Assumed to be of size sizeof(UINT64). +struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals +{ + static unsigned GetHashCode(const T val) + { + // A static cast when T is a float or a double converts the value (i.e. 0.25 converts to 0) + // + // Instead we want to use all of the bits of a float to create the hash value + // So we cast the address of val to a pointer to an equivalent sized unsigned int + // This allows us to read the actual bit representation of a float type + // + // We can't read beyond the end of val, so we use sizeof(T) to determine + // exactly how many bytes to read + // + if (sizeof(T) == 8) + { + // cast &val to (UINT64 *) then deref to get the bits + UINT64 asUINT64 = *(reinterpret_cast(&val)); + + // Get the upper and lower 32-bit values from the 64-bit value + UINT32 upper32 = static_cast (asUINT64 >> 32); + UINT32 lower32 = static_cast (asUINT64 & 0xFFFFFFFF); + + // Exclusive-Or the upper32 and the lower32 values + return static_cast(upper32 ^ lower32); + + } + else if (sizeof(T) == 4) + { + // cast &val to (UINT32 *) then deref to get the bits + UINT32 asUINT32 = *(reinterpret_cast(&val)); + + // Just return the 32-bit value + return static_cast(asUINT32); + } + else if ((sizeof(T) == 2) || (sizeof(T) == 1)) + { + // For small sizes we must have an integer type + // so we can just use the static_cast. + // + return static_cast(val); + } + else + { + // Only support Hashing for types that are 8,4,2 or 1 bytes in size + assert(!"Unsupported size"); + return static_cast(val); // compile-time error here when we have a illegal size + } + } +}; + +#endif // _SIMPLERHASHTABLE_H_ diff --git a/lib/coreclr/src/inc/simplerhash.inl b/lib/coreclr/src/inc/simplerhash.inl new file mode 100644 index 0000000000..dc72acba26 --- /dev/null +++ b/lib/coreclr/src/inc/simplerhash.inl @@ -0,0 +1,350 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _SIMPLERHASHTABLE_INL_ +#define _SIMPLERHASHTABLE_INL_ + +// To implement magic-number divide with a 32-bit magic number, +// multiply by the magic number, take the top 64 bits, and shift that +// by the amount given in the table. + +inline +unsigned magicNumberDivide(unsigned numerator, const PrimeInfo &p) +{ + unsigned __int64 num = numerator; + unsigned __int64 mag = p.magic; + unsigned __int64 product = (num * mag) >> (32 + p.shift); + return (unsigned) product; +} + +inline +unsigned magicNumberRem(unsigned numerator, const PrimeInfo &p) +{ + unsigned div = magicNumberDivide(numerator, p); + unsigned result = numerator - (div * p.prime); + assert(result == numerator % p.prime); + return result; +} + +template +SimplerHashTable::SimplerHashTable(IAllocator* alloc) + : m_alloc(alloc), + m_table(NULL), + m_tableSizeInfo(), + m_tableCount(0), + m_tableMax(0) +{ + assert(m_alloc != nullptr); + +#ifndef __GNUC__ // these crash GCC + static_assert_no_msg(Behavior::s_growth_factor_numerator > Behavior::s_growth_factor_denominator); + static_assert_no_msg(Behavior::s_density_factor_numerator < Behavior::s_density_factor_denominator); +#endif +} + +template +SimplerHashTable::~SimplerHashTable() +{ + RemoveAll(); +} + +template +void * SimplerHashTable::operator new(size_t sz, IAllocator * alloc) +{ + return alloc->Alloc(sz); +} + +template +void * SimplerHashTable::operator new[](size_t sz, IAllocator * alloc) +{ + return alloc->Alloc(sz); +} + +template +void SimplerHashTable::operator delete(void * p, IAllocator * alloc) +{ + alloc->Free(p); +} + +template +void SimplerHashTable::operator delete[](void * p, IAllocator * alloc) +{ + alloc->Free(p); +} + +template +unsigned SimplerHashTable::GetCount() const +{ + return m_tableCount; +} + +template +bool SimplerHashTable::Lookup(Key key, Value* pVal) const +{ + Node* pN = FindNode(key); + + if (pN != NULL) + { + if (pVal != NULL) + { + *pVal = pN->m_val; + } + return true; + } + else + { + return false; + } +} + +template +Value *SimplerHashTable::LookupPointer(Key key) const +{ + Node* pN = FindNode(key); + + if (pN != NULL) + return &(pN->m_val); + else + return NULL; +} + +template +typename SimplerHashTable::Node* +SimplerHashTable::FindNode(Key k) const +{ + if (m_tableSizeInfo.prime == 0) + return NULL; + + unsigned index = GetIndexForKey(k); + + Node* pN = m_table[index]; + if (pN == NULL) + return NULL; + + // Otherwise... + while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) + pN = pN->m_next; + + assert(pN == NULL || KeyFuncs::Equals(k, pN->m_key)); + + // If pN != NULL, it's the node for the key, else the key isn't mapped. + return pN; +} + +template +unsigned SimplerHashTable::GetIndexForKey(Key k) const +{ + unsigned hash = KeyFuncs::GetHashCode(k); + + unsigned index = magicNumberRem(hash, m_tableSizeInfo); + + return index; +} + +template +bool SimplerHashTable::Set(Key k, Value v) +{ + CheckGrowth(); + + assert(m_tableSizeInfo.prime != 0); + + unsigned index = GetIndexForKey(k); + + Node* pN = m_table[index]; + while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) + { + pN = pN->m_next; + } + if (pN != NULL) + { + pN->m_val = v; + return true; + } + else + { + Node* pNewNode = new (m_alloc) Node(k, v, m_table[index]); + m_table[index] = pNewNode; + m_tableCount++; + return false; + } +} + +template +bool SimplerHashTable::Remove(Key k) +{ + unsigned index = GetIndexForKey(k); + + Node* pN = m_table[index]; + Node** ppN = &m_table[index]; + while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) + { + ppN = &pN->m_next; + pN = pN->m_next; + } + if (pN != NULL) + { + *ppN = pN->m_next; + m_tableCount--; + Node::operator delete(pN, m_alloc); + return true; + } + else + { + return false; + } +} + +template +void SimplerHashTable::RemoveAll() +{ + for (unsigned i = 0; i < m_tableSizeInfo.prime; i++) + { + for (Node* pN = m_table[i]; pN != NULL; ) + { + Node* pNext = pN->m_next; + Node::operator delete(pN, m_alloc); + pN = pNext; + } + } + m_alloc->Free(m_table); + + m_table = NULL; + m_tableSizeInfo = PrimeInfo(); + m_tableCount = 0; + m_tableMax = 0; + + return; +} + +template +typename SimplerHashTable::KeyIterator SimplerHashTable::Begin() const +{ + KeyIterator i(this, TRUE); + return i; +} + +template +typename SimplerHashTable::KeyIterator SimplerHashTable::End() const +{ + return KeyIterator(this, FALSE); +} + +template +void SimplerHashTable::CheckGrowth() +{ + if (m_tableCount == m_tableMax) + { + Grow(); + } +} + +template +void SimplerHashTable::Grow() +{ + unsigned newSize = (unsigned) (m_tableCount + * Behavior::s_growth_factor_numerator / Behavior::s_growth_factor_denominator + * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator); + if (newSize < Behavior::s_minimum_allocation) + newSize = Behavior::s_minimum_allocation; + + // handle potential overflow + if (newSize < m_tableCount) + Behavior::NoMemory(); + + Reallocate(newSize); +} + +template +void SimplerHashTable::Reallocate(unsigned newTableSize) +{ + assert(newTableSize >= (GetCount() * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator)); + + // Allocation size must be a prime number. This is necessary so that hashes uniformly + // distribute to all indices, and so that chaining will visit all indices in the hash table. + PrimeInfo newPrime = NextPrime(newTableSize); + newTableSize = newPrime.prime; + + Node** newTable = (Node**)m_alloc->ArrayAlloc(newTableSize, sizeof(Node*)); + + for (unsigned i = 0; i < newTableSize; i++) { + newTable[i] = NULL; + } + + // Move all entries over to new table (re-using the Node structures.) + + for (unsigned i = 0; i < m_tableSizeInfo.prime; i++) + { + Node* pN = m_table[i]; + while (pN != NULL) + { + Node* pNext = pN->m_next; + + unsigned newIndex = magicNumberRem(KeyFuncs::GetHashCode(pN->m_key), newPrime); + pN->m_next = newTable[newIndex]; + newTable[newIndex] = pN; + + pN = pNext; + } + } + + // @todo: + // We might want to try to delay this cleanup to allow asynchronous readers + if (m_table != NULL) + m_alloc->Free(m_table); + + m_table = newTable; + m_tableSizeInfo = newPrime; + m_tableMax = (unsigned) (newTableSize * Behavior::s_density_factor_numerator / Behavior::s_density_factor_denominator); +} + +// Table of primes and their magic-number-divide constant. +// For more info see the book "Hacker's Delight" chapter 10.9 "Unsigned Division by Divisors >= 1" +// These were selected by looking for primes, each roughly twice as big as the next, having +// 32-bit magic numbers, (because the algorithm for using 33-bit magic numbers is slightly slower). +// + +SELECTANY const PrimeInfo primeInfo[] = +{ + PrimeInfo(9, 0x38e38e39, 1), + PrimeInfo(23, 0xb21642c9, 4), + PrimeInfo(59, 0x22b63cbf, 3), + PrimeInfo(131, 0xfa232cf3, 7), + PrimeInfo(239, 0x891ac73b, 7), + PrimeInfo(433, 0x975a751, 4), + PrimeInfo(761, 0x561e46a5, 8), + PrimeInfo(1399, 0xbb612aa3, 10), + PrimeInfo(2473, 0x6a009f01, 10), + PrimeInfo(4327, 0xf2555049, 12), + PrimeInfo(7499, 0x45ea155f, 11), + PrimeInfo(12973, 0x1434f6d3, 10), + PrimeInfo(22433, 0x2ebe18db, 12), + PrimeInfo(46559, 0xb42bebd5, 15), + PrimeInfo(96581, 0xadb61b1b, 16), + PrimeInfo(200341, 0x29df2461, 15), + PrimeInfo(415517, 0xa181c46d, 18), + PrimeInfo(861719, 0x4de0bde5, 18), + PrimeInfo(1787021, 0x9636c46f, 20), + PrimeInfo(3705617, 0x4870adc1, 20), + PrimeInfo(7684087, 0x8bbc5b83, 22), + PrimeInfo(15933877, 0x86c65361, 23), + PrimeInfo(33040633, 0x40fec79b, 23), + PrimeInfo(68513161, 0x7d605cd1, 25), + PrimeInfo(142069021, 0xf1da390b, 27), + PrimeInfo(294594427, 0x74a2507d, 27), + PrimeInfo(733045421, 0x5dbec447, 28), +}; + +template +PrimeInfo SimplerHashTable::NextPrime(unsigned number) +{ + for (int i = 0; i < (int) (sizeof(primeInfo) / sizeof(primeInfo[0])); i++) { + if (primeInfo[i].prime >= number) + return primeInfo[i]; + } + + // overflow + Behavior::NoMemory(); +} + +#endif // _SIMPLERHASHTABLE_INL_ diff --git a/lib/coreclr/src/inc/slist.h b/lib/coreclr/src/inc/slist.h new file mode 100644 index 0000000000..f05d763dc6 --- /dev/null +++ b/lib/coreclr/src/inc/slist.h @@ -0,0 +1,387 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- +// @File: slist.h +// + +// +// @commn: Bunch of utility classes +// +// HISTORY: +// 02/03/98: created helper classes +// SLink, link node for singly linked list, every class that is intrusively +// linked should have a data member of this type +// SList, template linked list class, contains only inline +// methods for fast list operations, with proper type checking +// +// see below for futher info. on how to use these template classes +// +//----------------------------------------------------------------------------- + +//#ifndef _H_UTIL +//#error "I am a part of util.hpp Please don't include me alone !" +//#endif + + +#ifndef _H_SLIST_ +#define _H_SLIST_ + +//------------------------------------------------------------------ +// struct SLink, to use a singly linked list +// have a data member m_Link of type SLink in your class +// and instantiate the template SList class +//-------------------------------------------------------------------- + +struct SLink; +typedef DPTR(struct SLink) PTR_SLink; + +struct SLink +{ + PTR_SLink m_pNext; + SLink() + { + LIMITED_METHOD_CONTRACT; + + m_pNext = NULL; + } + + void InsertAfter(SLink* pLinkToInsert) + { + LIMITED_METHOD_CONTRACT; + PRECONDITION_MSG(NULL == pLinkToInsert->m_pNext, "This method does not support inserting lists"); + + PTR_SLink pTemp = m_pNext; + + m_pNext = PTR_SLink(pLinkToInsert); + pLinkToInsert->m_pNext = pTemp; + } + + // find pLink within the list starting at pHead + // if found remove the link from the list and return the link + // otherwise return NULL + static SLink* FindAndRemove(SLink *pHead, SLink* pLink, SLink ** ppPrior) + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(pHead != NULL); + _ASSERTE(pLink != NULL); + + SLink* pFreeLink = NULL; + *ppPrior = NULL; + + while (pHead->m_pNext != NULL) + { + if (pHead->m_pNext == pLink) + { + pFreeLink = pLink; + pHead->m_pNext = pLink->m_pNext; + *ppPrior = pHead; + break; + } + pHead = pHead->m_pNext; + } + + return pFreeLink; + } +}; + +//------------------------------------------------------------------ +// class SList. Intrusive singly linked list. +// +// To use SList with the default instantiation, your class should +// define a data member of type SLink and named 'm_Link'. To use a +// different field name, you need to provide an explicit LinkPtr +// template argument. For example: +// 'SList' +// +// SList has two different behaviours depending on boolean +// fHead variable, +// +// if fHead is true, then the list allows only InsertHead operations +// if fHead is false, then the list allows only InsertTail operations +// the code is optimized to perform these operations +// all methods are inline, and conditional compiled based on template +// argument 'fHead' +// so there is no actual code size increase +//-------------------------------------------------------------- +template +class SList +{ +public: + // typedef used by the Queue class below + typedef T ENTRY_TYPE; + +protected: + + // used as sentinel + SLink m_link; // slink.m_pNext == Null + PTR_SLink m_pHead; + PTR_SLink m_pTail; + + // get the list node within the object + static SLink* GetLink (T* pLink) + { + LIMITED_METHOD_DAC_CONTRACT; + return &(pLink->*LinkPtr); + } + + // move to the beginning of the object given the pointer within the object + static T* GetObject (SLink* pLink) + { + LIMITED_METHOD_DAC_CONTRACT; + if (pLink == NULL) + { + return NULL; + } + else + { +#if 1 + // Newer compilers define offsetof to be __builtin_offsetof, which doesn't use the + // old-school memory model trick to determine offset. + const UINT_PTR offset = (((UINT_PTR)&(((T *)0x1000)->*LinkPtr))-0x1000); + return (T*)__PTR(dac_cast(pLink) - offset); +#else + return (T*)__PTR(dac_cast(pLink) - offsetof(T, *LinkPtr)); +#endif + } + } + +public: + + SList() + { + WRAPPER_NO_CONTRACT; +#ifndef DACCESS_COMPILE + Init(); +#endif // !defined(DACCESS_COMPILE) + } + + void Init() + { + LIMITED_METHOD_CONTRACT; + m_pHead = &m_link; + // NOTE :: fHead variable is template argument + // the following code is a compiled in, only if the fHead flag + // is set to false, + if (!fHead) + { + m_pTail = &m_link; + } + } + + bool IsEmpty() + { + LIMITED_METHOD_CONTRACT; + return m_pHead->m_pNext == NULL; + } + +#ifndef DACCESS_COMPILE + + void InsertTail(T *pObj) + { + LIMITED_METHOD_CONTRACT; + // NOTE : conditional compilation on fHead template variable + if (!fHead) + { + _ASSERTE(pObj != NULL); + SLink *pLink = GetLink(pObj); + + m_pTail->m_pNext = pLink; + m_pTail = pLink; + } + else + {// you instantiated this class asking only for InsertHead operations + _ASSERTE(0); + } + } + + void InsertHead(T *pObj) + { + LIMITED_METHOD_CONTRACT; + // NOTE : conditional compilation on fHead template variable + if (fHead) + { + _ASSERTE(pObj != NULL); + SLink *pLink = GetLink(pObj); + + pLink->m_pNext = m_pHead->m_pNext; + m_pHead->m_pNext = pLink; + } + else + {// you instantiated this class asking only for InsertTail operations + _ASSERTE(0); + } + } + + T* RemoveHead() + { + LIMITED_METHOD_CONTRACT; + SLink* pLink = m_pHead->m_pNext; + if (pLink != NULL) + { + m_pHead->m_pNext = pLink->m_pNext; + } + // conditionally compiled, if the instantiated class + // uses Insert Tail operations + if (!fHead) + { + if(m_pTail == pLink) + { + m_pTail = m_pHead; + } + } + + return GetObject(pLink); + } + +#endif // !DACCESS_COMPILE + + T* GetHead() + { + WRAPPER_NO_CONTRACT; + return GetObject(m_pHead->m_pNext); + } + + T* GetTail() + { + WRAPPER_NO_CONTRACT; + + // conditional compile + if (fHead) + { // you instantiated this class asking only for InsertHead operations + // you need to walk the list yourself to find the tail + _ASSERTE(0); + } + return (m_pHead != m_pTail) ? GetObject(m_pTail) : NULL; + } + + static T *GetNext(T *pObj) + { + WRAPPER_NO_CONTRACT; + + _ASSERTE(pObj != NULL); + return GetObject(GetLink(pObj)->m_pNext); + } + + T* FindAndRemove(T *pObj) + { + WRAPPER_NO_CONTRACT; + + _ASSERTE(pObj != NULL); + + SLink *prior; + SLink *ret = SLink::FindAndRemove(m_pHead, GetLink(pObj), &prior); + + if (ret == m_pTail) + m_pTail = prior; + + return GetObject(ret); + } + + class Iterator + { + friend class SList; + + public: + Iterator & operator++() + { _ASSERTE(m_cur != NULL); m_cur = SList::GetNext(m_cur); return *this; } + + Iterator operator++(int) + { Iterator it(m_cur); ++(*this); return it; } + + bool operator==(Iterator const & other) const + { + return m_cur == other.m_cur || + (m_cur != NULL && other.m_cur != NULL && *m_cur == *other.m_cur); + } + + bool operator!=(Iterator const & other) const + { return !(*this == other); } + + T & operator*() + { _ASSERTE(m_cur != NULL); return *m_cur; } + + T * operator->() const + { return m_cur; } + + private: + Iterator(SList * pList) + : m_cur(pList->GetHead()) + { } + + Iterator(T* pObj) + : m_cur(pObj) + { } + + Iterator() + : m_cur(NULL) + { } + + T* m_cur; + }; + + Iterator begin() + { return Iterator(GetHead()); } + + Iterator end() + { return Iterator(); } +}; + +template +struct SListElem +{ + SLink m_Link; + ElemT m_Value; + + operator ElemT const &() const + { return m_Value; } + + operator ElemT &() + { return m_Value; } + + ElemT const & operator*() const + { return m_Value; } + + ElemT & operator*() + { return m_Value; } + + ElemT const & GetValue() const + { return m_Value; } + + ElemT & GetValue() + { return m_Value; } + + SListElem() + : m_Link() + , m_Value() + { } + + template + SListElem(T1&& val) + : m_Link() + , m_Value(std::forward(val)) + { } + + template + SListElem(T1&& val1, T2&& val2) + : m_Link() + , m_Value(std::forward(val1), std::forward(val2)) + { } + + template + SListElem(T1&& val1, T2&& val2, T3&& val3) + : m_Link() + , m_Value(std::forward(val1), std::forward(val2), std::forward(val3)) + { } + + template + SListElem(T1&& val1, T2&& val2, T3&& val3, T4&& val4) + : m_Link() + , m_Value(std::forward(val1), std::forward(val2), std::forward(val3), std::forward(val4)) + { } +}; + +#endif // _H_SLIST_ + +// End of file: list.h diff --git a/lib/coreclr/src/inc/sospriv.idl b/lib/coreclr/src/inc/sospriv.idl new file mode 100644 index 0000000000..589642675f --- /dev/null +++ b/lib/coreclr/src/inc/sospriv.idl @@ -0,0 +1,379 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/***************************************************************************** + ** ** + ** sospriv.idl - The private interface that SOS uses to query the runtime ** + ** for internal data. ** + ** ** + *****************************************************************************/ +import "unknwn.idl"; + +import "xclrdata.idl"; + +struct DacpSyncBlockCleanupData; +struct DacpThreadStoreData; +struct DacpAppDomainStoreData; +struct DacpAppDomainData; +struct DacpAssemblyData; +struct DacpThreadData; +struct DacpMethodDescData; +struct DacpCodeHeaderData; +struct DacpThreadpoolData; +struct DacpObjectData; +struct DacpWorkRequestData; +struct DacpMethodTableData; +struct DacpWorkRequestData; +struct DacpModuleData; +struct DacpGcHeapData; +struct DacpJitManagerInfo; +struct DacpHeapSegmentData; +struct DacpDomainLocalModuleData; +struct DacpDomainLocalModuleData; +struct DACEHInfo; +struct DacpRCWData; +struct DacpAllocData; +struct DacpGenerationAllocData; +struct DacpExceptionObjectData; +cpp_quote("#if 0") +typedef ULONG64 CLRDATA_ADDRESS; +typedef int CONTEXT; +typedef int T_CONTEXT; +typedef int mdToken; +typedef unsigned int size_t; +typedef int ModuleMapType; +typedef int VCSHeapType; +cpp_quote("#endif") + + +cpp_quote("typedef enum ModuleMapType { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE };") +cpp_quote("typedef enum VCSHeapType {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap};") + +typedef void (*MODULEMAPTRAVERSE)(UINT index, CLRDATA_ADDRESS methodTable,LPVOID token); +typedef void (*VISITHEAP)(CLRDATA_ADDRESS blockData,size_t blockSize,BOOL blockIsCurrentBlock); + +typedef BOOL (*VISITRCWFORCLEANUP)(CLRDATA_ADDRESS RCW,CLRDATA_ADDRESS Context,CLRDATA_ADDRESS Thread, + BOOL bIsFreeThreaded, LPVOID token); +typedef BOOL (*DUMPEHINFO)(UINT clauseIndex,UINT totalClauses, struct DACEHInfo *pEHInfo,LPVOID token); + +cpp_quote("#ifndef _SOS_HandleData") +cpp_quote("#define _SOS_HandleData") + +typedef struct _SOSHandleData +{ + CLRDATA_ADDRESS AppDomain; + CLRDATA_ADDRESS Handle; + CLRDATA_ADDRESS Secondary; + unsigned int Type; + BOOL StrongReference; + + // For RefCounted Handles + unsigned int RefCount; + unsigned int JupiterRefCount; + BOOL IsPegged; +} SOSHandleData; + +cpp_quote("#endif //HandleData") + +[ + object, + local, + uuid(286CA186-E763-4F61-9760-487D43AE4341) +] +interface ISOSEnum : IUnknown +{ + HRESULT Skip([in] unsigned int count); + HRESULT Reset(); + HRESULT GetCount([out] unsigned int *pCount); +} + + +[ + object, + local, + uuid(3E269830-4A2B-4301-8EE2-D6805B29B2FA) +] +interface ISOSHandleEnum : ISOSEnum +{ + HRESULT Next([in] unsigned int count, + [out, size_is(count), length_is(*pNeeded)] SOSHandleData handles[], + [out] unsigned int *pNeeded); +} + +cpp_quote("#ifndef _SOS_StackReference_") +cpp_quote("#define _SOS_StackReference_") + +typedef enum SOSStackSourceType +{ + SOS_StackSourceIP, // Instuction pointer in managed code + SOS_StackSourceFrame, // clr!Frame +} SOSStackSourceType; + +typedef enum SOSRefFlags +{ + SOSRefInterior = 1, + SOSRefPinned = 2 +} SOSRefFlags; + +typedef struct _SOS_StackRefData +{ + BOOL HasRegisterInformation; + int Register; + int Offset; + CLRDATA_ADDRESS Address; + CLRDATA_ADDRESS Object; + unsigned int Flags; + + SOSStackSourceType SourceType; + CLRDATA_ADDRESS Source; + CLRDATA_ADDRESS StackPointer; +} SOSStackRefData; + +/* Informs the user that we were unable to process the given clr!Frame or + * managed frame. + */ +typedef struct _SOS_StackRefError +{ + SOSStackSourceType SourceType; + CLRDATA_ADDRESS Source; + CLRDATA_ADDRESS StackPointer; +} SOSStackRefError; + +cpp_quote("#endif // _SOS_StackReference_") + +[ + object, + local, + uuid(774F4E1B-FB7B-491B-976D-A8130FE355E9) +] +interface ISOSStackRefErrorEnum : ISOSEnum +{ + HRESULT Next([in] unsigned int count, + [out, size_is(count), length_is(*pFetched)] SOSStackRefError ref[], + [out] unsigned int *pFetched); +} + +[ + object, + local, + uuid(8FA642BD-9F10-4799-9AA3-512AE78C77EE) +] +interface ISOSStackRefEnum : ISOSEnum +{ + HRESULT Next([in] unsigned int count, + [out, size_is(count), length_is(*pFetched)] SOSStackRefData ref[], + [out] unsigned int *pFetched); + + + /* Reports all frames which we could not enumerate gc references for. + */ + HRESULT EnumerateErrors([out] ISOSStackRefErrorEnum **ppEnum); +} + + +[ + object, + local, + uuid(436f00f2-b42a-4b9f-870c-e73db66ae930) +] +interface ISOSDacInterface : IUnknown +{ + // ThreadStore + HRESULT GetThreadStoreData(struct DacpThreadStoreData *data); + + // AppDomains + HRESULT GetAppDomainStoreData(struct DacpAppDomainStoreData *data); + HRESULT GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); + HRESULT GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data); + HRESULT GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, WCHAR *name, unsigned int *pNeeded); + HRESULT GetDomainFromContext(CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain); + + // Assemblies + HRESULT GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *pNeeded); + HRESULT GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); + HRESULT GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); + + // Modules + HRESULT GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod); + HRESULT GetModuleData(CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data); + HRESULT TraverseModuleMap(ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token); + HRESULT GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[], unsigned int *pNeeded); + HRESULT GetILForModule(CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il); + + // Threads + HRESULT GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data); + HRESULT GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread); + HRESULT GetStackLimits(CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp); + + // MethodDescs + HRESULT GetMethodDescData(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, struct DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData); + HRESULT GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD); + HRESULT GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, WCHAR *name, unsigned int *pNeeded); + HRESULT GetMethodDescPtrFromFrame(CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS * ppMD); + HRESULT GetMethodDescFromToken(CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc); + HRESULT GetMethodDescTransparencyData(CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data); + + // JIT Data + HRESULT GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data); + HRESULT GetJitManagerList(unsigned int count, struct DacpJitManagerInfo *managers, unsigned int *pNeeded); + HRESULT GetJitHelperFunctionName(CLRDATA_ADDRESS ip, unsigned int count, char *name, unsigned int *pNeeded); + HRESULT GetJumpThunkTarget(T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD); + + // ThreadPool + HRESULT GetThreadpoolData(struct DacpThreadpoolData *data); + HRESULT GetWorkRequestData(CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data); + HRESULT GetHillClimbingLogEntry(CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data); + + // Objects + HRESULT GetObjectData(CLRDATA_ADDRESS objAddr, struct DacpObjectData *data); + HRESULT GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *stringData, unsigned int *pNeeded); + HRESULT GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *className, unsigned int *pNeeded); + + // MethodTable + HRESULT GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, WCHAR *mtName, unsigned int *pNeeded); + HRESULT GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data); + HRESULT GetMethodTableSlot(CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value); + HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); + HRESULT GetMethodTableTransparencyData(CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data); + + // EEClass + HRESULT GetMethodTableForEEClass(CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value); + + // FieldDesc + HRESULT GetFieldDescData(CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data); + + // Frames + HRESULT GetFrameName(CLRDATA_ADDRESS vtable, unsigned int count, WCHAR *frameName, unsigned int *pNeeded); + + + // PEFiles + HRESULT GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base); + HRESULT GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, WCHAR *fileName, unsigned int *pNeeded); + + // GC + HRESULT GetGCHeapData(struct DacpGcHeapData *data); + HRESULT GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsigned int *pNeeded); // svr only + HRESULT GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details); // wks only + HRESULT GetGCHeapStaticData(struct DacpGcHeapDetails *data); + HRESULT GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data); + HRESULT GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data); + HRESULT GetOOMStaticData(struct DacpOomData *data); + HRESULT GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyzeData *data); + HRESULT GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *data); + + // DomainLocal + HRESULT GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data); + HRESULT GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data); + HRESULT GetDomainLocalModuleDataFromModule(CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data); + + // ThreadLocal + HRESULT GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data); + + // SyncBlock + HRESULT GetSyncBlockData(unsigned int number, struct DacpSyncBlockData *data); + HRESULT GetSyncBlockCleanupData(CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data); + + // Handles + HRESULT GetHandleEnum(ISOSHandleEnum **ppHandleEnum); + HRESULT GetHandleEnumForTypes(unsigned int types[], unsigned int count, ISOSHandleEnum **ppHandleEnum); + HRESULT GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppHandleEnum); + + // EH + HRESULT TraverseEHInfo(CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token); + HRESULT GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException); + + // StressLog + HRESULT GetStressLogAddress(CLRDATA_ADDRESS *stressLog); + + // Heaps + HRESULT TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback); + HRESULT GetCodeHeapList(CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo *codeHeaps, unsigned int *pNeeded); + HRESULT TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback); + + // Other + HRESULT GetUsefulGlobals(struct DacpUsefulGlobalsData *data); + HRESULT GetClrWatsonBuckets(CLRDATA_ADDRESS thread, void *pGenericModeBlock); + HRESULT GetTLSIndex(ULONG *pIndex); + HRESULT GetDacModuleHandle(HMODULE *phModule); + + // COM + HRESULT GetRCWData(CLRDATA_ADDRESS addr, struct DacpRCWData *data); + HRESULT GetRCWInterfaces(CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); + HRESULT GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *data); + HRESULT GetCCWInterfaces(CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); + HRESULT TraverseRCWCleanupList(CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token); + + // GC Reference Functions + + /* GetStackReferences + * Enumerates all references on a given callstack. + */ + HRESULT GetStackReferences([in] DWORD osThreadID, [out] ISOSStackRefEnum **ppEnum); + HRESULT GetRegisterName([in] int regName, [in] unsigned int count, [out] WCHAR *buffer, [out] unsigned int *pNeeded); + + HRESULT GetThreadAllocData(CLRDATA_ADDRESS thread, struct DacpAllocData *data); + HRESULT GetHeapAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded); + + // For BindingDisplay plugin + HRESULT GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); + HRESULT GetPrivateBinPaths(CLRDATA_ADDRESS appDomain, int count, WCHAR *paths, unsigned int *pNeeded); + HRESULT GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, WCHAR *location, unsigned int *pNeeded); + HRESULT GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, WCHAR *configFile, unsigned int *pNeeded); + HRESULT GetApplicationBase(CLRDATA_ADDRESS appDomain, int count, WCHAR *base, unsigned int *pNeeded); + HRESULT GetFailedAssemblyData(CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult); + HRESULT GetFailedAssemblyLocation(CLRDATA_ADDRESS assesmbly, unsigned int count, WCHAR *location, unsigned int *pNeeded); + HRESULT GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); +}; + +[ + object, + local, + uuid(A16026EC-96F4-40BA-87FB-5575986FB7AF) +] +interface ISOSDacInterface2 : IUnknown +{ + HRESULT GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data); + HRESULT IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy); +}; + +[ + object, + local, + uuid(B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4) +] +interface ISOSDacInterface3 : IUnknown +{ + HRESULT GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data); + HRESULT GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData *data); + HRESULT GetGCGlobalMechanisms(size_t* globalMechanisms); +}; + +[ + object, + local, + uuid(74B9D34C-A612-4B07-93DD-5462178FCE11) +] +interface ISOSDacInterface4 : IUnknown +{ + HRESULT GetClrNotification(CLRDATA_ADDRESS arguments[], int count, int *pNeeded); +}; + +[ + object, + local, + uuid(127d6abe-6c86-4e48-8e7b-220781c58101) +] +interface ISOSDacInterface5 : IUnknown +{ + HRESULT GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs); +}; + +[ + object, + local, + uuid(11206399-4B66-4EDB-98EA-85654E59AD45) +] +interface ISOSDacInterface6 : IUnknown +{ + HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); +}; diff --git a/lib/coreclr/src/inc/sstring.h b/lib/coreclr/src/inc/sstring.h new file mode 100644 index 0000000000..a37070d533 --- /dev/null +++ b/lib/coreclr/src/inc/sstring.h @@ -0,0 +1,1031 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// SString.h (Safe String) +// + +// --------------------------------------------------------------------------- + +// ------------------------------------------------------------------------------------------ +// SString is the "standard" string representation for the EE. Its has two purposes. +// (1) it provides an easy-to-use, relatively efficient, string class for APIs to standardize +// on. +// (2) it completely encapsulates all "unsafe" string operations - that is, string operations +// which yield possible buffer overrun bugs. Typesafe use of this API should help guarantee +// safety. +// +// A SString is conceptually unicode, although the internal conversion might be delayed as long as possible +// Basically it's up to the implementation whether conversion takes place immediately or is delayed, and if +// delayed, what operations trigger the conversion. +// +// Note that anywhere you express a "position" in a string, it is in terms of the Unicode representation of the +// string. +// +// If you need a direct non-unicode representation, you will have to provide a fresh SString which can +// recieve a conversion operation if necessary. +// +// The alternate encodings available are: +// 1. ASCII - string consisting entirely of ASCII (7 bit) characters. This is the only 1 byte encoding +// guaranteed to be fixed width. Such a string is also a valid instance of all the other 1 byte string +// representations, and we take advantage of this fact. +// 2. UTF-8 - standard multibyte unicode encoding. +// 3. ANSI - Potentially multibyte encoding using the ANSI page determined by GetACP(). +// +// @todo: Note that we could also provide support for several other cases (but currently do not.) +// - Page specified by GetOEMCP() (OEM page) +// - Arbitrary page support +// +// @todo: argument & overflow/underflow checking needs to be added +// ------------------------------------------------------------------------------------------ + + +#ifndef _SSTRING_H_ +#define _SSTRING_H_ + +#include "utilcode.h" +#include "sbuffer.h" + +// ========================================================================================== +// Documentational typedefs: use these to indicate specific representations of 8 bit strings: +// ========================================================================================== + +// Note that LPCSTR means ASCII (7-bit) only! + +typedef CHAR ASCII; +typedef ASCII *LPASCII; +typedef const ASCII *LPCASCII; + +typedef CHAR ANSI; +typedef ANSI *LPANSI; +typedef const ANSI *LPCANSI; + +typedef CHAR UTF8; +typedef UTF8 *LPUTF8; +typedef const UTF8 *LPCUTF8; + +// ========================================================================================== +// SString is the base class for safe strings. +// ========================================================================================== + + +typedef DPTR(class SString) PTR_SString; +class SString : private SBuffer +{ + friend struct _DacGlobals; + +private: + enum Representation + { + // Note: bits are meaningful: xVS V == Variable? S == Single byte width? + REPRESENTATION_EMPTY = 0x00, // 000 + REPRESENTATION_UNICODE = 0x04, // 100 + REPRESENTATION_ASCII = 0x01, // 001 + REPRESENTATION_UTF8 = 0x03, // 011 + REPRESENTATION_ANSI = 0x07, // 111 + + REPRESENTATION_VARIABLE_MASK = 0x02, + REPRESENTATION_SINGLE_MASK = 0x01, + REPRESENTATION_MASK = 0x07, + }; + + // Minimum guess for Printf buffer size + const static COUNT_T MINIMUM_GUESS = 20; + + +#ifdef _DEBUG + // Used to have a public ctor of this form - made it too easy to lose + // utf8 info by accident. Now you have to specify the representation type + // explicitly - this privator ctor prevents reinsertion of this ctor. + explicit SString(const ASCII *) + { + _ASSERTE(!"Don't call this."); + } +#endif + + protected: + class Index; + class UIndex; + + friend class Index; + friend class UIndex; + + public: + + // UIterator is character-level assignable. + class UIterator; + + // CIterators/Iterator'string must be modified by SString APIs. + class CIterator; + class Iterator; + + // Tokens for constructor overloads + enum tagUTF8Literal { Utf8Literal }; + enum tagLiteral { Literal }; + enum tagUTF8 { Utf8 }; + enum tagANSI { Ansi }; + enum tagASCII {Ascii }; + + static void Startup(); + static CHECK CheckStartup(); + + static const SString &Empty(); + + SString(); + + explicit SString(const SString &s); + + SString(const SString &s1, const SString &s2); + SString(const SString &s1, const SString &s2, const SString &s3); + SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4); + SString(const SString &s, const CIterator &i, COUNT_T length); + SString(const SString &s, const CIterator &start, const CIterator &end); + SString(const WCHAR *string); + SString(const WCHAR *string, COUNT_T count); + SString(enum tagASCII dummyTag, const ASCII *string); + SString(enum tagASCII dummyTag, const ASCII *string, COUNT_T count); + SString(enum tagUTF8 dummytag, const UTF8 *string); + SString(enum tagUTF8 dummytag, const UTF8 *string, COUNT_T count); + SString(enum tagANSI dummytag, const ANSI *string); + SString(enum tagANSI dummytag, const ANSI *string, COUNT_T count); + SString(WCHAR character); + + // NOTE: Literals MUST be read-only never-freed strings. + SString(enum tagLiteral dummytag, const CHAR *literal); + SString(enum tagUTF8Literal dummytag, const UTF8 *literal); + SString(enum tagLiteral dummytag, const WCHAR *literal); + SString(enum tagLiteral dummytag, const WCHAR *literal, COUNT_T count); + + // Set this string to the concatenation of s1,s2,s3,s4 + void Set(const SString &s); + void Set(const SString &s1, const SString &s2); + void Set(const SString &s1, const SString &s2, const SString &s3); + void Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4); + + // Set this string to the substring of s, starting at i, of length characters. + void Set(const SString &s, const CIterator &i, COUNT_T length); + + // Set this string to the substring of s, starting at start and ending at end (exclusive) + void Set(const SString &s, const CIterator &start, const CIterator &end); + + // Set this string to a copy of the given string + void Set(const WCHAR *string); + void SetASCII(const ASCII *string); + void SetUTF8(const UTF8 *string); + void SetANSI(const ANSI *string); + + // Set this string to a copy of the first count chars of the given string + void Set(const WCHAR *string, COUNT_T count); + + // Set this string to a prellocated copy of a given string. + // The caller is the owner of the bufffer and has to coordinate its lifetime. + void SetPreallocated(const WCHAR *string, COUNT_T count); + + void SetASCII(const ASCII *string, COUNT_T count); + + void SetUTF8(const UTF8 *string, COUNT_T count); + void SetANSI(const ANSI *string, COUNT_T count); + + // Set this string to the unicode character + void Set(WCHAR character); + + // Set this string to the UTF8 character + void SetUTF8(CHAR character); + + // This this string to the given literal. We share the mem and don't make a copy. + void SetLiteral(const CHAR *literal); + void SetLiteral(const WCHAR *literal); + + // ------------------------------------------------------------------ + // Public operations + // ------------------------------------------------------------------ + + // Normalizes the string representation to unicode. This can be used to + // make basic read-only operations non-failing. + void Normalize() const; + + // Return the number of characters in the string (excluding the terminating NULL). + COUNT_T GetCount() const; + BOOL IsEmpty() const; + + // Return whether a single byte string has all characters which fit in the ASCII set. + // (Note that this will return FALSE if the string has been converted to unicode for any + // reason.) + BOOL IsASCII() const; + + // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! + // + // THIS IS NOT SUPPORTED FULLY ON WIN9x + // SString case-insensitive comparison is based off LCMapString, + // which does not work on characters outside the current OS code page. + // + // Case insensitive code in SString is primarily targeted at + // supporting path comparisons, which is supported correctly on 9x, + // since file system names are limited to the OS code page. + // + // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! + + // Compute a content-based hash value + ULONG Hash() const; + ULONG HashCaseInsensitive() const; + + // Do a string comparison. Return 0 if the strings + // have the same value, -1 if this is "less than" s, or 1 if + // this is "greater than" s. + int Compare(const SString &s) const; + int CompareCaseInsensitive(const SString &s) const; // invariant locale + + // Do a case sensitive string comparison. Return TRUE if the strings + // have the same value FALSE if not. + BOOL Equals(const SString &s) const; + BOOL EqualsCaseInsensitive(const SString &s) const; // invariant locale + + // Match s to a portion of the string starting at the position. + // Return TRUE if the strings have the same value + // (regardless of representation), FALSE if not. + BOOL Match(const CIterator &i, const SString &s) const; + BOOL MatchCaseInsensitive(const CIterator &i, const SString &s) const; // invariant locale + + BOOL Match(const CIterator &i, WCHAR c) const; + BOOL MatchCaseInsensitive(const CIterator &i, WCHAR c) const; // invariant locale + + // Like match, but advances the iterator past the match + // if successful + BOOL Skip(CIterator &i, const SString &s) const; + BOOL Skip(CIterator &i, WCHAR c) const; + + // Start searching for a match of the given string, starting at + // the given iterator point. + // If a match exists, move the iterator to point to the nearest + // occurence of s in the string and return TRUE. + // If no match exists, return FALSE and leave the iterator unchanged. + BOOL Find(CIterator &i, const SString &s) const; + BOOL Find(CIterator &i, const WCHAR *s) const; + BOOL FindASCII(CIterator &i, const ASCII *s) const; + BOOL FindUTF8(CIterator &i, const UTF8 *s) const; + BOOL Find(CIterator &i, WCHAR c) const; + + BOOL FindBack(CIterator &i, const SString &s) const; + BOOL FindBack(CIterator &i, const WCHAR *s) const; + BOOL FindBackASCII(CIterator &i, const ASCII *s) const; + BOOL FindBackUTF8(CIterator &i, const UTF8 *s) const; + BOOL FindBack(CIterator &i, WCHAR c) const; + + // Returns TRUE if this string begins with the contents of s + BOOL BeginsWith(const SString &s) const; + BOOL BeginsWithCaseInsensitive(const SString &s) const; // invariant locale + + // Returns TRUE if this string ends with the contents of s + BOOL EndsWith(const SString &s) const; + BOOL EndsWithCaseInsensitive(const SString &s) const; // invariant locale + + // Sets this string to an empty string "". + void Clear(); + + // Truncate the string to the iterator position + void Truncate(const Iterator &i); + + // Append s to the end of this string. + void Append(const SString &s); + void Append(const WCHAR *s); + void AppendASCII(const CHAR *s); + void AppendUTF8(const CHAR *s); + + // Append char c to the end of this string. + void Append(const WCHAR c); + void AppendUTF8(const CHAR c); + + // Insert s into this string at the 'position'th character. + void Insert(const Iterator &i, const SString &s); + void Insert(const Iterator &i, const WCHAR *s); + void InsertASCII(const Iterator &i, const CHAR *s); + void InsertUTF8(const Iterator &i, const CHAR *s); + + // Delete substring position + length + void Delete(const Iterator &i, COUNT_T length); + + // Replace character at i with c + void Replace(const Iterator &i, WCHAR c); + + // Replace substring at (i,i+length) with s + void Replace(const Iterator &i, COUNT_T length, const SString &s); + + // Make sure that string buffer has room to grow + void Preallocate(COUNT_T characters) const; + + // Shrink buffer size as much as possible (reallocate if necessary.) + void Trim() const; + + // ------------------------------------------------------------------ + // Iterators: + // ------------------------------------------------------------------ + + // SString splits iterators into two categories. + // + // CIterator and Iterator are cheap to create, but allow only read-only + // access to the string. + // + // UIterator forces a unicode conversion, but allows + // assignment to individual string characters. They are also a bit more + // efficient once created. + + // ------------------------------------------------------------------ + // UIterator: + // ------------------------------------------------------------------ + + protected: + + class UIndex : public SBuffer::Index + { + friend class SString; + friend class Indexer; + + protected: + + UIndex(); + UIndex(SString *string, SCOUNT_T index); + WCHAR &GetAt(SCOUNT_T delta) const; + void Skip(SCOUNT_T delta); + SCOUNT_T Subtract(const UIndex &i) const; + CHECK DoCheck(SCOUNT_T delta) const; + + WCHAR *GetUnicode() const; + }; + + public: + + class UIterator : public UIndex, public Indexer + { + friend class SString; + + public: + UIterator() + { + } + + UIterator(SString *string, int index) + : UIndex(string, index) + { + } + }; + + UIterator BeginUnicode(); + UIterator EndUnicode(); + + // For CIterator & Iterator, we try our best to iterate the string without + // modifying it. (Currently, we do require an ASCII or Unicode string + // for simple WCHAR retrival, but you could imagine being more flexible + // going forward - perhaps even supporting iterating multibyte encodings + // directly.) + // + // Because of the runtime-changable nature of the string, CIterators + // require an extra member to record the character size. They also + // are unable to properly implement GetAt as required by the template + // (since there may not be a direct WCHAR pointer), so they provide + // further customization in a subclass. + // + // Normally the user expects to cast Iterators to CIterators transparently, so + // we provide a constructor on CIterator to support this. + + protected: + + class Index : public SBuffer::Index + { + friend class SString; + + friend class Indexer; + friend class Indexer; + + protected: + int m_characterSizeShift; + + Index(); + Index(SString *string, SCOUNT_T index); + BYTE &GetAt(SCOUNT_T delta) const; + void Skip(SCOUNT_T delta); + SCOUNT_T Subtract(const Index &i) const; + CHECK DoCheck(SCOUNT_T delta) const; + + void Resync(const SString *string, BYTE *ptr) const; + + const WCHAR *GetUnicode() const; + const CHAR *GetASCII() const; + + public: + // Note these should supercede the Indexer versions + // since this class comes first in the inheritence list + WCHAR operator*() const; + void operator->() const; + WCHAR operator[](int index) const; + }; + + public: + + class CIterator : public Index, public Indexer + { + friend class SString; + + public: + const Iterator &ConstCast() const + { + return *(const Iterator *)this; + } + + Iterator &ConstCast() + { + return *(Iterator *)this; + } + + operator const SBuffer::CIterator &() const + { + return *(const SBuffer::CIterator *)this; + } + + operator SBuffer::CIterator &() + { + return *(SBuffer::CIterator *)this; + } + + CIterator() + { + } + + CIterator(const SString *string, int index) + : Index(const_cast(string), index) + { + } + + // explicitly resolve these for gcc + WCHAR operator*() const { return Index::operator*(); } + void operator->() const { Index::operator->(); } + WCHAR operator[](int index) const { return Index::operator[](index); } + }; + + class Iterator : public Index, public Indexer + { + friend class SString; + + public: + operator const CIterator &() const + { + return *(const CIterator *)this; + } + + operator CIterator &() + { + return *(CIterator *)this; + } + + operator const SBuffer::Iterator &() const + { + return *(const SBuffer::Iterator *)this; + } + + operator SBuffer::Iterator &() + { + return *(SBuffer::Iterator *)this; + } + + Iterator() + { + } + + Iterator(SString *string, int index) + : Index(string, index) + { + SUPPORTS_DAC; + } + + // explicitly resolve these for gcc + WCHAR operator*() const { return Index::operator*(); } + void operator->() const { Index::operator->(); } + WCHAR operator[](int index) const { return Index::operator[](index); } + }; + + CIterator Begin() const; + CIterator End() const; + + Iterator Begin(); + Iterator End(); + + // ------------------------------------------------------------------ + // Conversion: + // ------------------------------------------------------------------ + + // Get a const pointer to the string in the current representation. + // This pointer can not be cached because it will become invalid if + // the SString changes representation or reallocates its buffer. + + // You can always get a unicode string. This will force a conversion + // if necessary. + const WCHAR *GetUnicode() const; + const WCHAR *GetUnicode(const CIterator &i) const; + + void LowerCase(); + void UpperCase(); + + // Helper function to convert string in-place to lower-case (no allocation overhead for SString instance) + static void LowerCase(__inout_z LPWSTR wszString); + + // These routines will use the given scratch string if necessary + // to perform a conversion to the desired representation + + // Use a local declaration of InlineScratchBuffer or StackScratchBuffer for parameters of + // AbstractScratchBuffer. + class AbstractScratchBuffer; + + // These routines will use the given scratch buffer if necessary + // to perform a conversion to the desired representation. Note that + // the lifetime of the pointer return is limited by BOTH the + // scratch string and the source (this) string. + // + // Typical usage: + // + // SString *s = ...; + // { + // StackScratchBuffer buffer; + // const UTF8 *utf8 = s->GetUTF8(buffer); + // CallFoo(utf8); + // } + // // No more pointers to returned buffer allowed. + + const UTF8 *GetUTF8(AbstractScratchBuffer &scratch) const; + const UTF8 *GetUTF8(AbstractScratchBuffer &scratch, COUNT_T *pcbUtf8) const; + const ANSI *GetANSI(AbstractScratchBuffer &scratch) const; + + // Used when the representation is known, throws if the representation doesn't match + const UTF8 *GetUTF8NoConvert() const; + + // Converts/copies into the given output string + void ConvertToUnicode(SString &dest) const; + void ConvertToANSI(SString &dest) const; + COUNT_T ConvertToUTF8(SString &dest) const; + + //------------------------------------------------------------------- + // Accessing the string contents directly + //------------------------------------------------------------------- + + // To write directly to the SString's underlying buffer: + // 1) Call OpenXXXBuffer() and pass it the count of characters + // you need. (Not including the null-terminator). + // 2) That returns a pointer to the raw buffer which you can write to. + // 3) When you are done writing to the pointer, call CloseBuffer() + // and pass it the count of characters you actually wrote (not including + // the null). The pointer from step 1 is now invalid. + + // example usage: + // void GetName(SString & str) { + // char * p = str.OpenANSIBuffer(3); + // strcpy(p, "Cat"); + // str.CloseBuffer(); + // } + + // Regarding the null-terminator: + // 1) Note that we wrote 4 characters (3 + a null). That's ok. OpenBuffer + // allocates 1 extra byte for the null. + // 2) If we only wrote 3 characters and no null, that's ok too. CloseBuffer() + // will add a null-terminator. + + // You should open the buffer, write the data, and immediately close it. + // No sstring operations are valid while the buffer is opened. + // + // In a debug build, Open/Close will do lots of little checks to make sure + // you don't buffer overflow while it's opened. In a retail build, this + // is a very streamlined action. + + + // Open the raw buffer for writing countChars characters (not including the null). + WCHAR *OpenUnicodeBuffer(COUNT_T maxCharCount); + UTF8 *OpenUTF8Buffer(COUNT_T maxSingleCharCount); + ANSI *OpenANSIBuffer(COUNT_T maxSingleCharCount); + + //Returns the unicode string, the caller is reponsible for lifetime of the string + WCHAR *GetCopyOfUnicodeString(); + + // Get the max size that can be passed to OpenUnicodeBuffer without causing allocations. + COUNT_T GetUnicodeAllocation(); + + // Call after OpenXXXBuffer(). + + // Provide the count of characters actually used (not including the + // null terminator). This will make sure the SString's size is correct + // and that we have a null-terminator. + void CloseBuffer(COUNT_T finalCount); + + // Close the buffer. Assumes that we completely filled the buffer + // that OpenBuffer() gave back. If we didn't write all the characters, + // call CloseBuffer(int) instead. + void CloseBuffer(); + +#ifdef DACCESS_COMPILE + // DAC access to string functions. + // Note that other accessors above are not DAC-safe and will return TARGET pointers into + // the string instead of copying the string over to the host. + // @dbgtodo dac support: Prevent usage of such DAC-unsafe SString APIs in DAC code + + // Instantiate a copy of the raw buffer in the host and return a pointer to it + void * DacGetRawContent() const; + + // Instantiate a copy of the raw buffer in the host. Requires that the underlying + // representation is already unicode. + const WCHAR * DacGetRawUnicode() const; + + // Copy the string from the target into the provided buffer, converting to unicode if necessary + bool DacGetUnicode(COUNT_T bufChars, + __out_z __inout_ecount(bufChars) WCHAR * buffer, + COUNT_T * needChars) const; + + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) const + { + SUPPORTS_DAC; + SBuffer::EnumMemoryRegions(flags); + } +#endif + + //--------------------------------------------------------------------- + // Utilities + //--------------------------------------------------------------------- + + // WARNING: The MBCS version of printf function are factory for globalization + // issues when used to format Unicode strings (%S). The Unicode versions are + // preferred in this case. + void Printf(const CHAR *format, ...); + void VPrintf(const CHAR *format, va_list args); + + void Printf(const WCHAR *format, ...); + void PPrintf(const WCHAR *format, ...); + void VPrintf(const WCHAR *format, va_list args); + + void PVPrintf(const WCHAR *format, va_list args); + + void AppendPrintf(const CHAR *format, ...); + void AppendVPrintf(const CHAR *format, va_list args); + + void AppendPrintf(const WCHAR *format, ...); + void AppendVPrintf(const WCHAR *format, va_list args); + + BOOL LoadResource(CCompRC::ResourceCategory eCategory, int resourceID); + HRESULT LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID); + HRESULT LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID); + BOOL FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, + const SString &arg1 = Empty(), const SString &arg2 = Empty(), + const SString &arg3 = Empty(), const SString &arg4 = Empty(), + const SString &arg5 = Empty(), const SString &arg6 = Empty(), + const SString &arg7 = Empty(), const SString &arg8 = Empty(), + const SString &arg9 = Empty(), const SString &arg10 = Empty()); + +#if 1 + // @todo - get rid of this and move it outside of SString + void MakeFullNamespacePath(const SString &nameSpace, const SString &name); +#endif + + //-------------------------------------------------------------------- + // Operators + //-------------------------------------------------------------------- + + operator const WCHAR * () const { WRAPPER_NO_CONTRACT; return GetUnicode(); } + + WCHAR operator[](int index) { WRAPPER_NO_CONTRACT; return Begin()[index]; } + WCHAR operator[](int index) const { WRAPPER_NO_CONTRACT; return Begin()[index]; } + + SString &operator= (const SString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } + SString &operator+= (const SString &s) { WRAPPER_NO_CONTRACT; Append(s); return *this; } + + // ------------------------------------------------------------------- + // Check functions + // ------------------------------------------------------------------- + + CHECK CheckIteratorRange(const CIterator &i) const; + CHECK CheckIteratorRange(const CIterator &i, COUNT_T length) const; + CHECK CheckEmpty() const; + + static CHECK CheckCount(COUNT_T count); + static CHECK CheckRepresentation(int representation); + +#if CHECK_INVARIANTS + static CHECK CheckASCIIString(const ASCII *string); + static CHECK CheckASCIIString(const ASCII *string, COUNT_T count); + + CHECK Check() const; + CHECK Invariant() const; + CHECK InternalInvariant() const; +#endif // CHECK_INVARIANTS + + // Helpers for CRT function equivalance. + static int __cdecl _stricmp(const CHAR *buffer1, const CHAR *buffer2); + static int __cdecl _strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); + + static int __cdecl _wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2); + static int __cdecl _wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); + + // C++ convenience overloads + static int _tstricmp(const CHAR *buffer1, const CHAR *buffer2); + static int _tstricmp(const WCHAR *buffer1, const WCHAR *buffer2); + + static int _tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); + static int _tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); + + // ------------------------------------------------------------------- + // Internal routines + // ------------------------------------------------------------------- + + + protected: + // Use this via InlineSString + SString(void *buffer, COUNT_T size); + + private: + static int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); + static int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); + + // Internal helpers: + + static const BYTE s_EmptyBuffer[2]; + + static UINT s_ACP; + + SPTR_DECL(SString,s_Empty); + + COUNT_T GetRawCount() const; + + // Get buffer as appropriate string rep + ASCII *GetRawASCII() const; + UTF8 *GetRawUTF8() const; + ANSI *GetRawANSI() const; + WCHAR *GetRawUnicode() const; + + void InitEmpty(); + + Representation GetRepresentation() const; + void SetRepresentation(Representation representation); + BOOL IsRepresentation(Representation representation) const; + BOOL IsFixedSize() const; + BOOL IsIteratable() const; + BOOL IsSingleByte() const; + + int GetCharacterSizeShift() const; + + COUNT_T SizeToCount(COUNT_T size) const; + COUNT_T CountToSize(COUNT_T count) const; + + COUNT_T GetBufferSizeInCharIncludeNullChar() const; + + BOOL IsLiteral() const; + BOOL IsAllocated() const; + BOOL IsBufferOpen() const; + BOOL IsASCIIScanned() const; + void SetASCIIScanned() const; + void SetNormalized() const; + BOOL IsNormalized() const; + void ClearNormalized() const; + + void EnsureWritable() const; + void ConvertToFixed() const; + void ConvertToIteratable() const; + + void ConvertASCIIToUnicode(SString &dest) const; + void ConvertToUnicode() const; + void ConvertToUnicode(const CIterator &i) const; + + const SString &GetCompatibleString(const SString &s, SString &scratch) const; + const SString &GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const; + BOOL ScanASCII() const; + void NullTerminate(); + + void Resize(COUNT_T count, Representation representation, + Preserve preserve = DONT_PRESERVE); + + void OpenBuffer(Representation representation, COUNT_T countChars); +}; + +// =========================================================================== +// InlineSString is used for stack allocation of strings, or when the string contents +// are expected or known to be small. Note that it still supports expandability via +// heap allocation if necessary. +// =========================================================================== + +template +class InlineSString : public SString +{ +private: + BYTE m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; + +public: + FORCEINLINE InlineSString() + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + } + + FORCEINLINE InlineSString(const SString &s) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s); + } + + FORCEINLINE InlineSString(const SString &s1, const SString &s2) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s1, s2); + } + + FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s1, s2, s3); + } + + FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s1, s2, s3, s4); + } + + FORCEINLINE InlineSString(const SString &s, const CIterator &start, const CIterator &end) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s, start, end); + } + + FORCEINLINE InlineSString(const SString &s, const CIterator &i, COUNT_T length) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(s, i, length); + } + + FORCEINLINE InlineSString(const WCHAR *string) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(string); + } + + FORCEINLINE InlineSString(const WCHAR *string, COUNT_T count) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(string, count); + } + + FORCEINLINE InlineSString(enum tagASCII, const CHAR *string) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetASCII(string); + } + + FORCEINLINE InlineSString(enum tagASCII, const CHAR *string, COUNT_T count) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetASCII(string, count); + } + + FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetUTF8(string); + } + + FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetUTF8(string, count); + } + + FORCEINLINE InlineSString(enum tagANSI dummytag, const ANSI *string) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetANSI(string); + } + + FORCEINLINE InlineSString(enum tagANSI dummytag, const ANSI *string, COUNT_T count) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetANSI(string, count); + } + + FORCEINLINE InlineSString(WCHAR character) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + Set(character); + } + + FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 character) + : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) + { + WRAPPER_NO_CONTRACT; + SetUTF8(character); + } + + FORCEINLINE InlineSString &operator= (const SString &s) + { + WRAPPER_NO_CONTRACT; + Set(s); + return *this; + } + + FORCEINLINE InlineSString &operator= (const InlineSString &s) + { + WRAPPER_NO_CONTRACT; + Set(s); + return *this; + } +}; + +// ================================================================================ +// StackSString is a lot like CQuickBytes. Use it to create an SString object +// using some stack space as a preallocated buffer. +// ================================================================================ + +typedef InlineSString<512> StackSString; + +// This is a smaller version for when it is known that the string that's going to +// be needed is small and it's preferable not to take up the stack space. +typedef InlineSString<32> SmallStackSString; + +// To be used specifically for path strings. +#ifdef _DEBUG +// This is a smaller version for debug builds to exercise the buffer allocation path +typedef InlineSString<32> PathString; +typedef InlineSString<2 * 32> LongPathString; +#else +// Set it to the current MAX_PATH +typedef InlineSString<260> PathString; +typedef InlineSString<2 * 260> LongPathString; +#endif + +// ================================================================================ +// Quick macro to create an SString around a literal string. +// usage: +// s = SL("My literal String"); +// ================================================================================ + +#define SL(_literal) SString(SString::Literal, _literal) + +// ================================================================================ +// ScratchBuffer classes are used by the GetXXX() routines to allocate scratch space in. +// ================================================================================ + +class SString::AbstractScratchBuffer : private SString +{ + protected: + // Do not use this class directly - use + // ScratchBuffer or StackScratchBuffer. + AbstractScratchBuffer(void *buffer, COUNT_T size); +}; + +template +class ScratchBuffer : public SString::AbstractScratchBuffer +{ + private: + BYTE m_inline[MEMSIZE]; + + public: + ScratchBuffer() + : AbstractScratchBuffer((void *)m_inline, MEMSIZE) + { + WRAPPER_NO_CONTRACT; + } +}; + +typedef ScratchBuffer<256> StackScratchBuffer; + +// ================================================================================ +// Special contract definition - THROWS_UNLESS_NORMALIZED +// this is used for operations which might fail for generalized strings but +// not if the string has already been converted to unicode. Rather than just +// setting this on all conversions to unicode, we only set it when explicitly +// asked. This should expose more potential problems. +// ================================================================================ + +#define THROWS_UNLESS_NORMALIZED \ + if (IsNormalized()) NOTHROW; else THROWS + +#define THROWS_UNLESS_BOTH_NORMALIZED(s) \ + if (IsNormalized() && s.IsNormalized()) NOTHROW; else THROWS + +#define FAULTS_UNLESS_NORMALIZED(stmt) \ + if (IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) + +#define FAULTS_UNLESS_BOTH_NORMALIZED(s, stmt) \ + if (IsNormalized() && s.IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) + +// ================================================================================ +// Inline definitions +// ================================================================================ + +#include + +#endif // _SSTRING_H_ diff --git a/lib/coreclr/src/inc/sstring.inl b/lib/coreclr/src/inc/sstring.inl new file mode 100644 index 0000000000..3bf84443bd --- /dev/null +++ b/lib/coreclr/src/inc/sstring.inl @@ -0,0 +1,2232 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +#ifndef _SSTRING_INL_ +#define _SSTRING_INL_ + +#include "sstring.h" + +#if defined(_MSC_VER) +#pragma inline_depth (20) +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4702) // Disable bogus unreachable code warning +#endif // _MSC_VER + +//#define SSTRING_EXTRA_CHECKS +#ifdef SSTRING_EXTRA_CHECKS +#define SS_CONTRACT CONTRACT +#define SS_CONTRACT_VOID CONTRACT_VOID +#define SS_CONTRACT_END CONTRACT_END +#define SS_RETURN RETURN +#define SS_CONSTRUCTOR_CHECK CONSTRUCTOR_CHECK +#define SS_PRECONDITION PRECONDITION +#define SS_POSTCONDITION POSTCONDITION + +#else //SSTRING_EXTRA_CHECKS + +#define SS_CONTRACT(x) CONTRACTL +#define SS_CONTRACT_VOID CONTRACTL +#define SS_CONTRACT_END CONTRACTL_END +#define SS_RETURN return +#define SS_CONSTRUCTOR_CHECK +#define SS_PRECONDITION(x) +#define SS_POSTCONDITION(x) +//Do I need this instance check at all? + +#endif + + +// --------------------------------------------------------------------------- +// Inline implementations. Pay no attention to that man behind the curtain. +// --------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// Default constructor. Sets the string to the empty string. +//---------------------------------------------------------------------------- +inline SString::SString() + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + CONSTRUCTOR_CHECK; + POSTCONDITION(IsEmpty()); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; + + RETURN; +#else + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; +#endif +} + +inline SString::SString(void *buffer, COUNT_T size) + : SBuffer(Prealloc, buffer, size) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckSize(size)); + SS_POSTCONDITION(IsEmpty()); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + if (size < sizeof(WCHAR)) + { + // Ignore the useless buffer + SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); + } + else + { + SBuffer::TweakSize(sizeof(WCHAR)); + GetRawUnicode()[0] = 0; + } + + SS_RETURN; +} + +inline SString::SString(const SString &s) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s.Check()); + SS_POSTCONDITION(Equals(s)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s); + + SS_RETURN; +} + +inline SString::SString(const SString &s1, const SString &s2) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s1, s2); + + SS_RETURN; +} + +inline SString::SString(const SString &s1, const SString &s2, const SString &s3) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + PRECONDITION(s3.Check()); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s1, s2, s3); + + SS_RETURN; +} + +inline SString::SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + PRECONDITION(s3.Check()); + PRECONDITION(s4.Check()); + THROWS; + } + SS_CONTRACT_END; + + Set(s1, s2, s3, s4); + + SS_RETURN; +} + +inline SString::SString(const SString &s, const CIterator &i, COUNT_T count) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s.Check()); + PRECONDITION(i.Check()); + PRECONDITION(CheckCount(count)); + SS_POSTCONDITION(s.Match(i, *this)); + SS_POSTCONDITION(GetRawCount() == count); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s, i, count); + + SS_RETURN; +} + +inline SString::SString(const SString &s, const CIterator &start, const CIterator &end) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(s.Check()); + PRECONDITION(start.Check()); + PRECONDITION(s.CheckIteratorRange(start)); + PRECONDITION(end.Check()); + PRECONDITION(s.CheckIteratorRange(end)); + PRECONDITION(start <= end); + SS_POSTCONDITION(s.Match(start, *this)); + SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s, start, end); + + SS_RETURN; +} + +inline SString::SString(const WCHAR *string) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(string); + + SS_RETURN; +} + +inline SString::SString(const WCHAR *string, COUNT_T count) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckCount(count)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(string, count); + + SS_RETURN; +} + +inline SString::SString(enum tagASCII, const ASCII *string) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckASCIIString(string)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetASCII(string); + + SS_RETURN; +} + +inline SString::SString(enum tagASCII, const ASCII *string, COUNT_T count) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckASCIIString(string, count)); + PRECONDITION(CheckCount(count)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetASCII(string, count); + + SS_RETURN; +} + +inline SString::SString(tagUTF8 dummytag, const UTF8 *string) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + // !!! Check for illegal UTF8 encoding? + PRECONDITION(CheckPointer(string, NULL_OK)); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + SetUTF8(string); + + SS_RETURN; +} + +inline SString::SString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + // !!! Check for illegal UTF8 encoding? + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckCount(count)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetUTF8(string, count); + + SS_RETURN; +} + +inline SString::SString(tagANSI dummytag, const ANSI *string) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetANSI(string); + + SS_RETURN; +} + +inline SString::SString(tagANSI dummytag, const ANSI *string, COUNT_T count) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(string, NULL_OK)); + PRECONDITION(CheckCount(count)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetANSI(string, count); + + SS_RETURN; +} + +inline SString::SString(WCHAR character) + : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(character); + + SS_RETURN; +} + +inline SString::SString(tagLiteral dummytag, const ASCII *literal) + : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(literal)); + PRECONDITION(CheckASCIIString(literal)); + NOTHROW; + GC_NOTRIGGER; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + SetRepresentation(REPRESENTATION_ASCII); + + SS_RETURN; +} + +inline SString::SString(tagUTF8Literal dummytag, const UTF8 *literal) + : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(literal)); + NOTHROW; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetRepresentation(REPRESENTATION_UTF8); + + SS_RETURN; +} + +inline SString::SString(tagLiteral dummytag, const WCHAR *literal) + : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (wcslen(literal)+1)*sizeof(WCHAR)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(literal)); + NOTHROW; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetRepresentation(REPRESENTATION_UNICODE); + SetNormalized(); + + SS_RETURN; +} + +inline SString::SString(tagLiteral dummytag, const WCHAR *literal, COUNT_T count) + : SBuffer(Immutable, (const BYTE *) literal, (count + 1) * sizeof(WCHAR)) +{ + SS_CONTRACT_VOID + { + SS_CONSTRUCTOR_CHECK; + PRECONDITION(CheckPointer(literal)); + NOTHROW; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + SetRepresentation(REPRESENTATION_UNICODE); + SetNormalized(); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Set this string to s +// s - source string +//----------------------------------------------------------------------------- +inline void SString::Set(const SString &s) +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(s.Check()); + SS_POSTCONDITION(Equals(s)); + THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + SBuffer::Set(s); + SetRepresentation(s.GetRepresentation()); + ClearNormalized(); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Set this string to concatenation of s1 and s2 +//----------------------------------------------------------------------------- +inline void SString::Set(const SString &s1, const SString &s2) +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Preallocate(s1.GetCount() + s2.GetCount()); + + Set(s1); + Append(s2); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Set this string to concatenation of s1, s2, and s3 +//----------------------------------------------------------------------------- +inline void SString::Set(const SString &s1, const SString &s2, const SString &s3) +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + PRECONDITION(s3.Check()); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount()); + + Set(s1); + Append(s2); + Append(s3); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Set this string to concatenation of s1, s2, s3, and s4 +//----------------------------------------------------------------------------- +inline void SString::Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4) +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(s1.Check()); + PRECONDITION(s2.Check()); + PRECONDITION(s3.Check()); + PRECONDITION(s4.Check()); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount() + s4.GetCount()); + + Set(s1); + Append(s2); + Append(s3); + Append(s4); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Set this string to the substring from s. +// s - the source string +// start - the character to start at +// length - number of characters to copy from s. +//----------------------------------------------------------------------------- +inline void SString::Set(const SString &s, const CIterator &i, COUNT_T count) +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + PRECONDITION(s.Check()); + PRECONDITION(i.Check()); + PRECONDITION(CheckCount(count)); + SS_POSTCONDITION(s.Match(i, *this)); + SS_POSTCONDITION(GetRawCount() == count); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + // @todo: detect case where we can reuse literal? + Resize(count, s.GetRepresentation()); + SBuffer::Copy(SBuffer::Begin(), i.m_ptr, count<= start); + SS_POSTCONDITION(s.Match(start, *this)); + SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); + THROWS; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + Set(s, start, end - start); + + SS_RETURN; +} + +// Return a global empty string +inline const SString &SString::Empty() +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACTL + { + // POSTCONDITION(RETVAL.IsEmpty()); + PRECONDITION(CheckStartup()); + NOTHROW; + GC_NOTRIGGER; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + CONTRACTL_END; +#else + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + STATIC_CONTRACT_SUPPORTS_DAC; +#endif + + _ASSERTE(s_Empty != NULL); // Did you call SString::Startup()? + return *s_Empty; +} + +// Get a const pointer to the internal buffer as a unicode string. +inline const WCHAR *SString::GetUnicode() const +{ + SS_CONTRACT(const WCHAR *) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(RETVAL)); + if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; + GC_NOTRIGGER; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + if (this == NULL) + SS_RETURN NULL; + + ConvertToUnicode(); + + SS_RETURN GetRawUnicode(); +} + +// Normalize the string to unicode. This will make many operations nonfailing. +inline void SString::Normalize() const +{ + SS_CONTRACT_VOID + { + INSTANCE_CHECK; + SS_POSTCONDITION(IsNormalized()); + THROWS_UNLESS_NORMALIZED; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + ConvertToUnicode(); + SetNormalized(); + + SS_RETURN; +} + +// Get a const pointer to the internal buffer as a unicode string. +inline const WCHAR *SString::GetUnicode(const CIterator &i) const +{ + SS_CONTRACT(const WCHAR *) + { + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + THROWS_UNLESS_NORMALIZED; + GC_NOTRIGGER; + } + SS_CONTRACT_END; + + PRECONDITION(CheckPointer(this)); + + ConvertToUnicode(i); + + SS_RETURN i.GetUnicode(); +} + +// Append s to the end of this string. +inline void SString::Append(const SString &s) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(s.Check()); + THROWS; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + Insert(End(), s); + + SS_RETURN; +} + +inline void SString::Append(const WCHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(string)); + THROWS; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + // Wrap the string in temporary SString without copying it + SString s(SString::Literal, string); + s.ClearImmutable(); + Append(s); + + SS_RETURN; +} + +inline void SString::AppendASCII(const CHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(string)); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Ascii, string); + Append(s); + + SS_RETURN; +} + +inline void SString::AppendUTF8(const CHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckPointer(string)); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Utf8, string); + Append(s); + + SS_RETURN; +} + +inline void SString::Append(const WCHAR c) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + THROWS; + } + SS_CONTRACT_END; + + InlineSString<2 * sizeof(c)> s(c); + Append(s); + + SS_RETURN; +} + +inline void SString::AppendUTF8(const CHAR c) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + THROWS; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + InlineSString<2 * sizeof(c)> s(SString::Utf8, c); + Append(s); + + SS_RETURN; +} + +// Turn this on to test that these if you are testing common scenarios dealing with +// ASCII strings that do not touch the cases where this family of function differs +// in behavior for expected reasons. +//#define VERIFY_CRT_EQUIVALNCE 1 + +// Helpers for CRT function equivalance. +/* static */ +inline int __cdecl SString::_stricmp(const CHAR *buffer1, const CHAR *buffer2) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelperA(buffer1, buffer2, 0, TRUE, FALSE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_stricmp(buffer1, buffer2) == 0)); +#endif + return returnValue; + +} + +/* static */ +inline int __cdecl SString::_strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelperA(buffer1, buffer2, count, TRUE, TRUE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_strnicmp(buffer1, buffer2, count) == 0)); +#endif + return returnValue; +} + +/* static */ +inline int __cdecl SString::_wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelper(buffer1, buffer2, 0, TRUE, FALSE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_wcsicmp(buffer1, buffer2) == 0)); +#endif + return returnValue; + +} + +/* static */ +inline int __cdecl SString::_wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) { + WRAPPER_NO_CONTRACT; + int returnValue = CaseCompareHelper(buffer1, buffer2, count, TRUE, TRUE); +#ifdef VERIFY_CRT_EQUIVALNCE + _ASSERTE((returnValue == 0) == (::_wcsnicmp(buffer1, buffer2, count) == 0)); +#endif + return returnValue; +} + +inline int SString::_tstricmp(const CHAR *buffer1, const CHAR *buffer2) +{ + return _stricmp(buffer1, buffer2); +} + +inline int SString::_tstricmp(const WCHAR *buffer1, const WCHAR *buffer2) +{ + return _wcsicmp(buffer1, buffer2); +} + +inline int SString::_tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) +{ + return _strnicmp(buffer1, buffer2, count); +} + +inline int SString::_tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) +{ + return _wcsnicmp(buffer1, buffer2, count); +} + +inline BOOL SString::Match(const CIterator &i, WCHAR c) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + NOTHROW; + } + SS_CONTRACT_END; + + // End() will not throw here + CONTRACT_VIOLATION(ThrowsViolation); + SS_RETURN (i < End() && i[0] == c); +} + +inline BOOL SString::Skip(CIterator &i, const SString &s) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + THROWS_UNLESS_BOTH_NORMALIZED(s); + } + SS_CONTRACT_END; + + if (Match(i, s)) + { + i += s.GetRawCount(); + SS_RETURN TRUE; + } + else + SS_RETURN FALSE; +} + +inline BOOL SString::Skip(CIterator &i, WCHAR c) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + INSTANCE_CHECK; + PRECONDITION(CheckIteratorRange(i)); + NOTHROW; + } + SS_CONTRACT_END; + + if (Match(i, c)) + { + i++; + SS_RETURN TRUE; + } + else + SS_RETURN FALSE; +} + +// Find string within this string. Return TRUE and update iterator if found +inline BOOL SString::Find(CIterator &i, const WCHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(string); + SS_RETURN Find(i, s); +} + +inline BOOL SString::FindASCII(CIterator &i, const CHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Ascii, string); + SS_RETURN Find(i, s); +} + +inline BOOL SString::FindUTF8(CIterator &i, const CHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Utf8, string); + SS_RETURN Find(i, s); +} + +inline BOOL SString::FindBack(CIterator &i, const WCHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(string); + SS_RETURN FindBack(i, s); +} + +inline BOOL SString::FindBackASCII(CIterator &i, const CHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Ascii, string); + SS_RETURN FindBack(i, s); +} + +inline BOOL SString::FindBackUTF8(CIterator &i, const CHAR *string) const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Utf8, string); + SS_RETURN FindBack(i, s); +} + +// Insert string at iterator position +inline void SString::Insert(const Iterator &i, const SString &s) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(s.Check()); + THROWS; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + Replace(i, 0, s); + + SS_RETURN; +} + +inline void SString::Insert(const Iterator &i, const WCHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(string); + Replace(i, 0, s); + + SS_RETURN; +} + +inline void SString::InsertASCII(const Iterator &i, const CHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Ascii, string); + Replace(i, 0, s); + + SS_RETURN; +} + +inline void SString::InsertUTF8(const Iterator &i, const CHAR *string) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i)); + PRECONDITION(CheckPointer(string)); + THROWS; + } + SS_CONTRACT_END; + + StackSString s(SString::Utf8, string); + Replace(i, 0, s); + + SS_RETURN; +} + +// Delete string at iterator position +inline void SString::Delete(const Iterator &i, COUNT_T length) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckIteratorRange(i, length)); + THROWS; + SUPPORTS_DAC_HOST_ONLY; + } + SS_CONTRACT_END; + + Replace(i, length, Empty()); + + SS_RETURN; +} + +// Preallocate some space for the string buffer +inline void SString::Preallocate(COUNT_T characters) const +{ + WRAPPER_NO_CONTRACT; + + // Assume unicode since we may get converted + SBuffer::Preallocate(characters * sizeof(WCHAR)); +} + +// Trim unused space from the buffer +inline void SString::Trim() const +{ + WRAPPER_NO_CONTRACT; + + if (GetRawCount() == 0) + { + // Share the global empty string buffer. + const_cast(this)->SBuffer::SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); + } + else + { + SBuffer::Trim(); + } +} + +// RETURN true if the string is empty. +inline BOOL SString::IsEmpty() const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + NOTHROW; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + SS_RETURN (GetRawCount() == 0); +} + +// RETURN true if the string rep is ASCII. +inline BOOL SString::IsASCII() const +{ + SS_CONTRACT(BOOL) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + NOTHROW; + } + SS_CONTRACT_END; + + SS_RETURN IsRepresentation(REPRESENTATION_ASCII); +} + +// Get the number of characters in the string (excluding the terminating NULL) +inline COUNT_T SString::GetCount() const +{ + SS_CONTRACT(COUNT_T) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckCount(RETVAL)); + THROWS_UNLESS_NORMALIZED; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + ConvertToFixed(); + + SS_RETURN SizeToCount(GetSize()); +} + +// Private helpers: +// Return the current size of the string (even if it is multibyte) +inline COUNT_T SString::GetRawCount() const +{ + WRAPPER_NO_CONTRACT; + + return SizeToCount(GetSize()); +} + +// Private helpers: +// get string contents as a particular character set: + +inline ASCII *SString::GetRawASCII() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (ASCII *) m_buffer; +} + +inline UTF8 *SString::GetRawUTF8() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (UTF8 *) m_buffer; +} + +inline ANSI *SString::GetRawANSI() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (ANSI *) m_buffer; +} + +inline WCHAR *SString::GetRawUnicode() const +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + return (WCHAR *)m_buffer; +} + +// Private helper: +// get the representation (ansi, unicode, utf8) +inline SString::Representation SString::GetRepresentation() const +{ + WRAPPER_NO_CONTRACT; + + return (Representation) SBuffer::GetRepresentationField(); +} + +// Private helper. +// Set the representation. +inline void SString::SetRepresentation(SString::Representation representation) +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + GC_NOTRIGGER; + NOTHROW; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckRepresentation(representation)); + POSTCONDITION(GetRepresentation() == representation); + } + CONTRACT_END; +#else //SSTRING_EXTRA_CHECKS + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; +#endif //SSTRING_EXTRA_CHECKS + + SBuffer::SetRepresentationField((int) representation); + + SS_RETURN; +} + +// Private helper: +// Get the amount to shift the byte size to get a character count +inline int SString::GetCharacterSizeShift() const +{ + WRAPPER_NO_CONTRACT; + + // Note that the flag is backwards; we want the default + // value to match the default representation (empty) + return (GetRepresentation()&REPRESENTATION_SINGLE_MASK) == 0; +} + +//---------------------------------------------------------------------------- +// Private helper. +// We know the buffer should be m_count characters. Place a null terminator +// in the buffer to make our internal string null-terminated at that length. +//---------------------------------------------------------------------------- +FORCEINLINE void SString::NullTerminate() +{ + SUPPORTS_DAC_HOST_ONLY; +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + POSTCONDITION(CheckPointer(this)); + NOTHROW; + GC_NOTRIGGER; + } + CONTRACT_END; +#else //SSTRING_EXTRA_CHECKS + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; +#endif //SSTRING_EXTRA_CHECKS + + BYTE *end = m_buffer + GetSize(); + + if (GetRepresentation()&REPRESENTATION_SINGLE_MASK) + { + ((CHAR *)end)[-1] = 0; + } + else + { + ((WCHAR *)end)[-1] = 0; + } + + SS_RETURN; +} + +//---------------------------------------------------------------------------- +// private helper +// Return true if the string is a literal. +// A literal string has immutable memory. +//---------------------------------------------------------------------------- +inline BOOL SString::IsLiteral() const +{ + WRAPPER_NO_CONTRACT; + + return SBuffer::IsImmutable() && (m_buffer != s_EmptyBuffer); +} + +//---------------------------------------------------------------------------- +// private helper: +// RETURN true if the string allocated (and should delete) its buffer. +// IsAllocated() will RETURN false for Literal strings and +// stack-based strings (the buffer is on the stack) +//---------------------------------------------------------------------------- +inline BOOL SString::IsAllocated() const +{ + WRAPPER_NO_CONTRACT; + + return SBuffer::IsAllocated(); +} + +//---------------------------------------------------------------------------- +// Return true after we call OpenBuffer(), but before we close it. +// All SString operations are illegal while the buffer is open. +//---------------------------------------------------------------------------- +#if _DEBUG +inline BOOL SString::IsBufferOpen() const +{ + WRAPPER_NO_CONTRACT; + + return SBuffer::IsOpened(); +} +#endif + +//---------------------------------------------------------------------------- +// Return true if we've scanned the string to see if it is in the ASCII subset. +//---------------------------------------------------------------------------- +inline BOOL SString::IsASCIIScanned() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return SBuffer::IsFlag1(); +} + +//---------------------------------------------------------------------------- +// Set that we've scanned the string to see if it is in the ASCII subset. +//---------------------------------------------------------------------------- +inline void SString::SetASCIIScanned() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + const_cast(this)->SBuffer::SetFlag1(); +} + +//---------------------------------------------------------------------------- +// Return true if we've normalized the string to unicode +//---------------------------------------------------------------------------- +inline BOOL SString::IsNormalized() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + return SBuffer::IsFlag3(); +} + +//---------------------------------------------------------------------------- +// Set that we've normalized the string to unicode +//---------------------------------------------------------------------------- +inline void SString::SetNormalized() const +{ + WRAPPER_NO_CONTRACT; + + const_cast(this)->SBuffer::SetFlag3(); +} + +//---------------------------------------------------------------------------- +// Clear normalization +//---------------------------------------------------------------------------- +inline void SString::ClearNormalized() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC_HOST_ONLY; + + const_cast(this)->SBuffer::ClearFlag3(); +} + +//---------------------------------------------------------------------------- +// Private helper. +// Check to see if the string representation has single byte size +//---------------------------------------------------------------------------- +inline BOOL SString::IsSingleByte() const +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + + return ((GetRepresentation()&REPRESENTATION_SINGLE_MASK) != 0); +} + +//---------------------------------------------------------------------------- +// Private helper. +// Check to see if the string representation has fixed size characters +//---------------------------------------------------------------------------- +inline BOOL SString::IsFixedSize() const +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_SUPPORTS_DAC; + + if (GetRepresentation()&REPRESENTATION_VARIABLE_MASK) + return FALSE; + else + return TRUE; +} + +//---------------------------------------------------------------------------- +// Private helper. +// Check to see if the string representation is appropriate for iteration +//---------------------------------------------------------------------------- +inline BOOL SString::IsIteratable() const +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_SUPPORTS_DAC; + + // Note that in many cases ANSI may be fixed width. However we + // currently still do not allow iterating on them, because we would have to + // do character-by-character conversion on a character dereference (which must + // go to unicode) . We may want to adjust this going forward to + // depending on perf in the non-ASCII but fixed width ANSI case. + + return ((GetRepresentation()&REPRESENTATION_VARIABLE_MASK) == 0); +} + +//---------------------------------------------------------------------------- +// Private helper +// Return the size of the given string in bytes +// in the given representation. +// count does not include the null-terminator, but the RETURN value does. +//---------------------------------------------------------------------------- +inline COUNT_T SString::CountToSize(COUNT_T count) const +{ + SS_CONTRACT(COUNT_T) + { + GC_NOTRIGGER; + PRECONDITION(CheckCount(count)); + SS_POSTCONDITION(SizeToCount(RETVAL) == count); + NOTHROW; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + SS_RETURN (count+1) << GetCharacterSizeShift(); +} + +//---------------------------------------------------------------------------- +// Private helper. +// Return the maxmimum count of characters that could fit in a buffer of +// 'size' bytes in the given representation. +// 'size' includes the null terminator, but the RETURN value does not. +//---------------------------------------------------------------------------- +inline COUNT_T SString::SizeToCount(COUNT_T size) const +{ + SS_CONTRACT(COUNT_T) + { + GC_NOTRIGGER; + PRECONDITION(CheckSize(size)); + SS_POSTCONDITION(CountToSize(RETVAL) == size); + NOTHROW; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + SS_RETURN (size >> GetCharacterSizeShift()) - 1; +} + +//---------------------------------------------------------------------------- +// Private helper. +// Return the maxmimum count of characters that could fit in the current +// buffer including NULL terminator. +//---------------------------------------------------------------------------- +inline COUNT_T SString::GetBufferSizeInCharIncludeNullChar() const +{ + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_SUPPORTS_DAC; + + return (GetSize() >> GetCharacterSizeShift()); +} + + + +//---------------------------------------------------------------------------- +// Assert helper +// Asser that the iterator is within the given string. +//---------------------------------------------------------------------------- +inline CHECK SString::CheckIteratorRange(const CIterator &i) const +{ + CANNOT_HAVE_CONTRACT; + CHECK(i >= Begin()); + CHECK(i <= End()); // Note that it's OK to look at the terminating null + CHECK_OK; +} + +//---------------------------------------------------------------------------- +// Assert helper +// Asser that the iterator is within the given string. +//---------------------------------------------------------------------------- +inline CHECK SString::CheckIteratorRange(const CIterator &i, COUNT_T length) const +{ + CANNOT_HAVE_CONTRACT; + CHECK(i >= Begin()); + CHECK(i + length <= End()); // Note that it's OK to look at the terminating null + CHECK_OK; +} + +//---------------------------------------------------------------------------- +// Assert that the string is empty +//---------------------------------------------------------------------------- +inline CHECK SString::CheckEmpty() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(IsEmpty()); + CHECK_OK; +} + +//---------------------------------------------------------------------------- +// Check the range of a count +//---------------------------------------------------------------------------- +inline CHECK SString::CheckCount(COUNT_T count) +{ + CANNOT_HAVE_CONTRACT; + CHECK(CheckSize(count*sizeof(WCHAR))); + CHECK_OK; +} + +//---------------------------------------------------------------------------- +// Check the representation field +//---------------------------------------------------------------------------- +inline CHECK SString::CheckRepresentation(int representation) +{ + CANNOT_HAVE_CONTRACT; + CHECK(representation == REPRESENTATION_EMPTY + || representation == REPRESENTATION_UNICODE + || representation == REPRESENTATION_ASCII + || representation == REPRESENTATION_UTF8 + || representation == REPRESENTATION_ANSI); + CHECK((representation & REPRESENTATION_MASK) == representation); + + CHECK_OK; +} + +#if CHECK_INVARIANTS +//---------------------------------------------------------------------------- +// Assert helper. Check that the string only uses the ASCII subset of +// codes. +//---------------------------------------------------------------------------- +inline CHECK SString::CheckASCIIString(const CHAR *string) +{ + CANNOT_HAVE_CONTRACT; + if (string != NULL) + CHECK(CheckASCIIString(string, (int) strlen(string))); + CHECK_OK; +} + +inline CHECK SString::CheckASCIIString(const CHAR *string, COUNT_T count) +{ + CANNOT_HAVE_CONTRACT; +#if _DEBUG + const CHAR *sEnd = string + count; + while (string < sEnd) + { + CHECK_MSG((*string & 0x80) == 0x00, "Found non-ASCII character in string."); + string++; + } +#endif + CHECK_OK; +} + +//---------------------------------------------------------------------------- +// Check routine and invariants. +//---------------------------------------------------------------------------- + +inline CHECK SString::Check() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::Check()); + CHECK_OK; +} + +inline CHECK SString::Invariant() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::Invariant()); + CHECK_OK; +} + +inline CHECK SString::InternalInvariant() const +{ + CANNOT_HAVE_CONTRACT; + CHECK(SBuffer::InternalInvariant()); + CHECK(SBuffer::GetSize() >= 2); + if (IsNormalized()) + CHECK(IsRepresentation(REPRESENTATION_UNICODE)); + CHECK_OK; +} +#endif // CHECK_INVARIANTS + +//---------------------------------------------------------------------------- +// Return a writeable buffer that can store 'countChars'+1 unicode characters. +// Call CloseBuffer when done. +//---------------------------------------------------------------------------- +inline WCHAR *SString::OpenUnicodeBuffer(COUNT_T countChars) +{ + SS_CONTRACT(WCHAR*) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckCount(countChars)); +#if _DEBUG + SS_POSTCONDITION(IsBufferOpen()); +#endif + SS_POSTCONDITION(GetRawCount() == countChars); + SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UNICODE || countChars == 0); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + OpenBuffer(REPRESENTATION_UNICODE, countChars); + SS_RETURN GetRawUnicode(); +} + +//---------------------------------------------------------------------------- +// Return a copy of the underlying buffer, the caller is responsible for managing +// the returned memory +//---------------------------------------------------------------------------- +inline WCHAR *SString::GetCopyOfUnicodeString() +{ + SS_CONTRACT(WCHAR*) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckPointer(buffer)); + THROWS; + } + SS_CONTRACT_END; + NewArrayHolder buffer = NULL; + + buffer = new WCHAR[GetCount() +1]; + wcscpy_s(buffer, GetCount() + 1, GetUnicode()); + + SS_RETURN buffer.Extract(); +} + +//---------------------------------------------------------------------------- +// Return a writeable buffer that can store 'countChars'+1 ansi characters. +// Call CloseBuffer when done. +//---------------------------------------------------------------------------- +inline ANSI *SString::OpenANSIBuffer(COUNT_T countChars) +{ + SS_CONTRACT(ANSI*) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckCount(countChars)); +#if _DEBUG + SS_POSTCONDITION(IsBufferOpen()); +#endif + SS_POSTCONDITION(GetRawCount() == countChars); + SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_ANSI || countChars == 0); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + OpenBuffer(REPRESENTATION_ANSI, countChars); + SS_RETURN GetRawANSI(); +} + +//---------------------------------------------------------------------------- +// Return a writeable buffer that can store 'countChars'+1 ansi characters. +// Call CloseBuffer when done. +//---------------------------------------------------------------------------- +inline UTF8 *SString::OpenUTF8Buffer(COUNT_T countBytes) +{ + SS_CONTRACT(UTF8*) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION(CheckCount(countBytes)); +#if _DEBUG + SS_POSTCONDITION(IsBufferOpen()); +#endif + SS_POSTCONDITION(GetRawCount() == countBytes); + SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UTF8 || countBytes == 0); + SS_POSTCONDITION(CheckPointer(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + OpenBuffer(REPRESENTATION_UTF8, countBytes); + SS_RETURN GetRawUTF8(); +} + +//---------------------------------------------------------------------------- +// Private helper to open a raw buffer. +// Called by public functions to open the buffer in the specific +// representation. +// While the buffer is opened, all other operations are illegal. Call +// CloseBuffer() when done. +//---------------------------------------------------------------------------- +inline void SString::OpenBuffer(SString::Representation representation, COUNT_T countChars) +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + PRECONDITION_MSG(!IsBufferOpen(), "Can't nest calls to OpenBuffer()"); + PRECONDITION(CheckRepresentation(representation)); + PRECONDITION(CheckSize(countChars)); +#if _DEBUG + POSTCONDITION(IsBufferOpen()); +#endif + POSTCONDITION(GetRawCount() == countChars); + POSTCONDITION(GetRepresentation() == representation || countChars == 0); + THROWS; + } + CONTRACT_END; +#else + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_THROWS; +#endif + + Resize(countChars, representation); + + SBuffer::OpenRawBuffer(CountToSize(countChars)); + + SS_RETURN; +} + +//---------------------------------------------------------------------------- +// Get the max size that can be passed to OpenUnicodeBuffer without causing +// allocations. +//---------------------------------------------------------------------------- +inline COUNT_T SString::GetUnicodeAllocation() +{ + CONTRACTL + { + INSTANCE_CHECK; + NOTHROW; + GC_NOTRIGGER; + } + CONTRACTL_END; + + COUNT_T allocation = GetAllocation(); + return ( (allocation > sizeof(WCHAR)) + ? (allocation - sizeof(WCHAR)) / sizeof(WCHAR) : 0 ); +} + +//---------------------------------------------------------------------------- +// Close an open buffer. Assumes that we wrote exactly number of characters +// we requested in OpenBuffer. +//---------------------------------------------------------------------------- +inline void SString::CloseBuffer() +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; +#if _DEBUG + PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); +#endif + SS_POSTCONDITION(CheckPointer(this)); + THROWS; + } + SS_CONTRACT_END; + + SBuffer::CloseRawBuffer(); + NullTerminate(); + + SS_RETURN; +} + +//---------------------------------------------------------------------------- +// CloseBuffer() tells the SString that we're done using the unsafe buffer. +// countChars is the count of characters actually used (so we can set m_count). +// This is important if we request a buffer larger than what we actually +// used. +//---------------------------------------------------------------------------- +inline void SString::CloseBuffer(COUNT_T finalCount) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; +#if _DEBUG + PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); +#endif + PRECONDITION(CheckSize(finalCount)); + SS_POSTCONDITION(CheckPointer(this)); + SS_POSTCONDITION(GetRawCount() == finalCount); + THROWS; + } + SS_CONTRACT_END; + + SBuffer::CloseRawBuffer(CountToSize(finalCount)); + NullTerminate(); + + SS_RETURN; +} + +//---------------------------------------------------------------------------- +// EnsureWritable +// Ensures that the buffer is writable +//---------------------------------------------------------------------------- +inline void SString::EnsureWritable() const +{ +#ifdef SSTRING_EXTRA_CHECKS + CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + POSTCONDITION(!IsLiteral()); + THROWS; + } + CONTRACT_END; +#else //SSTRING_EXTRA_CHECKS + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_THROWS; +#endif //SSTRING_EXTRA_CHECKS + + if (IsLiteral()) + const_cast(this)->Resize(GetRawCount(), GetRepresentation(), PRESERVE); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Convert the internal representation to be a fixed size +//----------------------------------------------------------------------------- +inline void SString::ConvertToFixed() const +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + SS_PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(IsFixedSize()); + THROWS_UNLESS_NORMALIZED; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + // If we're already fixed size, great. + if (IsFixedSize()) + SS_RETURN; + + // See if we can coerce it to ASCII. + if (ScanASCII()) + SS_RETURN; + + // Convert to unicode then. + ConvertToUnicode(); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Convert the internal representation to be an iteratable one (current +// requirements here are that it be trivially convertable to unicode chars.) +//----------------------------------------------------------------------------- +inline void SString::ConvertToIteratable() const +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + SS_PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(IsIteratable()); + THROWS_UNLESS_NORMALIZED; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + // If we're already iteratable, great. + if (IsIteratable()) + SS_RETURN; + + // See if we can coerce it to ASCII. + if (ScanASCII()) + SS_RETURN; + + // Convert to unicode then. + ConvertToUnicode(); + + SS_RETURN; +} + +//----------------------------------------------------------------------------- +// Create iterators on the string. +//----------------------------------------------------------------------------- + +inline SString::UIterator SString::BeginUnicode() +{ + SS_CONTRACT(SString::UIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + ConvertToUnicode(); + EnsureWritable(); + + SS_RETURN UIterator(this, 0); +} + +inline SString::UIterator SString::EndUnicode() +{ + SS_CONTRACT(SString::UIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + ConvertToUnicode(); + EnsureWritable(); + + SS_RETURN UIterator(this, GetCount()); +} + +//----------------------------------------------------------------------------- +// Create CIterators on the string. +//----------------------------------------------------------------------------- + +FORCEINLINE SString::CIterator SString::Begin() const +{ + SS_CONTRACT(SString::CIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS_UNLESS_NORMALIZED; + } + SS_CONTRACT_END; + + ConvertToIteratable(); + + SS_RETURN CIterator(this, 0); +} + +FORCEINLINE SString::CIterator SString::End() const +{ + SS_CONTRACT(SString::CIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS_UNLESS_NORMALIZED; + } + SS_CONTRACT_END; + + ConvertToIteratable(); + + SS_RETURN CIterator(this, GetCount()); +} + +//----------------------------------------------------------------------------- +// Create Iterators on the string. +//----------------------------------------------------------------------------- + +FORCEINLINE SString::Iterator SString::Begin() +{ + SS_CONTRACT(SString::Iterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; // EnsureMutable always throws + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + ConvertToIteratable(); + EnsureMutable(); + + SS_RETURN Iterator(this, 0); +} + +FORCEINLINE SString::Iterator SString::End() +{ + SS_CONTRACT(SString::Iterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; // EnsureMutable always Throws + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + ConvertToIteratable(); + EnsureMutable(); + + SS_RETURN Iterator(this, GetCount()); +} + +//----------------------------------------------------------------------------- +// CIterator support routines +//----------------------------------------------------------------------------- + +inline SString::Index::Index() +{ + LIMITED_METHOD_CONTRACT; +} + +inline SString::Index::Index(SString *string, SCOUNT_T index) + : SBuffer::Index(string, index<GetCharacterSizeShift()) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(string)); + PRECONDITION(string->IsIteratable()); + PRECONDITION(DoCheck(0)); + SS_POSTCONDITION(CheckPointer(this)); + // POSTCONDITION(Subtract(string->Begin()) == index); contract violation - fix later + NOTHROW; + CANNOT_TAKE_LOCK; + SUPPORTS_DAC; + } + SS_CONTRACT_END; + + m_characterSizeShift = string->GetCharacterSizeShift(); + + SS_RETURN; +} + +inline BYTE &SString::Index::GetAt(SCOUNT_T delta) const +{ + LIMITED_METHOD_DAC_CONTRACT; + + return m_ptr[delta<>m_characterSizeShift); +} + +inline CHECK SString::Index::DoCheck(SCOUNT_T delta) const +{ + CANNOT_HAVE_CONTRACT; +#if _DEBUG + const SString *string = (const SString *) GetContainerDebug(); + + CHECK(m_ptr + (delta<= string->m_buffer); + CHECK(m_ptr + (delta<m_buffer + string->GetSize()); +#endif + CHECK_OK; +} + +inline void SString::Index::Resync(const SString *string, BYTE *ptr) const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + SBuffer::Index::Resync(string, ptr); + + const_cast(this)->m_characterSizeShift = string->GetCharacterSizeShift(); +} + + +inline const WCHAR *SString::Index::GetUnicode() const +{ + LIMITED_METHOD_CONTRACT; + + return (const WCHAR *) m_ptr; +} + +inline const CHAR *SString::Index::GetASCII() const +{ + LIMITED_METHOD_CONTRACT; + + return (const CHAR *) m_ptr; +} + +inline WCHAR SString::Index::operator*() const +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + + if (m_characterSizeShift == 0) + return *(CHAR*)&GetAt(0); + else + return *(WCHAR*)&GetAt(0); +} + +inline void SString::Index::operator->() const +{ + LIMITED_METHOD_CONTRACT; +} + +inline WCHAR SString::Index::operator[](int index) const +{ + WRAPPER_NO_CONTRACT; + + if (m_characterSizeShift == 0) + return *(CHAR*)&GetAt(index); + else + return *(WCHAR*)&GetAt(index); +} + +//----------------------------------------------------------------------------- +// Iterator support routines +//----------------------------------------------------------------------------- + +inline SString::UIndex::UIndex() +{ + LIMITED_METHOD_CONTRACT; +} + +inline SString::UIndex::UIndex(SString *string, SCOUNT_T index) + : SBuffer::Index(string, index*sizeof(WCHAR)) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(string)); + PRECONDITION(string->IsRepresentation(REPRESENTATION_UNICODE)); + PRECONDITION(DoCheck(0)); + SS_POSTCONDITION(CheckPointer(this)); + NOTHROW; + CANNOT_TAKE_LOCK; + } + SS_CONTRACT_END; + + SS_RETURN; +} + +inline WCHAR &SString::UIndex::GetAt(SCOUNT_T delta) const +{ + LIMITED_METHOD_CONTRACT; + + return ((WCHAR*)m_ptr)[delta]; +} + +inline void SString::UIndex::Skip(SCOUNT_T delta) +{ + LIMITED_METHOD_CONTRACT; + + m_ptr += delta * sizeof(WCHAR); +} + +inline SCOUNT_T SString::UIndex::Subtract(const UIndex &i) const +{ + WRAPPER_NO_CONTRACT; + + return (SCOUNT_T) (GetUnicode() - i.GetUnicode()); +} + +inline CHECK SString::UIndex::DoCheck(SCOUNT_T delta) const +{ + CANNOT_HAVE_CONTRACT; +#if _DEBUG + const SString *string = (const SString *) GetContainerDebug(); + + CHECK(GetUnicode() + delta >= string->GetRawUnicode()); + CHECK(GetUnicode() + delta <= string->GetRawUnicode() + string->GetCount()); +#endif + + CHECK_OK; +} + +inline WCHAR *SString::UIndex::GetUnicode() const +{ + LIMITED_METHOD_CONTRACT; + + return (WCHAR*) m_ptr; +} + +//----------------------------------------------------------------------------- +// Opaque scratch buffer class routines +//----------------------------------------------------------------------------- +inline SString::AbstractScratchBuffer::AbstractScratchBuffer(void *buffer, COUNT_T size) + : SString(buffer, size) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(buffer)); + PRECONDITION(CheckCount(size)); + NOTHROW; + } + SS_CONTRACT_END; + + SS_RETURN; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif // _MSC_VER + +#endif // _SSTRING_INL_ diff --git a/lib/coreclr/src/inc/stack.h b/lib/coreclr/src/inc/stack.h new file mode 100644 index 0000000000..589f8f7766 --- /dev/null +++ b/lib/coreclr/src/inc/stack.h @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// This is a generic growable stack of T. + +#ifndef GENERIC_STACK_H +#define GENERIC_STACK_H 1 + +#include + +template +class Stack +{ + T* m_elems; + unsigned m_elemsSize; + unsigned m_elemsCount; + + static const unsigned InitSize = 8; + + void GrowForPush() + { + if (m_elemsCount == m_elemsSize) + { + m_elemsSize = max(InitSize, 2*m_elemsSize); + T* newElems = new T[m_elemsSize]; + if (m_elemsCount != 0) + { + _ASSERTE(m_elems != NULL); + for (unsigned k = 0; k < m_elemsCount; k++) newElems[k] = m_elems[k]; + delete[] m_elems; + } + m_elems = newElems; + } + } + + public: + Stack(unsigned sz = 0) : m_elems(NULL), m_elemsSize(sz), m_elemsCount(0) + { + if (sz > 0) + { + m_elems = new T[sz]; + } + } + + ~Stack() + { + if (m_elems != NULL) delete[] m_elems; + } + + void Push(T t) + { + GrowForPush(); + m_elems[m_elemsCount] = t; + m_elemsCount++; + } + + bool IsEmpty() + { + return m_elemsCount == 0; + } + + T Pop() + { + _ASSERTE(m_elemsCount > 0); + m_elemsCount--; + return m_elems[m_elemsCount]; + } + + T Peek() + { + _ASSERTE(m_elemsCount > 0); + return m_elems[m_elemsCount-1]; + } + + // Caller should take care to only side-effect the return reference if he/she is *sure* + // that the stack will not be popped in the interim! + T& PeekRef() + { + _ASSERTE(m_elemsCount > 0); + return m_elems[m_elemsCount-1]; + } +}; + +#endif // GENERIC_STACK_H diff --git a/lib/coreclr/src/inc/stackframe.h b/lib/coreclr/src/inc/stackframe.h new file mode 100644 index 0000000000..940951de31 --- /dev/null +++ b/lib/coreclr/src/inc/stackframe.h @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __STACKFRAME_H +#define __STACKFRAME_H + +#include "regdisp.h" + + +struct StackFrame +{ + const static UINT_PTR maxVal = (UINT_PTR)(INT_PTR)-1; + StackFrame() : SP(NULL) + { + } + + StackFrame(UINT_PTR sp) + { + SP = sp; + } + + void Clear() + { + SP = NULL; + } + + void SetMaxVal() + { + SP = maxVal; + } + + bool IsNull() + { + return (SP == NULL); + } + + bool IsMaxVal() + { + return (SP == maxVal); + } + + bool operator==(StackFrame sf) + { + return (SP == sf.SP); + } + + bool operator!=(StackFrame sf) + { + return (SP != sf.SP); + } + + bool operator<(StackFrame sf) + { + return (SP < sf.SP); + } + + bool operator<=(StackFrame sf) + { + return (SP <= sf.SP); + } + + bool operator>(StackFrame sf) + { + return (SP > sf.SP); + } + + bool operator>=(StackFrame sf) + { + return (SP >= sf.SP); + } + + static inline StackFrame FromEstablisherFrame(UINT_PTR EstablisherFrame) + { + return StackFrame(EstablisherFrame); + } + + static inline StackFrame FromRegDisplay(REGDISPLAY* pRD) + { + return StackFrame(GetRegdisplaySP(pRD)); + } + + UINT_PTR SP; +}; + + +//--------------------------------------------------------------------------------------- +// +// On WIN64, all the stack range tracking done by the Exception Handling (EH) subsystem is based on the +// establisher frame given by the OS. On IA64, the establisher frame is the caller SP and the current BSP. +// On X64, it is the initial SP before any dynamic stack allocation, i.e. it is the SP when a function exits +// the prolog. The EH subsystem uses the same format. +// +// The stackwalker needs to get information from the EH subsystem in order to skip funclets. Unfortunately, +// stackwalking is based on the current SP, i.e. the SP when the control flow leaves a function via a +// function call. Thus, for stack frames with dynamic stack allocations on X64, the SP values used by the +// stackwalker and the EH subsystem don't match. +// +// To work around this problem, we need to somehow bridge the different SP values. We do so by using the +// caller SP instead of the current SP for comparisons during a stackwalk on X64. Creating a new type +// explicitly spells out the important distinction that this is NOT in the same format as the +// OS establisher frame. +// +// Notes: +// In the long term, we should look at merging the two SP formats and have one consistent abstraction. +// + +struct CallerStackFrame : StackFrame +{ + CallerStackFrame() : StackFrame() + { + } + + CallerStackFrame(UINT_PTR sp) : StackFrame(sp) + { + } + +#ifdef WIN64EXCEPTIONS + static inline CallerStackFrame FromRegDisplay(REGDISPLAY* pRD) + { + _ASSERTE(pRD->IsCallerSPValid || pRD->IsCallerContextValid); + return CallerStackFrame(GetSP(pRD->pCallerContext)); + } +#endif // WIN64EXCEPTIONS +}; + +#endif // __STACKFRAME_H diff --git a/lib/coreclr/src/inc/stacktrace.h b/lib/coreclr/src/inc/stacktrace.h new file mode 100644 index 0000000000..9152116d39 --- /dev/null +++ b/lib/coreclr/src/inc/stacktrace.h @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +#ifndef __STACK_TRACE_H__ +#define __STACK_TRACE_H__ + +HINSTANCE LoadImageHlp(); +HINSTANCE LoadDbgHelp(); + +#include + +// +//--- Constants --------------------------------------------------------------- +// + +#define cchMaxAssertModuleLen 60 +#define cchMaxAssertSymbolLen 257 +#define cfrMaxAssertStackLevels 20 +#define cchMaxAssertExprLen 257 + +#ifdef _WIN64 + +#define cchMaxAssertStackLevelStringLen \ + ((3 * 8) + cchMaxAssertModuleLen + cchMaxAssertSymbolLen + 13) + // 3 addresses of at most 8 char, module, symbol, and the extra chars: + // 0x
: ! + 0x\n + //FMT_ADDR_BARE is defined as "%08x`%08x" on Win64, and as + //"%08x" on 32 bit platforms. Hence the difference in the definitions. + +#else + +#define cchMaxAssertStackLevelStringLen \ + ((2 * 8) + cchMaxAssertModuleLen + cchMaxAssertSymbolLen + 12) + // 2 addresses of at most 8 char, module, symbol, and the extra chars: + // 0x
: ! + 0x\n + +#endif + +// +//--- Prototypes -------------------------------------------------------------- +// + +/**************************************************************************** +* MagicDeinit * +*-------------* +* Description: +* Cleans up for the symbol loading code. Should be called before +* exiting in order to free the dynamically loaded imagehlp.dll +******************************************************************** robch */ +void MagicDeinit(void); + +/**************************************************************************** +* GetStringFromStackLevels * +*--------------------------* +* Description: +* Retrieves a string from the stack frame. If more than one frame, they +* are separated by newlines. Each fram appears in this format: +* +* 0x
: ! + 0x +******************************************************************** robch */ +void GetStringFromStackLevels(UINT ifrStart, UINT cfrTotal, __out_ecount(cchMaxAssertStackLevelStringLen * cfrTotal) CHAR *pszString, struct _CONTEXT * pContext = NULL); + +/**************************************************************************** +* GetStringFromAddr * +*-------------------* +* Description: +* Builds a string from an address in the format: +* +* 0x
: ! + 0x +******************************************************************** robch */ +void GetStringFromAddr(DWORD_PTR dwAddr, __out_ecount(cchMaxAssertStackLevelStringLen) LPSTR szString); + +#if defined(_TARGET_X86_) && !defined(FEATURE_PAL) +/**************************************************************************** +* ClrCaptureContext * +*-------------------* +* Description: +* Exactly the contents of RtlCaptureContext for Win7 - Win2K doesn't +* support this, so we need it for CoreCLR 4, if we require Win2K support +****************************************************************************/ +extern "C" void __stdcall ClrCaptureContext(__out PCONTEXT ctx); +#else // _TARGET_X86_ && !FEATURE_PAL +#define ClrCaptureContext RtlCaptureContext +#endif // _TARGET_X86_ && !FEATURE_PAL + + +#endif diff --git a/lib/coreclr/src/inc/static_assert.h b/lib/coreclr/src/inc/static_assert.h new file mode 100644 index 0000000000..e635d70f9e --- /dev/null +++ b/lib/coreclr/src/inc/static_assert.h @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// static_assert.h +// +// Static assertion infrastructure +// --------------------------------------------------------------------------- + +//-------------------------------------------------------------------------------- +// static_assert represents a check which should be made at compile time. It +// can only be done on a constant expression. +//-------------------------------------------------------------------------------- + +#ifndef __STATIC_ASSERT_H__ +#define __STATIC_ASSERT_H__ + +// static_assert( cond, msg ) is now a compiler-supported intrinsic in Dev10 C++ compiler. +// Replaces previous uses of STATIC_ASSERT_MSG and COMPILE_TIME_ASSERT_MSG. + +// Replaces previous uses of CPP_ASSERT +#define static_assert_n( n, cond ) static_assert( cond, #cond ) + +// Replaces previous uses of C_ASSERT and COMPILE_TIME_ASSERT +#define static_assert_no_msg( cond ) static_assert( cond, #cond ) + +#endif // __STATIC_ASSERT_H__ + diff --git a/lib/coreclr/src/inc/staticcontract.h b/lib/coreclr/src/inc/staticcontract.h new file mode 100644 index 0000000000..4cf7f4a92a --- /dev/null +++ b/lib/coreclr/src/inc/staticcontract.h @@ -0,0 +1,359 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// --------------------------------------------------------------------------- +// StaticContract.h +// --------------------------------------------------------------------------- + + +#ifndef __STATIC_CONTRACT_H_ +#define __STATIC_CONTRACT_H_ + +// Make sure we have the WCHAR defines available. +#include "palclr.h" + +#define SCAN_WIDEN2(x) L ## x +#define SCAN_WIDEN(x) SCAN_WIDEN2(x) + +#ifndef NOINLINE +#if __GNUC__ +#define NOINLINE __attribute__((noinline)) +#else +#define NOINLINE __declspec(noinline) +#endif +#endif + +// +// PDB annotations for the static contract analysis tool. These are seperated +// from Contract.h to allow their inclusion in any part of the system. +// + +#if defined(_DEBUG) && defined(_TARGET_X86_) +#define METHOD_CANNOT_BE_FOLDED_DEBUG \ + static int _noFold = 0; \ + _noFold++; +#else +#define METHOD_CANNOT_BE_FOLDED_DEBUG +#endif + +#ifdef _TARGET_X86_ + +// +// currently, only x86 has a static contract analysis tool, so let's not +// bloat the PDBs of all the other architectures too.. +// +#define ANNOTATION_TRY_BEGIN __annotation(W("TRY_BEGIN")) +#define ANNOTATION_TRY_END __annotation(W("TRY_END")) +#define ANNOTATION_HANDLER_BEGIN __annotation(W("HANDLER_BEGIN")) +#define ANNOTATION_HANDLER_END __annotation(W("HANDLER_END")) +#define ANNOTATION_NOTHROW __annotation(W("NOTHROW")) +#define ANNOTATION_CANNOT_TAKE_LOCK __annotation(W("CANNOT_TAKE_LOCK")) +#define ANNOTATION_WRAPPER __annotation(W("WRAPPER")) +#define ANNOTATION_FAULT __annotation(W("FAULT")) +#define ANNOTATION_FORBID_FAULT __annotation(W("FORBID_FAULT")) +#define ANNOTATION_COOPERATIVE __annotation(W("MODE_COOPERATIVE")) +#define ANNOTATION_MODE_COOPERATIVE __annotation(W("MODE_PREEMPTIVE")) +#define ANNOTATION_MODE_ANY __annotation(W("MODE_ANY")) +#define ANNOTATION_GC_TRIGGERS __annotation(W("GC_TRIGGERS")) +#define ANNOTATION_IGNORE_THROW __annotation(W("THROWS"), W("NOTHROW"), W("CONDITIONAL_EXEMPT")) +#define ANNOTATION_IGNORE_LOCK __annotation(W("CAN_TAKE_LOCK"), W("CANNOT_TAKE_LOCK"), W("CONDITIONAL_EXEMPT")) +#define ANNOTATION_IGNORE_FAULT __annotation(W("FAULT"), W("FORBID_FAULT"), W("CONDITIONAL_EXEMPT")) +#define ANNOTATION_IGNORE_TRIGGER __annotation(W("GC_TRIGGERS"), W("GC_NOTRIGGER"), W("CONDITIONAL_EXEMPT")) +#define ANNOTATION_VIOLATION(violationmask) __annotation(W("VIOLATION(") L#violationmask W(")")) +#define ANNOTATION_UNCHECKED(thecheck) __annotation(W("UNCHECKED(") L#thecheck W(")")) + +#define ANNOTATION_MARK_BLOCK_ANNOTATION __annotation(W("MARK")) +#define ANNOTATION_USE_BLOCK_ANNOTATION __annotation(W("USE")) +#define ANNOTATION_END_USE_BLOCK_ANNOTATION __annotation(W("END_USE")) + +// here is the plan: +// +// a special holder which implements a violation +// + +#define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN __annotation(W("SPECIAL_HOLDER_BEGIN ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_SPECIAL_HOLDER_END __annotation(W("SPECIAL_HOLDER_END")) +#define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT __annotation(W("SPECIAL_HOLDER_DYNAMIC")) + +#define ANNOTATION_SO_PROBE_BEGIN(probeAmount) __annotation(W("SO_PROBE_BEGIN(") L#probeAmount W(")")) +#define ANNOTATION_SO_PROBE_END __annotation(W("SO_PROBE_END")) + +// +// these annotations are all function-name qualified +// +#define ANNOTATION_FN_LEAF __annotation(W("LEAF ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_WRAPPER __annotation(W("WRAPPER ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_THROWS __annotation(W("THROWS ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_NOTHROW __annotation(W("NOTHROW ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_CAN_TAKE_LOCK __annotation(W("CAN_TAKE_LOCK ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_CANNOT_TAKE_LOCK __annotation(W("CANNOT_TAKE_LOCK ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_FAULT __annotation(W("FAULT ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_FORBID_FAULT __annotation(W("FORBID_FAULT ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_GC_TRIGGERS __annotation(W("GC_TRIGGERS ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_GC_NOTRIGGER __annotation(W("GC_NOTRIGGER ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_MODE_COOPERATIVE __annotation(W("MODE_COOPERATIVE ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_MODE_PREEMPTIVE __annotation(W("MODE_PREEMPTIVE ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_MODE_ANY __annotation(W("MODE_ANY ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_HOST_NOCALLS __annotation(W("HOST_NOCALLS ") SCAN_WIDEN(__FUNCTION__)) +#define ANNOTATION_FN_HOST_CALLS __annotation(W("HOST_CALLS ") SCAN_WIDEN(__FUNCTION__)) + +#define ANNOTATION_ENTRY_POINT __annotation(W("SO_EP ") SCAN_WIDEN(__FUNCTION__)) + + +// for DacCop +#define ANNOTATION_SUPPORTS_DAC __annotation(W("SUPPORTS_DAC")) +#define ANNOTATION_SUPPORTS_DAC_HOST_ONLY __annotation(W("SUPPORTS_DAC_HOST_ONLY")) + +#ifdef _DEBUG +// @todo : put correct annotation in and fixup the static analysis tool +// This is used to flag debug-only functions that we want to ignore in our static analysis +#define ANNOTATION_DEBUG_ONLY __annotation(W("DBG_ONLY")) + +#endif + +#else // _TARGET_X86_ + +#define ANNOTATION_TRY_BEGIN { } +#define ANNOTATION_TRY_END { } +#define ANNOTATION_HANDLER_BEGIN { } +#define ANNOTATION_HANDLER_END { } +#define ANNOTATION_NOTHROW { } +#define ANNOTATION_CANNOT_TAKE_LOCK { } +#define ANNOTATION_WRAPPER { } +#define ANNOTATION_FAULT { } +#define ANNOTATION_FORBID_FAULT { } +#define ANNOTATION_COOPERATIVE { } +#define ANNOTATION_MODE_COOPERATIVE { } +#define ANNOTATION_MODE_ANY { } +#define ANNOTATION_GC_TRIGGERS { } +#define ANNOTATION_IGNORE_THROW { } +#define ANNOTATION_IGNORE_LOCK { } +#define ANNOTATION_IGNORE_FAULT { } +#define ANNOTATION_IGNORE_TRIGGER { } +#define ANNOTATION_VIOLATION(violationmask) { } +#define ANNOTATION_UNCHECKED(thecheck) { } + +#define ANNOTATION_TRY_MARKER { } +#define ANNOTATION_CATCH_MARKER { } + +#define ANNOTATION_FN_HOST_NOCALLS { } +#define ANNOTATION_FN_HOST_CALLS { } + +#define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN { } +#define ANNOTATION_SPECIAL_HOLDER_END { } +#define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT { } + +#define ANNOTATION_FN_LEAF { } +#define ANNOTATION_FN_WRAPPER { } +#define ANNOTATION_FN_THROWS { } +#define ANNOTATION_FN_NOTHROW { } +#define ANNOTATION_FN_CAN_TAKE_LOCK { } +#define ANNOTATION_FN_CANNOT_TAKE_LOCK { } +#define ANNOTATION_FN_FAULT { } +#define ANNOTATION_FN_FORBID_FAULT { } +#define ANNOTATION_FN_GC_TRIGGERS { } +#define ANNOTATION_FN_GC_NOTRIGGER { } +#define ANNOTATION_FN_MODE_COOPERATIVE { } +#define ANNOTATION_FN_MODE_PREEMPTIVE { } +#define ANNOTATION_FN_MODE_ANY { } +#define ANNOTATION_FN_HOST_NOCALLS { } +#define ANNOTATION_FN_HOST_CALLS { } + +#define ANNOTATION_SUPPORTS_DAC { } +#define ANNOTATION_SUPPORTS_DAC_HOST_ONLY { } + +#define ANNOTATION_SO_PROBE_BEGIN(probeAmount) { } +#define ANNOTATION_SO_PROBE_END { } + +#define ANNOTATION_ENTRY_POINT { } +#ifdef _DEBUG +#define ANNOTATION_DEBUG_ONLY { } +#endif + +#endif // _TARGET_X86_ + +#define STATIC_CONTRACT_THROWS ANNOTATION_FN_THROWS +#define STATIC_CONTRACT_NOTHROW ANNOTATION_FN_NOTHROW +#define STATIC_CONTRACT_CAN_TAKE_LOCK ANNOTATION_FN_CAN_TAKE_LOCK +#define STATIC_CONTRACT_CANNOT_TAKE_LOCK ANNOTATION_FN_CANNOT_TAKE_LOCK +#define STATIC_CONTRACT_FAULT ANNOTATION_FN_FAULT +#define STATIC_CONTRACT_FORBID_FAULT ANNOTATION_FN_FORBID_FAULT +#define STATIC_CONTRACT_GC_TRIGGERS ANNOTATION_FN_GC_TRIGGERS +#define STATIC_CONTRACT_GC_NOTRIGGER ANNOTATION_FN_GC_NOTRIGGER +#define STATIC_CONTRACT_HOST_NOCALLS ANNOTATION_FN_HOST_NOCALLS +#define STATIC_CONTRACT_HOST_CALLS ANNOTATION_FN_HOST_CALLS + +#define STATIC_CONTRACT_SUPPORTS_DAC ANNOTATION_SUPPORTS_DAC +#define STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY ANNOTATION_SUPPORTS_DAC_HOST_ONLY + +#define STATIC_CONTRACT_MODE_COOPERATIVE ANNOTATION_FN_MODE_COOPERATIVE +#define STATIC_CONTRACT_MODE_PREEMPTIVE ANNOTATION_FN_MODE_PREEMPTIVE +#define STATIC_CONTRACT_MODE_ANY ANNOTATION_FN_MODE_ANY +#define STATIC_CONTRACT_LEAF ANNOTATION_FN_LEAF +#define STATIC_CONTRACT_LIMITED_METHOD ANNOTATION_FN_LEAF +#define STATIC_CONTRACT_WRAPPER ANNOTATION_FN_WRAPPER + +#define STATIC_CONTRACT_ENTRY_POINT + +#ifdef _DEBUG +#define STATIC_CONTRACT_DEBUG_ONLY \ + ANNOTATION_DEBUG_ONLY; \ + STATIC_CONTRACT_CANNOT_TAKE_LOCK; \ + ANNOTATION_VIOLATION(TakesLockViolation); +#else +#define STATIC_CONTRACT_DEBUG_ONLY +#endif + +#define STATIC_CONTRACT_VIOLATION(mask) \ + ANNOTATION_VIOLATION(mask) + +#define SCAN_SCOPE_BEGIN \ + METHOD_CANNOT_BE_FOLDED_DEBUG; \ + ANNOTATION_FN_SPECIAL_HOLDER_BEGIN; + +#define SCAN_SCOPE_END \ + METHOD_CANNOT_BE_FOLDED_DEBUG; \ + ANNOTATION_SPECIAL_HOLDER_END; + +namespace StaticContract +{ + struct ScanThrowMarkerStandard + { + NOINLINE ScanThrowMarkerStandard() + { + METHOD_CANNOT_BE_FOLDED_DEBUG; + STATIC_CONTRACT_THROWS; + STATIC_CONTRACT_GC_NOTRIGGER; + } + + static void used() + { + } + }; + + struct ScanThrowMarkerTerminal + { + NOINLINE ScanThrowMarkerTerminal() + { + METHOD_CANNOT_BE_FOLDED_DEBUG; + } + + static void used() + { + } + }; + + struct ScanThrowMarkerIgnore + { + NOINLINE ScanThrowMarkerIgnore() + { + METHOD_CANNOT_BE_FOLDED_DEBUG; + } + + static void used() + { + } + }; +} +typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker; + +// This is used to annotate code as throwing a terminal exception, and should +// be used immediately before the throw so that infer that it can be inferred +// that the block in which this annotation appears throws unconditionally. +#define SCAN_THROW_MARKER do { ScanThrowMarker __throw_marker; } while (0) + +#define SCAN_IGNORE_THROW_MARKER \ + typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; if (0) ScanThrowMarker::used(); + +// Terminal exceptions are asynchronous and cannot be included in THROWS contract +// analysis. As such, this uses typedef to reassign the ScanThrowMarker to a +// non-annotating struct so that SCAN does not see the block as throwing. +#define STATIC_CONTRACT_THROWS_TERMINAL \ + typedef StaticContract::ScanThrowMarkerTerminal ScanThrowMarker; if (0) ScanThrowMarker::used(); + +#ifdef _MSC_VER +#define SCAN_IGNORE_THROW typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; ANNOTATION_IGNORE_THROW +#define SCAN_IGNORE_LOCK ANNOTATION_IGNORE_LOCK +#define SCAN_IGNORE_FAULT ANNOTATION_IGNORE_FAULT +#define SCAN_IGNORE_TRIGGER ANNOTATION_IGNORE_TRIGGER +#else +#define SCAN_IGNORE_THROW +#define SCAN_IGNORE_LOCK +#define SCAN_IGNORE_FAULT +#define SCAN_IGNORE_TRIGGER +#endif + + +// we use BlockMarker's only for SCAN +#if defined(_DEBUG) && defined(_TARGET_X86_) && !defined(DACCESS_COMPILE) + +template +class BlockMarker +{ +public: + NOINLINE void MarkBlock() + { + ANNOTATION_MARK_BLOCK_ANNOTATION; + METHOD_CANNOT_BE_FOLDED_DEBUG; + return; + } + + NOINLINE void UseMarkedBlockAnnotation() + { + ANNOTATION_USE_BLOCK_ANNOTATION; + METHOD_CANNOT_BE_FOLDED_DEBUG; + return; + } + + NOINLINE void EndUseMarkedBlockAnnotation() + { + ANNOTATION_END_USE_BLOCK_ANNOTATION; + METHOD_CANNOT_BE_FOLDED_DEBUG; + return; + } +}; + +#define SCAN_BLOCKMARKER() BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope +#define SCAN_BLOCKMARKER_MARK() __blockMarker_onlyOneAllowedPerScope.MarkBlock() +#define SCAN_BLOCKMARKER_USE() __blockMarker_onlyOneAllowedPerScope.UseMarkedBlockAnnotation() +#define SCAN_BLOCKMARKER_END_USE() __blockMarker_onlyOneAllowedPerScope.EndUseMarkedBlockAnnotation() + +#define SCAN_BLOCKMARKER_N(num) BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope##num +#define SCAN_BLOCKMARKER_MARK_N(num) __blockMarker_onlyOneAllowedPerScope##num.MarkBlock() +#define SCAN_BLOCKMARKER_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.UseMarkedBlockAnnotation() +#define SCAN_BLOCKMARKER_END_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.EndUseMarkedBlockAnnotation() + +#define SCAN_EHMARKER() BlockMarker<__COUNTER__> __marker_onlyOneAllowedPerScope +#define SCAN_EHMARKER_TRY() __annotation(W("SCOPE(BLOCK);SCAN_TRY_BEGIN")); __marker_onlyOneAllowedPerScope.MarkBlock() +#define SCAN_EHMARKER_END_TRY() __annotation(W("SCOPE(BLOCK);SCAN_TRY_END")) +#define SCAN_EHMARKER_CATCH() __marker_onlyOneAllowedPerScope.UseMarkedBlockAnnotation() +#define SCAN_EHMARKER_END_CATCH() __marker_onlyOneAllowedPerScope.EndUseMarkedBlockAnnotation() + +#else + +#define SCAN_BLOCKMARKER() +#define SCAN_BLOCKMARKER_MARK() +#define SCAN_BLOCKMARKER_USE() +#define SCAN_BLOCKMARKER_END_USE() + +#define SCAN_BLOCKMARKER_N(num) +#define SCAN_BLOCKMARKER_MARK_N(num) +#define SCAN_BLOCKMARKER_USE_N(num) +#define SCAN_BLOCKMARKER_END_USE_N(num) + +#define SCAN_EHMARKER() +#define SCAN_EHMARKER_TRY() +#define SCAN_EHMARKER_END_TRY() +#define SCAN_EHMARKER_CATCH() +#define SCAN_EHMARKER_END_CATCH() + +#endif + + +// +// @todo remove this... if there really are cases where a function just shouldn't have a contract, then perhaps +// we can add a more descriptive name for it... +// +#define CANNOT_HAVE_CONTRACT __annotation(W("NO_CONTRACT")) + +#endif // __STATIC_CONTRACT_H_ diff --git a/lib/coreclr/src/inc/stdmacros.h b/lib/coreclr/src/inc/stdmacros.h new file mode 100644 index 0000000000..6a7f286443 --- /dev/null +++ b/lib/coreclr/src/inc/stdmacros.h @@ -0,0 +1,360 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +// +// common.h - precompiled headers include for the COM+ Execution Engine +// + +// +// Make sure _ASSERTE is defined before including this header file +// Other than that, please keep this header self-contained so that it can be included in +// all dlls +// + + +#ifndef _stdmacros_h_ +#define _stdmacros_h_ + +#include "specstrings.h" +#include "contract.h" + +#ifndef _ASSERTE +#error Please define _ASSERTE before including StdMacros.h +#endif + +#ifdef _DEBUG +#define DEBUG_ARG(x) , x +#define DEBUG_ARG1(x) x +#else +#define DEBUG_ARG(x) +#define DEBUG_ARG1(x) +#endif + +#ifdef DACCESS_COMPILE +#define DAC_ARG(x) , x +#else +#define DAC_ARG(x) +#endif + + +/********************************************/ +/* Portability macros */ +/********************************************/ + +#ifdef _TARGET_AMD64_ +#define AMD64_FIRST_ARG(x) x , +#define AMD64_ARG(x) , x +#define AMD64_ONLY(x) x +#define NOT_AMD64(x) +#define NOT_AMD64_ARG(x) +#else +#define AMD64_FIRST_ARG(x) +#define AMD64_ARG(x) +#define AMD64_ONLY(x) +#define NOT_AMD64(x) x +#define NOT_AMD64_ARG(x) , x +#endif + +#ifdef _TARGET_X86_ +#define X86_FIRST_ARG(x) x , +#define X86_ARG(x) , x +#define X86_ONLY(x) x +#define NOT_X86(x) +#define NOT_X86_ARG(x) +#else +#define X86_FIRST_ARG(x) +#define X86_ARG(x) +#define X86_ONLY(x) +#define NOT_X86(x) x +#define NOT_X86_ARG(x) , x +#endif + +#ifdef _WIN64 +#define WIN64_ARG(x) , x +#define WIN64_ONLY(x) x +#define NOT_WIN64(x) +#define NOT_WIN64_ARG(x) +#else +#define WIN64_ARG(x) +#define WIN64_ONLY(x) +#define NOT_WIN64(x) x +#define NOT_WIN64_ARG(x) , x +#endif // _WIN64 + +#ifdef _TARGET_ARM_ +#define ARM_FIRST_ARG(x) x , +#define ARM_ARG(x) , x +#define ARM_ONLY(x) x +#define NOT_ARM(x) +#define NOT_ARM_ARG(x) +#else +#define ARM_FIRST_ARG(x) +#define ARM_ARG(x) +#define ARM_ONLY(x) +#define NOT_ARM(x) x +#define NOT_ARM_ARG(x) , x +#endif + +#ifdef _TARGET_ARM64_ +#define ARM64_FIRST_ARG(x) x , +#define ARM64_ARG(x) , x +#define ARM64_ONLY(x) x +#define NOT_ARM64(x) +#define NOT_ARM64_ARG(x) +#else +#define ARM64_FIRST_ARG(x) +#define ARM64_ARG(x) +#define ARM64_ONLY(x) +#define NOT_ARM64(x) x +#define NOT_ARM64_ARG(x) , x +#endif + +#ifdef _TARGET_64BIT_ +#define LOG2_PTRSIZE 3 +#else +#define LOG2_PTRSIZE 2 +#endif + +#ifdef _WIN64 + #define INVALID_POINTER_CC 0xcccccccccccccccc + #define INVALID_POINTER_CD 0xcdcdcdcdcdcdcdcd + #define FMT_ADDR " %08x`%08x " + #define LFMT_ADDR W(" %08x`%08x ") + #define DBG_ADDR(ptr) (((UINT_PTR) (ptr)) >> 32), (((UINT_PTR) (ptr)) & 0xffffffff) +#else // _WIN64 + #define INVALID_POINTER_CC 0xcccccccc + #define INVALID_POINTER_CD 0xcdcdcdcd + #define FMT_ADDR " %08x " + #define LFMT_ADDR W(" %08x ") + #define DBG_ADDR(ptr) ((UINT_PTR)(ptr)) +#endif // _WIN64 + +#ifdef _TARGET_ARM_ + #define ALIGN_ACCESS ((1<= val ); // check for overflow + return result; +} +inline void* ALIGN_UP( void* val, size_t alignment ) +{ + WRAPPER_NO_CONTRACT; + + return (void*) ALIGN_UP( (size_t)val, alignment ); +} +inline uint8_t* ALIGN_UP( uint8_t* val, size_t alignment ) +{ + WRAPPER_NO_CONTRACT; + + return (uint8_t*) ALIGN_UP( (size_t)val, alignment ); +} + +inline size_t ALIGN_DOWN( size_t val, size_t alignment ) +{ + LIMITED_METHOD_CONTRACT; + + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE( 0 == (alignment & (alignment - 1)) ); + size_t result = val & ~(alignment - 1); + return result; +} +inline void* ALIGN_DOWN( void* val, size_t alignment ) +{ + WRAPPER_NO_CONTRACT; + return (void*) ALIGN_DOWN( (size_t)val, alignment ); +} +inline uint8_t* ALIGN_DOWN( uint8_t* val, size_t alignment ) +{ + WRAPPER_NO_CONTRACT; + return (uint8_t*) ALIGN_DOWN( (size_t)val, alignment ); +} + +inline BOOL IS_ALIGNED( size_t val, size_t alignment ) +{ + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + + // alignment must be a power of 2 for this implementation to work (need modulo otherwise) + _ASSERTE( 0 == (alignment & (alignment - 1)) ); + return 0 == (val & (alignment - 1)); +} +inline BOOL IS_ALIGNED( const void* val, size_t alignment ) +{ + WRAPPER_NO_CONTRACT; + return IS_ALIGNED( (size_t) val, alignment ); +} + +// Rounds a ULONG up to the nearest power of two number. +inline ULONG RoundUpToPower2(ULONG x) +{ + if (x == 0) return 1; + + x = x - 1; + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + return x + 1; +} + +#ifdef ALIGN_ACCESS + +// NOTE: pSrc is evaluated three times!!! +#define MAYBE_UNALIGNED_READ(pSrc, bits) (IS_ALIGNED((size_t)(pSrc), sizeof(UINT##bits)) ? \ + (*(UINT##bits*) (pSrc)) : \ + (GET_UNALIGNED_##bits(pSrc)) ) + +#define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { if (IS_ALIGNED((size_t)(pDst), sizeof(UINT##bits))) \ + *(UINT##bits*)(pDst) = (UINT##bits)(expr); else \ + SET_UNALIGNED_##bits(pDst, (UINT##bits)(expr)); } while (0) + +// these are necessary for MAYBE_UNALIGNED_XXX to work with UINT_PTR +#define GET_UNALIGNED__PTR(x) GET_UNALIGNED_PTR(x) +#define SET_UNALIGNED__PTR(p,x) SET_UNALIGNED_PTR(p,x) + +#else // ALIGN_ACCESS +#define MAYBE_UNALIGNED_READ(pSrc, bits) (*(UINT##bits*)(pSrc)) +#define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { *(UINT##bits*)(pDst) = (UINT##bits)(expr); } while(0) +#endif // ALIGN_ACCESS + +// +// define some useful macros for logging object +// + +#define FMT_OBJECT "object" FMT_ADDR +#define FMT_HANDLE "handle" FMT_ADDR +#define FMT_CLASS "%s" +#define FMT_REG "r%d " +#define FMT_STK "sp%s0x%02x " +#define FMT_PIPTR "%s%s pointer " + + +#define DBG_GET_CLASS_NAME(pMT) \ + (((pMT) == NULL) ? NULL : (pMT)->GetClass()->GetDebugClassName()) + +#define DBG_CLASS_NAME_MT(pMT) \ + (DBG_GET_CLASS_NAME(pMT) == NULL) ? "" : DBG_GET_CLASS_NAME(pMT) + +#define DBG_GET_MT_FROM_OBJ(obj) \ + (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable()) + +#define DBG_CLASS_NAME_OBJ(obj) \ + ((obj) == NULL) ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) + +#define DBG_CLASS_NAME_IPTR2(obj,iptr) \ + ((iptr) != 0) ? "" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) + +#define DBG_CLASS_NAME_IPTR(obj,iptr) \ + ((obj) == NULL) ? "null" : DBG_CLASS_NAME_IPTR2(obj,iptr) + +#define DBG_STK(off) \ + (off >= 0) ? "+" : "-", \ + (off >= 0) ? off : -off + +#define DBG_PIN_NAME(pin) \ + (pin) ? "pinned " : "" + +#define DBG_IPTR_NAME(iptr) \ + (iptr) ? "interior" : "base" + +#define LOG_HANDLE_OBJECT_CLASS(str1, hnd, str2, obj) \ + str1 FMT_HANDLE str2 FMT_OBJECT FMT_CLASS "\n", \ + DBG_ADDR(hnd), DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj) + +#define LOG_OBJECT_CLASS(obj) \ + FMT_OBJECT FMT_CLASS "\n", \ + DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj) + +#define LOG_PIPTR_OBJECT_CLASS(obj, pin, iptr) \ + FMT_PIPTR FMT_ADDR FMT_CLASS "\n", \ + DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr), \ + DBG_ADDR(obj), DBG_CLASS_NAME_IPTR(obj,iptr) + +#define LOG_HANDLE_OBJECT(str1, hnd, str2, obj) \ + str1 FMT_HANDLE str2 FMT_OBJECT "\n", \ + DBG_ADDR(hnd), DBG_ADDR(obj) + +#define LOG_PIPTR_OBJECT(obj, pin, iptr) \ + FMT_PIPTR FMT_ADDR "\n", \ + DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr), \ + DBG_ADDR(obj) + +#define UNIQUE_LABEL_DEF(a,x) a##x +#define UNIQUE_LABEL_DEF_X(a,x) UNIQUE_LABEL_DEF(a,x) +#ifdef _MSC_VER +#define UNIQUE_LABEL(a) UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __COUNTER__) +#else +#define UNIQUE_LABEL(a) UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __LINE__) +#endif + + +#ifndef _countof +#define _countof(_array) (sizeof(_array)/sizeof(_array[0])) +#endif + + +// This is temporary. LKG should provide these macros and we should then +// remove STRUNCATE and _TRUNCATE from here. + +/* error codes */ +#if !defined(STRUNCATE) +#define STRUNCATE 80 +#endif + +/* _TRUNCATE */ +#if !defined(_TRUNCATE) +#define _TRUNCATE ((size_t)-1) +#endif + +#endif //_stdmacros_h_ diff --git a/lib/coreclr/src/inc/stgpool.h b/lib/coreclr/src/inc/stgpool.h new file mode 100644 index 0000000000..67d78b24db --- /dev/null +++ b/lib/coreclr/src/inc/stgpool.h @@ -0,0 +1,1548 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// StgPool.h +// + +// +// Pools are used to reduce the amount of data actually required in the database. +// This allows for duplicate string and binary values to be folded into one +// copy shared by the rest of the database. Strings are tracked in a hash +// table when insert/changing data to find duplicates quickly. The strings +// are then persisted consecutively in a stream in the database format. +// +//***************************************************************************** + +#ifndef __StgPool_h__ +#define __StgPool_h__ + +#ifdef _MSC_VER +#pragma warning (disable : 4355) // warning C4355: 'this' : used in base member initializer list +#endif + +#include "stgpooli.h" // Internal helpers. +#include "corerror.h" // Error codes. +#include "metadatatracker.h" +#include "metamodelpub.h" +#include "ex.h" +#include "sarray.h" +#include "memoryrange.h" +#include "../md/hotdata/hotheap.h" + +#include "../md/debug_metadata.h" + +//***************************************************************************** +// NOTE: +// One limitation with the pools, we have no way to removing strings from +// the pool. To remove, you need to know the ref count on the string, and +// need the ability to compact the pool and reset all references. +//***************************************************************************** + +//********** Constants ******************************************************** +const int DFT_STRING_HEAP_SIZE = 1024; +const int DFT_GUID_HEAP_SIZE = 32; +const int DFT_BLOB_HEAP_SIZE = 1024; +const int DFT_VARIANT_HEAP_SIZE = 512; +const int DFT_CODE_HEAP_SIZE = 8192; + + + +// Forwards. +class StgStringPool; +class StgBlobPool; +class StgCodePool; +class CorProfileData; + +// Perform binary search on index table. +// +class RIDBinarySearch : public CBinarySearch +{ +public: + RIDBinarySearch(const UINT32 *pBase, int iCount) : CBinarySearch(pBase, iCount) + { + LIMITED_METHOD_CONTRACT; + } // RIDBinarySearch::RIDBinarySearch + + int Compare(UINT32 const *pFirst, UINT32 const *pSecond) + { + LIMITED_METHOD_CONTRACT; + + if (*pFirst < *pSecond) + return -1; + + if (*pFirst > *pSecond) + return 1; + + return 0; + } // RIDBinarySearch::Compare + +}; // class RIDBinarySearch + +//***************************************************************************** +// This class provides common definitions for heap segments. It is both the +// base class for the heap, and the class for heap extensions (additional +// memory that must be allocated to grow the heap). +//***************************************************************************** +class StgPoolSeg +{ + friend class VerifyLayoutsMD; +public: + StgPoolSeg() : + m_pSegData((BYTE*)m_zeros), + m_pNextSeg(NULL), + m_cbSegSize(0), + m_cbSegNext(0) + {LIMITED_METHOD_CONTRACT; } + ~StgPoolSeg() + { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pSegData == m_zeros);_ASSERTE(m_pNextSeg == NULL); } +protected: + BYTE *m_pSegData; // Pointer to the data. + StgPoolSeg *m_pNextSeg; // Pointer to next segment, or NULL. + // Size of the segment buffer. If this is last segment (code:m_pNextSeg is NULL), then it's the + // allocation size. If this is not the last segment, then this is shrinked to segment data size + // (code:m_cbSegNext). + ULONG m_cbSegSize; + ULONG m_cbSegNext; // Offset of next available byte in segment. + // Segment relative. + + friend class StgPool; + friend class StgStringPool; + friend class StgGuidPool; + friend class StgBlobPool; + friend class RecordPool; + +public: + const BYTE *GetSegData() const { LIMITED_METHOD_CONTRACT; return m_pSegData; } + const StgPoolSeg* GetNextSeg() const { LIMITED_METHOD_CONTRACT; return m_pNextSeg; } + // Returns size of the segment. It can be bigger than the size of represented data by this segment if + // this is the last segment. + ULONG GetSegSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegSize; } + // Returns size of represented data in this segment. + ULONG GetDataSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegNext; } + + static const BYTE m_zeros[64]; // array of zeros for "0" indices. + // The size should be at least maximum of all MD table record sizes + // (MD\Runtime\MDColumnDescriptors.cpp) which is currently 28 B. +}; // class StgPoolSeg + +namespace MetaData +{ + // Forward declarations + class StringHeapRO; + class StringHeapRW; + class BlobHeapRO; +}; // namespace MetaData + +// +// +// StgPoolReadOnly +// +// +//***************************************************************************** +// This is the read only StgPool class +//***************************************************************************** +class StgPoolReadOnly : public StgPoolSeg +{ +friend class CBlobPoolHash; +friend class MetaData::StringHeapRO; +friend class MetaData::StringHeapRW; +friend class MetaData::BlobHeapRO; +friend class VerifyLayoutsMD; + +public: + StgPoolReadOnly() + { LIMITED_METHOD_CONTRACT; }; + + ~StgPoolReadOnly(); + + +//***************************************************************************** +// Init the pool from existing data. +//***************************************************************************** + __checkReturn + HRESULT InitOnMemReadOnly( // Return code. + void *pData, // Predefined data. + ULONG iSize); // Size of data. + +//***************************************************************************** +// Prepare to shut down or reinitialize. +//***************************************************************************** + virtual void Uninit(); + +//***************************************************************************** +// Return the size of the pool. +//***************************************************************************** + virtual UINT32 GetPoolSize() const + { LIMITED_METHOD_CONTRACT; return m_cbSegSize; } + +//***************************************************************************** +// Indicate if heap is empty. +//***************************************************************************** + virtual int IsEmpty() // true if empty. + { LIMITED_METHOD_CONTRACT; _ASSERTE(!"This implementation should never be called!!!"); return FALSE; } + +//***************************************************************************** +// true if the heap is read only. +//***************************************************************************** + virtual int IsReadOnly() { LIMITED_METHOD_CONTRACT; return true ;}; + +//***************************************************************************** +// Is the given cookie a valid offset, index, etc? +//***************************************************************************** + virtual int IsValidCookie(UINT32 nCookie) + { WRAPPER_NO_CONTRACT; return (IsValidOffset(nCookie)); } + + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable:6387) // Suppress PREFast warning: '*pszString' might be '0': this does not adhere to the specification for the function + // *pszString may be NULL only if method fails, but warning 6387 doesn't respect __success(SUCCEEDED(return)) which is part of HRESULT definition +#endif +//***************************************************************************** +// Return a pointer to a null terminated string given an offset previously +// handed out by AddString or FindString. +//***************************************************************************** + __checkReturn + inline HRESULT GetString( + UINT32 nIndex, + __deref_out LPCSTR *pszString) + { + HRESULT hr; + + // Size of the data in the heap will be ignored, because we have verified during creation of the string + // heap (code:Initialize) and when adding new strings (e.g. code:AddString, + // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it + // for each string in the heap + MetaData::DataBlob stringData; + + // Get data from the heap (clears stringData on error) + IfFailGo(GetData( + nIndex, + &stringData)); + _ASSERTE(hr == S_OK); + // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK + PREFAST_ASSUME(stringData.GetDataPointer() != NULL); + // Fills output string + *pszString = reinterpret_cast(stringData.GetDataPointer()); + //_ASSERTE(stringData.GetSize() > strlen(*pszString)); + + return hr; + ErrExit: + // Clears output string on error + *pszString = NULL; + + return hr; + } + +//***************************************************************************** +// Return a pointer to a null terminated string given an offset previously +// handed out by AddString or FindString. Only valid for use if the Storage pool is actuall ReadOnly, and not derived +//***************************************************************************** + __checkReturn + inline HRESULT GetStringReadOnly( + UINT32 nIndex, + __deref_out LPCSTR *pszString) + { + HRESULT hr; + + // Size of the data in the heap will be ignored, because we have verified during creation of the string + // heap (code:Initialize) and when adding new strings (e.g. code:AddString, + // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it + // for each string in the heap + MetaData::DataBlob stringData; + + // Get data from the heap (clears stringData on error) + IfFailGo(GetDataReadOnly( + nIndex, + &stringData)); + _ASSERTE(hr == S_OK); + // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK + PREFAST_ASSUME(stringData.GetDataPointer() != NULL); + // Fills output string + *pszString = reinterpret_cast(stringData.GetDataPointer()); + //_ASSERTE(stringData.GetSize() > strlen(*pszString)); + + return hr; + ErrExit: + // Clears output string on error + *pszString = NULL; + + return hr; + } +#ifdef _PREFAST_ +#pragma warning(pop) +#endif + +//***************************************************************************** +// Convert a string to UNICODE into the caller's buffer. +//***************************************************************************** + __checkReturn + virtual HRESULT GetStringW( // Return code. + ULONG iOffset, // Offset of string in pool. + __out_ecount(cchBuffer) LPWSTR szOut, // Output buffer for string. + int cchBuffer); // Size of output buffer. + +//***************************************************************************** +// Copy a GUID into the caller's buffer. +//***************************************************************************** + __checkReturn + HRESULT GetGuid( + UINT32 nIndex, // 1-based index of Guid in pool. + GUID UNALIGNED **ppGuid) // Output buffer for Guid. + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + HRESULT hr; + MetaData::DataBlob heapData; + + if (nIndex == 0) + { + *ppGuid = (GUID *)m_zeros; + return S_OK; + } + + S_UINT32 nOffset = S_UINT32(nIndex - 1) * S_UINT32(sizeof(GUID)); + if (nOffset.IsOverflow() || !IsValidOffset(nOffset.Value())) + { + Debug_ReportError("Invalid index passed - integer overflow."); + IfFailGo(CLDB_E_INDEX_NOTFOUND); + } + if (FAILED(GetData(nOffset.Value(), &heapData))) + { + if (nOffset.Value() == 0) + { + Debug_ReportError("Invalid index 0 passed."); + IfFailGo(CLDB_E_INDEX_NOTFOUND); + } + Debug_ReportInternalError("Invalid index passed."); + IfFailGo(CLDB_E_INTERNALERROR); + } + _ASSERTE(heapData.GetSize() >= sizeof(GUID)); + + *ppGuid = (GUID UNALIGNED *)heapData.GetDataPointer(); + return S_OK; + + ErrExit: + *ppGuid = (GUID *)m_zeros; + return hr; + } // StgPoolReadOnly::GetGuid + +//***************************************************************************** +// Return a pointer to a null terminated blob given an offset previously +// handed out by Addblob or Findblob. +//***************************************************************************** + __checkReturn + virtual HRESULT GetBlob( + UINT32 nOffset, // Offset of blob in pool. + MetaData::DataBlob *pData); + +#ifdef FEATURE_PREJIT + // Initialize hot data structures. + // Method can be called multiple time, e.g. to disable usage of hot data structures in certain scenarios + // (see code:CMiniMd::DisableHotDataUsage). + void InitHotData(MetaData::HotHeap hotHeap) + { + LIMITED_METHOD_CONTRACT; + +#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) + m_HotHeap = hotHeap; +#else + _ASSERTE(!"InitHotData(): Not supposed to exist in RoMetaData.dll"); +#endif //!(defined(FEATURE_UTILCODE_NO_DEPENDENCIES)) + } +#endif //FEATURE_PREJIT + +protected: + +//***************************************************************************** +// Check whether a given offset is valid in the pool. +//***************************************************************************** + virtual int IsValidOffset(UINT32 nOffset) + {LIMITED_METHOD_CONTRACT; return (nOffset == 0) || ((m_pSegData != m_zeros) && (nOffset < m_cbSegSize)); } + +//***************************************************************************** +// Get a pointer to an offset within the heap. Inline for base segment, +// helper for extension segments. +//***************************************************************************** + __checkReturn + FORCEINLINE HRESULT GetDataReadOnly(UINT32 nOffset, __inout MetaData::DataBlob *pData) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(IsReadOnly()); + + // If off the end of the heap, return the 'nul' item from the beginning. + if (nOffset >= m_cbSegSize) + { + Debug_ReportError("Invalid offset passed."); + pData->Clear(); + return CLDB_E_INDEX_NOTFOUND; + } + +#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) +#ifdef FEATURE_PREJIT + // try hot data first + if (!m_HotHeap.IsEmpty()) + { + HRESULT hr = m_HotHeap.GetData(nOffset, pData); + if ((hr == S_OK) || FAILED(hr)) + { + return hr; + } + _ASSERTE(hr == S_FALSE); + } +#endif //FEATURE_PREJIT +#endif //!(defined(FEATURE_UTILCODE_NO_DEPENDENCIES)) + + + pData->Init(m_pSegData + nOffset, m_cbSegSize - nOffset); + + METADATATRACKER_ONLY(MetaDataTracker::NoteAccess((void *)pData->GetDataPointer())); + + return S_OK; + } // StgPoolReadOnly::GetDataReadOnly + +//***************************************************************************** +// Get a pointer to an offset within the heap. Inline for base segment, +// helper for extension segments. +//***************************************************************************** + __checkReturn + virtual HRESULT GetData(UINT32 nOffset, __inout MetaData::DataBlob *pData) + { + WRAPPER_NO_CONTRACT; + return GetDataReadOnly(nOffset, pData); + } // StgPoolReadOnly::GetData + +private: +#if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) + // hot pool data + MetaData::HotHeap m_HotHeap; +#endif //!(defined(FEATURE_UTILCODE_NO_DEPENDENCIES)) + +}; // class StgPoolReadOnly + +// +// +// StgBlobPoolReadOnly +// +// +//***************************************************************************** +// This is the read only StgBlobPool class +//***************************************************************************** +class StgBlobPoolReadOnly : public StgPoolReadOnly +{ +public: +//***************************************************************************** +// Return a pointer to a null terminated blob given an offset +//***************************************************************************** + __checkReturn + virtual HRESULT GetBlob( + UINT32 nOffset, // Offset of blob in pool. + MetaData::DataBlob *pData); + +protected: + +//***************************************************************************** +// Check whether a given offset is valid in the pool. +//***************************************************************************** + virtual int IsValidOffset(UINT32 nOffset) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + MetaData::DataBlob data; + return (StgBlobPoolReadOnly::GetBlob(nOffset, &data) == S_OK); + } + +}; // class StgBlobPoolReadOnly + +// +// +// StgPool +// +// + +//***************************************************************************** +// This base class provides common pool management code, such as allocation +// of dynamic memory. +//***************************************************************************** +class StgPool : public StgPoolReadOnly +{ +friend class StgStringPool; +friend class StgBlobPool; +friend class RecordPool; +friend class CBlobPoolHash; +friend class VerifyLayoutsMD; + +public: + StgPool(ULONG ulGrowInc=512, UINT32 nAlignment=4) : + m_ulGrowInc(ulGrowInc), + m_pCurSeg(this), + m_cbCurSegOffset(0), + m_bFree(true), + m_bReadOnly(false), + m_nVariableAlignmentMask(nAlignment-1), + m_cbStartOffsetOfEdit(0), + m_fValidOffsetOfEdit(0) + { LIMITED_METHOD_CONTRACT; } + + virtual ~StgPool(); + +protected: + HRESULT Align(UINT32 nValue, UINT32 *pnAlignedValue) const + { + LIMITED_METHOD_CONTRACT; + + *pnAlignedValue = (nValue + m_nVariableAlignmentMask) & ~m_nVariableAlignmentMask; + if (*pnAlignedValue < nValue) + { + return COR_E_OVERFLOW; + } + return S_OK; + } + +public: +//***************************************************************************** +// Init the pool for use. This is called for the create empty case. +//***************************************************************************** + __checkReturn + virtual HRESULT InitNew( // Return code. + ULONG cbSize=0, // Estimated size. + ULONG cItems=0); // Estimated item count. + +//***************************************************************************** +// Init the pool from existing data. +//***************************************************************************** + __checkReturn + virtual HRESULT InitOnMem( // Return code. + void *pData, // Predefined data. + ULONG iSize, // Size of data. + int bReadOnly); // true if append is forbidden. + +//***************************************************************************** +// Called when the pool must stop accessing memory passed to InitOnMem(). +//***************************************************************************** + __checkReturn + virtual HRESULT TakeOwnershipOfInitMem(); + +//***************************************************************************** +// Clear out this pool. Cannot use until you call InitNew. +//***************************************************************************** + virtual void Uninit(); + +//***************************************************************************** +// Called to copy the pool to writable memory, reset the r/o bit. +//***************************************************************************** + __checkReturn + virtual HRESULT ConvertToRW(); + +//***************************************************************************** +// Turn hashing off or on. Implemented as required in subclass. +//***************************************************************************** + __checkReturn + virtual HRESULT SetHash(int bHash); + +//***************************************************************************** +// Allocate memory if we don't have any, or grow what we have. If successful, +// then at least iRequired bytes will be allocated. +//***************************************************************************** + bool Grow( // true if successful. + ULONG iRequired); // Min required bytes to allocate. + +//***************************************************************************** +// Add a segment to the chain of segments. +//***************************************************************************** + __checkReturn + virtual HRESULT AddSegment( // S_OK or error. + const void *pData, // The data. + ULONG cbData, // Size of the data. + bool bCopy); // If true, make a copy of the data. + +//***************************************************************************** +// Trim any empty final segment. +//***************************************************************************** + void Trim(); // + +//***************************************************************************** +// Return the size in bytes of the persistent version of this pool. If +// PersistToStream were the next call, the amount of bytes written to pIStream +// has to be same as the return value from this function. +//***************************************************************************** + __checkReturn + virtual HRESULT GetSaveSize( + UINT32 *pcbSaveSize) const + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + _ASSERTE(pcbSaveSize != NULL); + // Size is offset of last seg + size of last seg. + UINT32 cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; + + if (FAILED(Align(cbSize, pcbSaveSize))) + { + *pcbSaveSize = 0; + Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); + return CLDB_E_INTERNALERROR; + } + return S_OK; + } + +//***************************************************************************** +// Return the size in bytes of the edits contained in the persistent version of this pool. +//***************************************************************************** + __checkReturn + HRESULT GetEditSaveSize( + UINT32 *pcbSaveSize) const // Return save size of this pool. + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + _ASSERTE(pcbSaveSize != NULL); + UINT32 cbSize = 0; + + if (HaveEdits()) + { + // Size is offset of last seg + size of last seg. + + // An offset of zero in the pool will give us a zero length blob. The first + // "real" user string is at offset 1. Wherever this delta gets applied, it will + // already have this zero length blob. Let's make sure we don't sent it another one. +#ifdef _DEBUG + MetaData::DataBlob debug_data; + HRESULT hr = const_cast(this)->GetData(0, &debug_data); + _ASSERTE(hr == S_OK); + _ASSERTE(debug_data.ContainsData(1)); + _ASSERTE(*(debug_data.GetDataPointer()) == 0); +#endif //_DEBUG + UINT32 nOffsetOfEdit = GetOffsetOfEdit(); + + if (nOffsetOfEdit == 0) + nOffsetOfEdit = 1; + + cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset - nOffsetOfEdit; + } + + if (FAILED(Align(cbSize, pcbSaveSize))) + { + *pcbSaveSize = 0; + Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); + return CLDB_E_INTERNALERROR; + } + return S_OK; + } // StgPool::GetEditSaveSize + +//***************************************************************************** +// The entire pool is written to the given stream. The stream is aligned +// to a 4 byte boundary. +//***************************************************************************** + __checkReturn + virtual HRESULT PersistToStream( // Return code. + IStream *pIStream) // The stream to write to. + DAC_UNEXPECTED(); + +//***************************************************************************** +// A portion of the pool is written to the stream. Must not be optimized. +//***************************************************************************** + __checkReturn + virtual HRESULT PersistPartialToStream( // Return code. + IStream *pIStream, // The stream to write to. + ULONG iOffset); // Starting byte. + +//***************************************************************************** +// Get the size of the data block obtained from the pool. +// Needed for generic persisting of data blocks. +// Override in concrete pool classes to return the correct size. +//***************************************************************************** + virtual ULONG GetSizeOfData( void const * data ) + { + LIMITED_METHOD_CONTRACT; + return 0; + } + +//***************************************************************************** +// Return the size of the pool. +//***************************************************************************** + virtual UINT32 GetPoolSize() const + {LIMITED_METHOD_CONTRACT; return m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; } + +//***************************************************************************** +// Indicate if heap is empty. +//***************************************************************************** + virtual int IsEmpty() // true if empty. + {LIMITED_METHOD_CONTRACT; return (m_pSegData == m_zeros); } + +//***************************************************************************** +// true if the heap is read only. +//***************************************************************************** + int IsReadOnly() + {LIMITED_METHOD_CONTRACT; return (m_bReadOnly == false); } + +//***************************************************************************** +// Is the given cookie a valid offset, index, etc? +//***************************************************************************** + virtual int IsValidCookie(UINT32 nCookie) + { WRAPPER_NO_CONTRACT; return (IsValidOffset(nCookie)); } + +//***************************************************************************** +// Get a pointer to an offset within the heap. Inline for base segment, +// helper for extension segments. +//***************************************************************************** + __checkReturn + FORCEINLINE HRESULT GetData(UINT32 nOffset, MetaData::DataBlob *pData) + { + WRAPPER_NO_CONTRACT; + if (nOffset < m_cbSegNext) + { + pData->Init(m_pSegData + nOffset, m_cbSegNext - nOffset); + return S_OK; + } + else + { + return GetData_i(nOffset, pData); + } + } // StgPool::GetData + + // Copies data from pSourcePool starting at index nStartSourceIndex. + __checkReturn + HRESULT CopyPool( + UINT32 nStartSourceIndex, + const StgPool *pSourcePool); + +//***************************************************************************** +// Copies data from the pool into a buffer. It will correctly walk the different +// segments for the copy +//***************************************************************************** +private: + __checkReturn + HRESULT CopyData( + UINT32 nOffset, + BYTE *pBuffer, + UINT32 cbBuffer, + UINT32 *pcbWritten) const; + +public: +//***************************************************************************** +// Helpers for dump utilities. +//***************************************************************************** + UINT32 GetRawSize() const + { + LIMITED_METHOD_CONTRACT; + + // Size is offset of last seg + size of last seg. + return m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; + } + + BOOL HaveEdits() const {LIMITED_METHOD_CONTRACT; return m_fValidOffsetOfEdit;} + UINT32 GetOffsetOfEdit() const {LIMITED_METHOD_CONTRACT; return m_cbStartOffsetOfEdit;} + void ResetOffsetOfEdit() {LIMITED_METHOD_CONTRACT; m_fValidOffsetOfEdit=FALSE;} + +protected: + +//***************************************************************************** +// Check whether a given offset is valid in the pool. +//***************************************************************************** + virtual int IsValidOffset(UINT32 nOffset) + { WRAPPER_NO_CONTRACT; return (nOffset == 0) || ((m_pSegData != m_zeros) && (nOffset < GetNextOffset())); } + + // Following virtual because a) this header included outside the project, and + // non-virtual function call (in non-expanded inline function!!) generates + // an external def, which causes linkage errors. + __checkReturn + virtual HRESULT GetData_i(UINT32 nOffset, MetaData::DataBlob *pData); + + // Get pointer to next location to which to write. + BYTE *GetNextLocation() + {LIMITED_METHOD_CONTRACT; return (m_pCurSeg->m_pSegData + m_pCurSeg->m_cbSegNext); } + + // Get pool-relative offset of next location to which to write. + ULONG GetNextOffset() + {LIMITED_METHOD_CONTRACT; return (m_cbCurSegOffset + m_pCurSeg->m_cbSegNext); } + + // Get count of bytes available in tail segment of pool. + ULONG GetCbSegAvailable() + {LIMITED_METHOD_CONTRACT; return (m_pCurSeg->m_cbSegSize - m_pCurSeg->m_cbSegNext); } + + // Allocate space from the segment. + + void SegAllocate(ULONG cb) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(cb <= GetCbSegAvailable()); + + if (!m_fValidOffsetOfEdit) + { + m_cbStartOffsetOfEdit = GetNextOffset(); + m_fValidOffsetOfEdit = TRUE; + } + + m_pCurSeg->m_cbSegNext += cb; + }// SegAllocate + + + + ULONG m_ulGrowInc; // How many bytes at a time. + StgPoolSeg *m_pCurSeg; // Current seg for append -- end of chain. + ULONG m_cbCurSegOffset; // Base offset of current seg. + + unsigned m_bFree : 1; // True if we should free base data. + // Extension data is always freed. + unsigned m_bReadOnly : 1; // True if we shouldn't append. + + UINT32 m_nVariableAlignmentMask; // Alignment mask (variable 0, 1 or 3). + UINT32 m_cbStartOffsetOfEdit; // Place in the pool where edits started + BOOL m_fValidOffsetOfEdit; // Is the pool edit offset valid + +}; + + +// +// +// StgStringPool +// +// + + + +//***************************************************************************** +// This string pool class collects user strings into a big consecutive heap. +// Internally it manages this data in a hash table at run time to help throw +// out duplicates. The list of strings is kept in memory while adding, and +// finally flushed to a stream at the caller's request. +//***************************************************************************** +class StgStringPool : public StgPool +{ + friend class VerifyLayoutsMD; +public: + StgStringPool() : + StgPool(DFT_STRING_HEAP_SIZE), + m_Hash(this), + m_bHash(true) + { + LIMITED_METHOD_CONTRACT; + // force some code in debug. + _ASSERTE(m_bHash); + } + +//***************************************************************************** +// Create a new, empty string pool. +//***************************************************************************** + __checkReturn + HRESULT InitNew( // Return code. + ULONG cbSize=0, // Estimated size. + ULONG cItems=0); // Estimated item count. + +//***************************************************************************** +// Load a string heap from persisted memory. If a copy of the data is made +// (so that it may be updated), then a new hash table is generated which can +// be used to elminate duplicates with new strings. +//***************************************************************************** + __checkReturn + HRESULT InitOnMem( // Return code. + void *pData, // Predefined data. + ULONG iSize, // Size of data. + int bReadOnly); // true if append is forbidden. + +//***************************************************************************** +// Clears the hash table then calls the base class. +//***************************************************************************** + void Uninit(); + +//***************************************************************************** +// Turn hashing off or on. If you turn hashing on, then any existing data is +// thrown away and all data is rehashed during this call. +//***************************************************************************** + __checkReturn + virtual HRESULT SetHash(int bHash); + +//***************************************************************************** +// The string will be added to the pool. The offset of the string in the pool +// is returned in *piOffset. If the string is already in the pool, then the +// offset will be to the existing copy of the string. +// +// The first version essentially adds a zero-terminated sequence of bytes +// to the pool. MBCS pairs will not be converted to the appropriate UTF8 +// sequence. The second version converts from Unicode. +//***************************************************************************** + __checkReturn + HRESULT AddString( + LPCSTR szString, // The string to add to pool. + UINT32 *pnOffset); // Return offset of string here. + + __checkReturn + HRESULT AddStringW( + LPCWSTR szString, // The string to add to pool. + UINT32 *pnOffset); // Return offset of string here. + +//***************************************************************************** +// Look for the string and return its offset if found. +//***************************************************************************** + __checkReturn + HRESULT FindString( // S_OK, S_FALSE. + LPCSTR szString, // The string to find in pool. + ULONG *piOffset) // Return offset of string here. + { + WRAPPER_NO_CONTRACT; + + STRINGHASH *pHash; // Hash item for lookup. + if ((pHash = m_Hash.Find(szString)) == 0) + return (S_FALSE); + *piOffset = pHash->iOffset; + return (S_OK); + } + +//***************************************************************************** +// How many objects are there in the pool? If the count is 0, you don't need +// to persist anything at all to disk. +//***************************************************************************** + int Count() + { + WRAPPER_NO_CONTRACT; + _ASSERTE(m_bHash); + return (m_Hash.Count()); } + +//***************************************************************************** +// String heap is considered empty if the only thing it has is the initial +// empty string, or if after organization, there are no strings. +//***************************************************************************** + int IsEmpty() // true if empty. + { + WRAPPER_NO_CONTRACT; + + return (GetNextOffset() <= 1); + } + +//***************************************************************************** +// Return the size in bytes of the persistent version of this pool. If +// PersistToStream were the next call, the amount of bytes written to pIStream +// has to be same as the return value from this function. +//***************************************************************************** + __checkReturn + virtual HRESULT GetSaveSize( + UINT32 *pcbSaveSize) const + { + LIMITED_METHOD_CONTRACT; + + _ASSERTE(pcbSaveSize != NULL); + + // Size is offset of last seg + size of last seg. + S_UINT32 cbSize = S_UINT32(m_pCurSeg->m_cbSegNext + m_cbCurSegOffset); + + cbSize.AlignUp(4); + + if (cbSize.IsOverflow()) + { + *pcbSaveSize = 0; + Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); + return CLDB_E_INTERNALERROR; + } + *pcbSaveSize = cbSize.Value(); + return S_OK; + } + +//***************************************************************************** +// Get the size of the string obtained from the pool. +// Needed for generic persisting of data blocks. +//***************************************************************************** + virtual ULONG GetSizeOfData( void const * data ) + { + LIMITED_METHOD_CONTRACT; + return ULONG( strlen( reinterpret_cast< LPCSTR >( data ) ) + 1 ); // using strlen since the string is UTF8 + } + +private: + __checkReturn + HRESULT RehashStrings(); + +private: + CStringPoolHash m_Hash; // Hash table for lookups. + int m_bHash; // true to keep hash table. +}; // class StgStringPool + +// +// +// StgGuidPool +// +// + +//***************************************************************************** +// This Guid pool class collects user Guids into a big consecutive heap. +// Internally it manages this data in a hash table at run time to help throw +// out duplicates. The list of Guids is kept in memory while adding, and +// finally flushed to a stream at the caller's request. +//***************************************************************************** +class StgGuidPool : public StgPool +{ + friend class VerifyLayoutsMD; +public: + StgGuidPool() : + StgPool(DFT_GUID_HEAP_SIZE), + m_Hash(this), + m_bHash(true) + { LIMITED_METHOD_CONTRACT; } + +//***************************************************************************** +// Init the pool for use. This is called for the create empty case. +//***************************************************************************** + __checkReturn + HRESULT InitNew( // Return code. + ULONG cbSize=0, // Estimated size. + ULONG cItems=0); // Estimated item count. + +//***************************************************************************** +// Load a Guid heap from persisted memory. If a copy of the data is made +// (so that it may be updated), then a new hash table is generated which can +// be used to elminate duplicates with new Guids. +//***************************************************************************** + __checkReturn + HRESULT InitOnMem( // Return code. + void *pData, // Predefined data. + ULONG iSize, // Size of data. + int bReadOnly); // true if append is forbidden. + +//***************************************************************************** +// Clears the hash table then calls the base class. +//***************************************************************************** + void Uninit(); + +//***************************************************************************** +// Add a segment to the chain of segments. +//***************************************************************************** + __checkReturn + virtual HRESULT AddSegment( // S_OK or error. + const void *pData, // The data. + ULONG cbData, // Size of the data. + bool bCopy); // If true, make a copy of the data. + +//***************************************************************************** +// Turn hashing off or on. If you turn hashing on, then any existing data is +// thrown away and all data is rehashed during this call. +//***************************************************************************** + __checkReturn + virtual HRESULT SetHash(int bHash); + +//***************************************************************************** +// The Guid will be added to the pool. The index of the Guid in the pool +// is returned in *piIndex. If the Guid is already in the pool, then the +// index will be to the existing copy of the Guid. +//***************************************************************************** + __checkReturn + HRESULT AddGuid( + const GUID *pGuid, // The Guid to add to pool. + UINT32 *pnIndex); // Return index of Guid here. + +//***************************************************************************** +// Get the size of the GUID obtained from the pool. +// Needed for generic persisting of data blocks. +//***************************************************************************** + virtual ULONG GetSizeOfData( void const * data ) + { + LIMITED_METHOD_CONTRACT; + return sizeof( GUID ); + } + +//***************************************************************************** +// How many objects are there in the pool? If the count is 0, you don't need +// to persist anything at all to disk. +//***************************************************************************** + int Count() + { + WRAPPER_NO_CONTRACT; + _ASSERTE(m_bHash); + return (m_Hash.Count()); } + +//***************************************************************************** +// Indicate if heap is empty. This has to be based on the size of the data +// we are keeping. If you open in r/o mode on memory, there is no hash +// table. +//***************************************************************************** + virtual int IsEmpty() // true if empty. + { + WRAPPER_NO_CONTRACT; + + return (GetNextOffset() == 0); + } + +//***************************************************************************** +// Is the index valid for the GUID? +//***************************************************************************** + virtual int IsValidCookie(UINT32 nCookie) + { WRAPPER_NO_CONTRACT; return ((nCookie == 0) || IsValidOffset((nCookie - 1) * sizeof(GUID))); } + +//***************************************************************************** +// Return the size of the heap. +//***************************************************************************** + ULONG GetNextIndex() + { LIMITED_METHOD_CONTRACT; return (GetNextOffset() / sizeof(GUID)); } + +//***************************************************************************** +// Return the size in bytes of the persistent version of this pool. If +// PersistToStream were the next call, the amount of bytes written to pIStream +// has to be same as the return value from this function. +//***************************************************************************** + __checkReturn + virtual HRESULT GetSaveSize( + UINT32 *pcbSaveSize) const + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + _ASSERTE(pcbSaveSize != NULL); + + // Size is offset of last seg + size of last seg. + *pcbSaveSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; + + // Should be aligned. + _ASSERTE(*pcbSaveSize == ALIGN4BYTE(*pcbSaveSize)); + return S_OK; + } + +private: + + __checkReturn + HRESULT RehashGuids(); + + +private: + CGuidPoolHash m_Hash; // Hash table for lookups. + int m_bHash; // true to keep hash table. +}; // class StgGuidPool + +// +// +// StgBlobPool +// +// + +//***************************************************************************** +// Just like the string pool, this pool manages a list of items, throws out +// duplicates using a hash table, and can be persisted to a stream. The only +// difference is that instead of saving null terminated strings, this code +// manages binary values of up to 64K in size. Any data you have larger than +// this should be stored someplace else with a pointer in the record to the +// external source. +//***************************************************************************** +class StgBlobPool : public StgPool +{ + friend class VerifyLayoutsMD; + + using StgPool::InitNew; + using StgPool::InitOnMem; + +public: + StgBlobPool(ULONG ulGrowInc=DFT_BLOB_HEAP_SIZE) : + StgPool(ulGrowInc), + m_Hash(this) + { LIMITED_METHOD_CONTRACT; } + +//***************************************************************************** +// Init the pool for use. This is called for the create empty case. +//***************************************************************************** + __checkReturn + HRESULT InitNew( // Return code. + ULONG cbSize=0, // Estimated size. + ULONG cItems=0, // Estimated item count. + BOOL fAddEmptryItem=TRUE); // Should we add an empty item at offset 0 + +//***************************************************************************** +// Init the blob pool for use. This is called for both create and read case. +// If there is existing data and bCopyData is true, then the data is rehashed +// to eliminate dupes in future adds. +//***************************************************************************** + __checkReturn + HRESULT InitOnMem( // Return code. + void *pData, // Predefined data. + ULONG iSize, // Size of data. + int bReadOnly); // true if append is forbidden. + +//***************************************************************************** +// Clears the hash table then calls the base class. +//***************************************************************************** + void Uninit(); + +//***************************************************************************** +// The blob will be added to the pool. The offset of the blob in the pool +// is returned in *piOffset. If the blob is already in the pool, then the +// offset will be to the existing copy of the blob. +//***************************************************************************** + __checkReturn + HRESULT AddBlob( + const MetaData::DataBlob *pData, + UINT32 *pnOffset); + +//***************************************************************************** +// Return a pointer to a null terminated blob given an offset previously +// handed out by Addblob or Findblob. +//***************************************************************************** + __checkReturn + virtual HRESULT GetBlob( + UINT32 nOffset, // Offset of blob in pool. + MetaData::DataBlob *pData); + + __checkReturn + HRESULT GetBlobWithSizePrefix( + UINT32 nOffset, // Offset of blob in pool. + MetaData::DataBlob *pData); + +//***************************************************************************** +// Turn hashing off or on. If you turn hashing on, then any existing data is +// thrown away and all data is rehashed during this call. +//***************************************************************************** + __checkReturn + virtual HRESULT SetHash(int bHash); + +//***************************************************************************** +// Get the size of the blob obtained from the pool. +// Needed for generic persisting of data blocks. +//***************************************************************************** + virtual ULONG GetSizeOfData( void const * data ) + { + WRAPPER_NO_CONTRACT; + + void const * blobdata = 0; + ULONG blobsize = CPackedLen::GetLength( data, & blobdata ); // the size is encoded at the beginning of the block + return blobsize + static_cast< ULONG >( reinterpret_cast< BYTE const * >( blobdata ) - reinterpret_cast< BYTE const * >( data ) ); + } + +//***************************************************************************** +// How many objects are there in the pool? If the count is 0, you don't need +// to persist anything at all to disk. +//***************************************************************************** + int Count() + { WRAPPER_NO_CONTRACT; return (m_Hash.Count()); } + +//***************************************************************************** +// String heap is considered empty if the only thing it has is the initial +// empty string, or if after organization, there are no strings. +//***************************************************************************** + virtual int IsEmpty() // true if empty. + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + return (GetNextOffset() <= 1); + } + +//***************************************************************************** +// Return the size in bytes of the persistent version of this pool. If +// PersistToStream were the next call, the amount of bytes written to pIStream +// has to be same as the return value from this function. +//***************************************************************************** + __checkReturn + virtual HRESULT GetSaveSize( + UINT32 *pcbSaveSize) const + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + return StgPool::GetSaveSize(pcbSaveSize); + } + +protected: + +//***************************************************************************** +// Check whether a given offset is valid in the pool. +//***************************************************************************** + virtual int IsValidOffset(UINT32 nOffset) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FORBID_FAULT; + + MetaData::DataBlob data; + return (StgBlobPool::GetBlob(nOffset, &data) == S_OK); + } + +private: + __checkReturn + HRESULT RehashBlobs(); + + CBlobPoolHash m_Hash; // Hash table for lookups. +}; // class StgBlobPool + +#ifdef _MSC_VER +#pragma warning (default : 4355) +#endif + +//***************************************************************************** +// Unfortunately the CreateStreamOnHGlobal is a little too smart in that +// it gets its size from GlobalSize. This means that even if you give it the +// memory for the stream, it has to be globally allocated. We don't want this +// because we have the stream read only in the middle of a memory mapped file. +// CreateStreamOnMemory and the corresponding, internal only stream object solves +// that problem. +//***************************************************************************** +class CInMemoryStream : public IStream +{ +public: + CInMemoryStream() : + m_pMem(0), + m_cbSize(0), + m_cbCurrent(0), + m_cRef(1), + m_dataCopy(NULL) + { LIMITED_METHOD_CONTRACT; } + + virtual ~CInMemoryStream() {} + + void InitNew( + void *pMem, + ULONG cbSize) + { + LIMITED_METHOD_CONTRACT; + + m_pMem = pMem; + m_cbSize = cbSize; + m_cbCurrent = 0; + } + + ULONG STDMETHODCALLTYPE AddRef() { + LIMITED_METHOD_CONTRACT; + return InterlockedIncrement(&m_cRef); + } + + + ULONG STDMETHODCALLTYPE Release(); + + __checkReturn + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); + + __checkReturn + HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead); + + __checkReturn + HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten); + + __checkReturn + HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); + + __checkReturn + HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE CopyTo( + IStream *pstm, + ULARGE_INTEGER cb, + ULARGE_INTEGER *pcbRead, + ULARGE_INTEGER *pcbWritten); + + __checkReturn + HRESULT STDMETHODCALLTYPE Commit( + DWORD grfCommitFlags) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE Revert() + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE LockRegion( + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE UnlockRegion( + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE Stat( + STATSTG *pstatstg, + DWORD grfStatFlag) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + pstatstg->cbSize.QuadPart = m_cbSize; + return (S_OK); + } + + __checkReturn + HRESULT STDMETHODCALLTYPE Clone( + IStream **ppstm) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; + + return (BadError(E_NOTIMPL)); + } + + __checkReturn + static HRESULT CreateStreamOnMemory( // Return code. + void *pMem, // Memory to create stream on. + ULONG cbSize, // Size of data. + IStream **ppIStream, // Return stream object here. + BOOL fDeleteMemoryOnRelease = FALSE + ); + + __checkReturn + static HRESULT CreateStreamOnMemoryCopy( + void *pMem, + ULONG cbSize, + IStream **ppIStream); + +private: + void *m_pMem; // Memory for the read. + ULONG m_cbSize; // Size of the memory. + ULONG m_cbCurrent; // Current offset. + LONG m_cRef; // Ref count. + BYTE *m_dataCopy; // Optional copy of the data. +}; // class CInMemoryStream + +//***************************************************************************** +// CGrowableStream is a simple IStream implementation that grows as +// its written to. All the memory is contigious, so read access is +// fast. A grow does a realloc, so be aware of that if you're going to +// use this. +//***************************************************************************** + +// DPTR instead of VPTR because we don't actually call any of the virtuals. +typedef DPTR(class CGrowableStream) PTR_CGrowableStream; + +class CGrowableStream : public IStream +{ +public: + //Constructs a new GrowableStream + // multiplicativeGrowthRate - when the stream grows it will be at least this + // multiple of its old size. Values greater than 1 ensure O(N) amortized + // performance growing the stream to size N, 1 ensures O(N^2) amortized perf + // but gives the tightest memory usage. Valid range is [1.0, 2.0]. + // additiveGrowthRate - when the stream grows it will increase in size by at least + // this number of bytes. Larger numbers cause fewer re-allocations at the cost of + // increased memory usage. + CGrowableStream(float multiplicativeGrowthRate = 2.0, DWORD additiveGrowthRate = 4096); + +#ifndef DACCESS_COMPILE + virtual ~CGrowableStream(); +#endif + + // Expose the total raw buffer. + // This can be used by DAC to get the raw contents. + // This becomes potentiallyinvalid on the next call on the class, because the underlying storage can be + // reallocated. + MemoryRange GetRawBuffer() const + { + SUPPORTS_DAC; + PTR_VOID p = m_swBuffer; + return MemoryRange(p, m_dwBufferSize); + } + +private: + // Raw pointer to buffer. This may change as the buffer grows and gets reallocated. + PTR_BYTE m_swBuffer; + + // Total size of the buffer in bytes. + DWORD m_dwBufferSize; + + // Current index in the buffer. This can be moved around by Seek. + DWORD m_dwBufferIndex; + + // Logical length of the stream + DWORD m_dwStreamLength; + + // Reference count + LONG m_cRef; + + // growth rate parameters determine new stream size when it must grow + float m_multiplicativeGrowthRate; + int m_additiveGrowthRate; + + // Ensures the stream is physically and logically at least newLogicalSize + // in size + HRESULT EnsureCapacity(DWORD newLogicalSize); + + // IStream methods +public: + +#ifndef DACCESS_COMPILE + ULONG STDMETHODCALLTYPE AddRef() { + LIMITED_METHOD_CONTRACT; + return InterlockedIncrement(&m_cRef); + } + + + ULONG STDMETHODCALLTYPE Release(); + + __checkReturn + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); + + STDMETHOD(Read)( + void * pv, + ULONG cb, + ULONG * pcbRead); + + STDMETHOD(Write)( + const void * pv, + ULONG cb, + ULONG * pcbWritten); + + STDMETHOD(Seek)( + LARGE_INTEGER dlibMove, + DWORD dwOrigin, + ULARGE_INTEGER * plibNewPosition); + + STDMETHOD(SetSize)(ULARGE_INTEGER libNewSize); + + STDMETHOD(CopyTo)( + IStream * pstm, + ULARGE_INTEGER cb, + ULARGE_INTEGER * pcbRead, + ULARGE_INTEGER * pcbWritten) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } + + STDMETHOD(Commit)( + DWORD grfCommitFlags) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return NOERROR; } + + STDMETHOD(Revert)( void) {STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } + + STDMETHOD(LockRegion)( + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } + + STDMETHOD(UnlockRegion)( + ULARGE_INTEGER libOffset, + ULARGE_INTEGER cb, + DWORD dwLockType) {STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } + + STDMETHOD(Stat)( + STATSTG * pstatstg, + DWORD grfStatFlag); + + // Make a deep copy of the stream into a new CGrowableStream instance + STDMETHOD(Clone)( + IStream ** ppstm); + +#endif // DACCESS_COMPILE +}; // class CGrowableStream + +#endif // __StgPool_h__ diff --git a/lib/coreclr/src/inc/stgpooli.h b/lib/coreclr/src/inc/stgpooli.h new file mode 100644 index 0000000000..a29fa01e75 --- /dev/null +++ b/lib/coreclr/src/inc/stgpooli.h @@ -0,0 +1,256 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// StgPooli.h +// + +// +// This is helper code for the string and blob pools. It is here because it is +// secondary to the pooling interface and reduces clutter in the main file. +// +//***************************************************************************** + +#ifndef __StgPooli_h__ +#define __StgPooli_h__ + +#include "utilcode.h" // Base hashing code. + + + +// +// +// CPackedLen +// +// + +//***************************************************************************** +// Helper class to pack and unpack lengths. +//***************************************************************************** +struct CPackedLen +{ + enum {MAX_LEN = 0x1fffffff}; + static int Size(ULONG len) + { + LIMITED_METHOD_CONTRACT; + // Smallest. + if (len <= 0x7F) + return 1; + // Medium. + if (len <= 0x3FFF) + return 2; + // Large (too large?). + _ASSERTE(len <= MAX_LEN); + return 4; + } + + // Get a pointer to the data, and store the length. + static void const *GetData(void const *pData, ULONG *pLength); + + // Get the length value encoded at *pData. Update ppData to point past data. + static ULONG GetLength(void const *pData, void const **ppData=0); + + // Get the length value encoded at *pData, and the size of that encoded value. + static ULONG GetLength(void const *pData, int *pSizeOfLength); + + // Pack a length at *pData; return a pointer to the next byte. + static void* PutLength(void *pData, ULONG len); + + // This is used for just getting an encoded length, and verifies that + // there is no buffer or integer overflow. + static HRESULT SafeGetLength( // S_OK, or error + void const *pDataSource, // First byte of length. + void const *pDataSourceEnd, // End of valid source data memory + ULONG *pLength, // Encoded value + void const **ppDataNext); // Pointer immediately following encoded length + + static HRESULT SafeGetLength( // S_OK, or error + BYTE const *pDataSource, // First byte of length. + BYTE const *pDataSourceEnd, // End of valid source data memory + ULONG *pLength, // Encoded value + BYTE const **ppDataNext) // Pointer immediately following encoded length + { + return SafeGetLength( + reinterpret_cast(pDataSource), + reinterpret_cast(pDataSourceEnd), + pLength, + reinterpret_cast(ppDataNext)); + } + + // This performs the same tasks as GetLength above in addition to checking + // that the value in *pcbData does not extend *ppData beyond pDataSourceEnd + // and does not cause an integer overflow. + static HRESULT SafeGetData( + void const *pDataSource, // First byte of length. + void const *pDataSourceEnd, // End of valid source data memory + ULONG *pcbData, // Length of data + void const **ppData); // Start of data + + static HRESULT SafeGetData( + BYTE const *pDataSource, // First byte of length. + BYTE const *pDataSourceEnd, // End of valid source data memory + ULONG *pcbData, // Length of data + BYTE const **ppData) // Start of data + { + return SafeGetData( + reinterpret_cast(pDataSource), + reinterpret_cast(pDataSourceEnd), + pcbData, + reinterpret_cast(ppData)); + } + + // This is the same as GetData above except it takes a byte count instead + // of pointer to determine the source data length. + static HRESULT SafeGetData( // S_OK, or error + void const *pDataSource, // First byte of data + ULONG cbDataSource, // Count of valid bytes in data source + ULONG *pcbData, // Length of data + void const **ppData); // Start of data + + static HRESULT SafeGetData( + BYTE const *pDataSource, // First byte of length. + ULONG cbDataSource, // Count of valid bytes in data source + ULONG *pcbData, // Length of data + BYTE const **ppData) // Start of data + { + return SafeGetData( + reinterpret_cast(pDataSource), + cbDataSource, + pcbData, + reinterpret_cast(ppData)); + } +}; + + +class StgPoolReadOnly; + +//***************************************************************************** +// This hash class will handle strings inside of a chunk of the pool. +//***************************************************************************** +struct STRINGHASH : HASHLINK +{ + ULONG iOffset; // Offset of this item. +}; + +class CStringPoolHash : public CChainedHash +{ + friend class VerifyLayoutsMD; +public: + CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + { + LIMITED_METHOD_CONTRACT; + } + + virtual bool InUse(STRINGHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + return (pItem->iOffset != 0xffffffff); + } + + virtual void SetFree(STRINGHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + pItem->iOffset = 0xffffffff; + } + + virtual ULONG Hash(const void *pData) + { + WRAPPER_NO_CONTRACT; + return (HashStringA(reinterpret_cast(pData))); + } + + virtual int Cmp(const void *pData, void *pItem); + +private: + StgPoolReadOnly *m_Pool; // String pool which this hashes. +}; + + +//***************************************************************************** +// This version is for byte streams with a 2 byte WORD giving the length of +// the data. +//***************************************************************************** +typedef STRINGHASH BLOBHASH; + +class CBlobPoolHash : public CChainedHash +{ + friend class VerifyLayoutsMD; +public: + CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + { + LIMITED_METHOD_CONTRACT; + } + + virtual bool InUse(BLOBHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + return (pItem->iOffset != 0xffffffff); + } + + virtual void SetFree(BLOBHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + pItem->iOffset = 0xffffffff; + } + + virtual ULONG Hash(const void *pData) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_FORBID_FAULT; + + ULONG ulSize; + ulSize = CPackedLen::GetLength(pData); + ulSize += CPackedLen::Size(ulSize); + return (HashBytes(reinterpret_cast(pData), ulSize)); + } + + virtual int Cmp(const void *pData, void *pItem); + +private: + StgPoolReadOnly *m_Pool; // Blob pool which this hashes. +}; + +//***************************************************************************** +// This hash class will handle guids inside of a chunk of the pool. +//***************************************************************************** +struct GUIDHASH : HASHLINK +{ + ULONG iIndex; // Index of this item. +}; + +class CGuidPoolHash : public CChainedHash +{ + friend class VerifyLayoutsMD; +public: + CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) + { + LIMITED_METHOD_CONTRACT; + } + + virtual bool InUse(GUIDHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + return (pItem->iIndex != 0xffffffff); + } + + virtual void SetFree(GUIDHASH *pItem) + { + LIMITED_METHOD_CONTRACT; + pItem->iIndex = 0xffffffff; + } + + virtual ULONG Hash(const void *pData) + { + WRAPPER_NO_CONTRACT; + return (HashBytes(reinterpret_cast(pData), sizeof(GUID))); + } + + virtual int Cmp(const void *pData, void *pItem); + +private: + StgPoolReadOnly *m_Pool; // The GUID pool which this hashes. +}; + + +#endif // __StgPooli_h__ diff --git a/lib/coreclr/src/inc/stresslog.h b/lib/coreclr/src/inc/stresslog.h new file mode 100644 index 0000000000..8e509e5f4e --- /dev/null +++ b/lib/coreclr/src/inc/stresslog.h @@ -0,0 +1,846 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*************************************************************************************/ +/* StressLog.h */ +/*************************************************************************************/ + +/* StressLog is a binary, memory based circular queue of logging messages. It is + intended to be used in retail builds during stress runs (activated + by registry key), so to help find bugs that only turn up during stress runs. + + It is meant to have very low overhead and can not cause deadlocks, etc. It is + however thread safe */ + +/* The log has a very simple structure, and it meant to be dumped from a NTSD + extention (eg. strike). There is no memory allocation system calls etc to purtub things */ + +// ****************************************************************************** +// WARNING!!!: These classes are used by SOS in the diagnostics repo. Values should +// added or removed in a backwards and forwards compatible way. +// See: https://github.com/dotnet/diagnostics/blob/master/src/inc/stresslog.h +// Parser: https://github.com/dotnet/diagnostics/blob/master/src/SOS/Strike/stressLogDump.cpp +// ****************************************************************************** + +/*************************************************************************************/ + +#ifndef StressLog_h +#define StressLog_h 1 + +#include "log.h" + +#if defined(STRESS_LOG) && !defined(FEATURE_NO_STRESSLOG) +#include "holder.h" +#include "staticcontract.h" +#include "mscoree.h" +#include "clrinternal.h" +#ifdef STRESS_LOG_READONLY +#include // offsetof +#else //STRESS_LOG_READONLY +#include "clrhost.h" +#endif //STRESS_LOG_READONLY + +#ifndef _ASSERTE +#define _ASSERTE(expr) +#endif + +/* The STRESS_LOG* macros work like printf. In fact the use printf in their implementation + so all printf format specifications work. In addition the Stress log dumper knows + about certain suffixes for the %p format specification (normally used to print a pointer) + + %pM // The pointer is a MethodDesc + %pT // The pointer is a type (MethodTable) + %pV // The pointer is a C++ Vtable pointer (useful for distinguishing different types of frames + %pK // The pointer is a code address (used for stack track) +*/ + +/* STRESS_LOG_VA was added to allow sendign GC trace output to the stress log. msg must be enclosed + in ()'s and contain a format string followed by 0 - 4 arguments. The arguments must be numbers or + string literals. LogMsgOL is overloaded so that all of the possible sets of parameters are covered. + This was done becasue GC Trace uses dprintf which dosen't contain info on how many arguments are + getting passed in and using va_args would require parsing the format string during the GC +*/ +#define STRESS_LOG_VA(msg) do { \ + if (StressLog::LogOn(LF_GC, LL_ALWAYS)) \ + StressLog::LogMsgOL msg; \ + LogSpewAlways msg; \ + } while(0) + +#define STRESS_LOG0(facility, level, msg) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 0, msg); \ + LOG((facility, level, msg)); \ + } while(0) + +#define STRESS_LOG1(facility, level, msg, data1) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 1, msg, (void*)(size_t)(data1));\ + LOG((facility, level, msg, data1)); \ + } while(0) + +#define STRESS_LOG2(facility, level, msg, data1, data2) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 2, msg, \ + (void*)(size_t)(data1), (void*)(size_t)(data2)); \ + LOG((facility, level, msg, data1, data2)); \ + } while(0) + +#define STRESS_LOG2_CHECK_EE_STARTED(facility, level, msg, data1, data2) do { \ + if (g_fEEStarted) \ + STRESS_LOG2(facility, level, msg, data1, data2); \ + else \ + LOG((facility, level, msg, data1, data2)); \ + } while(0) + +#define STRESS_LOG3(facility, level, msg, data1, data2, data3) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 3, msg, \ + (void*)(size_t)(data1),(void*)(size_t)(data2),(void*)(size_t)(data3)); \ + LOG((facility, level, msg, data1, data2, data3)); \ + } while(0) + +#define STRESS_LOG4(facility, level, msg, data1, data2, data3, data4) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 4, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4)); \ + LOG((facility, level, msg, data1, data2, data3, data4)); \ + } while(0) + +#define STRESS_LOG5(facility, level, msg, data1, data2, data3, data4, data5) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 5, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5)); \ + } while(0) + +#define STRESS_LOG6(facility, level, msg, data1, data2, data3, data4, data5, data6) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 6, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5), (void*)(size_t)(data6)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5, data6)); \ + } while(0) + +#define STRESS_LOG7(facility, level, msg, data1, data2, data3, data4, data5, data6, data7) do { \ + if (StressLog::LogOn(facility, level)) \ + StressLog::LogMsg(level, facility, 7, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5), (void*)(size_t)(data6), (void*)(size_t)(data7)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5, data6, data7)); \ + } while(0) + +#define STRESS_LOG_COND0(facility, level, cond, msg) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 0, msg); \ + LOG((facility, level, msg)); \ + } while(0) + +#define STRESS_LOG_COND1(facility, level, cond, msg, data1) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 1, msg, (void*)(size_t)(data1)); \ + LOG((facility, level, msg, data1)); \ + } while(0) + +#define STRESS_LOG_COND2(facility, level, cond, msg, data1, data2) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 2, msg, \ + (void*)(size_t)(data1), (void*)(size_t)(data2)); \ + LOG((facility, level, msg, data1, data2)); \ + } while(0) + +#define STRESS_LOG_COND3(facility, level, cond, msg, data1, data2, data3) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 3, msg, \ + (void*)(size_t)(data1),(void*)(size_t)(data2),(void*)(size_t)(data3)); \ + LOG((facility, level, msg, data1, data2, data3)); \ + } while(0) + +#define STRESS_LOG_COND4(facility, level, cond, msg, data1, data2, data3, data4) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 4, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4)); \ + LOG((facility, level, msg, data1, data2, data3, data4)); \ + } while(0) + +#define STRESS_LOG_COND5(facility, level, cond, msg, data1, data2, data3, data4, data5) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 5, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5)); \ + } while(0) + +#define STRESS_LOG_COND6(facility, level, cond, msg, data1, data2, data3, data4, data5, data6) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 6, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5), (void*)(size_t)(data6)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5, data6)); \ + } while(0) + +#define STRESS_LOG_COND7(facility, level, cond, msg, data1, data2, data3, data4, data5, data6, data7) do { \ + if (StressLog::LogOn(facility, level) && (cond)) \ + StressLog::LogMsg(level, facility, 7, msg, (void*)(size_t)(data1), \ + (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ + (void*)(size_t)(data5), (void*)(size_t)(data6), (void*)(size_t)(data7)); \ + LOG((facility, level, msg, data1, data2, data3, data4, data5, data6, data7)); \ + } while(0) + +#define STRESS_LOG_RESERVE_MEM(numChunks) do { \ + if (StressLog::StressLogOn(LF_ALL, LL_ALWAYS)) \ + {StressLog::ReserveStressLogChunks (numChunks);} \ + } while(0) +// !!! WARNING !!! +// !!! DO NOT ADD STRESS_LOG8, as the stress log infrastructure supports a maximum of 7 arguments +// !!! WARNING !!! + +#define STRESS_LOG_PLUG_MOVE(plug_start, plug_end, plug_delta) do { \ + if (StressLog::LogOn(LF_GC, LL_INFO1000)) \ + StressLog::LogMsg(LL_INFO1000, LF_GC, 3, ThreadStressLog::gcPlugMoveMsg(), \ + (void*)(size_t)(plug_start), (void*)(size_t)(plug_end), (void*)(size_t)(plug_delta)); \ + LOG((LF_GC, LL_INFO10000, ThreadStressLog::gcPlugMoveMsg(), (plug_start), (plug_end), (plug_delta))); \ + } while(0) + +#define STRESS_LOG_ROOT_PROMOTE(root_addr, objPtr, methodTable) do { \ + if (StressLog::LogOn(LF_GC|LF_GCROOTS, LL_INFO1000)) \ + StressLog::LogMsg(LL_INFO1000, LF_GC|LF_GCROOTS, 3, ThreadStressLog::gcRootPromoteMsg(), \ + (void*)(size_t)(root_addr), (void*)(size_t)(objPtr), (void*)(size_t)(methodTable)); \ + LOG((LF_GC|LF_GCROOTS, LL_INFO1000000, ThreadStressLog::gcRootPromoteMsg(), (root_addr), (objPtr), (methodTable))); \ + } while(0) + +#define STRESS_LOG_ROOT_RELOCATE(root_addr, old_value, new_value, methodTable) do { \ + if (StressLog::LogOn(LF_GC|LF_GCROOTS, LL_INFO1000) && ((size_t)(old_value) != (size_t)(new_value))) \ + StressLog::LogMsg(LL_INFO1000, LF_GC|LF_GCROOTS, 4, ThreadStressLog::gcRootMsg(), \ + (void*)(size_t)(root_addr), (void*)(size_t)(old_value), \ + (void*)(size_t)(new_value), (void*)(size_t)(methodTable)); \ + LOG((LF_GC|LF_GCROOTS, LL_INFO10000, ThreadStressLog::gcRootMsg(), (root_addr), (old_value), (new_value), (methodTable))); \ + } while(0) + +#define STRESS_LOG_GC_START(gcCount, Gen, collectClasses) do { \ + if (StressLog::LogOn(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10)) \ + StressLog::LogMsg(LL_INFO10, LF_GCROOTS|LF_GC|LF_GCALLOC, 3, ThreadStressLog::gcStartMsg(), \ + (void*)(size_t)(gcCount), (void*)(size_t)(Gen), (void*)(size_t)(collectClasses)); \ + LOG((LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, ThreadStressLog::gcStartMsg(), (gcCount), (Gen), (collectClasses))); \ + } while(0) + +#define STRESS_LOG_GC_END(gcCount, Gen, collectClasses) do { \ + if (StressLog::LogOn(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10)) \ + StressLog::LogMsg(LL_INFO10, LF_GCROOTS|LF_GC|LF_GCALLOC, 3, ThreadStressLog::gcEndMsg(), \ + (void*)(size_t)(gcCount), (void*)(size_t)(Gen), (void*)(size_t)(collectClasses), 0); \ + LOG((LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, ThreadStressLog::gcEndMsg(), (gcCount), (Gen), (collectClasses))); \ + } while(0) + +#if defined(_DEBUG) +#define MAX_CALL_STACK_TRACE 20 +#define STRESS_LOG_OOM_STACK(size) do { \ + CantAllocHolder caHolder; \ + if (StressLog::LogOn(LF_EEMEM, LL_ALWAYS)) \ + { \ + StressLog::LogMsgOL("OOM on alloc of size %x \n", (void*)(size_t)(size)); \ + StressLog::LogCallStack ("OOM"); \ + } \ + } while(0) +#define STRESS_LOG_GC_STACK do { \ + if (StressLog::LogOn(LF_GC |LF_GCINFO, LL_ALWAYS)) \ + { \ + StressLog::LogMsgOL("GC is triggered \n"); \ + StressLog::LogCallStack ("GC"); \ + } \ + } while(0) + +#else //!_DEBUG +#define STRESS_LOG_OOM_STACK(size) +#define STRESS_LOG_GC_STACK +#endif //_DEBUG + +class ThreadStressLog; + +/*************************************************************************************/ +/* a log is a circular queue of messages */ + +class StressLog { +public: + static void Initialize(unsigned facilities, unsigned level, unsigned maxBytesPerThread, + unsigned maxBytesTotal, HMODULE hMod); + static void Terminate(BOOL fProcessDetach=FALSE); + static void ThreadDetach(ThreadStressLog *msgs); // call at DllMain THREAD_DETACH if you want to recycle thread logs + static int NewChunk () + { + return InterlockedIncrement (&theLog.totalChunk); + } + static int ChunkDeleted () + { + return InterlockedDecrement (&theLog.totalChunk); + } + + //the result is not 100% accurate. If multiple threads call this funciton at the same time, + //we could allow the total size be bigger than required. But the memory won't grow forever + //and this is not critical so we don't try to fix the race + static BOOL AllowNewChunk (LONG numChunksInCurThread); + + //preallocate Stress log chunks for current thread. The memory we could preallocate is still + //bounded by per thread size limit and total size limit. If chunksToReserve is 0, we will try to + //preallocate up to per thread size limit + static BOOL ReserveStressLogChunks (unsigned chunksToReserve); + + // used by out of process debugger to dump the stress log to 'fileName' + // IDebugDataSpaces is the NTSD execution callback for getting process memory. + // This function is defined in the tools\strike\stressLogDump.cpp file + static HRESULT Dump(ULONG64 logAddr, const char* fileName, struct IDebugDataSpaces* memCallBack); + + static BOOL StressLogOn(unsigned facility, unsigned level); + static BOOL ETWLogOn(unsigned facility, unsigned level); + static BOOL LogOn(unsigned facility, unsigned level); + +// private: + unsigned facilitiesToLog; // Bitvector of facilities to log (see loglf.h) + unsigned levelToLog; // log level (see log.h) + unsigned MaxSizePerThread; // maximum number of bytes each thread should have before wrapping + unsigned MaxSizeTotal; //maximum memory allowed for stress log + Volatile totalChunk; //current number of total chunks allocated + Volatile logs; // the list of logs for every thread. + Volatile TLSslot; // Each thread gets a log this is used to fetch each threads log + Volatile deadCount; // count of dead threads in the log + CRITSEC_COOKIE lock; // lock + unsigned __int64 tickFrequency; // number of ticks per second + unsigned __int64 startTimeStamp; // start time from when tick counter started + FILETIME startTime; // time the application started + SIZE_T moduleOffset; // Used to compute format strings. + +// private: + static void Enter(CRITSEC_COOKIE dummy = NULL); + static void Leave(CRITSEC_COOKIE dummy = NULL); + static ThreadStressLog* CreateThreadStressLog(); + static ThreadStressLog* CreateThreadStressLogHelper(); + + static BOOL InlinedStressLogOn(unsigned facility, unsigned level); + static BOOL InlinedETWLogOn(unsigned facility, unsigned level); + + static void LogMsg(unsigned level, unsigned facility, int cArgs, const char* format, ... ); + +// Support functions for STRESS_LOG_VA +// We disable the warning "conversion from 'type' to 'type' of greater size" since everything will +// end up on the stack, and LogMsg will know the size of the variable based on the format string. +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4312 ) +#endif + static void LogMsgOL(const char* format) + { LogMsg(LL_ALWAYS, LF_GC, 0, format); } + + template < typename T1 > + static void LogMsgOL(const char* format, T1 data1) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 1, format, (void*)(size_t)data1); + } + + template < typename T1, typename T2 > + static void LogMsgOL(const char* format, T1 data1, T2 data2) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 2, format, (void*)(size_t)data1, (void*)(size_t)data2); + } + + template < typename T1, typename T2, typename T3 > + static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 3, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3); + } + + template < typename T1, typename T2, typename T3, typename T4 > + static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 4, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4); + } + + template < typename T1, typename T2, typename T3, typename T4, typename T5 > + static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 5, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5); + } + + template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > + static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 6, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6); + } + + template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > + static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7) + { + static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*)); + LogMsg(LL_ALWAYS, LF_GC, 7, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7); + } + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +// We can only log the stacktrace on DEBUG builds! +#ifdef _DEBUG +typedef USHORT +(__stdcall *PFNRtlCaptureStackBackTrace)( + IN ULONG FramesToSkip, + IN ULONG FramesToCapture, + OUT PVOID * BackTrace, + OUT PULONG BackTraceHash); + + PFNRtlCaptureStackBackTrace RtlCaptureStackBackTrace; + + static void LogCallStack(const char *const callTag); +#endif //_DEBUG + +// private: // static variables + static StressLog theLog; // We only have one log, and this is it +}; + +typedef Holder> StressLogLockHolder; + +#if defined(DACCESS_COMPILE) +inline BOOL StressLog::LogOn(unsigned facility, unsigned level) +{ + STATIC_CONTRACT_LEAF; + STATIC_CONTRACT_SUPPORTS_DAC; + + // StressLog isn't dacized, and besides we don't want to log to it in DAC builds. + return FALSE; +} +#endif + +/*************************************************************************************/ +/* private classes */ + +#if defined(_MSC_VER) +#pragma warning(disable:4200 4201) // don't warn about 0 sized array below or unnamed structures +#endif + +// The order of fields is important. Keep the prefix length as the first field. +// And make sure the timeStamp field is naturally alligned, so we don't waste +// space on 32-bit platforms +struct StressMsg { + union { + struct { + uint32_t numberOfArgs : 3; // at most 7 arguments + uint32_t formatOffset : 29; // offset of string in mscorwks + }; + uint32_t fmtOffsCArgs; // for optimized access + }; + uint32_t facility; // facility used to log the entry + uint64_t timeStamp; // time when mssg was logged + void* args[0]; // size given by numberOfArgs + + static const size_t maxArgCnt = 7; + static const size_t maxOffset = 0x20000000; + static size_t maxMsgSize () + { return sizeof(StressMsg) + maxArgCnt*sizeof(void*); } + + friend class ThreadStressLog; + friend class StressLog; +}; +#ifdef _WIN64 +#define STRESSLOG_CHUNK_SIZE (32 * 1024) +#else //_WIN64 +#define STRESSLOG_CHUNK_SIZE (16 * 1024) +#endif //_WIN64 +#define GC_STRESSLOG_MULTIPLY 5 + +// a chunk of memory for stress log +struct StressLogChunk +{ + StressLogChunk * prev; + StressLogChunk * next; + char buf[STRESSLOG_CHUNK_SIZE]; + DWORD dwSig1; + DWORD dwSig2; + +#if !defined(STRESS_LOG_READONLY) + static HANDLE s_LogChunkHeap; + + void * operator new (size_t) throw() + { + if (IsInCantAllocStressLogRegion ()) + { + return NULL; + } + + _ASSERTE (s_LogChunkHeap != NULL); + //no need to zero memory because we could handle garbage contents + return ClrHeapAlloc (s_LogChunkHeap, 0, S_SIZE_T(sizeof (StressLogChunk))); + } + + void operator delete (void * chunk) + { + _ASSERTE (s_LogChunkHeap != NULL); + ClrHeapFree (s_LogChunkHeap, 0, chunk); + } +#endif //!STRESS_LOG_READONLY + + StressLogChunk (StressLogChunk * p = NULL, StressLogChunk * n = NULL) + :prev (p), next (n), dwSig1 (0xCFCFCFCF), dwSig2 (0xCFCFCFCF) + {} + + char * StartPtr () + { + return buf; + } + + char * EndPtr () + { + return buf + STRESSLOG_CHUNK_SIZE; + } + + BOOL IsValid () const + { + return dwSig1 == 0xCFCFCFCF && dwSig2 == 0xCFCFCFCF; + } +}; + +// This class implements a circular stack of variable sized elements +// .The buffer between startPtr-endPtr is used in a circular manner +// to store instances of the variable-sized struct StressMsg. +// The StressMsg are always aligned to endPtr, while the space +// left between startPtr and the last element is 0-padded. +// .curPtr points to the most recently written log message +// .readPtr points to the next log message to be dumped +// .hasWrapped is TRUE while dumping the log, if we had wrapped +// past the endPtr marker, back to startPtr +// The AdvanceRead/AdvanceWrite operations simply update the +// readPtr / curPtr fields. thecaller is responsible for reading/writing +// to the corresponding field +class ThreadStressLog { + ThreadStressLog* next; // we keep a linked list of these + uint64_t threadId; // the id for the thread using this buffer + uint8_t isDead; // Is this thread dead + uint8_t readHasWrapped; // set when read ptr has passed chunListTail + uint8_t writeHasWrapped; // set when write ptr has passed chunListHead + StressMsg* curPtr; // where packets are being put on the queue + StressMsg* readPtr; // where we are reading off the queue (used during dumping) + StressLogChunk * chunkListHead; //head of a list of stress log chunks + StressLogChunk * chunkListTail; //tail of a list of stress log chunks + StressLogChunk * curReadChunk; //the stress log chunk we are currently reading + StressLogChunk * curWriteChunk; //the stress log chunk we are currently writing + long chunkListLength; // how many stress log chunks are in this stress log + +#ifdef STRESS_LOG_READONLY + FORCEINLINE StressMsg* AdvanceRead(); +#endif //STRESS_LOG_READONLY + FORCEINLINE StressMsg* AdvanceWrite(int cArgs); + +#ifdef STRESS_LOG_READONLY + inline StressMsg* AdvReadPastBoundary(); +#endif //STRESS_LOG_READONLY + inline StressMsg* AdvWritePastBoundary(int cArgs); + +#ifdef STRESS_LOG_READONLY + ThreadStressLog* FindLatestThreadLog() const; +#endif //STRESS_LOG_READONLY + friend class StressLog; + +#ifndef STRESS_LOG_READONLY + FORCEINLINE BOOL GrowChunkList () + { + _ASSERTE (chunkListLength >= 1); + if (!StressLog::AllowNewChunk (chunkListLength)) + { + return FALSE; + } + StressLogChunk * newChunk = new StressLogChunk (chunkListTail, chunkListHead); + if (newChunk == NULL) + { + return FALSE; + } + StressLog::NewChunk (); + chunkListLength++; + chunkListHead->prev = newChunk; + chunkListTail->next = newChunk; + chunkListHead = newChunk; + + return TRUE; + } +#endif //!STRESS_LOG_READONLY + +public: +#ifndef STRESS_LOG_READONLY + ThreadStressLog () + { + chunkListHead = chunkListTail = curWriteChunk = NULL; + StressLogChunk * newChunk =new StressLogChunk; + //OOM or in cantalloc region + if (newChunk == NULL) + { + return; + } + StressLog::NewChunk (); + + newChunk->prev = newChunk; + newChunk->next = newChunk; + + chunkListHead = chunkListTail = newChunk; + + next = NULL; + threadId = 0; + isDead = TRUE; + curPtr = NULL; + readPtr = NULL; + writeHasWrapped = FALSE; + curReadChunk = NULL; + curWriteChunk = NULL; + chunkListLength = 1; + } + +#endif //!STRESS_LOG_READONLY + ~ThreadStressLog () + { + //no thing to do if the list is empty (failed to initialize) + if (chunkListHead == NULL) + { + return; + } +#ifndef STRESS_LOG_READONLY + _ASSERTE (chunkListLength >= 1 && chunkListLength <= StressLog::theLog.totalChunk); +#endif //!STRESS_LOG_READONLY + StressLogChunk * chunk = chunkListHead; + + do + { + StressLogChunk * tmp = chunk; + chunk = chunk->next; + delete tmp; +#ifndef STRESS_LOG_READONLY + StressLog::ChunkDeleted (); +#endif //!STRESS_LOG_READONLY + } while (chunk != chunkListHead); + } + + void Activate () + { +#ifndef STRESS_LOG_READONLY + //there is no need to zero buffers because we could handle garbage contents + threadId = GetCurrentThreadId (); + isDead = FALSE; + curWriteChunk = chunkListTail; + curPtr = (StressMsg *)curWriteChunk->EndPtr (); + writeHasWrapped = FALSE; +#else //STRESS_LOG_READONLY + curReadChunk = curWriteChunk; + readPtr = curPtr; + readHasWrapped = FALSE; + // the last written log, if it wrapped around may have partially overwritten + // a previous record. Update curPtr to reflect the last safe beginning of a record, + // but curPtr shouldn't wrap around, otherwise it'll break our assumptions about stress + // log + curPtr = (StressMsg*)((char*)curPtr - StressMsg::maxMsgSize()); + if (curPtr < (StressMsg*)curWriteChunk->StartPtr()) + { + curPtr = (StressMsg *)curWriteChunk->StartPtr(); + } + //corner case: the log is empty + if (readPtr == (StressMsg *)curReadChunk->EndPtr ()) + { + AdvReadPastBoundary(); + } +#endif //!STRESS_LOG_READONLY + } + + BOOL IsValid () const + { + return chunkListHead != NULL && (!curWriteChunk || curWriteChunk->IsValid ()); + } + +#ifdef STRESS_LOG_READONLY + // Called while dumping. Returns true after all messages in log were dumped + FORCEINLINE BOOL CompletedDump () + { + return readPtr->timeStamp == 0 + //if read has passed end of list but write has not passed head of list yet, we are done + //if write has also wrapped, we are at the end if read pointer passed write pointer + || (readHasWrapped && + (!writeHasWrapped || (curReadChunk == curWriteChunk && readPtr >= curPtr))); + } +#endif //STRESS_LOG_READONLY + + static const char* gcStartMsg() + { + STATIC_CONTRACT_LEAF; + return "{ =========== BEGINGC %d, (requested generation = %lu, collect_classes = %lu) ==========\n"; + } + + static const char* gcEndMsg() + { + STATIC_CONTRACT_LEAF; + return "========== ENDGC %d (gen = %lu, collect_classes = %lu) ===========}\n"; + } + + static const char* gcRootMsg() + { + STATIC_CONTRACT_LEAF; + return " GC Root %p RELOCATED %p -> %p MT = %pT\n"; + } + + static const char* gcRootPromoteMsg() + { + STATIC_CONTRACT_LEAF; + return " IGCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; + } + + static const char* gcPlugMoveMsg() + { + STATIC_CONTRACT_LEAF; + return "GC_HEAP RELOCATING Objects in heap within range [%p %p) by -0x%x bytes\n"; + } + + static const char* TaskSwitchMsg() + { + STATIC_CONTRACT_LEAF; + return "StressLog TaskSwitch Marker\n"; + } + + void LogMsg (unsigned facility, int cArgs, const char* format, ... ) + { + va_list Args; + va_start(Args, format); + LogMsg (facility, cArgs, format, Args); + va_end(Args); + } + void LogMsg (unsigned facility, int cArgs, const char* format, va_list Args); +#ifdef STRESS_LOG_READONLY + static size_t OffsetOfNext () {return offsetof (ThreadStressLog, next);} + static size_t OffsetOfListHead () {return offsetof (ThreadStressLog, chunkListHead);} +#endif //STRESS_LOG_READONLY +}; + +#ifdef STRESS_LOG_READONLY +/*********************************************************************************/ +// Called when dumping the log (by StressLog::Dump()) +// Updates readPtr to point to next stress messaage to be dumped +// For convenience it returns the new value of readPtr +inline StressMsg* ThreadStressLog::AdvanceRead() { + STATIC_CONTRACT_LEAF; + // advance the marker + readPtr = (StressMsg*)((char*)readPtr + sizeof(StressMsg) + readPtr->numberOfArgs*sizeof(void*)); + // wrap around if we need to + if (readPtr >= (StressMsg *)curReadChunk->EndPtr ()) + { + AdvReadPastBoundary(); + } + return readPtr; +} + +// It's the factored-out slow codepath for AdvanceRead() and +// is only called by AdvanceRead(). +// Updates readPtr to and returns the first stress message >= startPtr +inline StressMsg* ThreadStressLog::AdvReadPastBoundary() { + STATIC_CONTRACT_LEAF; + //if we pass boundary of tail list, we need to set has Wrapped + if (curReadChunk == chunkListTail) + { + readHasWrapped = TRUE; + //If write has not wrapped, we know the contents from list head to + //cur pointer is garbage, we don't need to read them + if (!writeHasWrapped) + { + return readPtr; + } + } + curReadChunk = curReadChunk->next; + void** p = (void**)curReadChunk->StartPtr(); + while (*p == NULL && (size_t)(p-(void**)curReadChunk->StartPtr ()) < (StressMsg::maxMsgSize()/sizeof(void*))) + { + ++p; + } + // if we failed to find a valid start of a StressMsg fallback to startPtr (since timeStamp==0) + if (*p == NULL) + { + p = (void**) curReadChunk->StartPtr (); + } + readPtr = (StressMsg*)p; + + return readPtr; +} +#endif //STRESS_LOG_READONLY +/*********************************************************************************/ +// Called at runtime when writing the log (by StressLog::LogMsg()) +// Updates curPtr to point to the next spot in the log where we can write +// a stress message with cArgs arguments +// For convenience it returns a pointer to the empty slot where we can +// write the next stress message. +// cArgs is the number of arguments in the message to be written. +inline StressMsg* ThreadStressLog::AdvanceWrite(int cArgs) { + STATIC_CONTRACT_LEAF; + // _ASSERTE(cArgs <= StressMsg::maxArgCnt); + // advance the marker + StressMsg* p = (StressMsg*)((char*)curPtr - sizeof(StressMsg) - cArgs*sizeof(void*)); + + //past start of current chunk + //wrap around if we need to + if (p < (StressMsg*)curWriteChunk->StartPtr ()) + { + curPtr = AdvWritePastBoundary(cArgs); + } + else + { + curPtr = p; + } + + return curPtr; +} + +// It's the factored-out slow codepath for AdvanceWrite() and +// is only called by AdvanceWrite(). +// Returns the stress message flushed against endPtr +// In addition it writes NULLs b/w the startPtr and curPtr +inline StressMsg* ThreadStressLog::AdvWritePastBoundary(int cArgs) { + STATIC_CONTRACT_WRAPPER; +#ifndef STRESS_LOG_READONLY + //zeroed out remaining buffer + memset (curWriteChunk->StartPtr (), 0, (BYTE *)curPtr - (BYTE *)curWriteChunk->StartPtr ()); + + //if we are already at head of the list, try to grow the list + if (curWriteChunk == chunkListHead) + { + GrowChunkList (); + } +#endif //!STRESS_LOG_READONLY + + curWriteChunk = curWriteChunk->prev; +#ifndef STRESS_LOG_READONLY + if (curWriteChunk == chunkListTail) + { + writeHasWrapped = TRUE; + } +#endif //STRESS_LOG_READONLY + curPtr = (StressMsg*)((char*)curWriteChunk->EndPtr () - sizeof(StressMsg) - cArgs * sizeof(void*)); + return curPtr; +} + +#else // STRESS_LOG + +#define STRESS_LOG_VA(msg) do { } while(0) +#define STRESS_LOG0(facility, level, msg) do { } while(0) +#define STRESS_LOG1(facility, level, msg, data1) do { } while(0) +#define STRESS_LOG2(facility, level, msg, data1, data2) do { } while(0) +#define STRESS_LOG2_CHECK_EE_STARTED(facility, level, msg, data1, data2)do { } while(0) +#define STRESS_LOG3(facility, level, msg, data1, data2, data3) do { } while(0) +#define STRESS_LOG4(facility, level, msg, data1, data2, data3, data4) do { } while(0) +#define STRESS_LOG5(facility, level, msg, data1, data2, data3, data4, data5) do { } while(0) +#define STRESS_LOG6(facility, level, msg, data1, data2, data3, data4, data5, data6) do { } while(0) +#define STRESS_LOG7(facility, level, msg, data1, data2, data3, data4, data5, data6, data7) do { } while(0) +#define STRESS_LOG_PLUG_MOVE(plug_start, plug_end, plug_delta) do { } while(0) +#define STRESS_LOG_ROOT_PROMOTE(root_addr, objPtr, methodTable) do { } while(0) +#define STRESS_LOG_ROOT_RELOCATE(root_addr, old_value, new_value, methodTable) do { } while(0) +#define STRESS_LOG_GC_START(gcCount, Gen, collectClasses) do { } while(0) +#define STRESS_LOG_GC_END(gcCount, Gen, collectClasses) do { } while(0) +#define STRESS_LOG_OOM_STACK(size) do { } while(0) +#define STRESS_LOG_GC_STACK(size) do { } while(0) +#define STRESS_LOG_RESERVE_MEM(numChunks) do {} while (0) +#endif // STRESS_LOG + +#endif // StressLog_h diff --git a/lib/coreclr/src/inc/stringarraylist.h b/lib/coreclr/src/inc/stringarraylist.h new file mode 100644 index 0000000000..10401ac31b --- /dev/null +++ b/lib/coreclr/src/inc/stringarraylist.h @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef STRINGARRAYLIST_H_ +#define STRINGARRAYLIST_H_ + + +// +// StringArrayList is a simple class which is used to contain a growable +// list of Strings, stored in chunks. Based on top of ArrayList +#include "arraylist.h" + + +class StringArrayList +{ + ArrayList m_Elements; +public: + DWORD GetCount() const; + SString& operator[] (DWORD idx) const; + SString& Get (DWORD idx) const; +#ifndef DACCESS_COMPILE + void Append(const SString& string); + void AppendIfNotThere(const SString& string); +#endif + ~StringArrayList(); +}; + + +#include "stringarraylist.inl" +#endif diff --git a/lib/coreclr/src/inc/stringarraylist.inl b/lib/coreclr/src/inc/stringarraylist.inl new file mode 100644 index 0000000000..73ca405537 --- /dev/null +++ b/lib/coreclr/src/inc/stringarraylist.inl @@ -0,0 +1,76 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "ex.h" + +inline SString& StringArrayList::operator[] (DWORD idx) const +{ + WRAPPER_NO_CONTRACT; + return Get(idx); +} + +inline SString& StringArrayList::Get (DWORD idx) const +{ + WRAPPER_NO_CONTRACT; + PTR_SString ppRet=(PTR_SString)m_Elements.Get(idx); + return *ppRet; +} + +inline DWORD StringArrayList::GetCount() const +{ + WRAPPER_NO_CONTRACT; + return m_Elements.GetCount(); +} + +#ifndef DACCESS_COMPILE +inline void StringArrayList::Append(const SString& string) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + NewHolder pAdd=new SString(string); + pAdd->Normalize(); + IfFailThrow(m_Elements.Append(pAdd)); + pAdd.SuppressRelease(); +} + +inline void StringArrayList::AppendIfNotThere(const SString& string) +{ + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + for (DWORD i=0;i +#include +#include +#include +#include +#include +#include "clrtypes.h" +#include "safewrap.h" +#include "volatile.h" +#include +#include "clrhost.h" +#include "debugmacros.h" +#include "corhlprpriv.h" +#include "winnls.h" +#include "check.h" +#include "safemath.h" +#include "new.hpp" + +#ifdef PAL_STDCPP_COMPAT +#include +#else +#include "clr_std/type_traits" +#endif + +#include "contract.h" +#include "entrypoints.h" + +#include "clrnt.h" + +#include "random.h" + +#define WINDOWS_KERNEL32_DLLNAME_A "kernel32" +#define WINDOWS_KERNEL32_DLLNAME_W W("kernel32") + +#define CoreLibName_W W("System.Private.CoreLib") +#define CoreLibName_IL_W W("System.Private.CoreLib.dll") +#define CoreLibName_NI_W W("System.Private.CoreLib.ni.dll") +#define CoreLibName_TLB_W W("System.Private.CoreLib.tlb") +#define CoreLibName_A "System.Private.CoreLib" +#define CoreLibName_IL_A "System.Private.CoreLib.dll" +#define CoreLibName_NI_A "System.Private.CoreLib.ni.dll" +#define CoreLibName_TLB_A "System.Private.CoreLib.tlb" +#define CoreLibNameLen 22 +#define CoreLibSatelliteName_A "System.Private.CoreLib.resources" +#define CoreLibSatelliteNameLen 32 +#define LegacyCoreLibName_A "mscorlib" + +class StringArrayList; + +#if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) +#define _DEBUG_IMPL 1 +#endif + +#ifdef _TARGET_ARM_ + +// Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct +// mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this +// is handled automatically for us by the compiler. When generating and working with code generated +// dynamically we have to be careful to set or mask-out this bit as appropriate. +#ifndef THUMB_CODE +#define THUMB_CODE 1 +#endif + +// Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff). +inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit) +{ + _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit)); + return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1); +} + +// Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the +// instruction. +inline bool Is32BitInstruction(WORD opcode) +{ + return BitExtract(opcode, 15, 11) >= 0x1d; +} + +template +inline ResultType DataPointerToThumbCode(SourceType pCode) +{ + return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE); +} + +template +inline ResultType ThumbCodeToDataPointer(SourceType pCode) +{ + return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE); +} + +#endif // _TARGET_ARM_ + +// Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function; +// on ARM, this will mask off the THUMB bit. +inline TADDR PCODEToPINSTR(PCODE pc) +{ +#ifdef _TARGET_ARM_ + return ThumbCodeToDataPointer(pc); +#else + return dac_cast(pc); +#endif +} + +// Convert from a PINSTR to the corresponding PCODE. On many architectures this will be the identity function; +// on ARM, this will raise the THUMB bit. +inline PCODE PINSTRToPCODE(TADDR addr) +{ +#ifdef _TARGET_ARM_ + return DataPointerToThumbCode(addr); +#else + return dac_cast(addr); +#endif +} + +typedef LPCSTR LPCUTF8; +typedef LPSTR LPUTF8; + +#include "nsutilpriv.h" + +#include "stdmacros.h" + +//********** Macros. ********************************************************** +#ifndef FORCEINLINE + #if _MSC_VER < 1200 + #define FORCEINLINE inline + #else + #define FORCEINLINE __forceinline + #endif +#endif + +#ifndef DEBUG_NOINLINE +#if defined(_DEBUG) +#define DEBUG_NOINLINE NOINLINE +#else +#define DEBUG_NOINLINE +#endif +#endif + +#include // for offsetof + +#ifndef NumItems +// Number of elements in a fixed-size array +#define NumItems(s) (sizeof(s) / sizeof(s[0])) +#endif + +#ifndef StrLen +// Number of characters in a string literal. Excludes terminating NULL. +#define StrLen(str) (NumItems(str) - 1) +#endif + + +#define IS_DIGIT(ch) ((ch >= W('0')) && (ch <= W('9'))) +#define DIGIT_TO_INT(ch) (ch - W('0')) +#define INT_TO_DIGIT(i) ((WCHAR)(W('0') + i)) + +#define IS_HEXDIGIT(ch) (((ch >= W('a')) && (ch <= W('f'))) || \ + ((ch >= W('A')) && (ch <= W('F')))) +#define HEXDIGIT_TO_INT(ch) ((towlower(ch) - W('a')) + 10) +#define INT_TO_HEXDIGIT(i) ((WCHAR)(W('a') + (i - 10))) + + +// Helper will 4 byte align a value, rounding up. +#define ALIGN4BYTE(val) (((val) + 3) & ~0x3) + +#ifdef _DEBUG +#define DEBUGARG(x) , x +#else +#define DEBUGARG(x) +#endif + +#ifndef sizeofmember +// Returns the size of a class or struct member. +#define sizeofmember(c,m) (sizeof(((c*)0)->m)) +#endif + +//=--------------------------------------------------------------------------= +// Prefast helpers. +// + +#include "safemath.h" + + +//=--------------------------------------------------------------------------= +// string helpers. + +// +// given and ANSI String, copy it into a wide buffer. +// be careful about scoping when using this macro! +// +// how to use the below two macros: +// +// ... +// LPSTR pszA; +// pszA = MyGetAnsiStringRoutine(); +// MAKE_WIDEPTR_FROMANSI(pwsz, pszA); +// MyUseWideStringRoutine(pwsz); +// ... +// +// similarily for MAKE_ANSIPTR_FROMWIDE. note that the first param does not +// have to be declared, and no clean up must be done. +// + +// We'll define an upper limit that allows multiplication by 4 (the max +// bytes/char in UTF-8) but still remains positive, and allows some room for pad. +// Under normal circumstances, we should never get anywhere near this limit. +#define MAKE_MAX_LENGTH 0x1fffff00 + +#ifndef MAKE_TOOLONGACTION +#define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW) +#endif + +#ifndef MAKE_TRANSLATIONFAILED +#define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION) +#endif + +// This version throws on conversion errors (ie, no best fit character +// mapping to characters that look similar, and no use of the default char +// ('?') when printing out unrepresentable characters. Use this method for +// most development in the EE, especially anything like metadata or class +// names. See the BESTFIT version if you're printing out info to the console. +#define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \ + int __l##ptrname = (int)wcslen(widestr); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ + CQuickBytes __CQuickBytes##ptrname; \ + __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \ + BOOL __b##ptrname; \ + DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \ + if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \ + MAKE_TRANSLATIONFAILED; \ + } \ + LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr() + +// This version does best fit character mapping and also allows the use +// of the default char ('?') for any Unicode character that isn't +// representable. This is reasonable for writing to the console, but +// shouldn't be used for most string conversions. +#define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \ + int __l##ptrname = (int)wcslen(widestr); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ + CQuickBytes __CQuickBytes##ptrname; \ + __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \ + DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \ + if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \ + MAKE_TRANSLATIONFAILED; \ + } \ + LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr() + +// Use for anything critical other than output to console, where weird +// character mappings are unacceptable. +#define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP) + +// Use for output to the console. +#define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP) + +#define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname; \ + __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \ + if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \ + MAKE_TRANSLATIONFAILED; \ + } + +#define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \ + CQuickBytes __qb##ptrname; \ + LPWSTR ptrname = 0; \ + int __l##ptrname; \ + __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \ + if (__l##ptrname <= MAKE_MAX_LENGTH) { \ + ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \ + if (ptrname) { \ + if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \ + ptrname[__l##ptrname] = 0; \ + } else { \ + ptrname = 0; \ + } \ + } \ + } + +#define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr(); + +#define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname = (int)wcslen(widestr); \ + LPUTF8 ptrname = 0; \ + if (__l##ptrname <= MAKE_MAX_LENGTH) { \ + __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ + ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \ + } \ + if (ptrname) { \ + INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \ + DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \ + if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \ + if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \ + INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \ + ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \ + if (ptrname) { \ + if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \ + ptrname[__l##ptrname] = 0; \ + } else { \ + ptrname = 0; \ + } \ + } \ + } \ + else { \ + ptrname = 0; \ + } \ + } \ + } \ + +#define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname; \ + __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \ + if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \ + MAKE_TRANSLATIONFAILED; \ + } \ + ptrname[__l##ptrname] = 0; + + +#define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname; _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr(); + + +#define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname; \ + LPWSTR ptrname = 0; \ + __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \ + if (__l##ptrname <= MAKE_MAX_LENGTH) { \ + ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \ + if (ptrname) { \ + if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \ + ptrname[__l##ptrname] = 0; \ + } else { \ + ptrname = 0; \ + } \ + } \ + } + +#define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str) MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1) + +// This method takes the number of characters +#define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname; \ + __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \ + BOOL __b##ptrname; \ + DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname); \ + if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \ + MAKE_TRANSLATIONFAILED; \ + } \ + ptrname[__l##ptrname] = 0; + +#define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage) \ + CQuickBytes __qb##ptrname; \ + int __l##ptrname; \ + __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL); \ + if (__l##ptrname > MAKE_MAX_LENGTH) \ + MAKE_TOOLONGACTION; \ + ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \ + DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL); \ + if (_pCnt == 0 && _nCharacters > 0) { \ + MAKE_TRANSLATIONFAILED; \ + } \ + ptrname[__l##ptrname] = 0; + +#define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt) \ + MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP) + + +inline +LPWSTR DuplicateString( + LPCWSTR wszString, + size_t cchString) +{ + STATIC_CONTRACT_NOTHROW; + + LPWSTR wszDup = NULL; + if (wszString != NULL) + { + wszDup = new (nothrow) WCHAR[cchString + 1]; + if (wszDup != NULL) + { + wcscpy_s(wszDup, cchString + 1, wszString); + } + } + return wszDup; +} + +inline +LPWSTR DuplicateString( + LPCWSTR wszString) +{ + STATIC_CONTRACT_NOTHROW; + + if (wszString != NULL) + { + return DuplicateString(wszString, wcslen(wszString)); + } + else + { + return NULL; + } +} + +void DECLSPEC_NORETURN ThrowOutOfMemory(); + +inline +LPWSTR DuplicateStringThrowing( + LPCWSTR wszString, + size_t cchString) +{ + STATIC_CONTRACT_THROWS; + + if (wszString == NULL) + return NULL; + + LPWSTR wszDup = DuplicateString(wszString, cchString); + if (wszDup == NULL) + ThrowOutOfMemory(); + + return wszDup; +} + +inline +LPWSTR DuplicateStringThrowing( + LPCWSTR wszString) +{ + STATIC_CONTRACT_THROWS; + + if (wszString == NULL) + return NULL; + + LPWSTR wszDup = DuplicateString(wszString); + if (wszDup == NULL) + ThrowOutOfMemory(); + + return wszDup; +} + + +//***************************************************************************** +// Placement new is used to new and object at an exact location. The pointer +// is simply returned to the caller without actually using the heap. The +// advantage here is that you cause the ctor() code for the object to be run. +// This is ideal for heaps of C++ objects that need to get init'd multiple times. +// Example: +// void *pMem = GetMemFromSomePlace(); +// Foo *p = new (pMem) Foo; +// DoSomething(p); +// p->~Foo(); +//***************************************************************************** +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void *__cdecl operator new(size_t, void *_P) +{ + LIMITED_METHOD_DAC_CONTRACT; + + return (_P); +} +#endif // __PLACEMENT_NEW_INLINE + + +/********************************************************************************/ +/* portability helpers */ +#ifdef _WIN64 +#define IN_WIN64(x) x +#define IN_WIN32(x) +#else +#define IN_WIN64(x) +#define IN_WIN32(x) x +#endif + +#ifdef _TARGET_64BIT_ +#define IN_TARGET_64BIT(x) x +#define IN_TARGET_32BIT(x) +#else +#define IN_TARGET_64BIT(x) +#define IN_TARGET_32BIT(x) x +#endif + +void * __cdecl +operator new(size_t n); + +_Ret_bytecap_(n) void * __cdecl +operator new[](size_t n); + +void __cdecl +operator delete(void *p) NOEXCEPT; + +void __cdecl +operator delete[](void *p) NOEXCEPT; + +#ifdef _DEBUG_IMPL +HRESULT _OutOfMemory(LPCSTR szFile, int iLine); +#define OutOfMemory() _OutOfMemory(__FILE__, __LINE__) +#else +inline HRESULT OutOfMemory() +{ + LIMITED_METHOD_CONTRACT; + return (E_OUTOFMEMORY); +} +#endif + +//***************************************************************************** +// Handle accessing localizable resource strings +//***************************************************************************** +typedef LPCWSTR LocaleID; +typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH]; + +// Notes about the culture callbacks: +// - The language we're operating in can change at *runtime*! +// - A process may operate in *multiple* languages. +// (ex: Each thread may have it's own language) +// - If we don't care what language we're in (or have no way of knowing), +// then return a 0-length name and UICULTUREID_DONTCARE for the culture ID. +// - GetCultureName() and the GetCultureId() must be in sync (refer to the +// same language). +// - We have two functions separate functions for better performance. +// - The name is used to resolve a directory for MsCorRC.dll. +// - The id is used as a key to map to a dll hinstance. + +// Callback to obtain both the culture name and the culture's parent culture name +typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames); +const LPCWSTR UICULTUREID_DONTCARE = NULL; + +typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*); + +HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName); + +HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); + +BOOL CLRFreeLibrary(HMODULE hModule); + +// Load a string using the resources for the current module. +STDAPI UtilLoadStringRC(UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE); + +// Specify callbacks so that UtilLoadStringRC can find out which language we're in. +// If no callbacks specified (or both parameters are NULL), we default to the +// resource dll in the root (which is probably english). +void SetResourceCultureCallbacks( + FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID fpGetThreadUICultureId +); + +void GetResourceCultureCallbacks( + FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID* fpGetThreadUICultureId +); + +#if !defined(DACCESS_COMPILE) +// Get the MUI ID, on downlevel platforms where MUI is not supported it +// returns the default system ID. +extern int GetMUILanguageID(LocaleIDValue* pResult); +extern HRESULT GetMUILanguageNames(__inout StringArrayList* pCultureNames); + +#endif // !defined(DACCESS_COMPILE) + +//***************************************************************************** +// Use this class by privately deriving from noncopyable to disallow copying of +// your class. +//***************************************************************************** +class noncopyable +{ +protected: + noncopyable() + {} + ~noncopyable() + {} + +private: + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); +}; + +//***************************************************************************** +// Must associate each handle to an instance of a resource dll with the int +// that it represents +//***************************************************************************** +typedef HINSTANCE HRESOURCEDLL; + + +class CCulturedHInstance +{ + LocaleIDValue m_LangId; + HRESOURCEDLL m_hInst; + BOOL m_fMissing; + +public: + CCulturedHInstance() + { + LIMITED_METHOD_CONTRACT; + m_hInst = NULL; + m_fMissing = FALSE; + } + + BOOL HasID(LocaleID id) + { + _ASSERTE(m_hInst != NULL || m_fMissing); + if (id == UICULTUREID_DONTCARE) + return FALSE; + + return wcscmp(id, m_LangId) == 0; + } + + HRESOURCEDLL GetLibraryHandle() + { + return m_hInst; + } + + BOOL IsSet() + { + return m_hInst != NULL; + } + + BOOL IsMissing() + { + return m_fMissing; + } + + void SetMissing(LocaleID id) + { + _ASSERTE(m_hInst == NULL); + SetId(id); + m_fMissing = TRUE; + } + + void Set(LocaleID id, HRESOURCEDLL hInst) + { + _ASSERTE(m_hInst == NULL); + _ASSERTE(m_fMissing == FALSE); + SetId(id); + m_hInst = hInst; + } + private: + void SetId(LocaleID id) + { + if (id != UICULTUREID_DONTCARE) + { + wcsncpy_s(m_LangId, NumItems(m_LangId), id, NumItems(m_LangId)); + m_LangId[NumItems(m_LangId)-1] = W('\0'); + } + else + { + m_LangId[0] = W('\0'); + } + } + }; + +#ifndef DACCESS_COMPILE +void AddThreadPreferredUILanguages(StringArrayList* pArray); +#endif +//***************************************************************************** +// CCompRC manages string Resource access for COM+. This includes loading +// the MsCorRC.dll for resources as well allowing each thread to use a +// a different localized version. +//***************************************************************************** +class CCompRC +{ +public: + + enum ResourceCategory + { + // must be present + Required, + + // present in Desktop CLR and Core CLR + debug pack, an error + // If missing, get a generic error message instead + Error, + + // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing) + // if missing, get a generic "resource not found" message instead + Debugging, + + // present in Desktop CLR, optional for CoreCLR + DesktopCLR, + + // might not be present, non essential + Optional + }; + + CCompRC() + { + // This constructor will be fired up on startup. Make sure it doesn't + // do anything besides zero-out out values. + m_bUseFallback = FALSE; + + m_fpGetThreadUICultureId = NULL; + m_fpGetThreadUICultureNames = NULL; + + + m_pHash = NULL; + m_nHashSize = 0; + m_csMap = NULL; + m_pResourceFile = NULL; +#ifdef FEATURE_PAL + m_pResourceDomain = NULL; +#endif // FEATURE_PAL + + }// CCompRC + + HRESULT Init(LPCWSTR pResourceFile, BOOL bUseFallback = FALSE); + void Destroy(); + + BOOL ShouldUseFallback() + { + LIMITED_METHOD_CONTRACT; + return m_bUseFallback; + }; + + static void SetIsMscoree() {s_bIsMscoree = TRUE;} + + HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); + HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed); + + void SetResourceCultureCallbacks( + FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID fpGetThreadUICultureId + ); + + void GetResourceCultureCallbacks( + FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID* fpGetThreadUICultureId + ); + + HRESULT LoadMUILibrary(HRESOURCEDLL * pHInst); + + // Get the default resource location (mscorrc.dll for desktop, mscorrc.debug.dll for CoreCLR) + static CCompRC* GetDefaultResourceDll(); + // Get the generic messages dll (Silverlight only, mscorrc.dll) + static CCompRC* GetFallbackResourceDll(); + static void ShutdownDefaultResourceDll(); + static void GetDefaultCallbacks( + FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID* fpGetThreadUICultureId) + { + WRAPPER_NO_CONTRACT; + m_DefaultResourceDll.GetResourceCultureCallbacks( + fpGetThreadUICultureNames, + fpGetThreadUICultureId); + } + + static void SetDefaultCallbacks( + FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, + FPGETTHREADUICULTUREID fpGetThreadUICultureId) + { + WRAPPER_NO_CONTRACT; + // Either both are NULL or neither are NULL + _ASSERTE((fpGetThreadUICultureNames != NULL) == + (fpGetThreadUICultureId != NULL)); + + m_DefaultResourceDll.SetResourceCultureCallbacks( + fpGetThreadUICultureNames, + fpGetThreadUICultureId); + + m_FallbackResourceDll.SetResourceCultureCallbacks( + fpGetThreadUICultureNames, + fpGetThreadUICultureId); + + } + +#ifdef USE_FORMATMESSAGE_WRAPPER + +DWORD +PALAPI +static +FormatMessage( + IN DWORD dwFlags, + IN LPCVOID lpSource, + IN DWORD dwMessageId, + IN DWORD dwLanguageId, + OUT LPWSTR lpBuffer, + IN DWORD nSize, + IN va_list *Arguments); +#endif // USE_FORMATMESSAGE_WRAPPER + + +private: + HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst); +#ifndef DACCESS_COMPILE + HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst, + SString& rcPath); + HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst); + HRESULT LoadLibrary(HRESOURCEDLL * pHInst); + HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName); +#endif + + // We do not have global constructors any more + static LONG m_dwDefaultInitialized; + static CCompRC m_DefaultResourceDll; + static LPCWSTR m_pDefaultResource; + + // fallback resources if debug pack is not installed + static LONG m_dwFallbackInitialized; + static CCompRC m_FallbackResourceDll; + static LPCWSTR m_pFallbackResource; + + // We must map between a thread's int and a dll instance. + // Since we only expect 1 language almost all of the time, we'll special case + // that and then use a variable size map for everything else. + CCulturedHInstance m_Primary; + CCulturedHInstance * m_pHash; + int m_nHashSize; + + CRITSEC_COOKIE m_csMap; + + LPCWSTR m_pResourceFile; +#ifdef FEATURE_PAL + // Resource domain is an ANSI string identifying a native resources file + static LPCSTR m_pDefaultResourceDomain; + static LPCSTR m_pFallbackResourceDomain; + LPCSTR m_pResourceDomain; +#endif // FEATURE_PAL + + // Main accessors for hash + HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing); + HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE); + + FPGETTHREADUICULTUREID m_fpGetThreadUICultureId; + FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames; + + BOOL m_bUseFallback; + static BOOL s_bIsMscoree; +}; + +HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResouceID, __out_ecount (iMax) LPWSTR szBuffer, int iMax); + + +int UtilMessageBox( + HWND hWnd, // Handle to Owner Window + UINT uText, // Resource Identifier for Text message + UINT uCaption, // Resource Identifier for Caption + UINT uType, // Style of MessageBox + BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + ...); // Additional Arguments + +int UtilMessageBoxNonLocalized( + HWND hWnd, // Handle to Owner Window + LPCWSTR lpText, // Resource Identifier for Text message + LPCWSTR lpTitle, // Resource Identifier for Caption + UINT uType, // Style of MessageBox + BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + ...); // Additional Arguments + +int UtilMessageBoxVA( + HWND hWnd, // Handle to Owner Window + UINT uText, // Resource Identifier for Text message + UINT uCaption, // Resource Identifier for Caption + UINT uType, // Style of MessageBox + BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + va_list args); // Additional Arguments + +int UtilMessageBoxNonLocalizedVA( + HWND hWnd, // Handle to Owner Window + LPCWSTR lpText, // Text message + LPCWSTR lpCaption, // Caption + UINT uType, // Style of MessageBox + BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort. + va_list args); // Additional Arguments + +int UtilMessageBoxNonLocalizedVA( + HWND hWnd, // Handle to Owner Window + LPCWSTR lpText, // Text message + LPCWSTR lpCaption, // Caption + LPCWSTR lpDetails, // Details that may be shown in a collapsed extended area of the dialog (Vista or higher). + UINT uType, // Style of MessageBox + BOOL displayForNonInteractive, // Display even if the process is running non interactive + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + BOOL * pInputFromUser, // To distinguish between user pressing abort vs. assuming abort. + va_list args); // Additional Arguments + +int UtilMessageBoxCatastrophic( + UINT uText, // Text for MessageBox + UINT uTitle, // Title for MessageBox + UINT uType, // Style of MessageBox + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + ...); + +int UtilMessageBoxCatastrophicNonLocalized( + LPCWSTR lpText, // Text for MessageBox + LPCWSTR lpTitle, // Title for MessageBox + UINT uType, // Style of MessageBox + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + ...); + +int UtilMessageBoxCatastrophicVA( + UINT uText, // Text for MessageBox + UINT uTitle, // Title for MessageBox + UINT uType, // Style of MessageBox + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + va_list args); // Additional Arguments + +int UtilMessageBoxCatastrophicNonLocalizedVA( + LPCWSTR lpText, // Text for MessageBox + LPCWSTR lpTitle, // Title for MessageBox + UINT uType, // Style of MessageBox + BOOL ShowFileNameInTitle, // Flag to show FileName in Caption + va_list args); // Additional Arguments + + +// The HRESULT_FROM_WIN32 macro evaluates its arguments three times. +// TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to +// this helper function avoid code bloat +inline HRESULT HRESULT_FROM_GetLastError() +{ + WRAPPER_NO_CONTRACT; + DWORD dw = GetLastError(); + // Make sure we return a failure + if (dw == ERROR_SUCCESS) + { + _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!"); + return E_FAIL; + } + else + return HRESULT_FROM_WIN32(dw); +} + +inline HRESULT HRESULT_FROM_GetLastErrorNA() +{ + WRAPPER_NO_CONTRACT; + DWORD dw = GetLastError(); + // Make sure we return a failure + if (dw == ERROR_SUCCESS) + return E_FAIL; + else + return HRESULT_FROM_WIN32(dw); +} + +inline HRESULT BadError(HRESULT hr) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE(!"Serious Error"); + return (hr); +} + +#define TESTANDRETURN(test, hrVal) \ +{ \ + int ___test = (int)(test); \ + if (! ___test) \ + return hrVal; \ +} + +#define TESTANDRETURNPOINTER(pointer) \ + TESTANDRETURN(pointer!=NULL, E_POINTER) + +#define TESTANDRETURNMEMORY(pointer) \ + TESTANDRETURN(pointer!=NULL, E_OUTOFMEMORY) + +#define TESTANDRETURNHR(hr) \ + TESTANDRETURN(SUCCEEDED(hr), hr) + +#define TESTANDRETURNARG(argtest) \ + TESTANDRETURN(argtest, E_INVALIDARG) + +// Quick validity check for HANDLEs that are returned by Win32 APIs that +// use INVALID_HANDLE_VALUE instead of NULL to indicate an error +inline BOOL IsValidHandle(HANDLE h) +{ + LIMITED_METHOD_CONTRACT; + return ((h != NULL) && (h != INVALID_HANDLE_VALUE)); +} + +// Count the bits in a value in order iBits time. +inline int CountBits(int iNum) +{ + LIMITED_METHOD_CONTRACT; + int iBits; + for (iBits=0; iNum; iBits++) + iNum = iNum & (iNum - 1); + return (iBits); +} + +#include "bitposition.h" + +// Convert the currency to a decimal and canonicalize. +inline void VarDecFromCyCanonicalize(CY cyIn, DECIMAL* dec) +{ + WRAPPER_NO_CONTRACT; + + (*(ULONG*)dec) = 0; + DECIMAL_HI32(*dec) = 0; + if (cyIn.int64 == 0) // For compatibility, a currency of 0 emits the Decimal "0.0000" (scale set to 4). + { + DECIMAL_SCALE(*dec) = 4; + DECIMAL_LO32(*dec) = 0; + DECIMAL_MID32(*dec) = 0; + return; + } + + if (cyIn.int64 < 0) { + DECIMAL_SIGN(*dec) = DECIMAL_NEG; + cyIn.int64 = -cyIn.int64; + } + + BYTE scale = 4; + ULONGLONG absoluteCy = (ULONGLONG)cyIn.int64; + while (scale != 0 && ((absoluteCy % 10) == 0)) + { + scale--; + absoluteCy /= 10; + } + DECIMAL_SCALE(*dec) = scale; + DECIMAL_LO32(*dec) = (ULONG)absoluteCy; + DECIMAL_MID32(*dec) = (ULONG)(absoluteCy >> 32); +} + +//***************************************************************************** +// +// Paths functions. Use these instead of the CRT. +// +//***************************************************************************** +// secure version! Specify the size of the each buffer in count of elements +void SplitPath(const WCHAR *path, + __inout_z __inout_ecount_opt(driveSizeInWords) WCHAR *drive, int driveSizeInWords, + __inout_z __inout_ecount_opt(dirSizeInWords) WCHAR *dir, int dirSizeInWords, + __inout_z __inout_ecount_opt(fnameSizeInWords) WCHAR *fname, size_t fnameSizeInWords, + __inout_z __inout_ecount_opt(extSizeInWords) WCHAR *ext, size_t extSizeInWords); + +//******************************************************************************* +// A much more sensible version that just points to each section of the string. +//******************************************************************************* +void SplitPathInterior( + __in LPCWSTR wszPath, + __out_opt LPCWSTR *pwszDrive, __out_opt size_t *pcchDrive, + __out_opt LPCWSTR *pwszDir, __out_opt size_t *pcchDir, + __out_opt LPCWSTR *pwszFileName, __out_opt size_t *pcchFileName, + __out_opt LPCWSTR *pwszExt, __out_opt size_t *pcchExt); + + +void MakePath(__out CQuickWSTR &path, + __in LPCWSTR drive, + __in LPCWSTR dir, + __in LPCWSTR fname, + __in LPCWSTR ext); + +WCHAR * FullPath(__out_ecount (maxlen) WCHAR *UserBuf, const WCHAR *path, size_t maxlen); + +//***************************************************************************** +// +// SString version of the path functions. +// +//***************************************************************************** +void SplitPath(__in SString const &path, + __inout_opt SString *drive, + __inout_opt SString *dir, + __inout_opt SString *fname, + __inout_opt SString *ext); + +#if !defined(NO_CLRCONFIG) + +//***************************************************************************** +// +// **** REGUTIL - Static helper functions for reading/writing to Windows registry. +// +//***************************************************************************** + + +class REGUTIL +{ +public: +//***************************************************************************** + + enum CORConfigLevel + { + COR_CONFIG_ENV = 0x01, + COR_CONFIG_USER = 0x02, + COR_CONFIG_MACHINE = 0x04, + COR_CONFIG_FUSION = 0x08, + + COR_CONFIG_REGISTRY = (COR_CONFIG_USER|COR_CONFIG_MACHINE|COR_CONFIG_FUSION), + COR_CONFIG_ALL = (COR_CONFIG_ENV|COR_CONFIG_USER|COR_CONFIG_MACHINE), + }; + + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + static DWORD GetConfigDWORD_DontUse_( + LPCWSTR name, + DWORD defValue, + CORConfigLevel level = COR_CONFIG_ALL, + BOOL fPrependCOMPLUS = TRUE); + + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + static HRESULT GetConfigDWORD_DontUse_( + LPCWSTR name, + DWORD defValue, + __out DWORD * result, + CORConfigLevel level = COR_CONFIG_ALL, + BOOL fPrependCOMPLUS = TRUE); + + static ULONGLONG GetConfigULONGLONG_DontUse_( + LPCWSTR name, + ULONGLONG defValue, + CORConfigLevel level = COR_CONFIG_ALL, + BOOL fPrependCOMPLUS = TRUE); + + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + static DWORD GetConfigFlag_DontUse_( + LPCWSTR name, + DWORD bitToSet, + BOOL defValue = FALSE); + + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + static LPWSTR GetConfigString_DontUse_( + LPCWSTR name, + BOOL fPrependCOMPLUS = TRUE, + CORConfigLevel level = COR_CONFIG_ALL, + BOOL fUsePerfCache = TRUE); + + static void FreeConfigString(__in __in_z LPWSTR name); + +private: + static LPWSTR EnvGetString(LPCWSTR name, BOOL fPrependCOMPLUS); +public: + + static BOOL UseRegistry(); + +private: +//***************************************************************************** +// Get either a DWORD or ULONGLONG. Always puts the result in a ULONGLONG that +// you can safely cast to a DWORD if fGetDWORD is TRUE. +//***************************************************************************** + static HRESULT GetConfigInteger( + LPCWSTR name, + ULONGLONG defValue, + __out ULONGLONG * result, + BOOL fGetDWORD = TRUE, + CORConfigLevel level = COR_CONFIG_ALL, + BOOL fPrependCOMPLUS = TRUE); +public: + + +//***************************************************************************** +// (Optional) Initialize the config registry cache +// (see ConfigCacheValueNameSeenPerhaps, below.) +//***************************************************************************** + static void InitOptionalConfigCache(); + +private: + + +//***************************************************************************** +// Return TRUE if the registry value name might have been seen in the registry +// at startup; +// return FALSE if the value was definitely not seen at startup. +// +// Perf Optimization for VSWhidbey:113373. +//***************************************************************************** + static BOOL RegCacheValueNameSeenPerhaps( + LPCWSTR name); +//***************************************************************************** +// Return TRUE if the environment variable name might have been seen at startup; +// return FALSE if the value was definitely not seen at startup. +//***************************************************************************** + static BOOL EnvCacheValueNameSeenPerhaps( + LPCWSTR name); + + static BOOL s_fUseRegCache; // Enable registry cache; if FALSE, CCVNSP + // always returns TRUE. + static BOOL s_fUseEnvCache; // Enable env cache. + + static BOOL s_fUseRegistry; // Allow lookups in the registry + + // Open the .NetFramework keys once and cache the handles + static HKEY s_hMachineFrameworkKey; + static HKEY s_hUserFrameworkKey; +}; + +// need this here because CLRConfig depends on REGUTIL, and ConfigStringHolder depends on CLRConfig +#include "clrconfig.h" + +//----------------------------------------------------------------------------- +// Wrapper for configuration strings. +// This serves as a holder to call FreeConfigString. +class ConfigStringHolder +{ +public: + ConfigStringHolder() { m_wszString = NULL; } + ~ConfigStringHolder() + { + Clear(); + } + + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + void Init_DontUse_(LPCWSTR wszName) + { + Clear(); + m_wszString = REGUTIL::GetConfigString_DontUse_(wszName); + } + + // Free resources. + void Clear() + { + if (m_wszString != NULL) + { + REGUTIL::FreeConfigString(m_wszString); + m_wszString = NULL; + } + } + + // Get the string value. NULL if not set. + LPCWSTR Value() + { + return m_wszString; + } + +private: + LPWSTR m_wszString; +}; + +#endif // defined(NO_CLRCONFIG) + +#include "ostype.h" + +#define CLRGetTickCount64() GetTickCount64() + +// +// Use this function to initialize the s_CodeAllocHint +// during startup. base is runtime .dll base address, +// size is runtime .dll virtual size. +// +void InitCodeAllocHint(SIZE_T base, SIZE_T size, int randomPageOffset); + + +// +// Use this function to reset the s_CodeAllocHint +// after unloading an AppDomain +// +void ResetCodeAllocHint(); + +// +// Returns TRUE if p is located in near clr.dll that allows us +// to use rel32 IP-relative addressing modes. +// +BOOL IsPreferredExecutableRange(void * p); + +// +// Allocate free memory that will be used for executable code +// Handles the special requirements that we have on 64-bit platforms +// where we want the executable memory to be located near mscorwks +// +BYTE * ClrVirtualAllocExecutable(SIZE_T dwSize, + DWORD flAllocationType, + DWORD flProtect); + +// +// Allocate free memory within the range [pMinAddr..pMaxAddr] using +// ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it. +// +BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, + const BYTE *pMaxAddr, + SIZE_T dwSize, + DWORD flAllocationType, + DWORD flProtect); + +// +// Allocate free memory with specific alignment +// +LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment); + +class NumaNodeInfo +{ +private: + static BOOL m_enableGCNumaAware; + static uint16_t m_nNodes; + static BOOL InitNumaNodeInfoAPI(); + +public: + static BOOL CanEnableGCNumaAware(); + static void InitNumaNodeInfo(); + +#if !defined(FEATURE_REDHAWK) +public: // functions + + static LPVOID VirtualAllocExNuma(HANDLE hProc, LPVOID lpAddr, SIZE_T size, + DWORD allocType, DWORD prot, DWORD node); +#ifndef FEATURE_PAL + static BOOL GetNumaProcessorNodeEx(PPROCESSOR_NUMBER proc_no, PUSHORT node_no); + static bool GetNumaInfo(PUSHORT total_nodes, DWORD* max_procs_per_node); +#else // !FEATURE_PAL + static BOOL GetNumaProcessorNodeEx(USHORT proc_no, PUSHORT node_no); +#endif // !FEATURE_PAL +#endif +}; + +#ifndef FEATURE_PAL + +struct CPU_Group_Info +{ + WORD nr_active; // at most 64 + WORD reserved[1]; + WORD begin; + WORD end; + DWORD_PTR active_mask; + DWORD groupWeight; + DWORD activeThreadWeight; +}; + +class CPUGroupInfo +{ +private: + static LONG m_initialization; + static WORD m_nGroups; + static WORD m_nProcessors; + static BOOL m_enableGCCPUGroups; + static BOOL m_threadUseAllCpuGroups; + static WORD m_initialGroup; + static CPU_Group_Info *m_CPUGroupInfoArray; + static bool s_hadSingleProcessorAtStartup; + + static BOOL InitCPUGroupInfoArray(); + static BOOL InitCPUGroupInfoRange(); + static void InitCPUGroupInfo(); + static BOOL IsInitialized(); + +public: + static void EnsureInitialized(); + static BOOL CanEnableGCCPUGroups(); + static BOOL CanEnableThreadUseAllCpuGroups(); + static WORD GetNumActiveProcessors(); + static void GetGroupForProcessor(WORD processor_number, + WORD *group_number, WORD *group_processor_number); + static DWORD CalculateCurrentProcessorNumber(); + static bool GetCPUGroupInfo(PUSHORT total_groups, DWORD* max_procs_per_group); + //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize); + +#if !defined(FEATURE_REDHAWK) +public: + static BOOL GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP relationship, + SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count); + static BOOL SetThreadGroupAffinity(HANDLE h, + GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity); + static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity); + static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime); + static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf); + static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf); + static BOOL GetCPUGroupRange(WORD group_number, WORD* group_begin, WORD* group_size); +#endif + +public: + static bool HadSingleProcessorAtStartup() + { + LIMITED_METHOD_CONTRACT; + return s_hadSingleProcessorAtStartup; + } +}; + +DWORD_PTR GetCurrentProcessCpuMask(); + +#endif // !FEATURE_PAL + +//****************************************************************************** +// Returns the number of processors that a process has been configured to run on +//****************************************************************************** +int GetCurrentProcessCpuCount(); + +uint32_t GetOsPageSize(); + + +//***************************************************************************** +// Return != 0 if the bit at the specified index in the array is on and 0 if +// it is off. +//***************************************************************************** +inline int GetBit(PTR_BYTE pcBits,int iBit) +{ + LIMITED_METHOD_CONTRACT; + return (pcBits[iBit>>3] & (1 << (iBit & 0x7))); +} + +#ifdef DACCESS_COMPILE +inline int GetBit(BYTE const * pcBits,int iBit) +{ + WRAPPER_NO_CONTRACT; + return GetBit(dac_cast(pcBits), iBit); +} +#endif + +//***************************************************************************** +// Set the state of the bit at the specified index based on the value of bOn. +//***************************************************************************** +inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn) +{ + LIMITED_METHOD_CONTRACT; + if (bOn) + pcBits[iBit>>3] |= (1 << (iBit & 0x7)); + else + pcBits[iBit>>3] &= ~(1 << (iBit & 0x7)); +} + +#ifdef DACCESS_COMPILE +inline void SetBit(BYTE * pcBits,int iBit,int bOn) +{ + WRAPPER_NO_CONTRACT; + SetBit(dac_cast(pcBits), iBit, bOn); +} +#endif + +template +class SimpleListNode +{ +public: + SimpleListNode(const T& _t) + { + data = _t; + next = 0; + } + + T data; + SimpleListNode* next; +}; + +template +class SimpleList +{ +public: + typedef SimpleListNode NodeType; + + SimpleList() + { + head = NULL; + } + + void LinkHead(NodeType* pNode) + { + pNode->next = head; + head = pNode; + } + + NodeType* UnlinkHead() + { + NodeType* ret = head; + + if (head) + { + head = head->next; + } + return ret; + } + + NodeType* Head() + { + return head; + } + +protected: + + NodeType* head; +}; + + +template < typename T, typename U > +struct Pair +{ +public: + typedef Pair< T, U > this_type; + typedef T first_type; + typedef U second_type; + + Pair() + {} + + Pair( T const & t, U const & u ) + : m_first( t ) + , m_second( u ) + { SUPPORTS_DAC; } + + Pair( this_type const & obj ) + : m_first( obj.m_first ) + , m_second( obj.m_second ) + {} + + this_type & operator=( this_type const & obj ) + { + m_first = obj.m_first; + m_second = obj.m_second; + return *this; + } + + T & First() + { + return m_first; + } + + T const & First() const + { + return m_first; + } + + U & Second() + { + return m_second; + } + + U const & Second() const + { + return m_second; + } + + bool operator==(const Pair& rhs) const + { + return ((this->First() == rhs.First()) && + (this->Second() == rhs.Second())); + } + + bool operator!=(const Pair& rhs) const + { + return !(*this == rhs); + } + +private: + first_type m_first; + second_type m_second; +}; + + +template < typename T, typename U > +Pair< T, U > MakePair( T const & t, U const & u ) +{ + SUPPORTS_DAC; + return Pair< T, U >( t, u ); +} + + +//***************************************************************************** +// This class implements a dynamic array of structures for which the order of +// the elements is unimportant. This means that any item placed in the list +// may be swapped to any other location in the list at any time. If the order +// of the items you place in the array is important, then use the CStructArray +// class. +//***************************************************************************** + +template +class CUnorderedArrayWithAllocator +{ + int m_iCount; // # of elements used in the list. + int m_iSize; // # of elements allocated in the list. +public: +#ifndef DACCESS_COMPILE + T *m_pTable; // Pointer to the list of elements. +#else + TADDR m_pTable; // Pointer to the list of elements. +#endif + +public: + +#ifndef DACCESS_COMPILE + + CUnorderedArrayWithAllocator() : + m_iCount(0), + m_iSize(0), + m_pTable(NULL) + { + LIMITED_METHOD_CONTRACT; + } + ~CUnorderedArrayWithAllocator() + { + LIMITED_METHOD_CONTRACT; + // Free the chunk of memory. + if (m_pTable != NULL) + ALLOCATOR::Free(this, m_pTable); + } + + void Clear() + { + WRAPPER_NO_CONTRACT; + m_iCount = 0; + if (m_iSize > iGrowInc) + { + T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc); + if (tmp) { + ALLOCATOR::Free(this, m_pTable); + m_pTable = tmp; + m_iSize = iGrowInc; + } + } + } + + void Clear(int iFirst, int iCount) + { + WRAPPER_NO_CONTRACT; + int iSize; + + if (iFirst + iCount < m_iCount) + memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount))); + + m_iCount -= iCount; + + iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0); + if (m_iSize > iGrowInc && iSize < m_iSize) + { + T *tmp = ALLOCATOR::AllocNoThrow(this, iSize); + if (tmp) { + memcpy (tmp, m_pTable, iSize * sizeof(T)); + delete [] m_pTable; + m_pTable = tmp; + m_iSize = iSize; + } + } + _ASSERTE(m_iCount <= m_iSize); + } + + T *Table() + { + LIMITED_METHOD_CONTRACT; + return (m_pTable); + } + + T *Append() + { + CONTRACTL { + NOTHROW; + } CONTRACTL_END; + + // The array should grow, if we can't fit one more element into the array. + if (m_iSize <= m_iCount && GrowNoThrow() == NULL) + return (NULL); + return (&m_pTable[m_iCount++]); + } + + T *AppendThrowing() + { + CONTRACTL { + THROWS; + } CONTRACTL_END; + + // The array should grow, if we can't fit one more element into the array. + if (m_iSize <= m_iCount) + Grow(); + return (&m_pTable[m_iCount++]); + } + + void Delete(const T &Entry) + { + LIMITED_METHOD_CONTRACT; + --m_iCount; + for (int i=0; i <= m_iCount; ++i) + if (m_pTable[i] == Entry) + { + m_pTable[i] = m_pTable[m_iCount]; + return; + } + + // Just in case we didn't find it. + ++m_iCount; + } + + void DeleteByIndex(int i) + { + LIMITED_METHOD_CONTRACT; + --m_iCount; + m_pTable[i] = m_pTable[m_iCount]; + } + + void Swap(int i,int j) + { + LIMITED_METHOD_CONTRACT; + T tmp; + + if (i == j) + return; + tmp = m_pTable[i]; + m_pTable[i] = m_pTable[j]; + m_pTable[j] = tmp; + } + +#else + + TADDR Table() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + return (m_pTable); + } + + void EnumMemoryRegions(void) + { + SUPPORTS_DAC; + DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T)); + } + +#endif // #ifndef DACCESS_COMPILE + + USHORT Count() + { + LIMITED_METHOD_CONTRACT; + SUPPORTS_DAC; + _ASSERTE(FitsIn(m_iCount)); + return static_cast(m_iCount); + } + +private: + T *Grow(); + T *GrowNoThrow(); +}; + + +#ifndef DACCESS_COMPILE + +//***************************************************************************** +// Increase the size of the array. +//***************************************************************************** +template +T *CUnorderedArrayWithAllocator::GrowNoThrow() // NULL if can't grow. +{ + WRAPPER_NO_CONTRACT; + T *pTemp; + + // try to allocate memory for reallocation. + if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL) + return (NULL); + memcpy (pTemp, m_pTable, m_iSize*sizeof(T)); + ALLOCATOR::Free(this, m_pTable); + m_pTable = pTemp; + m_iSize += iGrowInc; + _ASSERTE(m_iSize > 0); + return (pTemp); +} + +template +T *CUnorderedArrayWithAllocator::Grow() // exception if can't grow. +{ + WRAPPER_NO_CONTRACT; + T *pTemp; + + // try to allocate memory for reallocation. + pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc); + memcpy (pTemp, m_pTable, m_iSize*sizeof(T)); + ALLOCATOR::Free(this, m_pTable); + m_pTable = pTemp; + m_iSize += iGrowInc; + _ASSERTE(m_iSize > 0); + return (pTemp); +} + +#endif // #ifndef DACCESS_COMPILE + + +template +class CUnorderedArray__Allocator +{ +public: + + static T *AllocThrowing (void*, int nElements) + { + return new T[nElements]; + } + + static T *AllocNoThrow (void*, int nElements) + { + return new (nothrow) T[nElements]; + } + + static void Free (void*, T *pTable) + { + delete [] pTable; + } +}; + + +template +class CUnorderedArray : public CUnorderedArrayWithAllocator > +{ +public: + + CUnorderedArray () + { + LIMITED_METHOD_CONTRACT; + } +}; + + +//Used by the debugger. Included here in hopes somebody else might, too +typedef CUnorderedArray SIZE_T_UNORDERED_ARRAY; + + +//***************************************************************************** +// This class implements a dynamic array of structures for which the insert +// order is important. Inserts will slide all elements after the location +// down, deletes slide all values over the deleted item. If the order of the +// items in the array is unimportant to you, then CUnorderedArray may provide +// the same feature set at lower cost. +//***************************************************************************** +class CStructArray +{ + BYTE *m_pList; // Pointer to the list of elements. + int m_iCount; // # of elements used in the list. + int m_iSize; // # of elements allocated in the list. + int m_iGrowInc; // Growth increment. + short m_iElemSize; // Size of an array element. + bool m_bFree; // true if data is automatically maintained. + +public: + CStructArray(short iElemSize, short iGrowInc = 1) : + m_pList(NULL), + m_iCount(0), + m_iSize(0), + m_iGrowInc(iGrowInc), + m_iElemSize(iElemSize), + m_bFree(true) + { + LIMITED_METHOD_CONTRACT; + } + ~CStructArray() + { + WRAPPER_NO_CONTRACT; + Clear(); + } + + void *Insert(int iIndex); + void *InsertThrowing(int iIndex); + void *Append(); + void *AppendThrowing(); + int AllocateBlock(int iCount); + void AllocateBlockThrowing(int iCount); + void Delete(int iIndex); + void *Ptr() + { + LIMITED_METHOD_CONTRACT; + return (m_pList); + } + void *Get(int iIndex) + { + WRAPPER_NO_CONTRACT; + _ASSERTE(iIndex < m_iCount); + return (BYTE*) Ptr() + (iIndex * (size_t)m_iElemSize); + } + size_t Size() + { + LIMITED_METHOD_CONTRACT; + return (m_iCount * (size_t)m_iElemSize); + } + int Count() + { + LIMITED_METHOD_CONTRACT; + return (m_iCount); + } + void Clear(); + void ClearCount() + { + LIMITED_METHOD_CONTRACT; + m_iCount = 0; + } + + void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1) + { + LIMITED_METHOD_CONTRACT; + m_iElemSize = iElemSize; + m_iGrowInc = (short) iGrowInc; + m_pList = (BYTE*)pList; + m_iCount = iCount; + m_iSize = iSize; + m_bFree = false; + } + +private: + void Grow(int iCount); +}; + + +//***************************************************************************** +// This template simplifies access to a CStructArray by removing void * and +// adding some operator overloads. +//***************************************************************************** +template +class CDynArray : public CStructArray +{ +public: + CDynArray(short iGrowInc=16) : + CStructArray(sizeof(T), iGrowInc) + { + LIMITED_METHOD_CONTRACT; + } + + T *Insert(int iIndex) + { + WRAPPER_NO_CONTRACT; + return ((T *)CStructArray::Insert((int)iIndex)); + } + + T *InsertThrowing(int iIndex) + { + WRAPPER_NO_CONTRACT; + return ((T *)CStructArray::InsertThrowing((int)iIndex)); + } + + T *Append() + { + WRAPPER_NO_CONTRACT; + return ((T *)CStructArray::Append()); + } + + T *AppendThrowing() + { + WRAPPER_NO_CONTRACT; + return ((T *)CStructArray::AppendThrowing()); + } + + T *Ptr() + { + WRAPPER_NO_CONTRACT; + return ((T *)CStructArray::Ptr()); + } + + T *Get(int iIndex) + { + WRAPPER_NO_CONTRACT; + return (Ptr() + iIndex); + } + T &operator[](int iIndex) + { + WRAPPER_NO_CONTRACT; + return (*(Ptr() + iIndex)); + } + int ItemIndex(T *p) + { + WRAPPER_NO_CONTRACT; + return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T)); + } + void Move(int iFrom, int iTo) + { + WRAPPER_NO_CONTRACT; + T tmp; + + _ASSERTE(iFrom >= 0 && iFrom < Count() && + iTo >= 0 && iTo < Count()); + + tmp = *(Ptr() + iFrom); + if (iTo > iFrom) + memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T)); + else + memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T)); + *(Ptr() + iTo) = tmp; + } +}; + +// Some common arrays. +typedef CDynArray INTARRAY; +typedef CDynArray SHORTARRAY; +typedef CDynArray LONGARRAY; +typedef CDynArray USHORTARRAY; +typedef CDynArray ULONGARRAY; +typedef CDynArray BYTEARRAY; +typedef CDynArray TOKENARRAY; + +template class CStackArray : public CStructArray +{ +public: + CStackArray(short iGrowInc=4) : + CStructArray(sizeof(T), iGrowInc), + m_curPos(0) + { + LIMITED_METHOD_CONTRACT; + } + + void Push(T p) + { + WRAPPER_NO_CONTRACT; + // We should only inc m_curPos after we grow the array. + T *pT = (T *)CStructArray::InsertThrowing(m_curPos); + m_curPos ++; + *pT = p; + } + + T * Pop() + { + WRAPPER_NO_CONTRACT; + T * retPtr; + + _ASSERTE(m_curPos > 0); + + retPtr = (T *)CStructArray::Get(m_curPos-1); + CStructArray::Delete(m_curPos--); + + return (retPtr); + } + + int Count() + { + LIMITED_METHOD_CONTRACT; + return(m_curPos); + } + +private: + int m_curPos; +}; + + +//***************************************************************************** +// This template manages a list of free entries by their 0 based offset. By +// making it a template, you can use whatever size free chain will match your +// maximum count of items. -1 is reserved. +//***************************************************************************** +template class TFreeList +{ +public: + void Init( + T *rgList, + int iCount) + { + LIMITED_METHOD_CONTRACT; + // Save off values. + m_rgList = rgList; + m_iCount = iCount; + m_iNext = 0; + + // Init free list. + int i; + for (i=0; i class CQuickSort +{ +protected: + T *m_pBase; // Base of array to sort. +private: + SSIZE_T m_iCount; // How many items in array. + SSIZE_T m_iElemSize; // Size of one element. +public: + CQuickSort( + T *pBase, // Address of first element. + SSIZE_T iCount) : // How many there are. + m_pBase(pBase), + m_iCount(iCount), + m_iElemSize(sizeof(T)) + { + LIMITED_METHOD_DAC_CONTRACT; + } + +//***************************************************************************** +// Call to sort the array. +//***************************************************************************** + inline void Sort() + { + WRAPPER_NO_CONTRACT; + SortRange(0, m_iCount - 1); + } + +protected: +//***************************************************************************** +// Override this function to do the comparison. +//***************************************************************************** + virtual FORCEINLINE int Compare( // -1, 0, or 1 + T *psFirst, // First item to compare. + T *psSecond) // Second item to compare. + { + LIMITED_METHOD_DAC_CONTRACT; + return (memcmp(psFirst, psSecond, sizeof(T))); +// return (::Compare(*psFirst, *psSecond)); + } + + virtual FORCEINLINE void Swap( + SSIZE_T iFirst, + SSIZE_T iSecond) + { + LIMITED_METHOD_DAC_CONTRACT; + if (iFirst == iSecond) return; + T sTemp( m_pBase[iFirst] ); + m_pBase[iFirst] = m_pBase[iSecond]; + m_pBase[iSecond] = sTemp; + } + +private: + inline void SortRange( + SSIZE_T iLeft, + SSIZE_T iRight) + { + WRAPPER_NO_CONTRACT; + SSIZE_T iLast; + SSIZE_T i; // loop variable. + + for (;;) + { + // if less than two elements you're done. + if (iLeft >= iRight) + return; + + // ASSERT that we now have valid indicies. This is statically provable + // since this private function is only called with valid indicies, + // and iLeft and iRight only converge towards eachother. However, + // PreFast can't detect this because it doesn't know about our callers. + COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount); + COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount); + + // The mid-element is the pivot, move it to the left. + Swap(iLeft, (iLeft + iRight) / 2); + iLast = iLeft; + + // move everything that is smaller than the pivot to the left. + for (i = iLeft + 1; i <= iRight; i++) + { + if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0) + { + Swap(i, ++iLast); + } + } + + // Put the pivot to the point where it is in between smaller and larger elements. + Swap(iLeft, iLast); + + // Sort each partition. + SSIZE_T iLeftLast = iLast - 1; + SSIZE_T iRightFirst = iLast + 1; + if (iLeftLast - iLeft < iRight - iRightFirst) + { // Left partition is smaller, sort it recursively + SortRange(iLeft, iLeftLast); + // Tail call to sort the right (bigger) partition + iLeft = iRightFirst; + //iRight = iRight; + continue; + } + else + { // Right partition is smaller, sort it recursively + SortRange(iRightFirst, iRight); + // Tail call to sort the left (bigger) partition + //iLeft = iLeft; + iRight = iLeftLast; + continue; + } + } + } +}; + +//***************************************************************************** +// Faster and simpler version of the binary search below. +//***************************************************************************** +template +const T * BinarySearch(const T * pBase, int iCount, const T & find) +{ + WRAPPER_NO_CONTRACT; + + int iFirst = 0; + int iLast = iCount - 1; + + // It is faster to use linear search once we get down to a small number of elements. + while (iLast - iFirst > 10) + { + int iMid = (iLast + iFirst) / 2; + + if (find < pBase[iMid]) + iLast = iMid - 1; + else + iFirst = iMid; + } + + for (int i = iFirst; i <= iLast; i++) + { + if (find == pBase[i]) + return &pBase[i]; + + if (find < pBase[i]) + break; + } + + return NULL; +} + +//***************************************************************************** +// This template encapsulates a binary search algorithm on the given type +// of data. +//***************************************************************************** +template class CBinarySearch +{ +private: + const T *m_pBase; // Base of array to sort. + int m_iCount; // How many items in array. + +public: + CBinarySearch( + const T *pBase, // Address of first element. + int iCount) : // Value to find. + m_pBase(pBase), + m_iCount(iCount) + { + LIMITED_METHOD_CONTRACT; + } + +//***************************************************************************** +// Searches for the item passed to ctor. +//***************************************************************************** + const T *Find( // Pointer to found item in array. + const T *psFind, // The key to find. + int *piInsert = NULL) // Index to insert at. + { + WRAPPER_NO_CONTRACT; + int iMid, iFirst, iLast; // Loop control. + int iCmp; // Comparison. + + iFirst = 0; + iLast = m_iCount - 1; + while (iFirst <= iLast) + { + iMid = (iLast + iFirst) / 2; + iCmp = Compare(psFind, &m_pBase[iMid]); + if (iCmp == 0) + { + if (piInsert != NULL) + *piInsert = iMid; + return (&m_pBase[iMid]); + } + else if (iCmp < 0) + iLast = iMid - 1; + else + iFirst = iMid + 1; + } + if (piInsert != NULL) + *piInsert = iFirst; + return (NULL); + } + +//***************************************************************************** +// Override this function to do the comparison if a comparison operator is +// not valid for your data type (such as a struct). +//***************************************************************************** + virtual int Compare( // -1, 0, or 1 + const T *psFirst, // Key you are looking for. + const T *psSecond) // Item to compare to. + { + LIMITED_METHOD_CONTRACT; + return (memcmp(psFirst, psSecond, sizeof(T))); +// return (::Compare(*psFirst, *psSecond)); + } +}; + +//***************************************************************************** +// The information that the hash table implementation stores at the beginning +// of every record that can be but in the hash table. +//***************************************************************************** +typedef DPTR(struct HASHENTRY) PTR_HASHENTRY; +struct HASHENTRY +{ + ULONG iPrev; // Previous bucket in the chain. + ULONG iNext; // Next bucket in the chain. +}; + +typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY; +struct FREEHASHENTRY : HASHENTRY +{ + ULONG iFree; +}; + +//***************************************************************************** +// Used by the FindFirst/FindNextEntry functions. These api's allow you to +// do a sequential scan of all entries. +//***************************************************************************** +struct HASHFIND +{ + ULONG iBucket; // The next bucket to look in. + ULONG iNext; +}; + + +//***************************************************************************** +// IMPORTANT: This data structure is deprecated, please do not add any new uses. +// The hashtable implementation that should be used instead is code:SHash. +// If code:SHash does not work for you, talk to mailto:clrdeag. +//***************************************************************************** +// This is a class that implements a chain and bucket hash table. +// +// The data is actually supplied as an array of structures by the user of this class. +// This allows the buckets to use small indices to point to the chain, instead of pointers. +// +// Each entry in the array contains a HASHENTRY structure immediately +// followed by the key used to hash the structure. +// +// The HASHENTRY part of every structure is used to implement the chain of +// entries in a single bucket. +// +// This implementation does not support rehashing the buckets if the table grows +// to big. +// @TODO: Fix this by adding an abstract function Hash() which must be implemented +// by all clients. +// +//***************************************************************************** +class CHashTable +{ + friend class DebuggerRCThread; //RCthread actually needs access to + //fields of derrived class DebuggerPatchTable + +protected: + TADDR m_pcEntries; // Pointer to the array of structs. + ULONG m_iEntrySize; // Size of the structs. + + ULONG m_iBuckets; // # of chains we are hashing into. + PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains. + + INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics + + HASHENTRY *EntryPtr(ULONG iEntry) + { + LIMITED_METHOD_DAC_CONTRACT; + return (PTR_HASHENTRY(m_pcEntries + (iEntry * (size_t)m_iEntrySize))); + } + + ULONG ItemIndex(HASHENTRY *p) + { + SUPPORTS_DAC; + LIMITED_METHOD_CONTRACT; + return (ULONG)((dac_cast(p) - m_pcEntries) / m_iEntrySize); + } + + +public: + + CHashTable( + ULONG iBuckets) : // # of chains we are hashing into. + m_pcEntries((TADDR)NULL), + m_iBuckets(iBuckets) + { + LIMITED_METHOD_CONTRACT; + + m_piBuckets = NULL; + + INDEBUG(m_maxSearch = 0;) + } + + CHashTable() : // # of chains we are hashing into. + m_pcEntries((TADDR)NULL), + m_iBuckets(5) + { + LIMITED_METHOD_CONTRACT; + + m_piBuckets = NULL; + + INDEBUG(m_maxSearch = 0;) + } + +#ifndef DACCESS_COMPILE + + ~CHashTable() + { + LIMITED_METHOD_CONTRACT; + if (m_piBuckets != NULL) + { + delete [] m_piBuckets; + m_piBuckets = NULL; + } + } + +//***************************************************************************** +// This is the second part of construction where we do all of the work that +// can fail. We also take the array of structs here because the calling class +// presumably needs to allocate it in its NewInit. +//***************************************************************************** + HRESULT NewInit( // Return status. + BYTE *pcEntries, // Array of structs we are managing. + ULONG iEntrySize); // Size of the entries. + +//***************************************************************************** +// This can be called to change the pointer to the table that the hash table +// is managing. You might call this if (for example) you realloc the size +// of the table and its pointer is different. +//***************************************************************************** + void SetTable( + BYTE *pcEntries) // Array of structs we are managing. + { + LIMITED_METHOD_CONTRACT; + m_pcEntries = (TADDR)pcEntries; + } + +//***************************************************************************** +// Clear the hash table as if there were nothing in it. +//***************************************************************************** + void Clear() + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(m_piBuckets != NULL); + memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG)); + } + +//***************************************************************************** +// Add the struct at the specified index in m_pcEntries to the hash chains. +//***************************************************************************** + BYTE *Add( // New entry. + ULONG iHash, // Hash value of entry to add. + ULONG iIndex); // Index of struct in m_pcEntries. + +//***************************************************************************** +// Delete the struct at the specified index in m_pcEntries from the hash chains. +//***************************************************************************** + void Delete( + ULONG iHash, // Hash value of entry to delete. + ULONG iIndex); // Index of struct in m_pcEntries. + + void Delete( + ULONG iHash, // Hash value of entry to delete. + HASHENTRY *psEntry); // The struct to delete. + +//***************************************************************************** +// The item at the specified index has been moved, update the previous and +// next item. +//***************************************************************************** + void Move( + ULONG iHash, // Hash value for the item. + ULONG iNew); // New location. + +#endif // #ifndef DACCESS_COMPILE + +//***************************************************************************** +// Return a boolean indicating whether or not this hash table has been inited. +//***************************************************************************** + int IsInited() + { + LIMITED_METHOD_CONTRACT; + return (m_piBuckets != NULL); + } + +//***************************************************************************** +// Search the hash table for an entry with the specified key value. +//***************************************************************************** + BYTE *Find( // Index of struct in m_pcEntries. + ULONG iHash, // Hash value of the item. + SIZE_T key); // The key to match. + +//***************************************************************************** +// Search the hash table for the next entry with the specified key value. +//***************************************************************************** + ULONG FindNext( // Index of struct in m_pcEntries. + SIZE_T key, // The key to match. + ULONG iIndex); // Index of previous match. + +//***************************************************************************** +// Returns the first entry in the first hash bucket and inits the search +// struct. Use the FindNextEntry function to continue walking the list. The +// return order is not gauranteed. +//***************************************************************************** + BYTE *FindFirstEntry( // First entry found, or 0. + HASHFIND *psSrch) // Search object. + { + WRAPPER_NO_CONTRACT; + if (m_piBuckets == 0) + return (0); + psSrch->iBucket = 1; + psSrch->iNext = m_piBuckets[0]; + return (FindNextEntry(psSrch)); + } + +//***************************************************************************** +// Returns the next entry in the list. +//***************************************************************************** + BYTE *FindNextEntry( // The next entry, or0 for end of list. + HASHFIND *psSrch); // Search object. + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, + ULONG numEntries); +#endif + +protected: + virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0; +}; + + +class CNewData +{ +public: + static BYTE *Alloc(int iSize, int iMaxSize) + { + WRAPPER_NO_CONTRACT; + return (new BYTE[iSize]); + } + static void Free(BYTE *pPtr, int iSize) + { + LIMITED_METHOD_CONTRACT; + delete [] pPtr; + } + static BYTE *Grow(BYTE *&pPtr, int iCurSize) + { + WRAPPER_NO_CONTRACT; + BYTE *p; + S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize)); + //check for overflow + if(newSize.IsOverflow()) + p = NULL; + else + p = new (nothrow) BYTE[newSize.Value()]; + if (p == 0) return (0); + memcpy (p, pPtr, iCurSize); + delete [] pPtr; + pPtr = p; + return pPtr; + } + static void Clean(BYTE * pData, int iSize) + { + } + static int RoundSize(int iSize) + { + LIMITED_METHOD_CONTRACT; + return (iSize); + } + static int GrowSize(int iCurSize) + { + LIMITED_METHOD_CONTRACT; + int newSize = (3 * iCurSize) / 2; + return (newSize < 256) ? 256 : newSize; + } +}; + +class CNewDataNoThrow +{ +public: + static BYTE *Alloc(int iSize, int iMaxSize) + { + WRAPPER_NO_CONTRACT; + return (new (nothrow) BYTE[iSize]); + } + static void Free(BYTE *pPtr, int iSize) + { + LIMITED_METHOD_CONTRACT; + delete [] pPtr; + } + static BYTE *Grow(BYTE *&pPtr, int iCurSize) + { + WRAPPER_NO_CONTRACT; + BYTE *p; + S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize)); + //check for overflow + if(newSize.IsOverflow()) + p = NULL; + else + p = new (nothrow) BYTE[newSize.Value()]; + if (p == 0) return (0); + memcpy (p, pPtr, iCurSize); + delete [] pPtr; + pPtr = p; + return pPtr; + } + static void Clean(BYTE * pData, int iSize) + { + } + static int RoundSize(int iSize) + { + LIMITED_METHOD_CONTRACT; + return (iSize); + } + static int GrowSize(int iCurSize) + { + LIMITED_METHOD_CONTRACT; + int newSize = (3 * iCurSize) / 2; + return (newSize < 256) ? 256 : newSize; + } +}; + + +//***************************************************************************** +// IMPORTANT: This data structure is deprecated, please do not add any new uses. +// The hashtable implementation that should be used instead is code:SHash. +// If code:SHash does not work for you, talk to mailto:clrdeag. +//***************************************************************************** +// CHashTable expects the data to be in a single array - this is provided by +// CHashTableAndData. +// The array is allocated using the MemMgr type. CNewData and +// CNewDataNoThrow can be used for this. +//***************************************************************************** +template +class CHashTableAndData : public CHashTable +{ +public: + ULONG m_iFree; // Index into m_pcEntries[] of next available slot + ULONG m_iEntries; // size of m_pcEntries[] + +public: + + CHashTableAndData() : + CHashTable() + { + LIMITED_METHOD_CONTRACT; + } + + CHashTableAndData( + ULONG iBuckets) : // # of chains we are hashing into. + CHashTable(iBuckets) + { + LIMITED_METHOD_CONTRACT; + } + +#ifndef DACCESS_COMPILE + + ~CHashTableAndData() + { + WRAPPER_NO_CONTRACT; + if (m_pcEntries != NULL) + MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize)); + } + +//***************************************************************************** +// This is the second part of construction where we do all of the work that +// can fail. We also take the array of structs here because the calling class +// presumably needs to allocate it in its NewInit. +//***************************************************************************** + HRESULT NewInit( // Return status. + ULONG iEntries, // # of entries. + ULONG iEntrySize, // Size of the entries. + int iMaxSize); // Max size of data. + +//***************************************************************************** +// Clear the hash table as if there were nothing in it. +//***************************************************************************** + void Clear() + { + WRAPPER_NO_CONTRACT; + m_iFree = 0; + InitFreeChain(0, m_iEntries); + CHashTable::Clear(); + } + +//***************************************************************************** +// Grabs a slot for the new entry to be added. +// The caller should fill in the non-HASHENTRY part of the returned slot +//***************************************************************************** + BYTE *Add( + ULONG iHash) // Hash value of entry to add. + { + WRAPPER_NO_CONTRACT; + FREEHASHENTRY *psEntry; + + // Make the table bigger if necessary. + if (m_iFree == UINT32_MAX && !Grow()) + return (NULL); + + // Add the first entry from the free list to the hash chain. + psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree); + m_iFree = psEntry->iFree; + + // If we're recycling memory, give our memory-allocator a chance to re-init it. + + // Each entry is prefixed with a header - we don't want to trash that. + SIZE_T cbHeader = sizeof(FREEHASHENTRY); + MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader)); + + return ((BYTE *) psEntry); + } + +//***************************************************************************** +// Delete the struct at the specified index in m_pcEntries from the hash chains. +//***************************************************************************** + void Delete( + ULONG iHash, // Hash value of entry to delete. + ULONG iIndex) // Index of struct in m_pcEntries. + { + WRAPPER_NO_CONTRACT; + CHashTable::Delete(iHash, iIndex); + ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree; + m_iFree = iIndex; + } + + void Delete( + ULONG iHash, // Hash value of entry to delete. + HASHENTRY *psEntry) // The struct to delete. + { + WRAPPER_NO_CONTRACT; + CHashTable::Delete(iHash, psEntry); + ((FREEHASHENTRY *) psEntry)->iFree = m_iFree; + m_iFree = ItemIndex(psEntry); + } + +#endif // #ifndef DACCESS_COMPILE + + // This is a sad legacy workaround. The debugger's patch table (implemented as this + // class) is shared across process. We publish the runtime offsets of + // some key fields. Since those fields are private, we have to provide + // accessors here. So if you're not using these functions, don't start. + // We can hopefully remove them. + // Note that we can't just make RCThread a friend of this class (we tried + // originally) because the inheritence chain has a private modifier, + // so DebuggerPatchTable::m_pcEntries is illegal. + static SIZE_T helper_GetOffsetOfEntries() + { + LIMITED_METHOD_CONTRACT; + return offsetof(CHashTableAndData, m_pcEntries); + } + + static SIZE_T helper_GetOffsetOfCount() + { + LIMITED_METHOD_CONTRACT; + return offsetof(CHashTableAndData, m_iEntries); + } + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) + { + SUPPORTS_DAC; + CHashTable::EnumMemoryRegions(flags, m_iEntries); + } +#endif + +private: + void InitFreeChain(ULONG iStart,ULONG iEnd); + int Grow(); +}; + +#ifndef DACCESS_COMPILE + +//***************************************************************************** +// This is the second part of construction where we do all of the work that +// can fail. We also take the array of structs here because the calling class +// presumably needs to allocate it in its NewInit. +//***************************************************************************** +template +HRESULT CHashTableAndData::NewInit(// Return status. + ULONG iEntries, // # of entries. + ULONG iEntrySize, // Size of the entries. + int iMaxSize) // Max size of data. +{ + WRAPPER_NO_CONTRACT; + BYTE *pcEntries; + HRESULT hr; + + + // note that this function can throw because it depends on the ::Alloc + + // Allocate the memory for the entries. + if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize), + MemMgr::RoundSize(iMaxSize))) == 0) + return (E_OUTOFMEMORY); + m_iEntries = iEntries; + + // Init the base table. + if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize))) + MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize)); + else + { + // Init the free chain. + m_iFree = 0; + InitFreeChain(0, iEntries); + } + return (hr); +} + +//***************************************************************************** +// Initialize a range of records such that they are linked together to be put +// on the free chain. +//***************************************************************************** +template +void CHashTableAndData::InitFreeChain( + ULONG iStart, // Index to start initializing. + ULONG iEnd) // Index to stop initializing +{ + LIMITED_METHOD_CONTRACT; + BYTE* pcPtr; + _ASSERTE(iEnd > iStart); + + pcPtr = (BYTE*)m_pcEntries + iStart * (size_t)m_iEntrySize; + for (++iStart; iStart < iEnd; ++iStart) + { + ((FREEHASHENTRY *) pcPtr)->iFree = iStart; + pcPtr += m_iEntrySize; + } + ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX; +} + +//***************************************************************************** +// Attempt to increase the amount of space available for the record heap. +//***************************************************************************** +template +int CHashTableAndData::Grow() // 1 if successful, 0 if not. +{ + WRAPPER_NO_CONTRACT; + int iCurSize; // Current size in bytes. + int iEntries; // New # of entries. + + _ASSERTE(m_pcEntries != NULL); + _ASSERTE(m_iFree == UINT32_MAX); + + // Compute the current size and new # of entries. + S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize); + if( iTotEntrySize.IsOverflow() ) + { + _ASSERTE( !"CHashTableAndData overflow!" ); + return (0); + } + iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() ); + iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize; + + if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) ) + { + _ASSERTE( !"CHashTableAndData overflow!" ); + return (0); + } + + // Try to expand the array. + if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0) + return (0); + + // Init the newly allocated space. + InitFreeChain(m_iEntries, iEntries); + m_iFree = m_iEntries; + m_iEntries = iEntries; + return (1); +} + +#endif // #ifndef DACCESS_COMPILE + +//***************************************************************************** +//***************************************************************************** + +inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data) +{ + LIMITED_METHOD_DAC_CONTRACT; + return ((currentHash << 5) + currentHash) ^ data; +} + +inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr) +{ + WRAPPER_NO_CONTRACT; + SUPPORTS_DAC; + return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast(ptr)))); +} + +inline DWORD HashThreeToOne(DWORD a, DWORD b, DWORD c) +{ + LIMITED_METHOD_DAC_CONTRACT; + + /* + lookup3.c, by Bob Jenkins, May 2006, Public Domain. + + These are functions for producing 32-bit hashes for hash table lookup. + hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() + are externally useful functions. Routines to test the hash are included + if SELF_TEST is defined. You can use this free for any purpose. It's in + the public domain. It has no warranty. + */ + + #define rot32(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + c ^= b; c -= rot32(b,14); + a ^= c; a -= rot32(c,11); + b ^= a; b -= rot32(a,25); + c ^= b; c -= rot32(b,16); + a ^= c; a -= rot32(c,4); + b ^= a; b -= rot32(a,14); + c ^= b; c -= rot32(b,24); + + return c; +} + +inline ULONG HashBytes(BYTE const *pbData, size_t iSize) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + + BYTE const *pbDataEnd = pbData + iSize; + + for (/**/ ; pbData < pbDataEnd; pbData++) + { + hash = ((hash << 5) + hash) ^ *pbData; + } + return hash; +} + +// Helper function for hashing a string char by char. +inline ULONG HashStringA(LPCSTR szStr) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + int c; + + while ((c = *szStr) != 0) + { + hash = ((hash << 5) + hash) ^ c; + ++szStr; + } + return hash; +} + +inline ULONG HashString(LPCWSTR szStr) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + int c; + + while ((c = *szStr) != 0) + { + hash = ((hash << 5) + hash) ^ c; + ++szStr; + } + return hash; +} + +inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + + // hash the string two characters at a time + ULONG *ptr = (ULONG *)szStr; + + // we assume that szStr is null-terminated + _ASSERTE(cchStr <= wcslen(szStr)); + SIZE_T cDwordCount = (cchStr + 1) / 2; + + for (SIZE_T i = 0; i < cDwordCount; i++) + { + hash = ((hash << 5) + hash) ^ ptr[i]; + } + + return hash; +} + +// Case-insensitive string hash function. +inline ULONG HashiStringA(LPCSTR szStr) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + while (*szStr != 0) + { + hash = ((hash << 5) + hash) ^ toupper(*szStr); + szStr++; + } + return hash; +} + +// Case-insensitive string hash function. +inline ULONG HashiString(LPCWSTR szStr) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + while (*szStr != 0) + { + hash = ((hash << 5) + hash) ^ towupper(*szStr); + szStr++; + } + return hash; +} + +// Case-insensitive string hash function. +inline ULONG HashiStringN(LPCWSTR szStr, DWORD count) +{ + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + while (*szStr != 0 && count--) + { + hash = ((hash << 5) + hash) ^ towupper(*szStr); + szStr++; + } + return hash; +} + +// Case-insensitive string hash function when all of the +// characters in the string are known to be below 0x80. +// Knowing this is much more efficient than calling +// towupper above. +inline ULONG HashiStringKnownLower80(LPCWSTR szStr) { + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + int c; + int mask = ~0x20; + while ((c = *szStr)!=0) { + //If we have a lowercase character, ANDing off 0x20 + //(mask) will make it an uppercase character. + if (c>='a' && c<='z') { + c&=mask; + } + hash = ((hash << 5) + hash) ^ c; + ++szStr; + } + return hash; +} + +inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) { + LIMITED_METHOD_CONTRACT; + ULONG hash = 5381; + int c; + int mask = ~0x20; + while ((c = *szStr) !=0 && count--) { + //If we have a lowercase character, ANDing off 0x20 + //(mask) will make it an uppercase character. + if (c>='a' && c<='z') { + c&=mask; + } + hash = ((hash << 5) + hash) ^ c; + ++szStr; + } + return hash; +} + +//***************************************************************************** +// IMPORTANT: This data structure is deprecated, please do not add any new uses. +// The hashtable implementation that should be used instead is code:SHash. +// If code:SHash does not work for you, talk to mailto:clrdeag. +//***************************************************************************** +// This class implements a closed hashing table. Values are hashed to a bucket, +// and if that bucket is full already, then the value is placed in the next +// free bucket starting after the desired target (with wrap around). If the +// table becomes 75% full, it is grown and rehashed to reduce lookups. This +// class is best used in a reltively small lookup table where hashing is +// not going to cause many collisions. By not having the collision chain +// logic, a lot of memory is saved. +// +// The user of the template is required to supply several methods which decide +// how each element can be marked as free, deleted, or used. It would have +// been possible to write this with more internal logic, but that would require +// either (a) more overhead to add status on top of elements, or (b) hard +// coded types like one for strings, one for ints, etc... This gives you the +// flexibility of adding logic to your type. +//***************************************************************************** +class CClosedHashBase +{ + BYTE *EntryPtr(int iEntry) + { + LIMITED_METHOD_CONTRACT; + return (m_rgData + (iEntry * (size_t)m_iEntrySize)); + } + + BYTE *EntryPtr(int iEntry, BYTE *rgData) + { + LIMITED_METHOD_CONTRACT; + return (rgData + (iEntry * (size_t)m_iEntrySize)); + } + +public: + enum ELEMENTSTATUS + { + FREE, // Item is not in use right now. + DELETED, // Item is deleted. + USED // Item is in use. + }; + + CClosedHashBase( + int iBuckets, // How many buckets should we start with. + int iEntrySize, // Size of an entry. + bool bPerfect) : // true if bucket size will hash with no collisions. + m_bPerfect(bPerfect), + m_iBuckets(iBuckets), + m_iEntrySize(iEntrySize), + m_iCount(0), + m_iCollisions(0), + m_rgData(0) + { + LIMITED_METHOD_CONTRACT; + m_iSize = iBuckets + 7; + } + + virtual ~CClosedHashBase() + { + WRAPPER_NO_CONTRACT; + Clear(); + } + + virtual void Clear() + { + LIMITED_METHOD_CONTRACT; + delete [] m_rgData; + m_iCount = 0; + m_iCollisions = 0; + m_rgData = 0; + } + +//***************************************************************************** +// Accessors for getting at the underlying data. Be careful to use Count() +// only when you want the number of buckets actually used. +//***************************************************************************** + + int Count() + { + LIMITED_METHOD_CONTRACT; + return (m_iCount); + } + + int Collisions() + { + LIMITED_METHOD_CONTRACT; + return (m_iCollisions); + } + + int Buckets() + { + LIMITED_METHOD_CONTRACT; + return (m_iBuckets); + } + + void SetBuckets(int iBuckets, bool bPerfect=false) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(m_rgData == 0); + m_iBuckets = iBuckets; + m_iSize = m_iBuckets + 7; + m_bPerfect = bPerfect; + } + + BYTE *Data() + { + LIMITED_METHOD_CONTRACT; + return (m_rgData); + } + +//***************************************************************************** +// Add a new item to hash table given the key value. If this new entry +// exceeds maximum size, then the table will grow and be re-hashed, which +// may cause a memory error. +//***************************************************************************** + BYTE *Add( // New item to fill out on success. + void *pData) // The value to hash on. + { + WRAPPER_NO_CONTRACT; + // If we haven't allocated any memory, or it is too small, fix it. + if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect)) + { + if (!ReHash()) + return (0); + } + + return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount)); + } + +//***************************************************************************** +// Delete the given value. This will simply mark the entry as deleted (in +// order to keep the collision chain intact). There is an optimization that +// consecutive deleted entries leading up to a free entry are themselves freed +// to reduce collisions later on. +//***************************************************************************** + void Delete( + void *pData); // Key value to delete. + + +//***************************************************************************** +// Callback function passed to DeleteLoop. +//***************************************************************************** + typedef BOOL (* DELETELOOPFUNC)( // Delete current item? + BYTE *pEntry, // Bucket entry to evaluate + void *pCustomizer); // User-defined value + +//***************************************************************************** +// Iterates over all active values, passing each one to pDeleteLoopFunc. +// If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer +// and faster than using FindNext() and Delete(). +//***************************************************************************** + void DeleteLoop( + DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item + void *pCustomizer); // Extra value passed to deletefunc. + + +//***************************************************************************** +// Lookup a key value and return a pointer to the element if found. +//***************************************************************************** + BYTE *Find( // The item if found, 0 if not. + void *pData); // The key to lookup. + +//***************************************************************************** +// Look for an item in the table. If it isn't found, then create a new one and +// return that. +//***************************************************************************** + BYTE *FindOrAdd( // The item if found, 0 if not. + void *pData, // The key to lookup. + bool &bNew); // true if created. + +//***************************************************************************** +// The following functions are used to traverse each used entry. This code +// will skip over deleted and free entries freeing the caller up from such +// logic. +//***************************************************************************** + BYTE *GetFirst() // The first entry, 0 if none. + { + WRAPPER_NO_CONTRACT; + int i; // Loop control. + + // If we've never allocated the table there can't be any to get. + if (m_rgData == 0) + return (0); + + // Find the first one. + for (i=0; i class CClosedHash : public CClosedHashBase +{ +public: + CClosedHash( + int iBuckets, // How many buckets should we start with. + bool bPerfect=false) : // true if bucket size will hash with no collisions. + CClosedHashBase(iBuckets, sizeof(T), bPerfect) + { + WRAPPER_NO_CONTRACT; + } + + T &operator[](int iIndex) + { + WRAPPER_NO_CONTRACT; + return ((T &) *(Data() + (iIndex * sizeof(T)))); + } + + +//***************************************************************************** +// Add a new item to hash table given the key value. If this new entry +// exceeds maximum size, then the table will grow and be re-hashed, which +// may cause a memory error. +//***************************************************************************** + T *Add( // New item to fill out on success. + void *pData) // The value to hash on. + { + WRAPPER_NO_CONTRACT; + return ((T *) CClosedHashBase::Add(pData)); + } + +//***************************************************************************** +// Lookup a key value and return a pointer to the element if found. +//***************************************************************************** + T *Find( // The item if found, 0 if not. + void *pData) // The key to lookup. + { + WRAPPER_NO_CONTRACT; + return ((T *) CClosedHashBase::Find(pData)); + } + +//***************************************************************************** +// Look for an item in the table. If it isn't found, then create a new one and +// return that. +//***************************************************************************** + T *FindOrAdd( // The item if found, 0 if not. + void *pData, // The key to lookup. + bool &bNew) // true if created. + { + WRAPPER_NO_CONTRACT; + return ((T *) CClosedHashBase::FindOrAdd(pData, bNew)); + } + + +//***************************************************************************** +// The following functions are used to traverse each used entry. This code +// will skip over deleted and free entries freeing the caller up from such +// logic. +//***************************************************************************** + T *GetFirst() // The first entry, 0 if none. + { + WRAPPER_NO_CONTRACT; + return ((T *) CClosedHashBase::GetFirst()); + } + + T *GetNext(T *Prev) // The next entry, 0 if done. + { + WRAPPER_NO_CONTRACT; + return ((T *) CClosedHashBase::GetNext((BYTE *) Prev)); + } +}; + + +//***************************************************************************** +// IMPORTANT: This data structure is deprecated, please do not add any new uses. +// The hashtable implementation that should be used instead is code:SHash. +// If code:SHash does not work for you, talk to mailto:clrdeag. +//***************************************************************************** +// Closed hash with typed parameters. The derived class is the second +// parameter to the template. The derived class must implement: +// unsigned long Hash(const T *pData); +// unsigned long Compare(const T *p1, T *p2); +// ELEMENTSTATUS Status(T *pEntry); +// void SetStatus(T *pEntry, ELEMENTSTATUS s); +// void* GetKey(T *pEntry); +//***************************************************************************** +templateclass CClosedHashEx : public CClosedHash +{ +public: + CClosedHashEx( + int iBuckets, // How many buckets should we start with. + bool bPerfect=false) : // true if bucket size will hash with no collisions. + CClosedHash (iBuckets, bPerfect) + { + WRAPPER_NO_CONTRACT; + } + + unsigned int Hash(const void *pData) + { + WRAPPER_NO_CONTRACT; + return static_cast(this)->Hash((const T*)pData); + } + + unsigned int Compare(const void *p1, BYTE *p2) + { + WRAPPER_NO_CONTRACT; + return static_cast(this)->Compare((const T*)p1, (T*)p2); + } + + typename CClosedHash::ELEMENTSTATUS Status(BYTE *p) + { + WRAPPER_NO_CONTRACT; + return static_cast(this)->Status((T*)p); + } + + void SetStatus(BYTE *p, typename CClosedHash::ELEMENTSTATUS s) + { + WRAPPER_NO_CONTRACT; + static_cast(this)->SetStatus((T*)p, s); + } + + void* GetKey(BYTE *p) + { + WRAPPER_NO_CONTRACT; + return static_cast(this)->GetKey((T*)p); + } +}; + + +//***************************************************************************** +// IMPORTANT: This data structure is deprecated, please do not add any new uses. +// The hashtable implementation that should be used instead is code:SHash. +// If code:SHash does not work for you, talk to mailto:clrdeag. +//***************************************************************************** +// This template is another form of a closed hash table. It handles collisions +// through a linked chain. To use it, derive your hashed item from HASHLINK +// and implement the virtual functions required. 1.5 * ibuckets will be +// allocated, with the extra .5 used for collisions. If you add to the point +// where no free nodes are available, the entire table is grown to make room. +// The advantage to this system is that collisions are always directly known, +// there either is one or there isn't. +//***************************************************************************** +struct HASHLINK +{ + ULONG iNext; // Offset for next entry. +}; + +template class CChainedHash +{ + friend class VerifyLayoutsMD; +public: + CChainedHash(int iBuckets=32) : + m_rgData(0), + m_iBuckets(iBuckets), + m_iCount(0), + m_iMaxChain(0), + m_iFree(0) + { + LIMITED_METHOD_CONTRACT; + m_iSize = iBuckets + (iBuckets / 2); + } + + ~CChainedHash() + { + LIMITED_METHOD_CONTRACT; + if (m_rgData) + delete [] m_rgData; + } + + void SetBuckets(int iBuckets) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE(m_rgData == 0); + // if iBuckets==0, then we'll allocate a zero size array and AV on dereference. + _ASSERTE(iBuckets > 0); + m_iBuckets = iBuckets; + m_iSize = iBuckets + (iBuckets / 2); + } + + T *Add(void const *pData) + { + WRAPPER_NO_CONTRACT; + ULONG iHash; + int iBucket; + T *pItem; + + // Build the list if required. + if (m_rgData == 0 || m_iFree == 0xffffffff) + { + if (!ReHash()) + return (0); + } + + // Hash the item and pick a bucket. + iHash = Hash(pData); + iBucket = iHash % m_iBuckets; + + // Use the bucket if it is free. + if (InUse(&m_rgData[iBucket]) == false) + { + pItem = &m_rgData[iBucket]; + pItem->iNext = 0xffffffff; + } + // Else take one off of the free list for use. + else + { + ULONG iEntry; + + // Pull an item from the free list. + iEntry = m_iFree; + pItem = &m_rgData[m_iFree]; + m_iFree = pItem->iNext; + + // Link the new node in after the bucket. + pItem->iNext = m_rgData[iBucket].iNext; + m_rgData[iBucket].iNext = iEntry; + } + ++m_iCount; + return (pItem); + } + + T *Find(void const *pData, bool bAddIfNew=false) + { + WRAPPER_NO_CONTRACT; + ULONG iHash; + int iBucket; + T *pItem; + + // Check states for lookup. + if (m_rgData == 0) + { + // If we won't be adding, then we are through. + if (bAddIfNew == false) + return (0); + + // Otherwise, create the table. + if (!ReHash()) + return (0); + } + + // Hash the item and pick a bucket. + iHash = Hash(pData); + iBucket = iHash % m_iBuckets; + + // If it isn't in use, then there it wasn't found. + if (!InUse(&m_rgData[iBucket])) + { + if (bAddIfNew == false) + pItem = 0; + else + { + pItem = &m_rgData[iBucket]; + pItem->iNext = 0xffffffff; + ++m_iCount; + } + } + // Scan the list for the one we want. + else + { + ULONG iChain = 0; + for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem)) + { + if (Cmp(pData, pItem) == 0) + break; + ++iChain; + } + + if (!pItem && bAddIfNew) + { + ULONG iEntry; + + // Record maximum chain length. + if (iChain > m_iMaxChain) + m_iMaxChain = iChain; + + // Now need more room. + if (m_iFree == 0xffffffff) + { + if (!ReHash()) + return (0); + } + + // Pull an item from the free list. + iEntry = m_iFree; + pItem = &m_rgData[m_iFree]; + m_iFree = pItem->iNext; + + // Link the new node in after the bucket. + pItem->iNext = m_rgData[iBucket].iNext; + m_rgData[iBucket].iNext = iEntry; + ++m_iCount; + } + } + return (pItem); + } + + int Count() + { + LIMITED_METHOD_CONTRACT; + return (m_iCount); + } + + int Buckets() + { + LIMITED_METHOD_CONTRACT; + return (m_iBuckets); + } + + ULONG MaxChainLength() + { + LIMITED_METHOD_CONTRACT; + return (m_iMaxChain); + } + + virtual void Clear() + { + LIMITED_METHOD_CONTRACT; + // Free up the memory. + if (m_rgData) + { + delete [] m_rgData; + m_rgData = 0; + } + + m_rgData = 0; + m_iFree = 0; + m_iCount = 0; + m_iMaxChain = 0; + } + + virtual bool InUse(T *pItem)=0; + virtual void SetFree(T *pItem)=0; + virtual ULONG Hash(void const *pData)=0; + virtual int Cmp(void const *pData, void *pItem)=0; +private: + inline T *GetNext(T *pItem) + { + LIMITED_METHOD_CONTRACT; + if (pItem->iNext != 0xffffffff) + return ((T *) &m_rgData[pItem->iNext]); + return (0); + } + + bool ReHash() + { + WRAPPER_NO_CONTRACT; + T *rgTemp; + int iNewSize; + + // If this is a first time allocation, then just malloc it. + if (!m_rgData) + { + if ((m_rgData = new (nothrow) T[m_iSize]) == 0) + return (false); + + int i; + for (i=0; iiNext = i + 1; + ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff; + return (true); + } + + // Otherwise we need more room on the free chain, so allocate some. + iNewSize = m_iSize + (m_iSize / 2); + + // Allocate/realloc memory. + if ((rgTemp = new (nothrow) T[iNewSize]) == 0) + return (false); + + memcpy (rgTemp,m_rgData,m_iSize*sizeof(T)); + delete [] m_rgData; + + // Init new entries, save the new free chain, and reset internals. + m_iFree = m_iSize; + for (int i=m_iFree; iiNext = i + 1; + } + ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff; + + m_rgData = rgTemp; + m_iSize = iNewSize; + return (true); + } + +private: + T *m_rgData; // Data to store items in. + int m_iBuckets; // How many buckets we want. + int m_iSize; // How many are allocated. + int m_iCount; // How many are we using. + ULONG m_iMaxChain; // Max chain length. + ULONG m_iFree; // Free chain. +}; + + +//***************************************************************************** +// +//********** String helper functions. +// +//***************************************************************************** + +//***************************************************************************** +// Checks if string length exceeds the specified limit +//***************************************************************************** +inline BOOL IsStrLongerThan(__in __in_z char* pstr, unsigned N) +{ + LIMITED_METHOD_CONTRACT; + unsigned i = 0; + if(pstr) + { + for(i=0; (i < N)&&(pstr[i]); i++); + } + return (i >= N); +} + + +//***************************************************************************** +// Class to parse a list of simple assembly names and then find a match +//***************************************************************************** + +class AssemblyNamesList +{ + struct AssemblyName + { + LPUTF8 m_assemblyName; + AssemblyName *m_next; // Next name + }; + + AssemblyName *m_pNames; // List of names + +public: + + bool IsInList(LPCUTF8 assemblyName); + + bool IsEmpty() + { + LIMITED_METHOD_CONTRACT; + return m_pNames == 0; + } + + AssemblyNamesList(__in LPWSTR list); + ~AssemblyNamesList(); +}; + +//***************************************************************************** +// Class to parse a list of method names and then find a match +//***************************************************************************** + +struct CORINFO_SIG_INFO; + +class MethodNamesListBase +{ + struct MethodName + { + LPUTF8 methodName; // NULL means wildcard + LPUTF8 className; // NULL means wildcard + int numArgs; // number of args for the method, -1 is wildcard + MethodName *next; // Next name + }; + + MethodName *pNames; // List of names + + bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs); + +public: + void Init() + { + LIMITED_METHOD_CONTRACT; + pNames = 0; + } + + void Init(__in __in_z LPWSTR list) + { + WRAPPER_NO_CONTRACT; + pNames = 0; + Insert(list); + } + + void Destroy(); + + void Insert(__in __in_z LPWSTR list); + + bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL); + bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo); + bool IsEmpty() + { + LIMITED_METHOD_CONTRACT; + return pNames == 0; + } +}; + +class MethodNamesList : public MethodNamesListBase +{ +public: + MethodNamesList() + { + WRAPPER_NO_CONTRACT; + Init(); + } + + MethodNamesList(__in LPWSTR list) + { + WRAPPER_NO_CONTRACT; + Init(list); + } + + ~MethodNamesList() + { + WRAPPER_NO_CONTRACT; + Destroy(); + } +}; + +#if !defined(NO_CLRCONFIG) + +/**************************************************************************/ +/* simple wrappers around the REGUTIL and MethodNameList routines that make + the lookup lazy */ + +/* to be used as static variable - no constructor/destructor, assumes zero + initialized memory */ + +class ConfigDWORD +{ +public: + // + // NOTE: The following function is deprecated; use the CLRConfig class instead. + // To access a configuration value through CLRConfig, add an entry in file:../inc/CLRConfigValues.h. + // + inline DWORD val_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0) + { + WRAPPER_NO_CONTRACT; + // make sure that the memory was zero initialized + _ASSERTE(m_inited == 0 || m_inited == 1); + + if (!m_inited) init_DontUse_(keyName, defaultVal); + return m_value; + } + inline DWORD val(const CLRConfig::ConfigDWORDInfo & info) + { + WRAPPER_NO_CONTRACT; + // make sure that the memory was zero initialized + _ASSERTE(m_inited == 0 || m_inited == 1); + + if (!m_inited) init(info); + return m_value; + } + +private: + void init_DontUse_(__in __in_z LPCWSTR keyName, DWORD defaultVal=0); + void init(const CLRConfig::ConfigDWORDInfo & info); + +private: + DWORD m_value; + BYTE m_inited; +}; + +/**************************************************************************/ +class ConfigString +{ +public: + inline LPWSTR val(const CLRConfig::ConfigStringInfo & info) + { + WRAPPER_NO_CONTRACT; + // make sure that the memory was zero initialized + _ASSERTE(m_inited == 0 || m_inited == 1); + + if (!m_inited) init(info); + return m_value; + } + + bool isInitialized() + { + WRAPPER_NO_CONTRACT; + + // make sure that the memory was zero initialized + _ASSERTE(m_inited == 0 || m_inited == 1); + + return m_inited == 1; + } + +private: + void init(const CLRConfig::ConfigStringInfo & info); + +private: + LPWSTR m_value; + BYTE m_inited; +}; + +/**************************************************************************/ +class ConfigMethodSet +{ +public: + bool isEmpty() + { + WRAPPER_NO_CONTRACT; + _ASSERTE(m_inited == 1); + return m_list.IsEmpty(); + } + + bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL); + bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo); + + inline void ensureInit(const CLRConfig::ConfigStringInfo & info) + { + WRAPPER_NO_CONTRACT; + // make sure that the memory was zero initialized + _ASSERTE(m_inited == 0 || m_inited == 1); + + if (!m_inited) init(info); + } + +private: + void init(const CLRConfig::ConfigStringInfo & info); + +private: + MethodNamesListBase m_list; + + BYTE m_inited; +}; + +#endif // !defined(NO_CLRCONFIG) + +//***************************************************************************** +// Convert a pointer to a string into a GUID. +//***************************************************************************** +HRESULT LPCSTRToGuid( // Return status. + LPCSTR szGuid, // String to convert. + GUID *psGuid); // Buffer for converted GUID. + +//***************************************************************************** +// Convert a GUID into a pointer to a string +//***************************************************************************** +int GuidToLPWSTR( // Return status. + GUID Guid, // [IN] The GUID to convert. + __out_ecount (cchGuid) LPWSTR szGuid, // [OUT] String into which the GUID is stored + DWORD cchGuid); // [IN] Size in wide chars of szGuid + +//***************************************************************************** +// Parse a Wide char string into a GUID +//***************************************************************************** +BOOL LPWSTRToGuid( + GUID * Guid, // [OUT] The GUID to fill in + __in_ecount(cchGuid) LPCWSTR szGuid, // [IN] String to parse + DWORD cchGuid); // [IN] Count in wchars in string + +typedef VPTR(class RangeList) PTR_RangeList; + +class RangeList +{ + public: + VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList) + +#ifndef DACCESS_COMPILE + RangeList(); + ~RangeList(); +#else + RangeList() + { + LIMITED_METHOD_CONTRACT; + } +#endif + + // Wrappers to make the virtual calls DAC-safe. + BOOL AddRange(const BYTE *start, const BYTE *end, void *id) + { + return this->AddRangeWorker(start, end, id); + } + + void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL) + { + return this->RemoveRangesWorker(id, start, end); + } + + BOOL IsInRange(TADDR address, TADDR *pID = NULL) + { + SUPPORTS_DAC; + + return this->IsInRangeWorker(address, pID); + } + +#ifndef DACCESS_COMPILE + + // You can overload these two for synchronization (as LockedRangeList does) + virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id); + // If both "start" and "end" are NULL, then this method deletes all ranges with + // the given id (i.e. the original behaviour). Otherwise, it ignores the given + // id and deletes all ranges falling in the region [start, end). + virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL); +#else + virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id) + { + return TRUE; + } + virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { } +#endif // !DACCESS_COMPILE + + virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL); + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); +#endif + + enum + { + RANGE_COUNT = 10 + }; + + + private: + struct Range + { + TADDR start; + TADDR end; + TADDR id; + }; + + struct RangeListBlock + { + Range ranges[RANGE_COUNT]; + DPTR(RangeListBlock) next; + +#ifdef DACCESS_COMPILE + void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); +#endif + + }; + + void InitBlock(RangeListBlock *block); + + RangeListBlock m_starterBlock; + DPTR(RangeListBlock) m_firstEmptyBlock; + TADDR m_firstEmptyRange; +}; + + +// +// A private function to do the equavilent of a CoCreateInstance in +// cases where we can't make the real call. Use this when, for +// instance, you need to create a symbol reader in the Runtime but +// we're not CoInitialized. Obviously, this is only good for COM +// objects for which CoCreateInstance is just a glorified +// find-and-load-me operation. +// + +HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid, + LPCWSTR wszDllPath, + REFIID riid, + void ** ppv, + HMODULE * phmodDll); + +// Provided for backward compatibility and for code that doesn't need the HMODULE of the +// DLL that was loaded to create the COM object. See comment at implementation of +// code:FakeCoCreateInstanceEx for more details. +inline HRESULT FakeCoCreateInstance(REFCLSID rclsid, + REFIID riid, + void ** ppv) +{ + CONTRACTL + { + NOTHROW; + } + CONTRACTL_END; + + return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL); +}; + +//***************************************************************************** +// Gets the directory based on the location of the module. This routine +// is called at COR setup time. Set is called during EEStartup and by the +// MetaData dispenser. +//***************************************************************************** +HRESULT GetInternalSystemDirectory(__out_ecount_part_opt(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength); +LPCWSTR GetInternalSystemDirectory(__out_opt DWORD * pdwLength = NULL); + +//***************************************************************************** +// This function validates the given Method/Field/Standalone signature. (util.cpp) +//***************************************************************************** +struct IMDInternalImport; +HRESULT validateTokenSig( + mdToken tk, // [IN] Token whose signature needs to be validated. + PCCOR_SIGNATURE pbSig, // [IN] Signature. + ULONG cbSig, // [IN] Size in bytes of the signature. + DWORD dwFlags, // [IN] Method flags. + IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr + +//***************************************************************************** +// Determine the version number of the runtime that was used to build the +// specified image. The pMetadata pointer passed in is the pointer to the +// metadata contained in the image. +//***************************************************************************** +HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString); + +//***************************************************************************** +// The registry keys and values that contain the information regarding +// the default registered unmanaged debugger. +//***************************************************************************** +SELECTANY const WCHAR kDebugApplicationsPoliciesKey[] = W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications"); +SELECTANY const WCHAR kDebugApplicationsKey[] = W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications"); + +SELECTANY const WCHAR kUnmanagedDebuggerKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug"); +SELECTANY const WCHAR kUnmanagedDebuggerValue[] = W("Debugger"); +SELECTANY const WCHAR kUnmanagedDebuggerAutoValue[] = W("Auto"); +SELECTANY const WCHAR kUnmanagedDebuggerAutoExclusionListKey[] = W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList"); + +BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key. + LPCWSTR szKey, // Key name to look at. + LPCWSTR szName, // Name of value to get. + long *pValue, // Put value here, if found. + BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64 + +HRESULT GetCurrentModuleFileName(SString& pBuffer); + +//***************************************************************************** +// Retrieve information regarding what registered default debugger +//***************************************************************************** +void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto); +HRESULT GetDebuggerSettingInfoWorker(__out_ecount_part_opt(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto); + +void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch); + + +//***************************************************************************** +// Convert a UTF8 string to Unicode, into a CQuickArray. +//***************************************************************************** +HRESULT Utf2Quick( + LPCUTF8 pStr, // The string to convert. + CQuickArray &rStr, // The QuickArray to convert it into. + int iCurLen = 0); // Initial characters in the array to leave (default 0). + +//***************************************************************************** +// Extract the movl 64-bit unsigned immediate from an IA64 bundle +// (Format X2) +//***************************************************************************** +UINT64 GetIA64Imm64(UINT64 * pBundle); +UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1); + +//***************************************************************************** +// Deposit the movl 64-bit unsigned immediate into an IA64 bundle +// (Format X2) +//***************************************************************************** +void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64); + +//***************************************************************************** +// Extract the IP-Relative signed 25-bit immediate from an IA64 bundle +// (Formats B1, B2 or B3) +// Note that due to branch target alignment requirements +// the lowest four bits in the result will always be zero. +//***************************************************************************** +INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot); +INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot); + +//***************************************************************************** +// Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle +// (Formats B1, B2 or B3) +// Note that due to branch target alignment requirements +// the lowest four bits are required to be zero. +//***************************************************************************** +void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25); + +//***************************************************************************** +// Extract the IP-Relative signed 64-bit immediate from an IA64 bundle +// (Formats X3 or X4) +//***************************************************************************** +INT64 GetIA64Rel64(UINT64 * pBundle); +INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1); + +//***************************************************************************** +// Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle +// (Formats X3 or X4) +//***************************************************************************** +void PutIA64Rel64(UINT64 * pBundle, INT64 imm64); + +//***************************************************************************** +// Extract the 32-bit immediate from movw/movt Thumb2 sequence +//***************************************************************************** +UINT32 GetThumb2Mov32(UINT16 * p); + +//***************************************************************************** +// Deposit the 32-bit immediate into movw/movt Thumb2 sequence +//***************************************************************************** +void PutThumb2Mov32(UINT16 * p, UINT32 imm32); + +//***************************************************************************** +// Extract the 24-bit rel offset from bl instruction +//***************************************************************************** +INT32 GetThumb2BlRel24(UINT16 * p); + +//***************************************************************************** +// Extract the 24-bit rel offset from bl instruction +//***************************************************************************** +void PutThumb2BlRel24(UINT16 * p, INT32 imm24); + +//***************************************************************************** +// Extract the PC-Relative offset from a b or bl instruction +//***************************************************************************** +INT32 GetArm64Rel28(UINT32 * pCode); + +//***************************************************************************** +// Extract the PC-Relative page address from an adrp instruction +//***************************************************************************** +INT32 GetArm64Rel21(UINT32 * pCode); + +//***************************************************************************** +// Extract the page offset from an add instruction +//***************************************************************************** +INT32 GetArm64Rel12(UINT32 * pCode); + +//***************************************************************************** +// Deposit the PC-Relative offset 'imm28' into a b or bl instruction +//***************************************************************************** +void PutArm64Rel28(UINT32 * pCode, INT32 imm28); + +//***************************************************************************** +// Deposit the PC-Relative page address 'imm21' into an adrp instruction +//***************************************************************************** +void PutArm64Rel21(UINT32 * pCode, INT32 imm21); + +//***************************************************************************** +// Deposit the page offset 'imm12' into an add instruction +//***************************************************************************** +void PutArm64Rel12(UINT32 * pCode, INT32 imm12); + +//***************************************************************************** +// Returns whether the offset fits into bl instruction +//***************************************************************************** +inline bool FitsInThumb2BlRel24(INT32 imm24) +{ + return ((imm24 << 7) >> 7) == imm24; +} + +//***************************************************************************** +// Returns whether the offset fits into an Arm64 b or bl instruction +//***************************************************************************** +inline bool FitsInRel28(INT32 val32) +{ + return (val32 >= -0x08000000) && (val32 < 0x08000000); +} + +//***************************************************************************** +// Returns whether the offset fits into an Arm64 adrp instruction +//***************************************************************************** +inline bool FitsInRel21(INT32 val32) +{ + return (val32 >= 0) && (val32 <= 0x001FFFFF); +} + +//***************************************************************************** +// Returns whether the offset fits into an Arm64 add instruction +//***************************************************************************** +inline bool FitsInRel12(INT32 val32) +{ + return (val32 >= 0) && (val32 <= 0x00000FFF); +} + +//***************************************************************************** +// Returns whether the offset fits into an Arm64 b or bl instruction +//***************************************************************************** +inline bool FitsInRel28(INT64 val64) +{ + return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL); +} + +//***************************************************************************** +// Splits a command line into argc/argv lists, using the VC7 parsing rules. +// This functions interface mimics the CommandLineToArgvW api. +// If function fails, returns NULL. +// If function suceeds, call delete [] on return pointer when done. +//***************************************************************************** +LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs); + +// +// TEB access can be dangerous when using fibers because a fiber may +// run on multiple threads. If the TEB pointer is retrieved and saved +// and then a fiber is moved to a different thread, when it accesses +// the saved TEB pointer, it will be looking at the TEB state for a +// different fiber. +// +// These accessors serve the purpose of retrieving information from the +// TEB in a manner that ensures that the current fiber will not switch +// threads while the access is occuring. +// +class ClrTeb +{ +public: +#if defined(FEATURE_PAL) + + // returns pointer that uniquely identifies the fiber + static void* GetFiberPtrId() + { + LIMITED_METHOD_CONTRACT; + // not fiber for FEATURE_PAL - use the regular thread ID + return (void *)(size_t)GetCurrentThreadId(); + } + + static void* InvalidFiberPtrId() + { + return NULL; + } + + static void* GetStackBase() + { + return PAL_GetStackBase(); + } + + static void* GetStackLimit() + { + return PAL_GetStackLimit(); + } + +#else // !FEATURE_PAL + + // returns pointer that uniquely identifies the fiber + static void* GetFiberPtrId() + { + LIMITED_METHOD_CONTRACT; + // stackbase is the unique fiber identifier + return NtCurrentTeb()->NtTib.StackBase; + } + + static void* GetStackBase() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->NtTib.StackBase; + } + + static void* GetStackLimit() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->NtTib.StackLimit; + } + + // Please don't start to use this method unless you absolutely have to. + // The reason why this is added is for WIN64 to support LEGACY PE-style TLS + // variables. On X86 it is supported by the JIT compilers themselves. On + // WIN64 we build more logic into the JIT helper for accessing fields. + static void* GetLegacyThreadLocalStoragePointer() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->ThreadLocalStoragePointer; + } + + static void* GetOleReservedPtr() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->ReservedForOle; + } + + static void* GetProcessEnvironmentBlock() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->ProcessEnvironmentBlock; + } + + + static void* InvalidFiberPtrId() + { + return (void*) 1; + } +#endif // !FEATURE_PAL +}; + +#if !defined(DACCESS_COMPILE) + +// check if current thread is a GC thread (concurrent or server) +inline BOOL IsGCSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GC); +} + +// check if current thread is a Gate thread +inline BOOL IsGateSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Gate); +} + +// check if current thread is a Timer thread +inline BOOL IsTimerSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Timer); +} + +// check if current thread is a debugger helper thread +inline BOOL IsDbgHelperSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DbgHelper); +} + +// check if current thread is a debugger helper thread +inline BOOL IsETWRundownSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ETWRundownThread); +} + +// check if current thread is a generic instantiation lookup compare thread +inline BOOL IsGenericInstantiationLookupCompareThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_GenericInstantiationCompare); +} + +// check if current thread is a thread which is performing shutdown +inline BOOL IsShutdownSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Shutdown); +} + +inline BOOL IsThreadPoolIOCompletionSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_IOCompletion); +} + +inline BOOL IsThreadPoolWorkerSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Threadpool_Worker); +} + +inline BOOL IsWaitSpecialThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Wait); +} + +// check if current thread is a thread which is performing shutdown +inline BOOL IsSuspendEEThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_DynamicSuspendEE); +} + +inline BOOL IsFinalizerThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_Finalizer); +} + +inline BOOL IsShutdownHelperThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ShutdownHelper); +} + +inline BOOL IsProfilerAttachThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + return !!(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ThreadType_ProfAPI_Attach); +} + +// set specical type for current thread +inline void ClrFlsSetThreadType (TlsThreadTypeFlag flag) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) |flag)); +} + +// clear specical type for current thread +inline void ClrFlsClearThreadType (TlsThreadTypeFlag flag) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + + ClrFlsSetValue (TlsIdx_ThreadType, (LPVOID)(((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & ~flag)); +} + +#endif //!DACCESS_COMPILE + +#ifdef DACCESS_COMPILE +#define SET_THREAD_TYPE_STACKWALKER(pThread) +#define CLEAR_THREAD_TYPE_STACKWALKER() +#else // DACCESS_COMPILE +#define SET_THREAD_TYPE_STACKWALKER(pThread) ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, pThread) +#define CLEAR_THREAD_TYPE_STACKWALKER() ClrFlsSetValue(TlsIdx_StackWalkerWalkingThread, NULL) +#endif // DACCESS_COMPILE + +HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription); + +inline BOOL IsStackWalkerThread() +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_CANNOT_TAKE_LOCK; + +#if defined(DACCESS_COMPILE) + return FALSE; +#else + return ClrFlsGetValue (TlsIdx_StackWalkerWalkingThread) != NULL; +#endif +} + +inline BOOL IsGCThread () +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + STATIC_CONTRACT_SUPPORTS_DAC; + +#if !defined(DACCESS_COMPILE) + return IsGCSpecialThread () || IsSuspendEEThread (); +#else + return FALSE; +#endif +} + +class ClrFlsThreadTypeSwitch +{ +public: + ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + +#ifndef DACCESS_COMPILE + m_flag = flag; + m_fPreviouslySet = (((size_t)ClrFlsGetValue (TlsIdx_ThreadType)) & flag); + + // In debug builds, remember the full group of flags that were set at the time + // the constructor was called. This will be used in ASSERTs in the destructor + INDEBUG(m_nPreviousFlagGroup = (size_t)ClrFlsGetValue (TlsIdx_ThreadType)); + + if (!m_fPreviouslySet) + { + ClrFlsSetThreadType(flag); + } +#endif // DACCESS_COMPILE + } + + ~ClrFlsThreadTypeSwitch () + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + +#ifndef DACCESS_COMPILE + // This holder should only be used to set (and thus restore) ONE thread type flag + // at a time. If more than that one flag was modified since this holder was + // instantiated, then this holder still restores only the flag it knows about. To + // prevent confusion, assert if some other flag was modified, so the user doesn't + // expect the holder to restore the entire original set of flags. + // + // The expression below says that the only difference between the previous flag + // group and the current flag group should be m_flag (or no difference at all, if + // m_flag's state didn't actually change). + _ASSERTE(((m_nPreviousFlagGroup ^ (size_t) ClrFlsGetValue(TlsIdx_ThreadType)) | (size_t) m_flag) == (size_t) m_flag); + + if (m_fPreviouslySet) + { + ClrFlsSetThreadType(m_flag); + } + else + { + ClrFlsClearThreadType(m_flag); + } +#endif // DACCESS_COMPILE + } + +private: + TlsThreadTypeFlag m_flag; + BOOL m_fPreviouslySet; + INDEBUG(size_t m_nPreviousFlagGroup); +}; + +class ClrFlsValueSwitch +{ +public: + ClrFlsValueSwitch (PredefinedTlsSlots slot, PVOID value) + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + +#ifndef DACCESS_COMPILE + m_slot = slot; + m_PreviousValue = ClrFlsGetValue(slot); + ClrFlsSetValue(slot, value); +#endif // DACCESS_COMPILE + } + + ~ClrFlsValueSwitch () + { + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_MODE_ANY; + +#ifndef DACCESS_COMPILE + ClrFlsSetValue(m_slot, m_PreviousValue); +#endif // DACCESS_COMPILE + } + +private: + PVOID m_PreviousValue; + PredefinedTlsSlots m_slot; +}; + +//********************************************************************************* + +// When we're hosted, operations called by the host (such as Thread::YieldTask) +// may not cause calls back into the host, as the host needs not be reentrant. +// Use the following holder for code in which calls into the host are forbidden. +// (If a call into the host is attempted nevertheless, an assert will fire.) + +class ForbidCallsIntoHostOnThisThread +{ +private: + static Volatile s_pvOwningFiber; + + FORCEINLINE static BOOL Enter(BOOL) + { + WRAPPER_NO_CONTRACT; + return InterlockedCompareExchangePointer( + &s_pvOwningFiber, ClrTeb::GetFiberPtrId(), NULL) == NULL; + } + + FORCEINLINE static void Leave(BOOL) + { + LIMITED_METHOD_CONTRACT; + s_pvOwningFiber = NULL; + } + +public: + typedef ConditionalStateHolder Holder; + + FORCEINLINE static BOOL CanThisThreadCallIntoHost() + { + WRAPPER_NO_CONTRACT; + return s_pvOwningFiber != ClrTeb::GetFiberPtrId(); + } +}; + +typedef ForbidCallsIntoHostOnThisThread::Holder ForbidCallsIntoHostOnThisThreadHolder; + +FORCEINLINE BOOL CanThisThreadCallIntoHost() +{ + WRAPPER_NO_CONTRACT; + return ForbidCallsIntoHostOnThisThread::CanThisThreadCallIntoHost(); +} + +//********************************************************************************* + +#include "contract.inl" + +namespace util +{ + // compare adapters + // + + template < typename T > + struct less + { + bool operator()( T const & first, T const & second ) const + { + return first < second; + } + }; + + template < typename T > + struct greater + { + bool operator()( T const & first, T const & second ) const + { + return first > second; + } + }; + + + // sort adapters + // + + template< typename Iter, typename Pred > + void sort( Iter begin, Iter end, Pred pred ); + + template< typename T, typename Pred > + void sort( T * begin, T * end, Pred pred ) + { + struct sort_helper : CQuickSort< T > + { + sort_helper( T * begin, T * end, Pred pred ) + : CQuickSort< T >( begin, end - begin ) + , m_pred( pred ) + {} + + virtual int Compare( T * first, T * second ) + { + return m_pred( *first, *second ) ? -1 + : ( m_pred( *second, *first ) ? 1 : 0 ); + } + + Pred m_pred; + }; + + sort_helper sort_obj( begin, end, pred ); + sort_obj.Sort(); + } + + + template < typename Iter > + void sort( Iter begin, Iter end ); + + template < typename T > + void sort( T * begin, T * end ) + { + util::sort( begin, end, util::less< T >() ); + } + + + // binary search adapters + // + + template < typename Iter, typename T, typename Pred > + Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred ); + + template < typename T, typename Pred > + T * lower_bound( T * begin, T * end, T const & val, Pred pred ) + { + for (; begin != end; ) + { + T * mid = begin + ( end - begin ) / 2; + if ( pred( *mid, val ) ) + begin = ++mid; + else + end = mid; + } + + return begin; + } + + + template < typename Iter, typename T > + Iter lower_bound( Iter begin, Iter end, T const & val ); + + template < typename T > + T * lower_bound( T * begin, T * end, T const & val ) + { + return util::lower_bound( begin, end, val, util::less< T >() ); + } +} + + +/* ------------------------------------------------------------------------ * + * Overloaded operators for the executable heap + * ------------------------------------------------------------------------ */ + +#ifndef FEATURE_PAL + +struct CExecutable { int x; }; +extern const CExecutable executable; + +void * __cdecl operator new(size_t n, const CExecutable&); +void * __cdecl operator new[](size_t n, const CExecutable&); +void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&); +void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&); + + +// +// Executable heap delete to match the executable heap new above. +// +template void DeleteExecutable(T *p) +{ + if (p != NULL) + { + p->T::~T(); + + ClrHeapFree(ClrGetProcessExecutableHeap(), 0, p); + } +} + +#endif // FEATURE_PAL + +INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);) + +BOOL NoGuiOnAssert(); +#ifdef _DEBUG +VOID TerminateOnAssert(); +#endif // _DEBUG + +class HighCharHelper { +public: + static inline BOOL IsHighChar(int c) { + return (BOOL)HighCharTable[c]; + } + +private: + static const BYTE HighCharTable[]; +}; + + +BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommitedStack); + +FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); } + +typedef Wrapper BSTRHolder; + +// HMODULE_TGT represents a handle to a module in the target process. In non-DAC builds this is identical +// to HMODULE (HINSTANCE), which is the base address of the module. In DAC builds this must be a target address, +// and so is represented by TADDR. + +#ifdef DACCESS_COMPILE +typedef TADDR HMODULE_TGT; +#else +typedef HMODULE HMODULE_TGT; +#endif + +BOOL IsIPInModule(HMODULE_TGT hModule, PCODE ip); + +//---------------------------------------------------------------------------------------- +// The runtime invokes InitUtilcode() in its dllmain and passes along all of the critical +// callback pointers. For the desktop CLR, all DLLs loaded by the runtime must also call +// InitUtilcode with the same callbacks as the runtime used. To achieve this, the runtime +// calls a special initialization routine exposed by the loaded module with the callbacks, +// which in turn calls InitUtilcode. +// +// This structure collects all of the critical callback info passed in InitUtilcode(). +//---------------------------------------------------------------------------------------- +struct CoreClrCallbacks +{ + typedef IExecutionEngine* (* pfnIEE_t)(); + typedef HRESULT (* pfnGetCORSystemDirectory_t)(SString& pbuffer); + + HINSTANCE m_hmodCoreCLR; + pfnIEE_t m_pfnIEE; + pfnGetCORSystemDirectory_t m_pfnGetCORSystemDirectory; +}; + + +// For DAC, we include this functionality only when EH SxS is enabled. + +//---------------------------------------------------------------------------------------- +// CoreCLR must invoke this before CRT initialization to ensure utilcode has all the callback +// pointers it needs. +//---------------------------------------------------------------------------------------- +VOID InitUtilcode(const CoreClrCallbacks &cccallbacks); +CoreClrCallbacks const & GetClrCallbacks(); + +//---------------------------------------------------------------------------------------- +// Stuff below is for utilcode.lib eyes only. +//---------------------------------------------------------------------------------------- + +// Stores callback pointers provided by InitUtilcode(). +extern CoreClrCallbacks g_CoreClrCallbacks; + +// Throws up a helpful dialog if InitUtilcode() wasn't called. +#ifdef _DEBUG +void OnUninitializedCoreClrCallbacks(); +#define VALIDATECORECLRCALLBACKS() if (g_CoreClrCallbacks.m_hmodCoreCLR == NULL) OnUninitializedCoreClrCallbacks() +#else //_DEBUG +#define VALIDATECORECLRCALLBACKS() +#endif //_DEBUG + + +#ifdef FEATURE_CORRUPTING_EXCEPTIONS + +// Corrupting Exception limited support for outside the VM folder +BOOL IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE); + +#endif // FEATURE_CORRUPTING_EXCEPTIONS + +namespace UtilCode +{ + // These are type-safe versions of Interlocked[Compare]Exchange + // They avoid invoking struct cast operations via reinterpreting + // the struct's address as a LONG* or LONGLONG* and dereferencing it. + // + // If we had a global ::operator & (unary), we would love to use that + // to ensure we were not also accidentally getting a structs's provided + // operator &. TODO: probe with a static_assert? + + template + struct InterlockedCompareExchangeHelper; + + template + struct InterlockedCompareExchangeHelper + { + static inline T InterlockedExchange( + T volatile * target, + T value) + { + static_assert_no_msg(sizeof(T) == sizeof(LONG)); + LONG res = ::InterlockedExchange( + reinterpret_cast(target), + *reinterpret_cast(/*::operator*/&(value))); + return *reinterpret_cast(&res); + } + + static inline T InterlockedCompareExchange( + T volatile * destination, + T exchange, + T comparand) + { + static_assert_no_msg(sizeof(T) == sizeof(LONG)); + LONG res = ::InterlockedCompareExchange( + reinterpret_cast(destination), + *reinterpret_cast(/*::operator*/&(exchange)), + *reinterpret_cast(/*::operator*/&(comparand))); + return *reinterpret_cast(&res); + } + }; + + template + struct InterlockedCompareExchangeHelper + { + static inline T InterlockedExchange( + T volatile * target, + T value) + { + static_assert_no_msg(sizeof(T) == sizeof(LONGLONG)); + LONGLONG res = ::InterlockedExchange64( + reinterpret_cast(target), + *reinterpret_cast(/*::operator*/&(value))); + return *reinterpret_cast(&res); + } + + static inline T InterlockedCompareExchange( + T volatile * destination, + T exchange, + T comparand) + { + static_assert_no_msg(sizeof(T) == sizeof(LONGLONG)); + LONGLONG res = ::InterlockedCompareExchange64( + reinterpret_cast(destination), + *reinterpret_cast(/*::operator*/&(exchange)), + *reinterpret_cast(/*::operator*/&(comparand))); + return *reinterpret_cast(&res); + } + }; +} + +template +inline T InterlockedExchangeT( + T volatile * target, + T value) +{ + return ::UtilCode::InterlockedCompareExchangeHelper::InterlockedExchange( + target, value); +} + +template +inline T InterlockedCompareExchangeT( + T volatile * destination, + T exchange, + T comparand) +{ + return ::UtilCode::InterlockedCompareExchangeHelper::InterlockedCompareExchange( + destination, exchange, comparand); +} + +// Pointer variants for Interlocked[Compare]ExchangePointer +// If the underlying type is a const type, we have to remove its constness +// since Interlocked[Compare]ExchangePointer doesn't take const void * arguments. +template +inline T* InterlockedExchangeT( + T* volatile * target, + T* value) +{ + //STATIC_ASSERT(value == 0); + typedef typename std::remove_const::type * non_const_ptr_t; + return reinterpret_cast(InterlockedExchangePointer( + reinterpret_cast(const_cast(target)), + reinterpret_cast(const_cast(value)))); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + T* exchange, + T* comparand) +{ + //STATIC_ASSERT(exchange == 0); + typedef typename std::remove_const::type * non_const_ptr_t; + return reinterpret_cast(InterlockedCompareExchangePointer( + reinterpret_cast(const_cast(destination)), + reinterpret_cast(const_cast(exchange)), + reinterpret_cast(const_cast(comparand)))); +} + +// NULL pointer variants of the above to avoid having to cast NULL +// to the appropriate pointer type. +template +inline T* InterlockedExchangeT( + T* volatile * target, + int value) // When NULL is provided as argument. +{ + //STATIC_ASSERT(value == 0); + return InterlockedExchangeT(target, reinterpret_cast(value)); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + int exchange, // When NULL is provided as argument. + T* comparand) +{ + //STATIC_ASSERT(exchange == 0); + return InterlockedCompareExchangeT(destination, reinterpret_cast(exchange), comparand); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + T* exchange, + int comparand) // When NULL is provided as argument. +{ + //STATIC_ASSERT(comparand == 0); + return InterlockedCompareExchangeT(destination, exchange, reinterpret_cast(comparand)); +} + +// NULL pointer variants of the above to avoid having to cast NULL +// to the appropriate pointer type. +template +inline T* InterlockedExchangeT( + T* volatile * target, + std::nullptr_t value) // When nullptr is provided as argument. +{ + //STATIC_ASSERT(value == 0); + return InterlockedExchangeT(target, static_cast(value)); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + std::nullptr_t exchange, // When nullptr is provided as argument. + T* comparand) +{ + //STATIC_ASSERT(exchange == 0); + return InterlockedCompareExchangeT(destination, static_cast(exchange), comparand); +} + +template +inline T* InterlockedCompareExchangeT( + T* volatile * destination, + T* exchange, + std::nullptr_t comparand) // When nullptr is provided as argument. +{ + //STATIC_ASSERT(comparand == 0); + return InterlockedCompareExchangeT(destination, exchange, static_cast(comparand)); +} + +#undef InterlockedExchangePointer +#define InterlockedExchangePointer Use_InterlockedExchangeT +#undef InterlockedCompareExchangePointer +#define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT + +// Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL", +// then this would return "C:\Dir1\Dir2\" (note the trailing backslash). +HRESULT GetHModuleDirectory(HMODULE hMod, SString& wszPath); +HRESULT CopySystemDirectory(const SString& pPathString, SString& pbuffer); + +HMODULE LoadLocalizedResourceDLLForSDK(_In_z_ LPCWSTR wzResourceDllName, _In_opt_z_ LPCWSTR modulePath=NULL, bool trySelf=true); +// This is a slight variation that can be used for anything else +typedef void* (__cdecl *LocalizedFileHandler)(LPCWSTR); +void* FindLocalizedFile(_In_z_ LPCWSTR wzResourceDllName, LocalizedFileHandler lfh, _In_opt_z_ LPCWSTR modulePath=NULL); + + + +// Helper to support termination due to heap corruption +// It's not supported on Win2K, so we have to manually delay load it +void EnableTerminationOnHeapCorruption(); + + + +namespace Clr { namespace Util +{ + // This api returns a pointer to a null-terminated string that contains the local appdata directory + // or it returns NULL in the case that the directory could not be found. The return value from this function + // is not actually checked for existence. + HRESULT GetLocalAppDataDirectory(LPCWSTR *ppwzLocalAppDataDirectory); + HRESULT SetLocalAppDataDirectory(LPCWSTR pwzLocalAppDataDirectory); + +namespace Reg +{ + HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, SString & ssValue); + __success(return == S_OK) + HRESULT ReadStringValue(HKEY hKey, LPCWSTR wszSubKey, LPCWSTR wszName, __deref_out __deref_out_z LPWSTR* pwszValue); +} + +#ifdef FEATURE_COMINTEROP +namespace Com +{ + HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name); +} +#endif // FEATURE_COMINTEROP + +namespace Win32 +{ + static const WCHAR LONG_FILENAME_PREFIX_W[] = W("\\\\?\\"); + static const CHAR LONG_FILENAME_PREFIX_A[] = "\\\\?\\"; + + void GetModuleFileName( + HMODULE hModule, + SString & ssFileName, + bool fAllowLongFileNames = false); + + __success(return == S_OK) + HRESULT GetModuleFileName( + HMODULE hModule, + __deref_out_z LPWSTR * pwszFileName, + bool fAllowLongFileNames = false); + + void GetFullPathName( + SString const & ssFileName, + SString & ssPathName, + DWORD * pdwFilePartIdx, + bool fAllowLongFileNames = false); +} + +}} + +#if defined(FEATURE_APPX) && !defined(DACCESS_COMPILE) + // Forward declaration of AppX::IsAppXProcess + namespace AppX { bool IsAppXProcess(); } + + // LOAD_WITH_ALTERED_SEARCH_PATH is unsupported in AppX processes. + inline DWORD GetLoadWithAlteredSearchPathFlag() + { + WRAPPER_NO_CONTRACT; + return AppX::IsAppXProcess() ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH; + } +#else // FEATURE_APPX && !DACCESS_COMPILE + // LOAD_WITH_ALTERED_SEARCH_PATH can be used unconditionally. + inline DWORD GetLoadWithAlteredSearchPathFlag() + { + LIMITED_METHOD_CONTRACT; + #ifdef LOAD_WITH_ALTERED_SEARCH_PATH + return LOAD_WITH_ALTERED_SEARCH_PATH; + #else + return 0; + #endif + } +#endif // FEATURE_APPX && !DACCESS_COMPILE + +// clr::SafeAddRef and clr::SafeRelease helpers. +namespace clr +{ + //================================================================================================================= + template + static inline + typename std::enable_if< std::is_pointer::value, ItfT >::type + SafeAddRef(ItfT pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + if (pItf != nullptr) + { + pItf->AddRef(); + } + return pItf; + } + + //================================================================================================================= + template + typename std::enable_if< std::is_pointer::value && std::is_reference::value, ULONG >::type + SafeRelease(ItfT pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + ULONG res = 0; + if (pItf != nullptr) + { + res = pItf->Release(); + pItf = nullptr; + } + return res; + } + + //================================================================================================================= + template + typename std::enable_if< std::is_pointer::value && !std::is_reference::value, ULONG >::type + SafeRelease(ItfT pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + ULONG res = 0; + if (pItf != nullptr) + { + res = pItf->Release(); + } + return res; + } +} + +// clr::SafeDelete +namespace clr +{ + //================================================================================================================= + template + static inline + typename std::enable_if< std::is_pointer::value, PtrT >::type + SafeDelete(PtrT & ptr) + { + STATIC_CONTRACT_LIMITED_METHOD; + if (ptr != nullptr) + { + delete ptr; + ptr = nullptr; + } + } +} + +// ====================================================================================== +// Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp) + +struct SpinConstants +{ + DWORD dwInitialDuration; + DWORD dwMaximumDuration; + DWORD dwBackoffFactor; + DWORD dwRepetitions; + DWORD dwMonitorSpinCount; +}; + +extern SpinConstants g_SpinConstants; + +#endif // __UtilCode_h__ diff --git a/lib/coreclr/src/inc/utsem.h b/lib/coreclr/src/inc/utsem.h new file mode 100644 index 0000000000..91036db898 --- /dev/null +++ b/lib/coreclr/src/inc/utsem.h @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/* ---------------------------------------------------------------------------- + +---------------------------------------------------------------------------- */ +#ifndef __UTSEM_H__ +#define __UTSEM_H__ + + +// ------------------------------------------------------------- +// INCLUDES +// ------------------------------------------------------------- +#include "utilcode.h" + +/* ---------------------------------------------------------------------------- +@class UTSemReadWrite + + An instance of class UTSemReadWrite provides multi-read XOR single-write + (a.k.a. shared vs. exclusive) lock capabilities, with protection against + writer starvation. + + A thread MUST NOT call any of the Lock methods if it already holds a Lock. + (Doing so may result in a deadlock.) + + +---------------------------------------------------------------------------- */ +class UTSemReadWrite +{ +public: + UTSemReadWrite(); // Constructor + ~UTSemReadWrite(); // Destructor + + HRESULT Init(); + + HRESULT LockRead(); // Lock the object for reading + HRESULT LockWrite(); // Lock the object for writing + void UnlockRead(); // Unlock the object for reading + void UnlockWrite(); // Unlock the object for writing + +#ifdef _DEBUG + BOOL Debug_IsLockedForRead(); + BOOL Debug_IsLockedForWrite(); +#endif //_DEBUG + +private: + Semaphore * GetReadWaiterSemaphore() + { + return m_pReadWaiterSemaphore; + } + Event * GetWriteWaiterEvent() + { + return m_pWriteWaiterEvent; + } + + Volatile m_dwFlag; // internal state, see implementation + Semaphore * m_pReadWaiterSemaphore; // semaphore for awakening read waiters + Event * m_pWriteWaiterEvent; // event for awakening write waiters +}; // class UTSemReadWrite + +#endif // __UTSEM_H__ diff --git a/lib/coreclr/src/inc/vererror.h b/lib/coreclr/src/inc/vererror.h new file mode 100644 index 0000000000..2299b8e087 --- /dev/null +++ b/lib/coreclr/src/inc/vererror.h @@ -0,0 +1,137 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/************************************************************************************** + ** ** + ** Vererror.h - definitions of data structures, needed to report verifier errors. ** + ** ** + **************************************************************************************/ + +#ifndef __VERERROR_h__ +#define __VERERROR_h__ + +#ifndef _VER_RAW_STRUCT_FOR_IDL_ +#ifndef _JIT64_PEV_ +#include "corhdr.h" +#include "openum.h" +#include "corerror.h" +#endif // !_JIT64_PEV_ + +// Set these flags if the error info fields are valid. + +#define VER_ERR_FATAL 0x80000000L // Cannot Continue +#define VER_ERR_OFFSET 0x00000001L +#define VER_ERR_OPCODE 0x00000002L +#define VER_ERR_OPERAND 0x00000004L +#define VER_ERR_TOKEN 0x00000008L +#define VER_ERR_EXCEP_NUM_1 0x00000010L +#define VER_ERR_EXCEP_NUM_2 0x00000020L +#define VER_ERR_STACK_SLOT 0x00000040L +#define VER_ERR_ITEM_1 0x00000080L +#define VER_ERR_ITEM_2 0x00000100L +#define VER_ERR_ITEM_F 0x00000200L +#define VER_ERR_ITEM_E 0x00000400L +#define VER_ERR_TYPE_1 0x00000800L +#define VER_ERR_TYPE_2 0x00001000L +#define VER_ERR_TYPE_F 0x00002000L +#define VER_ERR_TYPE_E 0x00004000L +#define VER_ERR_ADDL_MSG 0x00008000L + +#define VER_ERR_SIG_MASK 0x07000000L // Enum +#define VER_ERR_METHOD_SIG 0x01000000L +#define VER_ERR_LOCAL_SIG 0x02000000L +#define VER_ERR_FIELD_SIG 0x03000000L +#define VER_ERR_CALL_SIG 0x04000000L + +#define VER_ERR_OPCODE_OFFSET (VER_ERR_OPCODE|VER_ERR_OFFSET) + +#define VER_ERR_LOCAL_VAR VER_ERR_LOCAL_SIG +#define VER_ERR_ARGUMENT VER_ERR_METHOD_SIG + +#define VER_ERR_ARG_RET 0xFFFFFFFEL // The Argument # is return +#define VER_ERR_NO_ARG 0xFFFFFFFFL // Argument # is not valid +#define VER_ERR_NO_LOC VER_ERR_NO_ARG // Local # is not valid + +typedef struct +{ + DWORD dwFlags; // BYREF / BOXED etc.. see veritem.hpp + void* pv; // TypeHandle / MethodDesc * etc. +} _VerItem; + +// This structure is used to fully define a verification error. +// Verification error codes are found in CorError.h +// The error resource strings are found in src/dlls/mscorrc/mscor.rc + +typedef struct VerErrorStruct +{ + DWORD dwFlags; // VER_ERR_XXX + + union { +#ifndef _JIT64_PEV_ + OPCODE opcode; +#endif // !_JIT64_PEV_ + unsigned long padding1; // to match with idl generated struct size + }; + + union { + DWORD dwOffset; // #of bytes from start of method + long uOffset; // for backward compat with Metadata validator + }; + + union { + mdToken token; + mdToken Token; // for backward compat with metadata validator + BYTE bCallConv; + CorElementType elem; + DWORD dwStackSlot; // positon in the Stack + unsigned long padding2; // to match with idl generated struct size + }; + + union { + _VerItem sItem1; + _VerItem sItemFound; + WCHAR* wszType1; + WCHAR* wszTypeFound; + DWORD dwException1; // Exception Record # + DWORD dwVarNumber; // Variable # + DWORD dwArgNumber; // Argument # + DWORD dwOperand; // Operand for the opcode + WCHAR* wszAdditionalMessage; // message from getlasterror + }; + + union { + _VerItem sItem2; + _VerItem sItemExpected; + WCHAR* wszType2; + WCHAR* wszTypeExpected; + DWORD dwException2; // Exception Record # + }; + +} VerError; + +#else + +// Assert that sizeof(_VerError) == sizeof(VerError) in Verifier.cpp +typedef struct tag_VerError +{ + unsigned long flags; // DWORD + unsigned long opcode; // OPCODE, padded to ulong + unsigned long uOffset; // DWORD + unsigned long Token; // mdToken + unsigned long item1_flags; // _VerItem.DWORD + int *item1_data; // _VerItem.PVOID + unsigned long item2_flags; // _VerItem.DWORD + int *item2_data; // _VerItem.PVOID +} _VerError; +#endif + +#endif // __VERERROR_h__ + + + + + + + + diff --git a/lib/coreclr/src/inc/volatile.h b/lib/coreclr/src/inc/volatile.h new file mode 100644 index 0000000000..fa756ef051 --- /dev/null +++ b/lib/coreclr/src/inc/volatile.h @@ -0,0 +1,532 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// Volatile.h +// + +// +// Defines the Volatile type, which provides uniform volatile-ness on +// Visual C++ and GNU C++. +// +// Visual C++ treats accesses to volatile variables as follows: no read or write +// can be removed by the compiler, no global memory access can be moved backwards past +// a volatile read, and no global memory access can be moved forward past a volatile +// write. +// +// The GCC volatile semantic is straight out of the C standard: the compiler is not +// allowed to remove accesses to volatile variables, and it is not allowed to reorder +// volatile accesses relative to other volatile accesses. It is allowed to freely +// reorder non-volatile accesses relative to volatile accesses. +// +// We have lots of code that assumes that ordering of non-volatile accesses will be +// constrained relative to volatile accesses. For example, this pattern appears all +// over the place: +// +// static volatile int lock = 0; +// +// while (InterlockedCompareExchange(&lock, 0, 1)) +// { +// //spin +// } +// +// //read and write variables protected by the lock +// +// lock = 0; +// +// This depends on the reads and writes in the critical section not moving past the +// final statement, which releases the lock. If this should happen, then you have an +// unintended race. +// +// The solution is to ban the use of the "volatile" keyword, and instead define our +// own type Volatile, which acts like a variable of type T except that accesses to +// the variable are always given VC++'s volatile semantics. +// +// (NOTE: The code above is not intended to be an example of how a spinlock should be +// implemented; it has many flaws, and should not be used. This code is intended only +// to illustrate where we might get into trouble with GCC's volatile semantics.) +// +// @TODO: many of the variables marked volatile in the CLR do not actually need to be +// volatile. For example, if a variable is just always passed to Interlocked functions +// (such as a refcount variable), there is no need for it to be volatile. A future +// cleanup task should be to examine each volatile variable and make them non-volatile +// if possible. +// +// @TODO: link to a "Memory Models for CLR Devs" doc here (this doc does not yet exist). +// + +#ifndef _VOLATILE_H_ +#define _VOLATILE_H_ + +#include "staticcontract.h" + +// +// This code is extremely compiler- and CPU-specific, and will need to be altered to +// support new compilers and/or CPUs. Here we enforce that we can only compile using +// VC++, or GCC on x86 or AMD64. +// +#if !defined(_MSC_VER) && !defined(__GNUC__) +#error The Volatile type is currently only defined for Visual C++ and GNU C++ +#endif + +#if defined(__GNUC__) && !defined(_X86_) && !defined(_AMD64_) && !defined(_ARM_) && !defined(_ARM64_) +#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM or ARM64 CPUs +#endif + +#if defined(__GNUC__) +#if defined(_ARM_) || defined(_ARM64_) +// This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows. +#define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb ish" : : : "memory") +#else +// +// For GCC, we prevent reordering by the compiler by inserting the following after a volatile +// load (to prevent subsequent operations from moving before the read), and before a volatile +// write (to prevent prior operations from moving past the write). We don't need to do anything +// special to prevent CPU reorderings, because the x86 and AMD64 architectures are already +// sufficiently constrained for our purposes. If we ever need to run on weaker CPU architectures +// (such as PowerPC), then we will need to do more work. +// +// Please do not use this macro outside of this file. It is subject to change or removal without +// notice. +// +#define VOLATILE_MEMORY_BARRIER() asm volatile ("" : : : "memory") +#endif // _ARM_ || _ARM64_ +#elif (defined(_ARM_) || defined(_ARM64_)) && _ISO_VOLATILE +// ARM & ARM64 have a very weak memory model and very few tools to control that model. We're forced to perform a full +// memory barrier to preserve the volatile semantics. Technically this is only necessary on MP systems but we +// currently don't have a cheap way to determine the number of CPUs from this header file. Revisit this if it +// turns out to be a performance issue for the uni-proc case. +#define VOLATILE_MEMORY_BARRIER() MemoryBarrier() +#else +// +// On VC++, reorderings at the compiler and machine level are prevented by the use of the +// "volatile" keyword in VolatileLoad and VolatileStore. This should work on any CPU architecture +// targeted by VC++ with /iso_volatile-. +// +#define VOLATILE_MEMORY_BARRIER() +#endif // __GNUC__ + +template +struct RemoveVolatile +{ + typedef T type; +}; + +template +struct RemoveVolatile +{ + typedef T type; +}; + + +// +// VolatileLoad loads a T from a pointer to T. It is guaranteed that this load will not be optimized +// away by the compiler, and that any operation that occurs after this load, in program order, will +// not be moved before this load. In general it is not guaranteed that the load will be atomic, though +// this is the case for most aligned scalar data types. If you need atomic loads or stores, you need +// to consult the compiler and CPU manuals to find which circumstances allow atomicity. +// +// Starting at version 3.8, clang errors out on initializing of type int * to volatile int *. To fix this, we add two templates to cast away volatility +// Helper structures for casting away volatileness + + +template +inline +T VolatileLoad(T const * pt) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; + +#ifndef DACCESS_COMPILE +#if defined(_ARM64_) && defined(__GNUC__) + T val; + static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); + if((1 << sizeof(T)) & lockFreeAtomicSizeMask) + { + __atomic_load((T const *)pt, const_cast::type *>(&val), __ATOMIC_ACQUIRE); + } + else + { + val = *(T volatile const *)pt; + asm volatile ("dmb ishld" : : : "memory"); + } +#else + T val = *(T volatile const *)pt; + VOLATILE_MEMORY_BARRIER(); +#endif +#else + T val = *pt; +#endif + return val; +} + +template +inline +T VolatileLoadWithoutBarrier(T const * pt) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; + +#ifndef DACCESS_COMPILE + T val = *(T volatile const *)pt; +#else + T val = *pt; +#endif + return val; +} + +template class Volatile; + +template +inline +T VolatileLoad(Volatile const * pt) +{ + STATIC_CONTRACT_SUPPORTS_DAC; + return pt->Load(); +} + +// +// VolatileStore stores a T into the target of a pointer to T. Is is guaranteed that this store will +// not be optimized away by the compiler, and that any operation that occurs before this store, in program +// order, will not be moved after this store. In general, it is not guaranteed that the store will be +// atomic, though this is the case for most aligned scalar data types. If you need atomic loads or stores, +// you need to consult the compiler and CPU manuals to find which circumstances allow atomicity. +// +template +inline +void VolatileStore(T* pt, T val) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; + +#ifndef DACCESS_COMPILE +#if defined(_ARM64_) && defined(__GNUC__) + static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); + if((1 << sizeof(T)) & lockFreeAtomicSizeMask) + { + __atomic_store((T volatile *)pt, &val, __ATOMIC_RELEASE); + } + else + { + VOLATILE_MEMORY_BARRIER(); + *(T volatile *)pt = val; + } +#else + VOLATILE_MEMORY_BARRIER(); + *(T volatile *)pt = val; +#endif +#else + *pt = val; +#endif +} + +template +inline +void VolatileStoreWithoutBarrier(T* pt, T val) +{ + STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; + +#ifndef DACCESS_COMPILE + *(T volatile *)pt = val; +#else + *pt = val; +#endif +} + +// +// Volatile implements accesses with our volatile semantics over a variable of type T. +// Wherever you would have used a "volatile Foo" or, equivalently, "Foo volatile", use Volatile +// instead. If Foo is a pointer type, use VolatilePtr. +// +// Note that there are still some things that don't work with a Volatile, +// that would have worked with a "volatile T". For example, you can't cast a Volatile to a float. +// You must instead cast to an int, then to a float. Or you can call Load on the Volatile, and +// cast the result to a float. In general, calling Load or Store explicitly will work around +// any problems that can't be solved by operator overloading. +// +// @TODO: it's not clear that we actually *want* any operator overloading here. It's in here primarily +// to ease the task of converting all of the old uses of the volatile keyword, but in the long +// run it's probably better if users of this class are forced to call Load() and Store() explicitly. +// This would make it much more clear where the memory barriers are, and which operations are actually +// being performed, but it will have to wait for another cleanup effort. +// +template +class Volatile +{ +private: + // + // The data which we are treating as volatile + // + T m_val; + +public: + // + // Default constructor. Results in an unitialized value! + // + inline Volatile() + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + + // + // Allow initialization of Volatile from a T + // + inline Volatile(const T& val) + { + STATIC_CONTRACT_SUPPORTS_DAC; + ((volatile T &)m_val) = val; + } + + // + // Copy constructor + // + inline Volatile(const Volatile& other) + { + STATIC_CONTRACT_SUPPORTS_DAC; + ((volatile T &)m_val) = other.Load(); + } + + // + // Loads the value of the volatile variable. See code:VolatileLoad for the semantics of this operation. + // + inline T Load() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return VolatileLoad(&m_val); + } + + // + // Loads the value of the volatile variable atomically without erecting the memory barrier. + // + inline T LoadWithoutBarrier() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return ((volatile T &)m_val); + } + + // + // Stores a new value to the volatile variable. See code:VolatileStore for the semantics of this + // operation. + // + inline void Store(const T& val) + { + STATIC_CONTRACT_SUPPORTS_DAC; + VolatileStore(&m_val, val); + } + + + // + // Stores a new value to the volatile variable atomically without erecting the memory barrier. + // + inline void StoreWithoutBarrier(const T& val) const + { + STATIC_CONTRACT_SUPPORTS_DAC; + ((volatile T &)m_val) = val; + } + + + // + // Gets a pointer to the volatile variable. This is dangerous, as it permits the variable to be + // accessed without using Load and Store, but it is necessary for passing Volatile to APIs like + // InterlockedIncrement. + // + inline volatile T* GetPointer() { return (volatile T*)&m_val; } + + + // + // Gets the raw value of the variable. This is dangerous, as it permits the variable to be + // accessed without using Load and Store + // + inline T& RawValue() { return m_val; } + + // + // Allow casts from Volatile to T. Note that this allows implicit casts, so you can + // pass a Volatile directly to a method that expects a T. + // + inline operator T() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return this->Load(); + } + + // + // Assignment from T + // + inline Volatile& operator=(T val) {Store(val); return *this;} + + // + // Get the address of the volatile variable. This is dangerous, as it allows the value of the + // volatile variable to be accessed directly, without going through Load and Store, but it is + // necessary for passing Volatile to APIs like InterlockedIncrement. Note that we are returning + // a pointer to a volatile T here, so we cannot accidentally pass this pointer to an API that + // expects a normal pointer. + // + inline T volatile * operator&() {return this->GetPointer();} + inline T volatile const * operator&() const {return this->GetPointer();} + + // + // Comparison operators + // + template + inline bool operator==(const TOther& other) const {return this->Load() == other;} + + template + inline bool operator!=(const TOther& other) const {return this->Load() != other;} + + // + // Miscellaneous operators. Add more as necessary. + // + inline Volatile& operator+=(T val) {Store(this->Load() + val); return *this;} + inline Volatile& operator-=(T val) {Store(this->Load() - val); return *this;} + inline Volatile& operator|=(T val) {Store(this->Load() | val); return *this;} + inline Volatile& operator&=(T val) {Store(this->Load() & val); return *this;} + inline bool operator!() const { STATIC_CONTRACT_SUPPORTS_DAC; return !this->Load();} + + // + // Prefix increment + // + inline Volatile& operator++() {this->Store(this->Load()+1); return *this;} + + // + // Postfix increment + // + inline T operator++(int) {T val = this->Load(); this->Store(val+1); return val;} + + // + // Prefix decrement + // + inline Volatile& operator--() {this->Store(this->Load()-1); return *this;} + + // + // Postfix decrement + // + inline T operator--(int) {T val = this->Load(); this->Store(val-1); return val;} +}; + +// +// A VolatilePtr builds on Volatile by adding operators appropriate to pointers. +// Wherever you would have used "Foo * volatile", use "VolatilePtr" instead. +// +// VolatilePtr also allows the substution of other types for the underlying pointer. This +// allows you to wrap a VolatilePtr around a custom type that looks like a pointer. For example, +// if what you want is a "volatile DPTR", use "VolatilePtr>". +// +template +class VolatilePtr : public Volatile

+{ +public: + // + // Default constructor. Results in an uninitialized pointer! + // + inline VolatilePtr() + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + + // + // Allow assignment from the pointer type. + // + inline VolatilePtr(P val) : Volatile

(val) + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + + // + // Copy constructor + // + inline VolatilePtr(const VolatilePtr& other) : Volatile

(other) + { + STATIC_CONTRACT_SUPPORTS_DAC; + } + + // + // Cast to the pointer type + // + inline operator P() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return (P)this->Load(); + } + + // + // Member access + // + inline P operator->() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return (P)this->Load(); + } + + // + // Dereference the pointer + // + inline T& operator*() const + { + STATIC_CONTRACT_SUPPORTS_DAC; + return *(P)this->Load(); + } + + // + // Access the pointer as an array + // + template + inline T& operator[](TIndex index) + { + STATIC_CONTRACT_SUPPORTS_DAC; + return ((P)this->Load())[index]; + } +}; + +// +// From here on out, we ban the use of the "volatile" keyword. If you found this while trying to define +// a volatile variable, go to the top of this file and start reading. +// +#ifdef volatile +#undef volatile +#endif +// ***** Temporarily removing this to unblock integration with new VC++ bits +//#define volatile (DoNotUseVolatileKeyword) volatile + +// The substitution for volatile above is defined in such a way that we can still explicitly access the +// volatile keyword without error using the macros below. Use with care. +//#define REMOVE_DONOTUSE_ERROR(x) +//#define RAW_KEYWORD(x) REMOVE_DONOTUSE_ERROR x +#define RAW_KEYWORD(x) x + +#ifdef DACCESS_COMPILE +// No need to use volatile in DAC builds - DAC is single-threaded and the target +// process is suspended. +#define VOLATILE(T) T +#else + +// Disable use of Volatile for GC/HandleTable code except on platforms where it's absolutely necessary. +#if defined(_MSC_VER) && !defined(_ARM_) && !defined(_ARM64_) +#define VOLATILE(T) T RAW_KEYWORD(volatile) +#else +#define VOLATILE(T) Volatile +#endif + +#endif // DACCESS_COMPILE + +// VolatilePtr-specific clr::SafeAddRef and clr::SafeRelease +namespace clr +{ + template < typename ItfT, typename PtrT > inline + #ifdef __checkReturn // Volatile.h is used in corunix headers, which don't define/nullify SAL. + __checkReturn + #endif + VolatilePtr& + SafeAddRef(VolatilePtr& pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + SafeAddRef(pItf.Load()); + return pItf; + } + + template < typename ItfT, typename PtrT > inline + ULONG + SafeRelease(VolatilePtr& pItf) + { + STATIC_CONTRACT_LIMITED_METHOD; + return SafeRelease(pItf.Load()); + } +} + +#endif //_VOLATILE_H_ diff --git a/lib/coreclr/src/inc/vptr_list.h b/lib/coreclr/src/inc/vptr_list.h new file mode 100644 index 0000000000..566cfa6e72 --- /dev/null +++ b/lib/coreclr/src/inc/vptr_list.h @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Any class with a vtable that needs to be instantiated +// during debugging data access must be listed here. + +VPTR_CLASS(Thread) + +VPTR_CLASS(EEJitManager) + +#ifdef FEATURE_PREJIT +VPTR_CLASS(NativeImageJitManager) +#endif // FEATURE_PREJIT +#ifdef FEATURE_READYTORUN +VPTR_CLASS(ReadyToRunJitManager) +#endif +VPTR_CLASS(EECodeManager) + +VPTR_CLASS(RangeList) +VPTR_CLASS(LockedRangeList) + +#ifdef EnC_SUPPORTED +VPTR_CLASS(EditAndContinueModule) +#endif +VPTR_CLASS(Module) +VPTR_CLASS(ReflectionModule) + +VPTR_CLASS(AppDomain) +VPTR_CLASS(SystemDomain) + +VPTR_CLASS(DomainAssembly) +VPTR_CLASS(PrecodeStubManager) +VPTR_CLASS(StubLinkStubManager) +VPTR_CLASS(ThePreStubManager) +VPTR_CLASS(ThunkHeapStubManager) +VPTR_CLASS(VirtualCallStubManager) +VPTR_CLASS(VirtualCallStubManagerManager) +VPTR_CLASS(JumpStubStubManager) +VPTR_CLASS(RangeSectionStubManager) +VPTR_CLASS(ILStubManager) +VPTR_CLASS(InteropDispatchStubManager) +VPTR_CLASS(DelegateInvokeStubManager) +VPTR_CLASS(TailCallStubManager) +VPTR_CLASS(PEFile) +VPTR_CLASS(PEAssembly) +VPTR_CLASS(PEImageLayout) +VPTR_CLASS(RawImageLayout) +VPTR_CLASS(ConvertedImageLayout) +VPTR_CLASS(MappedImageLayout) +#if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_PAL) +VPTR_CLASS(LoadedImageLayout) +#endif // !CROSSGEN_COMPILE && !FEATURE_PAL +VPTR_CLASS(FlatImageLayout) +#ifdef FEATURE_COMINTEROP +VPTR_CLASS(ComMethodFrame) +VPTR_CLASS(ComPlusMethodFrame) +VPTR_CLASS(ComPrestubMethodFrame) +#endif // FEATURE_COMINTEROP +VPTR_CLASS(ContextTransitionFrame) +#ifdef FEATURE_INTERPRETER +VPTR_CLASS(InterpreterFrame) +#endif // FEATURE_INTERPRETER +VPTR_CLASS(DebuggerClassInitMarkFrame) +VPTR_CLASS(DebuggerSecurityCodeMarkFrame) +VPTR_CLASS(DebuggerExitFrame) +VPTR_CLASS(DebuggerU2MCatchHandlerFrame) +VPTR_CLASS(FaultingExceptionFrame) +VPTR_CLASS(FuncEvalFrame) +VPTR_CLASS(GCFrame) +VPTR_CLASS(HelperMethodFrame) +VPTR_CLASS(HelperMethodFrame_1OBJ) +VPTR_CLASS(HelperMethodFrame_2OBJ) +VPTR_CLASS(HelperMethodFrame_3OBJ) +VPTR_CLASS(HelperMethodFrame_PROTECTOBJ) +#ifdef FEATURE_HIJACK +VPTR_CLASS(HijackFrame) +#endif +VPTR_CLASS(InlinedCallFrame) +VPTR_CLASS(SecureDelegateFrame) +VPTR_CLASS(MulticastFrame) +VPTR_CLASS(PInvokeCalliFrame) +VPTR_CLASS(PrestubMethodFrame) +VPTR_CLASS(ProtectByRefsFrame) +VPTR_CLASS(ProtectValueClassFrame) +#ifdef FEATURE_HIJACK +VPTR_CLASS(ResumableFrame) +VPTR_CLASS(RedirectedThreadFrame) +#endif +VPTR_CLASS(StubDispatchFrame) +VPTR_CLASS(ExternalMethodFrame) +#ifdef FEATURE_READYTORUN +VPTR_CLASS(DynamicHelperFrame) +#endif +#if !defined(_TARGET_X86_) +VPTR_CLASS(StubHelperFrame) +#endif +#if defined(_TARGET_X86_) +VPTR_CLASS(UMThkCallFrame) +#endif +VPTR_CLASS(TailCallFrame) +VPTR_CLASS(ExceptionFilterFrame) + +#ifdef _DEBUG +VPTR_CLASS(AssumeByrefFromJITStack) +#endif + +#ifdef DEBUGGING_SUPPORTED +VPTR_CLASS(Debugger) +VPTR_CLASS(EEDbgInterfaceImpl) +#endif // DEBUGGING_SUPPORTED + +VPTR_CLASS(DebuggerController) +VPTR_CLASS(DebuggerMethodInfoTable) +VPTR_CLASS(DebuggerPatchTable) + +VPTR_CLASS(LoaderCodeHeap) +VPTR_CLASS(HostCodeHeap) + +VPTR_CLASS(GlobalLoaderAllocator) +VPTR_CLASS(AssemblyLoaderAllocator) diff --git a/lib/coreclr/src/inc/warningcontrol.h b/lib/coreclr/src/inc/warningcontrol.h new file mode 100644 index 0000000000..e3b6f078ff --- /dev/null +++ b/lib/coreclr/src/inc/warningcontrol.h @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// warningcontrol.h +// +// Header file to globally control the warning settings for the entire Viper build. +// You do not need to explicitly include this file; rather, it gets included +// on the command line with a /FI (force include) directive. This is controlled +// in sources.vip. +// +// KEEP THIS LIST SORTED! +// + +#if defined(_MSC_VER) +#pragma warning(error :4007) // 'main' : must be __cdecl +#pragma warning(error :4013) // 'function' undefined - assuming extern returning int +#pragma warning(3 :4092) // sizeof returns 'unsigned long' +#pragma warning(error :4102) // "'%$S' : unreferenced label" +#pragma warning(3 :4121) // structure is sensitive to alignment +#pragma warning(3 :4125) // decimal digit in octal sequence +#pragma warning(3 :4130) // logical operation on address of string constant +#pragma warning(3 :4132) // const object should be initialized +#pragma warning(4 :4177) // pragma data_seg s/b at global scope +#pragma warning(3 :4212) // function declaration used ellipsis +#pragma warning(disable :4291) // delete not defined for new, c++ exception may cause leak +#pragma warning(disable :4302) // truncation from '%$S' to '%$S' +#pragma warning(disable :4311) // pointer truncation from '%$S' to '%$S' +#pragma warning(disable :4312) // '' : conversion from '%$S' to '%$S' of greater size +#pragma warning(disable :4477) // format string '%$S' requires an argument of type '%$S', but variadic argument %d has type '%$S' +#pragma warning(3 :4530) // C++ exception handler used, but unwind semantics are not enabled. Specify -GX +#pragma warning(error :4551) // Function call missing argument list + +#pragma warning(error :4700) // Local used w/o being initialized +#pragma warning(error :4806) // unsafe operation involving type 'bool' + +#if defined(_DEBUG) && (!defined(_MSC_FULL_VER) || (_MSC_FULL_VER <= 181040116)) +// The CLR header file check.h, macro CHECK_MSG_EX, can create unreachable code if the LEAVE_DEBUG_ONLY_CODE +// macro is not empty (such as it is defined in contract.h) and the _RESULT macro expands to "return". +// Checked-in compilers used by the TFS-based desktop build (e.g., version 18.10.40116.8) started reporting +// unreachable code warnings when debugholder.h was changed to no longer #define "return" to something relatively +// complex. However, newer compilers, such as Visual Studio 2015, used to build the CLR from the open source +// GitHub repo, still do not report this warning. We don't want to disable this warning for open source build, +// which will use a newer compiler. Hence, only disable it for older compilers. +#pragma warning(disable :4702) // unreachable code +#endif + +#endif // defined(_MSC_VER) diff --git a/lib/coreclr/src/inc/win64unwind.h b/lib/coreclr/src/inc/win64unwind.h new file mode 100644 index 0000000000..e4cea023b2 --- /dev/null +++ b/lib/coreclr/src/inc/win64unwind.h @@ -0,0 +1,126 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef _WIN64UNWIND_H_ +#define _WIN64UNWIND_H_ + +// +// Define AMD64 exception handling structures and function prototypes. +// +// Define unwind operation codes. +// + +typedef enum _UNWIND_OP_CODES { + UWOP_PUSH_NONVOL = 0, + UWOP_ALLOC_LARGE, + UWOP_ALLOC_SMALL, + UWOP_SET_FPREG, + UWOP_SAVE_NONVOL, + UWOP_SAVE_NONVOL_FAR, + UWOP_EPILOG, + UWOP_SPARE_CODE, + UWOP_SAVE_XMM128, + UWOP_SAVE_XMM128_FAR, + UWOP_PUSH_MACHFRAME, + +#ifdef PLATFORM_UNIX + // UWOP_SET_FPREG_LARGE is a CLR Unix-only extension to the Windows AMD64 unwind codes. + // It is not part of the standard Windows AMD64 unwind codes specification. + // UWOP_SET_FPREG allows for a maximum of a 240 byte offset between RSP and the + // frame pointer, when the frame pointer is established. UWOP_SET_FPREG_LARGE + // has a 32-bit range scaled by 16. When UWOP_SET_FPREG_LARGE is used, + // UNWIND_INFO.FrameRegister must be set to the frame pointer register, and + // UNWIND_INFO.FrameOffset must be set to 15 (its maximum value). UWOP_SET_FPREG_LARGE + // is followed by two UNWIND_CODEs that are combined to form a 32-bit offset (the same + // as UWOP_SAVE_NONVOL_FAR). This offset is then scaled by 16. The result must be less + // than 2^32 (that is, the top 4 bits of the unscaled 32-bit number must be zero). This + // result is used as the frame pointer register offset from RSP at the time the frame pointer + // is established. Either UWOP_SET_FPREG or UWOP_SET_FPREG_LARGE can be used, but not both. + + UWOP_SET_FPREG_LARGE, +#endif // PLATFORM_UNIX +} UNWIND_OP_CODES, *PUNWIND_OP_CODES; + +static const UCHAR UnwindOpExtraSlotTable[] = { + 0, // UWOP_PUSH_NONVOL + 1, // UWOP_ALLOC_LARGE (or 3, special cased in lookup code) + 0, // UWOP_ALLOC_SMALL + 0, // UWOP_SET_FPREG + 1, // UWOP_SAVE_NONVOL + 2, // UWOP_SAVE_NONVOL_FAR + 1, // UWOP_EPILOG + 2, // UWOP_SPARE_CODE // previously 64-bit UWOP_SAVE_XMM_FAR + 1, // UWOP_SAVE_XMM128 + 2, // UWOP_SAVE_XMM128_FAR + 0, // UWOP_PUSH_MACHFRAME + +#ifdef PLATFORM_UNIX + 2, // UWOP_SET_FPREG_LARGE +#endif // PLATFORM_UNIX +}; + +// +// Define unwind code structure. +// + +typedef union _UNWIND_CODE { + struct { + UCHAR CodeOffset; + UCHAR UnwindOp : 4; + UCHAR OpInfo : 4; + }; + + struct { + UCHAR OffsetLow; + UCHAR UnwindOp : 4; + UCHAR OffsetHigh : 4; + } EpilogueCode; + + USHORT FrameOffset; +} UNWIND_CODE, *PUNWIND_CODE; + +// +// Define unwind information flags. +// + +#define UNW_FLAG_NHANDLER 0x0 +#define UNW_FLAG_EHANDLER 0x1 +#define UNW_FLAG_UHANDLER 0x2 +#define UNW_FLAG_CHAININFO 0x4 + +#ifdef _TARGET_X86_ + +typedef struct _UNWIND_INFO { + ULONG FunctionLength; +} UNWIND_INFO, *PUNWIND_INFO; + +#else // _TARGET_X86_ + +typedef struct _UNWIND_INFO { + UCHAR Version : 3; + UCHAR Flags : 5; + UCHAR SizeOfProlog; + UCHAR CountOfUnwindCodes; + UCHAR FrameRegister : 4; + UCHAR FrameOffset : 4; + UNWIND_CODE UnwindCode[1]; + +// +// The unwind codes are followed by an optional DWORD aligned field that +// contains the exception handler address or the address of chained unwind +// information. If an exception handler address is specified, then it is +// followed by the language specified exception handler data. +// +// union { +// ULONG ExceptionHandler; +// ULONG FunctionEntry; +// }; +// +// ULONG ExceptionData[]; +// + +} UNWIND_INFO, *PUNWIND_INFO; + +#endif // _TARGET_X86_ +#endif // _WIN64UNWIND_H_ diff --git a/lib/coreclr/src/inc/winrt/ntassert.h b/lib/coreclr/src/inc/winrt/ntassert.h new file mode 100644 index 0000000000..33a90a1ab1 --- /dev/null +++ b/lib/coreclr/src/inc/winrt/ntassert.h @@ -0,0 +1,210 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + +Module Name: + + ntassert.h + +Abstract: + + Defines DbgRaiseAssertionFailure, and the NT_ASSERT and NT_VERIFY macros. + + Note that normally platform-specific definitions like + DbgRaiseAssertionFailure would go to platform-specific subheaders (nti386_x, + etc.), they are placed here instead for convenience. + +--*/ + +#pragma once + +// begin_wdm begin_winnt begin_ntminiport + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Assert exception. +// + +#if !defined(_DBGRAISEASSERTIONFAILURE_) && !defined(RC_INVOKED) && !defined(MIDL_PASS) + +#define _DBGRAISEASSERTIONFAILURE_ + +#if defined(_PREFAST_) + +__analysis_noreturn +FORCEINLINE +VOID +DbgRaiseAssertionFailure ( + VOID + ); + +#endif + +#if defined(_AMD64_) + +#if defined(_M_AMD64) + +VOID +__int2c ( + VOID + ); + +#pragma intrinsic(__int2c) + +#if !defined(_PREFAST_) + +#define DbgRaiseAssertionFailure() __int2c() + +#endif // !defined(_PREFAST_) + +#endif // defined(_M_AMD64) + +#elif defined(_X86_) + +#if defined(_M_IX86) + +#if _MSC_FULL_VER >= 140030222 + +VOID +__int2c ( + VOID + ); + +#pragma intrinsic(__int2c) + +#if !defined(_PREFAST_) + +#define DbgRaiseAssertionFailure() __int2c() + +#endif // !defined(_PREFAST_) + +#else // _MSC_FULL_VER >= 140030222 + +#pragma warning( push ) +#pragma warning( disable : 4793 ) + +#if !defined(_PREFAST_) + +__analysis_noreturn +FORCEINLINE +VOID +DbgRaiseAssertionFailure ( + VOID + ) + +{ + __asm int 0x2c +} + +#endif // !defined(_PREFAST_) + +#pragma warning( pop ) + +#endif // _MSC_FULL_VER >= 140030222 + +#endif // defined(_M_IX86) + +#elif defined(_IA64_) + +#if defined(_M_IA64) + +void +__break( + _In_ int StIIM + ); + +#pragma intrinsic (__break) + +#define BREAK_DEBUG_BASE 0x080000 +#define ASSERT_BREAKPOINT (BREAK_DEBUG_BASE+3) // Cause a STATUS_ASSERTION_FAILURE exception to be raised. + +#if !defined(_PREFAST_) + +#define DbgRaiseAssertionFailure() __break(ASSERT_BREAKPOINT) + +#endif // !defined(_PREFAST_) + +#endif // defined(_M_IA64) + +#elif defined(_ARM_) + +#if defined(_M_ARM) + +VOID +__emit( + const unsigned __int32 opcode + ); + +#pragma intrinsic(__emit) + +#if !defined(_PREFAST_) + +#define DbgRaiseAssertionFailure() __emit(0xdefc) // THUMB_ASSERT + +#endif // !defined(_PREFAST_) + +#endif // defined(_M_ARM) + +#endif // _AMD64_, _X86_, _IA64_, _ARM_ +#endif // !defined(_DBGRAISEASSERTIONFAILURE_) && !defined(RC_INVOKED) && !defined(MIDL_PASS) + +#ifdef __cplusplus +} +#endif + +// end_wdm end_winnt end_ntminiport + +// begin_wdm begin_ntminiport + +#if _MSC_VER >= 1300 +#if DBG + +#define NT_ASSERT(_exp) \ + ((!(_exp)) ? \ + (__annotation(L"Debug", L"AssertFail", L#_exp), \ + DbgRaiseAssertionFailure(), FALSE) : \ + TRUE) + +#define NT_ASSERTMSG(_msg, _exp) \ + ((!(_exp)) ? \ + (__annotation(L"Debug", L"AssertFail", L##_msg), \ + DbgRaiseAssertionFailure(), FALSE) : \ + TRUE) + +#define NT_ASSERTMSGW(_msg, _exp) \ + ((!(_exp)) ? \ + (__annotation(L"Debug", L"AssertFail", _msg), \ + DbgRaiseAssertionFailure(), FALSE) : \ + TRUE) + +#define NT_VERIFY NT_ASSERT +#define NT_VERIFYMSG NT_ASSERTMSG +#define NT_VERIFYMSGW NT_ASSERTMSGW + +#else // DBG + +#define NT_ASSERT(_exp) ((void) 0) +#define NT_ASSERTMSG(_msg, _exp) ((void) 0) +#define NT_ASSERTMSGW(_msg, _exp) ((void) 0) + +#define NT_VERIFY(_exp) ((_exp) ? TRUE : FALSE) +#define NT_VERIFYMSG(_msg, _exp ) ((_exp) ? TRUE : FALSE) +#define NT_VERIFYMSGW(_msg, _exp) ((_exp) ? TRUE : FALSE) + +#endif // DBG +#endif // _MSC_VER >= 1300 + +// end_wdm end_ntminiport + +#define WIN_ASSERT NT_ASSERT +#define WIN_ASSERTMSG NT_ASSERTMSG +#define WIN_ASSERTMSGW NT_ASSERTMSGW +#define WIN_VERIFY NT_VERIFY +#define WIN_VERIFYMSG NT_ASSERTMSG +#define WIN_VERIFYMSGW NT_ASSERTMSGW + diff --git a/lib/coreclr/src/inc/winrt/paraminstanceapi.h b/lib/coreclr/src/inc/winrt/paraminstanceapi.h new file mode 100644 index 0000000000..ad3fd17b91 --- /dev/null +++ b/lib/coreclr/src/inc/winrt/paraminstanceapi.h @@ -0,0 +1,1756 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*************************************************************** + +* +* Portions of this header fall under the following +* copyrights and/or licenses: +* +* rfc4122 and supporting functions +* * Algorithm from RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace +* * By Paul J. Leach, Michael Mealling and Rich Sals, July 2005. +* * +* * This function is adapted from the routines in the document +* * uuid_create_sha1_from_name and format_uuid_v3or5 +* * +* * +* * Copyright (c) 1990- 1993, 1996 Open Software Foundation, Inc. +* * Copyright (c) 1989 by Hewlett-Packard Company, Palo Alto, Ca. & +* * Digital Equipment Corporation, Maynard, Mass. +* * Copyright (c) 1998 Microsoft. +* * To anyone who acknowledges that this file is provided "AS IS" +* * without any express or implied warranty: permission to use, copy, +* * modify, and distribute this file for any purpose is hereby +* * granted without fee, provided that the above copyright notices and +* * this notice appears in all source code copies, and that none of +* * the names of Open Software Foundation, Inc., Hewlett-Packard +* * Company, Microsoft, or Digital Equipment Corporation be used in +* * advertising or publicity pertaining to distribution of the software +* * without specific, written prior permission. Neither Open Software +* * Foundation, Inc., Hewlett-Packard Company, Microsoft, nor Digital +* * Equipment Corporation makes any representations about the +* * suitability of this software for any purpose. +* * +*/ + +#ifdef _MSC_VER +#pragma once +#endif /* _MSC_VER */ + +#ifndef WINRT_PARAMINSTANCEAPI_H +#define WINRT_PARAMINSTANCEAPI_H + +#ifdef __cplusplus + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4180 ) // qualifier applied to function type has no meaning; ignored +#endif + +#include +#include +#include +#include +#include +#include +#include + +//#ifdef _MSC_VER +//#include +//#else +//#include +//#endif + +#ifndef WINRT_PARAMINSTANCE_NOCRYPT_SHA1 +#include +#endif + +#ifdef _MSC_VER +#pragma push_macro("CHKHR") +#pragma push_macro("CHKNT") +#endif + +namespace Ro { namespace detail { + + // + // Debugging aide. Set breakpoint on _FailedHR + // to see HRESULT propagation. + // + #ifdef DEBUG + inline HRESULT NOINLINE _FailedHR(HRESULT hr) { static HRESULT _hr = hr; return hr; } + #else + inline HRESULT _FailedHR(HRESULT hr) { return hr; } + #endif +}} + +#undef CHKHR +// +// Call HRESULT returning code and propagate any errors. +// Note: only use in code that is exception-safe / uses RAII. +// +#define CHKHR(expr) \ + { HRESULT _zzhr; \ + _zzhr = expr; \ + if (FAILED(_zzhr)) return Ro::detail::_FailedHR(_zzhr); } + +#undef CHKNT +// +// Call NTSTATUS returning code and propagate any errors, as HRESULTs. +// Note: +// - only use in code that is exception-safe / uses RAII / RRID. +// - HRESULT_FROM_NT does safely convert STATUS_SUCCESS into +// a SUCCEEDED hr. +// +#define CHKNT(expr) \ + CHKHR( HRESULT_FROM_NT( expr ) ) + +namespace Ro { namespace detail { + + // + // Runtime check for an invariant. This check executes in release builds. + // + + inline HRESULT Verify(bool invariant, HRESULT defaultHr = E_UNEXPECTED) + { + if (!invariant) + { + CHKHR(defaultHr); + } + return S_OK; + } +}} + + +extern "C" { + + +// sha1 adaptor +// create hash instance + +HRESULT _RoSha1Create( + __out void** handle); + + +// sha1 adaptor +// append more data to the input stream + +HRESULT _RoSha1AppendData( + __in void* handle, + __in size_t numBytes, + __in_bcount(numBytes) const void* data); + + +// sha1 adaptor +// return the first 16 bytes of SHA1 hash + +HRESULT _RoSha1Finish( + __in void* handle, + __out BYTE (*hashValue)[20]); + + +// sha1 adaptor +// free this instance + +void _RoSha1Release(__in void* handle); + +} + +struct IRoSimpleMetaDataBuilder; +struct IRoMetaDataLocator; + +// The 'detail' namespace includes implementation details that +// are subject to change without notice. +namespace Ro { namespace detail +{ + struct SimpleMetaDataBuffer; +}} + + +// +// Purpose: +// Given a parameterized type instance name and metadata, +// computes the IID for that instance. +// +// Parameters: +// +// nameElementCount +// number of elements in nameElements +// nameElements +// a parsed WinRt type name, as would be returned by RoParseTypeName. +// Eg: ["W.F.C.IVector`1", "N1.N2.IFoo"] +// metaDataLocator +// A callback to use for resolving metadata. +// +// An implementation could, for example, forward all calls +// to RoGetMetaData, then passing the results to +// RoWriteImporterToPushSimpleMetaData. As RoGetMetadata does +// not cache results, such an implementation would be inefficient. +// A better implementation will cache the results to RoGetMetaData, +// as appropriate. +// +// The Locator helper function can be used to wrap a lambda +// expression, or function pointer. eg: +// RoGetParameterizedTypeInstanceIID( +// ..., +// Locate([&](PCWSTR* name, IRoSimpleMetaDataBuilder& push){...}), +// ...); +// iid +// out param. Returns the iid for the parameterized type specified +// by nameElements +// extra +// out param. returns a handle that holds extra information about the +// IID result, for diagnostic purposes. If this handle is not desired, +// provide nullptr instead. +// +// Notes: +// - This function is stateless. IRoMetaDataLocator will not be preserved +// between calls. +// - This function does not perform deep semantic analysis. For instance, +// if IRoSimpleMetaDataBuilder specifies that a struct contains an interface pointer, +// this API will return success, even though such metadata is semantically +// invalid. The value of the IID returned is unspecified in such cases. +// - This function does introduce reentrancy. Its implementation +// of IRoSimpleMetaDataBuilder may make reentrant calls to IRoMetaDataLocator. +// - If a call to IRoSimpleMetaDataBuilder fails, this function will return that +// failure code. +// + + +DECLARE_HANDLE(ROPARAMIIDHANDLE); + +inline HRESULT RoGetParameterizedTypeInstanceIID( + UINT32 nameElementCount, + __in_ecount(nameElementCount) PCWSTR* nameElements, + __in const IRoMetaDataLocator& metaDataLocator, + __out GUID* iid, + __deref_opt_out ROPARAMIIDHANDLE* pExtra = nullptr); + +// Frees the 'extra' handle allocated +// by RoGetParameterizedTypeInstanceIID +inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra); + +// Fetches the TypeSignature used to compute the IID by the last +// call to RoGetParameterizedTypeInstanceIID on this extra handle. +// The string contains ASCII code only, and the string is valid +// until RoFreeParameterizedTypeExtra is called on the extra pointer. +inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extra); + +namespace Ro { namespace detail +{ + + // private type used in helper function + + template + struct _Locator; +}} // namespace Ro::detail + +namespace Ro +{ + + // helper function to create IRoMetaDataLocator from lambda expression + + template + Ro::detail::_Locator Locator(const Fn& fn); +} // namespace Ro + + +// +// Purpose: +// Destination for IRoMetaDataLocator::Locate to write parsed metadata to. +// 'Locate' should set the appropriate Windows Runtime metadata information gleaned +// from Windows Runtime metadata file, or other appropriate source. +// +// Notes: +// - Methods for base types and COM interfaces (eg, Int32 and IInspectable +// respectively) are not needed -- RoGetParameterizedTypeInstanceIID already +// knows the WinRT base type names, so will not invoke IMetDataLocator +// to discover them. +// - This is not a COM interface. It does not derive from IUnknown. +// + +struct IRoSimpleMetaDataBuilder +{ + + // Notes: + // IInspectable and other non-WinRT interfaces are not permissible. + // Not for use with parameterized type instances. See SetParameterizedInterface + + STDMETHOD(SetWinRtInterface)( + GUID iid) = 0; + + + // Notes: + // Not for use with parameterized type instances. See SetParameterizedDelegate + + STDMETHOD(SetDelegate)( + GUID iid) = 0; + + + // Notes: + // Call this method when an interface group has a default interface + // that is a non-parametric type. + + STDMETHOD(SetInterfaceGroupSimpleDefault)( + PCWSTR name, + PCWSTR defaultInterfaceName, + __in_opt const GUID* defaultInterfaceIID) = 0; + + + // Notes: + // Call this method when an interface group has a parameterized + // interface as its default interface. + + STDMETHOD(SetInterfaceGroupParameterizedDefault)( + PCWSTR name, + UINT32 elementCount, + __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) = 0; + + STDMETHOD(SetRuntimeClassSimpleDefault)( + PCWSTR name, + PCWSTR defaultInterfaceName, + __in_opt const GUID* defaultInterfaceIID) = 0; + + STDMETHOD(SetRuntimeClassParameterizedDefault)( + PCWSTR name, + UINT32 elementCount, + __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) = 0; + + STDMETHOD(SetStruct)( + PCWSTR name, + UINT32 numFields, + __in_ecount(numFields) PCWSTR* fieldTypeNames) = 0; + + STDMETHOD(SetEnum)( + PCWSTR name, + PCWSTR baseType) = 0; + + + // Notes: + // This is only for the 'non-instantiated' parameterized interface itself - + // instances are handled by RoGetParameterizedTypeInstanceIID, and the + // caller need not parse them. + + STDMETHOD(SetParameterizedInterface)( + GUID piid, + UINT32 numArgs) = 0; + + STDMETHOD(SetParameterizedDelegate)( + GUID piid, + UINT32 numArgs) = 0; +}; + + +// +// Purpose: +// Callback for resolving metadata. +// + +struct IRoMetaDataLocator +{ + + // + // Parameters: + // nameElement + // a metadata typeref name to resolve. + // Eg: "N1.N2.IFoo", or "W.F.C.IVector`1". + // pushMetaData + // data sink for providing information about the + // type information for nameElement + // + + STDMETHOD(Locate)( + PCWSTR nameElement, + __in IRoSimpleMetaDataBuilder& metaDataDestination + ) const = 0; +}; + +namespace Ro { namespace detail { + + + // + // helper function, moves range of elements + // + + template + void _VecMoveRange( + __in_ecount(size) T* dst, + __in_ecount(size) T* src, + size_t size) + { + for (size_t i = 0; i != size; ++i) + { + dst[i] = static_cast(src[i]); + } + } + + // + // specializations to move strings more efficiently + // + + inline void _VecMoveRange( + __in_ecount(size) char* dst, + __in_ecount(size) char* src, + size_t size) + { + errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst)); + NT_ASSERT(!err); + (void)err; + } + inline void _VecMoveRange( + __in_ecount(size) wchar_t* dst, + __in_ecount(size) wchar_t* src, + size_t size) + { + errno_t err = memcpy_s(dst, size*sizeof(*dst), src, size*sizeof(*dst)); + NT_ASSERT(!err); + (void)err; + } + + + // + // helper function, moves range of elements + // + + template + void _VecCopyRange( + __in_ecount(size) T* dst, + __in_ecount(size) const T* src, + size_t size) + { + for (size_t i = 0; i != size; ++i) + { + dst[i] = src[i]; + } + } + + // + // specializations to move strings more efficiently + // + + inline void _VecCopyRange( + __in_ecount(size) char* dst, + __in_ecount(size) const char* src, + size_t size) + { + errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast(src), size*sizeof(*dst)); + NT_ASSERT(!err); + (void)err; + } + inline void _VecCopyRange( + __in_ecount(size) wchar_t* dst, + __in_ecount(size) const wchar_t* src, + size_t size) + { + errno_t err = memcpy_s(dst, size*sizeof(*dst), const_cast(src), size*sizeof(*dst)); + NT_ASSERT(!err); + (void)err; + } + + // + // Single-owner smart pointer for arrays + // + + template + struct ArrayHolder + { + ArrayHolder() : _value(NULL) + { + } + T* Value() const + { + return _value; + } + T*& Value() + { + return _value; + } + T* Detach() + { + T* tmp = _value; + _value = NULL; + return tmp; + } + ~ArrayHolder() + { + delete[] _value; + } + + private: + T* _value; + }; + + // + // Single-owner smart pointer for object pointer + // + + template + struct ElementHolder + { + ElementHolder() : _value(NULL) + { + } + T* operator->() const + { + return _value; + } + T* Value() const + { + return _value; + } + T*& Value() + { + return _value; + } + T* Detach() + { + T* tmp = _value; + _value = NULL; + return tmp; + } + ~ElementHolder() + { + delete _value; + } + + private: + T* _value; + }; + + + + // + // simple vector, with small vector optimization + // T - must be default constructable and movable. + // const input overload of AppendN requires copyable. + // FixedBufSize - number of bytes to use for small array + // optimization, to avoid heap allocation in case of + // small vectors. Defaults to at least one element, + // otherwise the largest value such that <= 64 bytes + // are used. + // + + template < + typename T, + size_t FixedBufSize = 0 + > + class Vec + { + private: + static const size_t _fixedBufSize = + FixedBufSize/sizeof(T) + ? FixedBufSize/sizeof(T) + : (((64/sizeof(T)) > 0) ? (64/sizeof(T)) + : 1); + public: + Vec() : + _size(0), + _cap(_countof(_fixedBuf)), + _buf(_fixedBuf) + { + } + + + // Appends an element, or a default value if one + // it not specified. If called with an rvalue, + // it uses move assignment instead of copy. + + HRESULT Append(T value = T()) + { + if (_cap - _size < 1) + { + CHKHR(_Grow()); + } + _buf[_size] = static_cast(value); + ++_size; + + return S_OK; + } + + // Moves elements (move assignment) into array. + + HRESULT MoveN(__in_ecount(n) T* values, size_t n) + { + if (_cap - _size < n) + { + CHKHR(_Grow(n - (_cap - _size))); + } + _VecMoveRange(_buf + _size, values, n); + _size += n; + + return S_OK; + } + + + // Appends elements. Does not invoke move assignment. + + HRESULT AppendN(__in_ecount(n) const T* values, size_t n) + { + if (_cap - _size < n) + { + CHKHR(_Grow(n - (_cap - _size))); + } + _VecCopyRange(_buf + _size, values, n); + _size += n; + + return S_OK; + } + + HRESULT Pop() + { + CHKHR(Verify( _size > 0 )); + --_size; + return S_OK; + } + + HRESULT Resize(size_t newSize) + { + if (_cap < newSize) + { + CHKHR(_Grow(newSize - _cap)); + } + _size = newSize; + return S_OK; + } + + size_t Size() const + { + return _size; + } + + T& operator[](size_t index) + { + NT_ASSERT(index < _size); + return _buf[index]; + } + + T& Last() + { + return (*this)[_size-1]; + } + + ~Vec() + { + if (_buf != _fixedBuf) + { + delete[] _buf; + } + } + + private: + + // + // growth factor (does not check for overflow) -- returns amount to grow by + // + + static size_t _GrowthIncrement(size_t n) + { + return n / 2; + } + + HRESULT _Grow(size_t byAtLeast = 4) + { + size_t increase = _GrowthIncrement(_cap); + if (increase < byAtLeast) + { + increase = byAtLeast; + } + size_t newCap = _cap + increase; + if (newCap <= _cap) + { + CHKHR(E_OUTOFMEMORY); + } + ArrayHolder newBuf; + + void* p = (newBuf.Value() = new (std::nothrow) T[newCap]); + if (!p) + { + CHKHR(E_OUTOFMEMORY); + } + + _VecMoveRange( newBuf.Value(), _buf, _size ); + + if (_buf != _fixedBuf) + { + delete _buf; + } + _buf = newBuf.Detach(); + _cap = newCap; + + return S_OK; + } + + size_t _size; + size_t _cap; + T* _buf; + T _fixedBuf[_fixedBufSize]; + }; + + struct SimpleMetaDataBuilder : IRoSimpleMetaDataBuilder + { + public: + SimpleMetaDataBuilder(SimpleMetaDataBuffer& buffer, const IRoMetaDataLocator& locator) + : _buffer(&buffer), _locator(&locator), _invoked(false) + { + } + IFACEMETHOD(SetWinRtInterface)(GUID iid); + IFACEMETHOD(SetDelegate)(GUID iid); + IFACEMETHOD(SetInterfaceGroupSimpleDefault)(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID); + IFACEMETHOD(SetInterfaceGroupParameterizedDefault)(PCWSTR name, UINT32 elementCount, __in_ecount(elementCount) PCWSTR *defaultInterfaceNameElements); + IFACEMETHOD(SetRuntimeClassSimpleDefault)(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID); + IFACEMETHOD(SetRuntimeClassParameterizedDefault)(PCWSTR name, UINT32 elementCount, __in_ecount(elementCount) PCWSTR *defaultInterfaceNameElements); + IFACEMETHOD(SetStruct)(PCWSTR name, UINT32 numFields, __in_ecount(numFields) PCWSTR *fieldTypeNames); + IFACEMETHOD(SetEnum)(PCWSTR name, PCWSTR baseType); + IFACEMETHOD(SetParameterizedInterface)(GUID piid, UINT32 numArgs); + IFACEMETHOD(SetParameterizedDelegate)(GUID piid, UINT32 numArgs); + + + // Runs the locating process for a parameterized type. + // Notes: + // _buffer->_nestingLevel is used to determine the number of + // arguments left to consume for nested parameterized types. + + HRESULT SendArguments(UINT32 nameElementCount, __in_ecount(nameElementCount) PCWSTR *nameElements); + + private: + + + // Writes the type signature for the type 'name' + // Notes: + // - If a builtin type, writes the type directly. + // - Otherwise, uses the IRoMetaDataLocator to + // write the type signature into _buffer + // - As the sole function to call + // IRoMetaDataLocator, it also performs the check + // on recursion depth bounds. + + HRESULT _WriteType(PCWSTR name); + + + // The tail portion of IG and RC formats is the same. This + // function implements the shared portion of that format. + + HRESULT _CommonInterfaceGroupSimple(PCWSTR name, PCWSTR defaultInterfaceName, __in_opt const GUID *defaultInterfaceIID); + + + // Called at the beginning of every 'Set' method. Set must only be called once. + + HRESULT _OnSet(); + + + // Called at the end of every 'Set' method, only if successful. + + void _Completed(); + + static char _AsciiLower(char ch) + { + if ('A' <= ch && ch <= 'Z') + { + return ch + ('a' - 'A'); + } + else + { + return ch; + } + } + + + // Writes a guid into the type signature being built, in lower case. + + HRESULT _WriteGuid(const GUID& iid); + HRESULT _WriteString(PCSTR str); + HRESULT _WriteChar(char c); + HRESULT _WriteWideString(PCWSTR str); + + SimpleMetaDataBuilder(); + SimpleMetaDataBuilder(const SimpleMetaDataBuilder&); + void operator=(const SimpleMetaDataBuilder&); + + SimpleMetaDataBuffer* _buffer; + const IRoMetaDataLocator* _locator; + bool _invoked; + }; + + + // If the type string describes a built-in type, modifies + // this instance to use builtin type table entry instead of name. + + inline bool _IsBuiltin(__in PCWSTR name, __out PCSTR * typeSignature) + { + *typeSignature = nullptr; + + struct BuiltinEntry { PCWSTR name; PCSTR typeSignature; }; + static const BuiltinEntry entries[] = { + + { L"UInt8", "u1" }, + { L"Int16", "i2" }, + { L"UInt16", "u2" }, + { L"Int32", "i4" }, + { L"UInt32", "u4" }, + { L"Int64", "i8" }, + { L"UInt64", "u8" }, + { L"Single", "f4" }, + { L"Double", "f8" }, + { L"Boolean", "b1" }, + { L"Char16", "c2" }, + { L"String", "string" }, + { L"Guid", "g16" }, + { L"Object", "cinterface(IInspectable)" }, + }; + for (const BuiltinEntry* tip = entries; + tip != &entries[_countof(entries)]; + ++tip) + { + if (wcscmp(tip->name, name) == 0) + { + *typeSignature = tip->typeSignature; + return true; + } + } + + // if not found, assume is a normal type name + + return false; + } + + + // Linked list (stack allocated) of type resolution calls, + // used to detect if an InterfaceGroup/RuntimeClass type + // signature depends on itself. In that case, we use "*" + // in the type signature instead of recurring further. + + struct ResolutionPathEntry + { + ResolutionPathEntry* _next; + PCWSTR _typeName; + + ResolutionPathEntry(PCWSTR typeName) + : _next(nullptr) + , _typeName(typeName) + { + } + }; + + inline void Push(ResolutionPathEntry*& top, ResolutionPathEntry* item) + { + item->_next = top; + top = item; + } + inline HRESULT Pop(ResolutionPathEntry*& top) + { + if (!top) + { + return E_UNEXPECTED; + } + top = top->_next; + return S_OK; + } + + + // Holds metadata state that is shared between RoGetParamInstanceIID and SimpleMetaDataBuilder + + struct SimpleMetaDataBuffer + { + SimpleMetaDataBuffer() + { + Clear(); + } + + // reset all tables + void Clear() + { + _recursionDepth = 0; + _topLevelTypes = 0; + _resolutionPath = nullptr; + _outputStream.Resize(0); + } + + static const size_t _maxTypeName = 256; + + + // Estimate of 'reasonable' level of Interface Group / Runtime + // Class / Parameterized Type nesting. + + static const size_t _maxRecursionDepth = 64; + + Vec _outputStream; + ResolutionPathEntry* _resolutionPath; + + + // RAII object, places an item on the resolution path, and pops it on destruction + + class ResolutionPathGuard + { + private: + ResolutionPathEntry _entry; + SimpleMetaDataBuffer* _buffer; + + public: + ResolutionPathGuard(PCWSTR typeName, SimpleMetaDataBuffer* buffer) + : _buffer(buffer) + , _entry(typeName) + { + Push(buffer->_resolutionPath, &_entry); + } + ~ResolutionPathGuard() + { + HRESULT hr = Pop(_buffer->_resolutionPath); + NT_ASSERT(SUCCEEDED(hr)); + (void)hr; + } + }; + + + // Searches the resolution path for 'name' returning true if exists + + bool ExistsCycle(PCWSTR typeName) + { + for (auto pTip = _resolutionPath; pTip; pTip = pTip->_next) + { + if (wcscmp(typeName, pTip->_typeName) == 0) + { + return true; + } + } + return false; + } + + + // Indicates the nesting level of compound types, used + // to properly balance parenthesis on parameterized types, + // and used to bound recursion depth. + // + // - Pinterfaces + // : push 'numArgs' on to _nestingLevel + // - A compound type that doesn't know number of arguments + // eg, RoGetParameterizedInstanceIID arguments, or + // SetIG..Parameterized + // : will 0) note nesting level + // 1) iterate calling Locate on the compound arguments. + // 2) the above should cause exactly one push of _nestingLevel + // 3) reduce nesting level back to original nesting level, + // inserting the difference in closing parens + // - Compound types that do know number of arguments (eg SetStruct) + // : will 1) increase nesting level by 1 + // 2) iterate calling Locate on arguments + // 3) decrease nesting level again + // + // + + Vec _nestedArgs; + + // topLevelTypes should be incremented once, by the initial + // parameterized type, then never again. + + size_t _topLevelTypes; + size_t _recursionDepth; + }; +}} // namespace Ro::detail + +namespace Ro { namespace detail +{ + template + struct _Locator : IRoMetaDataLocator + { + Fn _fn; + + _Locator(const Fn& fn) + : _fn(fn) + { + } + + IFACEMETHOD(Locate)( + PCWSTR name, + IRoSimpleMetaDataBuilder& pushMetaData) const + { + return _fn(name, pushMetaData); + } + }; +}} // namespace Ro::detail + +namespace Ro +{ + template + Ro::detail::_Locator Locator(const Fn& fn) + { + return Ro::detail::_Locator(fn); + } +} + +namespace Ro { namespace detail +{ + + // Figure out if we're compiling for a big- or little-endian machine. + + inline bool BigEndian() + { + unsigned long n = 0xff000000L; + + return 0 != *reinterpret_cast(&n); + } + + + // HostToNetworkLong converts a 32-bit long to network byte order + + inline ULONG HostToNetworkLong(ULONG hostlong) + { + if (BigEndian()) + return hostlong; + else + return ( (hostlong >> 24) & 0x000000FFL) | + ( (hostlong >> 8) & 0x0000FF00L) | + ( (hostlong << 8) & 0x00FF0000L) | + ( (hostlong << 24) & 0xFF000000L); + } + + + // HostToNetworkLong converts a 16-bit short to network byte order + + inline USHORT HostToNetworkShort(USHORT hostshort) + { + if (BigEndian()) + return hostshort; + else + return ((hostshort >> 8) & 0x00FF) | ((hostshort << 8) & 0xFF00); + } + + + // NetworkToHostLong converts a 32-bit long to local host byte order + + inline ULONG NetworkToHostLong(ULONG netlong) + { + if (BigEndian()) + return netlong; + else + return ( (netlong >> 24) & 0x000000FFL) | + ( (netlong >> 8) & 0x0000FF00L) | + ( (netlong << 8) & 0x00FF0000L) | + ( (netlong << 24) & 0xFF000000L); + } + + + // NetworkToHostShort converts a 16-bit short to local host byte order + + inline USHORT NetworkToHostShort(USHORT netshort) + { + if (BigEndian()) + return netshort; + else + return ((netshort >> 8) & 0x00FF) | ((netshort << 8) & 0xFF00); + } + + + // smart pointer for Sha1 handle + + struct Sha1Holder + { + Sha1Holder() : _handle(nullptr) + { + } + void*& Value() + { + return _handle; + } + ~Sha1Holder() + { + if (_handle) + { + _RoSha1Release(_handle); + } + } + private: + void* _handle; + }; + + + + // + // Computes the rfc4122 v5 UUID from GUID,name pair. + // + // Notes: + // - see copyright at beginning of file. + // + + inline HRESULT + GuidFromName( + __in const GUID& guidNamespace, + __in_bcount(dwcbSize) const void* pbName, + __in DWORD dwcbSize, + __out GUID* pGuid) + { + Sha1Holder sha1; + + CHKHR( _RoSha1Create(&sha1.Value()) ); + { + GUID networkOrderGuidNamespace = guidNamespace; + + // Put name space ID in network byte order so it hashes the same + // no matter what endian machine we're on + + if (!BigEndian()) + { + networkOrderGuidNamespace.Data1 = HostToNetworkLong (networkOrderGuidNamespace.Data1); + networkOrderGuidNamespace.Data2 = HostToNetworkShort(networkOrderGuidNamespace.Data2); + networkOrderGuidNamespace.Data3 = HostToNetworkShort(networkOrderGuidNamespace.Data3); + } + CHKHR( _RoSha1AppendData(sha1.Value(), sizeof(networkOrderGuidNamespace), reinterpret_cast(&networkOrderGuidNamespace)) ); + } + CHKHR( _RoSha1AppendData(sha1.Value(), dwcbSize, pbName) ); + + { + BYTE sha1Result[20]; + CHKHR( _RoSha1Finish(sha1.Value(), &sha1Result) ); + + errno_t err = memcpy_s(pGuid, sizeof(GUID), &sha1Result[0], sizeof(GUID)); + CHKHR(Verify( 0 == err )); + + + // Restore the byte order + + if (!BigEndian()) + { + pGuid->Data1 = NetworkToHostLong (pGuid->Data1); + pGuid->Data2 = NetworkToHostShort(pGuid->Data2); + pGuid->Data3 = NetworkToHostShort(pGuid->Data3); + } + + + // set version number + // 1: clear version number nibble + // 2: set version 5 = name-based SHA1 + + pGuid->Data3 &= 0x0FFF; + pGuid->Data3 |= (5 << 12); + + + // set variant field by clearing variant bits. + + pGuid->Data4[0] &= 0x3F; + pGuid->Data4[0] |= 0x80; + } + return S_OK; + } +}} // namespace Ro::detail + +inline HRESULT RoGetParameterizedTypeInstanceIID( + UINT32 nameElementCount, + __in_ecount(nameElementCount) PCWSTR* nameElements, + __in const IRoMetaDataLocator& metaDataLocator, + __out GUID* iid, + __deref_opt_out ROPARAMIIDHANDLE* pExtra) +{ + using namespace Ro::detail; + memset(iid, 0, sizeof(*iid)); + + SimpleMetaDataBuffer reserveBuffer; + SimpleMetaDataBuffer *pBuffer = &reserveBuffer; + + // if user wishes to hold on to the result value, + // dynamically allocate this buffer. + if (pExtra) + { + pBuffer = new (std::nothrow) SimpleMetaDataBuffer; + *pExtra = static_cast(static_cast(pBuffer)); + } + SimpleMetaDataBuffer& buffer = *pBuffer; + SimpleMetaDataBuilder builder(*pBuffer, metaDataLocator); + + // send initial arguments + CHKHR(builder.SendArguments(nameElementCount, nameElements)); + + // verify that precisely one type was resolved, to completion. + CHKHR(Verify(buffer._topLevelTypes == 1 + && buffer._nestedArgs.Size() == 0, + E_INVALIDARG)); + + // compute type signature hash + static const GUID guidPinterfaceNamespace + = { 0x11f47ad5, 0x7b73, 0x42c0, { 0xab, 0xae, 0x87, 0x8b, 0x1e, 0x16, 0xad, 0xee }}; + + CHKHR(Ro::detail::Verify( buffer._outputStream.Size() <= DWORD(-1) )); + + // null terminate + CHKHR( buffer._outputStream.Append('\0') ); + + + // + // Unit test logging, to verify proper signatures + // + #ifdef UNITTEST_TRACE + { + CHKHR( UNITTEST_TRACE("type signature", &buffer._outputStream[0]) ); + } + #endif + + + CHKHR( GuidFromName(guidPinterfaceNamespace, + &buffer._outputStream[0], + DWORD(buffer._outputStream.Size() - 1), // does not include terminator + iid) ); + return S_OK; +} + +inline void RoFreeParameterizedTypeExtra(__in ROPARAMIIDHANDLE extra) +{ + using namespace Ro::detail; + delete static_cast(static_cast(extra)); +} +inline PCSTR RoParameterizedTypeExtraGetTypeSignature(__in ROPARAMIIDHANDLE extra) +{ + using namespace Ro::detail; + SimpleMetaDataBuffer* pBuffer = static_cast(static_cast(extra)); + + return &pBuffer->_outputStream[0]; +} + +namespace Ro { namespace detail +{ + + inline HRESULT SimpleMetaDataBuilder::_WriteType(PCWSTR name) + { + PCSTR builtInName = nullptr; + SimpleMetaDataBuilder builder(*_buffer, *_locator); + + if (_IsBuiltin(name, &builtInName)) + { + CHKHR(builder._OnSet()); + CHKHR(builder._WriteString(builtInName)); + builder._Completed(); + } + else + { + size_t newDepth = ++_buffer->_recursionDepth; + size_t pinterfaceNesting = _buffer->_nestedArgs.Size(); + if (newDepth + pinterfaceNesting > _buffer->_maxRecursionDepth) + { + + // Terminate recursion; bounds call stack consumption + + CHKHR(E_UNEXPECTED); + } + CHKHR(_locator->Locate(name, builder)); + + // Note, buffers aren't reusable, so it's fine that we don't + // unwind this value on return. Also note, we do not unwind + // this value if the user provides inconsistent data either + // (eg, if they provide only 1 argument to a 2 parameter + // parameterized type). + + --_buffer->_recursionDepth; + } + return S_OK; + } + + inline HRESULT SimpleMetaDataBuilder::_OnSet() + { + if (_invoked) + { + CHKHR(E_INVALIDARG); + } + _invoked = true; + + + // Reduce the number of arguments left for this compound type. + + if(_buffer->_nestedArgs.Size() > 0) + { + --(_buffer->_nestedArgs.Last()); + } + else + { + + // Increase number of top level types in signature + // string. (should never exceed one) + + ++_buffer->_topLevelTypes; + } + + return S_OK; + } + + inline void SimpleMetaDataBuilder::_Completed() + { + } + inline HRESULT SimpleMetaDataBuilder::SendArguments(UINT32 nameElementCount, __in_ecount(nameElementCount) PCWSTR *nameElements) + { + CHKHR(Verify(nameElementCount > 0)); + + CHKHR(Verify(_buffer->_nestedArgs.Size() <= UINT32(-1))); + UINT32 previousLevel = UINT32(_buffer->_nestedArgs.Size()); + + for (UINT32 i = 0; i < nameElementCount; ++i) + { + CHKHR(_WriteType(nameElements[i])); + + + // Close any nested parameterized types that are complete + + while (_buffer->_nestedArgs.Size() > previousLevel + && _buffer->_nestedArgs.Last() == 0) + { + CHKHR(_buffer->_nestedArgs.Pop()); + CHKHR(_WriteChar(')')); + } + + // insert separator between parameterized type arguments + + CHKHR(_WriteChar(';')); + } + + // remove final separator + + CHKHR(_buffer->_outputStream.Pop()); + + + // Verify that all the arguments were consumed. + + CHKHR(Verify(_buffer->_nestedArgs.Size() == previousLevel, + E_INVALIDARG)); + return S_OK; + } + + inline HRESULT SimpleMetaDataBuilder::_WriteGuid(const GUID& iid) + { + static const size_t guidStringLength = _countof("{11223344-1122-1122-1122-334455667788}") - 1; + WCHAR tmpString[guidStringLength+1]; + + int numWritten = StringFromGUID2(iid, tmpString, guidStringLength + 1); + CHKHR(Verify( numWritten == guidStringLength + 1 )); + NT_ASSERT( numWritten == guidStringLength + 1 ); + + size_t offset = _buffer->_outputStream.Size(); + CHKHR(Verify( offset + guidStringLength > offset )) + CHKHR( _buffer->_outputStream.Resize(offset + guidStringLength) ); + char* writePtr = &_buffer->_outputStream[offset]; + + + // All characters are ascii. Just truncate. + + for(size_t i = 0; i < guidStringLength; ++i) + { + writePtr[i] = _AsciiLower(char(tmpString[i])); + } + return S_OK; + } + inline HRESULT SimpleMetaDataBuilder::_WriteString(PCSTR str) + { + CHKHR( _buffer->_outputStream.AppendN(str, strlen(str)) ); + return S_OK; + } + inline HRESULT SimpleMetaDataBuilder::_WriteChar(char c) + { + CHKHR( _buffer->_outputStream.Append(c) ); + return S_OK; + } + inline HRESULT SimpleMetaDataBuilder::_WriteWideString(PCWSTR str) + { + size_t len = wcslen(str); + size_t offset = _buffer->_outputStream.Size(); + int written; + + + // provision enough space for conversion to take place + + size_t provision = len + 1; + for(;;) + { + CHKHR( _buffer->_outputStream.Resize(offset+provision)); + char* writePtr = &_buffer->_outputStream[offset]; + + CHKHR(Verify(len <= INT_MAX)); + CHKHR(Verify(provision <= INT_MAX)); + + written = WideCharToMultiByte( + CP_UTF8, + 0, + str, + int(len), + writePtr, + int(provision), + nullptr, + nullptr + ); + + if (written > 0) + { + break; + } + else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + CHKHR(HRESULT_FROM_WIN32(GetLastError())); + } + else + { + provision *= 2; + CHKHR(Verify( offset + provision > offset )); + } + } + + // reduce size to reflect number of characters actually written. + // Note that since we specified string length, no null terminator + // was injected, so we don't have to remove it. + + CHKHR( _buffer->_outputStream.Resize(offset+written) ); + + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetWinRtInterface( + GUID iid) + { + CHKHR(_OnSet()); + + CHKHR(_WriteGuid(iid)); + + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetDelegate( + GUID iid) + { + CHKHR(_OnSet()); + + CHKHR(_WriteString("delegate(")); + CHKHR(_WriteGuid(iid)); + CHKHR(_WriteChar(')')); + + _Completed(); + return S_OK; + } + + inline HRESULT SimpleMetaDataBuilder::_CommonInterfaceGroupSimple( + PCWSTR name, + PCWSTR defaultInterfaceName, + __in_opt const GUID * defaultInterfaceIID) + { + CHKHR(_WriteWideString(name)); + CHKHR(_WriteChar(';')); + + + // InterfaceGroups and RuntimeClasses take one nested argument + + CHKHR(_buffer->_nestedArgs.Append(1)); + if (!defaultInterfaceIID) + { + CHKHR(_WriteType(defaultInterfaceName)); + } + else + { + + // complete the type signature immediately; no nested + // call needed to resolve the interface. + + SimpleMetaDataBuilder builder(*_buffer, *_locator); + CHKHR(builder.SetWinRtInterface(*defaultInterfaceIID)) + } + CHKHR(_WriteChar(')')); + CHKHR(_buffer->_nestedArgs.Pop()); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupSimpleDefault( + PCWSTR name, + PCWSTR defaultInterfaceName, + __in_opt const GUID* defaultInterfaceIID) + { + CHKHR(_OnSet()); + + CHKHR(_WriteString("ig(")); + CHKHR(_CommonInterfaceGroupSimple(name, defaultInterfaceName, defaultInterfaceIID)); + + _Completed(); + return S_OK; + } + + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetInterfaceGroupParameterizedDefault( + PCWSTR name, + UINT32 elementCount, + __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) + { + CHKHR(_OnSet()); + + + // If an interface group or runtime class has a compound type as its default, and that + // type directly or indirectly refers to itself, the second occurrence instead used '*' + // to signal that the default interface has already been specified earlier up the call + // stack. This prevents unbounded recursion. + + if (_buffer->ExistsCycle(name)) + { + CHKHR( _WriteString("ig(") ); + CHKHR( _WriteWideString(name) ); + CHKHR( _WriteString(";*)") ); + } + else + { + SimpleMetaDataBuffer::ResolutionPathGuard guard(name, _buffer); + + CHKHR( _WriteString("ig(") ); + CHKHR( _WriteWideString(name) ); + CHKHR( _WriteChar(';') ); + + + // InterfaceGroups and RuntimeClasses take one nested argument + + CHKHR( _buffer->_nestedArgs.Append(1) ); + CHKHR( SendArguments(elementCount, defaultInterfaceNameElements) ); + CHKHR( _buffer->_nestedArgs.Pop() ); + CHKHR( _WriteChar(')') );; + + } + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassSimpleDefault( + PCWSTR name, + PCWSTR defaultInterfaceName, + __in_opt const GUID* defaultInterfaceIID) + { + CHKHR(_OnSet()); + + CHKHR(_WriteString("rc(")); + CHKHR(_CommonInterfaceGroupSimple(name, defaultInterfaceName, defaultInterfaceIID)); + + _Completed(); + return S_OK; + } + + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetRuntimeClassParameterizedDefault( + PCWSTR name, + UINT32 elementCount, + __in_ecount(elementCount) PCWSTR* defaultInterfaceNameElements) + { + CHKHR(_OnSet()); + + if (_buffer->ExistsCycle(name)) + { + CHKHR(_WriteString("rc(")); + CHKHR(_WriteWideString(name)); + CHKHR(_WriteString(";*)")); + } + else + { + SimpleMetaDataBuffer::ResolutionPathGuard guard(name, _buffer); + + CHKHR(_WriteString("rc(")); + CHKHR(_WriteWideString(name)); + CHKHR(_WriteChar(';')); + + + // InterfaceGroups and RuntimeClasses take one nested argument + + CHKHR(_buffer->_nestedArgs.Append(1)); + CHKHR(SendArguments(elementCount, defaultInterfaceNameElements)); + CHKHR(_buffer->_nestedArgs.Pop()); + + CHKHR(_WriteChar(')')); + } + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetStruct( + PCWSTR name, + UINT32 numFields, + __in_ecount(numFields) PCWSTR* fieldTypeNames) + { + CHKHR(_OnSet()); + CHKHR(_WriteString("struct(")); + CHKHR(_WriteWideString(name)); + CHKHR(_WriteChar(';')); + + CHKHR(_buffer->_nestedArgs.Append(1)); + CHKHR(SendArguments(numFields, fieldTypeNames)); + CHKHR(_buffer->_nestedArgs.Pop()); + + CHKHR(_WriteChar(')')); + + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetEnum( + PCWSTR name, + PCWSTR baseType) + { + CHKHR(_OnSet()); + + CHKHR(_WriteString("enum(")); + CHKHR(_WriteWideString(name)); + CHKHR(_WriteChar(';')); + CHKHR(_buffer->_nestedArgs.Append(1)); + CHKHR(_WriteType(baseType)); + CHKHR(_buffer->_nestedArgs.Pop()); + CHKHR(_WriteChar(')')); + + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedInterface( + GUID piid, + UINT32 numArgs) + { + CHKHR(_OnSet()); + + CHKHR(_WriteString("pinterface(")); + CHKHR(_WriteGuid(piid)); + + + // Note the number of arguments. The SendArguments + // function will append the ')' after that number of + // arguments are consumed. + + CHKHR(_buffer->_nestedArgs.Append(numArgs)); + + _Completed(); + return S_OK; + } + + inline __override HRESULT STDMETHODCALLTYPE SimpleMetaDataBuilder::SetParameterizedDelegate( + GUID piid, + UINT32 numArgs) + { + + // Parameterized interfaces and parameterized delegates use the same signature scheme. + + return SetParameterizedInterface(piid, numArgs); + } + +}} // namespace Ro::detail + +#ifndef WINRT_PARAMINSTANCE_NOCRYPT_SHA1 + +namespace Ro { namespace detail { + + class Sha1 + { + public: + Sha1() + : _hAlg(nullptr) + , _hHash(nullptr) + { + } + + HRESULT Initialize() + { + DWORD dwcb; + DWORD dwcbResult; + +#ifdef _PREFAST_ +#pragma warning(push) +#pragma warning(disable: 33098) // "Banned hash algorithm is used" - SHA-1 is required for compatibility +#endif // _PREFAST_ + CHKNT(BCryptOpenAlgorithmProvider(&_hAlg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0)); +#ifdef _PREFAST_ +#pragma warning(pop) +#endif // _PREFAST_ + + CHKNT(BCryptGetProperty(_hAlg, BCRYPT_OBJECT_LENGTH, reinterpret_cast(&dwcb), sizeof(dwcb), &dwcbResult, 0)); + + _ahBuf.Value() = new (std::nothrow) BYTE[dwcb]; + if (nullptr == _ahBuf.Value()) + { + CHKHR( E_OUTOFMEMORY ); + } + + CHKNT(BCryptCreateHash(_hAlg, &_hHash, _ahBuf.Value(), dwcb, NULL, 0, 0)); + return S_OK; + } + HRESULT AppendData(size_t numBytes, __in_bcount(numBytes) const void* bytes) + { + CHKHR(Verify(numBytes <= DWORD(-1))); + CHKNT(BCryptHashData(_hHash, reinterpret_cast(const_cast(bytes)), DWORD(numBytes), 0)); + return S_OK;; + } + HRESULT GetResult(__out BYTE (*hashValue)[20]) + { + + // Sha1 hash result is fixed size, at 20 bytes. + + CHKNT(BCryptFinishHash(_hHash, reinterpret_cast(&hashValue[0]), _countof(*hashValue), 0)); + return S_OK; + } + ~Sha1() + { + if (_hHash) + { + BCryptDestroyHash(_hHash); + } + if (_hAlg) + { + BCryptCloseAlgorithmProvider(_hAlg, 0); + } + } + private: + + ArrayHolder _ahBuf; + BCRYPT_ALG_HANDLE _hAlg; + BCRYPT_HASH_HANDLE _hHash; + }; +}} // namespace Ro::detail + +extern "C" +{ + +inline HRESULT _RoSha1Create( + __out void** handle) +{ + *handle = nullptr; + + Ro::detail::ElementHolder sha1Instance; + sha1Instance.Value() = new (std::nothrow) Ro::detail::Sha1; + if (!sha1Instance.Value()) + { + CHKHR(E_OUTOFMEMORY); + } + CHKHR(sha1Instance->Initialize()); + + *handle = sha1Instance.Detach(); + return S_OK; +} + + +inline HRESULT _RoSha1AppendData( + __in void* handle, + __in size_t numBytes, + __in_bcount(numBytes) const void* data) +{ + Ro::detail::Sha1* sha1Instance = static_cast(handle); + CHKHR(sha1Instance->AppendData(numBytes, data)); + return S_OK; +} + + +inline HRESULT _RoSha1Finish( + __in void* handle, + __out BYTE (*hashValue)[20]) +{ + Ro::detail::Sha1* sha1Instance = static_cast(handle); + CHKHR(sha1Instance->GetResult(hashValue)); + return S_OK; +} + +inline void _RoSha1Release(__in void* handle) +{ + Ro::detail::Sha1* sha1Instance = static_cast(handle); + delete sha1Instance; +} + +} + +#endif /* ifdef WINRT_PARAMINSTANCE_NOCRYPT_SHA1 */ + +#ifdef _MSC_VER +#pragma pop_macro("CHKNT") +#pragma pop_macro("CHKHR") +#pragma warning( pop ) +#endif + +#endif /* ifdef __cplusplus */ +#endif /* ifndef WINRT_PARAMINSTANCEAPI_H */ diff --git a/lib/coreclr/src/inc/winrt/windowsruntime.h b/lib/coreclr/src/inc/winrt/windowsruntime.h new file mode 100644 index 0000000000..2ac4391612 --- /dev/null +++ b/lib/coreclr/src/inc/winrt/windowsruntime.h @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef WindowsRuntime_h +#define WindowsRuntime_h + +#include +#include +#include "holder.h" + +#ifndef IID_INS_ARGS + #define IID_INS_ARGS(ppType) __uuidof(**(ppType)), IID_INS_ARGS_Helper(ppType) +#endif + +HRESULT StringCchLength( + __in LPCWSTR wz, + __out UINT32 *pcch); + +#ifndef CROSSGEN_COMPILE +namespace clr +{ + namespace winrt + { + using ABI::Windows::Foundation::GetActivationFactory; + + template inline + HRESULT GetActivationFactory( + __in WinRtStringRef const & wzActivatableClassId, + __deref_out ItfT** ppItf) + { + LIMITED_METHOD_CONTRACT; + GCX_PREEMP(); + return GetActivationFactory(wzActivatableClassId.Get(), ppItf); + } + + template + HRESULT GetActivationFactory( + __in WinRtStringRef const & wzActivatableClassId, + __in typename ReleaseHolder& hItf) + { + LIMITED_METHOD_CONTRACT; + GCX_PREEMP(); + return GetActivationFactory(wzActivatableClassId.Get(), (ItfT**)&hItf); + } + } // namespace winrt +} // namespace clr +#endif //CROSSGEN_COMPILE + +#endif // WindowsRuntime_h + + diff --git a/lib/coreclr/src/inc/winrt/windowsstring.h b/lib/coreclr/src/inc/winrt/windowsstring.h new file mode 100644 index 0000000000..aa18eb6f49 --- /dev/null +++ b/lib/coreclr/src/inc/winrt/windowsstring.h @@ -0,0 +1,774 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// +// + +#pragma once + +#ifndef WindowsString_h +#define WindowsString_h + +#include // Required by strsafe.h +#include // For SizeTToUInt32 +#include // For StringCchLengthW. +#include // The Windows SDK header file for HSTRING and HSTRING_HEADER. + +//--------------------------------------------------------------------------------------------------------------------------- +// Forward declarations +void DECLSPEC_NORETURN ThrowHR(HRESULT hr); + +//--------------------------------------------------------------------------------------------------------------------------- +namespace clr +{ + namespace winrt + { + //------------------------------------------------------------------------------------------------------------------- + // The internal Windows Runtime String wrapper class which doesn't throw exception when a failure occurs + // Note String class doesn't provide copy constructor and copy assigment. This is because the *fast* string duplicate + // can fail, which makes the copy constructor unusable in contexts where exceptions are not expected because it would + // need to throw on failure. However, a move constructor and move assignment are provided. These require a String && + // argument, which prevents a *fast* string from being moved (StringReference can be cast to const String&, but not + // String&&). + class String + { + public: + String() throw() : _hstring(nullptr) + { + STATIC_CONTRACT_LIMITED_METHOD; + } + + // Move Constructor + String(__inout String&& other) throw() + : _hstring(other._hstring) + { + STATIC_CONTRACT_LIMITED_METHOD; + other._hstring = nullptr; + } + + // Move assignment + String & operator = (__inout String&& other) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + Release(); + _hstring = other._hstring; + other._hstring = nullptr; + return *this; + } + + // Initialize this string from a source string. A copy is made in this call. + // The str parameter doesn't need to be null terminated, and it may have embedded NUL characters. + HRESULT Initialize(_In_reads_opt_(length) const wchar_t *str, UINT32 length) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsCreateString(str, length, &local); + return FreeAndAssignOnSuccess(hr, local, &_hstring); + } + + // Initialize this string from a source string. A copy is made in this call. The input string must have a terminating NULL. + HRESULT Initialize(__in PCWSTR str) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HRESULT hr = S_OK; + + if (nullptr == str) + { // HSTRING functions promote null string pointers to the empty string, so we should too. + str = L""; + } + + size_t length = 0; + if (SUCCEEDED(hr)) + { + hr = StringCchLengthW(str, STRSAFE_MAX_CCH, &length); + } + + HSTRING local = nullptr; + if (SUCCEEDED(hr)) + { + hr = WindowsCreateString(str, static_cast(length), &local); + } + + return FreeAndAssignOnSuccess(hr, local, &_hstring); + } + + // Initialize this string from an HSTRING. A copy is made in this call. + HRESULT Initialize(const HSTRING& other) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsDuplicateString(other, &local); + return FreeAndAssignOnSuccess(hr, local, &_hstring); + } + + ~String() throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + if (_hstring) + { + WindowsDeleteString(_hstring); + } + } + + // Release the current HSTRING object and reset the member variable to empty + void Release() throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + if (_hstring) + { + WindowsDeleteString(_hstring); + _hstring = nullptr; + } + } + + // Detach the current HSTRING + void Detach(__out HSTRING *phstring) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + *phstring = _hstring; + _hstring = nullptr; + } + + // Duplicate from another String. + HRESULT Duplicate(__in const String& other) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsDuplicateString(other, &local); + return FreeAndAssignOnSuccess(hr, local, &_hstring); + } + + // Copy/duplicate into a bare HSTRING + HRESULT CopyTo(__out HSTRING *phstring) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return WindowsDuplicateString(this->_hstring, phstring); + } + + // HSTRING operator + operator const HSTRING&() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _hstring; + } + + // Explicit conversion to HSTRING + HSTRING Get() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _hstring; + } + + // Retrieve the address of the held hstring + HSTRING* Address() + { + STATIC_CONTRACT_LIMITED_METHOD; + return &_hstring; + } + + // Return the address of the internal HSTRING so that the caller can overwrite it, + // trusting that the caller will not leak the previously held value + HSTRING* GetAddressOf() + { + STATIC_CONTRACT_LIMITED_METHOD; + return &_hstring; + } + + // Return the address of the internal HSTRING so that the caller can overwrite it, + // but release the previous HSTRING to prevent a leak + HSTRING* ReleaseAndGetAddressOf() + { + STATIC_CONTRACT_LIMITED_METHOD; + if (_hstring != nullptr) + { + WindowsDeleteString(_hstring); + _hstring = nullptr; + } + return &_hstring; + } + + // Allow the wrapper to assign a new HSTRING to this wrapper, releasing the old HSTRING + void Attach(__in_opt HSTRING string) + { + STATIC_CONTRACT_LIMITED_METHOD; + WindowsDeleteString(_hstring); + _hstring = string; + } + + // Data Access + UINT32 length() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return WindowsGetStringLen(_hstring); + } + + // The size() function is an alias for length(), included to parallel stl conventions. + // The length() function is preferred. + UINT32 size() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return length(); + } + + BOOL IsEmpty() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return WindowsIsStringEmpty(_hstring); + } + + BOOL HasEmbeddedNull() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + BOOL answer; + // Not capturing HRESULT + WindowsStringHasEmbeddedNull(_hstring, &answer); + return answer; + } + + LPCWSTR GetRawBuffer(__out_opt UINT32 *length = nullptr) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return WindowsGetStringRawBuffer(_hstring, length); + } + + HRESULT GetLpcwstr(__deref_out LPCWSTR *ppsz) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + if (HasEmbeddedNull()) + { + *ppsz = nullptr; + return E_INVALIDARG; + } + *ppsz = WindowsGetStringRawBuffer(_hstring, nullptr); + return S_OK; + } + + // CompareOrdinal + INT32 CompareOrdinal(const String& other) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(_hstring, other, &result); + + return result; + } + + // Concatenation + HRESULT Concat(const String& string, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsConcatString(_hstring, string, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + // Trim + HRESULT TrimStart(const String& trimString, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsTrimStringStart(_hstring, trimString, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + HRESULT TrimEnd(const String& trimString, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsTrimStringEnd(_hstring, trimString, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + // Substring + HRESULT Substring(UINT32 startIndex, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsSubstring(_hstring, startIndex, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + HRESULT Substring(UINT32 startIndex, UINT32 length, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsSubstringWithSpecifiedLength(_hstring, startIndex, length, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + // Replace + HRESULT Replace(const String& stringReplaced, const String& stringReplaceWith, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HSTRING local; + HRESULT hr = WindowsReplaceString(_hstring, stringReplaced, stringReplaceWith, &local); + return FreeAndAssignOnSuccess(hr, local, &newString._hstring); + } + + private: + + // No Copy Constructor + String(const String& other); + + // No Copy assignment because if it can fail + String & operator = (const String& other); + + // + // helper function, always returns the passed in HRESULT + // + // if the HRESULT indicates success, frees any previous *target string, + // and over-writes it with newValue + // + // if the HRESULT indicates failure, does nothing + // + static HRESULT FreeAndAssignOnSuccess(HRESULT hr, HSTRING newValue, __inout HSTRING *target) + { + STATIC_CONTRACT_LIMITED_METHOD; + if (SUCCEEDED(hr)) + { + // InterlockedExchangePointer wouldn't have much value, unless we also modified + // all readers of *target to insert a ReadBarrier. + HSTRING oldValue = *target; + *target = newValue; + WindowsDeleteString(oldValue); + } + return hr; + } + + HSTRING _hstring; + }; + + static_assert(sizeof(String[2]) == sizeof(HSTRING[2]), "clr::winrt::String must be same size as HSTRING!"); + + //------------------------------------------------------------------------------------------------------------------- + // String Comparison Operators + inline + bool operator == (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return 0 == result; + } + + inline + bool operator != (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return 0 != result; + } + + inline + bool operator < (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return -1 == result; + } + + inline + bool operator <= (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return -1 == result || 0 == result; + } + + inline + bool operator > (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return 1 == result; + } + + inline + bool operator >= (const String& left, const String& right) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + INT32 result = 0; + // Ignore the HRESULT from the following call. + WindowsCompareStringOrdinal(left, right, &result); + + return 1 == result || 0 == result; + } + + + //------------------------------------------------------------------------------------------------------------------- + // The internal Windows Runtime String wrapper class for passing a reference of an existing string buffer. + // This class is allocated on stack. + class StringReference + { + public: + + // Constructor which takes an existing string buffer and its length as the parameters. + // It fills an HSTRING_HEADER struct with the parameter. + // + // Warning: The caller must ensure the lifetime of the buffer outlives this + // object as it does not make a copy of the wide string memory. + StringReference(__in_opt PCWSTR stringRef, UINT32 length) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + HRESULT hr = WindowsCreateStringReference(stringRef, length, &_header, &_hstring); + + // Failfast if internal developers try to create a reference to a non-NUL terminated string + if (FAILED(hr)) + { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + // Constructor for use with string literals. + // It fills an HSTRING_HEADER struct with the parameter. + template + StringReference(__in WCHAR const (&stringRef)[N]) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + + HRESULT hr = WindowsCreateStringReference(stringRef, N - 1 /* remove terminating NUL from length */, &_header, &_hstring); + + // Failfast if internal developers try to create a reference to a non-NUL terminated string. This constructor + // should only be used with string literals, but someone could mistakenly use this with a local WCHAR array and + // forget to NUL-terminate it. + if (FAILED(hr)) + { + RaiseException(static_cast(STATUS_INVALID_PARAMETER), EXCEPTION_NONCONTINUABLE, 0, nullptr); + } + } + + // Contructor which takes an HSTRING as the parameter. The new StringReference will not create a new copy of the original HSTRING. + // + // Warning: The caller must ensure the lifetime of the hstring argument outlives this + // object as it does not make a copy. + explicit StringReference(const HSTRING& hstring) throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + // Create the StringReference without using the _header member, but instead with whatever header is used in hstring so that we + // prevent copying when Duplicate() is called on this object. There is no addref, nor decrement in the destructor, since we + // don't know or care if it's refcounted or truly a stack allocated reference. + _hstring = hstring; + } + + // const String& operator + operator const String&() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString(); + } + + // const HSTRING& operator + operator const HSTRING&() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _hstring; + } + + // Explicit conversion to HSTRING + HSTRING Get() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _hstring; + } + + // CompareOrdinal + INT32 CompareOrdinal(const String& other) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().CompareOrdinal(other); + } + + // Data Access + UINT32 length() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().length(); + } + + UINT32 size() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().size(); + } + + BOOL IsEmpty() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().IsEmpty(); + } + + BOOL HasEmbeddedNull() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().HasEmbeddedNull(); + } + + LPCWSTR GetRawBuffer(__out_opt UINT32 *length) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().GetRawBuffer(length); + } + + HRESULT GetLpcwstr(__deref_out LPCWSTR *ppsz) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().GetLpcwstr(ppsz); + } + + HRESULT CopyTo(__out HSTRING *phstring) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return WindowsDuplicateString(this->_hstring, phstring); + } + + // Concatenation + HRESULT Concat(const String& otherString, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().Concat(otherString, newString); + } + + // Trim + HRESULT TrimStart(const String& trimString, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().TrimStart(trimString, newString); + } + + HRESULT TrimEnd(const String& trimString, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().TrimEnd(trimString, newString); + } + + // Substring + HRESULT Substring(UINT32 startIndex, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().Substring(startIndex, newString); + } + + HRESULT Substring(UINT32 startIndex, UINT32 length, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().Substring(startIndex, length, newString); + } + + // Replace + HRESULT Replace(const String& stringReplaced, const String& stringReplaceWith, __out String& newString) const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return _AsString().Replace(stringReplaced, stringReplaceWith, newString); + } + + private: + // No Copy Constructor + StringReference(const String& other); + + // No non-const WCHAR array constructor + template + StringReference(__in WCHAR (&stringRef)[N]); + + // No Copy assigment + const StringReference & operator = (const String& other); + + // No new operator + static void * operator new(size_t size); + + // No delete operator + static void operator delete(void *p, size_t size); + + // const String& operator + const String& _AsString() const throw() + { + STATIC_CONTRACT_LIMITED_METHOD; + return reinterpret_cast(_hstring); + } + + HSTRING _hstring; + HSTRING_HEADER _header; + }; + } // namespace winrt +} // namespace clr + +typedef clr::winrt::String WinRtString; +typedef clr::winrt::StringReference WinRtStringRef; + +// ========================================================== +// WinRT-specific DuplicateString variations. + +LPWSTR DuplicateString( + LPCWSTR wszString, + size_t cchString); + +LPWSTR DuplicateStringThrowing( + LPCWSTR wszString, + size_t cchString); + +inline +LPWSTR DuplicateString(WinRtString const & str) +{ + STATIC_CONTRACT_NOTHROW; + UINT32 cchStr; + LPCWSTR wzStr = str.GetRawBuffer(&cchStr); + return DuplicateString(wzStr, cchStr); +} + +inline +LPWSTR DuplicateStringThrowing(WinRtString const & str) +{ + STATIC_CONTRACT_THROWS; + UINT32 cchStr; + LPCWSTR wzStr = str.GetRawBuffer(&cchStr); + return DuplicateStringThrowing(wzStr, cchStr); +} + +inline +LPWSTR DuplicateString(HSTRING const & hStr) +{ + STATIC_CONTRACT_NOTHROW; + WinRtStringRef str(hStr); + UINT32 cchStr; + LPCWSTR wzStr = str.GetRawBuffer(&cchStr); + return DuplicateString(wzStr, cchStr); +} + +inline +LPWSTR DuplicateStringThrowing(HSTRING const & hStr) +{ + STATIC_CONTRACT_THROWS; + WinRtStringRef str(hStr); + UINT32 cchStr; + LPCWSTR wzStr = str.GetRawBuffer(&cchStr); + return DuplicateStringThrowing(wzStr, cchStr); +} + +// ========================================================== +// Convenience overloads of StringCchLength + +// A convenience overload that assumes cchMax is STRSAFE_MAX_CCH. +inline +HRESULT StringCchLength( + __in LPCWSTR wz, + __out size_t *pcch) +{ + // To align with HSTRING functionality (which always promotes null + // string pointers to the empty string), this wrapper also promotes + // null string pointers to empty string before forwarding to Windows' + // implementation. Don't skip the call to StringCchLength for null + // pointers because we want to continue to align with the return value + // when passed a null length out parameter. + return StringCchLengthW(wz == nullptr ? L"" : wz, size_t(STRSAFE_MAX_CCH), pcch); +} + +#ifdef _WIN64 + // A UINT32-specific overload with built-in overflow check. + inline + HRESULT StringCchLength( + __in LPCWSTR wz, + __out UINT32 *pcch) + { + if (pcch == nullptr) + return E_INVALIDARG; + + size_t cch; + HRESULT hr = StringCchLength(wz, &cch); + if (FAILED(hr)) + return hr; + + return SizeTToUInt32(cch, pcch); + } +#endif // _WIN64 + +#ifndef DACCESS_COMPILE + //===================================================================================================================== + // Holder of CoTaskMem-allocated array of HSTRING (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::GetFileNameListForNamespace). + class CoTaskMemHSTRINGArrayHolder + { + public: + CoTaskMemHSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + + m_cValues = 0; + m_rgValues = nullptr; + } + ~CoTaskMemHSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + Destroy(); + } + + // Destroys current array and holds new array rgValues of size cValues. + void Init(HSTRING * rgValues, DWORD cValues) + { + LIMITED_METHOD_CONTRACT; + + Destroy(); + _ASSERTE(m_cValues == 0); + + _ASSERTE(((cValues == 0) && (rgValues == nullptr)) || + ((cValues > 0) && (rgValues != nullptr))); + + m_rgValues = rgValues; + m_cValues = cValues; + } + + HSTRING GetAt(DWORD index) const + { + LIMITED_METHOD_CONTRACT; + return m_rgValues[index]; + } + + DWORD GetCount() + { + LIMITED_METHOD_CONTRACT; + return m_cValues; + } + + private: + void Destroy() + { + LIMITED_METHOD_CONTRACT; + + for (DWORD i = 0; i < m_cValues; i++) + { + if (m_rgValues[i] != nullptr) + { + WindowsDeleteString(m_rgValues[i]); + } + } + m_cValues = 0; + + if (m_rgValues != nullptr) + { + CoTaskMemFree(m_rgValues); + m_rgValues = nullptr; + } + } + + private: + DWORD m_cValues; + HSTRING * m_rgValues; + }; // class CoTaskMemHSTRINGArrayHolder +#endif //!DACCESS_COMPILE + + +#endif // WindowsString_h + diff --git a/lib/coreclr/src/inc/winrtprojectedtypes.h b/lib/coreclr/src/inc/winrtprojectedtypes.h new file mode 100644 index 0000000000..503e0305df --- /dev/null +++ b/lib/coreclr/src/inc/winrtprojectedtypes.h @@ -0,0 +1,271 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// This header defines the list of types that are redirected in the CLR projection of WinRT. +// + +// +// The DEFINE_PROJECTED_TYPE macro takes the following parameters: +// * An ASCII string representing the namespace in winmd which contains the type being projected from +// * An ASCII string representing the name in winmd of the type being projected from +// * An ASCII string representing the namespace in .NET which contains the type being projected to +// * An ASCII string representing the name in .NET of the type being projected to +// * A symbol which is used to represent the assembly the .NET type is defined in +// * A symbol which is used to represent the contract assembly the .NET type is defined in +// * A symbol which is used to represent the WinRT type +// * A symbol which is used to represent the .NET type +// * A symbol which indicates what kind of type this is (struct, runtimeclassclass, etc) + +// +// Optionally, the DEFINE_PROJECTED_RUNTIMECLASS, DEFINE_PROJECTED_STRUCT, DEFINE_PROJECTED_ENUM, DEFINE_PROJECTED_PINTERFACE, +// DEFINE_PROJECTED_INTERFACE, and DEFINE_PROJECTED_ATTRIBUTE macros can be defined by the consumer of this header file, in +// order to get extra information about the projected types. +// +// Note that the input to these macros is in terms of the original winmd - so HResult is a DEFINE_PROJECTED_STRUCT even though it +// projects to the class Exception. If you are adding a projection where the WinRT and CLR views differ upon if the type is a +// value type or not, you'll need to update the signature rewriting code in md\winmd\adapter.cpp as well as the export code in +// toolbox\winmdexp\projectedtypes.cspp. +// +// If these extra macros are not defined, then the DEFINE_PROJECTED_TYPE macro is used to register the type +// +// Additionally, the DEFINE_HIDDEN_WINRT_TYPE macro can be defined by the consumer of this file to get information about WinRT +// types that are not projected but should be hidden from the developer, for instance because they are not intended to be used +// by 3rd party components. +// +// + +// DEFINE_PROJECTED_RUNTIMECLASS adds the following parameters: +// * A ASCII string representing the namespace qualified default interface name +// * The IID of the default interface +#ifndef DEFINE_PROJECTED_RUNTIMECLASS +#define DEFINE_PROJECTED_RUNTIMECLASS(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, szDefaultInterfaceName, DefaultInterfaceIID) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Runtimeclass) +#define __LOCAL_DEFINE_PROJECTED_RUNTIMECLASS +#endif // !DEFINE_PROJECTED_RUNTIMECLASS + +// DEFINE_PROJECTED_STRUCT adds the following parameters: +// * An array of Unicode strings representing the types of those fields +// +// Note that if a field is of a non-primitive type, it must be represented in WinRTGuidGenerator::MetaDataLocator::Locate +#ifndef DEFINE_PROJECTED_STRUCT +#define DEFINE_PROJECTED_STRUCT(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, fieldSizes) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Struct) +#define __LOCAL_DEFINE_PROJECTED_STRUCT +#endif // !DEFINE_PROJECTED_STRUCT + +#ifndef DEFINE_PROJECTED_JUPITER_STRUCT +#define DEFINE_PROJECTED_JUPITER_STRUCT(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, fieldSizes) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Struct) +#define __LOCAL_DEFINE_PROJECTED_JUPITER_STRUCT +#endif // !DEFINE_PROJECTED_JUPITER_STRUCT + +#ifndef STRUCT_FIELDS +#define STRUCT_FIELDS(...) __VA_ARGS__ +#endif // !STRUCT_FIELDS + +// DEFINE_PROJECTED_ENUM adds the following parameters: +// * An ASCII string defining the size of the backing field of the enumeration +#ifndef DEFINE_PROJECTED_ENUM +#define DEFINE_PROJECTED_ENUM(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, szBackingFieldSize) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Enum) +#define __LOCAL_DEFINE_PROJECTED_ENUM +#endif // !DEFINE_PROJECTED_ENUM + +// DEFINE_PROJECTED_INTERFACE adds the following extra parameters: +// * The IID of the interface +#ifndef DEFINE_PROJECTED_INTERFACE +#define DEFINE_PROJECTED_INTERFACE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, PIID) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Interface) +#define __LOCAL_DEFINE_PROJECTED_INTERFACE +#endif // !DEFINE_PROJECTED_INTERFACE + +// DEFINE_PROJECTED_PINTERFACE adds the following extra parameters: +// * The number of generic type parameters on the interface +// * The PIID of the interface +#ifndef DEFINE_PROJECTED_PINTERFACE +#define DEFINE_PROJECTED_PINTERFACE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, GenericTypeParameterCount, PIID) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, PInterface) +#define __LOCAL_DEFINE_PROJECTED_PINTERFACE +#endif // !DEFINE_PROJECTED_PINTERFACE + +// DEFINE_PROJECTED_DELEGATE adds the following extra parameters: +// * The IID of the delegate +#ifndef DEFINE_PROJECTED_DELEGATE +#define DEFINE_PROJECTED_DELEGATE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, PIID) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Delegate) +#define __LOCAL_DEFINE_PROJECTED_DELEGATE +#endif // !DEFINE_PROJECTED_DELEGATE + +// DEFINE_PROJECTED_PDELEGATE adds the following extra parameters: +// * The number of generic type parameters on the interface +// * The PIID of the delegate +#ifndef DEFINE_PROJECTED_PDELEGATE +#define DEFINE_PROJECTED_PDELEGATE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, GenericTypeParameterCount, PIID) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, PDelegate) +#define __LOCAL_DEFINE_PROJECTED_PDELEGATE +#endif // !DEFINE_PROJECTED_PDELEGATE + +#ifndef PIID +#define PIID(...) { __VA_ARGS__ } +#endif // !PIID + +// DEFINE_PROJECTED_ATTRIBUTE adds no additional parameters +#ifndef DEFINE_PROJECTED_ATTRIBUTE +#define DEFINE_PROJECTED_ATTRIBUTE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex) \ + DEFINE_PROJECTED_TYPE(szWinRTNamespace, szWinRTName, szClrNamespace, szClrName, nClrAssemblyIndex, nContractAsmIdx, WinRTRedirectedTypeIndex, ClrRedirectedTypeIndex, Attribute) +#define __LOCAL_DEFINE_PROJECTED_ATTRIBUTE +#endif // !DEFINE_PROJECTED_ATTRIBUTE + +#ifndef DEFINE_HIDDEN_WINRT_TYPE +#define DEFINE_HIDDEN_WINRT_TYPE(szWinRTNamespace, szWinRTName) +#define __LOCAL_DEFINE_HIDDEN_WINRT_TYPE +#endif // !DEFINE_HIDDEN_WINRT_TYPE + +// szWinRTNamespace szWinRTName szClrNamespace szClrName nClrAssemblyIndex nContractAsmIdx WinRTRedirectedTypeIndex ClrRedirectedTypeIndex Extra parameters +// ---------------- ----------- -------------- --------- ----------------- --------------- --------------------- ---------------------- ---------------- +DEFINE_PROJECTED_ATTRIBUTE ("Windows.Foundation.Metadata", "AttributeUsageAttribute", "System", "AttributeUsageAttribute", Mscorlib, SystemRuntime, Windows_Foundation_Metadata_AttributeUsageAttribute, System_AttributeUsage) +DEFINE_PROJECTED_ENUM ("Windows.Foundation.Metadata", "AttributeTargets", "System", "AttributeTargets", Mscorlib, SystemRuntime, Windows_Foundation_Metadata_AttributeTargets, System_AttributeTargets, "Int32") + +DEFINE_PROJECTED_STRUCT ("Windows.UI", "Color", "Windows.UI", "Color", SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntime, Windows_UI_Color, System_Windows_Color, STRUCT_FIELDS(W("UInt8"), W("UInt8"), W("UInt8"), W("UInt8"))) + +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "DateTime", "System", "DateTimeOffset", Mscorlib, SystemRuntime, Windows_Foundation_DateTime, System_DateTimeOffset, STRUCT_FIELDS(W("Int64"))) +DEFINE_PROJECTED_PDELEGATE ("Windows.Foundation", "EventHandler`1", "System", "EventHandler`1", Mscorlib, SystemRuntime, Windows_Foundation_EventHandlerGeneric, System_EventHandlerGeneric, 1, PIID(0x9de1c535, 0x6ae1, 0x11e0, {0x84, 0xe1, 0x18, 0xa9, 0x05, 0xbc, 0xc5, 0x3f})) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "EventRegistrationToken", "System.Runtime.InteropServices.WindowsRuntime", "EventRegistrationToken", Mscorlib, SystemRuntimeInteropServicesWindowsRuntime, Windows_Foundation_EventRegistrationToken, System_Runtime_InteropServices_WindowsRuntime_EventRegistrationToken, STRUCT_FIELDS(W("Int64"))) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "HResult", "System", "Exception", Mscorlib, SystemRuntime, Windows_Foundation_HResult, System_Exception, STRUCT_FIELDS(W("Int32"))) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation", "IReference`1", "System", "Nullable`1", Mscorlib, SystemRuntime, Windows_Foundation_IReference, System_Nullable, 1, PIID(0x61c17706, 0x2d65, 0x11e0, {0x9a, 0xe8, 0xd4, 0x85, 0x64, 0x01, 0x54, 0x72})) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "Point", "Windows.Foundation", "Point", SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntime, Windows_Foundation_Point, Windows_Foundation_Point_clr, STRUCT_FIELDS(W("Single"), W("Single"))) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "Rect", "Windows.Foundation", "Rect", SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntime, Windows_Foundation_Rect, Windows_Foundation_Rect_clr, STRUCT_FIELDS(W("Single"), W("Single"), W("Single"), W("Single"))) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "Size", "Windows.Foundation", "Size", SystemRuntimeWindowsRuntime, SystemRuntimeWindowsRuntime, Windows_Foundation_Size, Windows_Foundation_Size_clr, STRUCT_FIELDS(W("Single"), W("Single"))) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation", "TimeSpan", "System", "TimeSpan", Mscorlib, SystemRuntime, Windows_Foundation_TimeSpan, System_TimeSpan, STRUCT_FIELDS(W("Int64"))) +DEFINE_PROJECTED_RUNTIMECLASS("Windows.Foundation", "Uri", "System", "Uri", SystemRuntime, SystemRuntime, Windows_Foundation_Uri, System_Uri, "Windows.Foundation.IUriRuntimeClass", __uuidof(ABI::Windows::Foundation::IUriRuntimeClass)) + +DEFINE_PROJECTED_INTERFACE ("Windows.Foundation", "IClosable", "System", "IDisposable", Mscorlib, SystemRuntime, Windows_Foundation_IClosable, System_IDisposable, PIID(0x30d5a829, 0x7fa4, 0x4026, {0x83, 0xbb, 0xd7, 0x5b, 0xae, 0x4e, 0xa9, 0x9e})) + +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IIterable`1", "System.Collections.Generic", "IEnumerable`1", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IIterable, System_Collections_Generic_IEnumerable, 1, PIID(0xfaa585ea, 0x6214, 0x4217, {0xaf, 0xda, 0x7f, 0x46, 0xde, 0x58, 0x69, 0xb3})) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IVector`1", "System.Collections.Generic", "IList`1", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IVector, System_Collections_Generic_IList, 1, PIID(0x913337e9, 0x11a1, 0x4345, {0xa3, 0xa2, 0x4e, 0x7f, 0x95, 0x6e, 0x22, 0x2d})) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IVectorView`1", "System.Collections.Generic", "IReadOnlyList`1", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IVectorView, System_Collections_Generic_IReadOnlyList, 1, PIID(0xbbe1fa4c, 0xb0e3, 0x4583, {0xba, 0xef, 0x1f, 0x1b, 0x2e, 0x48, 0x3e, 0x56})) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IMap`2", "System.Collections.Generic", "IDictionary`2", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IMap, System_Collections_Generic_IDictionary, 2, PIID(0x3c2925fe, 0x8519, 0x45c1, {0xaa, 0x79, 0x19, 0x7b, 0x67, 0x18, 0xc1, 0xc1})) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IMapView`2", "System.Collections.Generic", "IReadOnlyDictionary`2", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IMapView, System_Collections_Generic_IReadOnlyDictionary, 2, PIID(0xe480ce40, 0xa338, 0x4ada, {0xad, 0xcf, 0x27, 0x22, 0x72, 0xe4, 0x8c, 0xb9})) +DEFINE_PROJECTED_PINTERFACE ("Windows.Foundation.Collections", "IKeyValuePair`2", "System.Collections.Generic", "KeyValuePair`2", Mscorlib, SystemRuntime, Windows_Foundation_Collections_IKeyValuePair, System_Collections_Generic_KeyValuePair, 2, PIID(0x02b51929, 0xc1c4, 0x4a7e, {0x89, 0x40, 0x03, 0x12, 0xb5, 0xc1, 0x85, 0x00})) + +DEFINE_PROJECTED_INTERFACE ("Windows.UI.Xaml.Input", "ICommand", "System.Windows.Input", "ICommand", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Input_ICommand, System_Windows_Input_ICommand, PIID(0xE5AF3542, 0xCA67, 0x4081, {0x99, 0x5B, 0x70, 0x9D, 0xD1, 0x37, 0x92, 0xDF})) + +DEFINE_PROJECTED_INTERFACE ("Windows.UI.Xaml.Interop", "IBindableIterable", "System.Collections", "IEnumerable", Mscorlib, SystemRuntime, Windows_UI_Xaml_Interop_IBindableIterable, System_Collections_IEnumerable, PIID(0x036d2c08, 0xdf29, 0x41af, {0x8a, 0xa2, 0xd7, 0x74, 0xbe, 0x62, 0xba, 0x6f})) +DEFINE_PROJECTED_INTERFACE ("Windows.UI.Xaml.Interop", "IBindableVector", "System.Collections", "IList", Mscorlib, SystemRuntime, Windows_UI_Xaml_Interop_IBindableVector, System_Collections_IList, PIID(0x393de7de, 0x6fd0, 0x4c0d, {0xbb, 0x71, 0x47, 0x24, 0x4a, 0x11, 0x3e, 0x93})) + +DEFINE_PROJECTED_INTERFACE ("Windows.UI.Xaml.Interop", "INotifyCollectionChanged", "System.Collections.Specialized", "INotifyCollectionChanged", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Interop_INotifyCollectionChanged, System_Collections_Specialized_INotifyCollectionChanged, PIID(0x28b167d5, 0x1a31, 0x465b, {0x9b, 0x25, 0xd5, 0xc3, 0xae, 0x68, 0x6c, 0x40})) +DEFINE_PROJECTED_DELEGATE ("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventHandler", "System.Collections.Specialized", "NotifyCollectionChangedEventHandler", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Interop_NotifyCollectionChangedEventHandler, System_Collections_Specialized_NotifyCollectionChangedEventHandler, PIID(0xca10b37c, 0xf382, 0x4591, {0x85, 0x57, 0x5e, 0x24, 0x96, 0x52, 0x79, 0xb0})) +DEFINE_PROJECTED_RUNTIMECLASS("Windows.UI.Xaml.Interop", "NotifyCollectionChangedEventArgs", "System.Collections.Specialized", "NotifyCollectionChangedEventArgs", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Interop_NotifyCollectionChangedEventArgs, System_Collections_Specialized_NotifyCollectionChangedEventArgs, "Windows.UI.Xaml.Interop.INotifyCollectionChangedEventArgs", PIID(0x4cf68d33, 0xe3f2, 0x4964, {0xb8, 0x5e, 0x94, 0x5b, 0x4f, 0x7e, 0x2f, 0x21})) +DEFINE_PROJECTED_ENUM ("Windows.UI.Xaml.Interop", "NotifyCollectionChangedAction", "System.Collections.Specialized", "NotifyCollectionChangedAction", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Interop_NotifyCollectionChangedAction, System_Collections_Specialized_NotifyCollectionChangedAction, "Int32") + +DEFINE_PROJECTED_INTERFACE ("Windows.UI.Xaml.Data", "INotifyPropertyChanged", "System.ComponentModel", "INotifyPropertyChanged", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Data_INotifyPropertyChanged, System_ComponentModel_INotifyPropertyChanged, PIID(0xcf75d69c, 0xf2f4, 0x486b, {0xb3, 0x02, 0xbb, 0x4c, 0x09, 0xba, 0xeb, 0xfa})) +DEFINE_PROJECTED_DELEGATE ("Windows.UI.Xaml.Data", "PropertyChangedEventHandler", "System.ComponentModel", "PropertyChangedEventHandler", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Data_PropertyChangedEventHandler, System_ComponentModel_PropertyChangedEventHandler, PIID(0x50f19c16, 0x0a22, 0x4d8e, {0xa0, 0x89, 0x1e, 0xa9, 0x95, 0x16, 0x57, 0xd2})) +DEFINE_PROJECTED_RUNTIMECLASS("Windows.UI.Xaml.Data", "PropertyChangedEventArgs", "System.ComponentModel", "PropertyChangedEventArgs", SystemObjectModel, SystemObjectModel, Windows_UI_Xaml_Data_PropertyChangedEventArgs, System_ComponentModel_PropertyChangedEventArgs, "Windows.UI.Xaml.Data.IPropertyChangedEventArgs", PIID(0x4f33a9a0, 0x5cf4, 0x47a4, {0xb1, 0x6f, 0xd7, 0xfa, 0xaf, 0x17, 0x45, 0x7e})) + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml", "CornerRadius", "Windows.UI.Xaml", "CornerRadius", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_CornerRadius, Windows_UI_Xaml_CornerRadius_clr, STRUCT_FIELDS(W("Double"), W("Double"), W("Double"), W("Double"))) +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml", "Duration", "Windows.UI.Xaml", "Duration", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Duration, Windows_UI_Xaml_Duration_clr, STRUCT_FIELDS(W("Windows.Foundation.TimeSpan"), W("Windows.UI.Xaml.DurationType"))) +DEFINE_PROJECTED_ENUM ("Windows.UI.Xaml", "DurationType", "Windows.UI.Xaml", "DurationType", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_DurationType, Windows_UI_Xaml_DurationType_clr, "Int32") +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml", "GridLength", "Windows.UI.Xaml", "GridLength", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_GridLength, Windows_UI_Xaml_GridLength_clr, STRUCT_FIELDS(W("Double"), W("Windows.UI.Xaml.GridUnitType"))) +DEFINE_PROJECTED_ENUM ("Windows.UI.Xaml", "GridUnitType", "Windows.UI.Xaml", "GridUnitType", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_GridUnitType, Windows_UI_Xaml_GridUnitType_clr, "Int32") +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml", "Thickness", "Windows.UI.Xaml", "Thickness", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Thickness, Windows_UI_Xaml_Thickness_clr, STRUCT_FIELDS(W("Double"), W("Double"), W("Double"), W("Double"))) + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Interop", "TypeName", "System", "Type", Mscorlib, SystemRuntime, Windows_UI_Xaml_Interop_TypeName, System_Type, STRUCT_FIELDS(W("String"), W("Windows.UI.Xaml.Interop.TypeKind"))) + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", "Windows.UI.Xaml.Controls.Primitives", "GeneratorPosition", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Controls_Primitives_GeneratorPosition, Windows_UI_Xaml_Controls_Primitives_GeneratorPosition_clr, STRUCT_FIELDS(W("Int32"), W("Int32"))) + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Media", "Matrix", "Windows.UI.Xaml.Media", "Matrix", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Media_Matrix, Windows_UI_Xaml_Media_Matrix_clr, STRUCT_FIELDS(W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"))) + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Media.Animation", "KeyTime", "Windows.UI.Xaml.Media.Animation", "KeyTime", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Media_Animation_KeyTime, Windows_UI_Xaml_Media_Animation_KeyTime_clr, STRUCT_FIELDS(W("Windows.Foundation.TimeSpan"))) +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Media.Animation", "RepeatBehavior", "Windows.UI.Xaml.Media.Animation", "RepeatBehavior", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Media_Animation_RepeatBehavior, Windows_UI_Xaml_Media_Animation_RepeatBehavior_clr, STRUCT_FIELDS(W("Double"), W("Windows.Foundation.TimeSpan"), W("Windows.UI.Xaml.Media.Animation.RepeatBehaviorType"))) +DEFINE_PROJECTED_ENUM ("Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", "Windows.UI.Xaml.Media.Animation", "RepeatBehaviorType", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Media_Animation_RepeatBehaviorType, Windows_UI_Xaml_Media_Animation_RepeatBehaviorType_clr, "Int32") + +DEFINE_PROJECTED_JUPITER_STRUCT("Windows.UI.Xaml.Media.Media3D", "Matrix3D", "Windows.UI.Xaml.Media.Media3D", "Matrix3D", SystemRuntimeWindowsRuntimeUIXaml, SystemRuntimeWindowsRuntimeUIXaml, Windows_UI_Xaml_Media_Media3D_Matrix3D, Windows_UI_Xaml_Media_Media3D_Matrix3D_clr, STRUCT_FIELDS(W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"), W("Double"))) + +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Vector2", "System.Numerics", "Vector2", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Vector2, System_Numerics_Vector2, STRUCT_FIELDS(L"Single", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Vector3", "System.Numerics", "Vector3", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Vector3, System_Numerics_Vector3, STRUCT_FIELDS(L"Single", L"Single", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Vector4", "System.Numerics", "Vector4", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Vector4, System_Numerics_Vector4, STRUCT_FIELDS(L"Single", L"Single", L"Single", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Matrix3x2", "System.Numerics", "Matrix3x2", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Matrix3x2, System_Numerics_Matrix3x2, STRUCT_FIELDS(L"Single", L"Single", L"Single", L"Single", L"Single", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Matrix4x4", "System.Numerics", "Matrix4x4", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Matrix4x4, System_Numerics_Matrix4x4, STRUCT_FIELDS(L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Plane", "System.Numerics", "Plane", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Plane, System_Numerics_Plane, STRUCT_FIELDS(L"Windows.Foundation.Numerics.Vector3", L"Single")) +DEFINE_PROJECTED_STRUCT ("Windows.Foundation.Numerics", "Quaternion", "System.Numerics", "Quaternion", SystemNumericsVectors, SystemNumericsVectors, Windows_Foundation_Numerics_Quaternion, System_Numerics_Quaternion, STRUCT_FIELDS(L"Single", L"Single", L"Single", L"Single")) + +#ifdef DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE + +// Windows.Foundation.Metadata.AttributeTarget and System.AttributeTarget enum +// define different bits for everything (@todo: Be nice to change that before we ship.) +// +// This table encapsulates the correspondence. NOTE: Some rows in the CLR column store a 0 +// to indicate that the CLR has no corresponding bit for the WinRT value. +// +// WinRT CLR +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000001, 0x00001000) // AttributeTargets.Delegate +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000002, 0x00000010) // AttributeTargets.Enum +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000004, 0x00000200) // AttributeTargets.Event +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000008, 0x00000100) // AttributeTargets.Field +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000010, 0x00000400) // AttributeTargets.Interface +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000020, 0x00000000) // AttributeTargets.InterfaceGroup (no equivalent in CLR) +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000040, 0x00000040) // AttributeTargets.Method +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000080, 0x00000800) // AttributeTargets.Parameter +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000100, 0x00000080) // AttributeTargets.Property +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000200, 0x00000004) // AttributeTargets.RuntimeClass <--> Class +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000400, 0x00000008) // AttributeTargets.Struct +DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUE(0x00000800, 0x00000000) // AttributeTargets.InterfaceImpl (no equivalent in CLR) + +#endif // #ifdef DEFINE_PROJECTED_ATTRIBUTETARGETS_VALUES + + +DEFINE_HIDDEN_WINRT_TYPE("Windows.Foundation.Metadata", "GCPressureAttribute") +DEFINE_HIDDEN_WINRT_TYPE("Windows.Foundation.Metadata", "GCPressureAmount") + +DEFINE_HIDDEN_WINRT_TYPE("Windows.Foundation", "IPropertyValue") +DEFINE_HIDDEN_WINRT_TYPE("Windows.Foundation", "IReferenceArray`1") + + +#ifdef __LOCAL_DEFINE_PROJECTED_RUNTIMECLASS +#undef DEFINE_PROJECTED_RUNTIMECLASS +#endif // __LOCAL_DEFINE_PROJECTED_RUNTIMECLASS + +#ifdef __LOCAL_DEFINE_PROJECTED_STRUCT +#undef DEFINE_PROJECTED_STRUCT +#endif // __LOCAL_DEFINE_PROJECTED_STRUCT + +#ifdef __LOCAL_DEFINE_PROJECTED_JUPITER_STRUCT +#undef DEFINE_PROJECTED_JUPITER_STRUCT +#endif // __LOCAL_DEFINE_PROJECTED_JUPITER_STRUCT + +#ifdef __LOCAL_DEFINE_PROJECTED_ENUM +#undef DEFINE_PROJECTED_ENUM +#endif // __LOCAL_DEFINE_PROJECTED_ENUM + +#ifdef __LOCAL_DEFINE_PROJECTED_INTERFACE +#undef DEFINE_PROJECTED_INTERFACE +#endif // __LOCAL_DEFINE_PROJECTED_INTERFACE + +#ifdef __LOCAL_DEFINE_PROJECTED_PINTERFACE +#undef DEFINE_PROJECTED_PINTERFACE +#endif // __LOCAL_DEFINE_PROJECTED_PINTERFACE + +#ifdef __LOCAL_DEFINE_PROJECTED_DELEGATE +#undef DEFINE_PROJECTED_DELEGATE +#endif // __LOCAL_DEFINE_PROJECTED_DELEGATE + +#ifdef __LOCAL_DEFINE_PROJECTED_PDELEGATE +#undef DEFINE_PROJECTED_PDELEGATE +#endif // __LOCAL_DEFINE_PROJECTED_PDELEGATE + +#ifdef __LOCAL_DEFINE_PROJECTED_ATTRIBUTE +#undef DEFINE_PROJECTED_ATTRIBUTE +#endif // __LOCAL_DEFINE_PROJECTED_ATTRIBUTE + +#ifdef __LOCAL_DEFINE_HIDDEN_WINRT_TYPE +#undef DEFINE_HIDDEN_WINRT_TYPE +#endif // __LOCAL_DEFINE_HIDDEN_WINRT_TYPE + +#undef JUPITER_PROJECTION_NS +#undef JUPITER_PROJECTION_CONTROLS_PRIMITIVES_NS +#undef JUPITER_PROJECTION_MEDIA_NS +#undef JUPITER_PROJECTION_MEDIA_ANIMATION_NS +#undef JUPITER_PROJECTION_MEDIA_3D_NS +#undef JUPITER_FOUNDATION_PROJECTION_NS diff --git a/lib/coreclr/src/inc/winwrap.h b/lib/coreclr/src/inc/winwrap.h new file mode 100644 index 0000000000..1986e1d40b --- /dev/null +++ b/lib/coreclr/src/inc/winwrap.h @@ -0,0 +1,533 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +//***************************************************************************** +// WinWrap.h +// +// This file contains wrapper functions for Win32 API's that take strings. +// +// The Common Language Runtime internally uses UNICODE as the internal state +// and string format. This file will undef the mapping macros so that one +// cannot mistakingly call a method that isn't going to work. Instead, you +// have to call the correct wrapper API. +// +//***************************************************************************** + +#ifndef __WIN_WRAP_H__ +#define __WIN_WRAP_H__ + +//********** Macros. ********************************************************** +#if !defined(WIN32_LEAN_AND_MEAN) +#define WIN32_LEAN_AND_MEAN +#endif + +// +// WinCE uniformly uses cdecl calling convention on x86. __stdcall is defined as __cdecl in SDK. +// STDCALL macro is meant to be used where we have hard dependency on __stdcall calling convention +// - the unification with __cdecl does not apply to STDCALL. +// +#define STDCALL _stdcall + +//********** Includes. ******************************************************** + +#include +#include +#include +#include + +#include "registrywrapper.h" +#include "longfilepathwrappers.h" + +#if defined(_PREFAST_) || defined(SOURCE_FORMATTING) +// +// For PREFAST we don't want the C_ASSERT to be expanded since it always +// involves the comparison of two constants which causes PREfast warning 326 +// +#undef C_ASSERT +#define C_ASSERT(expr) +#endif + +#include "palclr.h" + +#if !defined(__TODO_PORT_TO_WRAPPERS__) +//***************************************************************************** +// Undefine all of the windows wrappers so you can't use them. +//***************************************************************************** + +// winbase.h +#undef GetBinaryType +#undef GetShortPathName +#undef GetLongPathName +#undef GetEnvironmentStrings +#undef FreeEnvironmentStrings +#undef FormatMessage +#undef lstrcmp +#undef lstrcmpi +#undef lstrcpyn +#undef lstrlen +#undef CreateMutex +#undef OpenMutex +#undef CreateEvent +#undef OpenEvent +#undef CreateSemaphore +#undef OpenSemaphore +#undef CreateWaitableTimer +#undef CreateFileMapping +#undef OpenFileMapping +#undef LoadLibrary +#undef LoadLibraryEx +#undef GetModuleFileName +#undef GetModuleHandle +#undef GetModuleHandleEx +#undef CreateProcess +#undef GetCommandLine +#undef GetEnvironmentVariable +#undef SetEnvironmentVariable +#undef ExpandEnvironmentStrings +#undef OutputDebugString +#undef FindResource +#undef FindResourceEx +#undef BeginUpdateResource +#undef UpdateResource +#undef EndUpdateResource +#undef GetPrivateProfileInt +#undef GetSystemDirectory +#undef GetTempPath +#undef GetTempFileName +#undef SetCurrentDirectory +#undef GetCurrentDirectory +#undef CreateDirectory +#undef RemoveDirectory +#undef GetFullPathName +#undef CreateFile +#undef SetFileAttributes +#undef GetFileAttributes +#undef GetFileAttributesEx +#undef DeleteFile +#undef FindFirstFileEx +#undef FindFirstFile +#undef FindNextFile +#undef SearchPath +#undef CopyFile +#undef CopyFileEx +#undef MoveFile +#undef MoveFileEx +#undef CreateHardLink +#undef CreateNamedPipe +#undef WaitNamedPipe +#undef LookupPrivilegeValue +#undef GetVersionEx + +// winuser.h +#undef MAKEINTRESOURCE +#undef GetUserObjectInformation +#undef GetMessage + +#undef SendMessage +#undef CharLower +#undef CharNext +#undef MessageBox +#undef GetClassName +#undef LoadString +#undef GetCalendarInfo +#undef GetDateFormat +#undef GetTimeFormat +#undef LCMapString + +#endif // !defined(__TODO_PORT_TO_WRAPPERS__) + +// +// NT supports the wide entry points. So we redefine the wrappers right back +// to the *W entry points as macros. This way no client code needs a wrapper on NT. +// + +// winbase.h +#define WszGetEnvironmentStrings GetEnvironmentStringsW +#define WszFreeEnvironmentStrings FreeEnvironmentStringsW +#ifndef USE_FORMATMESSAGE_WRAPPER +#define WszFormatMessage FormatMessageW +#else +#define WszFormatMessage CCompRC::FormatMessage +#endif +#define Wszlstrcmp lstrcmpW +#define Wszlstrcmpi lstrcmpiW +#define WszCreateMutex CreateMutexW +#define WszOpenMutex OpenMutexW +#define WszCreateEvent CreateEventW +#define WszOpenEvent OpenEventW +#define WszCreateWaitableTimer CreateWaitableTimerW +#define WszCreateFileMapping CreateFileMappingW +#define WszOpenFileMapping OpenFileMappingW +#define WszGetModuleHandle GetModuleHandleW +#define WszGetModuleHandleEx GetModuleHandleExW +#define WszGetCommandLine GetCommandLineW +#define WszSetEnvironmentVariable SetEnvironmentVariableW +#define WszExpandEnvironmentStrings ExpandEnvironmentStringsW +#define WszOutputDebugString OutputDebugStringW +#define WszFindResource FindResourceW +#define WszFindResourceEx FindResourceExW +#define WszBeginUpdateResource BeginUpdateResourceW +#define WszUpdateResource UpdateResourceW +#define WszEndUpdateResource EndUpdateResourceW +#define WszGetPrivateProfileInt GetPrivateProfileIntW +#define WszGetSystemDirectory GetSystemDirectoryW +#define WszCreateNamedPipe CreateNamedPipeW +#define WszWaitNamedPipe WaitNamedPipeW +#define WszLookupPrivilegeValue LookupPrivilegeValueW + +// winuser.h +#define WszMAKEINTRESOURCE MAKEINTRESOURCEW +#define WszGetUserObjectInformation GetUserObjectInformationW +#define WszGetMessage GetMessageW +#define WszSendMessage SendMessageW +#define WszCharLower CharLowerW +#define WszCharNext CharNextW +#define WszMessageBox LateboundMessageBoxW +#define WszGetClassName GetClassNameW +#define WszLoadString LoadStringW +#define WszRegOpenKeyEx ClrRegOpenKeyEx +#define WszRegOpenKey(hKey, wszSubKey, phkRes) ClrRegOpenKeyEx(hKey, wszSubKey, 0, KEY_ALL_ACCESS, phkRes) +#define WszRegQueryValue RegQueryValueW +#define WszRegQueryValueEx RegQueryValueExW +#define WszRegQueryValueExTrue RegQueryValueExW +#define WszRegQueryStringValueEx RegQueryValueExW + + +#define WszRegQueryInfoKey RegQueryInfoKeyW +#define WszRegEnumValue RegEnumValueW +#define WszRegEnumKeyEx RegEnumKeyExW +#define WszGetCalendarInfo GetCalendarInfoW +#define WszGetDateFormat GetDateFormatW +#define WszGetTimeFormat GetTimeFormatW +#define WszLCMapString LCMapStringW +#define WszMultiByteToWideChar MultiByteToWideChar +#define WszWideCharToMultiByte WideCharToMultiByte +#define WszCreateSemaphore CreateSemaphoreW + + +#ifdef FEATURE_CORESYSTEM + +// CoreSystem has CreateSemaphoreExW but not CreateSemaphoreW. +#undef WszCreateSemaphore +#define WszCreateSemaphore(_secattr, _count, _maxcount, _name) CreateSemaphoreExW((_secattr), (_count), (_maxcount), (_name), 0, MAXIMUM_ALLOWED | SYNCHRONIZE | SEMAPHORE_MODIFY_STATE) + +// Same deal as above for GetFileVersionInfo/GetFileVersionInfoSize. +#undef GetFileVersionInfo +#define GetFileVersionInfo(_filename, _handle, _len, _data) GetFileVersionInfoEx(0, (_filename), (_handle), (_len), (_data)) +#undef GetFileVersionInfoSize +#define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle)) + +#endif // FEATURE_CORESYSTEM + +#ifndef _T +#define _T(str) W(str) +#endif + +//File and Directory Functions which need special handling for LongFile Names +//Note only the functions which are currently used are defined +#define WszLoadLibrary LoadLibraryExWrapper +#define WszLoadLibraryEx LoadLibraryExWrapper +#define WszCreateFile CreateFileWrapper +#define WszSetFileAttributes SetFileAttributesWrapper +#define WszGetFileAttributes GetFileAttributesWrapper +#define WszGetFileAttributesEx GetFileAttributesExWrapper +#define WszDeleteFile DeleteFileWrapper +#define WszFindFirstFileEx FindFirstFileExWrapper +#define WszFindNextFile FindNextFileW +#define WszCopyFile CopyFileWrapper +#define WszCopyFileEx CopyFileExWrapper +#define WszMoveFileEx MoveFileExWrapper +#define WszMoveFile(lpExistingFileName, lpNewFileName) WszMoveFileEx(lpExistingFileName, lpNewFileName, 0) +#define WszCreateDirectory CreateDirectoryWrapper +#define WszRemoveDirectory RemoveDirectoryWrapper +#define WszCreateHardLink CreateHardLinkWrapper + +//Can not use extended syntax +#define WszGetFullPathName GetFullPathNameW + +//Long Files will not work on these till redstone +#define WszGetCurrentDirectory GetCurrentDirectoryWrapper +#define WszGetTempFileName GetTempFileNameWrapper +#define WszGetTempPath GetTempPathWrapper + +//APIS which have a buffer as an out parameter +#define WszGetEnvironmentVariable GetEnvironmentVariableWrapper +#define WszSearchPath SearchPathWrapper +#define WszGetShortPathName GetShortPathNameWrapper +#define WszGetLongPathName GetLongPathNameWrapper +#define WszGetModuleFileName GetModuleFileNameWrapper + +//NOTE: IF the following API's are enabled ensure that they can work with LongFile Names +//See the usage and implementation of above API's +// +//#define WszSetCurrentDirectory SetCurrentDirectoryW +//#define WszGetBinaryType GetBinaryTypeWrapper //Coresys does not seem to have this API + +#if FEATURE_PAL +#define WszFindFirstFile FindFirstFileW +#else +#define WszFindFirstFile(_lpFileName_, _lpFindData_) FindFirstFileExWrapper(_lpFileName_, FindExInfoStandard, _lpFindData_, FindExSearchNameMatch, NULL, 0) +#endif //FEATURE_PAL +//***************************************************************************** +// Prototypes for API's. +//***************************************************************************** + +extern DWORD g_dwMaxDBCSCharByteSize; + +void EnsureCharSetInfoInitialized(); + +inline DWORD GetMaxDBCSCharByteSize() +{ + // contract.h not visible here + __annotation(W("WRAPPER ") W("GetMaxDBCSCharByteSize")); +#ifndef FEATURE_PAL + EnsureCharSetInfoInitialized(); + + _ASSERTE(g_dwMaxDBCSCharByteSize != 0); + return (g_dwMaxDBCSCharByteSize); +#else // FEATURE_PAL + return 3; +#endif // FEATURE_PAL +} + +#ifndef FEATURE_PAL +BOOL RunningInteractive(); +#else // !FEATURE_PAL +#define RunningInteractive() FALSE +#endif // !FEATURE_PAL + +#ifndef Wsz_mbstowcs +#define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize) +#endif + +#ifndef Wsz_wcstombs +#define Wsz_wcstombs(szOut, szIn, iSize) WszWideCharToMultiByte(CP_ACP, 0, szIn, -1, szOut, iSize, 0, 0) +#endif + +// For all platforms: + +BOOL +WszCreateProcess( + LPCWSTR lpApplicationName, + LPCWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation + ); + +#if defined(_X86_) && defined(_MSC_VER) + +// +// Windows SDK does not use intrinsics on x86. Redefine the interlocked operations to use intrinsics. +// + +#include "intrin.h" + +#define InterlockedIncrement _InterlockedIncrement +#define InterlockedDecrement _InterlockedDecrement +#define InterlockedExchange _InterlockedExchange +#define InterlockedCompareExchange _InterlockedCompareExchange +#define InterlockedExchangeAdd _InterlockedExchangeAdd +#define InterlockedCompareExchange64 _InterlockedCompareExchange64 +#define InterlockedAnd _InterlockedAnd +#define InterlockedOr _InterlockedOr + +// +// There is no _InterlockedCompareExchangePointer intrinsic in VC++ for x86. +// winbase.h #defines InterlockedCompareExchangePointer as __InlineInterlockedCompareExchangePointer, +// which calls the Win32 InterlockedCompareExchange, not the intrinsic _InterlockedCompareExchange. +// We want the intrinsic, so we #undef the Windows version of this API, and define our own. +// +#ifdef InterlockedCompareExchangePointer +#undef InterlockedCompareExchangePointer +#endif + +FORCEINLINE +PVOID +InterlockedCompareExchangePointer ( + __inout PVOID volatile *Destination, + __in_opt PVOID ExChange, + __in_opt PVOID Comperand + ) +{ + return((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile *)Destination, (LONG)(LONG_PTR)ExChange, (LONG)(LONG_PTR)Comperand)); +} + +#endif // _X86_ && _MSC_VER + +#if defined(_ARM_) & !defined(FEATURE_PAL) +// +// InterlockedCompareExchangeAcquire/InterlockedCompareExchangeRelease is not mapped in SDK to the correct intrinsics. Remove once +// the SDK definition is fixed (OS Bug #516255) +// +#undef InterlockedCompareExchangeAcquire +#define InterlockedCompareExchangeAcquire _InterlockedCompareExchange_acq +#undef InterlockedCompareExchangeRelease +#define InterlockedCompareExchangeRelease _InterlockedCompareExchange_rel +#endif + +#if defined(_X86_) & !defined(InterlockedIncrement64) + +// Interlockedxxx64 that do not have intrinsics are only supported on Windows Server 2003 +// or higher for X86 so define our own portable implementation + +#undef InterlockedIncrement64 +#define InterlockedIncrement64 __InterlockedIncrement64 +#undef InterlockedDecrement64 +#define InterlockedDecrement64 __InterlockedDecrement64 +#undef InterlockedExchange64 +#define InterlockedExchange64 __InterlockedExchange64 +#undef InterlockedExchangeAdd64 +#define InterlockedExchangeAdd64 __InterlockedExchangeAdd64 + +__forceinline LONGLONG __InterlockedIncrement64(LONGLONG volatile *Addend) +{ + LONGLONG Old; + + do { + Old = *Addend; + } while (InterlockedCompareExchange64(Addend, + Old + 1, + Old) != Old); + + return Old + 1; +} + +__forceinline LONGLONG __InterlockedDecrement64(LONGLONG volatile *Addend) +{ + LONGLONG Old; + + do { + Old = *Addend; + } while (InterlockedCompareExchange64(Addend, + Old - 1, + Old) != Old); + + return Old - 1; +} + +__forceinline LONGLONG __InterlockedExchange64(LONGLONG volatile * Target, LONGLONG Value) +{ + LONGLONG Old; + + do { + Old = *Target; + } while (InterlockedCompareExchange64(Target, + Value, + Old) != Old); + + return Old; +} + +__forceinline LONGLONG __InterlockedExchangeAdd64(LONGLONG volatile * Addend, LONGLONG Value) +{ + LONGLONG Old; + + do { + Old = *Addend; + } while (InterlockedCompareExchange64(Addend, + Old + Value, + Old) != Old); + + return Old; +} + +#endif // _X86_ + +// Output printf-style formatted text to the debugger if it's present or stdout otherwise. +inline void DbgWPrintf(const LPCWSTR wszFormat, ...) +{ + WCHAR wszBuffer[4096]; + + va_list args; + va_start(args, wszFormat); + + _vsnwprintf_s(wszBuffer, sizeof(wszBuffer) / sizeof(WCHAR), _TRUNCATE, wszFormat, args); + + va_end(args); + + if (IsDebuggerPresent()) + { + OutputDebugStringW(wszBuffer); + } + else + { + fwprintf(stdout, W("%s"), wszBuffer); + fflush(stdout); + } +} + +typedef int (*MessageBoxWFnPtr)(HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType); + +inline int LateboundMessageBoxW(HWND hWnd, + LPCWSTR lpText, + LPCWSTR lpCaption, + UINT uType) +{ +#ifndef FEATURE_PAL + // User32 should exist on all systems where displaying a message box makes sense. + HMODULE hGuiExtModule = WszLoadLibrary(W("user32")); + if (hGuiExtModule) + { + int result = IDCANCEL; + MessageBoxWFnPtr fnptr = (MessageBoxWFnPtr)GetProcAddress(hGuiExtModule, "MessageBoxW"); + if (fnptr) + result = fnptr(hWnd, lpText, lpCaption, uType); + + FreeLibrary(hGuiExtModule); + return result; + } +#endif // !FEATURE_PAL + + // No luck. Output the caption and text to the debugger if present or stdout otherwise. + if (lpText == NULL) + lpText = W(""); + if (lpCaption == NULL) + lpCaption = W(""); + DbgWPrintf(W("**** MessageBox invoked, title '%s' ****\n"), lpCaption); + DbgWPrintf(W(" %s\n"), lpText); + DbgWPrintf(W("********\n")); + DbgWPrintf(W("\n")); + + // Indicate to the caller that message box was not actually displayed + SetLastError(ERROR_NOT_SUPPORTED); + return 0; +} + +inline int LateboundMessageBoxA(HWND hWnd, + LPCSTR lpText, + LPCSTR lpCaption, + UINT uType) +{ + if (lpText == NULL) + lpText = ""; + if (lpCaption == NULL) + lpCaption = ""; + + SIZE_T cchText = strlen(lpText) + 1; + LPWSTR wszText = (LPWSTR)_alloca(cchText * sizeof(WCHAR)); + swprintf_s(wszText, cchText, W("%S"), lpText); + + SIZE_T cchCaption = strlen(lpCaption) + 1; + LPWSTR wszCaption = (LPWSTR)_alloca(cchCaption * sizeof(WCHAR)); + swprintf_s(wszCaption, cchCaption, W("%S"), lpCaption); + + return LateboundMessageBoxW(hWnd, wszText, wszCaption, uType); +} + +#if defined(FEATURE_CORESYSTEM) && !defined(CROSSGEN_COMPILE) + +#define MessageBoxW LateboundMessageBoxW +#define MessageBoxA LateboundMessageBoxA + +#endif // FEATURE_CORESYSTEM + +#endif // __WIN_WRAP_H__ diff --git a/lib/coreclr/src/inc/xclrdata.idl b/lib/coreclr/src/inc/xclrdata.idl new file mode 100644 index 0000000000..fb3f19ade4 --- /dev/null +++ b/lib/coreclr/src/inc/xclrdata.idl @@ -0,0 +1,2552 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/***************************************************************************** + ** ** + ** clrdata.idl - Common Language Runtime data access interfaces for ** + ** clients needing to access runtime state from outside ** + ** runtime, such as out-of-process debuggers. ** + ** ** + ** The access interface defines two different types of code running: ** + ** The host is the user of the access interface. ** + ** The target is the target of the access. ** + ** ** + ** The host and target can be have different instruction sets, ** + ** pointer sizes, runtime versions and so on. ** + ** ** + *****************************************************************************/ + +import "clrdata.idl"; + +cpp_quote("#if 0") + +typedef UINT32 mdToken; +typedef mdToken mdTypeDef; +typedef mdToken mdMethodDef; +typedef mdToken mdFieldDef; + +typedef ULONG CorElementType; + +#define EXCEPTION_MAXIMUM_PARAMETERS 15 // maximum number of exception parameters + +// The following definition is pasted in from winnt.h, which doesn't +// import cleanly as a whole. +typedef struct _EXCEPTION_RECORD64 { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD64 ExceptionRecord; + DWORD64 ExceptionAddress; + DWORD NumberParameters; + DWORD __unusedAlignment; + DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; + +cpp_quote("#endif") + +/* ------------------------------------------------------------------------- * + * Forward declarations. + * ------------------------------------------------------------------------- */ + +/* + * The following interfaces (with an "IX" prefix instead of the conventional + * "I") are works in progress. They will change at least once before Whidbey + * ships. + */ + +#pragma warning(push) +#pragma warning(disable:28718) //Unable to annotate as this is not a local interface + +interface IXCLRDataProcess; +interface IXCLRDataAppDomain; +interface IXCLRDataAssembly; +interface IXCLRDataModule; +interface IXCLRDataModule2; + +interface IXCLRDataTypeDefinition; +interface IXCLRDataTypeInstance; +interface IXCLRDataMethodDefinition; +interface IXCLRDataMethodInstance; + +interface IXCLRDataTask; +interface IXCLRDataStackWalk; +interface IXCLRDataFrame; +interface IXCLRDataFrame2; + +interface IXCLRDataExceptionState; +interface IXCLRDataExceptionNotification; + +interface IXCLRDataValue; + +interface IXCLRDataTarget3; + +interface IXCLRDataDisplay; + +#pragma warning(pop) + +typedef struct +{ + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; +} CLRDATA_ADDRESS_RANGE; + +/* + * Many enumerators are based on an opaque state bundle. + */ +typedef ULONG64 CLRDATA_ENUM; + +/* + * Exception code used for notifications in this interface. + */ +cpp_quote("#define CLRDATA_NOTIFY_EXCEPTION 0xe0444143") + +/* + * General requests shared by two or more interfaces. + */ + +typedef enum +{ + CLRDATA_REQUEST_REVISION = 0xe0000000, +} CLRDataGeneralRequest; + +/* + * The following three sets of flags share + * many common definitions are so are + * grouped into a block. + */ + +typedef enum +{ + CLRDATA_TYPE_DEFAULT = 0x00000000, + + // Identify particular kinds of types. These flags + // are shared between type, field and value. + CLRDATA_TYPE_IS_PRIMITIVE = 0x00000001, + CLRDATA_TYPE_IS_VALUE_TYPE = 0x00000002, + CLRDATA_TYPE_IS_STRING = 0x00000004, + CLRDATA_TYPE_IS_ARRAY = 0x00000008, + CLRDATA_TYPE_IS_REFERENCE = 0x00000010, + CLRDATA_TYPE_IS_POINTER = 0x00000020, + CLRDATA_TYPE_IS_ENUM = 0x00000040, + + // Alias for all field kinds. + CLRDATA_TYPE_ALL_KINDS = 0x7f, +} CLRDataTypeFlag; + +typedef enum +{ + CLRDATA_FIELD_DEFAULT = 0x00000000, + + // Identify particular kinds of types. These flags + // are shared between type, field and value. + CLRDATA_FIELD_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, + CLRDATA_FIELD_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, + CLRDATA_FIELD_IS_STRING = CLRDATA_TYPE_IS_STRING, + CLRDATA_FIELD_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, + CLRDATA_FIELD_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, + CLRDATA_FIELD_IS_POINTER = CLRDATA_TYPE_IS_POINTER, + CLRDATA_FIELD_IS_ENUM = CLRDATA_TYPE_IS_ENUM, + + // Alias for all field kinds. + CLRDATA_FIELD_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, + + // Identify field properties. These flags are + // shared between field and value. + CLRDATA_FIELD_IS_INHERITED = 0x00000080, + CLRDATA_FIELD_IS_LITERAL = 0x00000100, + + // Identify field storage location. These flags are + // shared between field and value. + CLRDATA_FIELD_FROM_INSTANCE = 0x00000200, + CLRDATA_FIELD_FROM_TASK_LOCAL = 0x00000400, + CLRDATA_FIELD_FROM_STATIC = 0x00000800, + + // Alias for all types of field locations. + CLRDATA_FIELD_ALL_LOCATIONS = 0x00000e00, + // Alias for all fields from all locations. + CLRDATA_FIELD_ALL_FIELDS = 0x00000eff, +} CLRDataFieldFlag; + +typedef enum +{ + CLRDATA_VALUE_DEFAULT = 0x00000000, + + // Identify particular kinds of types. These flags + // are shared between type, field and value. + CLRDATA_VALUE_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, + CLRDATA_VALUE_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, + CLRDATA_VALUE_IS_STRING = CLRDATA_TYPE_IS_STRING, + CLRDATA_VALUE_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, + CLRDATA_VALUE_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, + CLRDATA_VALUE_IS_POINTER = CLRDATA_TYPE_IS_POINTER, + CLRDATA_VALUE_IS_ENUM = CLRDATA_TYPE_IS_ENUM, + + // Alias for all value kinds. + CLRDATA_VALUE_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, + + // Identify field properties. These flags are + // shared between field and value. + CLRDATA_VALUE_IS_INHERITED = CLRDATA_FIELD_IS_INHERITED, + CLRDATA_VALUE_IS_LITERAL = CLRDATA_FIELD_IS_LITERAL, + + // Identify field storage location. These flags are + // shared between field and value. + CLRDATA_VALUE_FROM_INSTANCE = CLRDATA_FIELD_FROM_INSTANCE, + CLRDATA_VALUE_FROM_TASK_LOCAL = CLRDATA_FIELD_FROM_TASK_LOCAL, + CLRDATA_VALUE_FROM_STATIC = CLRDATA_FIELD_FROM_STATIC, + + // Alias for all types of field locations. + CLRDATA_VALUE_ALL_LOCATIONS = CLRDATA_FIELD_ALL_LOCATIONS, + // Alias for all fields from all locations. + CLRDATA_VALUE_ALL_FIELDS = CLRDATA_FIELD_ALL_FIELDS, + + // Identify whether the value is a boxed object. + CLRDATA_VALUE_IS_BOXED = 0x00001000, +} CLRDataValueFlag; + +[ + object, + local, + uuid(59d9b5e1-4a6f-4531-84c3-51d12da22fd4), + pointer_default(unique) +] +interface IXCLRDataTarget3 : ICLRDataTarget2 +{ + /* + * Ask the target to recover metadata for + * an image. May not succeed. + */ + HRESULT GetMetaData([in] LPCWSTR imagePath, + [in] ULONG32 imageTimestamp, + [in] ULONG32 imageSize, + [in] GUID* mvid, + [in] ULONG32 mdRva, + [in] ULONG32 flags, + [in] ULONG32 bufferSize, + [out, size_is(bufferSize), length_is(*dataSize)] + BYTE* buffer, + [out] ULONG32* dataSize); +}; + +/* + * Flags used for *ByName methods. + */ +typedef enum +{ + CLRDATA_BYNAME_CASE_SENSITIVE = 0x00000000, + CLRDATA_BYNAME_CASE_INSENSITIVE = 0x00000001, +} CLRDataByNameFlag; + +/* + * Flags used in GetName methods. + */ +typedef enum +{ + CLRDATA_GETNAME_DEFAULT = 0x00000000, + CLRDATA_GETNAME_NO_NAMESPACES = 0x00000001, + CLRDATA_GETNAME_NO_PARAMETERS = 0x00000002, +} CLRDataGetNameFlag; + +typedef enum +{ + CLRDATA_PROCESS_DEFAULT = 0x00000000, + CLRDATA_PROCESS_IN_GC = 0x00000001, +} CLRDataProcessFlag; + +typedef enum +{ + CLRDATA_ADDRESS_UNRECOGNIZED, + CLRDATA_ADDRESS_MANAGED_METHOD, + CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE, + CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE, + CLRDATA_ADDRESS_GC_DATA, + CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB, + CLRDATA_ADDRESS_RUNTIME_UNMANAGED_STUB, +} CLRDataAddressType; + +typedef enum +{ + CLRDATA_NOTIFY_ON_MODULE_LOAD = 0x00000001, + CLRDATA_NOTIFY_ON_MODULE_UNLOAD = 0x00000002, + CLRDATA_NOTIFY_ON_EXCEPTION = 0x00000004, + CLRDATA_NOTIFY_ON_EXCEPTION_CATCH_ENTER = 0x00000008, +} CLRDataOtherNotifyFlag; + +/* + * Data buffer and flags for follow-stub data. + */ + +typedef struct +{ + ULONG64 Data[8]; +} CLRDATA_FOLLOW_STUB_BUFFER; + +typedef enum +{ + CLRDATA_FOLLOW_STUB_DEFAULT = 0x00000000, +} CLRDataFollowStubInFlag; + +typedef enum +{ + CLRDATA_FOLLOW_STUB_INTERMEDIATE = 0x00000000, + CLRDATA_FOLLOW_STUB_EXIT = 0x00000001, +} CLRDataFollowStubOutFlag; + +typedef enum +{ + CLRNATIVEIMAGE_PE_INFO = 0x00000001, + CLRNATIVEIMAGE_COR_INFO = 0x00000002, + CLRNATIVEIMAGE_FIXUP_TABLES = 0x00000004, + CLRNATIVEIMAGE_FIXUP_HISTOGRAM = 0x00000008, + CLRNATIVEIMAGE_MODULE = 0x00000010, + CLRNATIVEIMAGE_METHODS = 0x00000020, + CLRNATIVEIMAGE_DISASSEMBLE_CODE = 0x00000040, + CLRNATIVEIMAGE_IL = 0x00000080, + CLRNATIVEIMAGE_METHODTABLES = 0x00000100, + CLRNATIVEIMAGE_NATIVE_INFO = 0x00000200, + CLRNATIVEIMAGE_MODULE_TABLES = 0x00000400, + CLRNATIVEIMAGE_FROZEN_SEGMENT = 0x00000800, + CLRNATIVEIMAGE_PE_FILE = 0x00001000, + CLRNATIVEIMAGE_GC_INFO = 0x00002000, + CLRNATIVEIMAGE_EECLASSES = 0x00004000, + CLRNATIVEIMAGE_NATIVE_TABLES = 0x00008000, + CLRNATIVEIMAGE_PRECODES = 0x00010000, + CLRNATIVEIMAGE_TYPEDESCS = 0x00020000, + CLRNATIVEIMAGE_VERBOSE_TYPES = 0x00040000, + CLRNATIVEIMAGE_METHODDESCS = 0x00080000, + CLRNATIVEIMAGE_METADATA = 0x00100000, + CLRNATIVEIMAGE_DISABLE_NAMES = 0x00200000, + CLRNATIVEIMAGE_DISABLE_REBASING = 0x00400000, + CLRNATIVEIMAGE_SLIM_MODULE_TBLS = 0x00800000, + CLRNATIVEIMAGE_RESOURCES = 0x01000000, + CLRNATIVEIMAGE_FILE_OFFSET = 0x02000000, + CLRNATIVEIMAGE_DEBUG_TRACE = 0x04000000, + CLRNATIVEIMAGE_RELOCATIONS = 0x08000000, + CLRNATIVEIMAGE_FIXUP_THUNKS = 0x10000000, + CLRNATIVEIMAGE_DEBUG_COVERAGE = 0x80000000 +} CLRNativeImageDumpOptions; +cpp_quote("#ifdef __cplusplus") +cpp_quote("inline CLRNativeImageDumpOptions operator|=(CLRNativeImageDumpOptions& lhs, CLRNativeImageDumpOptions rhs) { return (lhs = (CLRNativeImageDumpOptions)( ((unsigned)lhs) | ((unsigned)rhs) )); }") +cpp_quote("#endif") +typedef enum +{ + CLRDATAHINT_DISPLAY_HINTS_NONE = 0, + //array hints 0x000000ff + CLRDATAHINT_DISPLAY_ARRAY_AS_TABLE = 0x00000001, + CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY = 0x00000002, + CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY_IDX = 0x00000003, //print idx as field 1 + CLRDATAHINT_DISPLAY_ARRAY_AS_MAP = 0x00000004, + CLRDATAHINT_DISPLAY_ARRAY_HINT_MASK = 0x000000ff, + + //structure hints + CLRDATAHINT_DISPLAY_STRUCT_AS_TABLE = 0x00000100, + CLRDATAHINT_DISPLAY_STRUCT_HINT_MASK = 0x0000ff00, + + //separate fields with tabs + CLRDATAHINT_DISPLAY_SEP_TAB = 0x00000000, + //separate fields with spaces + CLRDATAHINT_DISPLAY_SEP_SPACE = 0x01000000, + //separate first field by a tab, and all other fields with spaces + CLRDATAHINT_DISPLAY_SEP_TAB_SPACE = 0x02000000, + CLRDATAHINT_DISPLAY_SEP_MASK = 0xff000000, +} CLRDataDisplayHints; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning for interface IXCLRDataProcess */ + +/* + * This interface supports the loading of dependencies and processing of PE + * files for the NativeImageDumper. + */ +[ + object, + local, + uuid(E5F3039D-2C0C-4230-A69E-12AF1C3E563C) +] +interface IXCLRLibrarySupport : IUnknown +{ + //loads a dependency. It can fail if the image needs to be relocated. + HRESULT LoadHardboundDependency(const WCHAR * name, REFGUID mvid, + [out]SIZE_T *loadedBase); + HRESULT LoadSoftboundDependency(const WCHAR * name, + const BYTE * assemblymetadataBinding, + const BYTE * hash, ULONG hashLength, + [out]SIZE_T *loadedBase); +}; + +interface IXCLRDisassemblySupport; +typedef SIZE_T (__stdcall *CDSTranslateAddrCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, wchar_t *, SIZE_T, DWORDLONG *); +typedef SIZE_T (__stdcall *CDSTranslateFixupCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, SIZE_T, wchar_t *, SIZE_T, DWORDLONG *); +typedef SIZE_T (__stdcall *CDSTranslateConstCB)(IXCLRDisassemblySupport *, DWORD, wchar_t *, SIZE_T); +typedef SIZE_T (__stdcall *CDSTranslateRegrelCB)(IXCLRDisassemblySupport *, unsigned rega, CLRDATA_ADDRESS, wchar_t *, SIZE_T, DWORD *); + +[ + object, + local, + uuid(1F0F7134-D3F3-47DE-8E9B-C2FD358A2936) +] +interface IXCLRDisassemblySupport : IUnknown +{ + HRESULT SetTranslateAddrCallback([in] CDSTranslateAddrCB cb); + HRESULT PvClientSet([in] void * pv); + + SIZE_T CbDisassemble(CLRDATA_ADDRESS, const void *, SIZE_T); + SIZE_T Cinstruction(); + BOOL FSelectInstruction(SIZE_T); + SIZE_T CchFormatInstr(wchar_t *, SIZE_T); + void *PvClient(); + HRESULT SetTranslateFixupCallback([in]CDSTranslateFixupCB cb); + HRESULT SetTranslateConstCallback([in]CDSTranslateConstCB cb); + HRESULT SetTranslateRegrelCallback([in]CDSTranslateRegrelCB cb); + BOOL TargetIsAddress(); +}; + +/* + * This interface is passed to CLRDataCreateInstance::DumpNativeImage. It + * handles display of the logical data in the ngen image. + */ +[ + object, + local, + uuid(A3C1704A-4559-4a67-8D28-E8F4FE3B3F62) +] +interface IXCLRDataDisplay : IUnknown +{ + HRESULT ErrorPrintF(const char * const fmt, ...); + HRESULT NativeImageDimensions(SIZE_T base, SIZE_T size, DWORD sectionAlign); + HRESULT Section(const char * const name, SIZE_T rva, SIZE_T size); + HRESULT GetDumpOptions([out] CLRNativeImageDumpOptions * pOptions); + + //Start and end the document + HRESULT StartDocument(); + HRESULT EndDocument(); + + //XML-Constructs that do not map to actual fields or structures + + //A category is a top level section of the ngen output. For example, + //"Sections", "Directories", "CLR Info", etc. + HRESULT StartCategory(const char * const name); + HRESULT EndCategory(); + + //starts an element containing either xml text or other elements. Only + //used within arrays and lists. Otherwise use StartVStructure. + HRESULT StartElement(const char * const name); + HRESULT EndElement(); + //like a Structure, but without a name and size. Used within categories + //and structures. + HRESULT StartVStructure(const char * const name ); + HRESULT StartVStructureWithOffset( const char * const name, + unsigned fieldOffset, + unsigned fieldSize ); + HRESULT EndVStructure(); + + //An element that contains xml text. + HRESULT StartTextElement(const char * const name); + HRESULT EndTextElement(); + HRESULT WriteXmlText(const char * const fmt, ...); + HRESULT WriteXmlTextBlock(const char * const fmt, ...); + + HRESULT WriteEmptyElement(const char * const element); + + + //produces ptr + HRESULT WriteElementPointer(const char * const element, SIZE_T ptr); + HRESULT WriteElementPointerAnnotated(const char * const element, SIZE_T ptr, + const WCHAR * const annotation ); + //produces + HRESULT WriteElementAddress(const char * const element, SIZE_T base, SIZE_T size); + HRESULT WriteElementAddressNamed(const char * const element, const char * const name, + SIZE_T base, SIZE_T size); + HRESULT WriteElementAddressNamedW(const char * const element, const WCHAR * const name, + SIZE_T base, SIZE_T size); + HRESULT WriteElementString(const char * const element, const char * const data); + HRESULT WriteElementStringW(const char * const element, const WCHAR * const data); + HRESULT WriteElementInt(const char * const element, int value); + HRESULT WriteElementUInt(const char * const element, DWORD value); + HRESULT WriteElementEnumerated(const char * const element, DWORD value, + const WCHAR * const mnemonic); + //writes value if value != suppressIfEqual. + //in text mode the whole element is suppressed (and a "" is appended if + //inside an array or list. + HRESULT WriteElementIntWithSuppress( const char * const element, int value, + int suppressIfEqual ); + //For text, it produces "(element)" or "" instead of "true" or "false". + HRESULT WriteElementFlag(const char * const element, BOOL flag); + + //if countPrefix is not Null, displays a total at the end in text mode. + //Arrays have headings in both text and xml. Lists are "repeated elements" + HRESULT StartArray( const char * const name, const WCHAR * const fmt); + HRESULT EndArray( const char * const countPrefix ); + HRESULT StartList( const WCHAR * const fmt ); + HRESULT EndList(); + + //XML-Constructs that represent real C++ Data structure + HRESULT StartArrayWithOffset( const char * const name, unsigned fieldOffset, + unsigned fieldSize, const WCHAR * const fmt ); +#if 0 + + //writes value if value != suppressIfEqual. + //in text mode the whole element is suppressed (and a "" is appended if + //inside an array or list. + HRESULT WriteFieldIntWithSuppress( const char * const element, unsigned offset, + int value, int suppressIfEqual ); +#endif + + HRESULT WriteFieldString(const char * const element, unsigned fieldOffset, + unsigned fieldSize, const char * const data); + HRESULT WriteFieldStringW(const char * const element, unsigned fieldOffset, + unsigned fieldSize, const WCHAR * const data); + //produces ptr + HRESULT WriteFieldPointer(const char * const element, unsigned fieldOffset, + unsigned fieldSize, SIZE_T ptr); + //produces ptr+size + HRESULT WriteFieldPointerWithSize(const char * const element, + unsigned fieldOffset, unsigned fieldSize, + SIZE_T ptr, SIZE_T size); + HRESULT WriteFieldInt(const char * const element, unsigned fieldOffset, + unsigned fieldSize, int value); + HRESULT WriteFieldUInt(const char * const element, unsigned fieldOffset, + unsigned fieldSize, DWORD value); + HRESULT WriteFieldEnumerated(const char * const element, unsigned fieldOffset, + unsigned fieldSize, DWORD value, + const WCHAR * const mnemonic); + HRESULT WriteFieldEmpty(const char * const element, unsigned fieldOffset, + unsigned fieldSize); + HRESULT WriteFieldFlag(const char * const element, unsigned fieldOffset, + unsigned fieldSize, BOOL flag); + HRESULT WriteFieldPointerAnnotated(const char * const element, + unsigned fieldOffset, unsigned fieldSize, + SIZE_T ptr, const WCHAR * const annotation); + + //produces + HRESULT WriteFieldAddress(const char * const element, unsigned fieldOffset, + unsigned fieldSize, SIZE_T base, SIZE_T size); + //For text, it produces "(element)" or "" instead of "true" or "false". +#if 0 + HRESULT WriteFieldFlag(const char * const element, unsigned offset, BOOL flag); + HRESULT WriteFieldInt(const char * const element, unsigned offset, int value); + HRESULT WriteFieldUInt(const char * const element, unsigned offset, DWORD value); + + + HRESULT WriteFieldEnumerated(const char * const element, unsigned offset, + DWORD value, const WCHAR * const mnemonic); +#endif + //structures are like categories and elements, but they have a base and + //size. + HRESULT StartStructure( const char * const name, SIZE_T ptr, SIZE_T size ); + HRESULT StartStructureWithNegSpace( const char * const name, SIZE_T ptr, + SIZE_T startPtr, SIZE_T totalSize ); + HRESULT StartStructureWithOffset( const char * const name, unsigned fieldOffset, + unsigned fieldSize, SIZE_T ptr, + SIZE_T size ); + HRESULT EndStructure(); +#if 0 + //produces ptr+size + HRESULT WriteElementPointerWithSize(const char * const element, SIZE_T ptr, + SIZE_T size); + HRESULT WriteElementInt(const char * const element, int value); + + + HRESULT WriteFixupDescription(SIZE_T ptr, DWORD tagged, SIZE_T handle, + const char * const name ); + + + //structures are like categories and elements, but they have a base and + //size. + HRESULT StartStructure( const char * const name, SIZE_T ptr, SIZE_T size ); + HRESULT EndStructure(); + +#endif +}; + +/* + * Interface representing the process itself. Can be obtained via + * CLRDataCreateInstance. + */ +[ + object, + local, + uuid(5c552ab6-fc09-4cb3-8e36-22fa03c798b7) +] +interface IXCLRDataProcess : IUnknown +{ + /* + * Flush any cached data for this process. All ICLR* interfaces obtained + * for this process will become invalid with this call. + */ + HRESULT Flush(); + + /* + * Begin enumeration of tasks. + * Returns S_FALSE if the enumeration is empty. + */ + HRESULT StartEnumTasks([out] CLRDATA_ENUM* handle); + + /* + * Get the next entry in the enumeration. + * Returns S_FALSE if there isn't a next entry. + */ + HRESULT EnumTask([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTask** task); + + /* + * Release the enumerator. + */ + HRESULT EndEnumTasks([in] CLRDATA_ENUM handle); + + /* + * Get the managed task running on the given OS thread ID + */ + HRESULT GetTaskByOSThreadID([in] ULONG32 osThreadID, + [out] IXCLRDataTask** task); + + /* + * Get the managed task corresponding to the given task ID. + */ + HRESULT GetTaskByUniqueID([in] ULONG64 taskID, + [out] IXCLRDataTask** task); + + /* + * Get state flags, defined in CLRDataProcessFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataProcess* process); + + /* + * Get the managed object representing the process. + */ + HRESULT GetManagedObject([out] IXCLRDataValue** value); + + /* + * Mark the process so that it attempts to reach the + * desired execution state the next time it executes. + */ + HRESULT GetDesiredExecutionState([out] ULONG32* state); + HRESULT SetDesiredExecutionState([in] ULONG32 state); + + /* + * Return an indicator of the type of data referred + * to by the given address. + */ + HRESULT GetAddressType([in] CLRDATA_ADDRESS address, + [out] CLRDataAddressType* type); + + /* + * Get a name for the given address if + * the address refers to non-managed-method information. + * Method names can be retrieved by using GetMethodInstanceByAddress + * and GetName on the method instance. + * + * Returns S_FALSE if the buffer is not large enough for the name, + * and sets nameLen to be the buffer length needed. + */ + HRESULT GetRuntimeNameByAddress([in] CLRDATA_ADDRESS address, + [in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[], + [out] CLRDATA_ADDRESS* displacement); + + /* + * App domain enumeration. + */ + HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); + HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataAppDomain** appDomain); + HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); + + /* + * Find an app domain by its unique ID. + */ + HRESULT GetAppDomainByUniqueID([in] ULONG64 id, + [out] IXCLRDataAppDomain** appDomain); + + /* + * Assembly enumeration. + */ + HRESULT StartEnumAssemblies([out] CLRDATA_ENUM* handle); + HRESULT EnumAssembly([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataAssembly **assembly); + HRESULT EndEnumAssemblies([in] CLRDATA_ENUM handle); + + /* + * Module enumeration. + */ + HRESULT StartEnumModules([out] CLRDATA_ENUM* handle); + HRESULT EnumModule([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataModule **mod); + HRESULT EndEnumModules([in] CLRDATA_ENUM handle); + + /* + * Look up a module by address. + */ + HRESULT GetModuleByAddress([in] CLRDATA_ADDRESS address, + [out] IXCLRDataModule** mod); + + /* + * Look up method instances by native code address. + */ + HRESULT StartEnumMethodInstancesByAddress([in] CLRDATA_ADDRESS address, + [in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodInstanceByAddress([in] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodInstance** method); + HRESULT EndEnumMethodInstancesByAddress([in] CLRDATA_ENUM handle); + + /* + * Look up the name and value of a piece of data by its address. + */ + HRESULT GetDataByAddress([in] CLRDATA_ADDRESS address, + [in] ULONG32 flags, + [in] IXCLRDataAppDomain* appDomain, + [in] IXCLRDataTask* tlsTask, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[], + [out] IXCLRDataValue** value, + [out] CLRDATA_ADDRESS* displacement); + + /* + * Get managed state, if any, for the given system exception. + * OBSOLETE, DO NOT USE. + */ + HRESULT GetExceptionStateByExceptionRecord([in] EXCEPTION_RECORD64* record, + [out] IXCLRDataExceptionState **exState); + + /* + * Translate a system exception record into + * a particular kind of notification if possible. + */ + HRESULT TranslateExceptionRecordToNotification([in] EXCEPTION_RECORD64* record, + [in] IXCLRDataExceptionNotification* notify); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Create a simple value based on the given + * type and address information. + */ + HRESULT CreateMemoryValue([in] IXCLRDataAppDomain* appDomain, + [in] IXCLRDataTask* tlsTask, + [in] IXCLRDataTypeInstance* type, + [in] CLRDATA_ADDRESS addr, + [out] IXCLRDataValue** value); + + /* + * Update all existing notifications for a module. + * If module is NULL all modules are affected. + */ + HRESULT SetAllTypeNotifications(IXCLRDataModule* mod, + ULONG32 flags); + HRESULT SetAllCodeNotifications(IXCLRDataModule* mod, + ULONG32 flags); + + /* + * Request notification when a type is + * loaded or unloaded. + * If mods is NULL singleMod is used as + * the module for all tokens. + * If flags is NULL singleFlags is used as + * the flags for all tokens. + */ + HRESULT GetTypeNotifications([in] ULONG32 numTokens, + [in, size_is(numTokens)] + IXCLRDataModule* mods[], + [in] IXCLRDataModule* singleMod, + [in, size_is(numTokens)] mdTypeDef tokens[], + [out, size_is(numTokens)] ULONG32 flags[]); + HRESULT SetTypeNotifications([in] ULONG32 numTokens, + [in, size_is(numTokens)] + IXCLRDataModule* mods[], + [in] IXCLRDataModule* singleMod, + [in, size_is(numTokens)] mdTypeDef tokens[], + [in, size_is(numTokens)] ULONG32 flags[], + [in] ULONG32 singleFlags); + + /* + * Request notification when code is generated or + * discarded for a method. + * If mods is NULL singleMod is used as + * the module for all tokens. + * If flags is NULL singleFlags is used as + * the flags for all tokens. + */ + HRESULT GetCodeNotifications([in] ULONG32 numTokens, + [in, size_is(numTokens)] + IXCLRDataModule* mods[], + [in] IXCLRDataModule* singleMod, + [in, size_is(numTokens)] mdMethodDef tokens[], + [out, size_is(numTokens)] ULONG32 flags[]); + HRESULT SetCodeNotifications([in] ULONG32 numTokens, + [in, size_is(numTokens)] + IXCLRDataModule* mods[], + [in] IXCLRDataModule* singleMod, + [in, size_is(numTokens)] mdMethodDef tokens[], + [in, size_is(numTokens)] ULONG32 flags[], + [in] ULONG32 singleFlags); + + /* + * Control notifications other than code and + * type notifications. + */ + HRESULT GetOtherNotificationFlags([out] ULONG32* flags); + HRESULT SetOtherNotificationFlags([in] ULONG32 flags); + + /* + * Look up method definitions by IL code address. + */ + HRESULT StartEnumMethodDefinitionsByAddress([in] CLRDATA_ADDRESS address, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodDefinitionByAddress([in] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodDefinition** method); + HRESULT EndEnumMethodDefinitionsByAddress([in] CLRDATA_ENUM handle); + + /* + * Given an address which is a CLR stub + * (and potentially state from a previous follow) + * determine the next execution address at which + * to check whether the stub has been exited. + * OBSOLETE: Use FollowStub2. + */ + HRESULT FollowStub([in] ULONG32 inFlags, + [in] CLRDATA_ADDRESS inAddr, + [in] CLRDATA_FOLLOW_STUB_BUFFER* inBuffer, + [out] CLRDATA_ADDRESS* outAddr, + [out] CLRDATA_FOLLOW_STUB_BUFFER* outBuffer, + [out] ULONG32* outFlags); + + /* Requires revision 7. */ + HRESULT FollowStub2([in] IXCLRDataTask* task, + [in] ULONG32 inFlags, + [in] CLRDATA_ADDRESS inAddr, + [in] CLRDATA_FOLLOW_STUB_BUFFER* inBuffer, + [out] CLRDATA_ADDRESS* outAddr, + [out] CLRDATA_FOLLOW_STUB_BUFFER* outBuffer, + [out] ULONG32* outFlags); + HRESULT DumpNativeImage([in] CLRDATA_ADDRESS loadedBase, + [in] LPCWSTR name, + [in] IXCLRDataDisplay* display, + [in] IXCLRLibrarySupport* libSupport, + [in] IXCLRDisassemblySupport* dis); +} +#pragma warning(pop) + +/* + * Types used in IXCLRDataProcess2 and IXCLRDataExceptionNotification3 + */ + +typedef enum +{ + GC_MARK_END = 1, + GC_EVENT_TYPE_MAX, +} GcEvt_t; + +typedef struct +{ + GcEvt_t typ; + + [switch_is(typ)] + union + { + [case(GC_MARK_END)] + int condemnedGeneration; + }; +} GcEvtArgs; + + +[ + object, + local, + uuid(5c552ab6-fc09-4cb3-8e36-22fa03c798b8) +] +interface IXCLRDataProcess2 : IXCLRDataProcess +{ + /* + * Request notification when a GC is triggered. + * GcEvtArgs specifies exactly which GC events + * are of interest. + */ + /* + * On entry gcEvtArgs is a mask, specifying all events of + * interest, in accordance with GcNotification::IsMatch + * On exit it represents the first entry matching the input. + */ + HRESULT GetGcNotification([in, out] GcEvtArgs* gcEvtArgs); + HRESULT SetGcNotification([in] GcEvtArgs gcEvtArgs); +} + +typedef enum +{ + CLRDATA_DOMAIN_DEFAULT = 0x00000000, +} CLRDataAppDomainFlag; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataAppDomain */ +[ + object, + local, + uuid(7CA04601-C702-4670-A63C-FA44F7DA7BD5) +] +interface IXCLRDataAppDomain : IUnknown +{ + /* + * Get the process that contains this app domain. + */ + HRESULT GetProcess([out] IXCLRDataProcess** process); + + /* + * Get the app domain's name. + */ + HRESULT GetName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get a unique, stable identifier for this object. + */ + HRESULT GetUniqueID([out] ULONG64* id); + + /* + * Get state flags, defined in CLRDataAppDomainFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataAppDomain* appDomain); + + /* + * Get the managed object representing the app domain. + */ + HRESULT GetManagedObject([out] IXCLRDataValue** value); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); +} +#pragma warning(pop) + +typedef enum +{ + CLRDATA_ASSEMBLY_DEFAULT = 0x00000000, +} CLRDataAssemblyFlag; + +#pragma warning(push) +#pragma warning(disable:28718) +[ + object, + local, + uuid(2FA17588-43C2-46ab-9B51-C8F01E39C9AC) +] +interface IXCLRDataAssembly : IUnknown +{ + /* + * Enumerate modules in the assembly. + */ + HRESULT StartEnumModules([out] CLRDATA_ENUM* handle); + HRESULT EnumModule([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataModule **mod); + HRESULT EndEnumModules([in] CLRDATA_ENUM handle); + + /* + * Get the assembly's base name. + */ + HRESULT GetName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get the full path and filename for the assembly, + * if there is one. + */ + HRESULT GetFileName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get state flags, defined in CLRDataAssemblyFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataAssembly* assembly); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Enumerate the app domains using this assembly. + */ + HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); + HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataAppDomain** appDomain); + HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); + + /* + * Get the metadata display name for the assembly. + * Requires revision 2. + */ + HRESULT GetDisplayName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); +} +#pragma warning(pop) + +typedef enum +{ + CLRDATA_MODULE_DEFAULT = 0x00000000, + CLRDATA_MODULE_IS_DYNAMIC = 0x00000001, + CLRDATA_MODULE_IS_MEMORY_STREAM = 0x00000002, +} CLRDataModuleFlag; + +typedef enum +{ + CLRDATA_MODULE_PE_FILE, + CLRDATA_MODULE_PREJIT_FILE, + CLRDATA_MODULE_MEMORY_STREAM, + CLRDATA_MODULE_OTHER +} CLRDataModuleExtentType; + +typedef struct +{ + CLRDATA_ADDRESS base; + ULONG32 length; + CLRDataModuleExtentType type; +} CLRDATA_MODULE_EXTENT; + +typedef enum +{ + CLRDATA_TYPENOTIFY_NONE = 0x00000000, + CLRDATA_TYPENOTIFY_LOADED = 0x00000001, + CLRDATA_TYPENOTIFY_UNLOADED = 0x00000002, +} CLRDataTypeNotification; + +typedef enum +{ + CLRDATA_METHNOTIFY_NONE = 0x00000000, + CLRDATA_METHNOTIFY_GENERATED = 0x00000001, + CLRDATA_METHNOTIFY_DISCARDED = 0x00000002, +} CLRDataMethodCodeNotification; + +#pragma warning(push) +#pragma warning(disable:28718) +/* + * Represents a loaded module. + * + * Can be QI'd for a metadata interface or a symbol-store interface. + */ +[ + object, + local, + uuid(88E32849-0A0A-4cb0-9022-7CD2E9E139E2) +] +interface IXCLRDataModule : IUnknown +{ + /* + * Enumerate assemblies this module is part of. + * Module-to-assembly is an enumeration as a + * shared module might be part of more than one assembly. + */ + HRESULT StartEnumAssemblies([out] CLRDATA_ENUM* handle); + HRESULT EnumAssembly([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataAssembly **assembly); + HRESULT EndEnumAssemblies([in] CLRDATA_ENUM handle); + + /* + * Enumerate types in this module. + */ + HRESULT StartEnumTypeDefinitions([out] CLRDATA_ENUM* handle); + HRESULT EnumTypeDefinition([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeDefinition **typeDefinition); + HRESULT EndEnumTypeDefinitions([in] CLRDATA_ENUM handle); + + HRESULT StartEnumTypeInstances([in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumTypeInstance([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeInstance **typeInstance); + HRESULT EndEnumTypeInstances([in] CLRDATA_ENUM handle); + + /* + * Look up types by name. + */ + HRESULT StartEnumTypeDefinitionsByName([in] LPCWSTR name, + [in] ULONG32 flags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumTypeDefinitionByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeDefinition** type); + HRESULT EndEnumTypeDefinitionsByName([in] CLRDATA_ENUM handle); + + HRESULT StartEnumTypeInstancesByName([in] LPCWSTR name, + [in] ULONG32 flags, + [in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumTypeInstanceByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeInstance** type); + HRESULT EndEnumTypeInstancesByName([in] CLRDATA_ENUM handle); + + /* + * Get a type definition by metadata token. + */ + HRESULT GetTypeDefinitionByToken([in] mdTypeDef token, + [out] IXCLRDataTypeDefinition** typeDefinition); + + /* + * Look up methods by name. + */ + HRESULT StartEnumMethodDefinitionsByName([in] LPCWSTR name, + [in] ULONG32 flags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodDefinitionByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodDefinition** method); + HRESULT EndEnumMethodDefinitionsByName([in] CLRDATA_ENUM handle); + + HRESULT StartEnumMethodInstancesByName([in] LPCWSTR name, + [in] ULONG32 flags, + [in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodInstance** method); + HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); + + /* + * Get a method definition by metadata token. + */ + HRESULT GetMethodDefinitionByToken([in] mdMethodDef token, + [out] IXCLRDataMethodDefinition** methodDefinition); + + /* + * Look up pieces of data by name. + */ + HRESULT StartEnumDataByName([in] LPCWSTR name, + [in] ULONG32 flags, + [in] IXCLRDataAppDomain* appDomain, + [in] IXCLRDataTask* tlsTask, + [out] CLRDATA_ENUM* handle); + HRESULT EnumDataByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value); + HRESULT EndEnumDataByName([in] CLRDATA_ENUM handle); + + /* + * Get the module's base name. + */ + HRESULT GetName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get the full path and filename for the module, + * if there is one. + */ + HRESULT GetFileName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get state flags, defined in CLRDataModuleFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataModule* mod); + + /* + * Get the memory regions associated with this module. + */ + HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); + HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, + [out] CLRDATA_MODULE_EXTENT* extent); + HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Enumerate the app domains using this module. + */ + HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); + HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataAppDomain** appDomain); + HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); + + /* + * Get the module's version ID. + * Requires revision 3. + */ + HRESULT GetVersionId([out] GUID* vid); +} +#pragma warning(pop) + + +/* + * Represents additional APIs for a loaded module. + * + */ +[ + object, + local, + uuid(34625881-7EB3-4524-817B-8DB9D064C760) +] +interface IXCLRDataModule2 : IUnknown +{ + /* + * SetJITCompilerFlags sets the flags that control the JIT compiler. If the set of flags is invalid, + * the function will fail. This function can only be called from within the LoadModule callback + * for the given module. + */ + HRESULT SetJITCompilerFlags( [in] DWORD dwFlags ); +} + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataTypeDefinition */ +[ + object, + local, + uuid(4675666C-C275-45b8-9F6C-AB165D5C1E09) +] +interface IXCLRDataTypeDefinition : IUnknown +{ + /* + * Get the module this type is part of. + */ + HRESULT GetModule([out] IXCLRDataModule **mod); + + /* + * Enumerate the methods for this type. + */ + HRESULT StartEnumMethodDefinitions([out] CLRDATA_ENUM* handle); + HRESULT EnumMethodDefinition([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodDefinition **methodDefinition); + HRESULT EndEnumMethodDefinitions([in] CLRDATA_ENUM handle); + + /* + * Look up methods by name. + */ + HRESULT StartEnumMethodDefinitionsByName([in] LPCWSTR name, + [in] ULONG32 flags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodDefinitionByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodDefinition** method); + HRESULT EndEnumMethodDefinitionsByName([in] CLRDATA_ENUM handle); + + /* + * Get a method definition by metadata token. + */ + HRESULT GetMethodDefinitionByToken([in] mdMethodDef token, + [out] IXCLRDataMethodDefinition** methodDefinition); + + /* + * Enumerate instances of this definition. + */ + HRESULT StartEnumInstances([in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumInstance([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeInstance **instance); + HRESULT EndEnumInstances([in] CLRDATA_ENUM handle); + + /* + * Get the namespace-qualified name for this type definition. + */ + HRESULT GetName([in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Get the metadata token and scope. + */ + HRESULT GetTokenAndScope([out] mdTypeDef* token, + [out] IXCLRDataModule **mod); + + /* + * Get standard element type. + */ + HRESULT GetCorElementType([out] CorElementType* type); + + /* + * Get state flags, defined in CLRDataTypeFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataTypeDefinition* type); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * If this is an array type, return the number + * of dimensions in the array. + */ + HRESULT GetArrayRank([out] ULONG32* rank); + + /* + * Get the base type of this type, if any. + */ + HRESULT GetBase([out] IXCLRDataTypeDefinition** base); + + /* + * Get the number of fields in the type. + */ + HRESULT GetNumFields([in] ULONG32 flags, + [out] ULONG32* numFields); + + /* + * Enumerate the fields for this type. + * OBSOLETE: Use EnumField2. + */ + HRESULT StartEnumFields([in] ULONG32 flags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumField([in, out] CLRDATA_ENUM* handle, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags, + [out] mdFieldDef* token); + HRESULT EndEnumFields([in] CLRDATA_ENUM handle); + + HRESULT StartEnumFieldsByName([in] LPCWSTR name, + [in] ULONG32 nameFlags, + [in] ULONG32 fieldFlags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumFieldByName([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags, + [out] mdFieldDef* token); + HRESULT EndEnumFieldsByName([in] CLRDATA_ENUM handle); + + /* + * Look up information for a specific field by token. + */ + HRESULT GetFieldByToken([in] mdFieldDef token, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags); + + /* + * Request notification when the given type is + * loaded or unloaded. + */ + HRESULT GetTypeNotification([out] ULONG32* flags); + HRESULT SetTypeNotification([in] ULONG32 flags); + + HRESULT EnumField2([in, out] CLRDATA_ENUM* handle, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags, + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT EnumFieldByName2([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags, + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT GetFieldByToken2([in] IXCLRDataModule* tokenScope, + [in] mdFieldDef token, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] IXCLRDataTypeDefinition** type, + [out] ULONG32* flags); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable:28718) +[ + object, + local, + uuid(4D078D91-9CB3-4b0d-97AC-28C8A5A82597) +] +interface IXCLRDataTypeInstance : IUnknown +{ + /* + * Enumerate method instances within this type. + */ + HRESULT StartEnumMethodInstances([out] CLRDATA_ENUM* handle); + HRESULT EnumMethodInstance([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodInstance** methodInstance); + HRESULT EndEnumMethodInstances([in] CLRDATA_ENUM handle); + + /* + * Look up method instances by name. + */ + HRESULT StartEnumMethodInstancesByName([in] LPCWSTR name, + [in] ULONG32 flags, + [out] CLRDATA_ENUM* handle); + HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodInstance** method); + HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); + + /* + * Get the number of static fields in the type. + * OBSOLETE: Use GetNumStaticFields2. + */ + HRESULT GetNumStaticFields([out] ULONG32* numFields); + + /* + * Get one static field of the type. + * + * Because static field ordering is not fixed, can also return name + * information and/or the metadata token, if the caller passes + * in appropriate values. + * OBSOLETE: Use EnumStaticField. + */ + HRESULT GetStaticFieldByIndex([in] ULONG32 index, + [in] IXCLRDataTask* tlsTask, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[], + [out] mdFieldDef* token); + + /* + * Look up fields by name. + * OBSOLETE: Use EnumStaticFieldByName2. + */ + HRESULT StartEnumStaticFieldsByName([in] LPCWSTR name, + [in] ULONG32 flags, + [in] IXCLRDataTask* tlsTask, + [out] CLRDATA_ENUM* handle); + HRESULT EnumStaticFieldByName([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value); + HRESULT EndEnumStaticFieldsByName([in] CLRDATA_ENUM handle); + + /* + * Enumerate this type's parameterization. + */ + HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); + HRESULT GetTypeArgumentByIndex([in] ULONG32 index, + [out] IXCLRDataTypeInstance** typeArg); + + /* + * Get the fully qualified name for this type instance. + */ + HRESULT GetName([in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Get the module for this type instance. + */ + HRESULT GetModule([out] IXCLRDataModule **mod); + + /* + * Get the definition matching this instance. + */ + HRESULT GetDefinition([out] IXCLRDataTypeDefinition **typeDefinition); + + /* + * Get state flags, defined in CLRDataTypeFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataTypeInstance* type); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Get the number of static fields in the type. + */ + HRESULT GetNumStaticFields2([in] ULONG32 flags, + [out] ULONG32* numFields); + + /* + * Enumerate values for the static fields of this type. + */ + HRESULT StartEnumStaticFields([in] ULONG32 flags, + [in] IXCLRDataTask* tlsTask, + [out] CLRDATA_ENUM* handle); + HRESULT EnumStaticField([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value); + HRESULT EndEnumStaticFields([in] CLRDATA_ENUM handle); + + HRESULT StartEnumStaticFieldsByName2([in] LPCWSTR name, + [in] ULONG32 nameFlags, + [in] ULONG32 fieldFlags, + [in] IXCLRDataTask* tlsTask, + [out] CLRDATA_ENUM* handle); + HRESULT EnumStaticFieldByName2([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value); + HRESULT EndEnumStaticFieldsByName2([in] CLRDATA_ENUM handle); + + /* + * Retrieve a static field by field metadata token. + */ + HRESULT GetStaticFieldByToken([in] mdFieldDef token, + [in] IXCLRDataTask* tlsTask, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Get the base type of this type, if any. + */ + HRESULT GetBase([out] IXCLRDataTypeInstance** base); + + HRESULT EnumStaticField2([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[], + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT EnumStaticFieldByName3([in,out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** value, + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT GetStaticFieldByToken2([in] IXCLRDataModule* tokenScope, + [in] mdFieldDef token, + [in] IXCLRDataTask* tlsTask, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); +} +#pragma warning(pop) + +typedef enum +{ + CLRDATA_SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies +} CLRDataSourceType; + +/* + * Special IL offset values for special regions. + */ +typedef enum +{ + CLRDATA_IL_OFFSET_NO_MAPPING = -1, + CLRDATA_IL_OFFSET_PROLOG = -2, + CLRDATA_IL_OFFSET_EPILOG = -3 +} CLRDATA_IL_OFFSET_MARKER; + +typedef struct +{ + ULONG32 ilOffset; + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; + CLRDataSourceType type; +} CLRDATA_IL_ADDRESS_MAP; + +typedef enum +{ + CLRDATA_METHOD_DEFAULT = 0x00000000, + + // Method has a 'this' pointer. + CLRDATA_METHOD_HAS_THIS = 0x00000001, +} CLRDataMethodFlag; + +typedef enum +{ + CLRDATA_METHDEF_IL +} CLRDataMethodDefinitionExtentType; + +typedef struct +{ + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; + ULONG32 enCVersion; + CLRDataMethodDefinitionExtentType type; +} CLRDATA_METHDEF_EXTENT; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodDefinition */ +[ + object, + local, + uuid(AAF60008-FB2C-420b-8FB1-42D244A54A97) +] +interface IXCLRDataMethodDefinition : IUnknown +{ + /* + * Get the type this method is part of. + */ + HRESULT GetTypeDefinition([out] IXCLRDataTypeDefinition **typeDefinition); + + /* + * Enumerate instances of this definition. + */ + HRESULT StartEnumInstances([in] IXCLRDataAppDomain* appDomain, + [out] CLRDATA_ENUM* handle); + HRESULT EnumInstance([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataMethodInstance **instance); + HRESULT EndEnumInstances([in] CLRDATA_ENUM handle); + + /* + * Get the method's name. + */ + HRESULT GetName([in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get the metadata token and scope. + */ + HRESULT GetTokenAndScope([out] mdMethodDef* token, + [out] IXCLRDataModule **mod); + + /* + * Get state flags, defined in CLRDataMethodFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataMethodDefinition* method); + + /* + * Get the latest EnC version of this method. + */ + HRESULT GetLatestEnCVersion([out] ULONG32* version); + + /* + * Get the IL code regions associated with this method. + */ + HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); + HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, + [out] CLRDATA_METHDEF_EXTENT* extent); + HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); + + /* + * Request notification when code is generated or + * discarded for the method. + */ + HRESULT GetCodeNotification([out] ULONG32* flags); + HRESULT SetCodeNotification([in] ULONG32 flags); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Gets the most representative start address of + * the native code for this method. + * A method may have multiple entry points, so this + * address is not guaranteed to be hit by all entries. + * Requires revision 1. + */ + HRESULT GetRepresentativeEntryAddress([out] CLRDATA_ADDRESS* addr); + + HRESULT HasClassOrMethodInstantiation([out] BOOL* bGeneric); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodInstance */ +[ + object, + local, + uuid(ECD73800-22CA-4b0d-AB55-E9BA7E6318A5) +] +interface IXCLRDataMethodInstance : IUnknown +{ + /* + * Get the type instance for this method. + */ + HRESULT GetTypeInstance([out] IXCLRDataTypeInstance **typeInstance); + + /* + * Get the definition that matches this instance. + */ + HRESULT GetDefinition([out] IXCLRDataMethodDefinition **methodDefinition); + + /* + * Get the metadata token and scope. + */ + HRESULT GetTokenAndScope([out] mdMethodDef* token, + [out] IXCLRDataModule **mod); + + /* + * Get the fully qualified name for this method instance. + */ + HRESULT GetName([in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Get state flags, defined in CLRDataMethodFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataMethodInstance* method); + + /* + * Get the EnC version of this instance. + */ + HRESULT GetEnCVersion([out] ULONG32* version); + + /* + * Enumerate this method's parameterization. + */ + HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); + HRESULT GetTypeArgumentByIndex([in] ULONG32 index, + [out] IXCLRDataTypeInstance** typeArg); + + /* + * Access the IL <-> address mapping information. + */ + HRESULT GetILOffsetsByAddress([in] CLRDATA_ADDRESS address, + [in] ULONG32 offsetsLen, + [out] ULONG32 *offsetsNeeded, + [out, size_is(offsetsLen)] + ULONG32 ilOffsets[]); + HRESULT GetAddressRangesByILOffset([in] ULONG32 ilOffset, + [in] ULONG32 rangesLen, + [out] ULONG32 *rangesNeeded, + [out, size_is(rangesLen)] + CLRDATA_ADDRESS_RANGE addressRanges[]); + HRESULT GetILAddressMap([in] ULONG32 mapLen, + [out] ULONG32 *mapNeeded, + [out, size_is(mapLen)] + CLRDATA_IL_ADDRESS_MAP maps[]); + + /* + * Get the native code regions associated with this method. + */ + HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); + HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, + [out] CLRDATA_ADDRESS_RANGE* extent); + HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Gets the most representative start address of + * the native code for this method. + * A method may have multiple entry points, so this + * address is not guaranteed to be hit by all entries. + * Requires revision 1. + */ + HRESULT GetRepresentativeEntryAddress([out] CLRDATA_ADDRESS* addr); +} +#pragma warning(pop) + +typedef enum +{ + CLRDATA_TASK_DEFAULT = 0x00000000, + CLRDATA_TASK_WAITING_FOR_GC = 0x00000001, +} CLRDataTaskFlag; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodInstance */ +/* + * Interface representing a task (thread or fiber) in the process. + */ +[ + object, + local, + uuid(A5B0BEEA-EC62-4618-8012-A24FFC23934C) +] +interface IXCLRDataTask : IUnknown +{ + /* + * Get the process for this task. + */ + HRESULT GetProcess([out] IXCLRDataProcess** process); + + /* + * Get the application domain that the task is + * currently running in. This can change over time. + */ + HRESULT GetCurrentAppDomain([out] IXCLRDataAppDomain **appDomain); + + /* + * Get a unique, stable identifier for this task. + */ + HRESULT GetUniqueID([out] ULONG64* id); + + /* + * Get state flags, defined in CLRDataTaskFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Determine whether the given interface represents + * the same target state. + */ + HRESULT IsSameObject([in] IXCLRDataTask* task); + + /* + * Get the managed object representing the task. + */ + HRESULT GetManagedObject([out] IXCLRDataValue** value); + + /* + * Mark the task so that it attempts to reach the + * given execution state the next time it executes. + */ + HRESULT GetDesiredExecutionState([out] ULONG32* state); + HRESULT SetDesiredExecutionState([in] ULONG32 state); + + /* + * Create a stack walker to walk this task's stack. The + * flags parameter takes a bitfield of values from the + * CLRDataSimpleFrameType enum. + */ + HRESULT CreateStackWalk([in] ULONG32 flags, + [out] IXCLRDataStackWalk** stackWalk); + + /* + * Get the current OS thread ID for this task. If this task is on a fiber, + * the ID may change over time. + */ + HRESULT GetOSThreadID([out] ULONG32* id); + + /* + * Get the current context for this task, controlled by the given flags. + * Returns S_FALSE if the size is not large enough. + */ + HRESULT GetContext([in] ULONG32 contextFlags, + [in] ULONG32 contextBufSize, + [out] ULONG32* contextSize, + [out, size_is(contextBufSize)] BYTE contextBuf[]); + + /* + * Destructively set the current context for this task. + */ + HRESULT SetContext([in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE context[]); + + /* + * Get the current exception state for the + * task, if any. This may be the first element + * in a list of exception states if there are + * nested exceptions. + */ + HRESULT GetCurrentExceptionState([out] IXCLRDataExceptionState **exception); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Get the task's name if it has one. + * Requires revision 1. + */ + HRESULT GetName([in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get the last exception state for the + * task, if any. If an exception is currently + * being processed the last exception state may + * be the same as the current exception state. + * Requires revision 2. + */ + HRESULT GetLastExceptionState([out] IXCLRDataExceptionState **exception); +} +#pragma warning(pop) + +typedef enum +{ + /* Frame not recognized */ + CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, + + /* Frame corresponds to a managed method */ + CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, + + /* Frame corresponds to runtime-controlled managed code */ + CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, + + /* Frame corresponds to runtime-controlled unmanaged code */ + CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE = 0x8 +} CLRDataSimpleFrameType; + +typedef enum +{ + /* These are tentative values...they will likely change as + * implementation progresses. */ + CLRDATA_DETFRAME_UNRECOGNIZED, + CLRDATA_DETFRAME_UNKNOWN_STUB, + CLRDATA_DETFRAME_CLASS_INIT, + CLRDATA_DETFRAME_EXCEPTION_FILTER, + CLRDATA_DETFRAME_SECURITY, + CLRDATA_DETFRAME_CONTEXT_POLICY, + CLRDATA_DETFRAME_INTERCEPTION, + CLRDATA_DETFRAME_PROCESS_START, + CLRDATA_DETFRAME_THREAD_START, + CLRDATA_DETFRAME_TRANSITION_TO_MANAGED, + CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED, + CLRDATA_DETFRAME_COM_INTEROP_STUB, + CLRDATA_DETFRAME_DEBUGGER_EVAL, + CLRDATA_DETFRAME_CONTEXT_SWITCH, + CLRDATA_DETFRAME_FUNC_EVAL, + CLRDATA_DETFRAME_FINALLY + /* There will be others */ +} CLRDataDetailedFrameType; + +/* + * StackWalk requests. + */ + +typedef enum +{ + CLRDATA_STACK_WALK_REQUEST_SET_FIRST_FRAME = 0xe1000000, +} CLRDataStackWalkRequest; + +/* + * SetContext flags. + */ + +typedef enum +{ + /* Context being set is the result of stack unwinding. */ + CLRDATA_STACK_SET_UNWIND_CONTEXT = 0x00000000, + /* Context being set is the "current" context. */ + CLRDATA_STACK_SET_CURRENT_CONTEXT = 0x00000001, +} CLRDataStackSetContextFlag; + +/* + * Stack-walker interface. + */ +[ + object, + local, + uuid(E59D8D22-ADA7-49a2-89B5-A415AFCFC95F) +] +interface IXCLRDataStackWalk : IUnknown +{ + /* + * Get the current context of this stack walk. + * This is the original context with any unwinding + * applied to it. As unwinding may only restore + * a subset of the registers, such as only non-volatile + * registers, the context may not exactly match the + * register state at the time of the actual call. + */ + HRESULT GetContext([in] ULONG32 contextFlags, + [in] ULONG32 contextBufSize, + [out] ULONG32* contextSize, + [out, size_is(contextBufSize)] BYTE contextBuf[]); + + /* + * Change the current context of this stack walk, allowing the + * debugger to move it to an arbitrary context. Does not actually + * alter the current context of the thread whose stack is being walked. + * OBSOLETE: Use SetContext2. + */ + HRESULT SetContext([in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE context[]); + + /* + * Attempt to advance the stack walk to the next frame that + * matches the stack walk's filter. If the current frame type is + * CLRDATA_UNRECOGNIZED_FRAME, Next() will be unable to + * advance. (The debugger will have to walk the unrecognized frame + * itself, reset the walk's context, and try again.) + * + * Upon creation, the stack walk is positioned "before" the first + * frame on the stack. Debuggers must call Next() to advance to + * the first frame before any other functions will work. The + * function will output S_FALSE when there are no more frames that + * meet its filter criteria. + */ + HRESULT Next(); + + /* + * Return the number of bytes skipped by the last call to Next(). + * If Next() moved to the very next frame, outputs 0. + * + * Note that calling GetStackSizeSkipped() after any function other + * than Next() has no meaning. + */ + HRESULT GetStackSizeSkipped([out] ULONG64* stackSizeSkipped); + + /* + * Return information about the type of the current frame + */ + HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, + [out] CLRDataDetailedFrameType* detailedType); + + /* + * Return the current frame, if it is recognized. + */ + HRESULT GetFrame([out] IXCLRDataFrame** frame); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Change the current context of this stack walk, allowing the + * debugger to move it to an arbitrary context. Does not actually + * alter the current context of the thread whose stack is being walked. + */ + HRESULT SetContext2([in] ULONG32 flags, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE context[]); +} + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataFrame */ +[ + object, + local, + uuid(271498C2-4085-4766-BC3A-7F8ED188A173) +] +interface IXCLRDataFrame : IUnknown +{ + /* + * Return information about the type of this frame. + */ + HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, + [out] CLRDataDetailedFrameType* detailedType); + + /* + * Get the stack walk context as of this frame. + * This is the original context with any unwinding + * applied to it. As unwinding may only restore + * a subset of the registers, such as only non-volatile + * registers, the context may not exactly match the + * register state at the time of the actual call. + */ + HRESULT GetContext([in] ULONG32 contextFlags, + [in] ULONG32 contextBufSize, + [out] ULONG32* contextSize, + [out, size_is(contextBufSize)] BYTE contextBuf[]); + + /* + * Return the app domain of this frame + */ + HRESULT GetAppDomain([out] IXCLRDataAppDomain** appDomain); + + /* + * Return the number of arguments on the stack. + */ + HRESULT GetNumArguments([out] ULONG32* numArgs); + + /* + * Return an argument by (0-based) index. + * The name parameter is filled in if name information is availble. + */ + HRESULT GetArgumentByIndex([in] ULONG32 index, + [out] IXCLRDataValue** arg, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Return the number of local variables on the stack. + */ + HRESULT GetNumLocalVariables([out] ULONG32* numLocals); + + /* + * Return a local variable by (0-based) index. + * The name parameter is filled in if name information is availble. + */ + HRESULT GetLocalVariableByIndex([in] ULONG32 index, + [out] IXCLRDataValue** localVariable, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR name[]); + + /* + * Get a name for the frame's current instruction pointer. + * This is either a method's name or a runtime code name. + * + * Returns S_FALSE if the buffer is not large enough for the name, + * and sets nameLen to be the buffer length needed. + */ + HRESULT GetCodeName([in] ULONG32 flags, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Gets the method instance corresponding to this frame. + */ + HRESULT GetMethodInstance([out] IXCLRDataMethodInstance** method); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Enumerate the full parameterization of the frame's + * type and method. + */ + HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); + HRESULT GetTypeArgumentByIndex([in] ULONG32 index, + [out] IXCLRDataTypeInstance** typeArg); +} +#pragma warning(pop) + +[ + object, + local, + uuid(1C4D9A4B-702D-4CF6-B290-1DB6F43050D0) +] +interface IXCLRDataFrame2 : IUnknown +{ + /* + * Retun generic token if available. + */ + HRESULT GetExactGenericArgsToken([out] IXCLRDataValue** genericToken); +} + +typedef enum +{ + CLRDATA_EXCEPTION_DEFAULT = 0x00000000, + + // Exception is occurring during processing + // of other exception states. + CLRDATA_EXCEPTION_NESTED = 0x00000001, + + // Exception state is not completely available. + // This can happen when the state is no longer + // active or before a state is fully initialized. + CLRDATA_EXCEPTION_PARTIAL = 0x00000002, +} CLRDataExceptionStateFlag; + +typedef enum +{ + CLRDATA_EXBASE_EXCEPTION, + CLRDATA_EXBASE_OUT_OF_MEMORY, + CLRDATA_EXBASE_INVALID_ARGUMENT, +} CLRDataBaseExceptionType; + +typedef enum +{ + CLRDATA_EXSAME_SECOND_CHANCE = 0x00000000, + CLRDATA_EXSAME_FIRST_CHANCE = 0x00000001, +} CLRDataExceptionSameFlag; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for inteface IXCLRDataExceptionState */ +[ + object, + local, + uuid(75DA9E4C-BD33-43C8-8F5C-96E8A5241F57) +] +interface IXCLRDataExceptionState : IUnknown +{ + /* + * Get state flags, defined in CLRDataExceptionStateFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * For nested exceptions, get the exception that + * was being handled when this exception occurred. + */ + HRESULT GetPrevious([out] IXCLRDataExceptionState** exState); + + /* + * Get the managed object representing the exception. + */ + HRESULT GetManagedObject([out] IXCLRDataValue** value); + + /* + * Get the standard base type of the exception. + */ + HRESULT GetBaseType([out] CLRDataBaseExceptionType* type); + + /* + * Get exception information. + */ + HRESULT GetCode([out] ULONG32* code); + HRESULT GetString([in] ULONG32 bufLen, + [out] ULONG32 *strLen, + [out, size_is(bufLen)] WCHAR str[]); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Determine whether the given interface represents + * the same exception state. + * OBSOLETE: Use IsSameState2. + * Requires revision 1. + */ + HRESULT IsSameState([in] EXCEPTION_RECORD64* exRecord, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE cxRecord[]); + + /* + * Determine whether the given interface represents + * the same exception state. + * Requires revision 2. + */ + HRESULT IsSameState2([in] ULONG32 flags, + [in] EXCEPTION_RECORD64* exRecord, + [in] ULONG32 contextSize, + [in, size_is(contextSize)] BYTE cxRecord[]); + + /* + * Gets the task this exception state is associated with. + * Requires revision 2. + */ + HRESULT GetTask([out] IXCLRDataTask** task); +} +#pragma warning(pop) + +typedef enum +{ + CLRDATA_VLOC_MEMORY = 0x00000000, + CLRDATA_VLOC_REGISTER = 0x00000001, +} ClrDataValueLocationFlag; + +#pragma warning(push) +#pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataValue */ +/* + * Object inspection interface. + */ +[ + object, + local, + uuid(96EC93C7-1000-4e93-8991-98D8766E6666) +] +interface IXCLRDataValue : IUnknown +{ + /* + * Get state flags, defined in CLRDataValueFlag. + */ + HRESULT GetFlags([out] ULONG32* flags); + + /* + * Get the address of the object. + * Fails unless the object is a single contiguous + * piece of data in memory. + * OBSOLETE: Use GetLocation instead. + */ + HRESULT GetAddress([out] CLRDATA_ADDRESS* address); + + /* + * Return the size (in bytes) of the object. + */ + HRESULT GetSize([out] ULONG64* size); + + /* + * Copy between an object and a buffer. + * Returns S_FALSE if the buffer was not at least as large + * as the object. + */ + HRESULT GetBytes([in] ULONG32 bufLen, + [out] ULONG32 *dataSize, + [out, size_is(bufLen)] BYTE buffer[]); + HRESULT SetBytes([in] ULONG32 bufLen, + [out] ULONG32 *dataSize, + [in, size_is(bufLen)] BYTE buffer[]); + + /* + * Get the type of the object + */ + HRESULT GetType([out] IXCLRDataTypeInstance **typeInstance); + + /* + * Get the number of fields in the object. + * OBSOLETE: Use GetNumFields2. + */ + HRESULT GetNumFields([out] ULONG32 *numFields); + + /* + * Gets one field of the object. + * + * Because field ordering is not fixed, can also return name + * information and/or the metadata token, if the caller passes in + * appropriate values. + * OBSOLETE: Use EnumField. + */ + HRESULT GetFieldByIndex([in] ULONG32 index, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[], + [out] mdFieldDef* token); + + HRESULT Request([in] ULONG32 reqCode, + [in] ULONG32 inBufferSize, + [in, size_is(inBufferSize)] BYTE* inBuffer, + [in] ULONG32 outBufferSize, + [out, size_is(outBufferSize)] BYTE* outBuffer); + + /* + * Get the number of fields in the value. + * If a type is passed in only fields defined + * by that type are enumerated. + */ + HRESULT GetNumFields2([in] ULONG32 flags, + [in] IXCLRDataTypeInstance* fromType, + [out] ULONG32* numFields); + + /* + * Enumerate the fields for this value. + * If a type is passed in only fields defined + * by that type are enumerated. + */ + HRESULT StartEnumFields([in] ULONG32 flags, + [in] IXCLRDataTypeInstance* fromType, + [out] CLRDATA_ENUM* handle); + HRESULT EnumField([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** field, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] mdFieldDef* token); + HRESULT EndEnumFields([in] CLRDATA_ENUM handle); + + HRESULT StartEnumFieldsByName([in] LPCWSTR name, + [in] ULONG32 nameFlags, + [in] ULONG32 fieldFlags, + [in] IXCLRDataTypeInstance* fromType, + [out] CLRDATA_ENUM* handle); + HRESULT EnumFieldByName([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** field, + [out] mdFieldDef* token); + HRESULT EndEnumFieldsByName([in] CLRDATA_ENUM handle); + + /* + * Retrieve a field by field metadata token. + */ + HRESULT GetFieldByToken([in] mdFieldDef token, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Get the value implicitly associated with this value. + * For pointers or reference values this is the value + * pointed/referred to. + * For boxed values this is the contained value. + * For other values there is no associated value. + */ + HRESULT GetAssociatedValue([out] IXCLRDataValue** assocValue); + + /* + * Get the type implicitly associated with this value. + * For pointers or reference types this is the type + * pointed/referred to. + * For boxed values this is the type of the contained value. + * For arrays this is the element type. + * For other values there is no associated type. + */ + HRESULT GetAssociatedType([out] IXCLRDataTypeInstance** assocType); + + /* + * String methods that only work for string data values. + */ + + /* + * Return the length and contents of the string. + */ + HRESULT GetString([in] ULONG32 bufLen, + [out] ULONG32 *strLen, + [out, size_is(bufLen)] WCHAR str[]); + + /* + * Array methods that only work for array data values. + */ + + /* + * Return the definition of the array. + */ + HRESULT GetArrayProperties([out] ULONG32 *rank, + [out] ULONG32 *totalElements, + [in] ULONG32 numDim, + [out, size_is(numDim)] ULONG32 dims[], + [in] ULONG32 numBases, + [out, size_is(numBases)] LONG32 bases[]); + + /* + * Return a value representing the given element in the array. + */ + HRESULT GetArrayElement([in] ULONG32 numInd, + [in, size_is(numInd)] LONG32 indices[], + [out] IXCLRDataValue **value); + + HRESULT EnumField2([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** field, + [in] ULONG32 nameBufLen, + [out] ULONG32* nameLen, + [out, size_is(nameBufLen)] WCHAR nameBuf[], + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT EnumFieldByName2([in, out] CLRDATA_ENUM* handle, + [out] IXCLRDataValue** field, + [out] IXCLRDataModule** tokenScope, + [out] mdFieldDef* token); + HRESULT GetFieldByToken2([in] IXCLRDataModule* tokenScope, + [in] mdFieldDef token, + [out] IXCLRDataValue **field, + [in] ULONG32 bufLen, + [out] ULONG32 *nameLen, + [out, size_is(bufLen)] WCHAR nameBuf[]); + + /* + * Returns the locations the value's + * data is spread across. + * Placeholder values, such as values for variables + * which are dead, may not have any locations. + * Memory locations return the memory address in arg. + * Register locations do not return an indication + * of which register. + * Requires revision 3. + */ + HRESULT GetNumLocations([out] ULONG32* numLocs); + HRESULT GetLocationByIndex([in] ULONG32 loc, + [out] ULONG32* flags, + [out] CLRDATA_ADDRESS* arg); +} +#pragma warning(pop) + +[ + object, + local, + uuid(2D95A079-42A1-4837-818F-0B97D7048E0E) +] +interface IXCLRDataExceptionNotification : IUnknown +{ + /* + * New code was generated or discarded for a method. + */ + HRESULT OnCodeGenerated([in] IXCLRDataMethodInstance* method); + HRESULT OnCodeDiscarded([in] IXCLRDataMethodInstance* method); + + /* + * The process or task reached the desired execution state. + */ + HRESULT OnProcessExecution([in] ULONG32 state); + HRESULT OnTaskExecution([in] IXCLRDataTask* task, + [in] ULONG32 state); + + /* + * The given module was loaded or unloaded. + */ + HRESULT OnModuleLoaded([in] IXCLRDataModule* mod); + HRESULT OnModuleUnloaded([in] IXCLRDataModule* mod); + + /* + * The given type was loaded or unloaded. + */ + HRESULT OnTypeLoaded([in] IXCLRDataTypeInstance* typeInst); + HRESULT OnTypeUnloaded([in] IXCLRDataTypeInstance* typeInst); +} + +[ + object, + local, + uuid(31201a94-4337-49b7-aef7-0c755054091f) +] +interface IXCLRDataExceptionNotification2 : IXCLRDataExceptionNotification +{ + /* + * The given app domain was loaded or unloaded. + */ + HRESULT OnAppDomainLoaded([in] IXCLRDataAppDomain* domain); + HRESULT OnAppDomainUnloaded([in] IXCLRDataAppDomain* domain); + + /* + * A managed exception has been raised. + */ + HRESULT OnException([in] IXCLRDataExceptionState* exception); +} + +[ + object, + local, + uuid(31201a94-4337-49b7-aef7-0c7550540920) +] +interface IXCLRDataExceptionNotification3 : IXCLRDataExceptionNotification2 +{ + /* + * The specified GC event was triggered. The GC event is passed in an + * opaque structure, whose structure is given by buffSize + */ + HRESULT OnGcEvent([in] GcEvtArgs gcEvtArgs); +} + +[ + object, + local, + uuid(C25E926E-5F09-4AA2-BBAD-B7FC7F10CFD7) +] +interface IXCLRDataExceptionNotification4 : IXCLRDataExceptionNotification3 +{ + /* + * A managed catch clause is about to be executed + */ + HRESULT ExceptionCatcherEnter([in] IXCLRDataMethodInstance* catchingMethod, DWORD catcherNativeOffset); +} + +[ + object, + local, + uuid(e77a39ea-3548-44d9-b171-8569ed1a9423) +] +interface IXCLRDataExceptionNotification5 : IXCLRDataExceptionNotification4 +{ + /* + * New code was generated for a method. The given address is the start address of + * the native newly jitted code. + */ + HRESULT OnCodeGenerated2([in] IXCLRDataMethodInstance* method, [in] CLRDATA_ADDRESS nativeCodeLocation); +} \ No newline at end of file diff --git a/lib/coreclr/src/inc/xcordebug.idl b/lib/coreclr/src/inc/xcordebug.idl new file mode 100644 index 0000000000..ef9128bea7 --- /dev/null +++ b/lib/coreclr/src/inc/xcordebug.idl @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +/***************************************************************************** + ** ** + ** XCordebug.idl - Experimental (undocumented) Debugging interfaces. ** + ** ** + *****************************************************************************/ + + +/* ------------------------------------------------------------------------- * + * Imported types + * ------------------------------------------------------------------------- */ + +import "cordebug.idl"; + + + + +// @dbgtodo : proper API docs here. +// - include failure semantics of Filter. What does failure mean? +// +/* Comments to add to ICorDebugDataTarget docs: + * Whenever the target process changes, the debugger client must + * call ICorDebugProcess4::ProcessStateChanged before issuing any other + * ICorDebug API calls. +*/ +[ + object, + local, + uuid(E930C679-78AF-4953-8AB7-B0AABF0F9F80), + pointer_default(unique) +] +interface ICorDebugProcess4 : IUnknown +{ + /* + * Process native debug events. + */ + HRESULT Filter( + [in, length_is(countBytes), size_is(countBytes)] const BYTE pRecord[], + [in] DWORD countBytes, + [in] CorDebugRecordFormat format, + [in] DWORD dwFlags, + [in] DWORD dwThreadId, + [in] ICorDebugManagedCallback * pCallback, + [in, out] CORDB_CONTINUE_STATUS * pContinueStatus); + + /* + * Debugger calls this to notify ICorDebug that the process is running. + * + * Notes: + * ProcessStateChanged(PROCESS_RUNNING) has similar semantics to ICorDebugProcess::Continue(); + */ + HRESULT ProcessStateChanged([in] CorDebugStateChange eChange); + +}; diff --git a/lib/coreclr/src/inc/zapper.h b/lib/coreclr/src/inc/zapper.h new file mode 100644 index 0000000000..29fc4fbf04 --- /dev/null +++ b/lib/coreclr/src/inc/zapper.h @@ -0,0 +1,452 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef ZAPPER_H_ +#define ZAPPER_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include "sarray.h" +#include "sstring.h" +#include "shash.h" +#include "utilcode.h" +#include "corjit.h" +#include "corcompile.h" +#include "corhlprpriv.h" +#include "ngen.h" +#include "corbbtprof.h" +#include "pedecoder.h" +#include "mscorsvc.h" +#include "holderinst.h" +#include "corpriv.h" + +// For side by side issues, it's best to use the exported API calls to generate a +// Zapper Object instead of creating one on your own. + +STDAPI NGenCreateNGenWorker(ICorSvcWorker **pCorSvcWorker, ILocalServerLifetime *pLocalServerLifetime, ICorSvcLogger *pCorSvcLogger); +STDAPI NGenCreateZapper(HANDLE* hZapper, NGenOptions* opt); +STDAPI NGenFreeZapper(HANDLE hZapper); +STDAPI NGenTryEnumerateFusionCache(HANDLE hZapper, LPCWSTR assemblyName, bool fPrint, bool fDelete); +STDAPI_(BOOL) NGenCompile(HANDLE hZapper, LPCWSTR path); + + +/* --------------------------------------------------------------------------- * + * Zapper classes + * --------------------------------------------------------------------------- */ + +class ZapperOptions; +class ZapperAttributionStats; +class ZapImage; +class ZapInfo; + +typedef enum CorZapLogLevel +{ + CORZAP_LOGLEVEL_ERROR, + CORZAP_LOGLEVEL_WARNING, + CORZAP_LOGLEVEL_SUCCESS, + CORZAP_LOGLEVEL_INFO, +} CorZapLogLevel; + +class Zapper +{ + friend class ZapImage; + friend class ZapInfo; + friend class ZapILMetaData; + + private: + + // + // Interfaces + // + + ICorDynamicInfo *m_pEEJitInfo; + ICorCompileInfo *m_pEECompileInfo; + ICorJitCompiler *m_pJitCompiler; + IMetaDataDispenserEx *m_pMetaDataDispenser; + HMODULE m_hJitLib; +#ifdef _TARGET_AMD64_ + HMODULE m_hJitLegacy; +#endif + +#ifdef ALLOW_SXS_JIT_NGEN + ICorJitCompiler *m_alternateJit; + HMODULE m_hAltJITCompiler; +#endif // ALLOW_SXS_JIT_NGEN + + // + // Options + // + + ZapperOptions * m_pOpt; + BOOL m_fFreeZapperOptions; + + SString m_exeName; // If an EXE is specified + + bool m_fromDllHost; + + // + // Current assembly info + // + + ICorCompilationDomain *m_pDomain; + CORINFO_ASSEMBLY_HANDLE m_hAssembly; + IMDInternalImport *m_pAssemblyImport; + + SString m_outputPath; // Temp folder for creating the output file + + IMetaDataAssemblyEmit *m_pAssemblyEmit; + IMetaDataAssemblyEmit *CreateAssemblyEmitter(); + + // + // + // Status info + // + + BOOL m_failed; + CorInfoRegionKind m_currentRegionKind; + + SString m_platformAssembliesPaths; + SString m_trustedPlatformAssemblies; + SString m_platformResourceRoots; + SString m_appPaths; + SString m_appNiPaths; + SString m_platformWinmdPaths; + +#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) + SString m_CLRJITPath; + bool m_fDontLoadJit; +#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) +#if !defined(NO_NGENPDB) + SString m_DiasymreaderPath; +#endif // !defined(NO_NGENPDB) + + SString m_outputFilename; + + SIZE_T m_customBaseAddress; + + public: + + struct assemblyDependencies + { + struct DependencyEntry + { + BSTR bstr; + LoadHintEnum loadHint; + NGenHintEnum ngenHint; + }; + + SArray dependencyArray; + NGenHintEnum ngenHint; + SString displayName; + + assemblyDependencies() + { + Initialize(); + ngenHint = NGenDefault; + } + + ~assemblyDependencies() + { + Cleanup(); + } + + void Reinitialize() + { + Cleanup(); + Initialize(); + } + + void SetNGenHint(NGenHintEnum ngenHint) + { + this->ngenHint = ngenHint; + } + + NGenHintEnum GetNGenHint() + { + return ngenHint; + } + + void SetDisplayName(const WCHAR *pStr) + { + displayName.Set(pStr); + } + + const WCHAR *GetDisplayName() + { + return displayName.GetUnicode(); + } + + void Append(const WCHAR *pStr, LoadHintEnum loadHint = LoadDefault, NGenHintEnum ngenHint = NGenDefault) + { + // Don't append string if it's a duplicate + for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++) + { + if (wcscmp(dependencyArray[i].bstr, pStr) == 0) + return; + } + + BSTRHolder bstr(::SysAllocString(pStr)); + DependencyEntry dependencyEntry; + dependencyEntry.bstr = bstr.GetValue(); + dependencyEntry.loadHint = loadHint; + dependencyEntry.ngenHint = ngenHint; + + dependencyArray.Append(dependencyEntry); + bstr.SuppressRelease(); + } + + SAFEARRAY *GetSAFEARRAY() + { + SafeArrayHolder pDependencies(SafeArrayCreateVector(VT_BSTR, 0, dependencyArray.GetCount())); + if (pDependencies.GetValue() == NULL) ThrowLastError(); + + for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++) + { + LONG indices[1]; + indices[0] = (LONG) i; + IfFailThrow(SafeArrayPutElement(pDependencies, indices, this->dependencyArray[i].bstr)); + } + + pDependencies.SuppressRelease(); + return pDependencies.GetValue(); + } + + SAFEARRAY *GetLoadHintSAFEARRAY() + { + SafeArrayHolder pSettings(SafeArrayCreateVector(VT_UI4, 0, dependencyArray.GetCount())); + if (pSettings.GetValue() == NULL) ThrowLastError(); + + for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++) + { + LONG indices[1]; + indices[0] = (LONG) i; + IfFailThrow(SafeArrayPutElement(pSettings, indices, &this->dependencyArray[i].loadHint)); + } + + pSettings.SuppressRelease(); + return pSettings.GetValue(); + } + + SAFEARRAY *GetNGenHintSAFEARRAY() + { + SafeArrayHolder pSettings(SafeArrayCreateVector(VT_UI4, 0, dependencyArray.GetCount())); + if (pSettings.GetValue() == NULL) ThrowLastError(); + + for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++) + { + LONG indices[1]; + indices[0] = (LONG) i; + IfFailThrow(SafeArrayPutElement(pSettings, indices, &this->dependencyArray[i].ngenHint)); + } + + pSettings.SuppressRelease(); + return pSettings.GetValue(); + } + + private: + void Initialize() + { + dependencyArray.SetCount(0); + // Should we reinitialize ngenHint to the default value as well? + } + + void Cleanup() + { + for (COUNT_T i = 0; i < dependencyArray.GetCount(); i++) + { + ::SysFreeString(dependencyArray[i].bstr); + } + } + } m_assemblyDependencies; + + + public: + + Zapper(ZapperOptions *pOpt); + Zapper(NGenOptions *pOpt, bool fromDllHost = false); + + void Init(ZapperOptions *pOpt, bool fFreeZapperOptions= false); + + static Zapper *NewZapper(NGenOptions *pOpt, bool fromDllHost = false) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + } + CONTRACTL_END; + return new Zapper(pOpt, fromDllHost); + } + + ~Zapper(); + + // The arguments control which native image of mscorlib to use. + // This matters for hardbinding. + void InitEE(BOOL fForceDebug, BOOL fForceProfile, BOOL fForceInstrument); + void LoadAndInitializeJITForNgen(LPCWSTR pwzJitName, OUT HINSTANCE* phJit, OUT ICorJitCompiler** ppICorJitCompiler); + + + BOOL IsAssembly(LPCWSTR path); + + void CreateDependenciesLookupDomain(); + void ComputeDependencies(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + void ComputeAssemblyDependencies(CORINFO_ASSEMBLY_HANDLE hAssembly); + + void CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath); + + void DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId); + + HRESULT Compile(LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig = NULL); + void DontUseProfileData(); + bool HasProfileData(); + + void CompileAssembly(CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + ZapImage * CompileModule(CORINFO_MODULE_HANDLE hModule, + IMetaDataAssemblyEmit *pEmit); + void InstallCompiledAssembly(LPCWSTR szAssemblyName, LPCWSTR szNativeImagePath, HANDLE hFile, SArray &hFiles); + + HRESULT GetExceptionHR(); + + void Success(LPCWSTR format, ...); + void Error(LPCWSTR format, ...); + void Warning(LPCWSTR format, ...); + void Info(LPCWSTR format, ...); + void Print(CorZapLogLevel level, LPCWSTR format, ...); + void Print(CorZapLogLevel level, LPCWSTR format, va_list args); + void PrintErrorMessage(CorZapLogLevel level, Exception *ex); + void PrintErrorMessage(CorZapLogLevel level, HRESULT hr); + + BOOL CheckAssemblyUpToDate(CORINFO_ASSEMBLY_HANDLE hAssembly, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + BOOL TryToInstallFromRepository(CORINFO_ASSEMBLY_HANDLE hAssembly, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + BOOL TryToInstallFromRepositoryDir(SString &strNativeImageDir, + SString &strSimpleName, + CORCOMPILE_NGEN_SIGNATURE *pNativeImageSig, + BOOL *pfHitMismatchedVersion, + BOOL *pfHitMismatchedDependencies, + BOOL useHardLink = FALSE); + void CopyAndInstallFromRepository(LPCWSTR lpszNativeImageDir, + LPCWSTR lpszNativeImageName, + CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig, + BOOL useHardLink = FALSE); + void InstallFromRepository(LPCWSTR lpszNativeImage, + CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + + void CopyDirectory(LPCWSTR srcPath, LPCWSTR dstPath); + void CleanDirectory(LPCWSTR path); + void TryCleanDirectory(LPCWSTR path); + static void TryCleanDirectory(Zapper * pZapper); + + void GetOutputFolder(); + + void SetPlatformAssembliesPaths(LPCWSTR pwzPlatformAssembliesPaths); + void SetTrustedPlatformAssemblies(LPCWSTR pwzTrustedPlatformAssemblies); + void SetPlatformResourceRoots(LPCWSTR pwzPlatformResourceRoots); + void SetAppPaths(LPCWSTR pwzAppPaths); + void SetAppNiPaths(LPCWSTR pwzAppNiPaths); + void SetPlatformWinmdPaths(LPCWSTR pwzPlatformWinmdPaths); + +#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) + void SetCLRJITPath(LPCWSTR pwszCLRJITPath); + void SetDontLoadJit(); +#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) + +#if !defined(NO_NGENPDB) + void SetDiasymreaderPath(LPCWSTR pwzDiasymreaderPath); +#endif // !defined(NO_NGENPDB) + + void SetOutputFilename(LPCWSTR pwszOutputFilename); + SString GetOutputFileName(); + + void SetCustomBaseAddress(SIZE_T baseAddress); + SIZE_T GetCustomBaseAddress(); + + private: + + void DestroyDomain(); + void CleanupAssembly(); + + void CreateCompilationDomain(); + void SetContextInfo(LPCWSTR assemblyName = NULL); + + void InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo); + + // DomainCallback is subclassed by each method that would like to compile in a given domain + class DomainCallback + { + public: + virtual void doCallback() = NULL; + }; + + void CompileInCurrentDomain(__in LPCWSTR path, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + void ComputeDependenciesInCurrentDomain(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); + void CreateDependenciesLookupDomainInCurrentDomain(); + + void HangWorker(LPCWSTR hangKey, LPCWSTR insideHangKey); +}; + +class ZapperOptions +{ + public: + enum StatOptions + { + NO_STATS = 0, + DEFAULT_STATS = 1, + FIXUP_STATS = DEFAULT_STATS << 1, + CALL_STATS = FIXUP_STATS << 1, + ATTRIB_STATS = CALL_STATS << 1, + ALL_STATS = ~NO_STATS, + }; + + LPWSTR m_zapSet; // Add to zap string. Use to get a private scope of ngen images, for debugging/testing + + LPCWSTR m_repositoryDir; // Directory with prebuilt native images + RepositoryFlags m_repositoryFlags; // Copy the native images back to NativeImagesDir + + bool m_autodebug; // Use the debug setting specified by the IL module + + MethodNamesList* m_onlyMethods; // only methods to process + MethodNamesList* m_excludeMethods; // excluded these methods + mdToken m_onlyOneMethod; // only compile method with matching token + + bool m_silent; // Dont spew any text output + bool m_verbose; // Spew extra text ouput + bool m_ignoreErrors; // Continue in the face of errors + unsigned m_statOptions; // print statisitcs on number of methods, size of code ... + bool m_ngenProfileImage; // ngening with "/prof" + + // Which optimizations should be done + bool m_ignoreProfileData; // Don't use profile data + bool m_noProcedureSplitting; // Don't do procedure splitting + + bool m_fHasAnyProfileData; // true if we successfully loaded and used + // any profile data when compiling this assembly + + bool m_fPartialNGen; // Generate partial NGen images using IBC data + + bool m_fPartialNGenSet; // m_fPartialNGen has been set through the environment + + bool m_fAutoNGen; // This is an automatic NGen request + + bool m_fRepositoryOnly; // Install from repository only, no real NGen + + bool m_fNGenLastRetry; // This is retry of the compilation + + CORJIT_FLAGS m_compilerFlags; + + bool m_fNoMetaData; // Do not copy metadata and IL to native image + + void SetCompilerFlags(void); + + ZapperOptions(); + ~ZapperOptions(); +}; + +#endif // ZAPPER_H_ + diff --git a/lib/coreclr/src/pal/inc/mbusafecrt.h b/lib/coreclr/src/pal/inc/mbusafecrt.h new file mode 100644 index 0000000000..abc2dca406 --- /dev/null +++ b/lib/coreclr/src/pal/inc/mbusafecrt.h @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*** +* mbusafecrt.h - public declarations for SafeCRT lib +* + +* +* Purpose: +* This file contains the public declarations SafeCRT +* functions ported to MacOS. These are the safe versions of +* functions standard functions banned by SWI +* + +****/ + +/* shields! */ + +#ifndef MBUSAFECRT_H +#define MBUSAFECRT_H + +//#include + +/* MacOS does not define a specifc type for errnos, but SafeCRT does */ +typedef int errno_t; + +/* errno value that specific to SafeCRT */ +#define STRUNCATE 80 + +// define the return value for success +#define SAFECRT_SUCCESS 0 + +#ifndef THROW_DECL +#if defined(_MSC_VER) || defined(__llvm__) || !defined(__cplusplus) +#define THROW_DECL +#else +#define THROW_DECL throw() +#endif // !_MSC_VER +#endif // !THROW_DECL + +#ifdef __cplusplus + extern "C" { +#endif + +typedef void ( *tSafeCRT_AssertFuncPtr )( const char* inExpression, const char* inComment, const char* inFile, const unsigned long inLineNum ); +void MBUSafeCRTSetAssertFunc( tSafeCRT_AssertFuncPtr inAssertFuncPtr ); + +extern errno_t strcat_s( char* ioDest, size_t inDestBufferSize, const char* inSrc ); +extern errno_t wcscat_s( WCHAR* ioDest, size_t inDestBufferSize, const WCHAR* inSrc ); + +extern errno_t strncat_s( char* ioDest, size_t inDestBufferSize, const char* inSrc, size_t inCount ); +extern errno_t wcsncat_s( WCHAR* ioDest, size_t inDestBufferSize, const WCHAR* inSrc, size_t inCount ); + +extern errno_t strcpy_s( char* outDest, size_t inDestBufferSize, const char* inSrc ); +extern errno_t wcscpy_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inSrc ); + +extern errno_t strncpy_s( char* outDest, size_t inDestBufferSize, const char* inSrc, size_t inCount ); +extern errno_t wcsncpy_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inSrc, size_t inCount ); + +extern char* strtok_s( char* inString, const char* inControl, char** ioContext ); +extern WCHAR* wcstok_s( WCHAR* inString, const WCHAR* inControl, WCHAR** ioContext ); + +// strnlen is not required unless the source string is completely untrusted (e.g. anonymous input on a website) +#ifndef SUPPRESS_STRNLEN + extern size_t PAL_strnlen( const char* inString, size_t inMaxSize ); + extern size_t PAL_wcsnlen( const WCHAR* inString, size_t inMaxSize ); +#endif + +extern errno_t _itoa_s( int inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _itow_s( int inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ltoa_s( long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ltow_s( long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ultoa_s( unsigned long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ultow_s( unsigned long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _i64toa_s( long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _i64tow_s( long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _ui64toa_s( unsigned long long inValue, char* outBuffer, size_t inDestBufferSize, int inRadix ); +extern errno_t _ui64tow_s( unsigned long long inValue, WCHAR* outBuffer, size_t inDestBufferSize, int inRadix ); + +extern errno_t _makepath_s( char* outDest, size_t inDestBufferSize, const char* inDrive, const char* inDirectory, const char* inFilename, const char* inExtension ); +extern errno_t _wmakepath_s( WCHAR* outDest, size_t inDestBufferSize, const WCHAR* inDrive, const WCHAR* inDirectory, const WCHAR* inFilename, const WCHAR* inExtension ); + +extern errno_t _splitpath_s( const char* inPath, char* outDrive, size_t inDriveSize, char* outDirectory, size_t inDirectorySize, char* outFilename, size_t inFilenameSize, char* outExtension, size_t inExtensionSize ); +extern errno_t _wsplitpath_s( const WCHAR* inPath, WCHAR* outDrive, size_t inDriveSize, WCHAR* outDirectory, size_t inDirectorySize, WCHAR* outFilename, size_t inFilenameSize, WCHAR* outExtension, size_t inExtensionSize ); + +extern int sprintf_s( char *string, size_t sizeInBytes, const char *format, ... ); +extern int swprintf_s( WCHAR *string, size_t sizeInWords, const WCHAR *format, ... ); + +extern int _snprintf_s( char *string, size_t sizeInBytes, size_t count, const char *format, ... ); +extern int _snwprintf_s( WCHAR *string, size_t sizeInWords, size_t count, const WCHAR *format, ... ); + +extern int vsprintf_s( char* string, size_t sizeInBytes, const char* format, va_list arglist ); +extern int _vsnprintf_s( char* string, size_t sizeInBytes, size_t count, const char* format, va_list arglist ); + +extern int vswprintf_s( WCHAR* string, size_t sizeInWords, const WCHAR* format, va_list arglist ); +extern int _vsnwprintf_s( WCHAR* string, size_t sizeInWords, size_t count, const WCHAR* format, va_list arglist ); + +extern int sscanf_s( const char *string, const char *format, ... ); +extern int swscanf_s( const WCHAR *string, const WCHAR *format, ... ); + +extern int _snscanf_s( const char *string, size_t count, const char *format, ... ); +extern int _snwscanf_s( const WCHAR *string, size_t count, const WCHAR *format, ... ); + +extern errno_t memcpy_s( void * dst, size_t sizeInBytes, const void * src, size_t count ) THROW_DECL; +extern errno_t memmove_s( void * dst, size_t sizeInBytes, const void * src, size_t count ); + +#ifdef __cplusplus + } +#endif + +#endif /* MBUSAFECRT_H */ diff --git a/lib/coreclr/src/pal/inc/pal.h b/lib/coreclr/src/pal/inc/pal.h new file mode 100644 index 0000000000..08a35c8f62 --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal.h @@ -0,0 +1,5411 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + +Module Name: + + pal.h + +Abstract: + + CoreCLR Platform Adaptation Layer (PAL) header file. This file + defines all types and API calls required by the CoreCLR when + compiled for Unix-like systems. + + Defines which control the behavior of this include file: + UNICODE - define it to set the Ansi/Unicode neutral names to + be the ...W names. Otherwise the neutral names default + to be the ...A names. + PAL_IMPLEMENTATION - define it when implementing the PAL. Otherwise + leave it undefined when consuming the PAL. + + Note: some fields in structs have been renamed from the original + SDK documentation names, with _PAL_Undefined appended. This leaves + the structure layout identical to its Win32 version, but prevents + PAL consumers from inadvertently referencing undefined fields. + + If you want to add a PAL_ wrapper function to a native function in + here, you also need to edit palinternal.h and win32pal.h. + + + +--*/ + +#ifndef __PAL_H__ +#define __PAL_H__ + +#ifdef PAL_STDCPP_COMPAT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// This macro is used to standardize the wide character string literals between UNIX and Windows. +// Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size +// of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined +// as u"" (char16_t) +#define W(str) u##str + +// Undefine the QUOTE_MACRO_L helper and redefine it in terms of u. +// The reason that we do this is that quote macro is defined in ndp\common\inc, +// not inside of coreclr sources. + +#define QUOTE_MACRO_L(x) QUOTE_MACRO_u(x) +#define QUOTE_MACRO_u_HELPER(x) u###x +#define QUOTE_MACRO_u(x) QUOTE_MACRO_u_HELPER(x) + +#include +#include +#include + +// Native system libray handle. +// On Unix systems, NATIVE_LIBRARY_HANDLE type represents a library handle not registered with the PAL. +// To get a HMODULE on Unix, call PAL_RegisterLibraryDirect() on a NATIVE_LIBRARY_HANDLE. +typedef PVOID NATIVE_LIBRARY_HANDLE; + +/******************* Processor-specific glue *****************************/ + +#ifndef _MSC_VER + +#if defined(__i686__) && !defined(_M_IX86) +#define _M_IX86 600 +#elif defined(__i586__) && !defined(_M_IX86) +#define _M_IX86 500 +#elif defined(__i486__) && !defined(_M_IX86) +#define _M_IX86 400 +#elif defined(__i386__) && !defined(_M_IX86) +#define _M_IX86 300 +#elif defined(__x86_64__) && !defined(_M_AMD64) +#define _M_AMD64 100 +#elif defined(__arm__) && !defined(_M_ARM) +#define _M_ARM 7 +#elif defined(__aarch64__) && !defined(_M_ARM64) +#define _M_ARM64 1 +#endif + +#if defined(_M_IX86) && !defined(_X86_) +#define _X86_ +#elif defined(_M_AMD64) && !defined(_AMD64_) +#define _AMD64_ +#elif defined(_M_ARM) && !defined(_ARM_) +#define _ARM_ +#elif defined(_M_ARM64) && !defined(_ARM64_) +#define _ARM64_ +#endif + +#endif // !_MSC_VER + +/******************* ABI-specific glue *******************************/ + +#ifdef __APPLE__ +// Both PowerPC, i386 and x86_64 on Mac OS X use 16-byte alignment. +#define STACK_ALIGN_BITS 4 +#define STACK_ALIGN_REQ (1 << STACK_ALIGN_BITS) +#endif + +#define MAX_PATH 260 +#define _MAX_PATH 260 +#define _MAX_DRIVE 3 /* max. length of drive component */ +#define _MAX_DIR 256 /* max. length of path component */ +#define _MAX_FNAME 256 /* max. length of file name component */ +#define _MAX_EXT 256 /* max. length of extension component */ + +// In some Win32 APIs MAX_PATH is used for file names (even though 256 is the normal file system limit) +// use _MAX_PATH_FNAME to indicate these cases +#define MAX_PATH_FNAME MAX_PATH +#define MAX_LONGPATH 1024 /* max. length of full pathname */ + +#define MAXSHORT 0x7fff +#define MAXLONG 0x7fffffff +#define MAXCHAR 0x7f +#define MAXDWORD 0xffffffff + +// Sorting IDs. +// +// Note that the named locale APIs (eg CompareStringExEx) are recommended. +// + +#define LANG_CHINESE 0x04 +#define LANG_ENGLISH 0x09 +#define LANG_JAPANESE 0x11 +#define LANG_KOREAN 0x12 +#define LANG_THAI 0x1e + +/******************* Compiler-specific glue *******************************/ +#ifndef THROW_DECL +#if defined(_MSC_VER) || defined(__llvm__) || !defined(__cplusplus) +#define THROW_DECL +#else +#define THROW_DECL throw() +#endif // !_MSC_VER +#endif // !THROW_DECL + +#ifndef _MSC_VER +#if defined(CORECLR) +// Define this if the underlying platform supports true 2-pass EH. +// At the same time, this enables running several PAL instances +// side-by-side. +#define FEATURE_PAL_SXS 1 +#endif // CORECLR +#endif // !_MSC_VER + +#if defined(_MSC_VER) +#define DECLSPEC_ALIGN(x) __declspec(align(x)) +#else +#define DECLSPEC_ALIGN(x) __attribute__ ((aligned(x))) +#endif + +#define DECLSPEC_NORETURN PAL_NORETURN + +#ifdef __clang_analyzer__ +#define ANALYZER_NORETURN __attribute((analyzer_noreturn)) +#else +#define ANALYZER_NORETURN +#endif + +#if !defined(_MSC_VER) || defined(SOURCE_FORMATTING) +#define __assume(x) (void)0 +#define __annotation(x) +#endif //!MSC_VER + +#define UNALIGNED + +#ifndef FORCEINLINE +#if _MSC_VER < 1200 +#define FORCEINLINE inline +#else +#define FORCEINLINE __forceinline +#endif +#endif + +#ifndef NOOPT_ATTRIBUTE +#if defined(__llvm__) +#define NOOPT_ATTRIBUTE optnone +#elif defined(__GNUC__) +#define NOOPT_ATTRIBUTE optimize("O0") +#endif +#endif + +#ifndef NODEBUG_ATTRIBUTE +#if defined(__llvm__) +#define NODEBUG_ATTRIBUTE __nodebug__ +#elif defined(__GNUC__) +#define NODEBUG_ATTRIBUTE __artificial__ +#endif +#endif + +#ifndef PAL_STDCPP_COMPAT + +#if __GNUC__ + +typedef __builtin_va_list va_list; + +/* We should consider if the va_arg definition here is actually necessary. + Could we use the standard va_arg definition? */ + +#define va_start __builtin_va_start +#define va_arg __builtin_va_arg + +#define va_copy __builtin_va_copy +#define va_end __builtin_va_end + +#define VOID void + +#else // __GNUC__ + +typedef char * va_list; + +#define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) + +#if _MSC_VER >= 1400 + +#ifdef __cplusplus +#define _ADDRESSOF(v) ( &reinterpret_cast(v) ) +#else +#define _ADDRESSOF(v) ( &(v) ) +#endif + +#define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) +#define _crt_va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) +#define _crt_va_end(ap) ( ap = (va_list)0 ) + +#define va_start _crt_va_start +#define va_arg _crt_va_arg +#define va_end _crt_va_end + +#else // _MSC_VER + +#define va_start(ap,v) (ap = (va_list) (&(v)) + _INTSIZEOF(v)) +#define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) +#define va_end(ap) + +#endif // _MSC_VER + +#define va_copy(dest,src) (dest = src) + +#endif // __GNUC__ + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-32768) +#define SHRT_MAX 32767 +#define USHRT_MAX 0xffff + +#define INT_MIN (-2147483647 - 1) +#define INT_MAX 2147483647 +#define UINT_MAX 0xffffffff + +#define LONG_MIN (-2147483647L - 1) +#define LONG_MAX 2147483647L +#define ULONG_MAX 0xffffffffUL + +#endif // !PAL_STDCPP_COMPAT + +/******************* PAL-Specific Entrypoints *****************************/ + +#define IsDebuggerPresent PAL_IsDebuggerPresent + +PALIMPORT +BOOL +PALAPI +PAL_IsDebuggerPresent(VOID); + +#define FLT_MAX 3.402823466e+38F +#define DBL_MAX 1.7976931348623157e+308 + +/* minimum signed 64 bit value */ +#define _I64_MIN (I64(-9223372036854775807) - 1) +/* maximum signed 64 bit value */ +#define _I64_MAX I64(9223372036854775807) +/* maximum unsigned 64 bit value */ +#define _UI64_MAX UI64(0xffffffffffffffff) + +#define _I8_MAX SCHAR_MAX +#define _I8_MIN SCHAR_MIN +#define _I16_MAX SHRT_MAX +#define _I16_MIN SHRT_MIN +#define _I32_MAX INT_MAX +#define _I32_MIN INT_MIN +#define _UI8_MAX UCHAR_MAX +#define _UI8_MIN UCHAR_MIN +#define _UI16_MAX USHRT_MAX +#define _UI16_MIN USHRT_MIN +#define _UI32_MAX UINT_MAX +#define _UI32_MIN UINT_MIN + +#undef NULL + +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((PVOID)0) +#endif + +#if defined(PAL_STDCPP_COMPAT) && !defined(__cplusplus) +#define nullptr NULL +#endif // defined(PAL_STDCPP_COMPAT) && !defined(__cplusplus) + +#ifndef PAL_STDCPP_COMPAT + +#if _WIN64 || _MSC_VER >= 1400 +typedef __int64 time_t; +#else +typedef long time_t; +#endif +#define _TIME_T_DEFINED +#endif // !PAL_STDCPP_COMPAT + +#define DLL_PROCESS_ATTACH 1 +#define DLL_THREAD_ATTACH 2 +#define DLL_THREAD_DETACH 3 +#define DLL_PROCESS_DETACH 0 + +#define PAL_INITIALIZE_NONE 0x00 +#define PAL_INITIALIZE_SYNC_THREAD 0x01 +#define PAL_INITIALIZE_EXEC_ALLOCATOR 0x02 +#define PAL_INITIALIZE_STD_HANDLES 0x04 +#define PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER 0x08 +#define PAL_INITIALIZE_DEBUGGER_EXCEPTIONS 0x10 +#define PAL_INITIALIZE_ENSURE_STACK_SIZE 0x20 +#define PAL_INITIALIZE_REGISTER_SIGNALS 0x40 + +// PAL_Initialize() flags +#define PAL_INITIALIZE (PAL_INITIALIZE_SYNC_THREAD | \ + PAL_INITIALIZE_STD_HANDLES) + +// PAL_InitializeDLL() flags - don't start any of the helper threads or register any exceptions +#define PAL_INITIALIZE_DLL PAL_INITIALIZE_NONE + +// PAL_InitializeCoreCLR() flags +#define PAL_INITIALIZE_CORECLR (PAL_INITIALIZE | \ + PAL_INITIALIZE_EXEC_ALLOCATOR | \ + PAL_INITIALIZE_REGISTER_SIGTERM_HANDLER | \ + PAL_INITIALIZE_DEBUGGER_EXCEPTIONS | \ + PAL_INITIALIZE_ENSURE_STACK_SIZE | \ + PAL_INITIALIZE_REGISTER_SIGNALS) + +typedef DWORD (PALAPI_NOEXPORT *PTHREAD_START_ROUTINE)(LPVOID lpThreadParameter); +typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; + +/******************* PAL-Specific Entrypoints *****************************/ + +PALIMPORT +int +PALAPI +PAL_Initialize( + int argc, + char * const argv[]); + +PALIMPORT +void +PALAPI +PAL_InitializeWithFlags( + DWORD flags); + +PALIMPORT +int +PALAPI +PAL_InitializeDLL( + VOID); + +PALIMPORT +void +PALAPI +PAL_SetInitializeDLLFlags( + DWORD flags); + +PALIMPORT +DWORD +PALAPI +PAL_InitializeCoreCLR( + const char *szExePath); + +PALIMPORT +DWORD_PTR +PALAPI +PAL_EntryPoint( + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter); + +///

+/// This function shuts down PAL WITHOUT exiting the current process. +/// +PALIMPORT +void +PALAPI +PAL_Shutdown( + void); + +/// +/// This function shuts down PAL and exits the current process. +/// +PALIMPORT +void +PALAPI +PAL_Terminate( + void); + +/// +/// This function shuts down PAL and exits the current process with +/// the specified exit code. +/// +PALIMPORT +void +PALAPI +PAL_TerminateEx( + int exitCode); + +typedef VOID (*PSHUTDOWN_CALLBACK)(void); + +PALIMPORT +VOID +PALAPI +PAL_SetShutdownCallback( + IN PSHUTDOWN_CALLBACK callback); + +PALIMPORT +BOOL +PALAPI +PAL_GenerateCoreDump( + IN LPCSTR dumpName, + IN INT dumpType, + IN BOOL diag); + +typedef VOID (*PPAL_STARTUP_CALLBACK)( + char *modulePath, + HMODULE hModule, + PVOID parameter); + +PALIMPORT +DWORD +PALAPI +PAL_RegisterForRuntimeStartup( + IN DWORD dwProcessId, + IN LPCWSTR lpApplicationGroupId, + IN PPAL_STARTUP_CALLBACK pfnCallback, + IN PVOID parameter, + OUT PVOID *ppUnregisterToken); + +PALIMPORT +DWORD +PALAPI +PAL_UnregisterForRuntimeStartup( + IN PVOID pUnregisterToken); + +PALIMPORT +BOOL +PALAPI +PAL_NotifyRuntimeStarted(VOID); + +#ifdef __APPLE__ +PALIMPORT +LPCSTR +PALAPI +PAL_GetApplicationGroupId(); +#endif + +static const unsigned int MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH = MAX_PATH; + +PALIMPORT +VOID +PALAPI +PAL_GetTransportName( + const unsigned int MAX_TRANSPORT_NAME_LENGTH, + OUT char *name, + IN const char *prefix, + IN DWORD id, + IN const char *applicationGroupId, + IN const char *suffix); + +PALIMPORT +VOID +PALAPI +PAL_GetTransportPipeName( + OUT char *name, + IN DWORD id, + IN const char *applicationGroupId, + IN const char *suffix); + +PALIMPORT +void +PALAPI +PAL_InitializeDebug( + void); + +PALIMPORT +void +PALAPI +PAL_IgnoreProfileSignal(int signalNum); + +PALIMPORT +HINSTANCE +PALAPI +PAL_RegisterModule( + IN LPCSTR lpLibFileName); + +PALIMPORT +VOID +PALAPI +PAL_UnregisterModule( + IN HINSTANCE hInstance); + +PALIMPORT +BOOL +PALAPI +PAL_GetPALDirectoryW( + OUT LPWSTR lpDirectoryName, + IN OUT UINT* cchDirectoryName); +#ifdef UNICODE +#define PAL_GetPALDirectory PAL_GetPALDirectoryW +#else +#define PAL_GetPALDirectory PAL_GetPALDirectoryA +#endif + +PALIMPORT +VOID +PALAPI +PAL_Random( + IN OUT LPVOID lpBuffer, + IN DWORD dwLength); + +PALIMPORT +BOOL +PALAPI +PAL_ProbeMemory( + PVOID pBuffer, + DWORD cbBuffer, + BOOL fWriteAccess); + +/******************* winuser.h Entrypoints *******************************/ +PALIMPORT +LPSTR +PALAPI +CharNextA( + IN LPCSTR lpsz); + +PALIMPORT +LPSTR +PALAPI +CharNextExA( + IN WORD CodePage, + IN LPCSTR lpCurrentChar, + IN DWORD dwFlags); + +#ifndef UNICODE +#define CharNext CharNextA +#define CharNextEx CharNextExA +#endif + + +#define MB_OK 0x00000000L +#define MB_OKCANCEL 0x00000001L +#define MB_ABORTRETRYIGNORE 0x00000002L +#define MB_YESNO 0x00000004L +#define MB_RETRYCANCEL 0x00000005L + +#define MB_ICONHAND 0x00000010L +#define MB_ICONQUESTION 0x00000020L +#define MB_ICONEXCLAMATION 0x00000030L +#define MB_ICONASTERISK 0x00000040L + +#define MB_ICONINFORMATION MB_ICONASTERISK +#define MB_ICONSTOP MB_ICONHAND +#define MB_ICONERROR MB_ICONHAND + +#define MB_DEFBUTTON1 0x00000000L +#define MB_DEFBUTTON2 0x00000100L +#define MB_DEFBUTTON3 0x00000200L + +#define MB_SYSTEMMODAL 0x00001000L +#define MB_TASKMODAL 0x00002000L +#define MB_SETFOREGROUND 0x00010000L +#define MB_TOPMOST 0x00040000L + +#define MB_NOFOCUS 0x00008000L +#define MB_DEFAULT_DESKTOP_ONLY 0x00020000L + +// Note: this is the NT 4.0 and greater value. +#define MB_SERVICE_NOTIFICATION 0x00200000L + +#define MB_TYPEMASK 0x0000000FL +#define MB_ICONMASK 0x000000F0L +#define MB_DEFMASK 0x00000F00L + +#define IDOK 1 +#define IDCANCEL 2 +#define IDABORT 3 +#define IDRETRY 4 +#define IDIGNORE 5 +#define IDYES 6 +#define IDNO 7 + + +PALIMPORT +int +PALAPI +MessageBoxW( + IN LPVOID hWnd, // NOTE: diff from winuser.h + IN LPCWSTR lpText, + IN LPCWSTR lpCaption, + IN UINT uType); + + +#ifdef UNICODE +#define MessageBox MessageBoxW +#else +#define MessageBox MessageBoxA +#endif + +// From win32.h +#ifndef _CRTIMP +#ifdef __GNUC__ +#define _CRTIMP +#else // __GNUC__ +#define _CRTIMP __declspec(dllimport) +#endif // __GNUC__ +#endif // _CRTIMP + +/******************* winbase.h Entrypoints and defines ************************/ +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; + +#define _SH_DENYWR 0x20 /* deny write mode */ + +#define FILE_READ_DATA ( 0x0001 ) // file & pipe +#define FILE_APPEND_DATA ( 0x0004 ) // file + +#define GENERIC_READ (0x80000000L) +#define GENERIC_WRITE (0x40000000L) + +#define FILE_SHARE_READ 0x00000001 +#define FILE_SHARE_WRITE 0x00000002 +#define FILE_SHARE_DELETE 0x00000004 + +#define CREATE_NEW 1 +#define CREATE_ALWAYS 2 +#define OPEN_EXISTING 3 +#define OPEN_ALWAYS 4 +#define TRUNCATE_EXISTING 5 + +#define FILE_ATTRIBUTE_READONLY 0x00000001 +#define FILE_ATTRIBUTE_HIDDEN 0x00000002 +#define FILE_ATTRIBUTE_SYSTEM 0x00000004 +#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 +#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 +#define FILE_ATTRIBUTE_DEVICE 0x00000040 +#define FILE_ATTRIBUTE_NORMAL 0x00000080 + +#define FILE_FLAG_WRITE_THROUGH 0x80000000 +#define FILE_FLAG_NO_BUFFERING 0x20000000 +#define FILE_FLAG_RANDOM_ACCESS 0x10000000 +#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000 +#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 + +#define FILE_BEGIN 0 +#define FILE_CURRENT 1 +#define FILE_END 2 + +#define STILL_ACTIVE (0x00000103L) + +#define INVALID_SET_FILE_POINTER ((DWORD)-1) + + +PALIMPORT +HANDLE +PALAPI +CreateFileW( + IN LPCWSTR lpFileName, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, + IN DWORD dwCreationDisposition, + IN DWORD dwFlagsAndAttributes, + IN HANDLE hTemplateFile); + +#ifdef UNICODE +#define CreateFile CreateFileW +#else +#define CreateFile CreateFileA +#endif + + +PALIMPORT +DWORD +PALAPI +SearchPathW( + IN LPCWSTR lpPath, + IN LPCWSTR lpFileName, + IN LPCWSTR lpExtension, + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer, + OUT LPWSTR *lpFilePart + ); +#ifdef UNICODE +#define SearchPath SearchPathW +#else +#define SearchPath SearchPathA +#endif // !UNICODE + + + +PALIMPORT +BOOL +PALAPI +CopyFileW( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN BOOL bFailIfExists); + +#ifdef UNICODE +#define CopyFile CopyFileW +#else +#define CopyFile CopyFileA +#endif + + +PALIMPORT +BOOL +PALAPI +DeleteFileW( + IN LPCWSTR lpFileName); + +#ifdef UNICODE +#define DeleteFile DeleteFileW +#else +#define DeleteFile DeleteFileA +#endif + + + +#define MOVEFILE_REPLACE_EXISTING 0x00000001 +#define MOVEFILE_COPY_ALLOWED 0x00000002 + + +PALIMPORT +BOOL +PALAPI +MoveFileExW( + IN LPCWSTR lpExistingFileName, + IN LPCWSTR lpNewFileName, + IN DWORD dwFlags); + +#ifdef UNICODE +#define MoveFileEx MoveFileExW +#else +#define MoveFileEx MoveFileExA +#endif + +PALIMPORT +BOOL +PALAPI +CreateDirectoryW( + IN LPCWSTR lpPathName, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes); + +#ifdef UNICODE +#define CreateDirectory CreateDirectoryW +#else +#define CreateDirectory CreateDirectoryA +#endif + +PALIMPORT +BOOL +PALAPI +RemoveDirectoryW( + IN LPCWSTR lpPathName); + +#ifdef UNICODE +#define RemoveDirectory RemoveDirectoryW +#else +#define RemoveDirectory RemoveDirectoryA +#endif + +typedef struct _BY_HANDLE_FILE_INFORMATION { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD dwVolumeSerialNumber; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD nNumberOfLinks; + DWORD nFileIndexHigh; + DWORD nFileIndexLow; +} BY_HANDLE_FILE_INFORMATION, *PBY_HANDLE_FILE_INFORMATION, *LPBY_HANDLE_FILE_INFORMATION; + +typedef struct _WIN32_FIND_DATAA { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + CHAR cFileName[ MAX_PATH_FNAME ]; + CHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA; + +typedef struct _WIN32_FIND_DATAW { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; + DWORD dwReserved0; + DWORD dwReserved1; + WCHAR cFileName[ MAX_PATH_FNAME ]; + WCHAR cAlternateFileName[ 14 ]; +} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW; + +#ifdef UNICODE +typedef WIN32_FIND_DATAW WIN32_FIND_DATA; +typedef PWIN32_FIND_DATAW PWIN32_FIND_DATA; +typedef LPWIN32_FIND_DATAW LPWIN32_FIND_DATA; +#else +typedef WIN32_FIND_DATAA WIN32_FIND_DATA; +typedef PWIN32_FIND_DATAA PWIN32_FIND_DATA; +typedef LPWIN32_FIND_DATAA LPWIN32_FIND_DATA; +#endif + +PALIMPORT +HANDLE +PALAPI +FindFirstFileW( + IN LPCWSTR lpFileName, + OUT LPWIN32_FIND_DATAW lpFindFileData); + +#ifdef UNICODE +#define FindFirstFile FindFirstFileW +#else +#define FindFirstFile FindFirstFileA +#endif + +PALIMPORT +BOOL +PALAPI +FindNextFileW( + IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAW lpFindFileData); + +#ifdef UNICODE +#define FindNextFile FindNextFileW +#else +#define FindNextFile FindNextFileA +#endif + +PALIMPORT +BOOL +PALAPI +FindClose( + IN OUT HANDLE hFindFile); + +PALIMPORT +DWORD +PALAPI +GetFileAttributesW( + IN LPCWSTR lpFileName); + +#ifdef UNICODE +#define GetFileAttributes GetFileAttributesW +#else +#define GetFileAttributes GetFileAttributesA +#endif + +typedef enum _GET_FILEEX_INFO_LEVELS { + GetFileExInfoStandard +} GET_FILEEX_INFO_LEVELS; + +typedef enum _FINDEX_INFO_LEVELS { + FindExInfoStandard, + FindExInfoBasic, + FindExInfoMaxInfoLevel +} FINDEX_INFO_LEVELS; + +typedef enum _FINDEX_SEARCH_OPS { + FindExSearchNameMatch, + FindExSearchLimitToDirectories, + FindExSearchLimitToDevices, + FindExSearchMaxSearchOp +} FINDEX_SEARCH_OPS; + +typedef struct _WIN32_FILE_ATTRIBUTE_DATA { + DWORD dwFileAttributes; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + DWORD nFileSizeHigh; + DWORD nFileSizeLow; +} WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA; + +PALIMPORT +BOOL +PALAPI +GetFileAttributesExW( + IN LPCWSTR lpFileName, + IN GET_FILEEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFileInformation); + +#ifdef UNICODE +#define GetFileAttributesEx GetFileAttributesExW +#endif + +PALIMPORT +BOOL +PALAPI +SetFileAttributesW( + IN LPCWSTR lpFileName, + IN DWORD dwFileAttributes); + +#ifdef UNICODE +#define SetFileAttributes SetFileAttributesW +#else +#define SetFileAttributes SetFileAttributesA +#endif + +typedef struct _OVERLAPPED { + ULONG_PTR Internal; + ULONG_PTR InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +PALIMPORT +BOOL +PALAPI +WriteFile( + IN HANDLE hFile, + IN LPCVOID lpBuffer, + IN DWORD nNumberOfBytesToWrite, + OUT LPDWORD lpNumberOfBytesWritten, + IN LPOVERLAPPED lpOverlapped); + +PALIMPORT +BOOL +PALAPI +ReadFile( + IN HANDLE hFile, + OUT LPVOID lpBuffer, + IN DWORD nNumberOfBytesToRead, + OUT LPDWORD lpNumberOfBytesRead, + IN LPOVERLAPPED lpOverlapped); + +#define STD_INPUT_HANDLE ((DWORD)-10) +#define STD_OUTPUT_HANDLE ((DWORD)-11) +#define STD_ERROR_HANDLE ((DWORD)-12) + +PALIMPORT +HANDLE +PALAPI +GetStdHandle( + IN DWORD nStdHandle); + +PALIMPORT +BOOL +PALAPI +SetEndOfFile( + IN HANDLE hFile); + +PALIMPORT +DWORD +PALAPI +SetFilePointer( + IN HANDLE hFile, + IN LONG lDistanceToMove, + IN PLONG lpDistanceToMoveHigh, + IN DWORD dwMoveMethod); + +PALIMPORT +BOOL +PALAPI +SetFilePointerEx( + IN HANDLE hFile, + IN LARGE_INTEGER liDistanceToMove, + OUT PLARGE_INTEGER lpNewFilePointer, + IN DWORD dwMoveMethod); + +PALIMPORT +DWORD +PALAPI +GetFileSize( + IN HANDLE hFile, + OUT LPDWORD lpFileSizeHigh); + +PALIMPORT +BOOL +PALAPI GetFileSizeEx( + IN HANDLE hFile, + OUT PLARGE_INTEGER lpFileSize); + +PALIMPORT +BOOL +PALAPI +GetFileInformationByHandle( + IN HANDLE hFile, + OUT BY_HANDLE_FILE_INFORMATION* lpFileInformation); + +PALIMPORT +LONG +PALAPI +CompareFileTime( + IN CONST FILETIME *lpFileTime1, + IN CONST FILETIME *lpFileTime2); + +PALIMPORT +VOID +PALAPI +GetSystemTimeAsFileTime( + OUT LPFILETIME lpSystemTimeAsFileTime); + +typedef struct _SYSTEMTIME { + WORD wYear; + WORD wMonth; + WORD wDayOfWeek; + WORD wDay; + WORD wHour; + WORD wMinute; + WORD wSecond; + WORD wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + +PALIMPORT +VOID +PALAPI +GetSystemTime( + OUT LPSYSTEMTIME lpSystemTime); + +PALIMPORT +BOOL +PALAPI +FileTimeToSystemTime( + IN CONST FILETIME *lpFileTime, + OUT LPSYSTEMTIME lpSystemTime); + + + +PALIMPORT +BOOL +PALAPI +FlushFileBuffers( + IN HANDLE hFile); + +PALIMPORT +UINT +PALAPI +GetConsoleOutputCP( + VOID); + +PALIMPORT +DWORD +PALAPI +GetFullPathNameW( + IN LPCWSTR lpFileName, + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer, + OUT LPWSTR *lpFilePart); + +#ifdef UNICODE +#define GetFullPathName GetFullPathNameW +#else +#define GetFullPathName GetFullPathNameA +#endif + +PALIMPORT +DWORD +PALAPI +GetLongPathNameW( + IN LPCWSTR lpszShortPath, + OUT LPWSTR lpszLongPath, + IN DWORD cchBuffer); + +#ifdef UNICODE +#define GetLongPathName GetLongPathNameW +#endif + +PALIMPORT +DWORD +PALAPI +GetShortPathNameW( + IN LPCWSTR lpszLongPath, + OUT LPWSTR lpszShortPath, + IN DWORD cchBuffer); + +#ifdef UNICODE +#define GetShortPathName GetShortPathNameW +#endif + + +PALIMPORT +UINT +PALAPI +GetTempFileNameW( + IN LPCWSTR lpPathName, + IN LPCWSTR lpPrefixString, + IN UINT uUnique, + OUT LPWSTR lpTempFileName); + +#ifdef UNICODE +#define GetTempFileName GetTempFileNameW +#else +#define GetTempFileName GetTempFileNameA +#endif + +PALIMPORT +DWORD +PALAPI +GetTempPathW( + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer); + +PALIMPORT +DWORD +PALAPI +GetTempPathA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer); + + +#ifdef UNICODE +#define GetTempPath GetTempPathW +#else +#define GetTempPath GetTempPathA +#endif + +PALIMPORT +DWORD +PALAPI +GetCurrentDirectoryW( + IN DWORD nBufferLength, + OUT LPWSTR lpBuffer); + +#ifdef UNICODE +#define GetCurrentDirectory GetCurrentDirectoryW +#else +#define GetCurrentDirectory GetCurrentDirectoryA +#endif + +PALIMPORT +BOOL +PALAPI +SetCurrentDirectoryW( + IN LPCWSTR lpPathName); + + +#ifdef UNICODE +#define SetCurrentDirectory SetCurrentDirectoryW +#else +#define SetCurrentDirectory SetCurrentDirectoryA +#endif + +PALIMPORT +HANDLE +PALAPI +CreateSemaphoreW( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCWSTR lpName); + +PALIMPORT +HANDLE +PALAPI +CreateSemaphoreExW( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCWSTR lpName, + IN /*_Reserved_*/ DWORD dwFlags, + IN DWORD dwDesiredAccess); + +PALIMPORT +HANDLE +PALAPI +OpenSemaphoreW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName); + +#ifdef UNICODE +#define CreateSemaphore CreateSemaphoreW +#define CreateSemaphoreEx CreateSemaphoreExW +#else +#define CreateSemaphore CreateSemaphoreA +#define CreateSemaphoreEx CreateSemaphoreExA +#endif + +PALIMPORT +BOOL +PALAPI +ReleaseSemaphore( + IN HANDLE hSemaphore, + IN LONG lReleaseCount, + OUT LPLONG lpPreviousCount); + +PALIMPORT +HANDLE +PALAPI +CreateEventW( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCWSTR lpName); + +PALIMPORT +HANDLE +PALAPI +CreateEventExW( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN LPCWSTR lpName, + IN DWORD dwFlags, + IN DWORD dwDesiredAccess); + +// CreateEventExW: dwFlags +#define CREATE_EVENT_MANUAL_RESET ((DWORD)0x1) +#define CREATE_EVENT_INITIAL_SET ((DWORD)0x2) + +#ifdef UNICODE +#define CreateEvent CreateEventW +#else +#define CreateEvent CreateEventA +#endif + +PALIMPORT +BOOL +PALAPI +SetEvent( + IN HANDLE hEvent); + +PALIMPORT +BOOL +PALAPI +ResetEvent( + IN HANDLE hEvent); + +PALIMPORT +HANDLE +PALAPI +OpenEventW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName); + +#ifdef UNICODE +#define OpenEvent OpenEventW +#endif + +PALIMPORT +HANDLE +PALAPI +CreateMutexW( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN BOOL bInitialOwner, + IN LPCWSTR lpName); + +PALIMPORT +HANDLE +PALAPI +CreateMutexExW( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN LPCWSTR lpName, + IN DWORD dwFlags, + IN DWORD dwDesiredAccess); + +// CreateMutexExW: dwFlags +#define CREATE_MUTEX_INITIAL_OWNER ((DWORD)0x1) + +#ifdef UNICODE +#define CreateMutex CreateMutexW +#else +#define CreateMutex CreateMutexA +#endif + +PALIMPORT +HANDLE +PALAPI +OpenMutexW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName); + + +#ifdef UNICODE +#define OpenMutex OpenMutexW +#else +#define OpenMutex OpenMutexA +#endif // UNICODE + +PALIMPORT +BOOL +PALAPI +ReleaseMutex( + IN HANDLE hMutex); + +PALIMPORT +DWORD +PALAPI +GetCurrentProcessId( + VOID); + +PALIMPORT +DWORD +PALAPI +GetCurrentSessionId( + VOID); + +PALIMPORT +HANDLE +PALAPI +GetCurrentProcess( + VOID); + +PALIMPORT +DWORD +PALAPI +GetCurrentThreadId( + VOID); + +PALIMPORT +size_t +PALAPI +PAL_GetCurrentOSThreadId( + VOID); + +// To work around multiply-defined symbols in the Carbon framework. +#define GetCurrentThread PAL_GetCurrentThread +PALIMPORT +HANDLE +PALAPI +GetCurrentThread( + VOID); + + +#define STARTF_USESTDHANDLES 0x00000100 + +typedef struct _STARTUPINFOW { + DWORD cb; + LPWSTR lpReserved_PAL_Undefined; + LPWSTR lpDesktop_PAL_Undefined; + LPWSTR lpTitle_PAL_Undefined; + DWORD dwX_PAL_Undefined; + DWORD dwY_PAL_Undefined; + DWORD dwXSize_PAL_Undefined; + DWORD dwYSize_PAL_Undefined; + DWORD dwXCountChars_PAL_Undefined; + DWORD dwYCountChars_PAL_Undefined; + DWORD dwFillAttribute_PAL_Undefined; + DWORD dwFlags; + WORD wShowWindow_PAL_Undefined; + WORD cbReserved2_PAL_Undefined; + LPBYTE lpReserved2_PAL_Undefined; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; +} STARTUPINFOW, *LPSTARTUPINFOW; + +typedef struct _STARTUPINFOA { + DWORD cb; + LPSTR lpReserved_PAL_Undefined; + LPSTR lpDesktop_PAL_Undefined; + LPSTR lpTitle_PAL_Undefined; + DWORD dwX_PAL_Undefined; + DWORD dwY_PAL_Undefined; + DWORD dwXSize_PAL_Undefined; + DWORD dwYSize_PAL_Undefined; + DWORD dwXCountChars_PAL_Undefined; + DWORD dwYCountChars_PAL_Undefined; + DWORD dwFillAttribute_PAL_Undefined; + DWORD dwFlags; + WORD wShowWindow_PAL_Undefined; + WORD cbReserved2_PAL_Undefined; + LPBYTE lpReserved2_PAL_Undefined; + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; +} STARTUPINFOA, *LPSTARTUPINFOA; + +#ifdef UNICODE +typedef STARTUPINFOW STARTUPINFO; +typedef LPSTARTUPINFOW LPSTARTUPINFO; +#else +typedef STARTUPINFOA STARTUPINFO; +typedef LPSTARTUPINFOW LPSTARTUPINFO; +#endif + +#define CREATE_NEW_CONSOLE 0x00000010 + +#define NORMAL_PRIORITY_CLASS 0x00000020 + +typedef struct _PROCESS_INFORMATION { + HANDLE hProcess; + HANDLE hThread; + DWORD dwProcessId; + DWORD dwThreadId_PAL_Undefined; +} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; + +PALIMPORT +BOOL +PALAPI +CreateProcessW( + IN LPCWSTR lpApplicationName, + IN LPWSTR lpCommandLine, + IN LPSECURITY_ATTRIBUTES lpProcessAttributes, + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN BOOL bInheritHandles, + IN DWORD dwCreationFlags, + IN LPVOID lpEnvironment, + IN LPCWSTR lpCurrentDirectory, + IN LPSTARTUPINFOW lpStartupInfo, + OUT LPPROCESS_INFORMATION lpProcessInformation); + +#ifdef UNICODE +#define CreateProcess CreateProcessW +#else +#define CreateProcess CreateProcessA +#endif + +PALIMPORT +PAL_NORETURN +VOID +PALAPI +ExitProcess( + IN UINT uExitCode); + +PALIMPORT +BOOL +PALAPI +TerminateProcess( + IN HANDLE hProcess, + IN UINT uExitCode); + +PALIMPORT +BOOL +PALAPI +GetExitCodeProcess( + IN HANDLE hProcess, + IN LPDWORD lpExitCode); + +PALIMPORT +BOOL +PALAPI +GetProcessTimes( + IN HANDLE hProcess, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime); + +#define MAXIMUM_WAIT_OBJECTS 64 +#define WAIT_OBJECT_0 0 +#define WAIT_ABANDONED 0x00000080 +#define WAIT_ABANDONED_0 0x00000080 +#define WAIT_TIMEOUT 258 +#define WAIT_FAILED ((DWORD)0xFFFFFFFF) + +#define INFINITE 0xFFFFFFFF // Infinite timeout + +PALIMPORT +DWORD +PALAPI +WaitForSingleObject( + IN HANDLE hHandle, + IN DWORD dwMilliseconds); + +PALIMPORT +DWORD +PALAPI +PAL_WaitForSingleObjectPrioritized( + IN HANDLE hHandle, + IN DWORD dwMilliseconds); + +PALIMPORT +DWORD +PALAPI +WaitForSingleObjectEx( + IN HANDLE hHandle, + IN DWORD dwMilliseconds, + IN BOOL bAlertable); + +PALIMPORT +DWORD +PALAPI +WaitForMultipleObjects( + IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds); + +PALIMPORT +DWORD +PALAPI +WaitForMultipleObjectsEx( + IN DWORD nCount, + IN CONST HANDLE *lpHandles, + IN BOOL bWaitAll, + IN DWORD dwMilliseconds, + IN BOOL bAlertable); + +PALIMPORT +DWORD +PALAPI +SignalObjectAndWait( + IN HANDLE hObjectToSignal, + IN HANDLE hObjectToWaitOn, + IN DWORD dwMilliseconds, + IN BOOL bAlertable); + +#define DUPLICATE_CLOSE_SOURCE 0x00000001 +#define DUPLICATE_SAME_ACCESS 0x00000002 + +PALIMPORT +BOOL +PALAPI +DuplicateHandle( + IN HANDLE hSourceProcessHandle, + IN HANDLE hSourceHandle, + IN HANDLE hTargetProcessHandle, + OUT LPHANDLE lpTargetHandle, + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN DWORD dwOptions); + +PALIMPORT +VOID +PALAPI +Sleep( + IN DWORD dwMilliseconds); + +PALIMPORT +DWORD +PALAPI +SleepEx( + IN DWORD dwMilliseconds, + IN BOOL bAlertable); + +PALIMPORT +BOOL +PALAPI +SwitchToThread( + VOID); + +#define DEBUG_PROCESS 0x00000001 +#define DEBUG_ONLY_THIS_PROCESS 0x00000002 +#define CREATE_SUSPENDED 0x00000004 +#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 + +PALIMPORT +HANDLE +PALAPI +CreateThread( + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN DWORD dwStackSize, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter, + IN DWORD dwCreationFlags, + OUT LPDWORD lpThreadId); + +PALIMPORT +HANDLE +PALAPI +PAL_CreateThread64( + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN DWORD dwStackSize, + IN LPTHREAD_START_ROUTINE lpStartAddress, + IN LPVOID lpParameter, + IN DWORD dwCreationFlags, + OUT SIZE_T* pThreadId); + +PALIMPORT +PAL_NORETURN +VOID +PALAPI +ExitThread( + IN DWORD dwExitCode); + +PALIMPORT +DWORD +PALAPI +ResumeThread( + IN HANDLE hThread); + +typedef VOID (PALAPI_NOEXPORT *PAPCFUNC)(ULONG_PTR dwParam); + +PALIMPORT +DWORD +PALAPI +QueueUserAPC( + IN PAPCFUNC pfnAPC, + IN HANDLE hThread, + IN ULONG_PTR dwData); + +#ifdef _X86_ + +// +// *********************************************************************************** +// +// NOTE: These context definitions are replicated in ndp/clr/src/debug/inc/DbgTargetContext.h (for the +// purposes manipulating contexts from different platforms during remote debugging). Be sure to keep those +// definitions in sync if you make any changes here. +// +// *********************************************************************************** +// + +#define SIZE_OF_80387_REGISTERS 80 + +#define CONTEXT_i386 0x00010000 +#define CONTEXT_CONTROL (CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP +#define CONTEXT_INTEGER (CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI +#define CONTEXT_SEGMENTS (CONTEXT_i386 | 0x00000004L) +#define CONTEXT_FLOATING_POINT (CONTEXT_i386 | 0x00000008L) // 387 state +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_i386 | 0x00000010L) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS) +#define CONTEXT_EXTENDED_REGISTERS (CONTEXT_i386 | 0x00000020L) +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS | CONTEXT_EXTENDED_REGISTERS) + +#define MAXIMUM_SUPPORTED_EXTENSION 512 + +#define CONTEXT_XSTATE (CONTEXT_i386 | 0x40L) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000L +#define CONTEXT_SERVICE_ACTIVE 0x10000000L +#define CONTEXT_EXCEPTION_REQUEST 0x40000000L +#define CONTEXT_EXCEPTION_REPORTING 0x80000000L + +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +typedef struct _FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[SIZE_OF_80387_REGISTERS]; + DWORD Cr0NpxState; +} FLOATING_SAVE_AREA; + +typedef FLOATING_SAVE_AREA *PFLOATING_SAVE_AREA; + +typedef struct _CONTEXT { + ULONG ContextFlags; + + ULONG Dr0_PAL_Undefined; + ULONG Dr1_PAL_Undefined; + ULONG Dr2_PAL_Undefined; + ULONG Dr3_PAL_Undefined; + ULONG Dr6_PAL_Undefined; + ULONG Dr7_PAL_Undefined; + + FLOATING_SAVE_AREA FloatSave; + + ULONG SegGs_PAL_Undefined; + ULONG SegFs_PAL_Undefined; + ULONG SegEs_PAL_Undefined; + ULONG SegDs_PAL_Undefined; + + ULONG Edi; + ULONG Esi; + ULONG Ebx; + ULONG Edx; + ULONG Ecx; + ULONG Eax; + + ULONG Ebp; + ULONG Eip; + ULONG SegCs; + ULONG EFlags; + ULONG Esp; + ULONG SegSs; + + UCHAR ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION]; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// To support saving and loading xmm register context we need to know the offset in the ExtendedRegisters +// section at which they are stored. This has been determined experimentally since I have found no +// documentation thus far but it corresponds to the offset we'd expect if a fxsave instruction was used to +// store the regular FP state along with the XMM registers at the start of the extended registers section. +// Technically the offset doesn't really matter if no code in the PAL or runtime knows what the offset should +// be either (as long as we're consistent across GetThreadContext() and SetThreadContext() and we don't +// support any other values in the ExtendedRegisters) but we might as well be as accurate as we can. +#define CONTEXT_EXREG_XMM_OFFSET 160 + +typedef struct _KNONVOLATILE_CONTEXT { + + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Ebp; + +} KNONVOLATILE_CONTEXT, *PKNONVOLATILE_CONTEXT; + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + // The ordering of these fields should be aligned with that + // of corresponding fields in CONTEXT + // + // (See FillRegDisplay in inc/regdisp.h for details) + PDWORD Edi; + PDWORD Esi; + PDWORD Ebx; + PDWORD Edx; + PDWORD Ecx; + PDWORD Eax; + + PDWORD Ebp; + +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + +#elif defined(_AMD64_) +// copied from winnt.h + +#define CONTEXT_AMD64 0x100000 + +#define CONTEXT_CONTROL (CONTEXT_AMD64 | 0x1L) +#define CONTEXT_INTEGER (CONTEXT_AMD64 | 0x2L) +#define CONTEXT_SEGMENTS (CONTEXT_AMD64 | 0x4L) +#define CONTEXT_FLOATING_POINT (CONTEXT_AMD64 | 0x8L) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_AMD64 | 0x10L) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_SEGMENTS | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define CONTEXT_XSTATE (CONTEXT_AMD64 | 0x40L) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000 +#define CONTEXT_SERVICE_ACTIVE 0x10000000 +#define CONTEXT_EXCEPTION_REQUEST 0x40000000 +#define CONTEXT_EXCEPTION_REPORTING 0x80000000 + +typedef struct DECLSPEC_ALIGN(16) _M128A { + ULONGLONG Low; + LONGLONG High; +} M128A, *PM128A; + +typedef struct _XMM_SAVE_AREA32 { + WORD ControlWord; + WORD StatusWord; + BYTE TagWord; + BYTE Reserved1; + WORD ErrorOpcode; + DWORD ErrorOffset; + WORD ErrorSelector; + WORD Reserved2; + DWORD DataOffset; + WORD DataSelector; + WORD Reserved3; + DWORD MxCsr; + DWORD MxCsr_Mask; + M128A FloatRegisters[8]; + M128A XmmRegisters[16]; + BYTE Reserved4[96]; +} XMM_SAVE_AREA32, *PXMM_SAVE_AREA32; + +#define LEGACY_SAVE_AREA_LENGTH sizeof(XMM_SAVE_AREA32) + +// +// Context Frame +// +// This frame has a several purposes: 1) it is used as an argument to +// NtContinue, 2) is is used to constuct a call frame for APC delivery, +// and 3) it is used in the user level thread creation routines. +// +// +// The flags field within this record controls the contents of a CONTEXT +// record. +// +// If the context record is used as an input parameter, then for each +// portion of the context record controlled by a flag whose value is +// set, it is assumed that that portion of the context record contains +// valid context. If the context record is being used to modify a threads +// context, then only that portion of the threads context is modified. +// +// If the context record is used as an output parameter to capture the +// context of a thread, then only those portions of the thread's context +// corresponding to set flags will be returned. +// +// CONTEXT_CONTROL specifies SegSs, Rsp, SegCs, Rip, and EFlags. +// +// CONTEXT_INTEGER specifies Rax, Rcx, Rdx, Rbx, Rbp, Rsi, Rdi, and R8-R15. +// +// CONTEXT_SEGMENTS specifies SegDs, SegEs, SegFs, and SegGs. +// +// CONTEXT_DEBUG_REGISTERS specifies Dr0-Dr3 and Dr6-Dr7. +// +// CONTEXT_MMX_REGISTERS specifies the floating point and extended registers +// Mm0/St0-Mm7/St7 and Xmm0-Xmm15). +// + +typedef struct DECLSPEC_ALIGN(16) _CONTEXT { + + // + // Register parameter home addresses. + // + // N.B. These fields are for convience - they could be used to extend the + // context record in the future. + // + + DWORD64 P1Home; + DWORD64 P2Home; + DWORD64 P3Home; + DWORD64 P4Home; + DWORD64 P5Home; + DWORD64 P6Home; + + // + // Control flags. + // + + DWORD ContextFlags; + DWORD MxCsr; + + // + // Segment Registers and processor flags. + // + + WORD SegCs; + WORD SegDs; + WORD SegEs; + WORD SegFs; + WORD SegGs; + WORD SegSs; + DWORD EFlags; + + // + // Debug registers + // + + DWORD64 Dr0; + DWORD64 Dr1; + DWORD64 Dr2; + DWORD64 Dr3; + DWORD64 Dr6; + DWORD64 Dr7; + + // + // Integer registers. + // + + DWORD64 Rax; + DWORD64 Rcx; + DWORD64 Rdx; + DWORD64 Rbx; + DWORD64 Rsp; + DWORD64 Rbp; + DWORD64 Rsi; + DWORD64 Rdi; + DWORD64 R8; + DWORD64 R9; + DWORD64 R10; + DWORD64 R11; + DWORD64 R12; + DWORD64 R13; + DWORD64 R14; + DWORD64 R15; + + // + // Program counter. + // + + DWORD64 Rip; + + // + // Floating point state. + // + + union { + XMM_SAVE_AREA32 FltSave; + struct { + M128A Header[2]; + M128A Legacy[8]; + M128A Xmm0; + M128A Xmm1; + M128A Xmm2; + M128A Xmm3; + M128A Xmm4; + M128A Xmm5; + M128A Xmm6; + M128A Xmm7; + M128A Xmm8; + M128A Xmm9; + M128A Xmm10; + M128A Xmm11; + M128A Xmm12; + M128A Xmm13; + M128A Xmm14; + M128A Xmm15; + }; + }; + + // + // Vector registers. + // + + M128A VectorRegister[26]; + DWORD64 VectorControl; + + // + // Special debug control registers. + // + + DWORD64 DebugControl; + DWORD64 LastBranchToRip; + DWORD64 LastBranchFromRip; + DWORD64 LastExceptionToRip; + DWORD64 LastExceptionFromRip; +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// +// Nonvolatile context pointer record. +// + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + union { + PM128A FloatingContext[16]; + struct { + PM128A Xmm0; + PM128A Xmm1; + PM128A Xmm2; + PM128A Xmm3; + PM128A Xmm4; + PM128A Xmm5; + PM128A Xmm6; + PM128A Xmm7; + PM128A Xmm8; + PM128A Xmm9; + PM128A Xmm10; + PM128A Xmm11; + PM128A Xmm12; + PM128A Xmm13; + PM128A Xmm14; + PM128A Xmm15; + } ; + } ; + + union { + PDWORD64 IntegerContext[16]; + struct { + PDWORD64 Rax; + PDWORD64 Rcx; + PDWORD64 Rdx; + PDWORD64 Rbx; + PDWORD64 Rsp; + PDWORD64 Rbp; + PDWORD64 Rsi; + PDWORD64 Rdi; + PDWORD64 R8; + PDWORD64 R9; + PDWORD64 R10; + PDWORD64 R11; + PDWORD64 R12; + PDWORD64 R13; + PDWORD64 R14; + PDWORD64 R15; + } ; + } ; + +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + +#elif defined(_ARM_) + +#define CONTEXT_ARM 0x00200000L + +// end_wx86 + +#define CONTEXT_CONTROL (CONTEXT_ARM | 0x1L) +#define CONTEXT_INTEGER (CONTEXT_ARM | 0x2L) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM | 0x4L) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM | 0x8L) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000L +#define CONTEXT_SERVICE_ACTIVE 0x10000000L +#define CONTEXT_EXCEPTION_REQUEST 0x40000000L +#define CONTEXT_EXCEPTION_REPORTING 0x80000000L + +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +// +// Specify the number of breakpoints and watchpoints that the OS +// will track. Architecturally, ARM supports up to 16. In practice, +// however, almost no one implements more than 4 of each. +// + +#define ARM_MAX_BREAKPOINTS 8 +#define ARM_MAX_WATCHPOINTS 1 + +typedef struct _NEON128 { + ULONGLONG Low; + LONGLONG High; +} NEON128, *PNEON128; + +// +// Context Frame +// +// This frame has a several purposes: 1) it is used as an argument to +// NtContinue, 2) it is used to constuct a call frame for APC delivery, +// and 3) it is used in the user level thread creation routines. +// +// +// The flags field within this record controls the contents of a CONTEXT +// record. +// +// If the context record is used as an input parameter, then for each +// portion of the context record controlled by a flag whose value is +// set, it is assumed that that portion of the context record contains +// valid context. If the context record is being used to modify a threads +// context, then only that portion of the threads context is modified. +// +// If the context record is used as an output parameter to capture the +// context of a thread, then only those portions of the thread's context +// corresponding to set flags will be returned. +// +// CONTEXT_CONTROL specifies Sp, Lr, Pc, and Cpsr +// +// CONTEXT_INTEGER specifies R0-R12 +// +// CONTEXT_FLOATING_POINT specifies Q0-Q15 / D0-D31 / S0-S31 +// +// CONTEXT_DEBUG_REGISTERS specifies up to 16 of DBGBVR, DBGBCR, DBGWVR, +// DBGWCR. +// + +typedef struct DECLSPEC_ALIGN(8) _CONTEXT { + + // + // Control flags. + // + + DWORD ContextFlags; + + // + // Integer registers + // + + DWORD R0; + DWORD R1; + DWORD R2; + DWORD R3; + DWORD R4; + DWORD R5; + DWORD R6; + DWORD R7; + DWORD R8; + DWORD R9; + DWORD R10; + DWORD R11; + DWORD R12; + + // + // Control Registers + // + + DWORD Sp; + DWORD Lr; + DWORD Pc; + DWORD Cpsr; + + // + // Floating Point/NEON Registers + // + + DWORD Fpscr; + DWORD Padding; + union { + NEON128 Q[16]; + ULONGLONG D[32]; + DWORD S[32]; + }; + + // + // Debug registers + // + + DWORD Bvr[ARM_MAX_BREAKPOINTS]; + DWORD Bcr[ARM_MAX_BREAKPOINTS]; + DWORD Wvr[ARM_MAX_WATCHPOINTS]; + DWORD Wcr[ARM_MAX_WATCHPOINTS]; + + DWORD Padding2[2]; + +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// +// Nonvolatile context pointer record. +// + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD R4; + PDWORD R5; + PDWORD R6; + PDWORD R7; + PDWORD R8; + PDWORD R9; + PDWORD R10; + PDWORD R11; + PDWORD Lr; + + PULONGLONG D8; + PULONGLONG D9; + PULONGLONG D10; + PULONGLONG D11; + PULONGLONG D12; + PULONGLONG D13; + PULONGLONG D14; + PULONGLONG D15; + +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + +typedef struct _IMAGE_ARM_RUNTIME_FUNCTION_ENTRY { + DWORD BeginAddress; + DWORD EndAddress; + union { + DWORD UnwindData; + struct { + DWORD Flag : 2; + DWORD FunctionLength : 11; + DWORD Ret : 2; + DWORD H : 1; + DWORD Reg : 3; + DWORD R : 1; + DWORD L : 1; + DWORD C : 1; + DWORD StackAdjust : 10; + }; + }; +} IMAGE_ARM_RUNTIME_FUNCTION_ENTRY, * PIMAGE_ARM_RUNTIME_FUNCTION_ENTRY; + +#elif defined(_ARM64_) + +#define CONTEXT_ARM64 0x00400000L + +#define CONTEXT_CONTROL (CONTEXT_ARM64 | 0x1L) +#define CONTEXT_INTEGER (CONTEXT_ARM64 | 0x2L) +#define CONTEXT_FLOATING_POINT (CONTEXT_ARM64 | 0x4L) +#define CONTEXT_DEBUG_REGISTERS (CONTEXT_ARM64 | 0x8L) + +#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) + +#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS) + +#define CONTEXT_EXCEPTION_ACTIVE 0x8000000L +#define CONTEXT_SERVICE_ACTIVE 0x10000000L +#define CONTEXT_EXCEPTION_REQUEST 0x40000000L +#define CONTEXT_EXCEPTION_REPORTING 0x80000000L + +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + +// +// Define initial Cpsr/Fpscr value +// + +#define INITIAL_CPSR 0x10 +#define INITIAL_FPSCR 0 + +// begin_ntoshvp + +// +// Specify the number of breakpoints and watchpoints that the OS +// will track. Architecturally, ARM64 supports up to 16. In practice, +// however, almost no one implements more than 4 of each. +// + +#define ARM64_MAX_BREAKPOINTS 8 +#define ARM64_MAX_WATCHPOINTS 2 + +// +// Context Frame +// +// This frame has a several purposes: 1) it is used as an argument to +// NtContinue, 2) it is used to constuct a call frame for APC delivery, +// and 3) it is used in the user level thread creation routines. +// +// +// The flags field within this record controls the contents of a CONTEXT +// record. +// +// If the context record is used as an input parameter, then for each +// portion of the context record controlled by a flag whose value is +// set, it is assumed that that portion of the context record contains +// valid context. If the context record is being used to modify a threads +// context, then only that portion of the threads context is modified. +// +// If the context record is used as an output parameter to capture the +// context of a thread, then only those portions of the thread's context +// corresponding to set flags will be returned. +// +// CONTEXT_CONTROL specifies Sp, Lr, Pc, and Cpsr +// +// CONTEXT_INTEGER specifies R0-R12 +// +// CONTEXT_FLOATING_POINT specifies Q0-Q15 / D0-D31 / S0-S31 +// +// CONTEXT_DEBUG_REGISTERS specifies up to 16 of DBGBVR, DBGBCR, DBGWVR, +// DBGWCR. +// + +typedef struct _NEON128 { + ULONGLONG Low; + LONGLONG High; +} NEON128, *PNEON128; + +typedef struct DECLSPEC_ALIGN(16) _CONTEXT { + + // + // Control flags. + // + + /* +0x000 */ DWORD ContextFlags; + + // + // Integer registers + // + + /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel + /* +0x008 */ union { + struct { + DWORD64 X0; + DWORD64 X1; + DWORD64 X2; + DWORD64 X3; + DWORD64 X4; + DWORD64 X5; + DWORD64 X6; + DWORD64 X7; + DWORD64 X8; + DWORD64 X9; + DWORD64 X10; + DWORD64 X11; + DWORD64 X12; + DWORD64 X13; + DWORD64 X14; + DWORD64 X15; + DWORD64 X16; + DWORD64 X17; + DWORD64 X18; + DWORD64 X19; + DWORD64 X20; + DWORD64 X21; + DWORD64 X22; + DWORD64 X23; + DWORD64 X24; + DWORD64 X25; + DWORD64 X26; + DWORD64 X27; + DWORD64 X28; + }; + DWORD64 X[29]; + }; + /* +0x0f0 */ DWORD64 Fp; + /* +0x0f8 */ DWORD64 Lr; + /* +0x100 */ DWORD64 Sp; + /* +0x108 */ DWORD64 Pc; + + // + // Floating Point/NEON Registers + // + + /* +0x110 */ NEON128 V[32]; + /* +0x310 */ DWORD Fpcr; + /* +0x314 */ DWORD Fpsr; + + // + // Debug registers + // + + /* +0x318 */ DWORD Bcr[ARM64_MAX_BREAKPOINTS]; + /* +0x338 */ DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; + /* +0x378 */ DWORD Wcr[ARM64_MAX_WATCHPOINTS]; + /* +0x380 */ DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; + /* +0x390 */ + +} CONTEXT, *PCONTEXT, *LPCONTEXT; + +// +// Nonvolatile context pointer record. +// + +typedef struct _KNONVOLATILE_CONTEXT_POINTERS { + + PDWORD64 X19; + PDWORD64 X20; + PDWORD64 X21; + PDWORD64 X22; + PDWORD64 X23; + PDWORD64 X24; + PDWORD64 X25; + PDWORD64 X26; + PDWORD64 X27; + PDWORD64 X28; + PDWORD64 Fp; + PDWORD64 Lr; + + PDWORD64 D8; + PDWORD64 D9; + PDWORD64 D10; + PDWORD64 D11; + PDWORD64 D12; + PDWORD64 D13; + PDWORD64 D14; + PDWORD64 D15; + +} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; + +#else +#error Unknown architecture for defining CONTEXT. +#endif + + +PALIMPORT +BOOL +PALAPI +GetThreadContext( + IN HANDLE hThread, + IN OUT LPCONTEXT lpContext); + +PALIMPORT +BOOL +PALAPI +SetThreadContext( + IN HANDLE hThread, + IN CONST CONTEXT *lpContext); + +#define THREAD_BASE_PRIORITY_LOWRT 15 +#define THREAD_BASE_PRIORITY_MAX 2 +#define THREAD_BASE_PRIORITY_MIN (-2) +#define THREAD_BASE_PRIORITY_IDLE (-15) + +#define THREAD_PRIORITY_LOWEST THREAD_BASE_PRIORITY_MIN +#define THREAD_PRIORITY_BELOW_NORMAL (THREAD_PRIORITY_LOWEST+1) +#define THREAD_PRIORITY_NORMAL 0 +#define THREAD_PRIORITY_HIGHEST THREAD_BASE_PRIORITY_MAX +#define THREAD_PRIORITY_ABOVE_NORMAL (THREAD_PRIORITY_HIGHEST-1) +#define THREAD_PRIORITY_ERROR_RETURN (MAXLONG) + +#define THREAD_PRIORITY_TIME_CRITICAL THREAD_BASE_PRIORITY_LOWRT +#define THREAD_PRIORITY_IDLE THREAD_BASE_PRIORITY_IDLE + +PALIMPORT +int +PALAPI +GetThreadPriority( + IN HANDLE hThread); + +PALIMPORT +BOOL +PALAPI +SetThreadPriority( + IN HANDLE hThread, + IN int nPriority); + +PALIMPORT +BOOL +PALAPI +GetThreadTimes( + IN HANDLE hThread, + OUT LPFILETIME lpCreationTime, + OUT LPFILETIME lpExitTime, + OUT LPFILETIME lpKernelTime, + OUT LPFILETIME lpUserTime); + +#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF) + +PALIMPORT +DWORD +PALAPI +TlsAlloc( + VOID); + +PALIMPORT +LPVOID +PALAPI +TlsGetValue( + IN DWORD dwTlsIndex); + +PALIMPORT +BOOL +PALAPI +TlsSetValue( + IN DWORD dwTlsIndex, + IN LPVOID lpTlsValue); + +PALIMPORT +BOOL +PALAPI +TlsFree( + IN DWORD dwTlsIndex); + +PALIMPORT +PVOID +PALAPI +PAL_GetStackBase(VOID); + +PALIMPORT +PVOID +PALAPI +PAL_GetStackLimit(VOID); + +PALIMPORT +DWORD +PALAPI +PAL_GetLogicalCpuCountFromOS(VOID); + +PALIMPORT +DWORD +PALAPI +PAL_GetTotalCpuCount(VOID); + +PALIMPORT +size_t +PALAPI +PAL_GetRestrictedPhysicalMemoryLimit(VOID); + +PALIMPORT +BOOL +PALAPI +PAL_GetPhysicalMemoryUsed(size_t* val); + +PALIMPORT +BOOL +PALAPI +PAL_GetCpuLimit(UINT* val); + +PALIMPORT +size_t +PALAPI +PAL_GetLogicalProcessorCacheSizeFromOS(VOID); + +typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size); + +PALIMPORT BOOL PALAPI PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers); + +PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback); + +#define GetLogicalProcessorCacheSizeFromOS PAL_GetLogicalProcessorCacheSizeFromOS + +/* PAL_CS_NATIVE_DATA_SIZE is defined as sizeof(PAL_CRITICAL_SECTION_NATIVE_DATA) */ + +#if defined(__APPLE__) && defined(__i386__) +#define PAL_CS_NATIVE_DATA_SIZE 76 +#elif defined(__APPLE__) && defined(__x86_64__) +#define PAL_CS_NATIVE_DATA_SIZE 120 +#elif defined(__FreeBSD__) && defined(_X86_) +#define PAL_CS_NATIVE_DATA_SIZE 12 +#elif defined(__FreeBSD__) && defined(__x86_64__) +#define PAL_CS_NATIVE_DATA_SIZE 24 +#elif defined(__linux__) && defined(_ARM_) +#define PAL_CS_NATIVE_DATA_SIZE 80 +#elif defined(__linux__) && defined(_ARM64_) +#define PAL_CS_NATIVE_DATA_SIZE 116 +#elif defined(__linux__) && defined(__i386__) +#define PAL_CS_NATIVE_DATA_SIZE 76 +#elif defined(__linux__) && defined(__x86_64__) +#define PAL_CS_NATIVE_DATA_SIZE 96 +#elif defined(__NetBSD__) && defined(__amd64__) +#define PAL_CS_NATIVE_DATA_SIZE 96 +#elif defined(__NetBSD__) && defined(__earm__) +#define PAL_CS_NATIVE_DATA_SIZE 56 +#elif defined(__NetBSD__) && defined(__i386__) +#define PAL_CS_NATIVE_DATA_SIZE 56 +#else +#warning +#error PAL_CS_NATIVE_DATA_SIZE is not defined for this architecture +#endif + +// +typedef struct _CRITICAL_SECTION { + PVOID DebugInfo; + LONG LockCount; + LONG RecursionCount; + HANDLE OwningThread; + HANDLE LockSemaphore; + ULONG_PTR SpinCount; + + BOOL bInternal; + volatile DWORD dwInitState; + union CSNativeDataStorage + { + BYTE rgNativeDataStorage[PAL_CS_NATIVE_DATA_SIZE]; + PVOID pvAlign; // make sure the storage is machine-pointer-size aligned + } csnds; +} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; + +PALIMPORT VOID PALAPI EnterCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); +PALIMPORT VOID PALAPI LeaveCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); +PALIMPORT VOID PALAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection); +PALIMPORT BOOL PALAPI InitializeCriticalSectionEx(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD Flags); +PALIMPORT VOID PALAPI DeleteCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); +PALIMPORT BOOL PALAPI TryEnterCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); + +#define SEM_FAILCRITICALERRORS 0x0001 +#define SEM_NOOPENFILEERRORBOX 0x8000 + +PALIMPORT +UINT +PALAPI +SetErrorMode( + IN UINT uMode); + +#define PAGE_NOACCESS 0x01 +#define PAGE_READONLY 0x02 +#define PAGE_READWRITE 0x04 +#define PAGE_WRITECOPY 0x08 +#define PAGE_EXECUTE 0x10 +#define PAGE_EXECUTE_READ 0x20 +#define PAGE_EXECUTE_READWRITE 0x40 +#define PAGE_EXECUTE_WRITECOPY 0x80 +#define MEM_COMMIT 0x1000 +#define MEM_RESERVE 0x2000 +#define MEM_DECOMMIT 0x4000 +#define MEM_RELEASE 0x8000 +#define MEM_RESET 0x80000 +#define MEM_FREE 0x10000 +#define MEM_PRIVATE 0x20000 +#define MEM_MAPPED 0x40000 +#define MEM_TOP_DOWN 0x100000 +#define MEM_WRITE_WATCH 0x200000 +#define MEM_LARGE_PAGES 0x20000000 +#define MEM_RESERVE_EXECUTABLE 0x40000000 // reserve memory using executable memory allocator + +PALIMPORT +HANDLE +PALAPI +CreateFileMappingW( + IN HANDLE hFile, + IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + IN DWORD flProtect, + IN DWORD dwMaxmimumSizeHigh, + IN DWORD dwMaximumSizeLow, + IN LPCWSTR lpName); + +#ifdef UNICODE +#define CreateFileMapping CreateFileMappingW +#else +#define CreateFileMapping CreateFileMappingA +#endif + +#define SECTION_QUERY 0x0001 +#define SECTION_MAP_WRITE 0x0002 +#define SECTION_MAP_READ 0x0004 +#define SECTION_ALL_ACCESS (SECTION_MAP_READ | SECTION_MAP_WRITE) // diff from winnt.h + +#define FILE_MAP_WRITE SECTION_MAP_WRITE +#define FILE_MAP_READ SECTION_MAP_READ +#define FILE_MAP_ALL_ACCESS SECTION_ALL_ACCESS +#define FILE_MAP_COPY SECTION_QUERY + +PALIMPORT +HANDLE +PALAPI +OpenFileMappingW( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCWSTR lpName); + +#ifdef UNICODE +#define OpenFileMapping OpenFileMappingW +#else +#define OpenFileMapping OpenFileMappingA +#endif + +typedef INT_PTR (PALAPI_NOEXPORT *FARPROC)(); + +PALIMPORT +LPVOID +PALAPI +MapViewOfFile( + IN HANDLE hFileMappingObject, + IN DWORD dwDesiredAccess, + IN DWORD dwFileOffsetHigh, + IN DWORD dwFileOffsetLow, + IN SIZE_T dwNumberOfBytesToMap); + +PALIMPORT +LPVOID +PALAPI +MapViewOfFileEx( + IN HANDLE hFileMappingObject, + IN DWORD dwDesiredAccess, + IN DWORD dwFileOffsetHigh, + IN DWORD dwFileOffsetLow, + IN SIZE_T dwNumberOfBytesToMap, + IN LPVOID lpBaseAddress); + +PALIMPORT +BOOL +PALAPI +UnmapViewOfFile( + IN LPCVOID lpBaseAddress); + + +PALIMPORT +HMODULE +PALAPI +LoadLibraryW( + IN LPCWSTR lpLibFileName); + +PALIMPORT +HMODULE +PALAPI +LoadLibraryExW( + IN LPCWSTR lpLibFileName, + IN /*Reserved*/ HANDLE hFile, + IN DWORD dwFlags); + +PALIMPORT +NATIVE_LIBRARY_HANDLE +PALAPI +PAL_LoadLibraryDirect( + IN LPCWSTR lpLibFileName); + +PALIMPORT +BOOL +PALAPI +PAL_FreeLibraryDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle); + +PALIMPORT +FARPROC +PALAPI +PAL_GetProcAddressDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle, + IN LPCSTR lpProcName); + +/*++ +Function: + PAL_LOADLoadPEFile + +Abstract + Loads a PE file into memory. Properly maps all of the sections in the PE file. Returns a pointer to the + loaded base. + +Parameters: + IN hFile - The file to load + +Return value: + A valid base address if successful. + 0 if failure +--*/ +PALIMPORT +PVOID +PALAPI +PAL_LOADLoadPEFile(HANDLE hFile); + +/*++ + PAL_LOADUnloadPEFile + + Unload a PE file that was loaded by PAL_LOADLoadPEFile(). + +Parameters: + IN ptr - the file pointer returned by PAL_LOADLoadPEFile() + +Return value: + TRUE - success + FALSE - failure (incorrect ptr, etc.) +--*/ +PALIMPORT +BOOL +PALAPI +PAL_LOADUnloadPEFile(PVOID ptr); + +#ifdef UNICODE +#define LoadLibrary LoadLibraryW +#define LoadLibraryEx LoadLibraryExW +#else +#define LoadLibrary LoadLibraryA +#define LoadLibraryEx LoadLibraryExA +#endif + +PALIMPORT +FARPROC +PALAPI +GetProcAddress( + IN HMODULE hModule, + IN LPCSTR lpProcName); + +PALIMPORT +BOOL +PALAPI +FreeLibrary( + IN OUT HMODULE hLibModule); + +PALIMPORT +PAL_NORETURN +VOID +PALAPI +FreeLibraryAndExitThread( + IN HMODULE hLibModule, + IN DWORD dwExitCode); + +PALIMPORT +BOOL +PALAPI +DisableThreadLibraryCalls( + IN HMODULE hLibModule); + +PALIMPORT +DWORD +PALAPI +GetModuleFileNameW( + IN HMODULE hModule, + OUT LPWSTR lpFileName, + IN DWORD nSize); + +#ifdef UNICODE +#define GetModuleFileName GetModuleFileNameW +#else +#define GetModuleFileName GetModuleFileNameA +#endif + +PALIMPORT +DWORD +PALAPI +GetModuleFileNameExW( + IN HANDLE hProcess, + IN HMODULE hModule, + OUT LPWSTR lpFilename, + IN DWORD nSize + ); + +#ifdef UNICODE +#define GetModuleFileNameEx GetModuleFileNameExW +#endif + +// Get base address of the module containing a given symbol +PALIMPORT +LPCVOID +PALAPI +PAL_GetSymbolModuleBase(PVOID symbol); + +PALIMPORT +LPCSTR +PALAPI +PAL_GetLoadLibraryError(); + +PALIMPORT +LPVOID +PALAPI +PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange( + IN LPCVOID lpBeginAddress, + IN LPCVOID lpEndAddress, + IN SIZE_T dwSize); + +PALIMPORT +LPVOID +PALAPI +VirtualAlloc( + IN LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD flAllocationType, + IN DWORD flProtect); + +PALIMPORT +BOOL +PALAPI +VirtualFree( + IN LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD dwFreeType); + +PALIMPORT +BOOL +PALAPI +VirtualProtect( + IN LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD flNewProtect, + OUT PDWORD lpflOldProtect); + +typedef struct _MEMORYSTATUSEX { + DWORD dwLength; + DWORD dwMemoryLoad; + DWORDLONG ullTotalPhys; + DWORDLONG ullAvailPhys; + DWORDLONG ullTotalPageFile; + DWORDLONG ullAvailPageFile; + DWORDLONG ullTotalVirtual; + DWORDLONG ullAvailVirtual; + DWORDLONG ullAvailExtendedVirtual; +} MEMORYSTATUSEX, *LPMEMORYSTATUSEX; + +PALIMPORT +BOOL +PALAPI +GlobalMemoryStatusEx( + IN OUT LPMEMORYSTATUSEX lpBuffer); + +typedef struct _MEMORY_BASIC_INFORMATION { + PVOID BaseAddress; + PVOID AllocationBase_PAL_Undefined; + DWORD AllocationProtect; + SIZE_T RegionSize; + DWORD State; + DWORD Protect; + DWORD Type; +} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; + +PALIMPORT +SIZE_T +PALAPI +VirtualQuery( + IN LPCVOID lpAddress, + OUT PMEMORY_BASIC_INFORMATION lpBuffer, + IN SIZE_T dwLength); + +#define MoveMemory memmove +#define CopyMemory memcpy +#define FillMemory(Destination,Length,Fill) memset((Destination),(Fill),(Length)) +#define ZeroMemory(Destination,Length) memset((Destination),0,(Length)) + +PALIMPORT +HANDLE +PALAPI +GetProcessHeap( + VOID); + +#define HEAP_ZERO_MEMORY 0x00000008 + +PALIMPORT +HANDLE +PALAPI +HeapCreate( + IN DWORD flOptions, + IN SIZE_T dwInitialSize, + IN SIZE_T dwMaximumSize); + +PALIMPORT +LPVOID +PALAPI +HeapAlloc( + IN HANDLE hHeap, + IN DWORD dwFlags, + IN SIZE_T dwBytes); + +PALIMPORT +LPVOID +PALAPI +HeapReAlloc( + IN HANDLE hHeap, + IN DWORD dwFlags, + IN LPVOID lpMem, + IN SIZE_T dwBytes + ); + +PALIMPORT +BOOL +PALAPI +HeapFree( + IN HANDLE hHeap, + IN DWORD dwFlags, + IN LPVOID lpMem); + +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation, + HeapEnableTerminationOnCorruption +} HEAP_INFORMATION_CLASS; + +PALIMPORT +BOOL +PALAPI +HeapSetInformation( + IN OPTIONAL HANDLE HeapHandle, + IN HEAP_INFORMATION_CLASS HeapInformationClass, + IN PVOID HeapInformation, + IN SIZE_T HeapInformationLength); + +#define LMEM_FIXED 0x0000 +#define LMEM_MOVEABLE 0x0002 +#define LMEM_ZEROINIT 0x0040 +#define LPTR (LMEM_FIXED | LMEM_ZEROINIT) + +PALIMPORT +HLOCAL +PALAPI +LocalAlloc( + IN UINT uFlags, + IN SIZE_T uBytes); + +PALIMPORT +HLOCAL +PALAPI +LocalReAlloc( + IN HLOCAL hMem, + IN SIZE_T uBytes, + IN UINT uFlags); + +PALIMPORT +HLOCAL +PALAPI +LocalFree( + IN HLOCAL hMem); + +PALIMPORT +BOOL +PALAPI +FlushInstructionCache( + IN HANDLE hProcess, + IN LPCVOID lpBaseAddress, + IN SIZE_T dwSize); + +#define MAX_LEADBYTES 12 +#define MAX_DEFAULTCHAR 2 + +PALIMPORT +UINT +PALAPI +GetACP(void); + +typedef struct _cpinfo { + UINT MaxCharSize; + BYTE DefaultChar[MAX_DEFAULTCHAR]; + BYTE LeadByte[MAX_LEADBYTES]; +} CPINFO, *LPCPINFO; + +PALIMPORT +BOOL +PALAPI +GetCPInfo( + IN UINT CodePage, + OUT LPCPINFO lpCPInfo); + +PALIMPORT +BOOL +PALAPI +IsDBCSLeadByteEx( + IN UINT CodePage, + IN BYTE TestChar); + +PALIMPORT +BOOL +PALAPI +IsDBCSLeadByte( + IN BYTE TestChar); + +PALIMPORT +BOOL +PALAPI +IsValidCodePage( + IN UINT CodePage); + + +#define MB_PRECOMPOSED 0x00000001 +#define MB_ERR_INVALID_CHARS 0x00000008 + +PALIMPORT +int +PALAPI +MultiByteToWideChar( + IN UINT CodePage, + IN DWORD dwFlags, + IN LPCSTR lpMultiByteStr, + IN int cbMultiByte, + OUT LPWSTR lpWideCharStr, + IN int cchWideChar); + +#define WC_NO_BEST_FIT_CHARS 0x00000400 + +PALIMPORT +int +PALAPI +WideCharToMultiByte( + IN UINT CodePage, + IN DWORD dwFlags, + IN LPCWSTR lpWideCharStr, + IN int cchWideChar, + OUT LPSTR lpMultiByteStr, + IN int cbMultyByte, + IN LPCSTR lpDefaultChar, + OUT LPBOOL lpUsedDefaultChar); + +PALIMPORT +int +PALAPI +PAL_GetResourceString( + IN LPCSTR lpDomain, + IN LPCSTR lpResourceStr, + OUT LPWSTR lpWideCharStr, + IN int cchWideChar); + +PALIMPORT +BOOL +PALAPI +PAL_BindResources(IN LPCSTR lpDomain); + +#define EXCEPTION_NONCONTINUABLE 0x1 +#define EXCEPTION_UNWINDING 0x2 + +#ifdef FEATURE_PAL_SXS + +#define EXCEPTION_EXIT_UNWIND 0x4 // Exit unwind is in progress (not used by PAL SEH) +#define EXCEPTION_NESTED_CALL 0x10 // Nested exception handler call +#define EXCEPTION_TARGET_UNWIND 0x20 // Target unwind in progress +#define EXCEPTION_COLLIDED_UNWIND 0x40 // Collided exception handler call +#define EXCEPTION_SKIP_VEH 0x200 + +#define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \ + EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND) + +#define IS_DISPATCHING(Flag) ((Flag & EXCEPTION_UNWIND) == 0) +#define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0) +#define IS_TARGET_UNWIND(Flag) (Flag & EXCEPTION_TARGET_UNWIND) + +#endif // FEATURE_PAL_SXS + +#define EXCEPTION_IS_SIGNAL 0x100 + +#define EXCEPTION_MAXIMUM_PARAMETERS 15 + +// Index in the ExceptionInformation array where we will keep the reference +// to the native exception that needs to be deleted when dispatching +// exception in managed code. +#define NATIVE_EXCEPTION_ASYNC_SLOT (EXCEPTION_MAXIMUM_PARAMETERS-1) + +typedef struct _EXCEPTION_RECORD { + DWORD ExceptionCode; + DWORD ExceptionFlags; + struct _EXCEPTION_RECORD *ExceptionRecord; + PVOID ExceptionAddress; + DWORD NumberParameters; + ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD, *PEXCEPTION_RECORD; + +typedef struct _EXCEPTION_POINTERS { + PEXCEPTION_RECORD ExceptionRecord; + PCONTEXT ContextRecord; +} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS, *LPEXCEPTION_POINTERS; + +#ifdef FEATURE_PAL_SXS + +typedef LONG EXCEPTION_DISPOSITION; + +enum { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind, +}; + +#endif // FEATURE_PAL_SXS + +// +// A function table entry is generated for each frame function. +// +typedef struct _RUNTIME_FUNCTION { + DWORD BeginAddress; +#ifdef _TARGET_AMD64_ + DWORD EndAddress; +#endif + DWORD UnwindData; +} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; + +#define STANDARD_RIGHTS_REQUIRED (0x000F0000L) +#define SYNCHRONIZE (0x00100000L) +#define READ_CONTROL (0x00020000L) +#define MAXIMUM_ALLOWED (0x02000000L) + +#define EVENT_MODIFY_STATE (0x0002) +#define EVENT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3) + +#define MUTANT_QUERY_STATE (0x0001) +#define MUTANT_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | MUTANT_QUERY_STATE) +#define MUTEX_ALL_ACCESS MUTANT_ALL_ACCESS + +#define SEMAPHORE_MODIFY_STATE (0x0002) +#define SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3) + +#define PROCESS_TERMINATE (0x0001) +#define PROCESS_CREATE_THREAD (0x0002) +#define PROCESS_SET_SESSIONID (0x0004) +#define PROCESS_VM_OPERATION (0x0008) +#define PROCESS_VM_READ (0x0010) +#define PROCESS_VM_WRITE (0x0020) +#define PROCESS_DUP_HANDLE (0x0040) +#define PROCESS_CREATE_PROCESS (0x0080) +#define PROCESS_SET_QUOTA (0x0100) +#define PROCESS_SET_INFORMATION (0x0200) +#define PROCESS_QUERY_INFORMATION (0x0400) +#define PROCESS_SUSPEND_RESUME (0x0800) +#define PROCESS_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | \ + 0xFFF) + +PALIMPORT +HANDLE +PALAPI +OpenProcess( + IN DWORD dwDesiredAccess, /* PROCESS_DUP_HANDLE or PROCESS_ALL_ACCESS */ + IN BOOL bInheritHandle, + IN DWORD dwProcessId + ); + +PALIMPORT +BOOL +PALAPI +EnumProcessModules( + IN HANDLE hProcess, + OUT HMODULE *lphModule, + IN DWORD cb, + OUT LPDWORD lpcbNeeded + ); + +PALIMPORT +VOID +PALAPI +OutputDebugStringA( + IN LPCSTR lpOutputString); + +PALIMPORT +VOID +PALAPI +OutputDebugStringW( + IN LPCWSTR lpOutputStrig); + +#ifdef UNICODE +#define OutputDebugString OutputDebugStringW +#else +#define OutputDebugString OutputDebugStringA +#endif + +PALIMPORT +VOID +PALAPI +DebugBreak( + VOID); + +PALIMPORT +DWORD +PALAPI +GetEnvironmentVariableW( + IN LPCWSTR lpName, + OUT LPWSTR lpBuffer, + IN DWORD nSize); + +#ifdef UNICODE +#define GetEnvironmentVariable GetEnvironmentVariableW +#else +#define GetEnvironmentVariable GetEnvironmentVariableA +#endif + +PALIMPORT +BOOL +PALAPI +SetEnvironmentVariableW( + IN LPCWSTR lpName, + IN LPCWSTR lpValue); + +#ifdef UNICODE +#define SetEnvironmentVariable SetEnvironmentVariableW +#else +#define SetEnvironmentVariable SetEnvironmentVariableA +#endif + +PALIMPORT +LPWSTR +PALAPI +GetEnvironmentStringsW( + VOID); + +#ifdef UNICODE +#define GetEnvironmentStrings GetEnvironmentStringsW +#else +#define GetEnvironmentStrings GetEnvironmentStringsA +#endif + +PALIMPORT +BOOL +PALAPI +FreeEnvironmentStringsW( + IN LPWSTR); + +#ifdef UNICODE +#define FreeEnvironmentStrings FreeEnvironmentStringsW +#else +#define FreeEnvironmentStrings FreeEnvironmentStringsA +#endif + +PALIMPORT +BOOL +PALAPI +CloseHandle( + IN OUT HANDLE hObject); + +PALIMPORT +VOID +PALAPI +RaiseException( + IN DWORD dwExceptionCode, + IN DWORD dwExceptionFlags, + IN DWORD nNumberOfArguments, + IN CONST ULONG_PTR *lpArguments); + +PALIMPORT +VOID +PALAPI +RaiseFailFastException( + IN PEXCEPTION_RECORD pExceptionRecord, + IN PCONTEXT pContextRecord, + IN DWORD dwFlags); + +PALIMPORT +DWORD +PALAPI +GetTickCount( + VOID); + +PALIMPORT +ULONGLONG +PALAPI +GetTickCount64(VOID); + +PALIMPORT +BOOL +PALAPI +QueryPerformanceCounter( + OUT LARGE_INTEGER *lpPerformanceCount + ); + +PALIMPORT +BOOL +PALAPI +QueryPerformanceFrequency( + OUT LARGE_INTEGER *lpFrequency + ); + +PALIMPORT +BOOL +PALAPI +QueryThreadCycleTime( + IN HANDLE ThreadHandle, + OUT PULONG64 CycleTime); + +PALIMPORT +INT +PALAPI +PAL_nanosleep( + IN long timeInNs); + +#ifndef FEATURE_PAL_SXS + +typedef LONG (PALAPI_NOEXPORT *PTOP_LEVEL_EXCEPTION_FILTER)( + struct _EXCEPTION_POINTERS *ExceptionInfo); +typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER; + +PALIMPORT +LPTOP_LEVEL_EXCEPTION_FILTER +PALAPI +SetUnhandledExceptionFilter( + IN LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter); + +#else // FEATURE_PAL_SXS + +typedef EXCEPTION_DISPOSITION (PALAPI_NOEXPORT *PVECTORED_EXCEPTION_HANDLER)( + struct _EXCEPTION_POINTERS *ExceptionPointers); + +#endif // FEATURE_PAL_SXS + +// Define BitScanForward64 and BitScanForward +// Per MSDN, BitScanForward64 will search the mask data from LSB to MSB for a set bit. +// If one is found, its bit position is stored in the out PDWORD argument and 1 is returned; +// otherwise, an undefined value is stored in the out PDWORD argument and 0 is returned. +// +// On GCC, the equivalent function is __builtin_ffsll. It returns 1+index of the least +// significant set bit, or 0 if if mask is zero. +// +// The same is true for BitScanForward, except that the GCC function is __builtin_ffs. +EXTERN_C +PALIMPORT +inline +unsigned char +PALAPI +BitScanForward( + IN OUT PDWORD Index, + IN UINT qwMask) +{ + int iIndex = __builtin_ffs(qwMask); + // Set the Index after deducting unity + *Index = (DWORD)(iIndex - 1); + // Both GCC and Clang generate better, smaller code if we check whether the + // mask was/is zero rather than the equivalent check that iIndex is zero. + return qwMask != 0 ? TRUE : FALSE; +} + +EXTERN_C +PALIMPORT +inline +unsigned char +PALAPI +BitScanForward64( + IN OUT PDWORD Index, + IN UINT64 qwMask) +{ + int iIndex = __builtin_ffsll(qwMask); + // Set the Index after deducting unity + *Index = (DWORD)(iIndex - 1); + // Both GCC and Clang generate better, smaller code if we check whether the + // mask was/is zero rather than the equivalent check that iIndex is zero. + return qwMask != 0 ? TRUE : FALSE; +} + +// Define BitScanReverse64 and BitScanReverse +// Per MSDN, BitScanReverse64 will search the mask data from MSB to LSB for a set bit. +// If one is found, its bit position is stored in the out PDWORD argument and 1 is returned. +// Otherwise, an undefined value is stored in the out PDWORD argument and 0 is returned. +// +// GCC/clang don't have a directly equivalent intrinsic; they do provide the __builtin_clzll +// intrinsic, which returns the number of leading 0-bits in x starting at the most significant +// bit position (the result is undefined when x = 0). +// +// The same is true for BitScanReverse, except that the GCC function is __builtin_clzl. + +EXTERN_C +PALIMPORT +inline +unsigned char +PALAPI +BitScanReverse( + IN OUT PDWORD Index, + IN UINT qwMask) +{ + // The result of __builtin_clzl is undefined when qwMask is zero, + // but it's still OK to call the intrinsic in that case (just don't use the output). + // Unconditionally calling the intrinsic in this way allows the compiler to + // emit branchless code for this function when possible (depending on how the + // intrinsic is implemented for the target platform). + int lzcount = __builtin_clzl(qwMask); + *Index = (DWORD)(31 - lzcount); + return qwMask != 0; +} + +EXTERN_C +PALIMPORT +inline +unsigned char +PALAPI +BitScanReverse64( + IN OUT PDWORD Index, + IN UINT64 qwMask) +{ + // The result of __builtin_clzll is undefined when qwMask is zero, + // but it's still OK to call the intrinsic in that case (just don't use the output). + // Unconditionally calling the intrinsic in this way allows the compiler to + // emit branchless code for this function when possible (depending on how the + // intrinsic is implemented for the target platform). + int lzcount = __builtin_clzll(qwMask); + *Index = (DWORD)(63 - lzcount); + return qwMask != 0; +} + +FORCEINLINE void PAL_ArmInterlockedOperationBarrier() +{ +#ifdef _ARM64_ + // On arm64, most of the __sync* functions generate a code sequence like: + // loop: + // ldaxr (load acquire exclusive) + // ... + // stlxr (store release exclusive) + // cbnz loop + // + // It is possible for a load following the code sequence above to be reordered to occur prior to the store above due to the + // release barrier, this is substantiated by https://github.com/dotnet/coreclr/pull/17508. Interlocked operations in the PAL + // require the load to occur after the store. This memory barrier should be used following a call to a __sync* function to + // prevent that reordering. Code generated for arm32 includes a 'dmb' after 'cbnz', so no issue there at the moment. + __sync_synchronize(); +#endif // _ARM64_ +} + +/*++ +Function: +InterlockedIncrement + +The InterlockedIncrement function increments (increases by one) the +value of the specified variable and checks the resulting value. The +function prevents more than one thread from using the same variable +simultaneously. + +Parameters + +lpAddend +[in/out] Pointer to the variable to increment. + +Return Values + +The return value is the resulting incremented value. + +--*/ +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedIncrement( + IN OUT LONG volatile *lpAddend) +{ + LONG result = __sync_add_and_fetch(lpAddend, (LONG)1); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +LONGLONG +PALAPI +InterlockedIncrement64( + IN OUT LONGLONG volatile *lpAddend) +{ + LONGLONG result = __sync_add_and_fetch(lpAddend, (LONGLONG)1); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +/*++ +Function: +InterlockedDecrement + +The InterlockedDecrement function decrements (decreases by one) the +value of the specified variable and checks the resulting value. The +function prevents more than one thread from using the same variable +simultaneously. + +Parameters + +lpAddend +[in/out] Pointer to the variable to decrement. + +Return Values + +The return value is the resulting decremented value. + +--*/ +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedDecrement( + IN OUT LONG volatile *lpAddend) +{ + LONG result = __sync_sub_and_fetch(lpAddend, (LONG)1); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +#define InterlockedDecrementAcquire InterlockedDecrement +#define InterlockedDecrementRelease InterlockedDecrement + +EXTERN_C +PALIMPORT +inline +LONGLONG +PALAPI +InterlockedDecrement64( + IN OUT LONGLONG volatile *lpAddend) +{ + LONGLONG result = __sync_sub_and_fetch(lpAddend, (LONGLONG)1); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +/*++ +Function: +InterlockedExchange + +The InterlockedExchange function atomically exchanges a pair of +values. The function prevents more than one thread from using the same +variable simultaneously. + +Parameters + +Target +[in/out] Pointer to the value to exchange. The function sets +this variable to Value, and returns its prior value. +Value +[in] Specifies a new value for the variable pointed to by Target. + +Return Values + +The function returns the initial value pointed to by Target. + +--*/ +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedExchange( + IN OUT LONG volatile *Target, + IN LONG Value) +{ + LONG result = __atomic_exchange_n(Target, Value, __ATOMIC_ACQ_REL); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +LONGLONG +PALAPI +InterlockedExchange64( + IN OUT LONGLONG volatile *Target, + IN LONGLONG Value) +{ + LONGLONG result = __atomic_exchange_n(Target, Value, __ATOMIC_ACQ_REL); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +/*++ +Function: +InterlockedCompareExchange + +The InterlockedCompareExchange function performs an atomic comparison +of the specified values and exchanges the values, based on the outcome +of the comparison. The function prevents more than one thread from +using the same variable simultaneously. + +If you are exchanging pointer values, this function has been +superseded by the InterlockedCompareExchangePointer function. + +Parameters + +Destination [in/out] Specifies the address of the destination value. The sign is ignored. +Exchange [in] Specifies the exchange value. The sign is ignored. +Comperand [in] Specifies the value to compare to Destination. The sign is ignored. + +Return Values + +The return value is the initial value of the destination. + +--*/ +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedCompareExchange( + IN OUT LONG volatile *Destination, + IN LONG Exchange, + IN LONG Comperand) +{ + LONG result = + __sync_val_compare_and_swap( + Destination, /* The pointer to a variable whose value is to be compared with. */ + Comperand, /* The value to be compared */ + Exchange /* The value to be stored */); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +#define InterlockedCompareExchangeAcquire InterlockedCompareExchange +#define InterlockedCompareExchangeRelease InterlockedCompareExchange + +// See the 32-bit variant in interlock2.s +EXTERN_C +PALIMPORT +inline +LONGLONG +PALAPI +InterlockedCompareExchange64( + IN OUT LONGLONG volatile *Destination, + IN LONGLONG Exchange, + IN LONGLONG Comperand) +{ + LONGLONG result = + __sync_val_compare_and_swap( + Destination, /* The pointer to a variable whose value is to be compared with. */ + Comperand, /* The value to be compared */ + Exchange /* The value to be stored */); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +/*++ +Function: +InterlockedExchangeAdd + +The InterlockedExchangeAdd function atomically adds the value of 'Value' +to the variable that 'Addend' points to. + +Parameters + +lpAddend +[in/out] Pointer to the variable to to added. + +Return Values + +The return value is the original value that 'Addend' pointed to. + +--*/ +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedExchangeAdd( + IN OUT LONG volatile *Addend, + IN LONG Value) +{ + LONG result = __sync_fetch_and_add(Addend, Value); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +LONGLONG +PALAPI +InterlockedExchangeAdd64( + IN OUT LONGLONG volatile *Addend, + IN LONGLONG Value) +{ + LONGLONG result = __sync_fetch_and_add(Addend, Value); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedAnd( + IN OUT LONG volatile *Destination, + IN LONG Value) +{ + LONG result = __sync_fetch_and_and(Destination, Value); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +LONG +PALAPI +InterlockedOr( + IN OUT LONG volatile *Destination, + IN LONG Value) +{ + LONG result = __sync_fetch_and_or(Destination, Value); + PAL_ArmInterlockedOperationBarrier(); + return result; +} + +EXTERN_C +PALIMPORT +inline +UCHAR +PALAPI +InterlockedBitTestAndReset( + IN OUT LONG volatile *Base, + IN LONG Bit) +{ + return (InterlockedAnd(Base, ~(1 << Bit)) & (1 << Bit)) != 0; +} + +EXTERN_C +PALIMPORT +inline +UCHAR +PALAPI +InterlockedBitTestAndSet( + IN OUT LONG volatile *Base, + IN LONG Bit) +{ + return (InterlockedOr(Base, (1 << Bit)) & (1 << Bit)) != 0; +} + +#if defined(BIT64) +#define InterlockedExchangePointer(Target, Value) \ + ((PVOID)InterlockedExchange64((PLONG64)(Target), (LONGLONG)(Value))) + +#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \ + ((PVOID)InterlockedCompareExchange64((PLONG64)(Destination), (LONGLONG)(ExChange), (LONGLONG)(Comperand))) +#else +#define InterlockedExchangePointer(Target, Value) \ + ((PVOID)(UINT_PTR)InterlockedExchange((PLONG)(UINT_PTR)(Target), (LONG)(UINT_PTR)(Value))) + +#define InterlockedCompareExchangePointer(Destination, ExChange, Comperand) \ + ((PVOID)(UINT_PTR)InterlockedCompareExchange((PLONG)(UINT_PTR)(Destination), (LONG)(UINT_PTR)(ExChange), (LONG)(UINT_PTR)(Comperand))) +#endif + +/*++ +Function: +MemoryBarrier + +The MemoryBarrier function creates a full memory barrier. + +--*/ +EXTERN_C +PALIMPORT +inline +VOID +PALAPI +MemoryBarrier( + VOID) +{ + __sync_synchronize(); +} + +EXTERN_C +PALIMPORT +inline +VOID +PALAPI +YieldProcessor( + VOID) +{ +#if defined(_X86_) || defined(_AMD64_) + __asm__ __volatile__( + "rep\n" + "nop"); +#elif defined(_ARM64_) + __asm__ __volatile__( "yield"); +#else + return; +#endif +} + +PALIMPORT +DWORD +PALAPI +GetCurrentProcessorNumber(VOID); + +/*++ +Function: +PAL_HasGetCurrentProcessorNumber + +Checks if GetCurrentProcessorNumber is available in the current environment + +--*/ +PALIMPORT +BOOL +PALAPI +PAL_HasGetCurrentProcessorNumber(VOID); + +#define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100 +#define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200 +#define FORMAT_MESSAGE_FROM_STRING 0x00000400 +#define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000 +#define FORMAT_MESSAGE_ARGUMENT_ARRAY 0x00002000 +#define FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF + +PALIMPORT +DWORD +PALAPI +FormatMessageW( + IN DWORD dwFlags, + IN LPCVOID lpSource, + IN DWORD dwMessageId, + IN DWORD dwLanguageId, + OUT LPWSTR lpBffer, + IN DWORD nSize, + IN va_list *Arguments); + +#ifdef UNICODE +#define FormatMessage FormatMessageW +#endif + + +PALIMPORT +DWORD +PALAPI +GetLastError( + VOID); + +PALIMPORT +VOID +PALAPI +SetLastError( + IN DWORD dwErrCode); + +PALIMPORT +LPWSTR +PALAPI +GetCommandLineW( + VOID); + +#ifdef UNICODE +#define GetCommandLine GetCommandLineW +#endif + +PALIMPORT +VOID +PALAPI +RtlRestoreContext( + IN PCONTEXT ContextRecord, + IN PEXCEPTION_RECORD ExceptionRecord +); + +PALIMPORT +VOID +PALAPI +RtlCaptureContext( + OUT PCONTEXT ContextRecord +); + +PALIMPORT +UINT +PALAPI +GetWriteWatch( + IN DWORD dwFlags, + IN PVOID lpBaseAddress, + IN SIZE_T dwRegionSize, + OUT PVOID *lpAddresses, + IN OUT PULONG_PTR lpdwCount, + OUT PULONG lpdwGranularity +); + +PALIMPORT +UINT +PALAPI +ResetWriteWatch( + IN LPVOID lpBaseAddress, + IN SIZE_T dwRegionSize +); + +PALIMPORT +VOID +PALAPI +FlushProcessWriteBuffers(VOID); + +typedef void (*PAL_ActivationFunction)(CONTEXT *context); +typedef BOOL (*PAL_SafeActivationCheckFunction)(SIZE_T ip, BOOL checkingCurrentThread); + +PALIMPORT +VOID +PALAPI +PAL_SetActivationFunction( + IN PAL_ActivationFunction pActivationFunction, + IN PAL_SafeActivationCheckFunction pSafeActivationCheckFunction); + +PALIMPORT +BOOL +PALAPI +PAL_InjectActivation( + IN HANDLE hThread +); + +#define VER_PLATFORM_WIN32_WINDOWS 1 +#define VER_PLATFORM_WIN32_NT 2 +#define VER_PLATFORM_UNIX 10 +#define VER_PLATFORM_MACOSX 11 + +typedef struct _OSVERSIONINFOA { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[ 128 ]; +} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA; + +typedef struct _OSVERSIONINFOW { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + WCHAR szCSDVersion[ 128 ]; +} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW; + +#ifdef UNICODE +typedef OSVERSIONINFOW OSVERSIONINFO; +typedef POSVERSIONINFOW POSVERSIONINFO; +typedef LPOSVERSIONINFOW LPOSVERSIONINFO; +#else +typedef OSVERSIONINFOA OSVERSIONINFO; +typedef POSVERSIONINFOA POSVERSIONINFO; +typedef LPOSVERSIONINFOA LPOSVERSIONINFO; +#endif + +typedef struct _OSVERSIONINFOEXA { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[ 128 ]; + WORD wServicePackMajor; + WORD wServicePackMinor; + WORD wSuiteMask; + BYTE wProductType; + BYTE wReserved; +} OSVERSIONINFOEXA, *POSVERSIONINFOEXA, *LPOSVERSIONINFOEXA; + +typedef struct _OSVERSIONINFOEXW { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + WCHAR szCSDVersion[ 128 ]; + WORD wServicePackMajor; + WORD wServicePackMinor; + WORD wSuiteMask; + BYTE wProductType; + BYTE wReserved; +} OSVERSIONINFOEXW, *POSVERSIONINFOEXW, *LPOSVERSIONINFOEXW; + +#ifdef UNICODE +typedef OSVERSIONINFOEXW OSVERSIONINFOEX; +typedef POSVERSIONINFOEXW POSVERSIONINFOEX; +typedef LPOSVERSIONINFOEXW LPOSVERSIONINFOEX; +#else +typedef OSVERSIONINFOEXA OSVERSIONINFOEX; +typedef POSVERSIONINFOEXA POSVERSIONINFOEX; +typedef LPOSVERSIONINFOEXA LPOSVERSIONINFOEX; +#endif + +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian + +typedef struct _SYSTEM_INFO { + WORD wProcessorArchitecture_PAL_Undefined; + WORD wReserved_PAL_Undefined; // NOTE: diff from winbase.h - no obsolete dwOemId union + DWORD dwPageSize; + LPVOID lpMinimumApplicationAddress; + LPVOID lpMaximumApplicationAddress; + DWORD_PTR dwActiveProcessorMask_PAL_Undefined; + DWORD dwNumberOfProcessors; + DWORD dwProcessorType_PAL_Undefined; + DWORD dwAllocationGranularity; + WORD wProcessorLevel_PAL_Undefined; + WORD wProcessorRevision_PAL_Undefined; +} SYSTEM_INFO, *LPSYSTEM_INFO; + +PALIMPORT +VOID +PALAPI +GetSystemInfo( + OUT LPSYSTEM_INFO lpSystemInfo); + +PALIMPORT +BOOL +PALAPI +CreatePipe( + OUT PHANDLE hReadPipe, + OUT PHANDLE hWritePipe, + IN LPSECURITY_ATTRIBUTES lpPipeAttributes, + IN DWORD nSize + ); + +// +// NUMA related APIs +// + +PALIMPORT +BOOL +PALAPI +GetNumaHighestNodeNumber( + OUT PULONG HighestNodeNumber +); + +PALIMPORT +BOOL +PALAPI +PAL_GetNumaProcessorNode(WORD procNo, WORD* node); + +PALIMPORT +LPVOID +PALAPI +VirtualAllocExNuma( + IN HANDLE hProcess, + IN OPTIONAL LPVOID lpAddress, + IN SIZE_T dwSize, + IN DWORD flAllocationType, + IN DWORD flProtect, + IN DWORD nndPreferred +); + +PALIMPORT +BOOL +PALAPI +PAL_SetCurrentThreadAffinity(WORD procNo); + +PALIMPORT +BOOL +PALAPI +PAL_GetCurrentThreadAffinitySet(SIZE_T size, UINT_PTR* data); + +// +// The types of events that can be logged. +// +#define EVENTLOG_SUCCESS 0x0000 +#define EVENTLOG_ERROR_TYPE 0x0001 +#define EVENTLOG_WARNING_TYPE 0x0002 +#define EVENTLOG_INFORMATION_TYPE 0x0004 +#define EVENTLOG_AUDIT_SUCCESS 0x0008 +#define EVENTLOG_AUDIT_FAILURE 0x0010 + +#if defined FEATURE_PAL_ANSI +#include "palprivate.h" +#endif //FEATURE_PAL_ANSI +/******************* C Runtime Entrypoints *******************************/ + +/* Some C runtime functions needs to be reimplemented by the PAL. + To avoid name collisions, those functions have been renamed using + defines */ +#ifndef PAL_STDCPP_COMPAT +#define exit PAL_exit +#define atexit PAL_atexit +#define printf PAL_printf +#define vprintf PAL_vprintf +#define wprintf PAL_wprintf +#define wcsspn PAL_wcsspn +#define wcstod PAL_wcstod +#define wcstol PAL_wcstol +#define wcstoul PAL_wcstoul +#define wcscat PAL_wcscat +#define wcscpy PAL_wcscpy +#define wcslen PAL_wcslen +#define wcsncmp PAL_wcsncmp +#define wcschr PAL_wcschr +#define wcsrchr PAL_wcsrchr +#define wcsstr PAL_wcsstr +#define swscanf PAL_swscanf +#define wcspbrk PAL_wcspbrk +#define wcscmp PAL_wcscmp +#define wcsncat PAL_wcsncat +#define wcsncpy PAL_wcsncpy +#define wcstok PAL_wcstok +#define wcscspn PAL_wcscspn +#define realloc PAL_realloc +#define fopen PAL_fopen +#define strtok PAL_strtok +#define strtoul PAL_strtoul +#define fprintf PAL_fprintf +#define fwprintf PAL_fwprintf +#define vfprintf PAL_vfprintf +#define vfwprintf PAL_vfwprintf +#define ctime PAL_ctime +#define localtime PAL_localtime +#define mktime PAL_mktime +#define rand PAL_rand +#define time PAL_time +#define getenv PAL_getenv +#define fgets PAL_fgets +#define fgetws PAL_fgetws +#define fputc PAL_fputc +#define putchar PAL_putchar +#define qsort PAL_qsort +#define bsearch PAL_bsearch +#define ferror PAL_ferror +#define fread PAL_fread +#define fwrite PAL_fwrite +#define feof PAL_feof +#define ftell PAL_ftell +#define fclose PAL_fclose +#define setbuf PAL_setbuf +#define fflush PAL_fflush +#define fputs PAL_fputs +#define fseek PAL_fseek +#define fgetpos PAL_fgetpos +#define fsetpos PAL_fsetpos +#define getc PAL_getc +#define fgetc PAL_getc // not a typo +#define ungetc PAL_ungetc +#define setvbuf PAL_setvbuf +#define atol PAL_atol +#define labs PAL_labs +#define acos PAL_acos +#define acosh PAL_acosh +#define asin PAL_asin +#define asinh PAL_asinh +#define atan2 PAL_atan2 +#define exp PAL_exp +#define fma PAL_fma +#define ilogb PAL_ilogb +#define log PAL_log +#define log2 PAL_log2 +#define log10 PAL_log10 +#define pow PAL_pow +#define scalbn PAL_scalbn +#define acosf PAL_acosf +#define acoshf PAL_acoshf +#define asinf PAL_asinf +#define asinhf PAL_asinhf +#define atan2f PAL_atan2f +#define expf PAL_expf +#define fmaf PAL_fmaf +#define ilogbf PAL_ilogbf +#define logf PAL_logf +#define log2f PAL_log2f +#define log10f PAL_log10f +#define powf PAL_powf +#define scalbnf PAL_scalbnf +#define malloc PAL_malloc +#define free PAL_free +#define mkstemp PAL_mkstemp +#define rename PAL_rename +#define _strdup PAL__strdup +#define _getcwd PAL__getcwd +#define _open PAL__open +#define _pread PAL__pread +#define _close PAL__close +#define _wcstoui64 PAL__wcstoui64 +#define _flushall PAL__flushall +#define strnlen PAL_strnlen +#define wcsnlen PAL_wcsnlen + +#ifdef _AMD64_ +#define _mm_getcsr PAL__mm_getcsr +#define _mm_setcsr PAL__mm_setcsr +#endif // _AMD64_ + +#endif // !PAL_STDCPP_COMPAT + +#ifndef _CONST_RETURN +#ifdef __cplusplus +#define _CONST_RETURN const +#define _CRT_CONST_CORRECT_OVERLOADS +#else +#define _CONST_RETURN +#endif +#endif + +/* For backwards compatibility */ +#define _WConst_return _CONST_RETURN + +#define EOF (-1) + +typedef int errno_t; + +#if defined(__WINT_TYPE__) +typedef __WINT_TYPE__ wint_t; +#else +typedef unsigned int wint_t; +#endif + +#ifndef PAL_STDCPP_COMPAT + +typedef struct { + int quot; + int rem; +} div_t; + +PALIMPORT div_t div(int numer, int denom); + +#if defined(_DEBUG) + +/*++ +Function: +PAL_memcpy + +Overlapping buffer-safe version of memcpy. +See MSDN doc for memcpy +--*/ +EXTERN_C +PALIMPORT +DLLEXPORT +void *PAL_memcpy (void *dest, const void * src, size_t count); + +PALIMPORT void * __cdecl memcpy(void *, const void *, size_t) THROW_DECL; + +#define memcpy PAL_memcpy +#define IS_PAL_memcpy 1 +#define TEST_PAL_DEFERRED(def) IS_##def +#define IS_REDEFINED_IN_PAL(def) TEST_PAL_DEFERRED(def) +#else //defined(_DEBUG) +PALIMPORT void * __cdecl memcpy(void *, const void *, size_t); +#endif //defined(_DEBUG) +PALIMPORT int __cdecl memcmp(const void *, const void *, size_t); +PALIMPORT void * __cdecl memset(void *, int, size_t); +PALIMPORT void * __cdecl memmove(void *, const void *, size_t); +PALIMPORT void * __cdecl memchr(const void *, int, size_t); +PALIMPORT long long int __cdecl atoll(const char *) THROW_DECL; +PALIMPORT size_t __cdecl strlen(const char *); +PALIMPORT int __cdecl strcmp(const char*, const char *); +PALIMPORT int __cdecl strncmp(const char*, const char *, size_t); +PALIMPORT int __cdecl _strnicmp(const char *, const char *, size_t); +PALIMPORT char * __cdecl strcat(char *, const char *); +PALIMPORT char * __cdecl strncat(char *, const char *, size_t); +PALIMPORT char * __cdecl strcpy(char *, const char *); +PALIMPORT char * __cdecl strncpy(char *, const char *, size_t); +PALIMPORT char * __cdecl strchr(const char *, int); +PALIMPORT char * __cdecl strrchr(const char *, int); +PALIMPORT char * __cdecl strpbrk(const char *, const char *); +PALIMPORT char * __cdecl strstr(const char *, const char *); +PALIMPORT char * __cdecl strtok(char *, const char *); +PALIMPORT size_t __cdecl strspn(const char *, const char *); +PALIMPORT size_t __cdecl strcspn(const char *, const char *); +PALIMPORT int __cdecl atoi(const char *); +PALIMPORT LONG __cdecl atol(const char *); +PALIMPORT ULONG __cdecl strtoul(const char *, char **, int); +PALIMPORT double __cdecl atof(const char *); +PALIMPORT double __cdecl strtod(const char *, char **); +PALIMPORT int __cdecl isprint(int); +PALIMPORT int __cdecl isspace(int); +PALIMPORT int __cdecl isalpha(int); +PALIMPORT int __cdecl isalnum(int); +PALIMPORT int __cdecl isdigit(int); +PALIMPORT int __cdecl isxdigit(int); +PALIMPORT int __cdecl isupper(int); +PALIMPORT int __cdecl islower(int); +PALIMPORT int __cdecl tolower(int); +PALIMPORT int __cdecl toupper(int); +PALIMPORT int __cdecl iswalpha(wint_t); +PALIMPORT int __cdecl iswdigit(wint_t); +PALIMPORT int __cdecl iswupper(wint_t); +PALIMPORT int __cdecl iswprint(wint_t); +PALIMPORT int __cdecl iswspace(wint_t); +PALIMPORT int __cdecl iswxdigit(wint_t); +PALIMPORT wint_t __cdecl towupper(wint_t); +PALIMPORT wint_t __cdecl towlower(wint_t); +#endif // PAL_STDCPP_COMPAT + +/* _TRUNCATE */ +#if !defined(_TRUNCATE) +#define _TRUNCATE ((size_t)-1) +#endif + +PALIMPORT DLLEXPORT errno_t __cdecl memcpy_s(void *, size_t, const void *, size_t) THROW_DECL; +PALIMPORT errno_t __cdecl memmove_s(void *, size_t, const void *, size_t); +PALIMPORT char * __cdecl _strlwr(char *); +PALIMPORT DLLEXPORT int __cdecl _stricmp(const char *, const char *); +PALIMPORT DLLEXPORT int __cdecl vsprintf_s(char *, size_t, const char *, va_list); +PALIMPORT char * __cdecl _gcvt_s(char *, int, double, int); +PALIMPORT int __cdecl __iscsym(int); +PALIMPORT unsigned char * __cdecl _mbsinc(const unsigned char *); +PALIMPORT unsigned char * __cdecl _mbsninc(const unsigned char *, size_t); +PALIMPORT unsigned char * __cdecl _mbsdec(const unsigned char *, const unsigned char *); +PALIMPORT DLLEXPORT int __cdecl _wcsicmp(const WCHAR *, const WCHAR*); +PALIMPORT int __cdecl _wcsnicmp(const WCHAR *, const WCHAR *, size_t); +PALIMPORT int __cdecl _vsnprintf(char *, size_t, const char *, va_list); +PALIMPORT DLLEXPORT int __cdecl _vsnprintf_s(char *, size_t, size_t, const char *, va_list); +PALIMPORT DLLEXPORT int __cdecl _vsnwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, va_list); +PALIMPORT DLLEXPORT int __cdecl _snwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, ...); +PALIMPORT DLLEXPORT int __cdecl _snprintf_s(char *, size_t, size_t, const char *, ...); +PALIMPORT DLLEXPORT int __cdecl sprintf_s(char *, size_t, const char *, ... ); +PALIMPORT DLLEXPORT int __cdecl swprintf_s(WCHAR *, size_t, const WCHAR *, ... ); +PALIMPORT int __cdecl _snwprintf_s(WCHAR *, size_t, size_t, const WCHAR *, ...); +PALIMPORT int __cdecl vswprintf_s( WCHAR *, size_t, const WCHAR *, va_list); +PALIMPORT DLLEXPORT int __cdecl sscanf_s(const char *, const char *, ...); +PALIMPORT DLLEXPORT errno_t __cdecl _itow_s(int, WCHAR *, size_t, int); + +PALIMPORT DLLEXPORT size_t __cdecl PAL_wcslen(const WCHAR *); +PALIMPORT DLLEXPORT int __cdecl PAL_wcscmp(const WCHAR*, const WCHAR*); +PALIMPORT DLLEXPORT int __cdecl PAL_wcsncmp(const WCHAR *, const WCHAR *, size_t); +PALIMPORT DLLEXPORT WCHAR * __cdecl PAL_wcscat(WCHAR *, const WCHAR *); +PALIMPORT WCHAR * __cdecl PAL_wcsncat(WCHAR *, const WCHAR *, size_t); +PALIMPORT WCHAR * __cdecl PAL_wcscpy(WCHAR *, const WCHAR *); +PALIMPORT WCHAR * __cdecl PAL_wcsncpy(WCHAR *, const WCHAR *, size_t); +PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcschr(const WCHAR *, WCHAR); +PALIMPORT DLLEXPORT const WCHAR * __cdecl PAL_wcsrchr(const WCHAR *, WCHAR); +PALIMPORT WCHAR _WConst_return * __cdecl PAL_wcspbrk(const WCHAR *, const WCHAR *); +PALIMPORT DLLEXPORT WCHAR _WConst_return * __cdecl PAL_wcsstr(const WCHAR *, const WCHAR *); +PALIMPORT WCHAR * __cdecl PAL_wcstok(WCHAR *, const WCHAR *); +PALIMPORT DLLEXPORT size_t __cdecl PAL_wcscspn(const WCHAR *, const WCHAR *); +PALIMPORT int __cdecl PAL_swprintf(WCHAR *, const WCHAR *, ...); +PALIMPORT int __cdecl PAL_vswprintf(WCHAR *, const WCHAR *, va_list); +PALIMPORT int __cdecl PAL_swscanf(const WCHAR *, const WCHAR *, ...); +PALIMPORT LONG __cdecl PAL_wcstol(const WCHAR *, WCHAR **, int); +PALIMPORT DLLEXPORT ULONG __cdecl PAL_wcstoul(const WCHAR *, WCHAR **, int); +PALIMPORT size_t __cdecl PAL_wcsspn (const WCHAR *, const WCHAR *); +PALIMPORT double __cdecl PAL_wcstod(const WCHAR *, WCHAR **); + +PALIMPORT WCHAR * __cdecl _wcslwr(WCHAR *); +PALIMPORT DLLEXPORT ULONGLONG _wcstoui64(const WCHAR *, WCHAR **, int); +PALIMPORT DLLEXPORT errno_t __cdecl _i64tow_s(long long, WCHAR *, size_t, int); +PALIMPORT int __cdecl _wtoi(const WCHAR *); + +#ifdef __cplusplus +extern "C++" { +inline WCHAR *PAL_wcschr(WCHAR *_S, WCHAR _C) + {return ((WCHAR *)PAL_wcschr((const WCHAR *)_S, _C)); } +inline WCHAR *PAL_wcsrchr(WCHAR *_S, WCHAR _C) + {return ((WCHAR *)PAL_wcsrchr((const WCHAR *)_S, _C)); } +inline WCHAR *PAL_wcspbrk(WCHAR *_S, const WCHAR *_P) + {return ((WCHAR *)PAL_wcspbrk((const WCHAR *)_S, _P)); } +inline WCHAR *PAL_wcsstr(WCHAR *_S, const WCHAR *_P) + {return ((WCHAR *)PAL_wcsstr((const WCHAR *)_S, _P)); } +} +#endif + +#if defined(__llvm__) +#define HAS_ROTL __has_builtin(_rotl) +#define HAS_ROTR __has_builtin(_rotr) +#else +#define HAS_ROTL 0 +#define HAS_ROTR 0 +#endif + +#if !HAS_ROTL +/*++ +Function: +_rotl + +See MSDN doc. +--*/ +EXTERN_C +PALIMPORT +inline +unsigned int __cdecl _rotl(unsigned int value, int shift) +{ + unsigned int retval = 0; + + shift &= 0x1f; + retval = (value << shift) | (value >> (sizeof(int) * CHAR_BIT - shift)); + return retval; +} +#endif // !HAS_ROTL + +// On 64 bit unix, make the long an int. +#ifdef BIT64 +#define _lrotl _rotl +#endif // BIT64 + +#if !HAS_ROTR + +/*++ +Function: +_rotr + +See MSDN doc. +--*/ +EXTERN_C +PALIMPORT +inline +unsigned int __cdecl _rotr(unsigned int value, int shift) +{ + unsigned int retval; + + shift &= 0x1f; + retval = (value >> shift) | (value << (sizeof(int) * CHAR_BIT - shift)); + return retval; +} + +#endif // !HAS_ROTR + +PALIMPORT int __cdecl abs(int); +// clang complains if this is declared with __int64 +PALIMPORT long long __cdecl llabs(long long); +#ifndef PAL_STDCPP_COMPAT +PALIMPORT LONG __cdecl labs(LONG); + +PALIMPORT int __cdecl _signbit(double); +PALIMPORT int __cdecl _finite(double); +PALIMPORT int __cdecl _isnan(double); +PALIMPORT double __cdecl _copysign(double, double); +PALIMPORT double __cdecl acos(double); +PALIMPORT double __cdecl acosh(double); +PALIMPORT double __cdecl asin(double); +PALIMPORT double __cdecl asinh(double); +PALIMPORT double __cdecl atan(double) THROW_DECL; +PALIMPORT double __cdecl atanh(double) THROW_DECL; +PALIMPORT double __cdecl atan2(double, double); +PALIMPORT double __cdecl cbrt(double) THROW_DECL; +PALIMPORT double __cdecl ceil(double); +PALIMPORT double __cdecl cos(double); +PALIMPORT double __cdecl cosh(double); +PALIMPORT double __cdecl exp(double); +PALIMPORT double __cdecl fabs(double); +PALIMPORT double __cdecl floor(double); +PALIMPORT double __cdecl fmod(double, double); +PALIMPORT double __cdecl fma(double, double, double); +PALIMPORT int __cdecl ilogb(double); +PALIMPORT double __cdecl log(double); +PALIMPORT double __cdecl log2(double); +PALIMPORT double __cdecl log10(double); +PALIMPORT double __cdecl modf(double, double*); +PALIMPORT double __cdecl pow(double, double); +PALIMPORT double __cdecl scalbn(double, int); +PALIMPORT double __cdecl sin(double); +PALIMPORT double __cdecl sinh(double); +PALIMPORT double __cdecl sqrt(double); +PALIMPORT double __cdecl tan(double); +PALIMPORT double __cdecl tanh(double); + +PALIMPORT int __cdecl _signbitf(float); +PALIMPORT int __cdecl _finitef(float); +PALIMPORT int __cdecl _isnanf(float); +PALIMPORT float __cdecl _copysignf(float, float); +PALIMPORT float __cdecl acosf(float); +PALIMPORT float __cdecl acoshf(float); +PALIMPORT float __cdecl asinf(float); +PALIMPORT float __cdecl asinhf(float); +PALIMPORT float __cdecl atanf(float) THROW_DECL; +PALIMPORT float __cdecl atanhf(float) THROW_DECL; +PALIMPORT float __cdecl atan2f(float, float); +PALIMPORT float __cdecl cbrtf(float) THROW_DECL; +PALIMPORT float __cdecl ceilf(float); +PALIMPORT float __cdecl cosf(float); +PALIMPORT float __cdecl coshf(float); +PALIMPORT float __cdecl expf(float); +PALIMPORT float __cdecl fabsf(float); +PALIMPORT float __cdecl floorf(float); +PALIMPORT float __cdecl fmodf(float, float); +PALIMPORT float __cdecl fmaf(float, float, float); +PALIMPORT int __cdecl ilogbf(float); +PALIMPORT float __cdecl logf(float); +PALIMPORT float __cdecl log2f(float); +PALIMPORT float __cdecl log10f(float); +PALIMPORT float __cdecl modff(float, float*); +PALIMPORT float __cdecl powf(float, float); +PALIMPORT float __cdecl scalbnf(float, int); +PALIMPORT float __cdecl sinf(float); +PALIMPORT float __cdecl sinhf(float); +PALIMPORT float __cdecl sqrtf(float); +PALIMPORT float __cdecl tanf(float); +PALIMPORT float __cdecl tanhf(float); +#endif // !PAL_STDCPP_COMPAT + +#ifndef PAL_STDCPP_COMPAT + +#ifdef __cplusplus +extern "C++" { + +inline __int64 abs(__int64 _X) { + return llabs(_X); +} + +} +#endif + +PALIMPORT DLLEXPORT void * __cdecl malloc(size_t); +PALIMPORT DLLEXPORT void __cdecl free(void *); +PALIMPORT DLLEXPORT void * __cdecl realloc(void *, size_t); +PALIMPORT char * __cdecl _strdup(const char *); + +#if defined(_MSC_VER) +#define alloca _alloca +#else +#define _alloca alloca +#endif //_MSC_VER + +#define alloca __builtin_alloca + +#define max(a, b) (((a) > (b)) ? (a) : (b)) +#define min(a, b) (((a) < (b)) ? (a) : (b)) + +#endif // !PAL_STDCPP_COMPAT + +PALIMPORT PAL_NORETURN void __cdecl exit(int); +int __cdecl atexit(void (__cdecl *function)(void)); + +PALIMPORT char * __cdecl _fullpath(char *, const char *, size_t); + +#ifndef PAL_STDCPP_COMPAT + +PALIMPORT DLLEXPORT void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *)); +PALIMPORT DLLEXPORT void * __cdecl bsearch(const void *, const void *, size_t, size_t, + int(__cdecl *)(const void *, const void *)); + +PALIMPORT time_t __cdecl time(time_t *); + +struct tm { + int tm_sec; /* seconds after the minute - [0,59] */ + int tm_min; /* minutes after the hour - [0,59] */ + int tm_hour; /* hours since midnight - [0,23] */ + int tm_mday; /* day of the month - [1,31] */ + int tm_mon; /* months since January - [0,11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday - [0,6] */ + int tm_yday; /* days since January 1 - [0,365] */ + int tm_isdst; /* daylight savings time flag */ + }; + +PALIMPORT struct tm * __cdecl localtime(const time_t *); +PALIMPORT time_t __cdecl mktime(struct tm *); +PALIMPORT char * __cdecl ctime(const time_t *); +#endif // !PAL_STDCPP_COMPAT + +PALIMPORT int __cdecl _open_osfhandle(INT_PTR, int); +PALIMPORT DLLEXPORT int __cdecl _open(const char *szPath, int nFlags, ...); +PALIMPORT DLLEXPORT size_t __cdecl _pread(int fd, void *buf, size_t nbytes, ULONG64 offset); +PALIMPORT DLLEXPORT int __cdecl _close(int); +PALIMPORT DLLEXPORT int __cdecl _flushall(); + +#ifdef PAL_STDCPP_COMPAT + +struct _PAL_FILE; +typedef struct _PAL_FILE PAL_FILE; + +#else // PAL_STDCPP_COMPAT + +struct _FILE; +typedef struct _FILE FILE; +typedef struct _FILE PAL_FILE; + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* Locale categories */ +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 + +#define _IOFBF 0 /* setvbuf should set fully buffered */ +#define _IOLBF 1 /* setvbuf should set line buffered */ +#define _IONBF 2 /* setvbuf should set unbuffered */ + +#endif // PAL_STDCPP_COMPAT + +PALIMPORT int __cdecl PAL_fclose(PAL_FILE *); +PALIMPORT void __cdecl PAL_setbuf(PAL_FILE *, char*); +PALIMPORT DLLEXPORT int __cdecl PAL_fflush(PAL_FILE *); +PALIMPORT size_t __cdecl PAL_fwrite(const void *, size_t, size_t, PAL_FILE *); +PALIMPORT size_t __cdecl PAL_fread(void *, size_t, size_t, PAL_FILE *); +PALIMPORT char * __cdecl PAL_fgets(char *, int, PAL_FILE *); +PALIMPORT int __cdecl PAL_fputs(const char *, PAL_FILE *); +PALIMPORT int __cdecl PAL_fputc(int c, PAL_FILE *stream); +PALIMPORT int __cdecl PAL_putchar(int c); +PALIMPORT DLLEXPORT int __cdecl PAL_fprintf(PAL_FILE *, const char *, ...); +PALIMPORT int __cdecl PAL_vfprintf(PAL_FILE *, const char *, va_list); +PALIMPORT int __cdecl PAL_fseek(PAL_FILE *, LONG, int); +PALIMPORT LONG __cdecl PAL_ftell(PAL_FILE *); +PALIMPORT int __cdecl PAL_feof(PAL_FILE *); +PALIMPORT int __cdecl PAL_ferror(PAL_FILE *); +PALIMPORT PAL_FILE * __cdecl PAL_fopen(const char *, const char *); +PALIMPORT int __cdecl PAL_getc(PAL_FILE *stream); +PALIMPORT int __cdecl PAL_fgetc(PAL_FILE *stream); +PALIMPORT int __cdecl PAL_ungetc(int c, PAL_FILE *stream); +PALIMPORT int __cdecl PAL_setvbuf(PAL_FILE *stream, char *, int, size_t); +PALIMPORT WCHAR * __cdecl PAL_fgetws(WCHAR *, int, PAL_FILE *); +PALIMPORT DLLEXPORT int __cdecl PAL_fwprintf(PAL_FILE *, const WCHAR *, ...); +PALIMPORT int __cdecl PAL_vfwprintf(PAL_FILE *, const WCHAR *, va_list); +PALIMPORT int __cdecl PAL_wprintf(const WCHAR*, ...); + +PALIMPORT int __cdecl _getw(PAL_FILE *); +PALIMPORT int __cdecl _putw(int, PAL_FILE *); +PALIMPORT PAL_FILE * __cdecl _fdopen(int, const char *); +PALIMPORT PAL_FILE * __cdecl _wfopen(const WCHAR *, const WCHAR *); +PALIMPORT PAL_FILE * __cdecl _wfsopen(const WCHAR *, const WCHAR *, int); + +/* Maximum value that can be returned by the rand function. */ + +#ifndef PAL_STDCPP_COMPAT +#define RAND_MAX 0x7fff +#endif // !PAL_STDCPP_COMPAT + +PALIMPORT int __cdecl rand(void); +PALIMPORT void __cdecl srand(unsigned int); + +PALIMPORT DLLEXPORT int __cdecl printf(const char *, ...); +PALIMPORT int __cdecl vprintf(const char *, va_list); + +#ifdef _MSC_VER +#define PAL_get_caller _MSC_VER +#else +#define PAL_get_caller 0 +#endif + +PALIMPORT DLLEXPORT PAL_FILE * __cdecl PAL_get_stdout(int caller); +PALIMPORT PAL_FILE * __cdecl PAL_get_stdin(int caller); +PALIMPORT DLLEXPORT PAL_FILE * __cdecl PAL_get_stderr(int caller); +PALIMPORT DLLEXPORT int * __cdecl PAL_errno(int caller); + +#ifdef PAL_STDCPP_COMPAT +#define PAL_stdout (PAL_get_stdout(PAL_get_caller)) +#define PAL_stdin (PAL_get_stdin(PAL_get_caller)) +#define PAL_stderr (PAL_get_stderr(PAL_get_caller)) +#define PAL_errno (*PAL_errno(PAL_get_caller)) +#else // PAL_STDCPP_COMPAT +#define stdout (PAL_get_stdout(PAL_get_caller)) +#define stdin (PAL_get_stdin(PAL_get_caller)) +#define stderr (PAL_get_stderr(PAL_get_caller)) +#define errno (*PAL_errno(PAL_get_caller)) +#endif // PAL_STDCPP_COMPAT + +PALIMPORT DLLEXPORT char * __cdecl getenv(const char *); +PALIMPORT DLLEXPORT int __cdecl _putenv(const char *); + +#define ERANGE 34 + +PALIMPORT WCHAR __cdecl PAL_ToUpperInvariant(WCHAR); +PALIMPORT WCHAR __cdecl PAL_ToLowerInvariant(WCHAR); + +/******************* PAL-specific I/O completion port *****************/ + +typedef struct _PAL_IOCP_CPU_INFORMATION { + union { + FILETIME ftLastRecordedIdleTime; + FILETIME ftLastRecordedCurrentTime; + } LastRecordedTime; + FILETIME ftLastRecordedKernelTime; + FILETIME ftLastRecordedUserTime; +} PAL_IOCP_CPU_INFORMATION; + +PALIMPORT +INT +PALAPI +PAL_GetCPUBusyTime( + IN OUT PAL_IOCP_CPU_INFORMATION *lpPrevCPUInfo); + +/****************PAL Perf functions for PInvoke*********************/ +#if PAL_PERF +PALIMPORT +VOID +PALAPI +PAL_EnableProcessProfile(VOID); + +PALIMPORT +VOID +PALAPI +PAL_DisableProcessProfile(VOID); + +PALIMPORT +BOOL +PALAPI +PAL_IsProcessProfileEnabled(VOID); + +PALIMPORT +INT64 +PALAPI +PAL_GetCpuTickCount(VOID); +#endif // PAL_PERF + +/******************* PAL functions for SIMD extensions *****************/ + +PALIMPORT +unsigned int _mm_getcsr(void); + +PALIMPORT +void _mm_setcsr(unsigned int i); + +/******************* PAL functions for CPU capability detection *******/ + +#ifdef __cplusplus + +class CORJIT_FLAGS; + +PALIMPORT +VOID +PALAPI +PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags); + +#endif + +/******************* PAL side-by-side support ************************/ + +#ifdef FEATURE_PAL_SXS +// +// Some versions of the PAL support several PALs side-by-side +// in the process. To avoid those PALs interfering with one +// another, they need to be told by clients when they are active +// and when they are not. +// + +// To avoid performance problems incurred by swapping thread +// exception ports every time we leave the PAL, there's also +// the concept of entering/leaving the PAL at its top boundary +// (entering down/leaving up) or at the bottom boundary +// (leaving down/entering up). + +typedef enum _PAL_Boundary { + PAL_BoundaryTop, // closer to main() + PAL_BoundaryBottom, // closer to execution + PAL_BoundaryEH, // out-of-band during EH + + PAL_BoundaryMax = PAL_BoundaryEH +} PAL_Boundary; + +// This function needs to be called on a thread when it enters +// a region of code that depends on this instance of the PAL +// in the process, and the current thread may or may not be +// known to the PAL. This function can fail (for something else +// than an internal error) if this is the first time that the +// current thread entered this PAL. Note that PAL_Initialize +// implies a call to this function. Does not modify LastError. +PALIMPORT +DWORD +PALAPI +PAL_Enter(PAL_Boundary boundary); + +// Returns TRUE if we this thread has already entered the PAL, +// returns FALSE if we have not entered the PAL. +PALIMPORT +BOOL +PALAPI +PAL_HasEntered(VOID); + +// Equivalent to PAL_Enter(PAL_BoundaryTop) and is for stub +// code generation use. +PALIMPORT +DWORD +PALAPI +PAL_EnterTop(VOID); + +// This function needs to be called on a thread when it enters +// a region of code that depends on this instance of the PAL +// in the process, and the current thread is already known to +// the PAL. Does not modify LastError. +PALIMPORT +VOID +PALAPI +PAL_Reenter(PAL_Boundary boundary); + +// This function needs to be called on a thread when it enters +// a region of code that depends on this instance of the PAL +// in the process, and it is unknown whether the current thread +// is already running in the PAL. Returns TRUE if and only if +// the thread was not running in the PAL previously. Does not +// modify LastError. +PALIMPORT +BOOL +PALAPI +PAL_ReenterForEH(VOID); + +// This function needs to be called on a thread when it leaves +// a region of code that depends on this instance of the PAL +// in the process. Does not modify LastError. +PALIMPORT +VOID +PALAPI +PAL_Leave(PAL_Boundary boundary); + +// This function is equivalent to PAL_Leave(PAL_BoundaryBottom) +// and is available to limit the creation of stub code. +PALIMPORT +VOID +PALAPI +PAL_LeaveBottom(VOID); + +// This function is equivalent to PAL_Leave(PAL_BoundaryTop) +// and is available to limit the creation of stub code. +PALIMPORT +VOID +PALAPI +PAL_LeaveTop(VOID); + +#ifdef __cplusplus +// +// A holder to enter the PAL for a specific region of code. +// Previously, we must have been executing outside the PAL +// (unless fEnter is set to FALSE). +// +class PAL_EnterHolder +{ +private: + BOOL m_fEntered; + DWORD m_palError; +public: + PAL_EnterHolder(BOOL fEnter = TRUE) : m_palError(ERROR_SUCCESS) + { + if (fEnter) + { + m_palError = PAL_Enter(PAL_BoundaryTop); + m_fEntered = m_palError == ERROR_SUCCESS; + } + else + { + m_fEntered = FALSE; + } + } + + ~PAL_EnterHolder() + { + if (m_fEntered) + { + PAL_Leave(PAL_BoundaryTop); + } + } + + DWORD GetError() + { + return m_palError; + } + + void SuppressRelease() + { + // Used to avoid calling PAL_Leave() when + // another code path will explicitly do so. + m_fEntered = FALSE; + } +}; + +class PAL_LeaveHolder +{ +public: + PAL_LeaveHolder() + { + PAL_Leave(PAL_BoundaryBottom); + } + + ~PAL_LeaveHolder() + { + PAL_Reenter(PAL_BoundaryBottom); + } +}; +#endif // __cplusplus + +#else // FEATURE_PAL_SXS + +#define PAL_Enter(boundary) ERROR_SUCCESS +#define PAL_Reenter(boundary) +#define PAL_Leave(boundary) + +#ifdef __cplusplus +class PAL_EnterHolder { +public: + // using constructor to suppress the "unused variable" warnings + PAL_EnterHolder() {} +}; +class PAL_LeaveHolder { +public: + // using constructor to suppress the "unused variable" warnings + PAL_LeaveHolder() {} +}; +#endif // __cplusplus + +#endif // FEATURE_PAL_SXS + +#ifdef __cplusplus + +#include "pal_unwind.h" + +PALIMPORT +VOID +PALAPI +PAL_FreeExceptionRecords( + IN EXCEPTION_RECORD *exceptionRecord, + IN CONTEXT *contextRecord); + +#define EXCEPTION_CONTINUE_SEARCH 0 +#define EXCEPTION_EXECUTE_HANDLER 1 +#define EXCEPTION_CONTINUE_EXECUTION -1 + +struct PAL_SEHException +{ +private: + static const SIZE_T NoTargetFrameSp = (SIZE_T)SIZE_MAX; + + void Move(PAL_SEHException& ex) + { + ExceptionPointers.ExceptionRecord = ex.ExceptionPointers.ExceptionRecord; + ExceptionPointers.ContextRecord = ex.ExceptionPointers.ContextRecord; + TargetFrameSp = ex.TargetFrameSp; + RecordsOnStack = ex.RecordsOnStack; + + ex.Clear(); + } + + void FreeRecords() + { + if (ExceptionPointers.ExceptionRecord != NULL && !RecordsOnStack ) + { + PAL_FreeExceptionRecords(ExceptionPointers.ExceptionRecord, ExceptionPointers.ContextRecord); + ExceptionPointers.ExceptionRecord = NULL; + ExceptionPointers.ContextRecord = NULL; + } + } + +public: + EXCEPTION_POINTERS ExceptionPointers; + // Target frame stack pointer set before the 2nd pass. + SIZE_T TargetFrameSp; + bool RecordsOnStack; + + PAL_SEHException(EXCEPTION_RECORD *pExceptionRecord, CONTEXT *pContextRecord, bool onStack = false) + { + ExceptionPointers.ExceptionRecord = pExceptionRecord; + ExceptionPointers.ContextRecord = pContextRecord; + TargetFrameSp = NoTargetFrameSp; + RecordsOnStack = onStack; + } + + PAL_SEHException() + { + Clear(); + } + + // The copy constructor and copy assignment operators are deleted so that the PAL_SEHException + // can never be copied, only moved. This enables simple lifetime management of the exception and + // context records, since there is always just one PAL_SEHException instance referring to the same records. + PAL_SEHException(const PAL_SEHException& ex) = delete; + PAL_SEHException& operator=(const PAL_SEHException& ex) = delete; + + PAL_SEHException(PAL_SEHException&& ex) + { + Move(ex); + } + + PAL_SEHException& operator=(PAL_SEHException&& ex) + { + FreeRecords(); + Move(ex); + return *this; + } + + ~PAL_SEHException() + { + FreeRecords(); + } + + void Clear() + { + ExceptionPointers.ExceptionRecord = NULL; + ExceptionPointers.ContextRecord = NULL; + TargetFrameSp = NoTargetFrameSp; + RecordsOnStack = false; + } + + CONTEXT* GetContextRecord() + { + return ExceptionPointers.ContextRecord; + } + + EXCEPTION_RECORD* GetExceptionRecord() + { + return ExceptionPointers.ExceptionRecord; + } + + bool IsFirstPass() + { + return (TargetFrameSp == NoTargetFrameSp); + } + + void SecondPassDone() + { + TargetFrameSp = NoTargetFrameSp; + } +}; + +typedef BOOL (*PHARDWARE_EXCEPTION_HANDLER)(PAL_SEHException* ex); +typedef BOOL (*PHARDWARE_EXCEPTION_SAFETY_CHECK_FUNCTION)(PCONTEXT contextRecord, PEXCEPTION_RECORD exceptionRecord); +typedef VOID (*PTERMINATION_REQUEST_HANDLER)(int terminationExitCode); +typedef DWORD (*PGET_GCMARKER_EXCEPTION_CODE)(LPVOID ip); + +PALIMPORT +VOID +PALAPI +PAL_SetHardwareExceptionHandler( + IN PHARDWARE_EXCEPTION_HANDLER exceptionHandler, + IN PHARDWARE_EXCEPTION_SAFETY_CHECK_FUNCTION exceptionCheckFunction); + +PALIMPORT +VOID +PALAPI +PAL_SetGetGcMarkerExceptionCode( + IN PGET_GCMARKER_EXCEPTION_CODE getGcMarkerExceptionCode); + +PALIMPORT +VOID +PALAPI +PAL_ThrowExceptionFromContext( + IN CONTEXT* context, + IN PAL_SEHException* ex); + +PALIMPORT +VOID +PALAPI +PAL_SetTerminationRequestHandler( + IN PTERMINATION_REQUEST_HANDLER terminationRequestHandler); + +PALIMPORT +VOID +PALAPI +PAL_CatchHardwareExceptionHolderEnter(); + +PALIMPORT +VOID +PALAPI +PAL_CatchHardwareExceptionHolderExit(); + +// +// This holder is used to indicate that a hardware +// exception should be raised as a C++ exception +// to better emulate SEH on the xplat platforms. +// +class CatchHardwareExceptionHolder +{ +public: + CatchHardwareExceptionHolder() + { + PAL_CatchHardwareExceptionHolderEnter(); + } + + ~CatchHardwareExceptionHolder() + { + PAL_CatchHardwareExceptionHolderExit(); + } + + static bool IsEnabled(); +}; + +// +// NOTE: This is only defined in one PAL test. +// +#ifdef FEATURE_ENABLE_HARDWARE_EXCEPTIONS +#define HardwareExceptionHolder CatchHardwareExceptionHolder __catchHardwareException; +#else +#define HardwareExceptionHolder +#endif // FEATURE_ENABLE_HARDWARE_EXCEPTIONS + +#ifdef FEATURE_PAL_SXS + +class NativeExceptionHolderBase; + +PALIMPORT +PALAPI +NativeExceptionHolderBase ** +PAL_GetNativeExceptionHolderHead(); + +extern "C++" { + +// +// This is the base class of native exception holder used to provide +// the filter function to the exception dispatcher. This allows the +// filter to be called during the first pass to better emulate SEH +// the xplat platforms that only have C++ exception support. +// +class NativeExceptionHolderBase +{ + // Save the address of the holder head so the destructor + // doesn't have access the slow (on Linux) TLS value again. + NativeExceptionHolderBase **m_head; + + // The next holder on the stack + NativeExceptionHolderBase *m_next; + +protected: + NativeExceptionHolderBase() + { + m_head = nullptr; + m_next = nullptr; + } + + ~NativeExceptionHolderBase() + { + // Only destroy if Push was called + if (m_head != nullptr) + { + *m_head = m_next; + m_head = nullptr; + m_next = nullptr; + } + } + +public: + // Calls the holder's filter handler. + virtual EXCEPTION_DISPOSITION InvokeFilter(PAL_SEHException& ex) = 0; + + // Adds the holder to the "stack" of holders. This is done explicitly instead + // of in the constructor was to avoid the mess of move constructors combined + // with return value optimization (in CreateHolder). + void Push() + { + NativeExceptionHolderBase **head = PAL_GetNativeExceptionHolderHead(); + m_head = head; + m_next = *head; + *head = this; + } + + // Given the currentHolder and locals stack range find the next holder starting with this one + // To find the first holder, pass nullptr as the currentHolder. + static NativeExceptionHolderBase *FindNextHolder(NativeExceptionHolderBase *currentHolder, PVOID frameLowAddress, PVOID frameHighAddress); +}; + +// +// This is the second part of the native exception filter holder. It is +// templated because the lambda used to wrap the exception filter is a +// unknown type. +// +template +class NativeExceptionHolder : public NativeExceptionHolderBase +{ + FilterType* m_exceptionFilter; + +public: + NativeExceptionHolder(FilterType* exceptionFilter) + : NativeExceptionHolderBase() + { + m_exceptionFilter = exceptionFilter; + } + + virtual EXCEPTION_DISPOSITION InvokeFilter(PAL_SEHException& ex) + { + return (*m_exceptionFilter)(ex); + } +}; + +// +// This is a native exception holder that is used when the catch catches +// all exceptions. +// +class NativeExceptionHolderCatchAll : public NativeExceptionHolderBase +{ + +public: + NativeExceptionHolderCatchAll() + : NativeExceptionHolderBase() + { + } + + virtual EXCEPTION_DISPOSITION InvokeFilter(PAL_SEHException& ex) + { + return EXCEPTION_EXECUTE_HANDLER; + } +}; + +// This is a native exception holder that doesn't catch any exceptions. +class NativeExceptionHolderNoCatch : public NativeExceptionHolderBase +{ + +public: + NativeExceptionHolderNoCatch() + : NativeExceptionHolderBase() + { + } + + virtual EXCEPTION_DISPOSITION InvokeFilter(PAL_SEHException& ex) + { + return EXCEPTION_CONTINUE_SEARCH; + } +}; + +// +// This factory class for the native exception holder is necessary because +// templated functions don't need the explicit type parameter and can infer +// the template type from the parameter. +// +class NativeExceptionHolderFactory +{ +public: + template + static NativeExceptionHolder CreateHolder(FilterType* exceptionFilter) + { + return NativeExceptionHolder(exceptionFilter); + } +}; + +// Start of a try block for exceptions raised by RaiseException +#define PAL_TRY(__ParamType, __paramDef, __paramRef) \ +{ \ + __ParamType __param = __paramRef; \ + auto tryBlock = [](__ParamType __paramDef) \ + { + +// Start of an exception handler. If an exception raised by the RaiseException +// occurs in the try block and the disposition is EXCEPTION_EXECUTE_HANDLER, +// the handler code is executed. If the disposition is EXCEPTION_CONTINUE_SEARCH, +// the exception is rethrown. The EXCEPTION_CONTINUE_EXECUTION disposition is +// not supported. +#define PAL_EXCEPT(dispositionExpression) \ + }; \ + const bool isFinally = false; \ + auto finallyBlock = []() {}; \ + EXCEPTION_DISPOSITION disposition = EXCEPTION_CONTINUE_EXECUTION; \ + auto exceptionFilter = [&disposition, &__param](PAL_SEHException& ex) \ + { \ + (void)__param; \ + disposition = dispositionExpression; \ + _ASSERTE(disposition != EXCEPTION_CONTINUE_EXECUTION); \ + return disposition; \ + }; \ + try \ + { \ + HardwareExceptionHolder \ + auto __exceptionHolder = NativeExceptionHolderFactory::CreateHolder(&exceptionFilter); \ + __exceptionHolder.Push(); \ + tryBlock(__param); \ + } \ + catch (PAL_SEHException& ex) \ + { \ + if (disposition == EXCEPTION_CONTINUE_EXECUTION) \ + { \ + exceptionFilter(ex); \ + } \ + if (disposition == EXCEPTION_CONTINUE_SEARCH) \ + { \ + throw; \ + } \ + ex.SecondPassDone(); + +// Start of an exception handler. It works the same way as the PAL_EXCEPT except +// that the disposition is obtained by calling the specified filter. +#define PAL_EXCEPT_FILTER(filter) PAL_EXCEPT(filter(&ex.ExceptionPointers, __param)) + +// Start of a finally block. The finally block is executed both when the try block +// finishes or when an exception is raised using the RaiseException in it. +#define PAL_FINALLY \ + }; \ + const bool isFinally = true; \ + auto finallyBlock = [&]() \ + { + +// End of an except or a finally block. +#define PAL_ENDTRY \ + }; \ + if (isFinally) \ + { \ + try \ + { \ + tryBlock(__param); \ + } \ + catch (...) \ + { \ + finallyBlock(); \ + throw; \ + } \ + finallyBlock(); \ + } \ +} + +} // extern "C++" + +#endif // FEATURE_PAL_SXS + +#define PAL_CPP_THROW(type, obj) { throw obj; } +#define PAL_CPP_RETHROW { throw; } +#define PAL_CPP_TRY try { HardwareExceptionHolder +#define PAL_CPP_CATCH_EXCEPTION(ident) } catch (Exception *ident) { PAL_Reenter(PAL_BoundaryBottom); +#define PAL_CPP_CATCH_EXCEPTION_NOARG } catch (Exception *) { PAL_Reenter(PAL_BoundaryBottom); +#define PAL_CPP_CATCH_DERIVED(type, ident) } catch (type *ident) { PAL_Reenter(PAL_BoundaryBottom); +#define PAL_CPP_CATCH_ALL } catch (...) { \ + PAL_Reenter(PAL_BoundaryBottom); \ + try { throw; } \ + catch (PAL_SEHException& ex) { ex.SecondPassDone(); } \ + catch (...) {} + +#define PAL_CPP_ENDTRY } + +#ifdef _MSC_VER +#pragma warning(disable:4611) // interaction between '_setjmp' and C++ object destruction is non-portable +#endif + +#ifdef FEATURE_PAL_SXS + +#define PAL_TRY_FOR_DLLMAIN(ParamType, paramDef, paramRef, _reason) PAL_TRY(ParamType, paramDef, paramRef) + +#else // FEATURE_PAL_SXS + +#define PAL_TRY(ParamType, paramDef, paramRef) \ + { \ + ParamType __param = paramRef; \ + ParamType paramDef; paramDef = __param; \ + try { \ + HardwareExceptionHolder + +#define PAL_TRY_FOR_DLLMAIN(ParamType, paramDef, paramRef, _reason) \ + { \ + ParamType __param = paramRef; \ + ParamType paramDef; paramDef = __param; \ + try { \ + HardwareExceptionHolder + +#define PAL_ENDTRY \ + } \ + } + +#endif // FEATURE_PAL_SXS + +#endif // __cplusplus + +// Platform-specific library naming +// +#ifdef __APPLE__ +#define MAKEDLLNAME_W(name) u"lib" name u".dylib" +#define MAKEDLLNAME_A(name) "lib" name ".dylib" +#else +#define MAKEDLLNAME_W(name) u"lib" name u".so" +#define MAKEDLLNAME_A(name) "lib" name ".so" +#endif + +#ifdef UNICODE +#define MAKEDLLNAME(x) MAKEDLLNAME_W(x) +#else +#define MAKEDLLNAME(x) MAKEDLLNAME_A(x) +#endif + +#define PAL_SHLIB_PREFIX "lib" +#define PAL_SHLIB_PREFIX_W u"lib" + +#if __APPLE__ +#define PAL_SHLIB_SUFFIX ".dylib" +#define PAL_SHLIB_SUFFIX_W u".dylib" +#else +#define PAL_SHLIB_SUFFIX ".so" +#define PAL_SHLIB_SUFFIX_W u".so" +#endif + +#define DBG_EXCEPTION_HANDLED ((DWORD )0x00010001L) +#define DBG_CONTINUE ((DWORD )0x00010002L) +#define DBG_EXCEPTION_NOT_HANDLED ((DWORD )0x80010001L) + +#define DBG_TERMINATE_THREAD ((DWORD )0x40010003L) +#define DBG_TERMINATE_PROCESS ((DWORD )0x40010004L) +#define DBG_CONTROL_C ((DWORD )0x40010005L) +#define DBG_RIPEXCEPTION ((DWORD )0x40010007L) +#define DBG_CONTROL_BREAK ((DWORD )0x40010008L) +#define DBG_COMMAND_EXCEPTION ((DWORD )0x40010009L) + +#define STATUS_USER_APC ((DWORD )0x000000C0L) +#define STATUS_GUARD_PAGE_VIOLATION ((DWORD )0x80000001L) +#define STATUS_DATATYPE_MISALIGNMENT ((DWORD )0x80000002L) +#define STATUS_BREAKPOINT ((DWORD )0x80000003L) +#define STATUS_SINGLE_STEP ((DWORD )0x80000004L) +#define STATUS_LONGJUMP ((DWORD )0x80000026L) +#define STATUS_UNWIND_CONSOLIDATE ((DWORD )0x80000029L) +#define STATUS_ACCESS_VIOLATION ((DWORD )0xC0000005L) +#define STATUS_IN_PAGE_ERROR ((DWORD )0xC0000006L) +#define STATUS_INVALID_HANDLE ((DWORD )0xC0000008L) +#define STATUS_NO_MEMORY ((DWORD )0xC0000017L) +#define STATUS_ILLEGAL_INSTRUCTION ((DWORD )0xC000001DL) +#define STATUS_NONCONTINUABLE_EXCEPTION ((DWORD )0xC0000025L) +#define STATUS_INVALID_DISPOSITION ((DWORD )0xC0000026L) +#define STATUS_ARRAY_BOUNDS_EXCEEDED ((DWORD )0xC000008CL) +#define STATUS_FLOAT_DENORMAL_OPERAND ((DWORD )0xC000008DL) +#define STATUS_FLOAT_DIVIDE_BY_ZERO ((DWORD )0xC000008EL) +#define STATUS_FLOAT_INEXACT_RESULT ((DWORD )0xC000008FL) +#define STATUS_FLOAT_INVALID_OPERATION ((DWORD )0xC0000090L) +#define STATUS_FLOAT_OVERFLOW ((DWORD )0xC0000091L) +#define STATUS_FLOAT_STACK_CHECK ((DWORD )0xC0000092L) +#define STATUS_FLOAT_UNDERFLOW ((DWORD )0xC0000093L) +#define STATUS_INTEGER_DIVIDE_BY_ZERO ((DWORD )0xC0000094L) +#define STATUS_INTEGER_OVERFLOW ((DWORD )0xC0000095L) +#define STATUS_PRIVILEGED_INSTRUCTION ((DWORD )0xC0000096L) +#define STATUS_STACK_OVERFLOW ((DWORD )0xC00000FDL) +#define STATUS_CONTROL_C_EXIT ((DWORD )0xC000013AL) + +#define WAIT_IO_COMPLETION STATUS_USER_APC + +#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION +#define EXCEPTION_DATATYPE_MISALIGNMENT STATUS_DATATYPE_MISALIGNMENT +#define EXCEPTION_BREAKPOINT STATUS_BREAKPOINT +#define EXCEPTION_SINGLE_STEP STATUS_SINGLE_STEP +#define EXCEPTION_ARRAY_BOUNDS_EXCEEDED STATUS_ARRAY_BOUNDS_EXCEEDED +#define EXCEPTION_FLT_DENORMAL_OPERAND STATUS_FLOAT_DENORMAL_OPERAND +#define EXCEPTION_FLT_DIVIDE_BY_ZERO STATUS_FLOAT_DIVIDE_BY_ZERO +#define EXCEPTION_FLT_INEXACT_RESULT STATUS_FLOAT_INEXACT_RESULT +#define EXCEPTION_FLT_INVALID_OPERATION STATUS_FLOAT_INVALID_OPERATION +#define EXCEPTION_FLT_OVERFLOW STATUS_FLOAT_OVERFLOW +#define EXCEPTION_FLT_STACK_CHECK STATUS_FLOAT_STACK_CHECK +#define EXCEPTION_FLT_UNDERFLOW STATUS_FLOAT_UNDERFLOW +#define EXCEPTION_INT_DIVIDE_BY_ZERO STATUS_INTEGER_DIVIDE_BY_ZERO +#define EXCEPTION_INT_OVERFLOW STATUS_INTEGER_OVERFLOW +#define EXCEPTION_PRIV_INSTRUCTION STATUS_PRIVILEGED_INSTRUCTION +#define EXCEPTION_IN_PAGE_ERROR STATUS_IN_PAGE_ERROR +#define EXCEPTION_ILLEGAL_INSTRUCTION STATUS_ILLEGAL_INSTRUCTION +#define EXCEPTION_NONCONTINUABLE_EXCEPTION STATUS_NONCONTINUABLE_EXCEPTION +#define EXCEPTION_STACK_OVERFLOW STATUS_STACK_OVERFLOW +#define EXCEPTION_INVALID_DISPOSITION STATUS_INVALID_DISPOSITION +#define EXCEPTION_GUARD_PAGE STATUS_GUARD_PAGE_VIOLATION +#define EXCEPTION_INVALID_HANDLE STATUS_INVALID_HANDLE + +#define CONTROL_C_EXIT STATUS_CONTROL_C_EXIT + +/* These are from the file in windows. + They are needed for _open_osfhandle.*/ +#define _O_RDONLY 0x0000 +#define _O_APPEND 0x0008 +#define _O_TEXT 0x4000 +#define _O_BINARY 0x8000 + +#ifdef __cplusplus +} +#endif + +#endif // __PAL_H__ diff --git a/lib/coreclr/src/pal/inc/pal_assert.h b/lib/coreclr/src/pal/inc/pal_assert.h new file mode 100644 index 0000000000..67ab24f527 --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal_assert.h @@ -0,0 +1,61 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + + + +--*/ + +#ifndef __PAL_ASSERT_H__ +#define __PAL_ASSERT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +// +// C_ASSERT() can be used to perform many compile-time assertions: +// type sizes, field offsets, etc. +// +#define C_ASSERT(e) static_assert(e, #e) + +// +// CPP_ASSERT() can be used within a class definition, to perform a +// compile-time assertion involving private names within the class. +// +#define CPP_ASSERT(n, e) static_assert(e, #e) + +#endif // __cplusplus + +#if defined(_DEBUG) +#define _ASSERTE(e) do { \ + if (!(e)) { \ + fprintf (stderr, \ + "ASSERT FAILED\n" \ + "\tExpression: %s\n" \ + "\tLocation: line %d in %s\n" \ + "\tFunction: %s\n" \ + "\tProcess: %d\n", \ + #e, __LINE__, __FILE__, __FUNCTION__, \ + GetCurrentProcessId()); \ + DebugBreak(); \ + } \ + }while (0) +#else // !DEBUG +#define _ASSERTE(e) ((void)0) +#endif + +#ifndef assert +#define assert(e) _ASSERTE(e) +#endif // assert + +#ifdef __cplusplus +} +#endif + +#endif // __PAL_ASSERT_H__ diff --git a/lib/coreclr/src/pal/inc/pal_char16.h b/lib/coreclr/src/pal/inc/pal_char16.h new file mode 100644 index 0000000000..0697b23d43 --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal_char16.h @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + pal_char16.h + +Abstract: + +This file is used to define the wchar_t type as a 16-bit type on Unix. + + + +--*/ + +// The unix compilers use a 32-bit wchar_t, so we must make a 16 bit wchar_t. +// The windows compilers, gcc and MSVC, both define a 16 bit wchar_t. + +// Note : wchar_t is a built-in type in C++, gcc/llvm ignores any attempts to +// typedef it. Using the preprocessor here, we make sure gcc sees +// __wchar_16_cpp__ instead of wchar_t. This is apparently not necessary under +// vc++, for whom wchar_t is already a typedef instead of a built-in. + +#ifndef PAL_STDCPP_COMPAT +#undef wchar_t +#undef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ __wchar_16_cpp__ +#define wchar_t __wchar_16_cpp__ + +// Set up the wchar_t type (which got preprocessed to __wchar_16_cpp__). +// In C++11, the standard gives us char16_t, which is what we want (and matches types with u"") +// In C, this doesn't exist, so use unsigned short. +// **** WARNING: Linking C and C++ objects will break with -fstrict-aliasing with GCC/Clang +// due to conditional typedef +#if !defined(_WCHAR_T_DEFINED) || !defined(_MSC_VER) +#if defined(__cplusplus) +#undef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ char16_t +typedef char16_t wchar_t; +#else +#undef __WCHAR_TYPE__ +#define __WCHAR_TYPE__ unsigned short +typedef unsigned short wchar_t; +#endif // __cplusplus + +#ifndef _WCHAR_T_DEFINED +#define _WCHAR_T_DEFINED +#endif // !_WCHAR_T_DEFINED +#endif // !_WCHAR_T_DEFINED || !_MSC_VER +#endif // !PAL_STDCPP_COMPAT diff --git a/lib/coreclr/src/pal/inc/pal_endian.h b/lib/coreclr/src/pal/inc/pal_endian.h new file mode 100644 index 0000000000..50b9e76765 --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal_endian.h @@ -0,0 +1,169 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + + + +--*/ + +#ifndef __PAL_ENDIAN_H__ +#define __PAL_ENDIAN_H__ + +#ifdef __cplusplus +extern "C++" { +inline UINT16 SWAP16(UINT16 x) +{ + return (x >> 8) | (x << 8); +} + +inline UINT32 SWAP32(UINT32 x) +{ + return (x >> 24) | + ((x >> 8) & 0x0000FF00L) | + ((x & 0x0000FF00L) << 8) | + (x << 24); +} + +} +#endif // __cplusplus + +#if BIGENDIAN +#ifdef __cplusplus +extern "C++" { +inline UINT16 VAL16(UINT16 x) +{ + return SWAP16(x); +} + +inline UINT32 VAL32(UINT32 x) +{ + return SWAP32(x); +} + +inline UINT64 VAL64(UINT64 x) +{ + return ((UINT64)VAL32(x) << 32) | VAL32(x >> 32); +} + +inline void SwapString(WCHAR *szString) +{ + unsigned i; + for (i = 0; szString[i] != L'\0'; i++) + { + szString[i] = VAL16(szString[i]); + } +} + +inline void SwapStringLength(WCHAR *szString, ULONG StringLength) +{ + unsigned i; + for (i = 0; i < StringLength; i++) + { + szString[i] = VAL16(szString[i]); + } +} + +inline void SwapGuid(GUID *pGuid) +{ + pGuid->Data1 = VAL32(pGuid->Data1); + pGuid->Data2 = VAL16(pGuid->Data2); + pGuid->Data3 = VAL16(pGuid->Data3); +} +}; +#else // __cplusplus +/* C Version of VAL functionality. Swap functions omitted for lack of use in C code */ +#define VAL16(x) (((x) >> 8) | ((x) << 8)) +#define VAL32(y) (((y) >> 24) | (((y) >> 8) & 0x0000FF00L) | (((y) & 0x0000FF00L) << 8) | ((y) << 24)) +#define VAL64(z) (((UINT64)VAL32(z) << 32) | VAL32((z) >> 32)) +#endif // __cplusplus + +#else // !BIGENDIAN + +#define VAL16(x) x +#define VAL32(x) x +#define VAL64(x) x +#define SwapString(x) +#define SwapStringLength(x, y) +#define SwapGuid(x) + +#endif // !BIGENDIAN + +#ifdef BIT64 +#define VALPTR(x) VAL64(x) +#else +#define VALPTR(x) VAL32(x) +#endif + +#ifdef _ARM_ +#define LOG2_PTRSIZE 2 +#define ALIGN_ACCESS ((1< long = 64 bits +// LLP64 => longs = 32 bits, long long = 64 bits) +// +// To handle this difference, we #define long to be int (and thus 32 bits) when +// compiling those files. (See the bottom of this file or search for +// #define long to see where we do this.) +// +// But this fix is more complicated than it seems, because we also use the +// preprocessor to #define __int64 to long for LP64 architectures (__int64 +// isn't a builtin in gcc). We don't want __int64 to be an int (by cascading +// macro rules). So we play this little trick below where we add +// __cppmungestrip before "long", which is what we're really #defining __int64 +// to. The preprocessor sees __cppmungestriplong as something different than +// long, so it doesn't replace it with int. The during the cppmunge phase, we +// remove the __cppmungestrip part, leaving long for the compiler to see. +// +// Note that we can't just use a typedef to define __int64 as long before +// #defining long because typedefed types can't be signedness-agnostic (i.e. +// they must be either signed or unsigned) and we want to be able to use +// __int64 as though it were intrinsic + +#ifdef BIT64 +#define __int64 long +#else // BIT64 +#define __int64 long long +#endif // BIT64 + +#define __int32 int +#define __int16 short int +#define __int8 char // assumes char is signed + +#endif // _MSC_VER + +#ifndef PAL_STDCPP_COMPAT +// Defined in gnu's types.h. For non PAL_IMPLEMENTATION system +// includes are not included, so we need to define them. +#ifndef PAL_IMPLEMENTATION + +// OS X already defines these types in 64 bit +#if !defined(_TARGET_MAC64) +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +#endif + +#endif // PAL_IMPLEMENTATION + +#ifndef _MSC_VER + +#if _WIN64 +typedef long double LONG_DOUBLE; +#endif + +#endif // _MSC_VER +#endif // !PAL_STDCPP_COMPAT + +typedef void VOID; + +typedef int LONG; // NOTE: diff from windows.h, for LP64 compat +typedef unsigned int ULONG; // NOTE: diff from windows.h, for LP64 compat + +typedef __int64 LONGLONG; +typedef unsigned __int64 ULONGLONG; +typedef ULONGLONG DWORD64; +typedef DWORD64 *PDWORD64; +typedef LONGLONG *PLONG64; +typedef ULONGLONG *PULONG64; +typedef ULONGLONG *PULONGLONG; +typedef ULONG *PULONG; +typedef short SHORT; +typedef SHORT *PSHORT; +typedef unsigned short USHORT; +typedef USHORT *PUSHORT; +typedef unsigned char UCHAR; +typedef UCHAR *PUCHAR; +typedef char *PSZ; +typedef ULONGLONG DWORDLONG; + +typedef unsigned int DWORD; // NOTE: diff from windows.h, for LP64 compat +typedef unsigned int DWORD32, *PDWORD32; + +typedef int BOOL; +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef float FLOAT; +typedef double DOUBLE; +typedef BOOL *PBOOL; +typedef BOOL *LPBOOL; +typedef BYTE *PBYTE; +typedef BYTE *LPBYTE; +typedef const BYTE *LPCBYTE; +typedef int *PINT; +typedef int *LPINT; +typedef WORD *PWORD; +typedef WORD *LPWORD; +typedef LONG *LPLONG; +typedef LPLONG PLONG; +typedef DWORD *PDWORD; +typedef DWORD *LPDWORD; +typedef void *PVOID; +typedef void *LPVOID; +typedef CONST void *LPCVOID; +typedef int INT; +typedef unsigned int UINT; +typedef unsigned int *PUINT; +typedef BYTE BOOLEAN; +typedef BOOLEAN *PBOOLEAN; + +typedef unsigned __int8 UINT8; +typedef signed __int8 INT8; +typedef unsigned __int16 UINT16; +typedef signed __int16 INT16; +typedef unsigned __int32 UINT32, *PUINT32; +typedef signed __int32 INT32, *PINT32; +typedef unsigned __int64 UINT64, *PUINT64; +typedef signed __int64 INT64, *PINT64; + +typedef unsigned __int32 ULONG32, *PULONG32; +typedef signed __int32 LONG32, *PLONG32; +typedef unsigned __int64 ULONG64; +typedef signed __int64 LONG64; + +#if defined(_X86_) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif + +#ifdef BIT64 + +#define _atoi64 (__int64)atoll + +typedef __int64 INT_PTR, *PINT_PTR; +typedef unsigned __int64 UINT_PTR, *PUINT_PTR; +typedef __int64 LONG_PTR, *PLONG_PTR; +typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; +typedef unsigned __int64 DWORD_PTR, *PDWORD_PTR; + +/* maximum signed 64 bit value */ +#define LONG_PTR_MAX I64(9223372036854775807) +/* maximum unsigned 64 bit value */ +#define ULONG_PTR_MAX UI64(0xffffffffffffffff) + +#ifndef SIZE_MAX +#define SIZE_MAX _UI64_MAX +#endif + +#define __int3264 __int64 + +#if !defined(BIT64) +__inline +unsigned long +HandleToULong( + const void *h + ) +{ + return((unsigned long) (ULONG_PTR) h ); +} + +__inline +long +HandleToLong( + const void *h + ) +{ + return((long) (LONG_PTR) h ); +} + +__inline +void * +ULongToHandle( + const unsigned long h + ) +{ + return((void *) (UINT_PTR) h ); +} + + +__inline +void * +LongToHandle( + const long h + ) +{ + return((void *) (INT_PTR) h ); +} + + +__inline +unsigned long +PtrToUlong( + const void *p + ) +{ + return((unsigned long) (ULONG_PTR) p ); +} + +__inline +unsigned int +PtrToUint( + const void *p + ) +{ + return((unsigned int) (UINT_PTR) p ); +} + +__inline +unsigned short +PtrToUshort( + const void *p + ) +{ + return((unsigned short) (unsigned long) (ULONG_PTR) p ); +} + +__inline +long +PtrToLong( + const void *p + ) +{ + return((long) (LONG_PTR) p ); +} + +__inline +int +PtrToInt( + const void *p + ) +{ + return((int) (INT_PTR) p ); +} + +__inline +short +PtrToShort( + const void *p + ) +{ + return((short) (long) (LONG_PTR) p ); +} + +__inline +void * +IntToPtr( + const int i + ) +// Caution: IntToPtr() sign-extends the int value. +{ + return( (void *)(INT_PTR)i ); +} + +__inline +void * +UIntToPtr( + const unsigned int ui + ) +// Caution: UIntToPtr() zero-extends the unsigned int value. +{ + return( (void *)(UINT_PTR)ui ); +} + +__inline +void * +LongToPtr( + const long l + ) +// Caution: LongToPtr() sign-extends the long value. +{ + return( (void *)(LONG_PTR)l ); +} + +__inline +void * +ULongToPtr( + const unsigned long ul + ) +// Caution: ULongToPtr() zero-extends the unsigned long value. +{ + return( (void *)(ULONG_PTR)ul ); +} + +__inline +void * +ShortToPtr( + const short s + ) +// Caution: ShortToPtr() sign-extends the short value. +{ + return( (void *)(INT_PTR)s ); +} + +__inline +void * +UShortToPtr( + const unsigned short us + ) +// Caution: UShortToPtr() zero-extends the unsigned short value. +{ + return( (void *)(UINT_PTR)us ); +} + +#else // !defined(BIT64) +#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) ) +#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) +#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) ) +#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) ) +#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) +#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) +#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) +#define PtrToInt( p ) ((INT)(INT_PTR) (p) ) +#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) +#define PtrToShort( p ) ((short)(LONG_PTR)(p) ) +#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)(i))) +#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)(ui))) +#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)(l))) +#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)(ul))) +#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)(s))) +#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)(s))) +#endif // !defined(BIT64) + + + +#else + +typedef _W64 __int32 INT_PTR; +typedef _W64 unsigned __int32 UINT_PTR; + +typedef _W64 __int32 LONG_PTR; +typedef _W64 unsigned __int32 ULONG_PTR, *PULONG_PTR; +typedef _W64 unsigned __int32 DWORD_PTR, *PDWORD_PTR; + +/* maximum signed 32 bit value */ +#define LONG_PTR_MAX 2147483647L +/* maximum unsigned 32 bit value */ +#define ULONG_PTR_MAX 0xffffffffUL + +#ifndef SIZE_MAX +#define SIZE_MAX UINT_MAX +#endif + +#define __int3264 __int32 + +#define HandleToULong( h ) ((ULONG)(ULONG_PTR)(h) ) +#define HandleToLong( h ) ((LONG)(LONG_PTR) (h) ) +#define ULongToHandle( ul ) ((HANDLE)(ULONG_PTR) (ul) ) +#define LongToHandle( h ) ((HANDLE)(LONG_PTR) (h) ) +#define PtrToUlong( p ) ((ULONG)(ULONG_PTR) (p) ) +#define PtrToLong( p ) ((LONG)(LONG_PTR) (p) ) +#define PtrToUint( p ) ((UINT)(UINT_PTR) (p) ) +#define PtrToInt( p ) ((INT)(INT_PTR) (p) ) +#define PtrToUshort( p ) ((unsigned short)(ULONG_PTR)(p) ) +#define PtrToShort( p ) ((short)(LONG_PTR)(p) ) +#define IntToPtr( i ) ((VOID *)(INT_PTR)((int)i)) +#define UIntToPtr( ui ) ((VOID *)(UINT_PTR)((unsigned int)ui)) +#define LongToPtr( l ) ((VOID *)(LONG_PTR)((long)l)) +#define ULongToPtr( ul ) ((VOID *)(ULONG_PTR)((unsigned long)ul)) +#define ShortToPtr( s ) ((VOID *)(INT_PTR)((short)s)) +#define UShortToPtr( us ) ((VOID *)(UINT_PTR)((unsigned short)s)) + +#endif + +#define HandleToUlong(h) HandleToULong(h) +#define UlongToHandle(ul) ULongToHandle(ul) +#define UlongToPtr(ul) ULongToPtr(ul) +#define UintToPtr(ui) UIntToPtr(ui) + +typedef ULONG_PTR SIZE_T, *PSIZE_T; +typedef LONG_PTR SSIZE_T, *PSSIZE_T; + +#ifndef SIZE_T_MAX +#define SIZE_T_MAX ULONG_PTR_MAX +#endif // SIZE_T_MAX + +#ifndef SSIZE_T_MAX +#define SSIZE_T_MAX LONG_PTR_MAX +#endif + +#ifndef SSIZE_T_MIN +#define SSIZE_T_MIN I64(0x8000000000000000) +#endif + +#ifndef PAL_STDCPP_COMPAT +#if defined(__APPLE_CC__) || defined(__linux__) +#ifdef BIT64 +typedef unsigned long size_t; +typedef long ptrdiff_t; +#else // !BIT64 +typedef unsigned int size_t; +typedef int ptrdiff_t; +#endif // !BIT64 +#else +typedef ULONG_PTR size_t; +typedef LONG_PTR ptrdiff_t; +#endif +#endif // !PAL_STDCPP_COMPAT +#define _SIZE_T_DEFINED + +typedef LONG_PTR LPARAM; + +#define _PTRDIFF_T_DEFINED +#ifdef _MINGW_ +// We need to define _PTRDIFF_T to make sure ptrdiff_t doesn't get defined +// again by system headers - but only for MinGW. +#define _PTRDIFF_T +#endif + +#ifdef PAL_STDCPP_COMPAT + +typedef char16_t WCHAR; + +#else // PAL_STDCPP_COMPAT + +typedef wchar_t WCHAR; +#if defined(__linux__) +#ifdef BIT64 +typedef long int intptr_t; +typedef unsigned long int uintptr_t; +#else // !BIT64 +typedef int intptr_t; +typedef unsigned int uintptr_t; +#endif // !BIT64 +#else +typedef INT_PTR intptr_t; +typedef UINT_PTR uintptr_t; +#endif + +#endif // PAL_STDCPP_COMPAT + +#define _INTPTR_T_DEFINED +#define _UINTPTR_T_DEFINED + +typedef DWORD LCID; +typedef PDWORD PLCID; +typedef WORD LANGID; + +typedef DWORD LCTYPE; + +typedef WCHAR *PWCHAR; +typedef WCHAR *LPWCH, *PWCH; +typedef CONST WCHAR *LPCWCH, *PCWCH; +typedef WCHAR *NWPSTR; +typedef WCHAR *LPWSTR, *PWSTR; + +typedef CONST WCHAR *LPCWSTR, *PCWSTR; + +typedef char CHAR; +typedef CHAR *PCHAR; +typedef CHAR *LPCH, *PCH; +typedef CONST CHAR *LPCCH, *PCCH; +typedef CHAR *NPSTR; +typedef CHAR *LPSTR, *PSTR; +typedef CONST CHAR *LPCSTR, *PCSTR; + +#ifdef UNICODE +typedef WCHAR TCHAR; +typedef WCHAR _TCHAR; +#else +typedef CHAR TCHAR; +typedef CHAR _TCHAR; +#endif +typedef TCHAR *PTCHAR; +typedef TCHAR *LPTSTR, *PTSTR; +typedef CONST TCHAR *LPCTSTR; + +#define MAKEWORD(a, b) ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xff))) << 8)) +#define MAKELONG(a, b) ((LONG)(((WORD)((DWORD_PTR)(a) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(b) & 0xffff))) << 16)) +#define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff)) +#define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) +#define LOBYTE(w) ((BYTE)((DWORD_PTR)(w) & 0xff)) +#define HIBYTE(w) ((BYTE)((DWORD_PTR)(w) >> 8)) + +typedef VOID *HANDLE; +typedef HANDLE HWND; +typedef struct __PAL_RemoteHandle__ { HANDLE h; } *RHANDLE; +typedef HANDLE *PHANDLE; +typedef HANDLE *LPHANDLE; +#define INVALID_HANDLE_VALUE ((VOID *)(-1)) +#define INVALID_FILE_SIZE ((DWORD)0xFFFFFFFF) +#define INVALID_FILE_ATTRIBUTES ((DWORD) -1) +typedef HANDLE HMODULE; +typedef HANDLE HINSTANCE; +typedef HANDLE HGLOBAL; +typedef HANDLE HLOCAL; +typedef HANDLE HRSRC; + +typedef LONG HRESULT; +typedef LONG NTSTATUS; + +typedef union _LARGE_INTEGER { + struct { +#if BIGENDIAN + LONG HighPart; + DWORD LowPart; +#else + DWORD LowPart; + LONG HighPart; +#endif + } u; + LONGLONG QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +#ifndef GUID_DEFINED +typedef struct _GUID { + ULONG Data1; // NOTE: diff from Win32, for LP64 + USHORT Data2; + USHORT Data3; + UCHAR Data4[ 8 ]; +} GUID; +typedef const GUID *LPCGUID; +#define GUID_DEFINED +#endif // !GUID_DEFINED + +typedef struct _FILETIME { + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, *PFILETIME, *LPFILETIME; + +/* Code Page Default Values */ +#define CP_ACP 0 /* default to ANSI code page */ +#define CP_OEMCP 1 /* default to OEM code page */ +#define CP_MACCP 2 /* default to MAC code page */ +#define CP_THREAD_ACP 3 /* current thread's ANSI code page */ +#define CP_WINUNICODE 1200 +#define CP_UNICODE 1200 /* Unicode */ +#define CP_UNICODESWAP 1201 /* Unicode Big-Endian */ +#define CP_UTF7 65000 /* UTF-7 translation */ +#define CP_UTF8 65001 /* UTF-8 translation */ + +typedef PVOID PSID; + +#ifdef __cplusplus +} +#endif + +#endif // __PAL_MSTYPES_H__ diff --git a/lib/coreclr/src/pal/inc/pal_safecrt.h b/lib/coreclr/src/pal/inc/pal_safecrt.h new file mode 100644 index 0000000000..d9e76cd783 --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal_safecrt.h @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + pal_safecrt.h + +Abstract: + +Wrapper for including SafeCRT for Mac build of CoreCLR + + + +--*/ + +#ifndef _PAL_SAFECRT_H_ +#define _PAL_SAFECRT_H_ + +#define _CRT_ALTERNATIVE_INLINES +#define _SAFECRT_NO_INCLUDES 1 + +#if !defined (_SAFECRT_USE_INLINES) +#define _SAFECRT_USE_INLINES 0 +#endif + +#if !defined (_SAFECRT_IMPL) +#define _SAFECRT_IMPL 0 +#endif + +#define _SAFECRT_SET_ERRNO 0 +#define _SAFECRT_DEFINE_MBS_FUNCTIONS 0 +#define _SAFECRT_DEFINE_TCS_MACROS 1 +//#define _SAFECRT_INVALID_PARAMETER(message) WARN(message "\n") + +#if defined (SAFECRT_IN_PAL) + +#define DUMMY_memset void * __cdecl memset(void *, int, size_t); + +#endif + +// Include the safecrt implementation +#include "../../palrt/inc/safecrt.h" + +#if defined(SAFECRT_IN_PAL) + +#define DUMMY_memset + +#endif + +#endif // _PAL_SAFECRT_H_ diff --git a/lib/coreclr/src/pal/inc/pal_unwind.h b/lib/coreclr/src/pal/inc/pal_unwind.h new file mode 100644 index 0000000000..2931488e3b --- /dev/null +++ b/lib/coreclr/src/pal/inc/pal_unwind.h @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Definition of the Unwind API functions. +// Taken from the ABI documentation. +// + + + +#ifndef __PAL_UNWIND_H__ +#define __PAL_UNWIND_H__ + +#if FEATURE_PAL_SXS + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + + // + // Exception Handling ABI Level I: Base ABI + // + + typedef enum + { + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + } _Unwind_Reason_Code; + + typedef enum + { + _UA_SEARCH_PHASE = 1, + _UA_CLEANUP_PHASE = 2, + _UA_HANDLER_FRAME = 4, + _UA_FORCE_UNWIND = 8, + } _Unwind_Action; + #define _UA_PHASE_MASK (_UA_SEARCH_PHASE|_UA_CLEANUP_PHASE) + + struct _Unwind_Context; + + void *_Unwind_GetIP(struct _Unwind_Context *context); + void _Unwind_SetIP(struct _Unwind_Context *context, void *new_value); + void *_Unwind_GetCFA(struct _Unwind_Context *context); + void *_Unwind_GetGR(struct _Unwind_Context *context, int index); + void _Unwind_SetGR(struct _Unwind_Context *context, int index, void *new_value); + + struct _Unwind_Exception; + + typedef void (*_Unwind_Exception_Cleanup_Fn)( + _Unwind_Reason_Code urc, + struct _Unwind_Exception *exception_object); + + struct _Unwind_Exception + { + ULONG64 exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + UINT_PTR private_1; + UINT_PTR private_2; + } __attribute__((aligned)); + + void _Unwind_DeleteException(struct _Unwind_Exception *exception_object); + + typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn)(struct _Unwind_Context *context, void *pvParam); + _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn pfnTrace, void *pvParam); + + _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exception_object); + __attribute__((noreturn)) void _Unwind_Resume(struct _Unwind_Exception *exception_object); + + // + // Exception Handling ABI Level II: C++ ABI + // + + void *__cxa_begin_catch(void *exceptionObject); + void __cxa_end_catch(); + +#ifdef __cplusplus +}; +#endif // __cplusplus + +#endif // FEATURE_PAL_SXS + +#endif // __PAL_UNWIND_H__ diff --git a/lib/coreclr/src/pal/inc/palprivate.h b/lib/coreclr/src/pal/inc/palprivate.h new file mode 100644 index 0000000000..b9c9d08a2f --- /dev/null +++ b/lib/coreclr/src/pal/inc/palprivate.h @@ -0,0 +1,287 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __PAL_PRIVATE_H__ +#define __PAL_PRIVATE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +PALIMPORT +int +PALAPI +MessageBoxA( + IN LPVOID hWnd, // NOTE: diff from winuser.h + IN LPCSTR lpText, + IN LPCSTR lpCaption, + IN UINT uType); + + +PALIMPORT +HANDLE +PALAPI +CreateFileA( + IN LPCSTR lpFileName, + IN DWORD dwDesiredAccess, + IN DWORD dwShareMode, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes, + IN DWORD dwCreationDisposition, + IN DWORD dwFlagsAndAttributes, + IN HANDLE hTemplateFile); + +PALIMPORT +DWORD +PALAPI +SearchPathA( + IN LPCSTR lpPath, + IN LPCSTR lpFileName, + IN LPCSTR lpExtension, + IN DWORD nBufferLength, + OUT LPSTR lpBuffer, + OUT LPSTR *lpFilePart + ); + +PALIMPORT +BOOL +PALAPI +CopyFileA( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN BOOL bFailIfExists); + + +PALIMPORT +BOOL +PALAPI +DeleteFileA( + IN LPCSTR lpFileName); + +PALIMPORT +BOOL +PALAPI +MoveFileExA( + IN LPCSTR lpExistingFileName, + IN LPCSTR lpNewFileName, + IN DWORD dwFlags); + +PALIMPORT +BOOL +PALAPI +CreateDirectoryA( + IN LPCSTR lpPathName, + IN LPSECURITY_ATTRIBUTES lpSecurityAttributes); + +PALIMPORT +HANDLE +PALAPI +FindFirstFileA( + IN LPCSTR lpFileName, + OUT LPWIN32_FIND_DATAA lpFindFileData); + +PALIMPORT +BOOL +PALAPI +FindNextFileA( + IN HANDLE hFindFile, + OUT LPWIN32_FIND_DATAA lpFindFileData); + +PALIMPORT +DWORD +PALAPI +GetFileAttributesA( + IN LPCSTR lpFileName); + +PALIMPORT +BOOL +PALAPI +SetFileAttributesA( + IN LPCSTR lpFileName, + IN DWORD dwFileAttributes); + +PALIMPORT +DWORD +PALAPI +GetFullPathNameA( + IN LPCSTR lpFileName, + IN DWORD nBufferLength, + OUT LPSTR lpBuffer, + OUT LPSTR *lpFilePart); + +PALIMPORT +UINT +PALAPI +GetTempFileNameA( + IN LPCSTR lpPathName, + IN LPCSTR lpPrefixString, + IN UINT uUnique, + OUT LPSTR lpTempFileName); + +PALIMPORT +DWORD +PALAPI +GetTempPathA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer); + +PALIMPORT +DWORD +PALAPI +GetCurrentDirectoryA( + IN DWORD nBufferLength, + OUT LPSTR lpBuffer); + +PALIMPORT +BOOL +PALAPI +SetCurrentDirectoryA( + IN LPCSTR lpPathName); + +PALIMPORT +HANDLE +PALAPI +CreateSemaphoreA( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCSTR lpName); + +PALIMPORT +HANDLE +PALAPI +CreateSemaphoreExA( + IN LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + IN LONG lInitialCount, + IN LONG lMaximumCount, + IN LPCSTR lpName, + IN /*_Reserved_*/ DWORD dwFlags, + IN DWORD dwDesiredAccess); + +PALIMPORT +HANDLE +PALAPI +CreateEventA( + IN LPSECURITY_ATTRIBUTES lpEventAttributes, + IN BOOL bManualReset, + IN BOOL bInitialState, + IN LPCSTR lpName); + +PALIMPORT +HANDLE +PALAPI +CreateMutexA( + IN LPSECURITY_ATTRIBUTES lpMutexAttributes, + IN BOOL bInitialOwner, + IN LPCSTR lpName); + +PALIMPORT +HANDLE +PALAPI +OpenMutexA( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName); + +PALIMPORT +BOOL +PALAPI +CreateProcessA( + IN LPCSTR lpApplicationName, + IN LPSTR lpCommandLine, + IN LPSECURITY_ATTRIBUTES lpProcessAttributes, + IN LPSECURITY_ATTRIBUTES lpThreadAttributes, + IN BOOL bInheritHandles, + IN DWORD dwCreationFlags, + IN LPVOID lpEnvironment, + IN LPCSTR lpCurrentDirectory, + IN LPSTARTUPINFOA lpStartupInfo, + OUT LPPROCESS_INFORMATION lpProcessInformation); + +PALIMPORT +HANDLE +PALAPI +CreateFileMappingA( + IN HANDLE hFile, + IN LPSECURITY_ATTRIBUTES lpFileMappingAttributes, + IN DWORD flProtect, + IN DWORD dwMaximumSizeHigh, + IN DWORD dwMaximumSizeLow, + IN LPCSTR lpName); + +PALIMPORT +HANDLE +PALAPI +OpenFileMappingA( + IN DWORD dwDesiredAccess, + IN BOOL bInheritHandle, + IN LPCSTR lpName); + +PALIMPORT +HMODULE +PALAPI +LoadLibraryA( + IN LPCSTR lpLibFileName); + +PALIMPORT +HMODULE +PALAPI +LoadLibraryExA( + IN LPCSTR lpLibFileName, + IN /*Reserved*/ HANDLE hFile, + IN DWORD dwFlags); + +PALIMPORT +DWORD +PALAPI +GetModuleFileNameA( + IN HMODULE hModule, + OUT LPSTR lpFileName, + IN DWORD nSize); + + +PALIMPORT +LPSTR +PALAPI +GetEnvironmentStringsA( + VOID); + +PALIMPORT +BOOL +PALAPI +SetEnvironmentVariableA( + IN LPCSTR lpName, + IN LPCSTR lpValue); + +PALIMPORT +DWORD +PALAPI +GetEnvironmentVariableA( + IN LPCSTR lpName, + OUT LPSTR lpBuffer, + IN DWORD nSize); + +PALIMPORT +BOOL +PALAPI +FreeEnvironmentStringsA( + IN LPSTR); + +PALIMPORT +BOOL +PALAPI +RemoveDirectoryA( + IN LPCSTR lpPathName); + +PALIMPORT +BOOL +PALAPI +PAL_GetPALDirectoryA( + OUT LPSTR lpDirectoryName, + IN UINT* cchDirectoryName); + +#ifdef __cplusplus +} +#endif + +#endif// __PAL_PRIVATE_H__ diff --git a/lib/coreclr/src/pal/inc/rt/accctrl.h b/lib/coreclr/src/pal/inc/rt/accctrl.h new file mode 100644 index 0000000000..6670eaca23 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/accctrl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: accctl.h +// +// =========================================================================== +// dummy accctl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/aclapi.h b/lib/coreclr/src/pal/inc/rt/aclapi.h new file mode 100644 index 0000000000..3cad8e48ae --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/aclapi.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: aclapi.h +// +// =========================================================================== +// dummy aclapi.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/atl.h b/lib/coreclr/src/pal/inc/rt/atl.h new file mode 100644 index 0000000000..9f95fc7248 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/atl.h @@ -0,0 +1,557 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: atl.h +// +// =========================================================================== + +#ifndef __ATL_H__ +#define __ATL_H__ + +#include "ole2.h" +///////////////////////////////////////////////////////////////////////////// +// COM Smart pointers + +template +class _NoAddRefReleaseOnCComPtr : public T +{ + private: + STDMETHOD_(ULONG, AddRef)()=0; + STDMETHOD_(ULONG, Release)()=0; +}; + +//CComPtrBase provides the basis for all other smart pointers +//The other smartpointers add their own constructors and operators +template +class CComPtrBase +{ +protected: + CComPtrBase() + { + p = NULL; + } + CComPtrBase(int nNull) + { + (void)nNull; + p = NULL; + } + CComPtrBase(T* lp) + { + p = lp; + if (p != NULL) + p->AddRef(); + } +public: + typedef T _PtrClass; + ~CComPtrBase() + { + if (p) + p->Release(); + } + operator T*() const + { + return p; + } + T& operator*() const + { + return *p; + } + T** operator&() + { + return &p; + } + _NoAddRefReleaseOnCComPtr* operator->() const + { + return (_NoAddRefReleaseOnCComPtr*)p; + } + bool operator!() const + { + return (p == NULL); + } + bool operator<(T* pT) const + { + return p < pT; + } + bool operator==(T* pT) const + { + return p == pT; + } + + // Release the interface and set to NULL + void Release() + { + T* pTemp = p; + if (pTemp) + { + p = NULL; + pTemp->Release(); + } + } + // Attach to an existing interface (does not AddRef) + void Attach(T* p2) + { + if (p) + p->Release(); + p = p2; + } + // Detach the interface (does not Release) + T* Detach() + { + T* pt = p; + p = NULL; + return pt; + } + HRESULT CopyTo(T** ppT) + { + if (ppT == NULL) + return E_POINTER; + *ppT = p; + if (p) + p->AddRef(); + return S_OK; + } + + T* p; +}; + +template +class CComPtr : public CComPtrBase +{ +public: + CComPtr() + { + } + CComPtr(int nNull) : + CComPtrBase(nNull) + { + } + CComPtr(T* lp) : + CComPtrBase(lp) + + { + } + CComPtr(const CComPtr& lp) : + CComPtrBase(lp.p) + { + } + T* operator=(T* lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&this->p, lp)); + } + T* operator=(const CComPtr& lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&this->p, lp)); + } +}; + +#define IUNKNOWN_METHODS \ +private: ULONG m_dwRef; \ +public: \ + virtual ULONG STDMETHODCALLTYPE AddRef( void) { \ + return (ULONG)InterlockedIncrement((LONG*)&m_dwRef); } \ + virtual ULONG STDMETHODCALLTYPE Release( void) { \ + ULONG new_ref = (ULONG)InterlockedDecrement((LONG*)&m_dwRef); \ + if (new_ref == 0) { delete this; return 0; } return new_ref; } \ + + +#define BEGIN_COM_MAP(t) \ + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) \ + { \ + if (ppvObject == NULL) \ + { \ + return E_POINTER; \ + } + +#define COM_INTERFACE_ENTRY(i) \ + if (riid == IID_##i) \ + { \ + *ppvObject = (i*)this; \ + this->AddRef(); \ + return S_OK; \ + } + +#define END_COM_MAP() \ + return E_NOINTERFACE; \ + } \ + virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; \ + virtual ULONG STDMETHODCALLTYPE Release( void) = 0; + + + +template +class ISupportErrorInfoImpl : public ISupportErrorInfo +{ +public: + STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid) + { + return (riid == *piid) ? S_OK : S_FALSE; + } +}; + +inline IUnknown* AtlComPtrAssign(IUnknown** pp, IUnknown* lp) +{ + if (lp != NULL) + lp->AddRef(); + if (*pp) + (*pp)->Release(); + *pp = lp; + return lp; +} + +inline IUnknown* AtlComQIPtrAssign(IUnknown** pp, IUnknown* lp, REFIID riid) +{ + IUnknown* pTemp = *pp; + *pp = NULL; + if (lp != NULL) + lp->QueryInterface(riid, (void**)pp); + if (pTemp) + pTemp->Release(); + return *pp; +} + + +class CComMultiThreadModelNoCS +{ +public: + static ULONG WINAPI Increment(LONG *p) {return InterlockedIncrement(p);} + static ULONG WINAPI Decrement(LONG *p) {return InterlockedDecrement(p);} +}; + +//Base is the user's class that derives from CComObjectRoot and whatever +//interfaces the user wants to support on the object +template +class CComObject : public Base +{ +public: + typedef Base _BaseClass; + + // Set refcount to -(LONG_MAX/2) to protect destruction and + // also catch mismatched Release in debug builds + ~CComObject() + { + this->m_dwRef = -(LONG_MAX/2); + } + //If InternalAddRef or InternalRelease is undefined then your class + //doesn't derive from CComObjectRoot + STDMETHOD_(ULONG, AddRef)() {return this->InternalAddRef();} + STDMETHOD_(ULONG, Release)() + { + ULONG l = this->InternalRelease(); + if (l == 0) + delete this; + return l; + } + + static HRESULT WINAPI CreateInstance(CComObject** pp); +}; + +template +HRESULT WINAPI CComObject::CreateInstance(CComObject** pp) +{ + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + *pp = NULL; + + HRESULT hRes = E_OUTOFMEMORY; + CComObject* p = NULL; + p = new CComObject(); + if (p != NULL) + { + hRes = NOERROR; + } + *pp = p; + return hRes; +} + + +// the functions in this class don't need to be virtual because +// they are called from CComObject +class CComObjectRootBase +{ +public: + CComObjectRootBase() + { + m_dwRef = 0L; + } +public: + LONG m_dwRef; +}; // CComObjectRootBase + +template +class CComObjectRootEx : public CComObjectRootBase +{ +public: + typedef ThreadModel _ThreadModel; + + ULONG InternalAddRef() + { + ATLASSERT(m_dwRef != -1L); + return _ThreadModel::Increment(&m_dwRef); + } + ULONG InternalRelease() + { +#ifdef _DEBUG + LONG nRef = _ThreadModel::Decrement(&m_dwRef); + if (nRef < -(LONG_MAX / 2)) + { + ATLASSERT(0); + } + return nRef; +#else + return _ThreadModel::Decrement(&m_dwRef); +#endif + } +}; // CComObjectRootEx + +typedef CComMultiThreadModelNoCS CComObjectThreadModel; + +typedef CComObjectRootEx CComObjectRoot; + +// dummy definitions for the ATL COM goo +#define DECLARE_NO_REGISTRY() + +#define BEGIN_OBJECT_MAP(x) static const int x = 0; +#define OBJECT_ENTRY(clsid, class) +#define END_OBJECT_MAP() + +template +class CComCoClass { +}; + +class CComModule { +public: + HINSTANCE m_hInst; + HINSTANCE m_hInstResource; + + HRESULT Init(int objmap, HINSTANCE h) + { + m_hInst = h; + return S_OK; + } + + void Term() + { + m_hInst = NULL; + m_hInstResource = NULL; + } + + HINSTANCE GetModuleInstance() + { + return m_hInst; + } + + HINSTANCE GetResourceInstance() + { + return m_hInstResource; + } +}; + +template +class CAtlArray +{ +private: + E * m_pData; // Elements of the array. + size_t m_nSize; // Number of valid elements in the array. + size_t m_nMaxSize; // Total number of elements m_pData buffer can hold. + + // Call the constructors for the nElements elements starting from pBeggingElement + void CallConstructors( E* pBeginningElement, size_t nElements ) + { + for( size_t iElement = 0; iElement < nElements; iElement++ ) + { + ::new( this->pElements+iElement ) E; + } + } + + // Call the destructor for the nElements elements starting from pBeggingElement + void CallDestructors( E* pBeginningElement, size_t nElements ) + { + ATLASSERT(nElements == 0 || + pBeginningElement + (nElements-1) < m_pData + m_nSize // Should not go beyond the valid element range. + ); + + for( size_t iElement = 0; iElement < nElements; iElement++ ) + { + pBeginningElement[iElement].~E(); +#ifdef DEBUG + // Put some garbage there. + // It would be 0xcccccccc if the element is a pointer. For easy debugging. + memset(&pBeginningElement[iElement], 0xcc, sizeof(E)); +#endif + } + } + + +public: + CAtlArray() : m_pData(NULL), m_nSize(0), m_nMaxSize(0) {} + ~CAtlArray() { RemoveAll(); } + + size_t GetCount() const + { + return m_nSize; + } + + bool IsEmpty() + { + return m_nSize == 0; + } + + void RemoveAll() + { + if (m_pData) + { + CallDestructors( m_pData, m_nSize ); + free( m_pData ); + m_pData = NULL; + m_nSize = 0; + m_nMaxSize = 0; + } + + ATLASSERT(m_pData == NULL); + ATLASSERT(m_nSize == 0); + ATLASSERT(m_nMaxSize == 0); + } + + E& GetAt( size_t iElement ) + { + ATLASSERT(iElement < m_nSize); + if (iElement >= m_nSize) + AtlThrow(E_INVALIDARG); + return (m_pData[iElement]); + } + + E& operator[]( size_t iElement ) + { + return GetAt(iElement); + } + + E* GetData() + { + return (m_pData); + } + + void SetCount( size_t nNewSize ) + { + if ( nNewSize == 0 ) + { + RemoveAll(); + } + else + if ( nNewSize <= m_nSize ) + { + CallDestructors( m_pData+nNewSize, m_nSize-nNewSize ); + m_nSize = nNewSize; + } + else + if ( nNewSize > m_nSize ) + { + bool bSuccess = GrowBuffer( nNewSize ); + if( !bSuccess ) + { + AtlThrow( E_OUTOFMEMORY ); + } + + CallDestructors( m_pData+m_nSize, nNewSize-m_nSize ); + m_nSize = nNewSize; + } + } + + bool GrowBuffer( size_t nNewMaxSize ) + { + if( nNewMaxSize > m_nMaxSize ) + { + E* pNewData = static_cast< E* >( malloc( nNewMaxSize*sizeof( E ) ) ); + if( pNewData == NULL ) + { + return false; + } + + // Ok, allocation succeeded. + + if (m_pData == NULL) + { + // First time allocation. Simply return the newly allocated buffer. + goto DoneNewBuffer; + + } + + // copy new data from old + memmove( pNewData, m_pData, m_nSize*sizeof( E )); + + // get rid of old stuff + // (note: no need to call the destructors, because the elements are still alive + // in the new array.) + free( m_pData ); + +DoneNewBuffer: + m_pData = pNewData; + m_nMaxSize = nNewMaxSize; + } + + return true; + } + + size_t Add( E element ) + { + size_t iElement = m_nSize; + + if( iElement >= m_nMaxSize ) + { + size_t nNewMaxSize = m_nMaxSize * 2; + nNewMaxSize = (nNewMaxSize >= 16)?nNewMaxSize:16; // Let's allocate at least 16 elements. + if (nNewMaxSize < m_nMaxSize) + AtlThrow( E_OUTOFMEMORY ); // Integer overflow + + if (iElement >= nNewMaxSize) + { + nNewMaxSize = iElement + 1; + if (nNewMaxSize m_nSize ) + AtlThrow(E_INVALIDARG); + + // just remove a range + size_t nMoveCount = m_nSize-(iElement+nElements); + CallDestructors( m_pData+iElement, nElements ); + if( nMoveCount > 0 ) + { + memmove_s( m_pData+iElement, + nMoveCount * sizeof( E ), + m_pData+(iElement+nElements), + nMoveCount * sizeof( E ) + ); + } + m_nSize -= nElements; + } + +}; // CAtlArray + +#endif // __ATL_H__ diff --git a/lib/coreclr/src/pal/inc/rt/atlcom.h b/lib/coreclr/src/pal/inc/rt/atlcom.h new file mode 100644 index 0000000000..f7d96a177c --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/atlcom.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: atlcom.h +// +// =========================================================================== +// dummy atlcom.h for PAL + +#include "atl.h" diff --git a/lib/coreclr/src/pal/inc/rt/atlwin.h b/lib/coreclr/src/pal/inc/rt/atlwin.h new file mode 100644 index 0000000000..0d63430b46 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/atlwin.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: atlwin.h +// +// =========================================================================== +// dummy atlwin.h for PAL + +#include "atlwin.h" diff --git a/lib/coreclr/src/pal/inc/rt/commctrl.h b/lib/coreclr/src/pal/inc/rt/commctrl.h new file mode 100644 index 0000000000..f7065dc25e --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/commctrl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: commctrl.h +// +// =========================================================================== +// dummy commctrl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/commdlg.h b/lib/coreclr/src/pal/inc/rt/commdlg.h new file mode 100644 index 0000000000..0ef590d2a5 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/commdlg.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: commdlg.h +// +// =========================================================================== +// dummy commdlg.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/conio.h b/lib/coreclr/src/pal/inc/rt/conio.h new file mode 100644 index 0000000000..955a9298b8 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/conio.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: conio.h +// +// =========================================================================== +// dummy conio.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/cstdlib b/lib/coreclr/src/pal/inc/rt/cpp/cstdlib new file mode 100644 index 0000000000..74d998901a --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/cstdlib @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clrosdev +// +// =========================================================================== +// File: cstdlib +// +// =========================================================================== +// dummy cstdlib for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/ctype.h b/lib/coreclr/src/pal/inc/rt/cpp/ctype.h new file mode 100644 index 0000000000..2cd945662a --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/ctype.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: ctype.h +// +// =========================================================================== +// dummy ctype.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/fcntl.h b/lib/coreclr/src/pal/inc/rt/cpp/fcntl.h new file mode 100644 index 0000000000..4acf456686 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/fcntl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: fcntl.h +// +// =========================================================================== +// dummy fcntl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/float.h b/lib/coreclr/src/pal/inc/rt/cpp/float.h new file mode 100644 index 0000000000..87705eef73 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/float.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: float.h +// +// =========================================================================== +// dummy float.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/io.h b/lib/coreclr/src/pal/inc/rt/cpp/io.h new file mode 100644 index 0000000000..d742d1c190 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/io.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: io.h +// +// =========================================================================== +// dummy io.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/limits.h b/lib/coreclr/src/pal/inc/rt/cpp/limits.h new file mode 100644 index 0000000000..21b6d47fd8 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/limits.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: limits.h +// +// =========================================================================== +// dummy limits.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/malloc.h b/lib/coreclr/src/pal/inc/rt/cpp/malloc.h new file mode 100644 index 0000000000..a9ecc1af93 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/malloc.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: malloc.h +// +// =========================================================================== +// dummy malloc.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/math.h b/lib/coreclr/src/pal/inc/rt/cpp/math.h new file mode 100644 index 0000000000..07dbfa3b50 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/math.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: math.h +// +// =========================================================================== +// dummy math.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/memory.h b/lib/coreclr/src/pal/inc/rt/cpp/memory.h new file mode 100644 index 0000000000..8257d710c3 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/memory.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: memory.h +// +// =========================================================================== +// dummy memory.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/stdarg.h b/lib/coreclr/src/pal/inc/rt/cpp/stdarg.h new file mode 100644 index 0000000000..22517d04a8 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/stdarg.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: stdarg.h +// +// =========================================================================== +// dummy stdarg.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/stddef.h b/lib/coreclr/src/pal/inc/rt/cpp/stddef.h new file mode 100644 index 0000000000..1725893869 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/stddef.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: stddef.h +// +// =========================================================================== +// dummy stddef.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/stdint.h b/lib/coreclr/src/pal/inc/rt/cpp/stdint.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/stdint.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/stdio.h b/lib/coreclr/src/pal/inc/rt/cpp/stdio.h new file mode 100644 index 0000000000..35ed76156c --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/stdio.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: stdio.h +// +// =========================================================================== +// dummy stdio.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/stdlib.h b/lib/coreclr/src/pal/inc/rt/cpp/stdlib.h new file mode 100644 index 0000000000..68e0a40ab4 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/stdlib.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: stdlib.h +// +// =========================================================================== +// dummy stdlib.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/string.h b/lib/coreclr/src/pal/inc/rt/cpp/string.h new file mode 100644 index 0000000000..804513265f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/string.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: string.h +// +// =========================================================================== +// dummy string.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/time.h b/lib/coreclr/src/pal/inc/rt/cpp/time.h new file mode 100644 index 0000000000..d6f487ed64 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/time.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: time.h +// +// =========================================================================== +// dummy time.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/cpp/wchar.h b/lib/coreclr/src/pal/inc/rt/cpp/wchar.h new file mode 100644 index 0000000000..af00ca0133 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/cpp/wchar.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: wchar.h +// +// =========================================================================== +// dummy wchar.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/crtdbg.h b/lib/coreclr/src/pal/inc/rt/crtdbg.h new file mode 100644 index 0000000000..e94bb3260c --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/crtdbg.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: crtdbg.h +// +// =========================================================================== +// dummy crtdbg.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/dbghelp.h b/lib/coreclr/src/pal/inc/rt/dbghelp.h new file mode 100644 index 0000000000..7d9cd334e9 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/dbghelp.h @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ BUILD Version: 0000 Increment this if a change has global effects + + + +Module Name: + + dbghelp.h + +Abstract: + + This module defines the prototypes and constants required for the image + help routines. + + Contains debugging support routines that are redistributable. + +Revision History: + +--*/ + +#ifndef _DBGHELP_ +#define _DBGHELP_ + +#if _MSC_VER > 1020 +#pragma once +#endif + +// +// options that are set/returned by SymSetOptions() & SymGetOptions() +// these are used as a mask +// +#define SYMOPT_LOAD_LINES 0x00000010 + +#endif // _DBGHELP_ diff --git a/lib/coreclr/src/pal/inc/rt/eh.h b/lib/coreclr/src/pal/inc/rt/eh.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/eh.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/errorrep.h b/lib/coreclr/src/pal/inc/rt/errorrep.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/errorrep.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/guiddef.h b/lib/coreclr/src/pal/inc/rt/guiddef.h new file mode 100644 index 0000000000..392df60075 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/guiddef.h @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: guiddef.h +// +// =========================================================================== +// simplified guiddef.h for PAL + +#include "palrt.h" + +#ifdef DEFINE_GUID +#undef DEFINE_GUID +#endif + +#ifdef INITGUID +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + EXTERN_C DLLEXPORT const GUID DECLSPEC_SELECTANY name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + EXTERN_C const GUID FAR name +#endif // INITGUID diff --git a/lib/coreclr/src/pal/inc/rt/hstring.h b/lib/coreclr/src/pal/inc/rt/hstring.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/hstring.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/htmlhelp.h b/lib/coreclr/src/pal/inc/rt/htmlhelp.h new file mode 100644 index 0000000000..6ae044a897 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/htmlhelp.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: htmlhelp.h +// +// =========================================================================== +// dummy htmlhelp.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/imagehlp.h b/lib/coreclr/src/pal/inc/rt/imagehlp.h new file mode 100644 index 0000000000..07824e49aa --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/imagehlp.h @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + +Module Name: + + imagehlp.h + +Abstract: + + This module defines the prototypes and constants required for the image + help routines. + + + + +--*/ + +#ifndef _IMAGEHLP_ +#define _IMAGEHLP_ + +#if _MSC_VER > 1020 +#pragma once +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define IMAGEAPI __stdcall + +PIMAGE_NT_HEADERS +IMAGEAPI +CheckSumMappedFile ( + PVOID BaseAddress, + DWORD FileLength, + PDWORD HeaderSum, + PDWORD CheckSum + ); + +PIMAGE_NT_HEADERS +IMAGEAPI +ImageNtHeader ( + IN PVOID Base + ); + +PVOID +IMAGEAPI +ImageRvaToVa( + IN PIMAGE_NT_HEADERS NtHeaders, + IN PVOID Base, + IN ULONG Rva, + IN OUT PIMAGE_SECTION_HEADER *LastRvaSection + ); + +#ifdef __cplusplus +} +#endif + +#endif // _IMAGEHLP_ diff --git a/lib/coreclr/src/pal/inc/rt/intrin.h b/lib/coreclr/src/pal/inc/rt/intrin.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/intrin.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/intsafe.h b/lib/coreclr/src/pal/inc/rt/intsafe.h new file mode 100644 index 0000000000..6e28175e22 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/intsafe.h @@ -0,0 +1,1409 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/****************************************************************** +* * +* intsafe.h -- This module defines helper functions to prevent * +* integer overflow issues. * +* * +* * +******************************************************************/ +#ifndef _INTSAFE_H_INCLUDED_ +#define _INTSAFE_H_INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include // for IN, etc. + +#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW + +#ifndef LOWORD +#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) +#endif + +#ifndef HIWORD +#define HIWORD(l) ((WORD)(((DWORD_PTR)(l)) >> 16)) +#endif + +#define HIDWORD(_qw) ((ULONG)((_qw) >> 32)) +#define LODWORD(_qw) ((ULONG)(_qw)) + +#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \ + || defined(_M_AMD64) || defined(__ARM_ARCH) + +#ifndef UInt32x32To64 +#define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b))) +#endif + +#elif defined(_M_IX86) + +#ifndef UInt32x32To64 +#define UInt32x32To64(a, b) (unsigned __int64)((unsigned __int64)(ULONG)(a) * (ULONG)(b)) +#endif + +#else + +#error Must define a target architecture. + +#endif + +#define INT_MAX 2147483647 +#define LONG_MAX 2147483647L +#define USHRT_MAX 0xffff +#define UINT_MAX 0xffffffff +#define ULONG_MAX 0xffffffffUL +#define DWORD_MAX 0xffffffffUL + +// +// It is common for -1 to be used as an error value for various types +// +#define USHORT_ERROR (0xffff) +#define INT_ERROR (-1) +#define LONG_ERROR (-1L) +#define UINT_ERROR (0xffffffff) +#define ULONG_ERROR (0xffffffffUL) +#ifdef _MSC_VER +#define ULONGLONG_ERROR (0xffffffffffffffffui64) +#define HIDWORD_MASK (0xffffffff00000000ui64) +#else // _MSC_VER +#define ULONGLONG_ERROR (0xffffffffffffffffULL) +#define HIDWORD_MASK (0xffffffff00000000ULL) +#endif // _MSC_VER +#ifdef _WIN64 +#define SIZET_ERROR ULONGLONG_ERROR +#else +#define SIZET_ERROR ULONG_ERROR +#endif + +// +// We make some assumptions about the sizes of various types. Let's be +// explicit about those assumptions and check them. +// +C_ASSERT(sizeof(unsigned short) == 2); +C_ASSERT(sizeof(unsigned int) == 4); +C_ASSERT(sizeof(ULONG) == 4); + +// +// INT -> signed char conversion +// +__inline +HRESULT +IntToSignedChar( + IN INT iOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((iOperand >= -128) && (iOperand <= 127)) + { + *pch = (signed char)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> UCHAR conversion +// +__inline +HRESULT +IntToUChar( + IN INT iOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((iOperand >= 0) && (iOperand <= 255)) + { + *pch = (UCHAR)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// LONG -> UCHAR conversion +// +__inline +HRESULT +LongToUChar( + IN LONG lOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((lOperand >= 0) && (lOperand <= 255)) + { + *pch = (UCHAR)lOperand; + hr = S_OK; + } + + return hr; +} + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// INT -> CHAR conversion +// +__forceinline +HRESULT +IntToChar( + IN INT iOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return IntToUChar(iOperand, (UCHAR*)pch); +#else + return IntToSignedChar(iOperand, (signed char*)pch); +#endif +} + +// +// INT -> USHORT conversion +// +__inline +HRESULT +IntToUShort( + IN INT iOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if ((iOperand >= 0) && (iOperand <= USHRT_MAX)) + { + *pusResult = (USHORT)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> UINT conversion +// +__inline +HRESULT +IntToUInt( + IN INT iOperand, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (iOperand >= 0) + { + *puResult = (UINT)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> ULONG conversion +// +__inline +HRESULT +IntToULong( + IN INT iOperand, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (iOperand >= 0) + { + *pulResult = (ULONG)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> ULONGLONG conversion +// +__inline +HRESULT +IntToULongLong( + IN INT iOperand, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONG_ERROR; + + if (iOperand >= 0) + { + *pullResult = (ULONGLONG)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> signed char conversion +// +__inline +HRESULT +UIntToSignedChar( + IN UINT uOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (uOperand <= 127) + { + *pch = (signed char)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> UCHAR conversion +// +__inline +HRESULT +UIntToUChar( + IN UINT uOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (uOperand <= 255) + { + *pch = (UCHAR)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> BYTE conversion +// +#define UIntToByte UIntToUChar + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// UINT -> CHAR conversion +// +__forceinline +HRESULT +UIntToChar( + IN UINT uOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return UIntToUChar(uOperand, (UCHAR*)pch); +#else + return UIntToSignedChar(uOperand, (signed char*)pch); +#endif // _CHAR_UNSIGNED +} + +// +// UINT -> INT conversion +// +__inline +HRESULT +UIntToInt( + IN UINT uOperand, + OUT INT* piResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *piResult = INT_ERROR; + + if (uOperand <= INT_MAX) + { + *piResult = (INT)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> LONG conversion +// +__inline +HRESULT +UIntToLong( + IN UINT Operand, + OUT LONG* Result) +{ + if (Operand <= LONG_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// UINT -> ULONG conversion +// +__inline +HRESULT +UIntToULong( + IN UINT uOperand, + OUT ULONG* pulResult) +{ + *pulResult = (ULONG)uOperand; + + return S_OK; +} + +// +// ULONG -> UCHAR conversion +// +__inline +HRESULT +ULongToSignedChar( + IN ULONG ulOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (ulOperand <= 127) + { + *pch = (signed char)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONG -> UCHAR conversion +// +__inline +HRESULT +ULongToUChar( + IN ULONG ulOperand, + OUT unsigned char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (ulOperand <= 255) + { + *pch = (unsigned char)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// ULONG -> CHAR conversion +// +__forceinline +HRESULT +ULongToChar( + IN ULONG ulOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return ULongToUChar(ulOperand, (unsigned char*)pch); +#else + return ULongToSignedChar(ulOperand, (signed char*)pch); +#endif // _CHAR_UNSIGNED +} + +// +// ULONG -> USHORT conversion +// +__inline +HRESULT +ULongToUShort( + IN ULONG ulOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (ulOperand <= USHRT_MAX) + { + *pusResult = (USHORT)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONG -> INT conversion +// +__inline +HRESULT +ULongToInt( + IN ULONG ulOperand, + OUT INT* piResult) +{ + if (ulOperand <= INT_MAX) + { + *piResult = (INT)ulOperand; + return S_OK; + } + else + { + *piResult = INT_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONG -> UINT conversion +// +__inline +HRESULT +ULongToUInt( + IN ULONG ulOperand, + OUT UINT* puResult) +{ + *puResult = (UINT)ulOperand; + + return S_OK; +} + +// +// ULONG -> LONG conversion +// +__inline +HRESULT +ULongToLong( + IN ULONG Operand, + OUT LONG* Result) +{ + if (Operand <= LONG_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONGLONG -> INT conversion +// +__inline +HRESULT +ULongLongToInt( + IN ULONGLONG ullOperand, + OUT INT* piResult) +{ + if (ullOperand <= INT_MAX) + { + *piResult = (INT)ullOperand; + return S_OK; + } + else + { + *piResult = INT_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONGLONG -> LONG conversion +// +__inline +HRESULT +ULongLongToLong( + IN ULONGLONG Operand, + OUT LONG* Result) +{ + if (Operand <= LONG_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// UINT -> USHORT conversion +// +__inline +HRESULT +UIntToUShort( + IN UINT uOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (uOperand <= USHRT_MAX) + { + *pusResult = (USHORT)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONGLONG -> USHORT conversion +// +__inline +HRESULT +ULongLongToUShort( + IN ULONGLONG ullOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + USHORT usResult = USHORT_ERROR; + + if (ullOperand <= USHRT_MAX) + { + usResult = (USHORT)ullOperand; + hr = S_OK; + } + *pusResult = usResult; + + return hr; +} + +// +// ULONGLONG -> ULONG conversion +// +__inline +HRESULT +ULongLongToULong( + IN ULONGLONG ullOperand, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (ullOperand <= ULONG_MAX) + { + *pulResult = (ULONG)ullOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR -> ULONG conversion +// ULONG_PTR -> ULONG conversion +// +#ifdef _WIN64 + +#define UIntPtrToULong ULongLongToULong +#define ULongPtrToULong ULongLongToULong + +#else + +__inline +HRESULT +UIntPtrToULong( + IN UINT_PTR Operand, + OUT ULONG* pResult) +{ + *pResult = (ULONG)Operand; + return S_OK; +} + +__inline +HRESULT +ULongPtrToULong( + IN ULONG_PTR Operand, + OUT ULONG* pResult) +{ + *pResult = (ULONG)Operand; + return S_OK; +} + +#endif + +// +// ULONGLONG -> UINT conversion +// +__inline +HRESULT +ULongLongToUInt( + IN ULONGLONG ullOperand, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (ullOperand <= UINT_MAX) + { + *puResult = (UINT)ullOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR -> UINT conversion +// ULONG_PTR -> UINT conversion +// +#ifdef _WIN64 + +#define UIntPtrToUInt ULongLongToUInt +#define ULongPtrToUInt ULongLongToUInt + +#else + +__inline +HRESULT +UIntPtrToUInt( + IN UINT_PTR Operand, + OUT UINT* pResult) +{ + *pResult = (UINT)Operand; + return S_OK; +} + +__inline +HRESULT +ULongPtrToUInt( + IN ULONG_PTR Operand, + OUT UINT* pResult) +{ + *pResult = (UINT)Operand; + return S_OK; +} + +#endif + +// +// * -> BYTE conversion (BYTE is always unsigned char) +// +#define IntToByte IntToUChar +#define UIntToByte UIntToUChar +#define LongToByte LongToUChar +#define ULongToByte ULongToUChar + +// +// * -> WORD conversion (WORD is always unsigned short) +// +#define IntToWord IntToUShort +#define LongToWord LongToUShort +#define LongLongToWord LongLongToUShort +#define UIntToWord UIntToUShort +#define ULongToWord ULongToUShort +#define ULongLongToWord ULongLongToUShort +#define UIntPtrToWord UIntPtrToUShort +#define ULongPtrToWord ULongPtrToUShort +#define SizeTToWord SizeTToUShort +#define SIZETToWord SIZETToUShort + +// +// WORD -> * conversion (WORD is always unsigned short) +// +#define WordToUChar UShortToUChar +#define WordToByte UShortToByte +#define WordToChar UShortToChar +#define WordToSignedChar UShortToSignedChar +#define WordToInt UShortToInt +#define WordToLong UShortToLong +#define WordToLongLong UShortToLongLong +#define WordToIntPtr UShortToIntPtr +#define WordToLongPtr UShortToLongPtr + +// +// * -> DWORD conversion (DWORD is always ULONG) +// +#define CharToDWord CharToULong +#define SignedCharToDWord SignedCharToULong +#define ShortToDWord ShortToULong +#define IntToDWord IntToULong +#define LongToDWord LongToULong +#define LongLongToDWord LongLongToULong +#define UIntToDWord UIntToULong +#define ULongLongToDWord ULongLongToULong +#define IntPtrToDWord IntPtrToULong +#define LongPtrToDWord LongPtrToULong +#define UIntPtrToDWord UIntPtrToULong +#define ULongPtrToDWord ULongPtrToULong +#define SizeTToDWord SizeTToULong +#define SIZETToDWord SIZETToULong + +// +// DWORD -> * conversion (DWORD is always ULONG) +// +#define DWordToChar ULongToChar +#define DWordToUChar ULongToUChar +#define DWordToByte ULongToByte +#define DWordToSignedChar ULongToSignedChar +#define DWordToUShort ULongToUShort +#define DWordToUInt ULongToUInt +#define DWordToInt ULongToInt +#define DWordToLong ULongToLong +#define DWordToLongLong ULongToLongLong +#define DWordToIntPtr ULongToIntPtr +#define DWordToLongPtr ULongToLongPtr + + +// +// * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) +// +#ifdef _WIN64 +#define CharToUIntPtr CharToULongLong +#define SignedCharToUIntPtr SignedCharToULongLong +#define ShortToUIntPtr ShortToULongLong +#define IntToUIntPtr IntToULongLong +#define LongToUIntPtr LongToULongLong +#define LongLongToUIntPtr LongLongToULongLong +#define IntPtrToUIntPtr IntPtrToULongLong +#define LongPtrToUIntPtr LongPtrToULongLong +#else +#define CharToUIntPtr CharToUInt +#define SignedCharToUIntPtr SignedCharToUInt +#define ShortToUIntPtr ShortToUInt + +__inline +HRESULT +IntToUIntPtr( + IN INT iOperand, + OUT UINT_PTR* puResult) +{ + return IntToUInt(iOperand, (UINT*)puResult); +} + +#define LongToUIntPtr LongToUInt +#define LongLongToUIntPtr LongLongToUInt + +#define IntPtrToUIntPtr IntPtrToUInt +#define LongPtrToUIntPtr LongPtrToUInt +#endif + +__inline +HRESULT +ULongLongToUIntPtr( + IN ULONGLONG ullOperand, + OUT UINT_PTR* puResult) +{ +#ifdef _WIN64 + *puResult = ullOperand; + return S_OK; +#else + return ULongLongToUInt(ullOperand, (UINT*)puResult); +#endif +} + + +// +// UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) +// +#ifdef _WIN64 +#define UIntPtrToUShort ULongLongToUShort +#define UIntPtrToInt ULongLongToInt +#define UIntPtrToLong ULongLongToLong +#define UIntPtrToLongLong ULongLongToLongLong +#define UIntPtrToIntPtr ULongLongToIntPtr +#define UIntPtrToLongPtr ULongLongToLongPtr +#else + +__inline +HRESULT +UIntPtrToUShort( + IN UINT_PTR uOperand, + OUT USHORT* pusResult) +{ + return UIntToUShort((UINT)uOperand, pusResult); +} + +__inline +HRESULT +UIntPtrToInt( + IN UINT_PTR uOperand, + OUT INT* piResult) +{ + return UIntToInt((UINT)uOperand, piResult); +} + +__inline +HRESULT +UIntPtrToLong( + IN UINT_PTR Operand, + OUT LONG* Result) +{ + return UIntToLong((UINT)Operand, Result); +} + +#define UIntPtrToLongLong UIntToLongLong +#define UIntPtrToIntPtr UIntToIntPtr +#define UIntPtrToLongPtr UIntToLongPtr +#endif + + +// +// * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) +// +#ifdef _WIN64 +#define CharToULongPtr CharToULongLong +#define SignedCharToULongPtr SignedCharToULongLong +#define ShortToULongPtr ShortToULongLong +#define IntToULongPtr IntToULongLong +#define LongToULongPtr LongToULongLong +#define LongLongToULongPtr LongLongToULongLong +#define IntPtrToULongPtr IntPtrToULongLong +#define LongPtrToULongPtr LongPtrToULongLong +#else +#define CharToULongPtr CharToULong +#define SignedCharToULongPtr SignedCharToULong +#define ShortToULongPtr ShortToULong + +__inline +HRESULT +IntToULongPtr( + IN INT iOperand, + OUT ULONG_PTR* pulResult) +{ + return IntToULong(iOperand, (ULONG*)pulResult); +} + +#define LongToULongPtr LongToULong +#define LongLongToULongPtr LongLongToULong + +#define IntPtrToULongPtr IntPtrToULong +#define LongPtrToULongPtr LongPtrToULong +#endif + +__inline +HRESULT +ULongLongToULongPtr( + IN ULONGLONG ullOperand, + OUT ULONG_PTR* pulResult) +{ +#ifdef _WIN64 + *pulResult = ullOperand; + return S_OK; +#else + return ULongLongToULong(ullOperand, (ULONG*)pulResult); +#endif +} + + +// +// ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) +// +#ifdef _WIN64 +#define ULongPtrToUShort ULongLongToUShort +#define ULongPtrToInt ULongLongToInt +#define ULongPtrToLong ULongLongToLong +#define ULongPtrToLongLong ULongLongToLongLong +#define ULongPtrToIntPtr ULongLongToIntPtr +#define ULongPtrToLongPtr ULongLongToLongPtr +#else + +__inline +HRESULT +ULongPtrToUShort( + IN ULONG_PTR ulOperand, + OUT USHORT* pusResult) +{ + return ULongToUShort((ULONG)ulOperand, pusResult); +} + +__inline +HRESULT +ULongPtrToInt( + IN ULONG_PTR ulOperand, + OUT INT* piResult) +{ + return ULongToInt((ULONG)ulOperand, piResult); +} + +__inline +HRESULT +ULongPtrToLong( + IN ULONG_PTR Operand, + OUT LONG* Result) +{ + return ULongToLong((ULONG)Operand, Result); +} + +#define ULongPtrToLongLong ULongToLongLong +#define ULongPtrToIntPtr ULongToIntPtr +#define ULongPtrToLongPtr ULongToLongPtr +#endif + +// +// * -> size_t conversion (size_t is always UINT_PTR) +// +#define CharToSizeT CharToUIntPtr +#define SignedCharToSizeT SignedCharToUIntPtr +#define ShortToSizeT ShortToUIntPtr +#define IntToSizeT IntToUIntPtr +#define LongToSizeT LongToUIntPtr +#define LongLongToSizeT LongLongToUIntPtr +#define ULongLongToSizeT ULongLongToUIntPtr +#define IntPtrToSizeT IntPtrToUIntPtr +#define LongPtrToSizeT LongPtrToUIntPtr + +// +// size_t -> * conversion (size_t is always UINT_PTR) +// +#define SizeTToUShort UIntPtrToUShort +#define SizeTToUInt UIntPtrToUInt +#define SizeTToULong UIntPtrToULong +#define SizeTToInt UIntPtrToInt +#define SizeTToLong UIntPtrToLong +#define SizeTToLongLong UIntPtrToLongLong +#define SizeTToIntPtr UIntPtrToIntPtr +#define SizeTToLongPtr UIntPtrToLongPtr + +// +// * -> SIZE_T conversion (SIZE_T is always ULONG_PTR) +// +#define CharToSIZET CharToULongPtr +#define SignedCharToSIZET SignedCharToULongPtr +#define ShortToSIZET ShortToULongPtr +#define IntToSIZET IntToULongPtr +#define LongToSIZET LongToULongPtr +#define LongLongToSIZET LongLongToULongPtr +#define IntPtrToSIZET IntPtrToULongPtr +#define LongPtrToSIZET LongPtrToULongPtr +#define ULongLongToSIZET ULongLongToULongPtr + +// +// SIZE_T -> * conversion (SIZE_T is always ULONG_PTR) +// +#define SIZETToUShort ULongPtrToUShort +#define SIZETToUInt ULongPtrToUInt +#define SIZETToULong ULongPtrToULong +#define SIZETToUIntPtr ULongPtrToUIntPtr +#define SIZETToULongPtr ULongPtrToULongPtr +#define SIZETToInt ULongPtrToInt +#define SIZETToLong ULongPtrToLong +#define SIZETToLongLong ULongPtrToLongLong +#define SIZETToIntPtr ULongPtrToIntPtr +#define SIZETToLongPtr ULongPtrToLongPtr + +// +// * -> DWORD_PTR conversion (DWORD_PTR is always ULONG_PTR) +// +#define CharToDWordPtr CharToULongPtr +#define SignedCharToDWordPtr SignedCharToULongPtr +#define ShortToDWordPtr ShortToULongPtr +#define IntToDWordPtr IntToULongPtr +#define LongToDWordPtr LongToULongPtr +#define LongLongToDWordPtr LongLongToULongPtr +#define ULongLongToDWordPtr ULongLongToULongPtr +#define IntPtrToDWordPtr IntPtrToULongPtr +#define LongPtrToDWordPtr LongPtrToULongPtr + +// +// DWORD_PTR -> * conversion (DWORD_PTR is always ULONG_PTR) +// +#define DWordPtrToUShort ULongPtrToUShort +#define DWordPtrToUInt ULongPtrToUInt +#define DWordPtrToULong ULongPtrToULong +#define DWordPtrToDWord ULongPtrToDWord +#define DWordPtrToInt ULongPtrToInt +#define DWordPtrToLong ULongPtrToLong +#define DWordPtrToLongLong ULongPtrToLongLong +#define DWordPtrToIntPtr ULongPtrToIntPtr +#define DWordPtrToLongPtr ULongPtrToLongPtr + +// +// USHORT addition +// +__inline +HRESULT +UShortAdd( + IN USHORT usAugend, + IN USHORT usAddend, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (((USHORT)(usAugend + usAddend)) >= usAugend) + { + *pusResult = (usAugend + usAddend); + hr = S_OK; + } + + return hr; +} + +// +// WORD addtition +// +#define WordAdd UShortAdd + +// +// UINT addition +// +__inline +HRESULT +UIntAdd( + IN UINT uAugend, + IN UINT uAddend, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if ((uAugend + uAddend) >= uAugend) + { + *puResult = (uAugend + uAddend); + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR addition +// +#define UIntPtrAdd SizeTAdd + +// +// ULONG addition +// +__inline +HRESULT +ULongAdd( + IN ULONG ulAugend, + IN ULONG ulAddend, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if ((ulAugend + ulAddend) >= ulAugend) + { + *pulResult = (ulAugend + ulAddend); + hr = S_OK; + } + + return hr; +} + +// +// ULONG_PTR addition +// +#ifdef _WIN64 +#define ULongPtrAdd ULongLongAdd +#else +__inline +HRESULT +ULongPtrAdd( + IN ULONG_PTR ulAugend, + IN ULONG_PTR ulAddend, + OUT ULONG_PTR* pulResult) +{ + return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult); +} +#endif // _WIN64 + +// +// DWORD addition +// +#define DWordAdd ULongAdd + +// +// DWORD_PTR addition +// +#define DWordPtrAdd ULongPtrAdd + +// +// size_t addition +// +__inline +HRESULT +SizeTAdd( + IN size_t Augend, + IN size_t Addend, + OUT size_t* pResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pResult = SIZET_ERROR; + + if ((Augend + Addend) >= Augend) + { + *pResult = (Augend + Addend); + hr = S_OK; + } + + return hr; +} + +// +// SIZE_T addition +// +#define SIZETAdd ULongPtrAdd + +// +// ULONGLONG addition +// +__inline +HRESULT +ULongLongAdd( + IN ULONGLONG ullAugend, + IN ULONGLONG ullAddend, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONGLONG_ERROR; + + if ((ullAugend + ullAddend) >= ullAugend) + { + *pullResult = (ullAugend + ullAddend); + hr = S_OK; + } + + return hr; +} + +// +// USHORT subtraction +// +__inline +HRESULT +UShortSub( + IN USHORT usMinuend, + IN USHORT usSubtrahend, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (usMinuend >= usSubtrahend) + { + *pusResult = (usMinuend - usSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// WORD subtraction +// +#define WordSub UShortSub + + +// +// UINT subtraction +// +__inline +HRESULT +UIntSub( + IN UINT uMinuend, + IN UINT uSubtrahend, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (uMinuend >= uSubtrahend) + { + *puResult = (uMinuend - uSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR subtraction +// +#define UIntPtrSub SizeTSub + +// +// ULONG subtraction +// +__inline +HRESULT +ULongSub( + IN ULONG ulMinuend, + IN ULONG ulSubtrahend, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (ulMinuend >= ulSubtrahend) + { + *pulResult = (ulMinuend - ulSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// ULONG_PTR subtraction +// +#ifdef _WIN64 +#define ULongPtrSub ULongLongSub +#else +__inline +HRESULT +ULongPtrSub( + IN ULONG_PTR ulMinuend, + IN ULONG_PTR ulSubtrahend, + OUT ULONG_PTR* pulResult) +{ + return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult); +} +#endif // _WIN64 + + +// +// DWORD subtraction +// +#define DWordSub ULongSub + +// +// DWORD_PTR subtraction +// +#define DWordPtrSub ULongPtrSub + +// +// size_t subtraction +// +__inline +HRESULT +SizeTSub( + IN size_t Minuend, + IN size_t Subtrahend, + OUT size_t* pResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pResult = SIZET_ERROR; + + if (Minuend >= Subtrahend) + { + *pResult = (Minuend - Subtrahend); + hr = S_OK; + } + + return hr; +} + +// +// SIZE_T subtraction +// +#define SIZETSub ULongPtrSub + +// +// ULONGLONG subtraction +// +__inline +HRESULT +ULongLongSub( + IN ULONGLONG ullMinuend, + IN ULONGLONG ullSubtrahend, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONGLONG_ERROR; + + if (ullMinuend >= ullSubtrahend) + { + *pullResult = (ullMinuend - ullSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// USHORT multiplication +// +__inline +HRESULT +UShortMult( + IN USHORT usMultiplicand, + IN USHORT usMultiplier, + OUT USHORT* pusResult) +{ + ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier; + + return ULongToUShort(ulResult, pusResult); +} + +// +// WORD multiplication +// +#define WordMult UShortMult + +// +// UINT multiplication +// +__inline +HRESULT +UIntMult( + IN UINT uMultiplicand, + IN UINT uMultiplier, + OUT UINT* puResult) +{ + ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier); + + return ULongLongToUInt(ull64Result, puResult); +} + +// +// ULONG multiplication +// +__inline +HRESULT +ULongMult( + IN ULONG ulMultiplicand, + IN ULONG ulMultiplier, + OUT ULONG* pulResult) +{ + ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier); + + return ULongLongToULong(ull64Result, pulResult); +} + +// +// DWORD multiplication +// +#define DWordMult ULongMult + +// +// DWORD_PTR multiplication +// +#define DWordPtrMult ULongPtrMult + +#endif // _INTSAFE_H_INCLUDED_ diff --git a/lib/coreclr/src/pal/inc/rt/mbstring.h b/lib/coreclr/src/pal/inc/rt/mbstring.h new file mode 100644 index 0000000000..bf9ceb66f4 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/mbstring.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: mbstring.h +// +// =========================================================================== +// dummy mbstring.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/new.h b/lib/coreclr/src/pal/inc/rt/new.h new file mode 100644 index 0000000000..b9932d7505 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/new.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: new.h +// +// =========================================================================== +// dummy new.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/no_sal2.h b/lib/coreclr/src/pal/inc/rt/no_sal2.h new file mode 100644 index 0000000000..d2a97a4138 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/no_sal2.h @@ -0,0 +1,534 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/*** +* no_sal2.h - renders the SAL annotations for documenting APIs harmless. +* + +* +*Purpose: +* sal.h provides a set of SAL2 annotations to describe how a function uses its +* parameters - the assumptions it makes about them, and the guarantees it makes +* upon finishing. This file redefines all those annotation macros to be harmless. +* It is designed for use in down-level build environments where the tooling may +* be unhappy with the standard SAL2 macro definitions. +* +* [Public] +* + +* +****/ + +#ifndef _NO_SAL_2_H_ +#define _NO_SAL_2_H_ + +#undef _When_ +#define _When_(c,a) +#undef _At_ +#define _At_(t,a) +#undef _At_buffer_ +#define _At_buffer_(t,i,c,a) +#undef _Group_ +#define _Group_(a) +#undef _Pre_ +#define _Pre_ +#undef _Post_ +#define _Post_ +#undef _Deref_ +#define _Deref_ +#undef _Null_ +#define _Null_ +#undef _Notnull_ +#define _Notnull_ +#undef _Maybenull_ +#define _Maybenull_ +#undef _Const_ +#define _Const_ +#undef _Check_return_ +#define _Check_return_ +#undef _Must_inspect_result_ +#define _Must_inspect_result_ +#undef _Pre_satisfies_ +#define _Pre_satisfies_(e) +#undef _Post_satisfies_ +#define _Post_satisfies_(e) +#undef _Writable_elements_ +#define _Writable_elements_(s) +#undef _Writable_bytes_ +#define _Writable_bytes_(s) +#undef _Readable_elements_ +#define _Readable_elements_(s) +#undef _Readable_bytes_ +#define _Readable_bytes_(s) +#undef _Null_terminated_ +#define _Null_terminated_ +#undef _NullNull_terminated_ +#define _NullNull_terminated_ +#undef _Valid_ +#define _Valid_ +#undef _Notvalid_ +#define _Notvalid_ +#undef _Success_ +#define _Success_(c) +#undef _Return_type_success_ +#define _Return_type_success_(c) +#undef _On_failure_ +#define _On_failure_(a) +#undef _Always_ +#define _Always_(a) +#undef _Use_decl_annotations_ +#define _Use_decl_annotations_ +#undef _Pre_defensive_ +#define _Pre_defensive_ +#undef _Post_defensive_ +#define _Post_defensive_ +#undef _Pre_unknown_ +#define _Pre_unknown_ +#undef _Acquires_lock_ +#define _Acquires_lock_(e) +#undef _Releases_lock_ +#define _Releases_lock_(e) +#undef _Requires_lock_held_ +#define _Requires_lock_held_(e) +#undef _Requires_lock_not_held_ +#define _Requires_lock_not_held_(e) +#undef _Requires_no_locks_held_ +#define _Requires_no_locks_held_ +#undef _Guarded_by_ +#define _Guarded_by_(e) +#undef _Write_guarded_by_ +#define _Write_guarded_by_(e) +#undef _Interlocked_ +#define _Interlocked_ +#undef _Post_same_lock_ +#define _Post_same_lock_(e1,e2) +#undef _Benign_race_begin_ +#define _Benign_race_begin_ +#undef _Benign_race_end_ +#define _Benign_race_end_ +#undef _No_competing_thread_ +#define _No_competing_thread_ +#undef _No_competing_thread_begin_ +#define _No_competing_thread_begin_ +#undef _No_competing_thread_end_ +#define _No_competing_thread_end_ +#undef _Acquires_shared_lock_ +#define _Acquires_shared_lock_(e) +#undef _Releases_shared_lock_ +#define _Releases_shared_lock_(e) +#undef _Requires_shared_lock_held_ +#define _Requires_shared_lock_held_(e) +#undef _Acquires_exclusive_lock_ +#define _Acquires_exclusive_lock_(e) +#undef _Releases_exclusive_lock_ +#define _Releases_exclusive_lock_(e) +#undef _Requires_exclusive_lock_held_ +#define _Requires_exclusive_lock_held_(e) +#undef _Has_lock_kind_ +#define _Has_lock_kind_(n) +#undef _Create_lock_level_ +#define _Create_lock_level_(n) +#undef _Has_lock_level_ +#define _Has_lock_level_(n) +#undef _Lock_level_order_ +#define _Lock_level_order_(n1,n2) +#undef _Analysis_assume_lock_acquired_ +#define _Analysis_assume_lock_acquired_(e) +#undef _Analysis_assume_lock_released_ +#define _Analysis_assume_lock_released_(e) +#undef _Analysis_assume_lock_held_ +#define _Analysis_assume_lock_held_(e) +#undef _Analysis_assume_lock_not_held_ +#define _Analysis_assume_lock_not_held_(e) +#undef _Analysis_assume_same_lock_ +#define _Analysis_assume_same_lock_(e) +#undef _In_ +#define _In_ +#undef _Out_ +#define _Out_ +#undef _Inout_ +#define _Inout_ +#undef _In_z_ +#define _In_z_ +#undef _Inout_z_ +#define _Inout_z_ +#undef _In_reads_ +#define _In_reads_(s) +#undef _In_reads_bytes_ +#define _In_reads_bytes_(s) +#undef _In_reads_z_ +#define _In_reads_z_(s) +#undef _In_reads_or_z_ +#define _In_reads_or_z_(s) +#undef _Out_writes_ +#define _Out_writes_(s) +#undef _Out_writes_bytes_ +#define _Out_writes_bytes_(s) +#undef _Out_writes_z_ +#define _Out_writes_z_(s) +#undef _Inout_updates_ +#define _Inout_updates_(s) +#undef _Inout_updates_bytes_ +#define _Inout_updates_bytes_(s) +#undef _Inout_updates_z_ +#define _Inout_updates_z_(s) +#undef _Out_writes_to_ +#define _Out_writes_to_(s,c) +#undef _Out_writes_bytes_to_ +#define _Out_writes_bytes_to_(s,c) +#undef _Out_writes_all_ +#define _Out_writes_all_(s) +#undef _Out_writes_bytes_all_ +#define _Out_writes_bytes_all_(s) +#undef _Inout_updates_to_ +#define _Inout_updates_to_(s,c) +#undef _Inout_updates_bytes_to_ +#define _Inout_updates_bytes_to_(s,c) +#undef _Inout_updates_all_ +#define _Inout_updates_all_(s) +#undef _Inout_updates_bytes_all_ +#define _Inout_updates_bytes_all_(s) +#undef _In_reads_to_ptr_ +#define _In_reads_to_ptr_(p) +#undef _In_reads_to_ptr_z_ +#define _In_reads_to_ptr_z_(p) +#undef _Out_writes_to_ptr_ +#define _Out_writes_to_ptr_(p) +#undef _Out_writes_to_ptr_z_ +#define _Out_writes_to_ptr_z_(p) +#undef _In_opt_ +#define _In_opt_ +#undef _Out_opt_ +#define _Out_opt_ +#undef _Inout_opt_ +#define _Inout_opt_ +#undef _In_opt_z_ +#define _In_opt_z_ +#undef _Inout_opt_z_ +#define _Inout_opt_z_ +#undef _In_reads_opt_ +#define _In_reads_opt_(s) +#undef _In_reads_bytes_opt_ +#define _In_reads_bytes_opt_(s) +#undef _Out_writes_opt_ +#define _Out_writes_opt_(s) +#undef _Out_writes_bytes_opt_ +#define _Out_writes_bytes_opt_(s) +#undef _Out_writes_opt_z_ +#define _Out_writes_opt_z_(s) +#undef _Inout_updates_opt_ +#define _Inout_updates_opt_(s) +#undef _Inout_updates_bytes_opt_ +#define _Inout_updates_bytes_opt_(s) +#undef _Inout_updates_opt_z_ +#define _Inout_updates_opt_z_(s) +#undef _Out_writes_to_opt_ +#define _Out_writes_to_opt_(s,c) +#undef _Out_writes_bytes_to_opt_ +#define _Out_writes_bytes_to_opt_(s,c) +#undef _Out_writes_all_opt_ +#define _Out_writes_all_opt_(s) +#undef _Out_writes_bytes_all_opt_ +#define _Out_writes_bytes_all_opt_(s) +#undef _Inout_updates_to_opt_ +#define _Inout_updates_to_opt_(s,c) +#undef _Inout_updates_bytes_to_opt_ +#define _Inout_updates_bytes_to_opt_(s,c) +#undef _Inout_updates_all_opt_ +#define _Inout_updates_all_opt_(s) +#undef _Inout_updates_bytes_all_opt_ +#define _Inout_updates_bytes_all_opt_(s) +#undef _In_reads_to_ptr_opt_ +#define _In_reads_to_ptr_opt_(p) +#undef _In_reads_to_ptr_opt_z_ +#define _In_reads_to_ptr_opt_z_(p) +#undef _Out_writes_to_ptr_opt_ +#define _Out_writes_to_ptr_opt_(p) +#undef _Out_writes_to_ptr_opt_z_ +#define _Out_writes_to_ptr_opt_z_(p) +#undef _Outptr_ +#define _Outptr_ +#undef _Outptr_opt_ +#define _Outptr_opt_ +#undef _Outptr_result_maybenull_ +#define _Outptr_result_maybenull_ +#undef _Outptr_opt_result_maybenull_ +#define _Outptr_opt_result_maybenull_ +#undef _Outptr_z_ +#define _Outptr_z_ +#undef _Outptr_opt_z_ +#define _Outptr_opt_z_ +#undef _Outptr_result_maybenull_z_ +#define _Outptr_result_maybenull_z_ +#undef _Outptr_opt_result_maybenull_z_ +#define _Outptr_opt_result_maybenull_z_ +#undef _COM_Outptr_ +#define _COM_Outptr_ +#undef _COM_Outptr_opt_ +#define _COM_Outptr_opt_ +#undef _COM_Outptr_result_maybenull_ +#define _COM_Outptr_result_maybenull_ +#undef _COM_Outptr_opt_result_maybenull_ +#define _COM_Outptr_opt_result_maybenull_ +#undef _Outptr_result_buffer_ +#define _Outptr_result_buffer_(s) +#undef _Outptr_result_bytebuffer_ +#define _Outptr_result_bytebuffer_(s) +#undef _Outptr_opt_result_buffer_ +#define _Outptr_opt_result_buffer_(s) +#undef _Outptr_opt_result_bytebuffer_ +#define _Outptr_opt_result_bytebuffer_(s) +#undef _Outptr_result_buffer_to_ +#define _Outptr_result_buffer_to_(s,c) +#undef _Outptr_result_bytebuffer_to_ +#define _Outptr_result_bytebuffer_to_(s,c) +#undef _Outptr_opt_result_buffer_to_ +#define _Outptr_opt_result_buffer_to_(s,c) +#undef _Outptr_opt_result_bytebuffer_to_ +#define _Outptr_opt_result_bytebuffer_to_(s,c) +#undef _Ret_ +#define _Ret_ +#undef _Ret_valid_ +#define _Ret_valid_ +#undef _Ret_z_ +#define _Ret_z_ +#undef _Ret_writes_ +#define _Ret_writes_(s) +#undef _Ret_writes_bytes_ +#define _Ret_writes_bytes_(s) +#undef _Ret_writes_z_ +#define _Ret_writes_z_(s) +#undef _Ret_writes_to_ +#define _Ret_writes_to_(s,c) +#undef _Ret_writes_bytes_to_ +#define _Ret_writes_bytes_to_(s,c) +#undef _Ret_writes_maybenull_ +#define _Ret_writes_maybenull_(s) +#undef _Ret_writes_bytes_maybenull_ +#define _Ret_writes_bytes_maybenull_(s) +#undef _Ret_writes_to_maybenull_ +#define _Ret_writes_to_maybenull_(s,c) +#undef _Ret_writes_bytes_to_maybenull_ +#define _Ret_writes_bytes_to_maybenull_(s,c) +#undef _Ret_writes_maybenull_z_ +#define _Ret_writes_maybenull_z_(s) +#undef _Ret_maybenull_ +#define _Ret_maybenull_ +#undef _Ret_maybenull_z_ +#define _Ret_maybenull_z_ +#undef _Field_size_ +#define _Field_size_(s) +#undef _Field_size_opt_ +#define _Field_size_opt_(s) +#undef _Field_size_bytes_ +#define _Field_size_bytes_(s) +#undef _Field_size_bytes_opt_ +#define _Field_size_bytes_opt_(s) +#undef _Field_size_part_ +#define _Field_size_part_(s,c) +#undef _Field_size_part_opt_ +#define _Field_size_part_opt_(s,c) +#undef _Field_size_bytes_part_ +#define _Field_size_bytes_part_(s,c) +#undef _Field_size_bytes_part_opt_ +#define _Field_size_bytes_part_opt_(s,c) +#undef _Field_size_full_ +#define _Field_size_full_(s) +#undef _Field_size_full_opt_ +#define _Field_size_full_opt_(s) +#undef _Field_size_bytes_full_ +#define _Field_size_bytes_full_(s) +#undef _Field_size_bytes_full_opt_ +#define _Field_size_bytes_full_opt_(s) +#undef _Printf_format_string_ +#define _Printf_format_string_ +#undef _Scanf_format_string_ +#define _Scanf_format_string_ +#undef _Scanf_s_format_string_ +#define _Scanf_s_format_string_ +#undef _Printf_format_string_params_ +#define _Printf_format_string_params_(x) +#undef _Scanf_format_string_params_ +#define _Scanf_format_string_params_(x) +#undef _Scanf_s_format_string_params_ +#define _Scanf_s_format_string_params_(x) +#undef _In_range_ +#define _In_range_(l,h) +#undef _Out_range_ +#define _Out_range_(l,h) +#undef _Ret_range_ +#define _Ret_range_(l,h) +#undef _Deref_in_range_ +#define _Deref_in_range_(l,h) +#undef _Deref_out_range_ +#define _Deref_out_range_(l,h) +#undef _Deref_inout_range_ +#define _Deref_inout_range_(l,h) +#undef _Field_range_ +#define _Field_range_(l,h) +#undef _Pre_equal_to_ +#define _Pre_equal_to_(e) +#undef _Post_equal_to_ +#define _Post_equal_to_(e) +#undef _Struct_size_bytes_ +#define _Struct_size_bytes_(s) +#undef _Analysis_assume_ +#define _Analysis_assume_ +#undef _Analysis_mode_ +#define _Analysis_mode_(m) +#undef _Analysis_noreturn_ +#define _Analysis_noreturn_ +#undef _Raises_SEH_exception_ +#define _Raises_SEH_exception_ +#undef _Maybe_raises_SEH_exception_ +#define _Maybe_raises_SEH_exception_ +#undef _Function_class_ +#define _Function_class_(n) +#undef _Literal_ +#define _Literal_ +#undef _Notliteral_ +#define _Notliteral_ +#undef _Enum_is_bitflag_ +#define _Enum_is_bitflag_ +#undef _Strict_type_match_ +#define _Strict_type_match_ +#undef _Points_to_data_ +#define _Points_to_data_ +#undef _Interlocked_operand_ +#define _Interlocked_operand_ +#undef _IRQL_raises_ +#define _IRQL_raises_(i) +#undef _IRQL_requires_ +#define _IRQL_requires_(i) +#undef _IRQL_requires_max_ +#define _IRQL_requires_max_(i) +#undef _IRQL_requires_min_ +#define _IRQL_requires_min_(i) +#undef _IRQL_saves_ +#define _IRQL_saves_ +#undef _IRQL_saves_global_ +#define _IRQL_saves_global_(k,s) +#undef _IRQL_restores_ +#define _IRQL_restores_ +#undef _IRQL_restores_global_ +#define _IRQL_restores_global_(k,s) +#undef _IRQL_always_function_min_ +#define _IRQL_always_function_min_(i) +#undef _IRQL_always_function_max_ +#define _IRQL_always_function_max_(i) +#undef _IRQL_requires_same_ +#define _IRQL_requires_same_ +#undef _IRQL_uses_cancel_ +#define _IRQL_uses_cancel_ +#undef _IRQL_is_cancel_ +#define _IRQL_is_cancel_ +#undef _Kernel_float_saved_ +#define _Kernel_float_saved_ +#undef _Kernel_float_restored_ +#define _Kernel_float_restored_ +#undef _Kernel_float_used_ +#define _Kernel_float_used_ +#undef _Kernel_acquires_resource_ +#define _Kernel_acquires_resource_(k) +#undef _Kernel_releases_resource_ +#define _Kernel_releases_resource_(k) +#undef _Kernel_requires_resource_held_ +#define _Kernel_requires_resource_held_(k) +#undef _Kernel_requires_resource_not_held_ +#define _Kernel_requires_resource_not_held_(k) +#undef _Kernel_clear_do_init_ +#define _Kernel_clear_do_init_(yn) +#undef _Kernel_IoGetDmaAdapter_ +#define _Kernel_IoGetDmaAdapter_ +#undef _Outref_ +#define _Outref_ +#undef _Outref_result_maybenull_ +#define _Outref_result_maybenull_ +#undef _Outref_result_buffer_ +#define _Outref_result_buffer_(s) +#undef _Outref_result_bytebuffer_ +#define _Outref_result_bytebuffer_(s) +#undef _Outref_result_buffer_to_ +#define _Outref_result_buffer_to_(s,c) +#undef _Outref_result_bytebuffer_to_ +#define _Outref_result_bytebuffer_to_(s,c) +#undef _Outref_result_buffer_all_ +#define _Outref_result_buffer_all_(s) +#undef _Outref_result_bytebuffer_all_ +#define _Outref_result_bytebuffer_all_(s) +#undef _Outref_result_buffer_maybenull_ +#define _Outref_result_buffer_maybenull_(s) +#undef _Outref_result_bytebuffer_maybenull_ +#define _Outref_result_bytebuffer_maybenull_(s) +#undef _Outref_result_buffer_to_maybenull_ +#define _Outref_result_buffer_to_maybenull_(s,c) +#undef _Outref_result_bytebuffer_to_maybenull_ +#define _Outref_result_bytebuffer_to_maybenull_(s,c) +#undef _Outref_result_buffer_all_maybenull_ +#define _Outref_result_buffer_all_maybenull_(s) +#undef _Outref_result_bytebuffer_all_maybenull_ +#define _Outref_result_bytebuffer_all_maybenull_(s) +#undef _In_defensive_ +#define _In_defensive_(a) +#undef _Out_defensive_ +#define _Out_defensive_(a) +#undef _Inout_defensive_ +#define _Inout_defensive_(a) +#undef _Outptr_result_nullonfailure_ +#define _Outptr_result_nullonfailure_ +#undef _Outptr_opt_result_nullonfailure_ +#define _Outptr_opt_result_nullonfailure_ +#undef _Outref_result_nullonfailure_ +#define _Outref_result_nullonfailure_ +#undef _Result_nullonfailure_ +#define _Result_nullonfailure_ +#undef _Result_zeroonfailure_ +#define _Result_zeroonfailure_ +#undef _Acquires_nonreentrant_lock_ +#define _Acquires_nonreentrant_lock_(e) +#undef _Releases_nonreentrant_lock_ +#define _Releases_nonreentrant_lock_(e) +#undef _Reserved_ +#define _Reserved_ _Pre_equal_to_(0) _Pre_ _Null_ +#undef _Pre_z_ +#define _Pre_z_ _Pre_ _Null_terminated_ +#undef _Post_z_ +#define _Post_z_ _Post_ _Null_terminated_ +#undef _Prepost_z_ +#define _Prepost_z_ _Pre_z_ _Post_z_ +#undef _Pre_null_ +#define _Pre_null_ _Pre_ _Null_ +#undef _Pre_maybenull_ +#define _Pre_maybenull_ _Pre_ _Maybenull_ +#undef _Pre_notnull_ +#define _Pre_notnull_ _Pre_ _Notnull_ +#undef _Pre_valid_ +#define _Pre_valid_ _Pre_notnull_ _Pre_ _Valid_ +#undef _Pre_opt_valid_ +#define _Pre_opt_valid_ _Pre_maybenull_ _Pre_ _Valid_ +#undef _Post_valid_ +#define _Post_valid_ _Post_ _Valid_ +#undef _Post_invalid_ +#define _Post_invalid_ _Post_ _Deref_ _Notvalid_ +#undef _Post_ptr_invalid_ +#define _Post_ptr_invalid_ _Post_ _Notvalid_ +#undef _Pre_readable_size_ +#define _Pre_readable_size_(s) _Pre_ _Readable_elements_(s) _Pre_ _Valid_ +#undef _Pre_writable_size_ +#define _Pre_writable_size_(s) _Pre_ _Writable_elements_(s) +#undef _Pre_readable_byte_size_ +#define _Pre_readable_byte_size_(s) _Pre_ _Readable_bytes_(s) _Pre_ _Valid_ +#undef _Pre_writable_byte_size_ +#define _Pre_writable_byte_size_(s) _Pre_ _Writable_bytes_(s) +#undef _Post_readable_size_ +#define _Post_readable_size_(s) _Post_ _Readable_elements_(s) _Post_ _Valid_ +#undef _Post_writable_size_ +#define _Post_writable_size_(s) _Post_ _Writable_elements_(s) +#undef _Post_readable_byte_size_ +#define _Post_readable_byte_size_(s) _Post_ _Readable_bytes_(s) _Post_ _Valid_ +#undef _Post_writable_byte_size_ +#define _Post_writable_byte_size_(s) _Post_ _Writable_bytes_(s) + +#endif /* _NO_SAL_2_H_ */ diff --git a/lib/coreclr/src/pal/inc/rt/ntimage.h b/lib/coreclr/src/pal/inc/rt/ntimage.h new file mode 100644 index 0000000000..8e03cb4e19 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/ntimage.h @@ -0,0 +1,1790 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: ntimage.h +// +// =========================================================================== + +// +//Abstract: +// +// This is the include file that describes all image structures. +// +//Author: +// +// +// +//Revision History: +// + + +#ifndef _NTIMAGE_ +#define _NTIMAGE_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +// +// Define the linker version number. + +#define IMAGE_MAJOR_LINKER_VERSION 2 + +// begin_winnt + + +// +// Image Format +// + + +#ifndef _MAC + +#include "pshpack4.h" // 4 byte packing is the default + +#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define IMAGE_OS2_SIGNATURE 0x454E // NE +#define IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define IMAGE_VXD_SIGNATURE 0x454C // LE +#define IMAGE_NT_SIGNATURE 0x00004550 // PE00 + +#include "pshpack2.h" // 16 bit headers are 2 byte packed + +#else + +#include "pshpack1.h" + +#define IMAGE_DOS_SIGNATURE 0x4D5A // MZ +#define IMAGE_OS2_SIGNATURE 0x4E45 // NE +#define IMAGE_OS2_SIGNATURE_LE 0x4C45 // LE +#define IMAGE_NT_SIGNATURE 0x50450000 // PE00 +#endif + +typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header + USHORT e_magic; // Magic number + USHORT e_cblp; // Bytes on last page of file + USHORT e_cp; // Pages in file + USHORT e_crlc; // Relocations + USHORT e_cparhdr; // Size of header in paragraphs + USHORT e_minalloc; // Minimum extra paragraphs needed + USHORT e_maxalloc; // Maximum extra paragraphs needed + USHORT e_ss; // Initial (relative) SS value + USHORT e_sp; // Initial SP value + USHORT e_csum; // Checksum + USHORT e_ip; // Initial IP value + USHORT e_cs; // Initial (relative) CS value + USHORT e_lfarlc; // File address of relocation table + USHORT e_ovno; // Overlay number + USHORT e_res[4]; // Reserved words + USHORT e_oemid; // OEM identifier (for e_oeminfo) + USHORT e_oeminfo; // OEM information; e_oemid specific + USHORT e_res2[10]; // Reserved words + LONG e_lfanew; // File address of new exe header + } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; + +typedef struct _IMAGE_OS2_HEADER { // OS/2 .EXE header + USHORT ne_magic; // Magic number + CHAR ne_ver; // Version number + CHAR ne_rev; // Revision number + USHORT ne_enttab; // Offset of Entry Table + USHORT ne_cbenttab; // Number of bytes in Entry Table + LONG ne_crc; // Checksum of whole file + USHORT ne_flags; // Flag word + USHORT ne_autodata; // Automatic data segment number + USHORT ne_heap; // Initial heap allocation + USHORT ne_stack; // Initial stack allocation + LONG ne_csip; // Initial CS:IP setting + LONG ne_sssp; // Initial SS:SP setting + USHORT ne_cseg; // Count of file segments + USHORT ne_cmod; // Entries in Module Reference Table + USHORT ne_cbnrestab; // Size of non-resident name table + USHORT ne_segtab; // Offset of Segment Table + USHORT ne_rsrctab; // Offset of Resource Table + USHORT ne_restab; // Offset of resident name table + USHORT ne_modtab; // Offset of Module Reference Table + USHORT ne_imptab; // Offset of Imported Names Table + LONG ne_nrestab; // Offset of Non-resident Names Table + USHORT ne_cmovent; // Count of movable entries + USHORT ne_align; // Segment alignment shift count + USHORT ne_cres; // Count of resource segments + UCHAR ne_exetyp; // Target Operating system + UCHAR ne_flagsothers; // Other .EXE flags + USHORT ne_pretthunks; // offset to return thunks + USHORT ne_psegrefbytes; // offset to segment ref. bytes + USHORT ne_swaparea; // Minimum code swap area size + USHORT ne_expver; // Expected Windows version number + } IMAGE_OS2_HEADER, *PIMAGE_OS2_HEADER; + +typedef struct _IMAGE_VXD_HEADER { // Windows VXD header + USHORT e32_magic; // Magic number + UCHAR e32_border; // The byte ordering for the VXD + UCHAR e32_worder; // The word ordering for the VXD + ULONG e32_level; // The EXE format level for now = 0 + USHORT e32_cpu; // The CPU type + USHORT e32_os; // The OS type + ULONG e32_ver; // Module version + ULONG e32_mflags; // Module flags + ULONG e32_mpages; // Module # pages + ULONG e32_startobj; // Object # for instruction pointer + ULONG e32_eip; // Extended instruction pointer + ULONG e32_stackobj; // Object # for stack pointer + ULONG e32_esp; // Extended stack pointer + ULONG e32_pagesize; // VXD page size + ULONG e32_lastpagesize; // Last page size in VXD + ULONG e32_fixupsize; // Fixup section size + ULONG e32_fixupsum; // Fixup section checksum + ULONG e32_ldrsize; // Loader section size + ULONG e32_ldrsum; // Loader section checksum + ULONG e32_objtab; // Object table offset + ULONG e32_objcnt; // Number of objects in module + ULONG e32_objmap; // Object page map offset + ULONG e32_itermap; // Object iterated data map offset + ULONG e32_rsrctab; // Offset of Resource Table + ULONG e32_rsrccnt; // Number of resource entries + ULONG e32_restab; // Offset of resident name table + ULONG e32_enttab; // Offset of Entry Table + ULONG e32_dirtab; // Offset of Module Directive Table + ULONG e32_dircnt; // Number of module directives + ULONG e32_fpagetab; // Offset of Fixup Page Table + ULONG e32_frectab; // Offset of Fixup Record Table + ULONG e32_impmod; // Offset of Import Module Name Table + ULONG e32_impmodcnt; // Number of entries in Import Module Name Table + ULONG e32_impproc; // Offset of Import Procedure Name Table + ULONG e32_pagesum; // Offset of Per-Page Checksum Table + ULONG e32_datapage; // Offset of Enumerated Data Pages + ULONG e32_preload; // Number of preload pages + ULONG e32_nrestab; // Offset of Non-resident Names Table + ULONG e32_cbnrestab; // Size of Non-resident Name Table + ULONG e32_nressum; // Non-resident Name Table Checksum + ULONG e32_autodata; // Object # for automatic data object + ULONG e32_debuginfo; // Offset of the debugging information + ULONG e32_debuglen; // The length of the debugging info. in bytes + ULONG e32_instpreload; // Number of instance pages in preload section of VXD file + ULONG e32_instdemand; // Number of instance pages in demand load section of VXD file + ULONG e32_heapsize; // Size of heap - for 16-bit apps + UCHAR e32_res3[12]; // Reserved words + ULONG e32_winresoff; + ULONG e32_winreslen; + USHORT e32_devid; // Device ID for VxD + USHORT e32_ddkver; // DDK version for VxD + } IMAGE_VXD_HEADER, *PIMAGE_VXD_HEADER; + +#ifndef _MAC +#include "poppack.h" // Back to 4 byte packing +#endif + +// +// File header format. +// + +typedef struct _IMAGE_FILE_HEADER { + USHORT Machine; + USHORT NumberOfSections; + ULONG TimeDateStamp; + ULONG PointerToSymbolTable; + ULONG NumberOfSymbols; + USHORT SizeOfOptionalHeader; + USHORT Characteristics; +} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; + +#define IMAGE_SIZEOF_FILE_HEADER 20 + + +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file. +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file. +#define IMAGE_FILE_SYSTEM 0x1000 // System File. +#define IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. + +#define IMAGE_FILE_MACHINE_UNKNOWN 0 +#define IMAGE_FILE_MACHINE_I386 0x014c // Intel 386. +#define IMAGE_FILE_MACHINE_R3000 0x0162 // MIPS little-endian, 0x160 big-endian +#define IMAGE_FILE_MACHINE_R4000 0x0166 // MIPS little-endian +#define IMAGE_FILE_MACHINE_R10000 0x0168 // MIPS little-endian +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 +#define IMAGE_FILE_MACHINE_ALPHA 0x0184 // Alpha_AXP +#define IMAGE_FILE_MACHINE_SH3 0x01a2 // SH3 little-endian +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 // SH3E little-endian +#define IMAGE_FILE_MACHINE_SH4 0x01a6 // SH4 little-endian +#define IMAGE_FILE_MACHINE_SH5 0x01a8 // SH5 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_POWERPC 0x01F0 // IBM PowerPC Little-Endian +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 // MIPS +#define IMAGE_FILE_MACHINE_ALPHA64 0x0284 // ALPHA64 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 // MIPS +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 // MIPS +#define IMAGE_FILE_MACHINE_AXP64 IMAGE_FILE_MACHINE_ALPHA64 +#define IMAGE_FILE_MACHINE_TRICORE 0x0520 // Infineon +#define IMAGE_FILE_MACHINE_CEF 0x0CEF +#define IMAGE_FILE_MACHINE_EBC 0x0EBC // EFI Byte Code +#define IMAGE_FILE_MACHINE_AMD64 0x8664 // AMD64 (K8) +#define IMAGE_FILE_MACHINE_M32R 0x9041 // M32R little-endian +#define IMAGE_FILE_MACHINE_CEE 0xC0EE + +// +// Directory format. +// + +typedef struct _IMAGE_DATA_DIRECTORY { + ULONG VirtualAddress; + ULONG Size; +} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; + +#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 + +// +// Optional header format. +// + +typedef struct _IMAGE_OPTIONAL_HEADER { + // + // Standard fields. + // + + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONG BaseOfData; + + // + // NT additional fields. + // + + ULONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + USHORT Subsystem; + USHORT DllCharacteristics; + ULONG SizeOfStackReserve; + ULONG SizeOfStackCommit; + ULONG SizeOfHeapReserve; + ULONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; + +typedef struct _IMAGE_ROM_OPTIONAL_HEADER { + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONG BaseOfData; + ULONG BaseOfBss; + ULONG GprMask; + ULONG CprMask[4]; + ULONG GpValue; +} IMAGE_ROM_OPTIONAL_HEADER, *PIMAGE_ROM_OPTIONAL_HEADER; + +typedef struct _IMAGE_OPTIONAL_HEADER64 { + USHORT Magic; + UCHAR MajorLinkerVersion; + UCHAR MinorLinkerVersion; + ULONG SizeOfCode; + ULONG SizeOfInitializedData; + ULONG SizeOfUninitializedData; + ULONG AddressOfEntryPoint; + ULONG BaseOfCode; + ULONGLONG ImageBase; + ULONG SectionAlignment; + ULONG FileAlignment; + USHORT MajorOperatingSystemVersion; + USHORT MinorOperatingSystemVersion; + USHORT MajorImageVersion; + USHORT MinorImageVersion; + USHORT MajorSubsystemVersion; + USHORT MinorSubsystemVersion; + ULONG Win32VersionValue; + ULONG SizeOfImage; + ULONG SizeOfHeaders; + ULONG CheckSum; + USHORT Subsystem; + USHORT DllCharacteristics; + ULONGLONG SizeOfStackReserve; + ULONGLONG SizeOfStackCommit; + ULONGLONG SizeOfHeapReserve; + ULONGLONG SizeOfHeapCommit; + ULONG LoaderFlags; + ULONG NumberOfRvaAndSizes; + IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; +} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; + +#define IMAGE_SIZEOF_ROM_OPTIONAL_HEADER 56 +#define IMAGE_SIZEOF_STD_OPTIONAL_HEADER 28 +#define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224 +#define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240 + +#define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b +#define IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b +#define IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 + +#ifdef _WIN64 +typedef IMAGE_OPTIONAL_HEADER64 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER64 PIMAGE_OPTIONAL_HEADER; +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL64_HEADER +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR64_MAGIC +#else +typedef IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER; +typedef PIMAGE_OPTIONAL_HEADER32 PIMAGE_OPTIONAL_HEADER; +#define IMAGE_SIZEOF_NT_OPTIONAL_HEADER IMAGE_SIZEOF_NT_OPTIONAL32_HEADER +#define IMAGE_NT_OPTIONAL_HDR_MAGIC IMAGE_NT_OPTIONAL_HDR32_MAGIC +#endif + +typedef struct _IMAGE_NT_HEADERS64 { + ULONG Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; + +typedef struct _IMAGE_NT_HEADERS { + ULONG Signature; + IMAGE_FILE_HEADER FileHeader; + IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; + +typedef struct _IMAGE_ROM_HEADERS { + IMAGE_FILE_HEADER FileHeader; + IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} IMAGE_ROM_HEADERS, *PIMAGE_ROM_HEADERS; + +#ifdef _WIN64 +typedef IMAGE_NT_HEADERS64 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS64 PIMAGE_NT_HEADERS; +#else +typedef IMAGE_NT_HEADERS32 IMAGE_NT_HEADERS; +typedef PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS; +#endif + +// IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is the same either way. + +#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ + ((ULONG_PTR)ntheader + \ + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ + VAL16(((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader) \ + )) + +// Subsystem Values + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 // Unknown subsystem. +#define IMAGE_SUBSYSTEM_NATIVE 1 // Image doesn't require a subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem. +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem. +// end_winnt +// reserved 4 // Old Windows CE subsystem. +// begin_winnt +#define IMAGE_SUBSYSTEM_OS2_CUI 5 // image runs in the OS/2 character subsystem. +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 // image runs in the Posix character subsystem. +#define IMAGE_SUBSYSTEM_NATIVE_WINDOWS 8 // image is a native Win9x driver. +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 // Image runs in the Windows CE subsystem. +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 // +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 // +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 // +#define IMAGE_SUBSYSTEM_EFI_ROM 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +// DllCharacteristics Entries + +// IMAGE_LIBRARY_PROCESS_INIT 0x0001 // Reserved. +// IMAGE_LIBRARY_PROCESS_TERM 0x0002 // Reserved. +// IMAGE_LIBRARY_THREAD_INIT 0x0004 // Reserved. +// IMAGE_LIBRARY_THREAD_TERM 0x0008 // Reserved. +#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA 0x0020 // Image can handle a high entropy 64-bit virtual address space. +#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040 // DLL can move +#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT 0x0100 // Image ix NX compatible +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 // Image does not use SEH. No SE handler may reside in this image +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 // Do not bind this image. +#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000 // Image should execute in an AppContainer +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 // Driver uses WDM model +// 0x4000 // Reserved. +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 +// end_winnt +#define IMAGE_DLLCHARACTERISTICS_X86_THUNK 0x1000 // Image is a Wx86 Thunk DLL +// Note: The Borland linker sets IMAGE_LIBRARY_xxx flags in DllCharacteristics + +// LoaderFlags Values + +#define IMAGE_LOADER_FLAGS_COMPLUS 0x00000001 // COM+ image +#define IMAGE_LOADER_FLAGS_SYSTEM_GLOBAL 0x01000000 // Global subsections apply across TS sessions. + +// begin_winnt + +// Directory Entries + +#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Export Directory +#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Import Directory +#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Resource Directory +#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Exception Directory +#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Security Directory +#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Base Relocation Table +#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory +// IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // (X86 usage) +#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 // Architecture Specific Data +#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // RVA of GP +#define IMAGE_DIRECTORY_ENTRY_TLS 9 // TLS Directory +#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 // Load Configuration Directory +#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 // Bound Import Directory in headers +#define IMAGE_DIRECTORY_ENTRY_IAT 12 // Import Address Table +#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 // Delay Load Import Descriptors +#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 // COM Runtime descriptor + +#ifdef _MSC_VER +// +// Non-COFF Object file header +// + +typedef struct ANON_OBJECT_HEADER { + USHORT Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + USHORT Sig2; // Must be 0xffff + USHORT Version; // >= 1 (implies the CLSID field is present) + USHORT Machine; + ULONG TimeDateStamp; + CLSID ClassID; // Used to invoke CoCreateInstance + ULONG SizeOfData; // Size of data that follows the header +} ANON_OBJECT_HEADER; +#endif + +// +// Section header format. +// + +#define IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct _IMAGE_SECTION_HEADER { + UCHAR Name[IMAGE_SIZEOF_SHORT_NAME]; + union { + ULONG PhysicalAddress; + ULONG VirtualSize; + } Misc; + ULONG VirtualAddress; + ULONG SizeOfRawData; + ULONG PointerToRawData; + ULONG PointerToRelocations; + ULONG PointerToLinenumbers; + USHORT NumberOfRelocations; + USHORT NumberOfLinenumbers; + ULONG Characteristics; +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; + +#define IMAGE_SIZEOF_SECTION_HEADER 40 + +// +// Section characteristics. +// +// IMAGE_SCN_TYPE_REG 0x00000000 // Reserved. +// IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved. +// IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved. +// IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved. +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. +// IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved. + +#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code. +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data. +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data. + +#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +// IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved. +#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat. +// 0x00002000 // Reserved. +// IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000 +#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section. +#define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP +#define IMAGE_SCN_MEM_FARDATA 0x00008000 +// IMAGE_SCN_MEM_SYSHEAP - Obsolete 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 // Default alignment if no others are specified. +#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 // +// Unused 0x00F00000 +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations. +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded. +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable. +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable. +#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable. +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable. +#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable. +#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable. + +// +// TLS Chaacteristic Flags +// +#define IMAGE_SCN_SCALE_INDEX 0x00000001 // Tls index is scaled + +#ifndef _MAC +#include "pshpack2.h" // Symbols, relocs, and linenumbers are 2 byte packed +#endif + +// +// Symbol format. +// + +typedef struct _IMAGE_SYMBOL { + union { + UCHAR ShortName[8]; + struct { + ULONG Short; // if 0, use LongName + ULONG Long; // offset into string table + } Name; + ULONG LongName[2]; // PUCHAR[2] + } N; + ULONG Value; + SHORT SectionNumber; + USHORT Type; + UCHAR StorageClass; + UCHAR NumberOfAuxSymbols; +} IMAGE_SYMBOL; +typedef IMAGE_SYMBOL UNALIGNED *PIMAGE_SYMBOL; + + +#define IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// + +#define IMAGE_SYM_UNDEFINED (SHORT)0 // Symbol is undefined or is common. +#define IMAGE_SYM_ABSOLUTE (SHORT)-1 // Symbol is an absolute value. +#define IMAGE_SYM_DEBUG (SHORT)-2 // Symbol is a special debug item. +#define IMAGE_SYM_SECTION_MAX 0xFEFF // Values 0xFF00-0xFFFF are special + +// +// Type (fundamental) values. +// + +#define IMAGE_SYM_TYPE_NULL 0x0000 // no type. +#define IMAGE_SYM_TYPE_VOID 0x0001 // +#define IMAGE_SYM_TYPE_CHAR 0x0002 // type character. +#define IMAGE_SYM_TYPE_SHORT 0x0003 // type short integer. +#define IMAGE_SYM_TYPE_INT 0x0004 // +#define IMAGE_SYM_TYPE_LONG 0x0005 // +#define IMAGE_SYM_TYPE_FLOAT 0x0006 // +#define IMAGE_SYM_TYPE_DOUBLE 0x0007 // +#define IMAGE_SYM_TYPE_STRUCT 0x0008 // +#define IMAGE_SYM_TYPE_UNION 0x0009 // +#define IMAGE_SYM_TYPE_ENUM 0x000A // enumeration. +#define IMAGE_SYM_TYPE_MOE 0x000B // member of enumeration. +#define IMAGE_SYM_TYPE_UCHAR 0x000C // +#define IMAGE_SYM_TYPE_USHORT 0x000D // +#define IMAGE_SYM_TYPE_UINT 0x000E // +#define IMAGE_SYM_TYPE_ULONG 0x000F // +#define IMAGE_SYM_TYPE_PCODE 0x8000 // +// +// Type (derived) values. +// + +#define IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define IMAGE_SYM_DTYPE_POINTER 1 // pointer. +#define IMAGE_SYM_DTYPE_FUNCTION 2 // function. +#define IMAGE_SYM_DTYPE_ARRAY 3 // array. + +// +// Storage classes. +// +#define IMAGE_SYM_CLASS_END_OF_FUNCTION (UCHAR)-1 +#define IMAGE_SYM_CLASS_NULL 0x0000 +#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001 +#define IMAGE_SYM_CLASS_EXTERNAL 0x0002 +#define IMAGE_SYM_CLASS_STATIC 0x0003 +#define IMAGE_SYM_CLASS_REGISTER 0x0004 +#define IMAGE_SYM_CLASS_EXTERNAL_DEF 0x0005 +#define IMAGE_SYM_CLASS_LABEL 0x0006 +#define IMAGE_SYM_CLASS_UNDEFINED_LABEL 0x0007 +#define IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 0x0008 +#define IMAGE_SYM_CLASS_ARGUMENT 0x0009 +#define IMAGE_SYM_CLASS_STRUCT_TAG 0x000A +#define IMAGE_SYM_CLASS_MEMBER_OF_UNION 0x000B +#define IMAGE_SYM_CLASS_UNION_TAG 0x000C +#define IMAGE_SYM_CLASS_TYPE_DEFINITION 0x000D +#define IMAGE_SYM_CLASS_UNDEFINED_STATIC 0x000E +#define IMAGE_SYM_CLASS_ENUM_TAG 0x000F +#define IMAGE_SYM_CLASS_MEMBER_OF_ENUM 0x0010 +#define IMAGE_SYM_CLASS_REGISTER_PARAM 0x0011 +#define IMAGE_SYM_CLASS_BIT_FIELD 0x0012 + +#define IMAGE_SYM_CLASS_FAR_EXTERNAL 0x0044 // + +#define IMAGE_SYM_CLASS_BLOCK 0x0064 +#define IMAGE_SYM_CLASS_FUNCTION 0x0065 +#define IMAGE_SYM_CLASS_END_OF_STRUCT 0x0066 +#define IMAGE_SYM_CLASS_FILE 0x0067 +// new +#define IMAGE_SYM_CLASS_SECTION 0x0068 +#define IMAGE_SYM_CLASS_WEAK_EXTERNAL 0x0069 + +#define IMAGE_SYM_CLASS_CLR_TOKEN 0x006B + +// type packing constants + +#define N_BTMASK 0x000F +#define N_TMASK 0x0030 +#define N_TMASK1 0x00C0 +#define N_TMASK2 0x00F0 +#define N_BTSHFT 4 +#define N_TSHIFT 2 +// MACROS + +// Basic Type of x +#define BTYPE(x) ((x) & N_BTMASK) + +// Is x a pointer? +#ifndef ISPTR +#define ISPTR(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_POINTER << N_BTSHFT)) +#endif + +// Is x a function? +#ifndef ISFCN +#define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT)) +#endif + +// Is x an array? + +#ifndef ISARY +#define ISARY(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_ARRAY << N_BTSHFT)) +#endif + +// Is x a structure, union, or enumeration TAG? +#ifndef ISTAG +#define ISTAG(x) ((x)==IMAGE_SYM_CLASS_STRUCT_TAG || (x)==IMAGE_SYM_CLASS_UNION_TAG || (x)==IMAGE_SYM_CLASS_ENUM_TAG) +#endif + +#ifndef INCREF +#define INCREF(x) ((((x)&~N_BTMASK)<>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) +#endif + +// +// Auxiliary entry format. +// + +typedef union _IMAGE_AUX_SYMBOL { + struct { + ULONG TagIndex; // struct, union, or enum tag index + union { + struct { + USHORT Linenumber; // declaration line number + USHORT Size; // size of struct, union, or enum + } LnSz; + ULONG TotalSize; + } Misc; + union { + struct { // if ISFCN, tag, or .bb + ULONG PointerToLinenumber; + ULONG PointerToNextFunction; + } Function; + struct { // if ISARY, up to 4 dimen. + USHORT Dimension[4]; + } Array; + } FcnAry; + USHORT TvIndex; // tv index + } Sym; + struct { + UCHAR Name[IMAGE_SIZEOF_SYMBOL]; + } File; + struct { + ULONG Length; // section length + USHORT NumberOfRelocations; // number of relocation entries + USHORT NumberOfLinenumbers; // number of line numbers + ULONG CheckSum; // checksum for communal + SHORT Number; // section number to associate with + UCHAR Selection; // communal selection type + } Section; +} IMAGE_AUX_SYMBOL; +typedef IMAGE_AUX_SYMBOL UNALIGNED *PIMAGE_AUX_SYMBOL; + +#define IMAGE_SIZEOF_AUX_SYMBOL 18 + +typedef enum IMAGE_AUX_SYMBOL_TYPE { + IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF = 1, +} IMAGE_AUX_SYMBOL_TYPE; + +#include "pshpack2.h" + +typedef struct IMAGE_AUX_SYMBOL_TOKEN_DEF { + UCHAR bAuxType; // IMAGE_AUX_SYMBOL_TYPE + UCHAR bReserved; // Must be 0 + ULONG SymbolTableIndex; + UCHAR rgbReserved[12]; // Must be 0 +} IMAGE_AUX_SYMBOL_TOKEN_DEF; + +typedef IMAGE_AUX_SYMBOL_TOKEN_DEF UNALIGNED *PIMAGE_AUX_SYMBOL_TOKEN_DEF; + +#include "poppack.h" + +// +// Communal selection types. +// + +#define IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define IMAGE_COMDAT_SELECT_ANY 2 +#define IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 +#define IMAGE_COMDAT_SELECT_LARGEST 6 +#define IMAGE_COMDAT_SELECT_NEWEST 7 + +#define IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +// +// Relocation format. +// + +typedef struct _IMAGE_RELOCATION { + union { + ULONG VirtualAddress; + ULONG RelocCount; // Set to the real count when IMAGE_SCN_LNK_NRELOC_OVFL is set + }; + ULONG SymbolTableIndex; + USHORT Type; +} IMAGE_RELOCATION; +typedef IMAGE_RELOCATION UNALIGNED *PIMAGE_RELOCATION; + +#define IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// +#define IMAGE_REL_I386_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_I386_DIR16 0x0001 // Direct 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_REL16 0x0002 // PC-relative 16-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32 0x0006 // Direct 32-bit reference to the symbols virtual address +#define IMAGE_REL_I386_DIR32NB 0x0007 // Direct 32-bit reference to the symbols virtual address, base not included +#define IMAGE_REL_I386_SEG12 0x0009 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define IMAGE_REL_I386_SECTION 0x000A +#define IMAGE_REL_I386_SECREL 0x000B +#define IMAGE_REL_I386_TOKEN 0x000C // clr token +#define IMAGE_REL_I386_SECREL7 0x000D // 7 bit offset from base of section containing target +#define IMAGE_REL_I386_REL32 0x0014 // PC-relative 32-bit reference to the symbols virtual address + +// +// MIPS relocation types. +// +#define IMAGE_REL_MIPS_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_MIPS_REFHALF 0x0001 +#define IMAGE_REL_MIPS_REFWORD 0x0002 +#define IMAGE_REL_MIPS_JMPADDR 0x0003 +#define IMAGE_REL_MIPS_REFHI 0x0004 +#define IMAGE_REL_MIPS_REFLO 0x0005 +#define IMAGE_REL_MIPS_GPREL 0x0006 +#define IMAGE_REL_MIPS_LITERAL 0x0007 +#define IMAGE_REL_MIPS_SECTION 0x000A +#define IMAGE_REL_MIPS_SECREL 0x000B +#define IMAGE_REL_MIPS_SECRELLO 0x000C // Low 16-bit section relative referemce (used for >32k TLS) +#define IMAGE_REL_MIPS_SECRELHI 0x000D // High 16-bit section relative reference (used for >32k TLS) +#define IMAGE_REL_MIPS_TOKEN 0x000E // clr token +#define IMAGE_REL_MIPS_JMPADDR16 0x0010 +#define IMAGE_REL_MIPS_REFWORDNB 0x0022 +#define IMAGE_REL_MIPS_PAIR 0x0025 + +// +// Alpha Relocation types. +// +#define IMAGE_REL_ALPHA_ABSOLUTE 0x0000 +#define IMAGE_REL_ALPHA_REFLONG 0x0001 +#define IMAGE_REL_ALPHA_REFQUAD 0x0002 +#define IMAGE_REL_ALPHA_GPREL32 0x0003 +#define IMAGE_REL_ALPHA_LITERAL 0x0004 +#define IMAGE_REL_ALPHA_LITUSE 0x0005 +#define IMAGE_REL_ALPHA_GPDISP 0x0006 +#define IMAGE_REL_ALPHA_BRADDR 0x0007 +#define IMAGE_REL_ALPHA_HINT 0x0008 +#define IMAGE_REL_ALPHA_INLINE_REFLONG 0x0009 +#define IMAGE_REL_ALPHA_REFHI 0x000A +#define IMAGE_REL_ALPHA_REFLO 0x000B +#define IMAGE_REL_ALPHA_PAIR 0x000C +#define IMAGE_REL_ALPHA_MATCH 0x000D +#define IMAGE_REL_ALPHA_SECTION 0x000E +#define IMAGE_REL_ALPHA_SECREL 0x000F +#define IMAGE_REL_ALPHA_REFLONGNB 0x0010 +#define IMAGE_REL_ALPHA_SECRELLO 0x0011 // Low 16-bit section relative reference +#define IMAGE_REL_ALPHA_SECRELHI 0x0012 // High 16-bit section relative reference +#define IMAGE_REL_ALPHA_REFQ3 0x0013 // High 16 bits of 48 bit reference +#define IMAGE_REL_ALPHA_REFQ2 0x0014 // Middle 16 bits of 48 bit reference +#define IMAGE_REL_ALPHA_REFQ1 0x0015 // Low 16 bits of 48 bit reference +#define IMAGE_REL_ALPHA_GPRELLO 0x0016 // Low 16-bit GP relative reference +#define IMAGE_REL_ALPHA_GPRELHI 0x0017 // High 16-bit GP relative reference + +// +// IBM PowerPC relocation types. +// +#define IMAGE_REL_PPC_ABSOLUTE 0x0000 // NOP +#define IMAGE_REL_PPC_ADDR64 0x0001 // 64-bit address +#define IMAGE_REL_PPC_ADDR32 0x0002 // 32-bit address +#define IMAGE_REL_PPC_ADDR24 0x0003 // 26-bit address, shifted left 2 (branch absolute) +#define IMAGE_REL_PPC_ADDR16 0x0004 // 16-bit address +#define IMAGE_REL_PPC_ADDR14 0x0005 // 16-bit address, shifted left 2 (load doubleword) +#define IMAGE_REL_PPC_REL24 0x0006 // 26-bit PC-relative offset, shifted left 2 (branch relative) +#define IMAGE_REL_PPC_REL14 0x0007 // 16-bit PC-relative offset, shifted left 2 (br cond relative) +#define IMAGE_REL_PPC_TOCREL16 0x0008 // 16-bit offset from TOC base +#define IMAGE_REL_PPC_TOCREL14 0x0009 // 16-bit offset from TOC base, shifted left 2 (load doubleword) + +#define IMAGE_REL_PPC_ADDR32NB 0x000A // 32-bit addr w/o image base +#define IMAGE_REL_PPC_SECREL 0x000B // va of containing section (as in an image sectionhdr) +#define IMAGE_REL_PPC_SECTION 0x000C // sectionheader number +#define IMAGE_REL_PPC_IFGLUE 0x000D // substitute TOC restore instruction iff symbol is glue code +#define IMAGE_REL_PPC_IMGLUE 0x000E // symbol is glue code; virtual address is TOC restore instruction +#define IMAGE_REL_PPC_SECREL16 0x000F // va of containing section (limited to 16 bits) +#define IMAGE_REL_PPC_REFHI 0x0010 +#define IMAGE_REL_PPC_REFLO 0x0011 +#define IMAGE_REL_PPC_PAIR 0x0012 +#define IMAGE_REL_PPC_SECRELLO 0x0013 // Low 16-bit section relative reference (used for >32k TLS) +#define IMAGE_REL_PPC_SECRELHI 0x0014 // High 16-bit section relative reference (used for >32k TLS) +#define IMAGE_REL_PPC_GPREL 0x0015 +#define IMAGE_REL_PPC_TOKEN 0x0016 // clr token + +#define IMAGE_REL_PPC_TYPEMASK 0x00FF // mask to isolate above values in IMAGE_RELOCATION.Type + +// Flag bits in IMAGE_RELOCATION.TYPE + +#define IMAGE_REL_PPC_NEG 0x0100 // subtract reloc value rather than adding it +#define IMAGE_REL_PPC_BRTAKEN 0x0200 // fix branch prediction bit to predict branch taken +#define IMAGE_REL_PPC_BRNTAKEN 0x0400 // fix branch prediction bit to predict branch not taken +#define IMAGE_REL_PPC_TOCDEFN 0x0800 // toc slot defined in file (or, data in toc) + +// +// Hitachi SH3 relocation types. +// +#define IMAGE_REL_SH3_ABSOLUTE 0x0000 // No relocation +#define IMAGE_REL_SH3_DIRECT16 0x0001 // 16 bit direct +#define IMAGE_REL_SH3_DIRECT32 0x0002 // 32 bit direct +#define IMAGE_REL_SH3_DIRECT8 0x0003 // 8 bit direct, -128..255 +#define IMAGE_REL_SH3_DIRECT8_WORD 0x0004 // 8 bit direct .W (0 ext.) +#define IMAGE_REL_SH3_DIRECT8_LONG 0x0005 // 8 bit direct .L (0 ext.) +#define IMAGE_REL_SH3_DIRECT4 0x0006 // 4 bit direct (0 ext.) +#define IMAGE_REL_SH3_DIRECT4_WORD 0x0007 // 4 bit direct .W (0 ext.) +#define IMAGE_REL_SH3_DIRECT4_LONG 0x0008 // 4 bit direct .L (0 ext.) +#define IMAGE_REL_SH3_PCREL8_WORD 0x0009 // 8 bit PC relative .W +#define IMAGE_REL_SH3_PCREL8_LONG 0x000A // 8 bit PC relative .L +#define IMAGE_REL_SH3_PCREL12_WORD 0x000B // 12 LSB PC relative .W +#define IMAGE_REL_SH3_STARTOF_SECTION 0x000C // Start of EXE section +#define IMAGE_REL_SH3_SIZEOF_SECTION 0x000D // Size of EXE section +#define IMAGE_REL_SH3_SECTION 0x000E // Section table index +#define IMAGE_REL_SH3_SECREL 0x000F // Offset within section +#define IMAGE_REL_SH3_DIRECT32_NB 0x0010 // 32 bit direct not based +#define IMAGE_REL_SH3_GPREL4_LONG 0x0011 // GP-relative addressing +#define IMAGE_REL_SH3_TOKEN 0x0012 // clr token + +#define IMAGE_REL_ARM_ABSOLUTE 0x0000 // No relocation required +#define IMAGE_REL_ARM_ADDR32 0x0001 // 32 bit address +#define IMAGE_REL_ARM_ADDR32NB 0x0002 // 32 bit address w/o image base +#define IMAGE_REL_ARM_BRANCH24 0x0003 // 24 bit offset << 2 & sign ext. +#define IMAGE_REL_ARM_BRANCH11 0x0004 // Thumb: 2 11 bit offsets +#define IMAGE_REL_ARM_TOKEN 0x0005 // clr token +#define IMAGE_REL_ARM_GPREL12 0x0006 // GP-relative addressing (ARM) +#define IMAGE_REL_ARM_GPREL7 0x0007 // GP-relative addressing (Thumb) +#define IMAGE_REL_ARM_BLX24 0x0008 +#define IMAGE_REL_ARM_BLX11 0x0009 +#define IMAGE_REL_ARM_SECTION 0x000E // Section table index +#define IMAGE_REL_ARM_SECREL 0x000F // Offset within section + +// +// ARM64 relocation types +// +#define IMAGE_REL_ARM64_ABSOLUTE 0x0000 +#define IMAGE_REL_ARM64_ADDR32 0x0001 +#define IMAGE_REL_ARM64_ADDR32NB 0x0002 +#define IMAGE_REL_ARM64_BRANCH26 0x0003 +#define IMAGE_REL_ARM64_PAGEBASE_REL21 0x0004 +#define IMAGE_REL_ARM64_REL21 0x0005 +#define IMAGE_REL_ARM64_PAGEOFFSET_12A 0x0006 +#define IMAGE_REL_ARM64_PAGEOFFSET_12L 0x0007 +#define IMAGE_REL_ARM64_SECREL 0x0008 +#define IMAGE_REL_ARM64_SECREL_LOW12A 0x0009 +#define IMAGE_REL_ARM64_SECREL_HIGH12A 0x000A +#define IMAGE_REL_ARM64_SECREL_LOW12L 0x000B +#define IMAGE_REL_ARM64_TOKEN 0x000C +#define IMAGE_REL_ARM64_SECTION 0x000D +#define IMAGE_REL_ARM64_ADDR64 0x000E + +#define IMAGE_REL_AM_ABSOLUTE 0x0000 +#define IMAGE_REL_AM_ADDR32 0x0001 +#define IMAGE_REL_AM_ADDR32NB 0x0002 +#define IMAGE_REL_AM_CALL32 0x0003 +#define IMAGE_REL_AM_FUNCINFO 0x0004 +#define IMAGE_REL_AM_REL32_1 0x0005 +#define IMAGE_REL_AM_REL32_2 0x0006 +#define IMAGE_REL_AM_SECREL 0x0007 +#define IMAGE_REL_AM_SECTION 0x0008 +#define IMAGE_REL_AM_TOKEN 0x0009 + +// +// X86-64 relocations +// +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_AMD64_ADDR64 0x0001 // 64-bit address (VA). +#define IMAGE_REL_AMD64_ADDR32 0x0002 // 32-bit address (VA). +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 // 32-bit address w/o image base (RVA). +#define IMAGE_REL_AMD64_REL32 0x0004 // 32-bit relative address from byte following reloc +#define IMAGE_REL_AMD64_REL32_1 0x0005 // 32-bit relative address from byte distance 1 from reloc +#define IMAGE_REL_AMD64_REL32_2 0x0006 // 32-bit relative address from byte distance 2 from reloc +#define IMAGE_REL_AMD64_REL32_3 0x0007 // 32-bit relative address from byte distance 3 from reloc +#define IMAGE_REL_AMD64_REL32_4 0x0008 // 32-bit relative address from byte distance 4 from reloc +#define IMAGE_REL_AMD64_REL32_5 0x0009 // 32-bit relative address from byte distance 5 from reloc +#define IMAGE_REL_AMD64_SECTION 0x000A // Section index +#define IMAGE_REL_AMD64_SECREL 0x000B // 32 bit offset from base of section containing target +#define IMAGE_REL_AMD64_SECREL7 0x000C // 7 bit unsigned offset from base of section containing target +#define IMAGE_REL_AMD64_TOKEN 0x000D // 32 bit metadata token + +// +// IA64 relocation types. +// +#define IMAGE_REL_IA64_ABSOLUTE 0x0000 +#define IMAGE_REL_IA64_IMM14 0x0001 +#define IMAGE_REL_IA64_IMM22 0x0002 +#define IMAGE_REL_IA64_IMM64 0x0003 +#define IMAGE_REL_IA64_DIR32 0x0004 +#define IMAGE_REL_IA64_DIR64 0x0005 +#define IMAGE_REL_IA64_PCREL21B 0x0006 +#define IMAGE_REL_IA64_PCREL21M 0x0007 +#define IMAGE_REL_IA64_PCREL21F 0x0008 +#define IMAGE_REL_IA64_GPREL22 0x0009 +#define IMAGE_REL_IA64_LTOFF22 0x000A +#define IMAGE_REL_IA64_SECTION 0x000B +#define IMAGE_REL_IA64_SECREL22 0x000C +#define IMAGE_REL_IA64_SECREL64I 0x000D +#define IMAGE_REL_IA64_SECREL32 0x000E +// +#define IMAGE_REL_IA64_DIR32NB 0x0010 +#define IMAGE_REL_IA64_SREL14 0x0011 +#define IMAGE_REL_IA64_SREL22 0x0012 +#define IMAGE_REL_IA64_SREL32 0x0013 +#define IMAGE_REL_IA64_UREL32 0x0014 +#define IMAGE_REL_IA64_PCREL60X 0x0015 // This is always a BRL and never converted +#define IMAGE_REL_IA64_PCREL60B 0x0016 // If possible, convert to MBB bundle with NOP.B in slot 1 +#define IMAGE_REL_IA64_PCREL60F 0x0017 // If possible, convert to MFB bundle with NOP.F in slot 1 +#define IMAGE_REL_IA64_PCREL60I 0x0018 // If possible, convert to MIB bundle with NOP.I in slot 1 +#define IMAGE_REL_IA64_PCREL60M 0x0019 // If possible, convert to MMB bundle with NOP.M in slot 1 +#define IMAGE_REL_IA64_IMMGPREL64 0x001A +#define IMAGE_REL_IA64_TOKEN 0x001B // clr token +#define IMAGE_REL_IA64_GPREL32 0x001C +#define IMAGE_REL_IA64_ADDEND 0x001F + +// +// CEF relocation types. +// +#define IMAGE_REL_CEF_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_CEF_ADDR32 0x0001 // 32-bit address (VA). +#define IMAGE_REL_CEF_ADDR64 0x0002 // 64-bit address (VA). +#define IMAGE_REL_CEF_ADDR32NB 0x0003 // 32-bit address w/o image base (RVA). +#define IMAGE_REL_CEF_SECTION 0x0004 // Section index +#define IMAGE_REL_CEF_SECREL 0x0005 // 32 bit offset from base of section containing target +#define IMAGE_REL_CEF_TOKEN 0x0006 // 32 bit metadata token + +// +// clr relocation types. +// +#define IMAGE_REL_CEE_ABSOLUTE 0x0000 // Reference is absolute, no relocation is necessary +#define IMAGE_REL_CEE_ADDR32 0x0001 // 32-bit address (VA). +#define IMAGE_REL_CEE_ADDR64 0x0002 // 64-bit address (VA). +#define IMAGE_REL_CEE_ADDR32NB 0x0003 // 32-bit address w/o image base (RVA). +#define IMAGE_REL_CEE_SECTION 0x0004 // Section index +#define IMAGE_REL_CEE_SECREL 0x0005 // 32 bit offset from base of section containing target +#define IMAGE_REL_CEE_TOKEN 0x0006 // 32 bit metadata token + + +#define IMAGE_REL_M32R_ABSOLUTE 0x0000 // No relocation required +#define IMAGE_REL_M32R_ADDR32 0x0001 // 32 bit address +#define IMAGE_REL_M32R_ADDR32NB 0x0002 // 32 bit address w/o image base +#define IMAGE_REL_M32R_ADDR24 0x0003 // 24 bit address +#define IMAGE_REL_M32R_GPREL16 0x0004 // GP relative addressing +#define IMAGE_REL_M32R_PCREL24 0x0005 // 24 bit offset << 2 & sign ext. +#define IMAGE_REL_M32R_PCREL16 0x0006 // 16 bit offset << 2 & sign ext. +#define IMAGE_REL_M32R_PCREL8 0x0007 // 8 bit offset << 2 & sign ext. +#define IMAGE_REL_M32R_REFHALF 0x0008 // 16 MSBs +#define IMAGE_REL_M32R_REFHI 0x0009 // 16 MSBs; adj for LSB sign ext. +#define IMAGE_REL_M32R_REFLO 0x000A // 16 LSBs +#define IMAGE_REL_M32R_PAIR 0x000B // Link HI and LO +#define IMAGE_REL_M32R_SECTION 0x000C // Section table index +#define IMAGE_REL_M32R_SECREL32 0x000D // 32 bit section relative reference +#define IMAGE_REL_M32R_TOKEN 0x000E // clr token + + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) /* Intel-IA64-Filler */ \ + Value |= (((ULONGLONG)((*(Address) >> InstPos) & (((ULONGLONG)1 << Size) - 1))) << ValPos) // Intel-IA64-Filler + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) /* Intel-IA64-Filler */\ + *(PULONG)Address = (*(PULONG)Address & ~(((1 << Size) - 1) << InstPos)) | /* Intel-IA64-Filler */\ + ((ULONG)((((ULONGLONG)Value >> ValPos) & (((ULONGLONG)1 << Size) - 1))) << InstPos) // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM7B_INST_WORD_X 3 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM7B_SIZE_X 7 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM7B_INST_WORD_POS_X 4 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM7B_VAL_POS_X 0 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM9D_INST_WORD_X 3 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM9D_SIZE_X 9 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM9D_INST_WORD_POS_X 18 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM9D_VAL_POS_X 7 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM5C_INST_WORD_X 3 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM5C_SIZE_X 5 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM5C_INST_WORD_POS_X 13 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM5C_VAL_POS_X 16 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IC_INST_WORD_X 3 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IC_SIZE_X 1 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IC_INST_WORD_POS_X 12 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IC_VAL_POS_X 21 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM41a_INST_WORD_X 1 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41a_SIZE_X 10 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41a_INST_WORD_POS_X 14 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41a_VAL_POS_X 22 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM41b_INST_WORD_X 1 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41b_SIZE_X 8 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41b_INST_WORD_POS_X 24 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41b_VAL_POS_X 32 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_IMM41c_INST_WORD_X 2 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41c_SIZE_X 23 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41c_INST_WORD_POS_X 0 // Intel-IA64-Filler +#define EMARCH_ENC_I17_IMM41c_VAL_POS_X 40 // Intel-IA64-Filler + +#define EMARCH_ENC_I17_SIGN_INST_WORD_X 3 // Intel-IA64-Filler +#define EMARCH_ENC_I17_SIGN_SIZE_X 1 // Intel-IA64-Filler +#define EMARCH_ENC_I17_SIGN_INST_WORD_POS_X 27 // Intel-IA64-Filler +#define EMARCH_ENC_I17_SIGN_VAL_POS_X 63 // Intel-IA64-Filler + + +// +// Line number format. +// + +typedef struct _IMAGE_LINENUMBER { + union { + ULONG SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + ULONG VirtualAddress; // Virtual address of line number. + } Type; + USHORT Linenumber; // Line number. +} IMAGE_LINENUMBER; +typedef IMAGE_LINENUMBER UNALIGNED *PIMAGE_LINENUMBER; + +#define IMAGE_SIZEOF_LINENUMBER 6 + +#ifndef _MAC +#include "poppack.h" // Back to 4 byte packing +#endif + +// +// Based relocation format. +// + +typedef struct _IMAGE_BASE_RELOCATION { + ULONG VirtualAddress; + ULONG SizeOfBlock; +// USHORT TypeOffset[1]; +} IMAGE_BASE_RELOCATION; +typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION; + +#define IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// + +#define IMAGE_REL_BASED_ABSOLUTE 0 +#define IMAGE_REL_BASED_HIGH 1 +#define IMAGE_REL_BASED_LOW 2 +#define IMAGE_REL_BASED_HIGHLOW 3 +#define IMAGE_REL_BASED_HIGHADJ 4 +#define IMAGE_REL_BASED_MACHINE_SPECIFIC_5 5 +#define IMAGE_REL_BASED_RESERVED 6 +#define IMAGE_REL_BASED_MACHINE_SPECIFIC_7 7 +#define IMAGE_REL_BASED_MACHINE_SPECIFIC_8 8 +#define IMAGE_REL_BASED_MACHINE_SPECIFIC_9 9 +#define IMAGE_REL_BASED_DIR64 10 + +// +// Platform-specific based relocation types. +// + +#define IMAGE_REL_BASED_IA64_IMM64 9 + +#define IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define IMAGE_REL_BASED_MIPS_JMPADDR16 9 + +#define IMAGE_REL_BASED_ARM_MOV32 5 +#define IMAGE_REL_BASED_THUMB_MOV32 7 + +// +// Archive format. +// + +#define IMAGE_ARCHIVE_START_SIZE 8 +#define IMAGE_ARCHIVE_START "!\n" +#define IMAGE_ARCHIVE_END "`\n" +#define IMAGE_ARCHIVE_PAD "\n" +#define IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER { + UCHAR Name[16]; // File member name - `/' terminated. + UCHAR Date[12]; // File member date - decimal. + UCHAR UserID[6]; // File member user id - decimal. + UCHAR GroupID[6]; // File member group id - decimal. + UCHAR Mode[8]; // File member mode - octal. + UCHAR Size[10]; // File member size - decimal. + UCHAR EndHeader[2]; // String to end header. +} IMAGE_ARCHIVE_MEMBER_HEADER, *PIMAGE_ARCHIVE_MEMBER_HEADER; + +#define IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +// +// Export Format +// + +typedef struct _IMAGE_EXPORT_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG Name; + ULONG Base; + ULONG NumberOfFunctions; + ULONG NumberOfNames; + ULONG AddressOfFunctions; // RVA from base of image + ULONG AddressOfNames; // RVA from base of image + ULONG AddressOfNameOrdinals; // RVA from base of image +} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; + +// +// Import Format +// + +typedef struct _IMAGE_IMPORT_BY_NAME { + USHORT Hint; + UCHAR Name[1]; +} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; + +#include "pshpack8.h" // Use align 8 for the 64-bit IAT. + +typedef struct _IMAGE_THUNK_DATA64 { + union { + ULONGLONG ForwarderString; // PUCHAR + ULONGLONG Function; // PULONG + ULONGLONG Ordinal; + ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA64; +typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64; + +#include "poppack.h" // Back to 4 byte packing + +typedef struct _IMAGE_THUNK_DATA32 { + union { + ULONG ForwarderString; // PUCHAR + ULONG Function; // PULONG + ULONG Ordinal; + ULONG AddressOfData; // PIMAGE_IMPORT_BY_NAME + } u1; +} IMAGE_THUNK_DATA32; +typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32; + +#define IMAGE_ORDINAL_FLAG64 0x8000000000000000 +#define IMAGE_ORDINAL_FLAG32 0x80000000 +#define IMAGE_ORDINAL64(Ordinal) (Ordinal & 0xffff) +#define IMAGE_ORDINAL32(Ordinal) (Ordinal & 0xffff) +#define IMAGE_SNAP_BY_ORDINAL64(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG64) != 0) +#define IMAGE_SNAP_BY_ORDINAL32(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG32) != 0) + +// +// Thread Local Storage +// + +#ifdef _MSC_VER +typedef VOID +(NTAPI *PIMAGE_TLS_CALLBACK) ( + PVOID DllHandle, + ULONG Reason, + PVOID Reserved + ); +#endif + +typedef struct _IMAGE_TLS_DIRECTORY64 { + ULONGLONG StartAddressOfRawData; + ULONGLONG EndAddressOfRawData; + ULONGLONG AddressOfIndex; // PULONG + ULONGLONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; + ULONG SizeOfZeroFill; + ULONG Characteristics; +} IMAGE_TLS_DIRECTORY64; +typedef IMAGE_TLS_DIRECTORY64 * PIMAGE_TLS_DIRECTORY64; + +typedef struct _IMAGE_TLS_DIRECTORY32 { + ULONG StartAddressOfRawData; + ULONG EndAddressOfRawData; + ULONG AddressOfIndex; // PULONG + ULONG AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * + ULONG SizeOfZeroFill; + ULONG Characteristics; +} IMAGE_TLS_DIRECTORY32; +typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32; + +#ifdef _WIN64 +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG64 +#define IMAGE_ORDINAL(Ordinal) IMAGE_ORDINAL64(Ordinal) +typedef IMAGE_THUNK_DATA64 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA; +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) IMAGE_SNAP_BY_ORDINAL64(Ordinal) +typedef IMAGE_TLS_DIRECTORY64 IMAGE_TLS_DIRECTORY; +typedef PIMAGE_TLS_DIRECTORY64 PIMAGE_TLS_DIRECTORY; +#else +#define IMAGE_ORDINAL_FLAG IMAGE_ORDINAL_FLAG32 +#define IMAGE_ORDINAL(Ordinal) IMAGE_ORDINAL32(Ordinal) +typedef IMAGE_THUNK_DATA32 IMAGE_THUNK_DATA; +typedef PIMAGE_THUNK_DATA32 PIMAGE_THUNK_DATA; +#define IMAGE_SNAP_BY_ORDINAL(Ordinal) IMAGE_SNAP_BY_ORDINAL32(Ordinal) +typedef IMAGE_TLS_DIRECTORY32 IMAGE_TLS_DIRECTORY; +typedef PIMAGE_TLS_DIRECTORY32 PIMAGE_TLS_DIRECTORY; +#endif + +typedef struct _IMAGE_IMPORT_DESCRIPTOR { + union { + ULONG Characteristics; // 0 for terminating null import descriptor + ULONG OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) + } u; + ULONG TimeDateStamp; // 0 if not bound, + // -1 if bound, and real date\time stamp + // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) + // O.W. date/time stamp of DLL bound to (Old BIND) + + ULONG ForwarderChain; // -1 if no forwarders + ULONG Name; + ULONG FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) +} IMAGE_IMPORT_DESCRIPTOR; +typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR; + +// +// New format import descriptors pointed to by DataDirectory[ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ] +// + +typedef struct _IMAGE_BOUND_IMPORT_DESCRIPTOR { + ULONG TimeDateStamp; + USHORT OffsetModuleName; + USHORT NumberOfModuleForwarderRefs; +// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows +} IMAGE_BOUND_IMPORT_DESCRIPTOR, *PIMAGE_BOUND_IMPORT_DESCRIPTOR; + +typedef struct _IMAGE_BOUND_FORWARDER_REF { + ULONG TimeDateStamp; + USHORT OffsetModuleName; + USHORT Reserved; +} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; + +// +// Resource Format. +// + +// +// Resource directory consists of two counts, following by a variable length +// array of directory entries. The first count is the number of entries at +// beginning of the array that have actual names associated with each entry. +// The entries are in ascending order, case insensitive strings. The second +// count is the number of entries that immediately follow the named entries. +// This second count identifies the number of entries that have 16-bit integer +// Ids as their name. These entries are also sorted in ascending order. +// +// This structure allows fast lookup by either name or number, but for any +// given resource entry only one form of lookup is supported, not both. +// This is consistant with the syntax of the .RC file and the .RES file. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + USHORT NumberOfNamedEntries; + USHORT NumberOfIdEntries; +// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[]; +} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; + +#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000 +#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000 +// +// Each directory contains the 32-bit Name of the entry and an offset, +// relative to the beginning of the resource directory of the data associated +// with this directory entry. If the name of the entry is an actual text +// string instead of an integer Id, then the high order bit of the name field +// is set to one and the low order 31-bits are an offset, relative to the +// beginning of the resource directory of the string, which is of type +// IMAGE_RESOURCE_DIRECTORY_STRING. Otherwise the high bit is clear and the +// low-order 16-bits are the integer Id that identify this resource directory +// entry. If the directory entry is yet another resource directory (i.e. a +// subdirectory), then the high order bit of the offset field will be +// set to indicate this. Otherwise the high bit is clear and the offset +// field points to a resource data entry. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { + ULONG NameOffset:31; + ULONG NameIsString:1; + }; + ULONG Name; + USHORT Id; + }; + union { + ULONG OffsetToData; + struct { + ULONG OffsetToDirectory:31; + ULONG DataIsDirectory:1; + }; + }; +} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY; + +// +// For resource directory entries that have actual string names, the Name +// field of the directory entry points to an object of the following type. +// All of these string objects are stored together after the last resource +// directory entry and before the first resource data object. This minimizes +// the impact of these variable length objects on the alignment of the fixed +// size directory entry objects. +// + +typedef struct _IMAGE_RESOURCE_DIRECTORY_STRING { + USHORT Length; + CHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIRECTORY_STRING, *PIMAGE_RESOURCE_DIRECTORY_STRING; + + +typedef struct _IMAGE_RESOURCE_DIR_STRING_U { + USHORT Length; + WCHAR NameString[ 1 ]; +} IMAGE_RESOURCE_DIR_STRING_U, *PIMAGE_RESOURCE_DIR_STRING_U; + + +// +// Each resource data entry describes a leaf node in the resource directory +// tree. It contains an offset, relative to the beginning of the resource +// directory of the data for the resource, a size field that gives the number +// of bytes of data at that offset, a CodePage that should be used when +// decoding code point values within the resource data. Typically for new +// applications the code page would be the unicode code page. +// + +typedef struct _IMAGE_RESOURCE_DATA_ENTRY { + ULONG OffsetToData; + ULONG Size; + ULONG CodePage; + ULONG Reserved; +} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY; + +// +// Load Configuration Directory Entry +// + +typedef struct { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONG DeCommitFreeBlockThreshold; + ULONG DeCommitTotalFreeThreshold; + ULONG LockPrefixTable; // VA + ULONG MaximumAllocationSize; + ULONG VirtualMemoryThreshold; + ULONG ProcessHeapFlags; + ULONG ProcessAffinityMask; + USHORT CSDVersion; + USHORT Reserved1; + ULONG EditList; // VA + ULONG Reserved[ 1 ]; +} IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32; + +typedef struct { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG GlobalFlagsClear; + ULONG GlobalFlagsSet; + ULONG CriticalSectionDefaultTimeout; + ULONGLONG DeCommitFreeBlockThreshold; + ULONGLONG DeCommitTotalFreeThreshold; + ULONGLONG LockPrefixTable; // VA + ULONGLONG MaximumAllocationSize; + ULONGLONG VirtualMemoryThreshold; + ULONGLONG ProcessAffinityMask; + ULONG ProcessHeapFlags; + USHORT CSDVersion; + USHORT Reserved1; + ULONGLONG EditList; // VA + ULONG Reserved[ 2 ]; +} IMAGE_LOAD_CONFIG_DIRECTORY64, *PIMAGE_LOAD_CONFIG_DIRECTORY64; + +#ifdef _WIN64 +typedef IMAGE_LOAD_CONFIG_DIRECTORY64 IMAGE_LOAD_CONFIG_DIRECTORY; +typedef PIMAGE_LOAD_CONFIG_DIRECTORY64 PIMAGE_LOAD_CONFIG_DIRECTORY; +#else +typedef IMAGE_LOAD_CONFIG_DIRECTORY32 IMAGE_LOAD_CONFIG_DIRECTORY; +typedef PIMAGE_LOAD_CONFIG_DIRECTORY32 PIMAGE_LOAD_CONFIG_DIRECTORY; +#endif + +// +// WIN CE Exception table format +// + +// +// Function table entry format. Function table is pointed to by the +// IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry. +// + +typedef struct _IMAGE_CE_RUNTIME_FUNCTION_ENTRY { + ULONG FuncStart; + ULONG PrologLen : 8; + ULONG FuncLen : 22; + ULONG ThirtyTwoBit : 1; + ULONG ExceptionFlag : 1; +} IMAGE_CE_RUNTIME_FUNCTION_ENTRY, * PIMAGE_CE_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY { + ULONGLONG BeginAddress; + ULONGLONG EndAddress; + ULONGLONG ExceptionHandler; + ULONGLONG HandlerData; + ULONGLONG PrologEndAddress; +} IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + ULONG ExceptionHandler; + ULONG HandlerData; + ULONG PrologEndAddress; +} IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY, *PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY; + +typedef struct _IMAGE_RUNTIME_FUNCTION_ENTRY { + ULONG BeginAddress; + ULONG EndAddress; + ULONG UnwindInfoAddress; +} _IMAGE_RUNTIME_FUNCTION_ENTRY, *_PIMAGE_RUNTIME_FUNCTION_ENTRY; + +typedef _IMAGE_RUNTIME_FUNCTION_ENTRY IMAGE_IA64_RUNTIME_FUNCTION_ENTRY; +typedef _PIMAGE_RUNTIME_FUNCTION_ENTRY PIMAGE_IA64_RUNTIME_FUNCTION_ENTRY; + +#if defined(_AXP64_) + +typedef IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY IMAGE_AXP64_RUNTIME_FUNCTION_ENTRY; +typedef PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY PIMAGE_AXP64_RUNTIME_FUNCTION_ENTRY; +typedef IMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY IMAGE_RUNTIME_FUNCTION_ENTRY; +typedef PIMAGE_ALPHA64_RUNTIME_FUNCTION_ENTRY PIMAGE_RUNTIME_FUNCTION_ENTRY; + +#elif defined(_ALPHA_) + +typedef IMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY IMAGE_RUNTIME_FUNCTION_ENTRY; +typedef PIMAGE_ALPHA_RUNTIME_FUNCTION_ENTRY PIMAGE_RUNTIME_FUNCTION_ENTRY; + +#else + +typedef _IMAGE_RUNTIME_FUNCTION_ENTRY IMAGE_RUNTIME_FUNCTION_ENTRY; +typedef _PIMAGE_RUNTIME_FUNCTION_ENTRY PIMAGE_RUNTIME_FUNCTION_ENTRY; + +#endif + +// +// Debug Format +// + +typedef struct _IMAGE_DEBUG_DIRECTORY { + ULONG Characteristics; + ULONG TimeDateStamp; + USHORT MajorVersion; + USHORT MinorVersion; + ULONG Type; + ULONG SizeOfData; + ULONG AddressOfRawData; + ULONG PointerToRawData; +} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; + +#define IMAGE_DEBUG_TYPE_UNKNOWN 0 +#define IMAGE_DEBUG_TYPE_COFF 1 +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_FPO 3 +#define IMAGE_DEBUG_TYPE_MISC 4 +#define IMAGE_DEBUG_TYPE_EXCEPTION 5 +#define IMAGE_DEBUG_TYPE_FIXUP 6 +#define IMAGE_DEBUG_TYPE_OMAP_TO_SRC 7 +#define IMAGE_DEBUG_TYPE_OMAP_FROM_SRC 8 +#define IMAGE_DEBUG_TYPE_BORLAND 9 +#define IMAGE_DEBUG_TYPE_RESERVED10 10 +#define IMAGE_DEBUG_TYPE_CLSID 11 + +// end_winnt + +// + +// begin_winnt + +typedef struct _IMAGE_COFF_SYMBOLS_HEADER { + ULONG NumberOfSymbols; + ULONG LvaToFirstSymbol; + ULONG NumberOfLinenumbers; + ULONG LvaToFirstLinenumber; + ULONG RvaToFirstByteOfCode; + ULONG RvaToLastByteOfCode; + ULONG RvaToFirstByteOfData; + ULONG RvaToLastByteOfData; +} IMAGE_COFF_SYMBOLS_HEADER, *PIMAGE_COFF_SYMBOLS_HEADER; + +#define FRAME_FPO 0 +#define FRAME_TRAP 1 +#define FRAME_TSS 2 +#define FRAME_NONFPO 3 + +typedef struct _FPO_DATA { + ULONG ulOffStart; // offset 1st byte of function code + ULONG cbProcSize; // # bytes in function + ULONG cdwLocals; // # bytes in locals/4 + USHORT cdwParams; // # bytes in params/4 + USHORT cbProlog : 8; // # bytes in prolog + USHORT cbRegs : 3; // # regs saved + USHORT fHasSEH : 1; // TRUE if SEH in func + USHORT fUseBP : 1; // TRUE if EBP has been allocated + USHORT reserved : 1; // reserved for future use + USHORT cbFrame : 2; // frame type +} FPO_DATA, *PFPO_DATA; +#define SIZEOF_RFPO_DATA 16 + + +#define IMAGE_DEBUG_MISC_EXENAME 1 + +typedef struct _IMAGE_DEBUG_MISC { + ULONG DataType; // type of misc data, see defines + ULONG Length; // total length of record, rounded to four + // byte multiple. + BOOLEAN Unicode; // TRUE if data is unicode string + UCHAR Reserved[ 3 ]; + UCHAR Data[ 1 ]; // Actual data +} IMAGE_DEBUG_MISC, *PIMAGE_DEBUG_MISC; + + +// +// Function table extracted from MIPS/ALPHA/IA64 images. Does not contain +// information needed only for runtime support. Just those fields for +// each entry needed by a debugger. +// + +typedef struct _IMAGE_FUNCTION_ENTRY { + ULONG StartingAddress; + ULONG EndingAddress; + ULONG EndOfPrologue; +} IMAGE_FUNCTION_ENTRY, *PIMAGE_FUNCTION_ENTRY; + +typedef struct _IMAGE_FUNCTION_ENTRY64 { + ULONGLONG StartingAddress; + ULONGLONG EndingAddress; + union { + ULONGLONG EndOfPrologue; + ULONGLONG UnwindInfoAddress; + } u; +} IMAGE_FUNCTION_ENTRY64, *PIMAGE_FUNCTION_ENTRY64; + +// +// Debugging information can be stripped from an image file and placed +// in a separate .DBG file, whose file name part is the same as the +// image file name part (e.g. symbols for CMD.EXE could be stripped +// and placed in CMD.DBG). This is indicated by the IMAGE_FILE_DEBUG_STRIPPED +// flag in the Characteristics field of the file header. The beginning of +// the .DBG file contains the following structure which captures certain +// information from the image file. This allows a debug to proceed even if +// the original image file is not accessable. This header is followed by +// zero of more IMAGE_SECTION_HEADER structures, followed by zero or more +// IMAGE_DEBUG_DIRECTORY structures. The latter structures and those in +// the image file contain file offsets relative to the beginning of the +// .DBG file. +// +// If symbols have been stripped from an image, the IMAGE_DEBUG_MISC structure +// is left in the image file, but not mapped. This allows a debugger to +// compute the name of the .DBG file, from the name of the image in the +// IMAGE_DEBUG_MISC structure. +// + +typedef struct _IMAGE_SEPARATE_DEBUG_HEADER { + USHORT Signature; + USHORT Flags; + USHORT Machine; + USHORT Characteristics; + ULONG TimeDateStamp; + ULONG CheckSum; + ULONG ImageBase; + ULONG SizeOfImage; + ULONG NumberOfSections; + ULONG ExportedNamesSize; + ULONG DebugDirectorySize; + ULONG SectionAlignment; + ULONG Reserved[2]; +} IMAGE_SEPARATE_DEBUG_HEADER, *PIMAGE_SEPARATE_DEBUG_HEADER; + +typedef struct _NON_PAGED_DEBUG_INFO { + USHORT Signature; + USHORT Flags; + ULONG Size; + USHORT Machine; + USHORT Characteristics; + ULONG TimeDateStamp; + ULONG CheckSum; + ULONG SizeOfImage; + ULONGLONG ImageBase; + //DebugDirectorySize + //IMAGE_DEBUG_DIRECTORY +} NON_PAGED_DEBUG_INFO, *PNON_PAGED_DEBUG_INFO; + +#ifndef _MAC +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4944 +#define NON_PAGED_DEBUG_SIGNATURE 0x494E +#else +#define IMAGE_SEPARATE_DEBUG_SIGNATURE 0x4449 // DI +#define NON_PAGED_DEBUG_SIGNATURE 0x4E49 // NI +#endif + +#define IMAGE_SEPARATE_DEBUG_FLAGS_MASK 0x8000 +#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the + // old checksum didn't match. + +// +// The .arch section is made up of headers, each describing an amask position/value +// pointing to an array of IMAGE_ARCHITECTURE_ENTRY's. Each "array" (both the header +// and entry arrays) are terminiated by a quadword of 0xffffffffL. +// +// NOTE: There may be quadwords of 0 sprinkled around and must be skipped. +// + +typedef struct _ImageArchitectureHeader { + unsigned int AmaskValue: 1; // 1 -> code section depends on mask bit + // 0 -> new instruction depends on mask bit + int :7; // MBZ + unsigned int AmaskShift: 8; // Amask bit in question for this fixup + int :16; // MBZ + ULONG FirstEntryRVA; // RVA into .arch section to array of ARCHITECTURE_ENTRY's +} IMAGE_ARCHITECTURE_HEADER, *PIMAGE_ARCHITECTURE_HEADER; + +typedef struct _ImageArchitectureEntry { + ULONG FixupInstRVA; // RVA of instruction to fixup + ULONG NewInst; // fixup instruction (see alphaops.h) +} IMAGE_ARCHITECTURE_ENTRY, *PIMAGE_ARCHITECTURE_ENTRY; + +#include "poppack.h" // Back to the initial value + +// The following structure defines the new import object. Note the values of the first two fields, +// which must be set as stated in order to differentiate old and new import members. +// Following this structure, the linker emits two null-terminated strings used to recreate the +// import at the time of use. The first string is the import's name, the second is the dll's name. + +#define IMPORT_OBJECT_HDR_SIG2 0xffff + +typedef struct IMPORT_OBJECT_HEADER { + USHORT Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN + USHORT Sig2; // Must be IMPORT_OBJECT_HDR_SIG2. + USHORT Version; + USHORT Machine; + ULONG TimeDateStamp; // Time/date stamp + ULONG SizeOfData; // particularly useful for incremental links + + union { + USHORT Ordinal; // if grf & IMPORT_OBJECT_ORDINAL + USHORT Hint; + } u; + + USHORT Type : 2; // IMPORT_TYPE + USHORT NameType : 3; // IMPORT_NAME_TYPE + USHORT Reserved : 11; // Reserved. Must be zero. +} IMPORT_OBJECT_HEADER; + +typedef enum IMPORT_OBJECT_TYPE +{ + IMPORT_OBJECT_CODE = 0, + IMPORT_OBJECT_DATA = 1, + IMPORT_OBJECT_CONST = 2, +} IMPORT_OBJECT_TYPE; + +typedef enum IMPORT_OBJECT_NAME_TYPE +{ + IMPORT_OBJECT_ORDINAL = 0, // Import by ordinal + IMPORT_OBJECT_NAME = 1, // Import name == public symbol name. + IMPORT_OBJECT_NAME_NO_PREFIX = 2, // Import name == public symbol name skipping leading ?, @, or optionally _. + IMPORT_OBJECT_NAME_UNDECORATE = 3, // Import name == public symbol name skipping leading ?, @, or optionally _ + // and truncating at first @ +} IMPORT_OBJECT_NAME_TYPE; + +// end_winnt + +// +// End Image Format +// + +// end_winnt + +#endif // _NTIMAGE_ diff --git a/lib/coreclr/src/pal/inc/rt/oaidl.h b/lib/coreclr/src/pal/inc/rt/oaidl.h new file mode 100644 index 0000000000..f5c9aa155d --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/oaidl.h @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: oaidl.h +// +// =========================================================================== + +#ifndef __OAIDL_H__ +#define __OAIDL_H__ + +#include "rpc.h" +#include "rpcndr.h" + +#include "unknwn.h" + +typedef struct tagEXCEPINFO { + WORD wCode; + WORD wReserved; + BSTR bstrSource; + BSTR bstrDescription; + BSTR bstrHelpFile; + DWORD dwHelpContext; + PVOID pvReserved; + HRESULT (__stdcall *pfnDeferredFillIn)(struct tagEXCEPINFO *); + SCODE scode; +} EXCEPINFO, * LPEXCEPINFO; + +typedef interface IErrorInfo IErrorInfo; +typedef /* [unique] */ IErrorInfo *LPERRORINFO; + +EXTERN_C const IID IID_IErrorInfo; + + interface + IErrorInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetGUID( + /* [out] */ GUID *pGUID) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSource( + /* [out] */ BSTR *pBstrSource) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDescription( + /* [out] */ BSTR *pBstrDescription) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHelpFile( + /* [out] */ BSTR *pBstrHelpFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHelpContext( + /* [out] */ DWORD *pdwHelpContext) = 0; + + }; + +typedef interface ICreateErrorInfo ICreateErrorInfo; + +EXTERN_C const IID IID_ICreateErrorInfo; + +typedef /* [unique] */ ICreateErrorInfo *LPCREATEERRORINFO; + + interface + ICreateErrorInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetGUID( + /* [in] */ REFGUID rguid) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSource( + /* [in] */ LPOLESTR szSource) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDescription( + /* [in] */ LPOLESTR szDescription) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetHelpFile( + /* [in] */ LPOLESTR szHelpFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetHelpContext( + /* [in] */ DWORD dwHelpContext) = 0; + + }; + +STDAPI +SetErrorInfo(ULONG dwReserved, IErrorInfo FAR* perrinfo); + +STDAPI +GetErrorInfo(ULONG dwReserved, IErrorInfo FAR* FAR* pperrinfo); + +STDAPI +CreateErrorInfo(ICreateErrorInfo FAR* FAR* pperrinfo); + + +typedef interface ISupportErrorInfo ISupportErrorInfo; + +typedef /* [unique] */ ISupportErrorInfo *LPSUPPORTERRORINFO; + +EXTERN_C const IID IID_ISupportErrorInfo; + + + interface + ISupportErrorInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE InterfaceSupportsErrorInfo( + /* [in] */ REFIID riid) = 0; + + }; + +#endif //__OAIDL_H__ diff --git a/lib/coreclr/src/pal/inc/rt/objbase.h b/lib/coreclr/src/pal/inc/rt/objbase.h new file mode 100644 index 0000000000..6b2693272a --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/objbase.h @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// dummy objbase.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/objidl.h b/lib/coreclr/src/pal/inc/rt/objidl.h new file mode 100644 index 0000000000..4586a557cf --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/objidl.h @@ -0,0 +1,293 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: objidl.h +// +// =========================================================================== +// simplified objidl.h for PAL + +#include "rpc.h" +#include "rpcndr.h" + +#include "unknwn.h" + +#ifndef __IEnumUnknown_INTERFACE_DEFINED__ +#define __IEnumUnknown_INTERFACE_DEFINED__ + +// 00000100-0000-0000-C000-000000000046 +EXTERN_C const IID IID_IEnumUnknown; + +interface IEnumUnknown : public IUnknown +{ +public: + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Next( + /* [annotation][in] */ + _In_ ULONG celt, + /* [annotation][out] */ + _Out_writes_to_(celt,*pceltFetched) IUnknown **rgelt, + /* [annotation][out] */ + _Out_opt_ ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ __RPC__deref_out_opt IEnumUnknown **ppenum) = 0; + +}; + +#endif /* __IEnumUnknown_INTERFACE_DEFINED__ */ + +#ifndef __ISequentialStream_INTERFACE_DEFINED__ +#define __ISequentialStream_INTERFACE_DEFINED__ + +// 0c733a30-2a1c-11ce-ade5-00aa0044773d +EXTERN_C const IID IID_ISequentialStream; + +interface ISequentialStream : public IUnknown +{ +public: + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Read( + /* [length_is][size_is][out] */ void *pv, + /* [in] */ ULONG cb, + /* [out] */ ULONG *pcbRead) = 0; + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Write( + /* [size_is][in] */ const void *pv, + /* [in] */ ULONG cb, + /* [out] */ ULONG *pcbWritten) = 0; + +}; + +#endif // __ISequentialStream_INTERFACE_DEFINED__ + + +#ifndef __IStream_INTERFACE_DEFINED__ +#define __IStream_INTERFACE_DEFINED__ + +typedef struct tagSTATSTG + { + LPOLESTR pwcsName; + DWORD type; + ULARGE_INTEGER cbSize; + FILETIME mtime; + FILETIME ctime; + FILETIME atime; + DWORD grfMode; + DWORD grfLocksSupported; + CLSID clsid; + DWORD grfStateBits; + DWORD reserved; + } STATSTG; + +typedef +enum tagSTGTY + { STGTY_STORAGE = 1, + STGTY_STREAM = 2, + STGTY_LOCKBYTES = 3, + STGTY_PROPERTY = 4 + } STGTY; + +typedef +enum tagSTREAM_SEEK + { STREAM_SEEK_SET = 0, + STREAM_SEEK_CUR = 1, + STREAM_SEEK_END = 2 + } STREAM_SEEK; + +typedef +enum tagLOCKTYPE + { LOCK_WRITE = 1, + LOCK_EXCLUSIVE = 2, + LOCK_ONLYONCE = 4 + } LOCKTYPE; + +typedef +enum tagSTATFLAG + { STATFLAG_DEFAULT = 0, + STATFLAG_NONAME = 1, + STATFLAG_NOOPEN = 2 + } STATFLAG; + +// 0000000c-0000-0000-C000-000000000046 +EXTERN_C const IID IID_IStream; + +interface DECLSPEC_UUID("0000000c-0000-0000-C000-000000000046") +IStream : public ISequentialStream +{ +public: + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Seek( + /* [in] */ LARGE_INTEGER dlibMove, + /* [in] */ DWORD dwOrigin, + /* [out] */ ULARGE_INTEGER *plibNewPosition) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSize( + /* [in] */ ULARGE_INTEGER libNewSize) = 0; + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE CopyTo( + /* [unique][in] */ IStream *pstm, + /* [in] */ ULARGE_INTEGER cb, + /* [out] */ ULARGE_INTEGER *pcbRead, + /* [out] */ ULARGE_INTEGER *pcbWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE Commit( + /* [in] */ DWORD grfCommitFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Revert( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE LockRegion( + /* [in] */ ULARGE_INTEGER libOffset, + /* [in] */ ULARGE_INTEGER cb, + /* [in] */ DWORD dwLockType) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnlockRegion( + /* [in] */ ULARGE_INTEGER libOffset, + /* [in] */ ULARGE_INTEGER cb, + /* [in] */ DWORD dwLockType) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stat( + /* [out] */ STATSTG *pstatstg, + /* [in] */ DWORD grfStatFlag) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IStream **ppstm) = 0; + +}; + +#endif // __IStream_INTERFACE_DEFINED__ + + +#ifndef __IStorage_INTERFACE_DEFINED__ +#define __IStorage_INTERFACE_DEFINED__ + +typedef OLECHAR **SNB; + +interface IEnumSTATSTG; + +// 0000000b-0000-0000-C000-000000000046 + +interface IStorage : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE CreateStream( + /* [string][in] */ const OLECHAR *pwcsName, + /* [in] */ DWORD grfMode, + /* [in] */ DWORD reserved1, + /* [in] */ DWORD reserved2, + /* [out] */ IStream **ppstm) = 0; + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE OpenStream( + /* [string][in] */ const OLECHAR *pwcsName, + /* [unique][in] */ void *reserved1, + /* [in] */ DWORD grfMode, + /* [in] */ DWORD reserved2, + /* [out] */ IStream **ppstm) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStorage( + /* [string][in] */ const OLECHAR *pwcsName, + /* [in] */ DWORD grfMode, + /* [in] */ DWORD reserved1, + /* [in] */ DWORD reserved2, + /* [out] */ IStorage **ppstg) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenStorage( + /* [string][unique][in] */ const OLECHAR *pwcsName, + /* [unique][in] */ IStorage *pstgPriority, + /* [in] */ DWORD grfMode, + /* [unique][in] */ SNB snbExclude, + /* [in] */ DWORD reserved, + /* [out] */ IStorage **ppstg) = 0; + + virtual HRESULT STDMETHODCALLTYPE CopyTo( + /* [in] */ DWORD ciidExclude, + /* [size_is][unique][in] */ const IID *rgiidExclude, + /* [unique][in] */ SNB snbExclude, + /* [unique][in] */ IStorage *pstgDest) = 0; + + virtual HRESULT STDMETHODCALLTYPE MoveElementTo( + /* [string][in] */ const OLECHAR *pwcsName, + /* [unique][in] */ IStorage *pstgDest, + /* [string][in] */ const OLECHAR *pwcsNewName, + /* [in] */ DWORD grfFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Commit( + /* [in] */ DWORD grfCommitFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Revert( void) = 0; + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE EnumElements( + /* [in] */ DWORD reserved1, + /* [size_is][unique][in] */ void *reserved2, + /* [in] */ DWORD reserved3, + /* [out] */ IEnumSTATSTG **ppenum) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyElement( + /* [string][in] */ const OLECHAR *pwcsName) = 0; + + virtual HRESULT STDMETHODCALLTYPE RenameElement( + /* [string][in] */ const OLECHAR *pwcsOldName, + /* [string][in] */ const OLECHAR *pwcsNewName) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetElementTimes( + /* [string][unique][in] */ const OLECHAR *pwcsName, + /* [unique][in] */ const FILETIME *pctime, + /* [unique][in] */ const FILETIME *patime, + /* [unique][in] */ const FILETIME *pmtime) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetClass( + /* [in] */ REFCLSID clsid) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetStateBits( + /* [in] */ DWORD grfStateBits, + /* [in] */ DWORD grfMask) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stat( + /* [out] */ STATSTG *pstatstg, + /* [in] */ DWORD grfStatFlag) = 0; + +}; + +#endif // __IStorage_INTERFACE_DEFINED__ + + +#ifndef __IMalloc_INTERFACE_DEFINED__ +#define __IMalloc_INTERFACE_DEFINED__ + +/* interface IMalloc */ +/* [uuid][object][local] */ + +// 0000001d-0000-0000-C000-000000000046 +EXTERN_C const IID IID_IMalloc; + +interface IMalloc : public IUnknown +{ +public: + virtual void *STDMETHODCALLTYPE Alloc( + /* [in] */ SIZE_T cb) = 0; + + virtual void *STDMETHODCALLTYPE Realloc( + /* [in] */ void *pv, + /* [in] */ SIZE_T cb) = 0; + + virtual void STDMETHODCALLTYPE Free( + /* [in] */ void *pv) = 0; + + virtual SIZE_T STDMETHODCALLTYPE GetSize( + /* [in] */ void *pv) = 0; + + virtual int STDMETHODCALLTYPE DidAlloc( + void *pv) = 0; + + virtual void STDMETHODCALLTYPE HeapMinimize( void) = 0; + +}; + +typedef /* [unique] */ IMalloc *LPMALLOC; + +#endif // __IMalloc_INTERFACE_DEFINED__ diff --git a/lib/coreclr/src/pal/inc/rt/ocidl.h b/lib/coreclr/src/pal/inc/rt/ocidl.h new file mode 100644 index 0000000000..ab6272e758 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/ocidl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: ocidl.h +// +// =========================================================================== +// dummy ocidl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/ole2.h b/lib/coreclr/src/pal/inc/rt/ole2.h new file mode 100644 index 0000000000..36a057fcf9 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/ole2.h @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// dummy ole2.h for PAL + +#include "objidl.h" +#include "servprov.h" +#include "oaidl.h" + diff --git a/lib/coreclr/src/pal/inc/rt/oleauto.h b/lib/coreclr/src/pal/inc/rt/oleauto.h new file mode 100644 index 0000000000..958476f482 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/oleauto.h @@ -0,0 +1,134 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: oleauto.h +// +// =========================================================================== +// simplified oleauto.h for PAL + +#ifndef _OLEAUTO_H_ +#define _OLEAUTO_H_ +#include "oaidl.h" + +#ifndef BEGIN_INTERFACE +#define BEGIN_INTERFACE +#define END_INTERFACE +#endif + +// OleAut's VT_CY and VT_DECIMAL declarations required by System.Decimal and System.Currency + +typedef struct { + INT cDig; + ULONG dwInFlags; + ULONG dwOutFlags; + INT cchUsed; + INT nBaseShift; + INT nPwr10; +} NUMPARSE; + +#define NUMPRS_STD 0x1FFF + +/* flags used by both dwInFlags and dwOutFlags: + */ +#define NUMPRS_LEADING_WHITE 0x0001 +#define NUMPRS_TRAILING_WHITE 0x0002 +#define NUMPRS_LEADING_PLUS 0x0004 +#define NUMPRS_TRAILING_PLUS 0x0008 +#define NUMPRS_LEADING_MINUS 0x0010 +#define NUMPRS_TRAILING_MINUS 0x0020 +#define NUMPRS_HEX_OCT 0x0040 +#define NUMPRS_PARENS 0x0080 +#define NUMPRS_DECIMAL 0x0100 +#define NUMPRS_THOUSANDS 0x0200 +#define NUMPRS_CURRENCY 0x0400 +#define NUMPRS_EXPONENT 0x0800 +#define NUMPRS_USE_ALL 0x1000 + +/* flags used by dwOutFlags only: + */ +#define NUMPRS_NEG 0x10000 +#define NUMPRS_INEXACT 0x20000 +/* flags used by VarNumFromParseNum to indicate acceptable result types: + */ +#define VTBIT_I1 (1 << VT_I1) +#define VTBIT_UI1 (1 << VT_UI1) +#define VTBIT_I2 (1 << VT_I2) +#define VTBIT_UI2 (1 << VT_UI2) +#define VTBIT_I4 (1 << VT_I4) +#define VTBIT_UI4 (1 << VT_UI4) +#define VTBIT_I8 (1 << VT_I8) +#define VTBIT_UI8 (1 << VT_UI8) +#define VTBIT_R4 (1 << VT_R4) +#define VTBIT_R8 (1 << VT_R8) +#define VTBIT_CY (1 << VT_CY) +#define VTBIT_DECIMAL (1 << VT_DECIMAL) + +#define LOCALE_NOUSEROVERRIDE 0x80000000 /* OR in to avoid user override */ +/* + * Use NLS functions to format date, currency, time, and number. + */ +#ifndef LOCALE_USE_NLS +#define LOCALE_USE_NLS 0x10000000 +#endif + +// Compare results for VarDecCmp. These are returned as a SUCCESS HResult. +// Subtracting one gives the usual values of -1 for Less Than, +// 0 for Equal To, +1 for Greater Than. +// +#define VARCMP_LT 0 +#define VARCMP_EQ 1 +#define VARCMP_GT 2 +#define VARCMP_NULL 3 + +STDAPI VariantChangeType(VARIANTARG * pvargDest, + VARIANTARG * pvarSrc, USHORT wFlags, VARTYPE vt); + +STDAPI VarCyFromR4(FLOAT fltIn, CY * pcyOut); +STDAPI VarCyFromR8(DOUBLE dblIn, CY * pcyOut); +STDAPI VarCyFromDec(DECIMAL *pdecIn, CY *pcyOut); +STDAPI VarCyAdd(CY cyLeft, CY cyRight, LPCY pcyResult); +STDAPI VarCySub(CY cyLeft, CY cyRight, LPCY pcyResult); +STDAPI VarCyMul(CY cyLeft, CY cyRight, LPCY pcyResult); +STDAPI VarCyInt(CY cyIn, LPCY pcyResult); +STDAPI VarCyRound(CY cyIn, INT cDecimals, LPCY pcyResult); +STDAPI VarCyFix(CY cyIn, LPCY pcyResult); + +STDAPI VarR8FromCy(CY cyIn, DOUBLE * pdblOut); +STDAPI VarR4FromCy(CY cyIn, FLOAT * pfltOut); + +STDAPI VarDecFromR4(FLOAT fltIn, DECIMAL *pdecOut); +STDAPI VarDecFromR8(DOUBLE dblIn, DECIMAL *pdecOut); +STDAPI VarDecFromCy(CY cyIn, DECIMAL *pdecOut); +STDAPI VarDecAdd(LPDECIMAL pdecLeft, LPDECIMAL pdecRight, LPDECIMAL pdecResult); +STDAPI VarDecSub(LPDECIMAL pdecLeft, LPDECIMAL pdecRight, LPDECIMAL pdecResult); +STDAPI VarDecMul(LPDECIMAL pdecLeft, LPDECIMAL pdecRight, LPDECIMAL pdecResult); +STDAPI VarDecDiv(LPDECIMAL pdecLeft, LPDECIMAL pdecRight, LPDECIMAL pdecResult); +STDAPI VarDecCmp(LPDECIMAL pdecLeft, LPDECIMAL pdecRight); +STDAPI VarDecInt(LPDECIMAL pdecIn, LPDECIMAL pdecResult); +STDAPI VarDecRound(LPDECIMAL pdecIn, INT cDecimals, LPDECIMAL pdecResult); +STDAPI VarDecFix(LPDECIMAL pdecIn, LPDECIMAL pdecResult); +STDAPI VarDecNeg(LPDECIMAL pdecIn, LPDECIMAL pdecResult); +STDAPI VarDecFromI4(LONG I4in, DECIMAL *pdecOut); +STDAPI VarDecFromUI4(ULONG UI4in, DECIMAL *pdecOut); + +STDAPI VarI1FromDec(DECIMAL *pdecIn, CHAR *pI1In); +STDAPI VarUI1FromDec(DECIMAL *pdecIn, BYTE *pUI1In); +STDAPI VarI2FromDec(DECIMAL *pdecIn, SHORT *pI2In); +STDAPI VarUI2FromDec(DECIMAL *pdecIn, USHORT *pUI2In); +STDAPI VarI4FromDec(DECIMAL *pdecIn, LONG *pI4In); +STDAPI VarUI4FromDec(DECIMAL *pdecIn, ULONG *pUI4In); +STDAPI VarR8FromDec(DECIMAL *pdecIn, DOUBLE *pdblOut); +STDAPI VarR4FromDec(DECIMAL *pdecIn, FLOAT *pfltOut); + +STDAPI VarI1FromR8(DOUBLE dblIn, CHAR *pcOut); +STDAPI VarI2FromR8(DOUBLE dblIn, SHORT * psOut); +STDAPI VarI4FromR8(DOUBLE dblIn, LONG * plOut); +STDAPI VarUI1FromR8(DOUBLE dblIn, BYTE * pbOut); +STDAPI VarUI2FromR8(DOUBLE dblIn, USHORT *puiOut); +STDAPI VarUI4FromR8(DOUBLE dblIn, ULONG *pulOut); + +#endif // _OLEAUTO_H_ diff --git a/lib/coreclr/src/pal/inc/rt/olectl.h b/lib/coreclr/src/pal/inc/rt/olectl.h new file mode 100644 index 0000000000..94b093f017 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/olectl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: olectl.h +// +// =========================================================================== +// dummy olectl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/oleidl.h b/lib/coreclr/src/pal/inc/rt/oleidl.h new file mode 100644 index 0000000000..301692ea75 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/oleidl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: oleidl.h +// +// =========================================================================== +// simplified oleidl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/palrt.h b/lib/coreclr/src/pal/inc/rt/palrt.h new file mode 100644 index 0000000000..6502cf5891 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/palrt.h @@ -0,0 +1,1536 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: palrt.h +// +// =========================================================================== + +/*++ + + +Abstract: + + PAL runtime functions. These are functions which are ordinarily + implemented as part of the Win32 API set, but when compiling CoreCLR for + Unix-like systems, are implemented as a runtime library on top of the PAL. + +Author: + + + +Revision History: + +--*/ + +#ifndef __PALRT_H__ +#define __PALRT_H__ + +/******************* HRESULTs *********************************************/ + +#ifdef RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) _sc +#else // RC_INVOKED +#define _HRESULT_TYPEDEF_(_sc) ((HRESULT)_sc) +#endif // RC_INVOKED + +#define S_OK _HRESULT_TYPEDEF_(0x00000000L) +#define S_FALSE _HRESULT_TYPEDEF_(0x00000001L) + +#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L) +#define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L) +#define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFFL) +#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL) +#define E_INVALIDARG _HRESULT_TYPEDEF_(0x80070057L) +#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L) +#define E_HANDLE _HRESULT_TYPEDEF_(0x80070006L) +#define E_ABORT _HRESULT_TYPEDEF_(0x80004004L) +#define E_FAIL _HRESULT_TYPEDEF_(0x80004005L) +#define E_ACCESSDENIED _HRESULT_TYPEDEF_(0x80070005L) +#define E_PENDING _HRESULT_TYPEDEF_(0x8000000AL) + +#define DISP_E_PARAMNOTFOUND _HRESULT_TYPEDEF_(0x80020004L) +#define DISP_E_TYPEMISMATCH _HRESULT_TYPEDEF_(0x80020005L) +#define DISP_E_BADVARTYPE _HRESULT_TYPEDEF_(0x80020008L) +#define DISP_E_OVERFLOW _HRESULT_TYPEDEF_(0x8002000AL) +#define DISP_E_DIVBYZERO _HRESULT_TYPEDEF_(0x80020012L) + +#define CLASS_E_CLASSNOTAVAILABLE _HRESULT_TYPEDEF_(0x80040111L) +#define CLASS_E_NOAGGREGATION _HRESULT_TYPEDEF_(0x80040110L) + +#define CO_E_CLASSSTRING _HRESULT_TYPEDEF_(0x800401F3L) + +#define MK_E_SYNTAX _HRESULT_TYPEDEF_(0x800401E4L) + +#define STG_E_INVALIDFUNCTION _HRESULT_TYPEDEF_(0x80030001L) +#define STG_E_FILENOTFOUND _HRESULT_TYPEDEF_(0x80030002L) +#define STG_E_PATHNOTFOUND _HRESULT_TYPEDEF_(0x80030003L) +#define STG_E_WRITEFAULT _HRESULT_TYPEDEF_(0x8003001DL) +#define STG_E_FILEALREADYEXISTS _HRESULT_TYPEDEF_(0x80030050L) +#define STG_E_ABNORMALAPIEXIT _HRESULT_TYPEDEF_(0x800300FAL) + +#define NTE_BAD_UID _HRESULT_TYPEDEF_(0x80090001L) +#define NTE_BAD_HASH _HRESULT_TYPEDEF_(0x80090002L) +#define NTE_BAD_KEY _HRESULT_TYPEDEF_(0x80090003L) +#define NTE_BAD_LEN _HRESULT_TYPEDEF_(0x80090004L) +#define NTE_BAD_DATA _HRESULT_TYPEDEF_(0x80090005L) +#define NTE_BAD_SIGNATURE _HRESULT_TYPEDEF_(0x80090006L) +#define NTE_BAD_VER _HRESULT_TYPEDEF_(0x80090007L) +#define NTE_BAD_ALGID _HRESULT_TYPEDEF_(0x80090008L) +#define NTE_BAD_FLAGS _HRESULT_TYPEDEF_(0x80090009L) +#define NTE_BAD_TYPE _HRESULT_TYPEDEF_(0x8009000AL) +#define NTE_BAD_KEY_STATE _HRESULT_TYPEDEF_(0x8009000BL) +#define NTE_BAD_HASH_STATE _HRESULT_TYPEDEF_(0x8009000CL) +#define NTE_NO_KEY _HRESULT_TYPEDEF_(0x8009000DL) +#define NTE_NO_MEMORY _HRESULT_TYPEDEF_(0x8009000EL) +#define NTE_SIGNATURE_FILE_BAD _HRESULT_TYPEDEF_(0x8009001CL) +#define NTE_FAIL _HRESULT_TYPEDEF_(0x80090020L) + +#define CRYPT_E_HASH_VALUE _HRESULT_TYPEDEF_(0x80091007L) + +#define TYPE_E_SIZETOOBIG _HRESULT_TYPEDEF_(0x800288C5L) +#define TYPE_E_DUPLICATEID _HRESULT_TYPEDEF_(0x800288C6L) + +#define STD_CTL_SCODE(n) MAKE_SCODE(SEVERITY_ERROR, FACILITY_CONTROL, n) +#define CTL_E_OVERFLOW STD_CTL_SCODE(6) +#define CTL_E_OUTOFMEMORY STD_CTL_SCODE(7) +#define CTL_E_DIVISIONBYZERO STD_CTL_SCODE(11) +#define CTL_E_OUTOFSTACKSPACE STD_CTL_SCODE(28) +#define CTL_E_FILENOTFOUND STD_CTL_SCODE(53) +#define CTL_E_DEVICEIOERROR STD_CTL_SCODE(57) +#define CTL_E_PERMISSIONDENIED STD_CTL_SCODE(70) +#define CTL_E_PATHFILEACCESSERROR STD_CTL_SCODE(75) +#define CTL_E_PATHNOTFOUND STD_CTL_SCODE(76) + +#define INET_E_CANNOT_CONNECT _HRESULT_TYPEDEF_(0x800C0004L) +#define INET_E_RESOURCE_NOT_FOUND _HRESULT_TYPEDEF_(0x800C0005L) +#define INET_E_OBJECT_NOT_FOUND _HRESULT_TYPEDEF_(0x800C0006L) +#define INET_E_DATA_NOT_AVAILABLE _HRESULT_TYPEDEF_(0x800C0007L) +#define INET_E_DOWNLOAD_FAILURE _HRESULT_TYPEDEF_(0x800C0008L) +#define INET_E_CONNECTION_TIMEOUT _HRESULT_TYPEDEF_(0x800C000BL) +#define INET_E_UNKNOWN_PROTOCOL _HRESULT_TYPEDEF_(0x800C000DL) + +#define DBG_PRINTEXCEPTION_C _HRESULT_TYPEDEF_(0x40010006L) + +/********************** errorrep.h ****************************************/ + +typedef enum tagEFaultRepRetVal +{ + frrvOk = 0, + frrvOkManifest, + frrvOkQueued, + frrvErr, + frrvErrNoDW, + frrvErrTimeout, + frrvLaunchDebugger, + frrvOkHeadless, + frrvErrAnotherInstance +} EFaultRepRetVal; + +/**************************************************************************/ + +#ifndef RC_INVOKED + +#include "pal.h" + +#ifndef PAL_STDCPP_COMPAT +#ifdef __cplusplus +#ifndef __PLACEMENT_NEW_INLINE +#define __PLACEMENT_NEW_INLINE +inline void *__cdecl operator new(size_t, void *_P) +{ + return (_P); +} +#endif // __PLACEMENT_NEW_INLINE +#endif // __cplusplus +#endif // !PAL_STDCPP_COMPAT + +#include + +#define NTAPI __cdecl +#define WINAPI __cdecl +#define CALLBACK __cdecl +#define NTSYSAPI + +#define _WINNT_ + +// C++ standard, 18.1.5 - offsetof requires a POD (plain old data) struct or +// union. Since offsetof is a macro, gcc doesn't actually check for improper +// use of offsetof, it keys off of the -> from NULL (which is also invalid for +// non-POD types by 18.1.5) +// +// As we have numerous examples of this behavior in our codebase, +// making an offsetof which doesn't use 0. + +// PAL_safe_offsetof is a version of offsetof that protects against an +// overridden operator& + +#define FIELD_OFFSET(type, field) __builtin_offsetof(type, field) +#ifndef offsetof +#define offsetof(type, field) __builtin_offsetof(type, field) +#endif +#define PAL_safe_offsetof(type, field) __builtin_offsetof(type, field) + +#define CONTAINING_RECORD(address, type, field) \ + ((type *)((LONG_PTR)(address) - FIELD_OFFSET(type, field))) + +#define ARGUMENT_PRESENT(ArgumentPointer) (\ + (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) ) + +#if defined(_WIN64) +#define MAX_NATURAL_ALIGNMENT sizeof(ULONGLONG) +#else +#define MAX_NATURAL_ALIGNMENT sizeof(ULONG) +#endif + +#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name + +#ifndef COM_NO_WINDOWS_H +#define COM_NO_WINDOWS_H +#endif + +#define interface struct + +#define STDMETHODCALLTYPE __cdecl +#define STDMETHODVCALLTYPE __cdecl + +#define STDAPICALLTYPE __cdecl +#define STDAPIVCALLTYPE __cdecl + +#define STDMETHODIMP HRESULT STDMETHODCALLTYPE +#define STDMETHODIMP_(type) type STDMETHODCALLTYPE + +#define STDMETHODIMPV HRESULT STDMETHODVCALLTYPE +#define STDMETHODIMPV_(type) type STDMETHODVCALLTYPE + +#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method +#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method + +#define STDMETHODV(method) virtual HRESULT STDMETHODVCALLTYPE method +#define STDMETHODV_(type,method) virtual type STDMETHODVCALLTYPE method + +#define STDAPI EXTERN_C HRESULT STDAPICALLTYPE +#define STDAPI_(type) EXTERN_C type STDAPICALLTYPE +#define STDAPI_VIS(vis,type) EXTERN_C vis type STDAPICALLTYPE + +#define STDAPIV EXTERN_C HRESULT STDAPIVCALLTYPE +#define STDAPIV_(type) EXTERN_C type STDAPIVCALLTYPE + +#define PURE = 0 +#define THIS_ +#define THIS void + +#ifndef _DECLSPEC_DEFINED_ +#define _DECLSPEC_DEFINED_ + +#if defined(_MSC_VER) +#define DECLSPEC_NOVTABLE __declspec(novtable) +#define DECLSPEC_IMPORT __declspec(dllimport) +#define DECLSPEC_SELECTANY __declspec(selectany) +#elif defined(__GNUC__) +#define DECLSPEC_NOVTABLE +#define DECLSPEC_IMPORT +#define DECLSPEC_SELECTANY __attribute__((weak)) +#else +#define DECLSPEC_NOVTABLE +#define DECLSPEC_IMPORT +#define DECLSPEC_SELECTANY +#endif + +#endif // !_DECLSPEC_DEFINED_ + +#define DECLARE_INTERFACE(iface) interface DECLSPEC_NOVTABLE iface +#define DECLARE_INTERFACE_(iface, baseiface) interface DECLSPEC_NOVTABLE iface : public baseiface + +#ifdef __cplusplus +#define REFGUID const GUID & +#else +#define REFGUID const GUID * +#endif + +EXTERN_C const GUID GUID_NULL; + +typedef GUID *LPGUID; +typedef const GUID FAR *LPCGUID; + +#ifdef __cplusplus +extern "C++" { +#if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_ +#define _SYS_GUID_OPERATOR_EQ_ +inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2) + { return !memcmp(&rguid1, &rguid2, sizeof(GUID)); } +inline int operator==(REFGUID guidOne, REFGUID guidOther) + { return IsEqualGUID(guidOne,guidOther); } +inline int operator!=(REFGUID guidOne, REFGUID guidOther) + { return !IsEqualGUID(guidOne,guidOther); } +#endif +}; +#endif // __cplusplus + +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + EXTERN_C const GUID FAR name + +typedef GUID IID; +#ifdef __cplusplus +#define REFIID const IID & +#else +#define REFIID const IID * +#endif +#define IID_NULL GUID_NULL +#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2) + +#define __IID_DEFINED__ + +typedef GUID CLSID; +#define CLSID_DEFINED +#ifdef __cplusplus +#define REFCLSID const CLSID & +#else +#define REFCLSID const CLSID * +#endif +#define CLSID_NULL GUID_NULL +#define IsEqualCLSID(rclsid1, rclsid2) IsEqualGUID(rclsid1, rclsid2) +typedef CLSID *LPCLSID; + +typedef UINT_PTR WPARAM; +typedef LONG_PTR LRESULT; + +typedef LONG SCODE; + + +typedef union _ULARGE_INTEGER { + struct { +#if BIGENDIAN + DWORD HighPart; + DWORD LowPart; +#else + DWORD LowPart; + DWORD HighPart; +#endif + } +#ifndef PAL_STDCPP_COMPAT + u +#endif // PAL_STDCPP_COMPAT + ; + ULONGLONG QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +/******************* HRESULT types ****************************************/ + +#define FACILITY_WINDOWS 8 +#define FACILITY_URT 19 +#define FACILITY_UMI 22 +#define FACILITY_SXS 23 +#define FACILITY_STORAGE 3 +#define FACILITY_SSPI 9 +#define FACILITY_SCARD 16 +#define FACILITY_SETUPAPI 15 +#define FACILITY_SECURITY 9 +#define FACILITY_RPC 1 +#define FACILITY_WIN32 7 +#define FACILITY_CONTROL 10 +#define FACILITY_NULL 0 +#define FACILITY_MSMQ 14 +#define FACILITY_MEDIASERVER 13 +#define FACILITY_INTERNET 12 +#define FACILITY_ITF 4 +#define FACILITY_DPLAY 21 +#define FACILITY_DISPATCH 2 +#define FACILITY_COMPLUS 17 +#define FACILITY_CERT 11 +#define FACILITY_ACS 20 +#define FACILITY_AAF 18 + +#define NO_ERROR 0L + +#define SEVERITY_SUCCESS 0 +#define SEVERITY_ERROR 1 + +#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0) +#define FAILED(Status) ((HRESULT)(Status)<0) +#define IS_ERROR(Status) ((ULONG)(Status) >> 31 == SEVERITY_ERROR) // diff from win32 +#define HRESULT_CODE(hr) ((hr) & 0xFFFF) +#define SCODE_CODE(sc) ((sc) & 0xFFFF) +#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) +#define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff) +#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) +#define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1) + +// both macros diff from Win32 +#define MAKE_HRESULT(sev,fac,code) \ + ((HRESULT) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((ULONG)(code))) ) +#define MAKE_SCODE(sev,fac,code) \ + ((SCODE) (((ULONG)(sev)<<31) | ((ULONG)(fac)<<16) | ((LONG)(code))) ) + +#define FACILITY_NT_BIT 0x10000000 +#define HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) +#define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x) + +#define HRESULT_FROM_NT(x) ((HRESULT) ((x) | FACILITY_NT_BIT)) + +/******************* OLE, BSTR, VARIANT *************************/ + +STDAPI_VIS(DLLEXPORT, LPVOID) CoTaskMemAlloc(SIZE_T cb); +STDAPI_VIS(DLLEXPORT, LPVOID) CoTaskMemRealloc(LPVOID pv, SIZE_T cb); +STDAPI_VIS(DLLEXPORT, void) CoTaskMemFree(LPVOID pv); + +typedef SHORT VARIANT_BOOL; +#define VARIANT_TRUE ((VARIANT_BOOL)-1) +#define VARIANT_FALSE ((VARIANT_BOOL)0) + +typedef WCHAR OLECHAR; +typedef OLECHAR* LPOLESTR; +typedef const OLECHAR* LPCOLESTR; + +typedef WCHAR *BSTR; + +STDAPI_VIS(DLLEXPORT, BSTR) SysAllocString(const OLECHAR*); +STDAPI_VIS(DLLEXPORT, BSTR) SysAllocStringLen(const OLECHAR*, UINT); +STDAPI_VIS(DLLEXPORT, BSTR) SysAllocStringByteLen(const char *, UINT); +STDAPI_VIS(DLLEXPORT, void) SysFreeString(BSTR); +STDAPI_VIS(DLLEXPORT, UINT) SysStringLen(BSTR); +STDAPI_VIS(DLLEXPORT, UINT) SysStringByteLen(BSTR); + +typedef double DATE; + +typedef union tagCY { + struct { +#if BIGENDIAN + LONG Hi; + ULONG Lo; +#else + ULONG Lo; + LONG Hi; +#endif + } u; + LONGLONG int64; +} CY, *LPCY; + +typedef CY CURRENCY; + +typedef struct tagDEC { + // Decimal.cs treats the first two shorts as one long + // And they seriable the data so we need to little endian + // seriliazation + // The wReserved overlaps with Variant's vt member +#if BIGENDIAN + union { + struct { + BYTE sign; + BYTE scale; + } u; + USHORT signscale; + } u; + USHORT wReserved; +#else + USHORT wReserved; + union { + struct { + BYTE scale; + BYTE sign; + } u; + USHORT signscale; + } u; +#endif + ULONG Hi32; + union { + struct { + ULONG Lo32; + ULONG Mid32; + } v; + ULONGLONG Lo64; + } v; +} DECIMAL, *LPDECIMAL; + +#define DECIMAL_NEG ((BYTE)0x80) +#define DECIMAL_SCALE(dec) ((dec).u.u.scale) +#define DECIMAL_SIGN(dec) ((dec).u.u.sign) +#define DECIMAL_SIGNSCALE(dec) ((dec).u.signscale) +#define DECIMAL_LO32(dec) ((dec).v.v.Lo32) +#define DECIMAL_MID32(dec) ((dec).v.v.Mid32) +#define DECIMAL_HI32(dec) ((dec).Hi32) +#define DECIMAL_LO64_GET(dec) ((dec).v.Lo64) +#define DECIMAL_LO64_SET(dec,value) {(dec).v.Lo64 = value; } + +#define DECIMAL_SETZERO(dec) {DECIMAL_LO32(dec) = 0; DECIMAL_MID32(dec) = 0; DECIMAL_HI32(dec) = 0; DECIMAL_SIGNSCALE(dec) = 0;} + +typedef struct tagBLOB { + ULONG cbSize; + BYTE *pBlobData; +} BLOB, *LPBLOB; + +interface IStream; +interface IRecordInfo; + +typedef unsigned short VARTYPE; + +enum VARENUM { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_INT_PTR = 37, + VT_UINT_PTR = 38, + + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + + VT_VECTOR = 0x1000, + VT_ARRAY = 0x2000, + VT_BYREF = 0x4000, + VT_TYPEMASK = 0xfff, +}; + +typedef struct tagVARIANT VARIANT, *LPVARIANT; +typedef struct tagSAFEARRAY SAFEARRAY; + +struct tagVARIANT + { + union + { + struct + { +#if BIGENDIAN + // We need to make sure vt overlaps with DECIMAL's wReserved. + // See the DECIMAL type for details. + WORD wReserved1; + VARTYPE vt; +#else + VARTYPE vt; + WORD wReserved1; +#endif + WORD wReserved2; + WORD wReserved3; + union + { + LONGLONG llVal; + LONG lVal; + BYTE bVal; + SHORT iVal; + FLOAT fltVal; + DOUBLE dblVal; + VARIANT_BOOL boolVal; + SCODE scode; + CY cyVal; + DATE date; + BSTR bstrVal; + interface IUnknown *punkVal; + interface IDispatch *pdispVal; + SAFEARRAY *parray; + BYTE *pbVal; + SHORT *piVal; + LONG *plVal; + LONGLONG *pllVal; + FLOAT *pfltVal; + DOUBLE *pdblVal; + VARIANT_BOOL *pboolVal; + SCODE *pscode; + CY *pcyVal; + DATE *pdate; + BSTR *pbstrVal; + interface IUnknown **ppunkVal; + VARIANT *pvarVal; + PVOID byref; + CHAR cVal; + USHORT uiVal; + ULONG ulVal; + ULONGLONG ullVal; + INT intVal; + UINT uintVal; + DECIMAL *pdecVal; + CHAR *pcVal; + USHORT *puiVal; + ULONG *pulVal; + ULONGLONG *pullVal; + INT *pintVal; + UINT *puintVal; + struct __tagBRECORD + { + PVOID pvRecord; + interface IRecordInfo *pRecInfo; + } brecVal; + } n3; + } n2; + DECIMAL decVal; + } n1; + }; + +typedef VARIANT VARIANTARG, *LPVARIANTARG; + +STDAPI_(void) VariantInit(VARIANT * pvarg); +STDAPI_(HRESULT) VariantClear(VARIANT * pvarg); + +#define V_VT(X) ((X)->n1.n2.vt) +#define V_UNION(X, Y) ((X)->n1.n2.n3.Y) +#define V_RECORDINFO(X) ((X)->n1.n2.n3.brecVal.pRecInfo) +#define V_RECORD(X) ((X)->n1.n2.n3.brecVal.pvRecord) + +#define V_UI1(X) V_UNION(X, bVal) +#define V_UI1REF(X) V_UNION(X, pbVal) +#define V_I2(X) V_UNION(X, iVal) +#define V_I2REF(X) V_UNION(X, piVal) +#define V_I4(X) V_UNION(X, lVal) +#define V_I4REF(X) V_UNION(X, plVal) +#define V_I8(X) V_UNION(X, llVal) +#define V_I8REF(X) V_UNION(X, pllVal) +#define V_R4(X) V_UNION(X, fltVal) +#define V_R4REF(X) V_UNION(X, pfltVal) +#define V_R8(X) V_UNION(X, dblVal) +#define V_R8REF(X) V_UNION(X, pdblVal) +#define V_I1(X) V_UNION(X, cVal) +#define V_I1REF(X) V_UNION(X, pcVal) +#define V_UI2(X) V_UNION(X, uiVal) +#define V_UI2REF(X) V_UNION(X, puiVal) +#define V_UI4(X) V_UNION(X, ulVal) +#define V_UI4REF(X) V_UNION(X, pulVal) +#define V_UI8(X) V_UNION(X, ullVal) +#define V_UI8REF(X) V_UNION(X, pullVal) +#define V_INT(X) V_UNION(X, intVal) +#define V_INTREF(X) V_UNION(X, pintVal) +#define V_UINT(X) V_UNION(X, uintVal) +#define V_UINTREF(X) V_UNION(X, puintVal) +#define V_ARRAY(X) V_UNION(X, parray) + +#ifdef _WIN64 +#define V_INT_PTR(X) V_UNION(X, llVal) +#define V_UINT_PTR(X) V_UNION(X, ullVal) +#define V_INT_PTRREF(X) V_UNION(X, pllVal) +#define V_UINT_PTRREF(X) V_UNION(X, pullVal) +#else +#define V_INT_PTR(X) V_UNION(X, lVal) +#define V_UINT_PTR(X) V_UNION(X, ulVal) +#define V_INT_PTRREF(X) V_UNION(X, plVal) +#define V_UINT_PTRREF(X) V_UNION(X, pulVal) +#endif + +#define V_CY(X) V_UNION(X, cyVal) +#define V_CYREF(X) V_UNION(X, pcyVal) +#define V_DATE(X) V_UNION(X, date) +#define V_DATEREF(X) V_UNION(X, pdate) +#define V_BSTR(X) V_UNION(X, bstrVal) +#define V_BSTRREF(X) V_UNION(X, pbstrVal) +#define V_UNKNOWN(X) V_UNION(X, punkVal) +#define V_UNKNOWNREF(X) V_UNION(X, ppunkVal) +#define V_VARIANTREF(X) V_UNION(X, pvarVal) +#define V_DISPATCH(X) V_UNION(X, pdispVal) +#define V_ERROR(X) V_UNION(X, scode) +#define V_ERRORREF(X) V_UNION(X, pscode) +#define V_BOOL(X) V_UNION(X, boolVal) +#define V_BOOLREF(X) V_UNION(X, pboolVal) +#define V_BYREF(X) V_UNION(X, byref) + +#define V_DECIMAL(X) ((X)->n1.decVal) +#define V_DECIMALREF(X) V_UNION(X, pdecVal) + +#define V_ISBYREF(X) (V_VT(X)&VT_BYREF) + +STDAPI CreateStreamOnHGlobal(PVOID hGlobal, BOOL fDeleteOnRelease, interface IStream** ppstm); + +#define STGM_DIRECT 0x00000000L + +#define STGM_READ 0x00000000L +#define STGM_WRITE 0x00000001L +#define STGM_READWRITE 0x00000002L + +#define STGM_SHARE_DENY_NONE 0x00000040L +#define STGM_SHARE_DENY_READ 0x00000030L +#define STGM_SHARE_DENY_WRITE 0x00000020L +#define STGM_SHARE_EXCLUSIVE 0x00000010L + +#define STGM_DELETEONRELEASE 0x04000000L + +#define STGM_CREATE 0x00001000L +#define STGM_CONVERT 0x00020000L +#define STGM_FAILIFTHERE 0x00000000L + +#define STGM_NOSNAPSHOT 0x00200000L + +STDAPI IIDFromString(LPOLESTR lpsz, IID* lpiid); +STDAPI_(int) StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cchMax); + +/******************* CRYPT **************************************/ + +#define PUBLICKEYBLOB 0x6 + +// +// Algorithm IDs and Flags +// +#define GET_ALG_CLASS(x) (x & (7 << 13)) +#define GET_ALG_TYPE(x) (x & (15 << 9)) +#define GET_ALG_SID(x) (x & (511)) + +typedef unsigned int ALG_ID; + +// Algorithm classes +#define ALG_CLASS_SIGNATURE (1 << 13) +#define ALG_CLASS_HASH (4 << 13) + +// Algorithm types +#define ALG_TYPE_ANY (0) + +// Hash sub ids +#define ALG_SID_SHA1 4 + +// algorithm identifier definitions +#define CALG_SHA1 (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_SHA1) + +/******************* NLS ****************************************/ + +typedef +enum tagMIMECONTF { + MIMECONTF_MAILNEWS = 0x1, + MIMECONTF_BROWSER = 0x2, + MIMECONTF_MINIMAL = 0x4, + MIMECONTF_IMPORT = 0x8, + MIMECONTF_SAVABLE_MAILNEWS = 0x100, + MIMECONTF_SAVABLE_BROWSER = 0x200, + MIMECONTF_EXPORT = 0x400, + MIMECONTF_PRIVCONVERTER = 0x10000, + MIMECONTF_VALID = 0x20000, + MIMECONTF_VALID_NLS = 0x40000, + MIMECONTF_MIME_IE4 = 0x10000000, + MIMECONTF_MIME_LATEST = 0x20000000, + MIMECONTF_MIME_REGISTRY = 0x40000000 + } MIMECONTF; + +#define LCMAP_LOWERCASE 0x00000100 +#define LCMAP_UPPERCASE 0x00000200 +#define LCMAP_SORTKEY 0x00000400 +#define LCMAP_BYTEREV 0x00000800 + +#define LCMAP_HIRAGANA 0x00100000 +#define LCMAP_KATAKANA 0x00200000 +#define LCMAP_HALFWIDTH 0x00400000 +#define LCMAP_FULLWIDTH 0x00800000 + +#define LCMAP_LINGUISTIC_CASING 0x01000000 + +// 8 characters for language +// 8 characters for region +// 64 characters for suffix (script) +// 2 characters for '-' separators +// 2 characters for prefix like "i-" or "x-" +// 1 null termination +#define LOCALE_NAME_MAX_LENGTH 85 + +#define LOCALE_SCOUNTRY 0x00000006 +#define LOCALE_SENGCOUNTRY 0x00001002 + +#define LOCALE_SLANGUAGE 0x00000002 +#define LOCALE_SENGLANGUAGE 0x00001001 + +#define LOCALE_SDATE 0x0000001D +#define LOCALE_STIME 0x0000001E + +#define CSTR_LESS_THAN 1 +#define CSTR_EQUAL 2 +#define CSTR_GREATER_THAN 3 + +#define NORM_IGNORENONSPACE 0x00000002 + +#define WC_COMPOSITECHECK 0x00000000 // NOTE: diff from winnls.h + +/******************* shlwapi ************************************/ + +// note: diff in NULL handing and calling convetion +#define StrCpyW PAL_wcscpy +#define StrCatW PAL_wcscat +#define StrChrW (WCHAR*)PAL_wcschr +#define StrCmpW PAL_wcscmp +#define StrCmpIW _wcsicmp +#define StrCmpNW PAL_wcsncmp +#define StrCmpNIW _wcsnicmp + +STDAPI_(LPWSTR) StrNCatW(LPWSTR lpFront, LPCWSTR lpBack, int cchMax); +STDAPI_(int) StrToIntW(LPCWSTR lpSrc); +STDAPI_(LPWSTR) StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch); +STDAPI_(LPWSTR) StrRChrW(LPCWSTR lpStart, LPCWSTR lpEnd, WCHAR wMatch); +STDAPI_(LPWSTR) StrCatBuffW(LPWSTR pszDest, LPCWSTR pszSrc, int cchDestBuffSize); + +#define lstrcmpW PAL_wcscmp +#define lstrcmpiW _wcsicmp + +#ifdef UNICODE +#define StrCpy StrCpyW +#define StrCat StrCatW +#define StrNCat StrNCatW +#define StrChr StrChrW +#define StrCmp StrCmpW +#define StrCmpN StrCmpNW +#define StrCmpI StrCmpIW +#define StrCmpNI StrCmpNIW + +#define StrToInt StrToIntW +#define StrStrI StrStrIW +#define StrRChr StrRChrW +#define StrCatBuff StrCatBuffW + +#define lstrcmp lstrcmpW +#define lstrcmpi lstrcmpiW +#endif + + +#ifdef __cplusplus +/* + Safe CRT functions are not available (yet) on all platforms, so we use our own implementations from safecrt.h. +*/ +#define _CRT_ALTERNATIVE_INLINES +#define _SAFECRT_NO_INCLUDES 1 +#define _SAFECRT_USE_INLINES 1 +#define _SAFECRT_SET_ERRNO 0 +#define _SAFECRT_DEFINE_MBS_FUNCTIONS 0 +#define _SAFECRT_DEFINE_TCS_MACROS 1 +/* +#define _SAFECRT__ISMBBLEAD(_Character) 0 +#define _SAFECRT__MBSDEC(_String, _Current) (_Current - 1) +*/ +#include "safecrt.h" +#include "specstrings.h" + +/* +The wrappers below are simple implementations that may not be as robust as complete functions in the Secure CRT library. +Remember to fix the errcode defintion in safecrt.h. +*/ + +#define _wcslwr_s _wcslwr_unsafe +#define swscanf_s swscanf + +#define _wfopen_s _wfopen_unsafe +#define fopen_s _fopen_unsafe + +#define _strlwr_s _strlwr_unsafe + +#define _vscprintf _vscprintf_unsafe + +extern "C++" { + +#include + +inline errno_t __cdecl _wcslwr_unsafe(WCHAR *str, size_t sz) +{ + size_t fullSize; + if(!ClrSafeInt::multiply(sz, sizeof(WCHAR), fullSize)) + return 1; + WCHAR *copy = (WCHAR *)malloc(fullSize); + if(copy == nullptr) + return 1; + + errno_t retCode = wcscpy_s(copy, sz, str); + if(retCode) { + free(copy); + return 1; + } + + _wcslwr(copy); + wcscpy_s(str, sz, copy); + free(copy); + + return 0; +} +inline errno_t __cdecl _strlwr_unsafe(char *str, size_t sz) +{ + char *copy = (char *)malloc(sz); + if(copy == nullptr) + return 1; + + errno_t retCode = strcpy_s(copy, sz, str); + if(retCode) { + free(copy); + return 1; + } + + _strlwr(copy); + strcpy_s(str, sz, copy); + free(copy); + + return 0; +} + +inline int __cdecl _vscprintf_unsafe(const char *_Format, va_list _ArgList) +{ + int guess = 10; + + for (;;) + { + char *buf = (char *)malloc(guess * sizeof(char)); + if(buf == nullptr) + return 0; + + va_list argListCopy; + va_copy(argListCopy, _ArgList); + int ret = _vsnprintf_s(buf, guess, _TRUNCATE, _Format, argListCopy); + free(buf); + va_end(argListCopy); + + if ((ret != -1) && (ret < guess)) + return ret; + + guess *= 2; + } +} + +inline errno_t __cdecl _wfopen_unsafe(PAL_FILE * *ff, const WCHAR *fileName, const WCHAR *mode) +{ + PAL_FILE *result = _wfopen(fileName, mode); + if(result == 0) { + return 1; + } else { + *ff = result; + return 0; + } +} + +inline errno_t __cdecl _fopen_unsafe(PAL_FILE * *ff, const char *fileName, const char *mode) +{ + PAL_FILE *result = PAL_fopen(fileName, mode); + if(result == 0) { + return 1; + } else { + *ff = result; + return 0; + } +} + +} +#endif /* __cplusplus */ + + +STDAPI_(BOOL) PathAppendW(LPWSTR pszPath, LPCWSTR pszMore); +STDAPI_(int) PathCommonPrefixW(LPCWSTR pszFile1, LPCWSTR pszFile2, LPWSTR pszPath); +PALIMPORT LPWSTR PALAPI PathFindFileNameW(LPCWSTR pPath); +STDAPI_(int) PathGetDriveNumberW(LPCWSTR lpsz); +STDAPI_(BOOL) PathIsRelativeW(LPCWSTR lpszPath); +STDAPI_(BOOL) PathIsUNCW(LPCWSTR pszPath); +STDAPI_(LPWSTR) PathAddBackslashW(LPWSTR lpszPath); +STDAPI_(LPWSTR) PathRemoveBackslashW(LPWSTR lpszPath); +STDAPI_(void) PathRemoveExtensionW(LPWSTR pszPath); +STDAPI_(LPWSTR) PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile); +STDAPI_(BOOL) PathCanonicalizeW(LPWSTR lpszDst, LPCWSTR lpszSrc); +STDAPI_(BOOL) PathRelativePathToW(LPWSTR pszPath, LPCWSTR pszFrom, DWORD dwAttrFrom, LPCWSTR pszTo, DWORD dwAttrTo); +STDAPI_(BOOL) PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt); +STDAPI_(BOOL) PathRemoveFileSpecW(LPWSTR pFile); +STDAPI_(void) PathStripPathW (LPWSTR pszPath); + +#ifdef UNICODE +#define PathAppend PathAppendW +#define PathCommonPrefix PathCommonPrefixW +#define PathFindFileName PathFindFileNameW +#define PathIsRelative PathIsRelativeW +#define PathGetDriveNumber PathGetDriveNumberW +#define PathIsUNC PathIsUNCW +#define PathAddBackslash PathAddBackslashW +#define PathRemoveBackslash PathRemoveBackslashW +#define PathRemoveExtension PathRemoveExtensionW +#define PathCombine PathCombineW +#define PathSkipRoot PathSkipRootW +#define PathFindExtension PathFindExtensionW +#define PathCanonicalize PathCanonicalizeW +#define PathRelativePathTo PathRelativePathToW +#define PathRemoveFileSpec PathRemoveFileSpecW +#define PathRenameExtension PathRenameExtensionW +#define PathStripPath PathStripPathW + + +#endif // UNICODE + +/******************* misc ***************************************/ + +#ifdef __cplusplus +namespace std +{ + typedef decltype(nullptr) nullptr_t; +} + +extern "C++" +template< class T > +typename std::remove_reference::type&& move( T&& t ); +#endif // __cplusplus + +#define __RPC__out +#define __RPC__in +#define __RPC__deref_out_opt +#define __RPC__in_opt +#define __RPC__inout_xcount(x) +#define __RPC__in_ecount_full(x) +#define __RPC__out_ecount_part(x, y) +#define __RPC__in_xcount(x) +#define __RPC__inout +#define __RPC__deref_out_ecount_full_opt(x) + +typedef DWORD OLE_COLOR; + +#define PF_COMPARE_EXCHANGE_DOUBLE 2 + +typedef VOID (NTAPI * WAITORTIMERCALLBACKFUNC) (PVOID, BOOLEAN ); + +typedef HANDLE HWND; + +#define IS_TEXT_UNICODE_SIGNATURE 0x0008 +#define IS_TEXT_UNICODE_UNICODE_MASK 0x000F + +BOOL IsTextUnicode(CONST VOID* lpv, int iSize, LPINT lpiResult); + +typedef struct _LIST_ENTRY { + struct _LIST_ENTRY *Flink; + struct _LIST_ENTRY *Blink; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef VOID (NTAPI *WAITORTIMERCALLBACK)(PVOID, BOOLEAN); + +// PORTABILITY_ASSERT and PORTABILITY_WARNING macros are meant to be used to +// mark places in the code that needs attention for portability. The usual +// usage pattern is: +// +// int get_scratch_register() { +// #if defined(_TARGET_X86_) +// return eax; +// #elif defined(_TARGET_AMD64_) +// return rax; +// #elif defined(_TARGET_ARM_) +// return r0; +// #else +// PORTABILITY_ASSERT("scratch register"); +// return 0; +// #endif +// } +// +// PORTABILITY_ASSERT is meant to be used inside functions/methods. It can +// introduce compile-time and/or run-time errors. +// PORTABILITY_WARNING is meant to be used outside functions/methods. It can +// introduce compile-time errors or warnings only. +// +// People starting new ports will first define these to just cause run-time +// errors. Once they fix all the places that need attention for portability, +// they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause +// compile-time errors to make sure that they haven't missed anything. +// +// If it is reasonably possible all codepaths containing PORTABILITY_ASSERT +// should be compilable (e.g. functions should return NULL or something if +// they are expected to return a value). +// +// The message in these two macros should not contain any keywords like TODO +// or NYI. It should be just the brief description of the problem. + +#ifdef PORTABILITY_CHECK +// Finished ports - compile-time errors +#define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) +#define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) +#else +// Ports in progress - run-time asserts only +#define PORTABILITY_WARNING(message) +#define PORTABILITY_ASSERT(message) _ASSERTE(false && message) +#endif + +#define UNREFERENCED_PARAMETER(P) (void)(P) + +#ifdef BIT64 +#define VALPTR(x) VAL64(x) +#define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) +#define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) +#define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_64(p,x) +#define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL64(p,x) +#else +#define VALPTR(x) VAL32(x) +#define GET_UNALIGNED_PTR(x) GET_UNALIGNED_32(x) +#define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL32(x) +#define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_32(p,x) +#define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) +#endif + +#ifdef _TARGET_AMD64_ +#define RUNTIME_FUNCTION_INDIRECT 0x1 +#endif + +#define _ReturnAddress() __builtin_return_address(0) + +#define DIRECTORY_SEPARATOR_CHAR_A '/' +#define DIRECTORY_SEPARATOR_CHAR_W W('/') +#define DIRECTORY_SEPARATOR_STR_A "/" +#define DIRECTORY_SEPARATOR_STR_W W("/") +#define PATH_SEPARATOR_CHAR_W W(':') +#define PATH_SEPARATOR_STR_W W(":") +#define VOLUME_SEPARATOR_CHAR_W W('/') + +#ifndef IMAGE_IMPORT_DESC_FIELD +#define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).u.f) +#endif + +#ifndef IMAGE_COR20_HEADER_FIELD +#define IMAGE_COR20_HEADER_FIELD(obj, f) ((obj).f) +#endif + +// copied from winnt.h +#define PROCESSOR_ARCHITECTURE_INTEL 0 +#define PROCESSOR_ARCHITECTURE_MIPS 1 +#define PROCESSOR_ARCHITECTURE_ALPHA 2 +#define PROCESSOR_ARCHITECTURE_PPC 3 +#define PROCESSOR_ARCHITECTURE_SHX 4 +#define PROCESSOR_ARCHITECTURE_ARM 5 +#define PROCESSOR_ARCHITECTURE_IA64 6 +#define PROCESSOR_ARCHITECTURE_ALPHA64 7 +#define PROCESSOR_ARCHITECTURE_MSIL 8 +#define PROCESSOR_ARCHITECTURE_AMD64 9 +#define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10 +#define PROCESSOR_ARCHITECTURE_NEUTRAL 11 +#define PROCESSOR_ARCHITECTURE_ARM64 12 + +#define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF + +// +// JIT Debugging Info. This structure is defined to have constant size in +// both the emulated and native environment. +// + +typedef struct _JIT_DEBUG_INFO { + DWORD dwSize; + DWORD dwProcessorArchitecture; + DWORD dwThreadID; + DWORD dwReserved0; + ULONG64 lpExceptionAddress; + ULONG64 lpExceptionRecord; + ULONG64 lpContextRecord; +} JIT_DEBUG_INFO, *LPJIT_DEBUG_INFO; + +typedef JIT_DEBUG_INFO JIT_DEBUG_INFO32, *LPJIT_DEBUG_INFO32; +typedef JIT_DEBUG_INFO JIT_DEBUG_INFO64, *LPJIT_DEBUG_INFO64; + +/******************* resources ***************************************/ +#define IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0) +#define MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) +#define MAKEINTRESOURCE(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) +#define RT_RCDATA MAKEINTRESOURCE(10) +#define RT_VERSION MAKEINTRESOURCE(16) + +/******************* SAFEARRAY ************************/ + +#define FADF_VARIANT ( 0x800 ) + +typedef struct tagSAFEARRAYBOUND + { + ULONG cElements; + LONG lLbound; + } SAFEARRAYBOUND; + +typedef struct tagSAFEARRAYBOUND *LPSAFEARRAYBOUND; + +typedef struct tagSAFEARRAY + { + USHORT cDims; + USHORT fFeatures; + ULONG cbElements; + ULONG cLocks; + PVOID pvData; + SAFEARRAYBOUND rgsabound[ 1 ]; + } SAFEARRAY; + +typedef SAFEARRAY *LPSAFEARRAY; + + +STDAPI_(SAFEARRAY *) SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements); +STDAPI_(UINT) SafeArrayGetDim(SAFEARRAY * psa); +STDAPI SafeArrayGetElement(SAFEARRAY * psa, LONG * rgIndices, void * pv); +STDAPI SafeArrayGetLBound(SAFEARRAY * psa, UINT nDim, LONG * plLbound); +STDAPI SafeArrayGetUBound(SAFEARRAY * psa, UINT nDim, LONG * plUbound); +STDAPI SafeArrayGetVartype(SAFEARRAY * psa, VARTYPE * pvt); +STDAPI SafeArrayPutElement(SAFEARRAY * psa, LONG * rgIndices, void * pv); +STDAPI SafeArrayDestroy(SAFEARRAY * psa); + +EXTERN_C void * _stdcall _lfind(const void *, const void *, unsigned int *, unsigned int, + int (__cdecl *)(const void *, const void *)); + + +/******************* clean this up ************************/ + + +interface IDispatch; +interface ITypeInfo; +interface ITypeLib; +interface IMoniker; + +typedef VOID (WINAPI *LPOVERLAPPED_COMPLETION_ROUTINE)( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped); + +// +// Debug APIs +// +#define EXCEPTION_DEBUG_EVENT 1 +#define CREATE_THREAD_DEBUG_EVENT 2 +#define CREATE_PROCESS_DEBUG_EVENT 3 +#define EXIT_THREAD_DEBUG_EVENT 4 +#define EXIT_PROCESS_DEBUG_EVENT 5 +#define LOAD_DLL_DEBUG_EVENT 6 +#define UNLOAD_DLL_DEBUG_EVENT 7 +#define OUTPUT_DEBUG_STRING_EVENT 8 +#define RIP_EVENT 9 + +typedef struct _EXCEPTION_DEBUG_INFO { + EXCEPTION_RECORD ExceptionRecord; + DWORD dwFirstChance; +} EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO; + +typedef struct _CREATE_THREAD_DEBUG_INFO { + HANDLE hThread; + LPVOID lpThreadLocalBase; + LPTHREAD_START_ROUTINE lpStartAddress; +} CREATE_THREAD_DEBUG_INFO, *LPCREATE_THREAD_DEBUG_INFO; + +typedef struct _CREATE_PROCESS_DEBUG_INFO { + HANDLE hFile; + HANDLE hProcess; + HANDLE hThread; + LPVOID lpBaseOfImage; + DWORD dwDebugInfoFileOffset; + DWORD nDebugInfoSize; + LPVOID lpThreadLocalBase; + LPTHREAD_START_ROUTINE lpStartAddress; + LPVOID lpImageName; + WORD fUnicode; +} CREATE_PROCESS_DEBUG_INFO, *LPCREATE_PROCESS_DEBUG_INFO; + +typedef struct _EXIT_THREAD_DEBUG_INFO { + DWORD dwExitCode; +} EXIT_THREAD_DEBUG_INFO, *LPEXIT_THREAD_DEBUG_INFO; + +typedef struct _EXIT_PROCESS_DEBUG_INFO { + DWORD dwExitCode; +} EXIT_PROCESS_DEBUG_INFO, *LPEXIT_PROCESS_DEBUG_INFO; + +typedef struct _LOAD_DLL_DEBUG_INFO { + HANDLE hFile; + LPVOID lpBaseOfDll; + DWORD dwDebugInfoFileOffset; + DWORD nDebugInfoSize; + LPVOID lpImageName; + WORD fUnicode; +} LOAD_DLL_DEBUG_INFO, *LPLOAD_DLL_DEBUG_INFO; + +typedef struct _UNLOAD_DLL_DEBUG_INFO { + LPVOID lpBaseOfDll; +} UNLOAD_DLL_DEBUG_INFO, *LPUNLOAD_DLL_DEBUG_INFO; + +typedef struct _OUTPUT_DEBUG_STRING_INFO { + LPSTR lpDebugStringData; + WORD fUnicode; + WORD nDebugStringLength; +} OUTPUT_DEBUG_STRING_INFO, *LPOUTPUT_DEBUG_STRING_INFO; + +typedef struct _RIP_INFO { + DWORD dwError; + DWORD dwType; +} RIP_INFO, *LPRIP_INFO; + +typedef struct _DEBUG_EVENT { + DWORD dwDebugEventCode; + DWORD dwProcessId; + DWORD dwThreadId; + union { + EXCEPTION_DEBUG_INFO Exception; + CREATE_THREAD_DEBUG_INFO CreateThread; + CREATE_PROCESS_DEBUG_INFO CreateProcessInfo; + EXIT_THREAD_DEBUG_INFO ExitThread; + EXIT_PROCESS_DEBUG_INFO ExitProcess; + LOAD_DLL_DEBUG_INFO LoadDll; + UNLOAD_DLL_DEBUG_INFO UnloadDll; + OUTPUT_DEBUG_STRING_INFO DebugString; + RIP_INFO RipInfo; + } u; +} DEBUG_EVENT, *LPDEBUG_EVENT; + +// +// Define dynamic function table entry. +// + +typedef +PRUNTIME_FUNCTION +GET_RUNTIME_FUNCTION_CALLBACK ( + DWORD64 ControlPc, + PVOID Context + ); +typedef GET_RUNTIME_FUNCTION_CALLBACK *PGET_RUNTIME_FUNCTION_CALLBACK; + +typedef +DWORD +OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK ( + HANDLE Process, + PVOID TableAddress, + PDWORD Entries, + PRUNTIME_FUNCTION* Functions + ); +typedef OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK *POUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK; + +#define OUT_OF_PROCESS_FUNCTION_TABLE_CALLBACK_EXPORT_NAME \ + "OutOfProcessFunctionTableCallback" + +#if defined(FEATURE_PAL_SXS) + +// #if !defined(_TARGET_MAC64) +// typedef LONG (*PEXCEPTION_ROUTINE)( + // IN PEXCEPTION_POINTERS pExceptionPointers, + // IN LPVOID lpvParam); + +// #define DISPATCHER_CONTEXT LPVOID + +// #else // defined(_TARGET_MAC64) + +// +// Define unwind history table structure. +// + +#define UNWIND_HISTORY_TABLE_SIZE 12 + +typedef struct _UNWIND_HISTORY_TABLE_ENTRY { + DWORD64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; +} UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY; + +typedef struct _UNWIND_HISTORY_TABLE { + DWORD Count; + BYTE LocalHint; + BYTE GlobalHint; + BYTE Search; + BYTE Once; + DWORD64 LowAddress; + DWORD64 HighAddress; + UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; +} UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE; + +typedef +EXCEPTION_DISPOSITION +(*PEXCEPTION_ROUTINE) ( + PEXCEPTION_RECORD ExceptionRecord, + ULONG64 EstablisherFrame, + PCONTEXT ContextRecord, + PVOID DispatcherContext + ); + +#if defined(_ARM_) + +typedef struct _DISPATCHER_CONTEXT { + DWORD ControlPc; + DWORD ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + DWORD EstablisherFrame; + DWORD TargetPc; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + DWORD ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PBYTE NonVolatileRegisters; + DWORD Reserved; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#elif defined(_ARM64_) + +typedef struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetPc; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + ULONG64 ScopeIndex; + BOOLEAN ControlPcIsUnwound; + PBYTE NonVolatileRegisters; + ULONG64 Reserved; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#elif defined(_AMD64_) + +typedef struct _DISPATCHER_CONTEXT { + ULONG64 ControlPc; + ULONG64 ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + ULONG64 EstablisherFrame; + ULONG64 TargetIp; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#elif defined(_X86_) + +typedef struct _DISPATCHER_CONTEXT { + DWORD ControlPc; + DWORD ImageBase; + PRUNTIME_FUNCTION FunctionEntry; + DWORD EstablisherFrame; + DWORD TargetIp; + PKNONVOLATILE_CONTEXT CurrentNonVolatileContextRecord; + PCONTEXT ContextRecord; + PEXCEPTION_ROUTINE LanguageHandler; + PVOID HandlerData; + PUNWIND_HISTORY_TABLE HistoryTable; + BOOLEAN ControlPcIsUnwound; +} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; + +#else + +#error Unknown architecture for defining DISPATCHER_CONTEXT. + +#endif + +// #endif // !defined(_TARGET_MAC64) + +typedef DISPATCHER_CONTEXT *PDISPATCHER_CONTEXT; + +#define ExceptionContinueSearch EXCEPTION_CONTINUE_SEARCH +#define ExceptionStackUnwind EXCEPTION_EXECUTE_HANDLER +#define ExceptionContinueExecution EXCEPTION_CONTINUE_EXECUTION + +#endif // FEATURE_PAL_SXS + +typedef struct _EXCEPTION_REGISTRATION_RECORD EXCEPTION_REGISTRATION_RECORD; +typedef EXCEPTION_REGISTRATION_RECORD *PEXCEPTION_REGISTRATION_RECORD; + +typedef LPVOID HKEY; +typedef LPVOID PACL; +typedef LPVOID LPBC; +typedef LPVOID PSECURITY_DESCRIPTOR; + +typedef struct _EXCEPTION_RECORD64 { + DWORD ExceptionCode; + ULONG ExceptionFlags; + ULONG64 ExceptionRecord; + ULONG64 ExceptionAddress; + ULONG NumberParameters; + ULONG __unusedAlignment; + ULONG64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; +} EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; + +typedef LONG (WINAPI *PTOP_LEVEL_EXCEPTION_FILTER)( + IN struct _EXCEPTION_POINTERS *ExceptionInfo + ); +typedef PTOP_LEVEL_EXCEPTION_FILTER LPTOP_LEVEL_EXCEPTION_FILTER; + +/******************* ntdef ************************************/ + +#ifndef ANYSIZE_ARRAY +#define ANYSIZE_ARRAY 1 // winnt +#endif + +/******************* winnt ************************************/ + +typedef struct LIST_ENTRY32 { + ULONG Flink; + ULONG Blink; +} LIST_ENTRY32; +typedef LIST_ENTRY32 *PLIST_ENTRY32; + +typedef struct LIST_ENTRY64 { + ULONGLONG Flink; + ULONGLONG Blink; +} LIST_ENTRY64; +typedef LIST_ENTRY64 *PLIST_ENTRY64; + +/******************** PAL RT APIs *******************************/ + +typedef struct _HSATELLITE *HSATELLITE; + +EXTERN_C HSATELLITE PALAPI PAL_LoadSatelliteResourceW(LPCWSTR SatelliteResourceFileName); +EXTERN_C HSATELLITE PALAPI PAL_LoadSatelliteResourceA(LPCSTR SatelliteResourceFileName); +EXTERN_C BOOL PALAPI PAL_FreeSatelliteResource(HSATELLITE SatelliteResource); +EXTERN_C UINT PALAPI PAL_LoadSatelliteStringW(HSATELLITE SatelliteResource, + UINT uID, + LPWSTR lpBuffer, + UINT nBufferMax); +EXTERN_C UINT PALAPI PAL_LoadSatelliteStringA(HSATELLITE SatelliteResource, + UINT uID, + LPSTR lpBuffer, + UINT nBufferMax); + +EXTERN_C HRESULT PALAPI PAL_CoCreateInstance(REFCLSID rclsid, + REFIID riid, + void **ppv); + +// So we can have CoCreateInstance in most of the code base, +// instead of spreading around of if'def FEATURE_PALs for PAL_CoCreateInstance. +#define CoCreateInstance(rclsid, pUnkOuter, dwClsContext, riid, ppv) PAL_CoCreateInstance(rclsid, riid, ppv) + +STDAPI +CoCreateGuid(OUT GUID * pguid); + +/************** verrsrc.h ************************************/ + +/* ----- VS_VERSION.dwFileFlags ----- */ +#define VS_FF_DEBUG 0x00000001L +#define VS_FF_PRERELEASE 0x00000002L +#define VS_FF_PATCHED 0x00000004L +#define VS_FF_PRIVATEBUILD 0x00000008L +#define VS_FF_INFOINFERRED 0x00000010L +#define VS_FF_SPECIALBUILD 0x00000020L + +/* ----- Types and structures ----- */ +typedef struct tagVS_FIXEDFILEINFO +{ + DWORD dwSignature; /* e.g. 0xfeef04bd */ + DWORD dwStrucVersion; /* e.g. 0x00000042 = "0.42" */ + DWORD dwFileVersionMS; /* e.g. 0x00030075 = "3.75" */ + DWORD dwFileVersionLS; /* e.g. 0x00000031 = "0.31" */ + DWORD dwProductVersionMS; /* e.g. 0x00030010 = "3.10" */ + DWORD dwProductVersionLS; /* e.g. 0x00000031 = "0.31" */ + DWORD dwFileFlagsMask; /* = 0x3F for version "0.42" */ + DWORD dwFileFlags; /* e.g. VFF_DEBUG | VFF_PRERELEASE */ + DWORD dwFileOS; /* e.g. VOS_DOS_WINDOWS16 */ + DWORD dwFileType; /* e.g. VFT_DRIVER */ + DWORD dwFileSubtype; /* e.g. VFT2_DRV_KEYBOARD */ + DWORD dwFileDateMS; /* e.g. 0 */ + DWORD dwFileDateLS; /* e.g. 0 */ +} VS_FIXEDFILEINFO; + +/************** Byte swapping & unaligned access ******************/ + +#include + +/******************** external includes *************************/ + +#include "ntimage.h" + +#endif // RC_INVOKED + +#endif // __PALRT_H__ diff --git a/lib/coreclr/src/pal/inc/rt/poppack.h b/lib/coreclr/src/pal/inc/rt/poppack.h new file mode 100644 index 0000000000..ef4e86b63f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/poppack.h @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: poppack.h +// +// =========================================================================== +/* +Abstract: + + This file turns packing of structures off. (That is, it enables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. + + poppack.h is the complement to pshpack?.h. An inclusion of poppack.h + MUST ALWAYS be preceded by an inclusion of one of pshpack?.h, in one-to-one + correspondence. + + For Microsoft compatible compilers, this file uses the pop option + to the pack pragma so that it can restore the previous saved by the + pshpack?.h include file. + +*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(pop) +#else +#pragma pack() +#endif +#else +#pragma pack() +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/process.h b/lib/coreclr/src/pal/inc/rt/process.h new file mode 100644 index 0000000000..4dcfbe88bd --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/process.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: process.h +// +// =========================================================================== +// dummy process.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/psapi.h b/lib/coreclr/src/pal/inc/rt/psapi.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/psapi.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/pshpack1.h b/lib/coreclr/src/pal/inc/rt/pshpack1.h new file mode 100644 index 0000000000..f53472d720 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/pshpack1.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: pshpack1.h +// +// =========================================================================== + +/*++ + +Abstract: + + This file turns 1 byte packing of structures on. (That is, it disables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. For Microsoft + compatible compilers, this files uses the push option to the pack pragma + so that the poppack.h include file can restore the previous packing + reliably. + + The file poppack.h is the complement to this file. + +--*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(push,1) +#else +#pragma pack(1) +#endif +#else +#pragma pack(1) +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/pshpack2.h b/lib/coreclr/src/pal/inc/rt/pshpack2.h new file mode 100644 index 0000000000..bbeffac9ca --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/pshpack2.h @@ -0,0 +1,37 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: pshpack2.h +// +// =========================================================================== +/*++ + +Abstract: + + This file turns 2 byte packing of structures on. (That is, it disables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. For Microsoft + compatible compilers, this files uses the push option to the pack pragma + so that the poppack.h include file can restore the previous packing + reliably. + + The file poppack.h is the complement to this file. + +--*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(push,2) +#else +#pragma pack(2) +#endif +#else +#pragma pack(2) +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/pshpack4.h b/lib/coreclr/src/pal/inc/rt/pshpack4.h new file mode 100644 index 0000000000..4431c9d393 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/pshpack4.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: pshpack4.h +// +// =========================================================================== + +/*++ + +Abstract: + + This file turns 4 byte packing of structures on. (That is, it disables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. For Microsoft + compatible compilers, this files uses the push option to the pack pragma + so that the poppack.h include file can restore the previous packing + reliably. + + The file poppack.h is the complement to this file. + +--*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(push,4) +#else +#pragma pack(4) +#endif +#else +#pragma pack(4) +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/pshpack8.h b/lib/coreclr/src/pal/inc/rt/pshpack8.h new file mode 100644 index 0000000000..b1377d3e00 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/pshpack8.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: pshpack8.h +// +// =========================================================================== + +/*++ + +Abstract: + + This file turns 8 byte packing of structures on. (That is, it disables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. For Microsoft + compatible compilers, this files uses the push option to the pack pragma + so that the poppack.h include file can restore the previous packing + reliably. + + The file poppack.h is the complement to this file. + +--*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(push,8) +#else +#pragma pack(8) +#endif +#else +#pragma pack(8) +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/pshpck16.h b/lib/coreclr/src/pal/inc/rt/pshpck16.h new file mode 100644 index 0000000000..bb4a0e1228 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/pshpck16.h @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: pshpck16.h +// +// =========================================================================== + +/*++ + +Abstract: + + This file turns 16 byte packing of structures on. (That is, it disables + automatic alignment of structure fields.) An include file is needed + because various compilers do this in different ways. For Microsoft + compatible compilers, this files uses the push option to the pack pragma + so that the poppack.h include file can restore the previous packing + reliably. + + The file poppack.h is the complement to this file. + +--*/ + +#if ! (defined(lint) || defined(RC_INVOKED)) +#if ( _MSC_VER >= 800 && !defined(_M_I86)) || defined(_PUSHPOP_SUPPORTED) +#pragma warning(disable:4103) +#if !(defined( MIDL_PASS )) || defined( __midl ) +#pragma pack(push,16) +#else +#pragma pack(16) +#endif +#else +#pragma pack(16) +#endif +#endif // ! (defined(lint) || defined(RC_INVOKED)) diff --git a/lib/coreclr/src/pal/inc/rt/richedit.h b/lib/coreclr/src/pal/inc/rt/richedit.h new file mode 100644 index 0000000000..c3c5849669 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/richedit.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: richedit.h +// +// =========================================================================== +// dummy richedit.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/rpc.h b/lib/coreclr/src/pal/inc/rt/rpc.h new file mode 100644 index 0000000000..e63e617da1 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/rpc.h @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: rpc.h +// +// =========================================================================== +// dummy rpc.h for PAL + +#ifndef __RPC_H__ +#define __RPC_H__ + +#include "palrt.h" + +#define __RPC_STUB +#define __RPC_USER +#define __RPC_FAR + +#define DECLSPEC_UUID(x) __declspec(uuid(x)) +#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE + +#define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) \ + EXTERN_C const IID DECLSPEC_SELECTANY itf = {l1,s1,s2,{c1,c2,c3,c4,c5,c6,c7,c8}} + +interface IRpcStubBuffer; +interface IRpcChannelBuffer; + +typedef void* PRPC_MESSAGE; +typedef void* RPC_IF_HANDLE; + +#endif // __RPC_H__ diff --git a/lib/coreclr/src/pal/inc/rt/rpcndr.h b/lib/coreclr/src/pal/inc/rt/rpcndr.h new file mode 100644 index 0000000000..bf67d4cd57 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/rpcndr.h @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: rpcndr.h +// +// =========================================================================== +// dummy rpcndr.h for PAL + +#ifndef __RPCNDR_H__ +#define __RPCNDR_H__ + +#ifndef __RPCNDR_H_VERSION__ +#define __RPCNDR_H_VERSION__ +#endif + +#endif // __RPCNDR_H__ diff --git a/lib/coreclr/src/pal/inc/rt/safecrt.h b/lib/coreclr/src/pal/inc/rt/safecrt.h new file mode 100644 index 0000000000..9f9e15c244 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/safecrt.h @@ -0,0 +1,3370 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +/*** +*safecrt.h - secure crt downlevel for windows build +* +*Purpose: +* This file contains a subset of the Secure CRT. It is meant to +* be used in the Windows source tree. +* +****/ + +/* #pragma once */ + +/* guard against other includes */ +#if !defined(_CRT_ALTERNATIVE_INLINES) +#error "_CRT_ALTERNATIVE_INLINES needs to be defined to use safecrt.h. This will make sure the safecrt functions are not declared in the standard headers." +#endif + +#if defined(_CRT_ALTERNATIVE_IMPORTED) +#error "_CRT_ALTERNATIVE_IMPORTED is defined. This means some files were included with _CRT_ALTERNATIVE_INLINES undefined." +#endif + +#if !defined(_INC_SAFECRT) +#define _INC_SAFECRT + +#if !defined(_SAFECRT_NO_INCLUDES) +#include /* for va_start, etc. */ +#endif + +/* _SAFECRT switches */ +#if !defined(_SAFECRT_USE_INLINES) +#define _SAFECRT_USE_INLINES 0 +#endif + +#if !defined(_SAFECRT_SET_ERRNO) +#define _SAFECRT_SET_ERRNO 1 +#endif + +#if !defined(_SAFECRT_DEFINE_TCS_MACROS) +#define _SAFECRT_DEFINE_TCS_MACROS 0 +#endif + +#if !defined(_SAFECRT_DEFINE_MBS_FUNCTIONS) +#define _SAFECRT_DEFINE_MBS_FUNCTIONS 1 +#endif + +#if !defined(_SAFECRT_USE_CPP_OVERLOADS) +#define _SAFECRT_USE_CPP_OVERLOADS 0 +#endif + +#if !defined(_SAFECRT_FILL_BUFFER) +#if defined(_DEBUG) +#define _SAFECRT_FILL_BUFFER 1 +#else +#define _SAFECRT_FILL_BUFFER 0 +#endif +#endif + +#if !defined(_SAFECRT_FILL_BUFFER_PATTERN) +#define _SAFECRT_FILL_BUFFER_PATTERN 0xFD +#endif + +#if !defined(_SAFECRT_INVALID_PARAMETER_DEBUG_INFO) +#define _SAFECRT_INVALID_PARAMETER_DEBUG_INFO 0 +#endif + +#if !defined(_SAFECRT_IMPL) && defined (_SAFECRT_USE_INLINES) +#define _SAFECRT__INLINE __inline +#else +#define _SAFECRT__INLINE +#endif + +/* additional includes */ +#if _SAFECRT_USE_INLINES && !defined(_SAFECRT_NO_INCLUDES) +#include /* for _MAX_DRIVE */ +#include /* for memset */ +#include /* for NTSTATUS, RaiseException */ +#if _SAFECRT_SET_ERRNO +#include +#endif +#if _SAFECRT_DEFINE_MBS_FUNCTIONS +#include +#endif +#endif + +/* NULL */ +#if !defined(NULL) +#if !defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +/* WCHAR */ +#if defined (SAFECRT_INCLUDE_REDEFINES) +#if !defined(_WCHAR_T_DEFINED) +typedef unsigned short WCHAR; +#define _WCHAR_T_DEFINED +#endif +#endif + +/* _W64 */ +#if !defined(_W64) +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +#define _W64 __w64 +#else +#define _W64 +#endif +#endif + +/* size_t */ +#if defined (SAFECRT_INCLUDE_REDEFINES) +#if !defined(_SIZE_T_DEFINED) +#if defined(_WIN64) +typedef unsigned __int64 size_t; +#else +typedef _W64 unsigned int size_t; +#endif +#define _SIZE_T_DEFINED +#endif +#endif + +/* uintptr_t */ +#if !defined(_UINTPTR_T_DEFINED) +#if defined(_WIN64) +typedef unsigned __int64 uintptr_t; +#else +typedef _W64 unsigned int uintptr_t; +#endif +#define _UINTPTR_T_DEFINED +#endif + +#ifdef __GNUC__ +#define SAFECRT_DEPRECATED __attribute__((deprecated)) +#else +#define SAFECRT_DEPRECATED __declspec(deprecated) +#endif + +/* errno_t */ +#if !defined(_ERRCODE_DEFINED) +#define _ERRCODE_DEFINED +/* errcode is deprecated in favor or errno_t, which is part of the standard proposal */ +SAFECRT_DEPRECATED typedef int errcode; +typedef int errno_t; /* standard */ +#endif + +/* error codes */ +#if !defined(_SECURECRT_ERRCODE_VALUES_DEFINED) +#define _SECURECRT_ERRCODE_VALUES_DEFINED +#if !defined(EINVAL) +#define EINVAL 22 +#endif +#if !defined(ERANGE) +#define ERANGE 34 +#endif +#if !defined(EILSEQ) +#define EILSEQ 42 +#endif +#if !defined(STRUNCATE) +#define STRUNCATE 80 +#endif +#endif + +/* _TRUNCATE */ +#if !defined(_TRUNCATE) +#define _TRUNCATE ((size_t)-1) +#endif + +/* _SAFECRT_AUTOMATICALLY_REPLACED_CALL */ +#if !defined(_SAFECRT_AUTOMATICALLY_REPLACED_CALL) +#define _SAFECRT_AUTOMATICALLY_REPLACED_CALL(v) (v) +#endif + +/* internal macros */ +#if _SAFECRT_USE_INLINES +#define _SAFECRT__EXTERN_C +#else +#if defined(__cplusplus) +#define _SAFECRT__EXTERN_C extern "C" +#else +#define _SAFECRT__EXTERN_C extern +#endif +#endif /* _SAFECRT_USE_INLINES */ + +#if !defined(_SAFECRT_IMPL) + +#define _SAFECRT__STR2WSTR(str) L##str + +#define _SAFECRT__STR2WSTR2(str) _SAFECRT__STR2WSTR(str) + +#if !defined(__FILEW__) +#define __FILEW__ _SAFECRT__STR2WSTR2(__FILE__) +#endif + +#if !defined(__FUNCTIONW__) +#define __FUNCTIONW__ _SAFECRT__STR2WSTR2(__FUNCTION__) +#endif + +#endif + +/* validation macros */ +#if !defined(_SAFECRT_INVALID_PARAMETER) +#if _SAFECRT_INVALID_PARAMETER_DEBUG_INFO +#define _SAFECRT_INVALID_PARAMETER(message) _invalid_parameter(message, __FUNCTIONW__, __FILEW__, __LINE__, 0) +#else +#define _SAFECRT_INVALID_PARAMETER(message) _invalid_parameter(nullptr, nullptr, nullptr, 0, 0) +#endif +#endif + +#if !defined(_SAFECRT__SET_ERRNO) +#if _SAFECRT_SET_ERRNO +#define _SAFECRT__SET_ERRNO(_ErrorCode) errno = (_ErrorCode) +#else +#define _SAFECRT__SET_ERRNO(_ErrorCode) +#endif +#endif + +#if !defined(_SAFECRT__RETURN_ERROR) +#define _SAFECRT__RETURN_ERROR(_Msg, _Ret) \ + _SAFECRT__SET_ERRNO(EINVAL); \ + _SAFECRT_INVALID_PARAMETER(_Msg); \ + return _Ret +#endif + +#if !defined(_SAFECRT__VALIDATE_STRING_ERROR) +#define _SAFECRT__VALIDATE_STRING_ERROR(_String, _Size, _Ret) \ + if ((_String) == nullptr || (_Size) == 0) \ + { \ + _SAFECRT__SET_ERRNO(EINVAL); \ + _SAFECRT_INVALID_PARAMETER(L"String " _SAFECRT__STR2WSTR(#_String) L" is invalid"); \ + return _Ret; \ + } +#endif + +#if !defined(_SAFECRT__VALIDATE_STRING) +#define _SAFECRT__VALIDATE_STRING(_String, _Size) _SAFECRT__VALIDATE_STRING_ERROR(_String, _Size, EINVAL) +#endif + +#if !defined(_SAFECRT__VALIDATE_POINTER_ERROR_RETURN) +#define _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Pointer, _ErrorCode, _Ret) \ + if ((_Pointer) == nullptr) \ + { \ + _SAFECRT__SET_ERRNO(_ErrorCode); \ + _SAFECRT_INVALID_PARAMETER(L"Pointer " _SAFECRT__STR2WSTR(#_Pointer) L" is invalid"); \ + return _Ret; \ + } +#endif + +#if !defined(_SAFECRT__VALIDATE_POINTER_ERROR) +#define _SAFECRT__VALIDATE_POINTER_ERROR(_Pointer, _Ret) \ + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Pointer, EINVAL, _Ret) +#endif + +#if !defined(_SAFECRT__VALIDATE_POINTER) +#define _SAFECRT__VALIDATE_POINTER(_Pointer) \ + _SAFECRT__VALIDATE_POINTER_ERROR(_Pointer, EINVAL) +#endif + +#if !defined(_SAFECRT__VALIDATE_POINTER_RESET_STRING_ERROR) +#define _SAFECRT__VALIDATE_POINTER_RESET_STRING_ERROR(_Pointer, _String, _Size, _Ret) \ + if ((_Pointer) == nullptr) \ + { \ + _SAFECRT__SET_ERRNO(EINVAL); \ + _SAFECRT__RESET_STRING(_String, _Size); \ + _SAFECRT_INVALID_PARAMETER(L"Pointer " _SAFECRT__STR2WSTR(#_Pointer) L" is invalid"); \ + return _Ret; \ + } +#endif + +#if !defined(_SAFECRT__VALIDATE_POINTER_RESET_STRING) +#define _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Pointer, _String, _Size) \ + _SAFECRT__VALIDATE_POINTER_RESET_STRING_ERROR(_Pointer, _String, _Size, EINVAL) +#endif + +#if !defined(_SAFECRT__VALIDATE_CONDITION_ERROR_RETURN) +#define _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_Condition, _ErrorCode, _Ret) \ + if (!(_Condition)) \ + { \ + _SAFECRT__SET_ERRNO(_ErrorCode); \ + _SAFECRT_INVALID_PARAMETER(_SAFECRT__STR2WSTR(#_Condition)); \ + return _Ret; \ + } +#endif + +#if !defined(_SAFECRT__VALIDATE_CONDITION_ERROR) +#define _SAFECRT__VALIDATE_CONDITION_ERROR(_Condition, _Ret) \ + _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_Condition, EINVAL, _Ret) +#endif + +/* if _SAFECRT_FILL_BUFFER is on, fill the interval [_Offset, _Size) with _SAFECRT_FILL_BUFFER_PATTERN; + * assume that the string has been validated with _SAFECRT__VALIDATE_STRING + */ +#if !defined(_SAFECRT__FILL_STRING) +#if _SAFECRT_FILL_BUFFER +#define _SAFECRT__FILL_STRING(_String, _Size, _Offset) \ + if ((size_t)(_Offset) < (_Size)) \ + { \ + memset((_String) + (_Offset), _SAFECRT_FILL_BUFFER_PATTERN, ((_Size) - (_Offset)) * sizeof(*(_String))); \ + } +#else +#define _SAFECRT__FILL_STRING(_String, _Size, _Offset) +#endif +#endif + +/* if _SAFECRT_FILL_BUFFER is on, set the byte to _SAFECRT_FILL_BUFFER_PATTERN + */ +#if !defined(_SAFECRT__FILL_BYTE) +#if _SAFECRT_FILL_BUFFER +#define _SAFECRT__FILL_BYTE(_Position) \ + (_Position) = _SAFECRT_FILL_BUFFER_PATTERN +#else +#define _SAFECRT__FILL_BYTE(_Position) +#endif +#endif + +/* put a null terminator at the beginning of the string and then calls _SAFECRT__FILL_STRING; + * assume that the string has been validated with _SAFECRT__VALIDATE_STRING + */ +#if !defined(_SAFECRT__RESET_STRING) +#define _SAFECRT__RESET_STRING(_String, _Size) \ + *(_String) = 0; \ + _SAFECRT__FILL_STRING(_String, _Size, 1); +#endif + +#if !defined(_SAFECRT__RETURN_BUFFER_TOO_SMALL_ERROR) +#define _SAFECRT__RETURN_BUFFER_TOO_SMALL_ERROR(_String, _Size, _Ret) \ + _SAFECRT__SET_ERRNO(ERANGE); \ + _SAFECRT_INVALID_PARAMETER(L"Buffer " _SAFECRT__STR2WSTR(#_String) L" is too small"); \ + return _Ret; +#endif + +#if !defined(_SAFECRT__RETURN_BUFFER_TOO_SMALL) +#define _SAFECRT__RETURN_BUFFER_TOO_SMALL(_String, _Size) \ + _SAFECRT__RETURN_BUFFER_TOO_SMALL_ERROR(_String, _Size, ERANGE) +#endif + +#if !defined(_SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED) +#define _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_String, _Size) \ + _SAFECRT__SET_ERRNO(EINVAL); \ + _SAFECRT_INVALID_PARAMETER(L"String " _SAFECRT__STR2WSTR(#_String) L" is not terminated"); \ + return EINVAL; +#endif + +#if !defined(_SAFECRT__RETURN_EINVAL) +#define _SAFECRT__RETURN_EINVAL \ + _SAFECRT__SET_ERRNO(EINVAL); \ + _SAFECRT_INVALID_PARAMETER(L"Invalid parameter"); \ + return EINVAL; +#endif + +/* MBCS handling: change these definitions if you do not need to support mbcs strings */ +#if !defined(_SAFECRT__ISMBBLEAD) +#define _SAFECRT__ISMBBLEAD(_Character) \ + _ismbblead(_Character) +#endif + +#if !defined(_SAFECRT__MBSDEC) +#define _SAFECRT__MBSDEC(_String, _Current) \ + _mbsdec(_String, _Current) +#endif + +_SAFECRT__EXTERN_C +void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionName, const WCHAR *_FileName, unsigned int _LineNumber, uintptr_t _Reserved); + +#if (_SAFECRT_USE_INLINES || _SAFECRT_IMPL) && !defined(_SAFECRT_DO_NOT_DEFINE_INVALID_PARAMETER) + +#ifndef STATUS_INVALID_PARAMETER +#if defined (SAFECRT_INCLUDE_REDEFINES) +typedef LONG NTSTATUS; +#endif +#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) +#endif + +_SAFECRT__INLINE +void __cdecl _invalid_parameter(const WCHAR *_Message, const WCHAR *_FunctionName, const WCHAR *_FileName, unsigned int _LineNumber, uintptr_t _Reserved) +{ +#ifdef _MSC_VER + (_Message); + (_FunctionName); + (_FileName); + (_LineNumber); + (_Reserved); +#endif + /* invoke Watson */ + RaiseException((DWORD)STATUS_INVALID_PARAMETER, 0, 0, nullptr); +} + +#endif + +//#if !defined(_SAFECRT_IMPL) + +#if _SAFECRT_DEFINE_TCS_MACROS + +/* _tcs macros */ +#if !defined(_UNICODE) && !defined(UNICODE) && !defined(_MBCS) + +#define _tcscpy_s strcpy_s +#define _tcsncpy_s strncpy_s +#define _tcscat_s strcat_s +#define _tcsncat_s strncat_s +#define _tcsset_s _strset_s +#define _tcsnset_s _strnset_s +#define _tcstok_s strtok_s +#define _tmakepath_s _makepath_s +#define _tsplitpath_s _splitpath_s +#define _stprintf_s sprintf_s +#define _sntprintf_s _snprintf_s +#define _vsntprintf_s _vsnprintf_s +#define _tscanf_s scanf_s +#define _tsscanf_s sscanf_s +#define _tsnscanf_s _snscanf_s + +#elif defined(_UNICODE) || defined(UNICODE) + +#define _tcscpy_s wcscpy_s +#define _tcsncpy_s wcsncpy_s +#define _tcscat_s wcscat_s +#define _tcsncat_s wcsncat_s +#define _tcsset_s _wcsset_s +#define _tcsnset_s _wcsnset_s +#define _tcstok_s wcstok_s +#define _tmakepath_s _wmakepath_s +#define _tsplitpath_s _wsplitpath_s +#define _stprintf_s swprintf_s +#define _vsntprintf_s _vsnwprintf_s +#define _tscanf_s wscanf_s +#define _tsscanf_s swscanf_s +#define _tsnscanf_s _swnscanf_s + +#elif defined(_MBCS) + +#define _tcscpy_s _mbscpy_s +#define _tcsncpy_s _mbsnbcpy_s +#define _tcscat_s _mbscat_s +#define _tcsncat_s _mbsnbcat_s +#define _tcsset_s _mbsset_s +#define _tcsnset_s _mbsnbset_s +#define _tcstok_s _mbstok_s +#define _tmakepath_s _makepath_s +#define _tsplitpath_s _splitpath_s +#define _stprintf_s sprintf_s +#define _sntprintf_s _snprintf_s +#define _tscanf_s scanf_s +#define _tsscanf_s sscanf_s +#define _tsnscanf_s _snscanf_s + +#else + +#error We should not get here... + +#endif + +#endif /* _SAFECRT_DEFINE_TCS_MACROS */ + +/* strcpy_s */ +/* + * strcpy_s, wcscpy_s copy string _Src into _Dst; + * will call _SAFECRT_INVALID_PARAMETER if string _Src does not fit into _Dst + */ + + +_SAFECRT__EXTERN_C +errno_t __cdecl strcpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl strcpy_s(char (&_Dst)[_SizeInBytes], const char *_Src) +{ + return strcpy_s(_Dst, _SizeInBytes, _Src); +} +#endif + + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + + +_SAFECRT__INLINE +errno_t __cdecl strcpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src) +{ + + char *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* wcscpy_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl wcscpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl wcscpy_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src) +{ + return wcscpy_s(_Dst, _SizeInWords, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl wcscpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) +{ + WCHAR *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); + + p = _Dst; + available = _SizeInWords; + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbscpy_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbscpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbscpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src) +{ + return _mbscpy_s(_Dst, _SizeInBytes, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbscpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src) +{ + unsigned char *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + if (*_Src == 0 && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the source string ended with a lead byte: we remove it */ + p[-1] = 0; + return 0; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-2])) + { + /* the source string ended with a lead byte: we remove it */ + p[-2] = 0; + available++; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* strncpy_s */ +/* + * strncpy_s, wcsncpy_s copy at max _Count characters from string _Src into _Dst; + * string _Dst will always be null-terminated; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; + * if _Count == _TRUNCATE, we will copy as many characters as we can from _Src into _Dst, and + * return STRUNCATE if _Src does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); + * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed + */ +_SAFECRT__EXTERN_C +errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl strncpy_s(char (&_Dst)[_SizeInBytes], const char *_Src, size_t _Count) +{ + return strncpy_s(_Dst, _SizeInBytes, _Src, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl strncpy_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count) +{ + char *p; + size_t available; + + if (_Count == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_Count == 0) + { + /* notice that the source string pointer can be nullptr in this case */ + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + return 0; + } + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + if (_Count == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while ((*p++ = *_Src++) != 0 && --available > 0 && --_Count > 0) + { + } + if (_Count == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_Count == _TRUNCATE) + { + _Dst[_SizeInBytes - 1] = 0; + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* wcsncpy_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl wcsncpy_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src, size_t _Count) +{ + return wcsncpy_s(_Dst, _SizeInWords, _Src, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl wcsncpy_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count) +{ + WCHAR *p; + size_t available; + + if (_Count == 0 && _Dst == nullptr && _SizeInWords == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + if (_Count == 0) + { + /* notice that the source string pointer can be nullptr in this case */ + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + return 0; + } + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); + + p = _Dst; + available = _SizeInWords; + if (_Count == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while ((*p++ = *_Src++) != 0 && --available > 0 && --_Count > 0) + { + } + if (_Count == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_Count == _TRUNCATE) + { + _Dst[_SizeInWords - 1] = 0; + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbsnbcpy_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsnbcpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src, size_t _CountInBytes) +{ + return _mbsnbcpy_s(_Dst, _SizeInBytes, _Src, _CountInBytes); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsnbcpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes) +{ + unsigned char *p; + size_t available; + + if (_CountInBytes == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_CountInBytes == 0) + { + /* notice that the source string pointer can be nullptr in this case */ + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + return 0; + } + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + if (_CountInBytes == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while ((*p++ = *_Src++) != 0 && --available > 0 && --_CountInBytes > 0) + { + } + if (_CountInBytes == 0) + { + *p++ = 0; + } + } + + if (available == 0) + { + if ((*_Src == 0 || _CountInBytes == 1) && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the source string ended with a lead byte: we remove it */ + p[-1] = 0; + return 0; + } + if (_CountInBytes == _TRUNCATE) + { + if (_SizeInBytes > 1 && _SAFECRT__ISMBBLEAD(_Dst[_SizeInBytes - 2])) + { + _Dst[_SizeInBytes - 2] = 0; + _SAFECRT__FILL_BYTE(_Dst[_SizeInBytes - 1]); + } + else + { + _Dst[_SizeInBytes - 1] = 0; + } + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-2])) + { + /* the source string ended with a lead byte: we remove it */ + p[-2] = 0; + available++; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _mbsncpy_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsncpy_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src, size_t _CountInChars) +{ + return _mbsncpy_s(_Dst, _SizeInBytes, _Src, _CountInChars); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsncpy_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars) +{ + unsigned char *p; + size_t available; + + if (_CountInChars == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_CountInChars == 0) + { + /* notice that the source string pointer can be nullptr in this case */ + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + return 0; + } + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + if (_CountInChars == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + do + { + if (_SAFECRT__ISMBBLEAD(*_Src)) + { + if (_Src[1] == 0) + { + /* the source string ended with a lead byte: we remove it */ + *p = 0; + break; + } + if (available <= 2) + { + /* not enough space */ + available = 0; + break; + } + *p++ = *_Src++; + *p++ = *_Src++; + available -= 2; + } + else + { + if ((*p++ = *_Src++) == 0 || --available == 0) + { + break; + } + } + } + while (--_CountInChars > 0); + if (_CountInChars == 0) + { + *p++ = 0; + } + } + + if (available == 0) + { + if (_CountInChars == _TRUNCATE) + { + if (_SizeInBytes > 1 && _SAFECRT__ISMBBLEAD(_Dst[_SizeInBytes - 2])) + { + _Dst[_SizeInBytes - 2] = 0; + _SAFECRT__FILL_BYTE(_Dst[_SizeInBytes - 1]); + } + else + { + _Dst[_SizeInBytes - 1] = 0; + } + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* strcat_s */ +/* + * strcat_s, wcscat_s append string _Src to _Dst; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst + */ +_SAFECRT__EXTERN_C +errno_t __cdecl strcat_s(char *_Dst, size_t _SizeInBytes, const char *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl strcat_s(char (&_Dst)[_SizeInBytes], const char *_Src) +{ + return strcat_s(_Dst, _SizeInBytes, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl strcat_s(char *_Dst, size_t _SizeInBytes, const char *_Src) +{ + char *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* wcscat_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl wcscat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl wcscat_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src) +{ + return wcscat_s(_Dst, _SizeInWords, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl wcscat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src) +{ + WCHAR *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); + + p = _Dst; + available = _SizeInWords; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); + } + + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbscat_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbscat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src) +{ + return _mbscat_s(_Dst, _SizeInBytes, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbscat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src) +{ + unsigned char *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available = 1; + } + else + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available++; + } + + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + + if (available == 0) + { + if (*_Src == 0 && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the source string ended with a lead byte: we remove it */ + p[-1] = 0; + return 0; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-2])) + { + /* the source string ended with a lead byte: we remove it */ + p[-2] = 0; + available++; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* strncat_s */ +/* + * strncat_s, wcsncat_s append at max _Count characters from string _Src to _Dst; + * string _Dst will always be null-terminated; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; + * if _Count == _TRUNCATE, we will append as many characters as we can from _Src to _Dst, and + * return STRUNCATE if _Src does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); + * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed + */ +_SAFECRT__EXTERN_C +errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl strncat_s(char (&_Dst)[_SizeInBytes], const char *_Src, size_t _Count) +{ + return strncat_s(_Dst, _SizeInBytes, _Src, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl strncat_s(char *_Dst, size_t _SizeInBytes, const char *_Src, size_t _Count) +{ + char *p; + size_t available; + if (_Count == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_Count != 0) + { + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + } + + p = _Dst; + available = _SizeInBytes; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + + if (_Count == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while (_Count > 0 && (*p++ = *_Src++) != 0 && --available > 0) + { + _Count--; + } + if (_Count == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_Count == _TRUNCATE) + { + _Dst[_SizeInBytes - 1] = 0; + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* wcsncat_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl wcsncat_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Src, size_t _Count) +{ + return wcsncat_s(_Dst, _SizeInWords, _Src, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl wcsncat_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Src, size_t _Count) +{ + WCHAR *p; + size_t available; + if (_Count == 0 && _Dst == nullptr && _SizeInWords == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + if (_Count != 0) + { + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInWords); + } + + p = _Dst; + available = _SizeInWords; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); + } + + if (_Count == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while (_Count > 0 && (*p++ = *_Src++) != 0 && --available > 0) + { + _Count--; + } + if (_Count == 0) + { + *p = 0; + } + } + + if (available == 0) + { + if (_Count == _TRUNCATE) + { + _Dst[_SizeInWords - 1] = 0; + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbsnbcat_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsnbcat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src, size_t _CountInBytes) +{ + return _mbsnbcat_s(_Dst, _SizeInBytes, _Src, size_t _CountInBytes); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsnbcat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInBytes) +{ + unsigned char *p; + size_t available; + if (_CountInBytes == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_CountInBytes != 0) + { + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + } + + p = _Dst; + available = _SizeInBytes; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available = 1; + } + else + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available++; + } + + if (_CountInBytes == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while (_CountInBytes > 0 && (*p++ = *_Src++) != 0 && --available > 0) + { + _CountInBytes--; + } + if (_CountInBytes == 0) + { + *p++ = 0; + } + } + + if (available == 0) + { + if ((*_Src == 0 || _CountInBytes == 1) && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the source string ended with a lead byte: we remove it */ + p[-1] = 0; + return 0; + } + if (_CountInBytes == _TRUNCATE) + { + if (_SizeInBytes > 1 && _SAFECRT__ISMBBLEAD(_Dst[_SizeInBytes - 2])) + { + _Dst[_SizeInBytes - 2] = 0; + _SAFECRT__FILL_BYTE(_Dst[_SizeInBytes - 1]); + } + else + { + _Dst[_SizeInBytes - 1] = 0; + } + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-2])) + { + /* the source string ended with a lead byte: we remove it */ + p[-2] = 0; + available++; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _mbsncat_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsncat_s(unsigned char (&_Dst)[_SizeInBytes], const unsigned char *_Src, size_t _CountInChars) +{ + return _mbsncat_s(_Dst, _SizeInBytes, _Src, size_t _CountInChars); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsncat_s(unsigned char *_Dst, size_t _SizeInBytes, const unsigned char *_Src, size_t _CountInChars) +{ + unsigned char *p; + size_t available; + if (_CountInChars == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_CountInChars != 0) + { + _SAFECRT__VALIDATE_POINTER_RESET_STRING(_Src, _Dst, _SizeInBytes); + } + + p = _Dst; + available = _SizeInBytes; + while (available > 0 && *p != 0) + { + p++; + available--; + } + + if (available == 0) + { + if (*p == 0 && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available = 1; + } + else + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + } + if (available < _SizeInBytes && _SAFECRT__ISMBBLEAD(p[-1])) + { + /* the original string ended with a lead byte: we remove it */ + p--; + *p = 0; + available++; + } + + if (_CountInChars == _TRUNCATE) + { + while ((*p++ = *_Src++) != 0 && --available > 0) + { + } + } + else + { + while (_CountInChars > 0) + { + if (_SAFECRT__ISMBBLEAD(*_Src)) + { + if (_Src[1] == 0) + { + /* the source string ended with a lead byte: we remove it */ + *p = 0; + break; + } + if (available <= 2) + { + /* not enough space */ + available = 0; + break; + } + *p++ = *_Src++; + *p++ = *_Src++; + available -= 2; + } + else + { + if ((*p++ = *_Src++) == 0 || --available == 0) + { + break; + } + } + _CountInChars--; + } + if (_CountInChars == 0) + { + *p++ = 0; + } + } + + if (available == 0) + { + if (_CountInChars == _TRUNCATE) + { + if (_SizeInBytes > 1 && _SAFECRT__ISMBBLEAD(_Dst[_SizeInBytes - 2])) + { + _Dst[_SizeInBytes - 2] = 0; + _SAFECRT__FILL_BYTE(_Dst[_SizeInBytes - 1]); + } + else + { + _Dst[_SizeInBytes - 1] = 0; + } + return STRUNCATE; + } + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _strset_s */ +/* + * _strset_s, _wcsset_s ; + * will call _SAFECRT_INVALID_PARAMETER if _Dst is not null terminated. + */ +_SAFECRT__EXTERN_C +errno_t __cdecl _strset_s(char *_Dst, size_t _SizeInBytes, int _Value); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _strset_s(char (&_Dst)[_SizeInBytes], int _Value) +{ + return _strset_s(_Dst, _SizeInBytes, _Value); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _strset_s(char *_Dst, size_t _SizeInBytes, int _Value) +{ + char *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while (*p != 0 && --available > 0) + { + *p++ = (char)_Value; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* _wcsset_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl _wcsset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _wcsset_s(WCHAR (&_Dst)[_SizeInWords], WCHAR _Value) +{ + return _wcsset_s(_Dst, _SizeInWords, _Value); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _wcsset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value) +{ + WCHAR *p; + size_t available; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + + p = _Dst; + available = _SizeInWords; + while (*p != 0 && --available > 0) + { + *p++ = (WCHAR)_Value; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbsset_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _Value) +{ + return _mbsset_s(_Dst, _SizeInBytes, _Value); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value) +{ + int mbcs_error = 0; + unsigned char *p; + size_t available; + unsigned char highval, lowval; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + highval = (unsigned char)(_Value >> 8); + lowval = (unsigned char)(_Value & 0x00ff); + if (highval != 0) + { + if (_SAFECRT__ISMBBLEAD(highval) && lowval != 0) + { + while (*p != 0 && --available > 0) + { + if (p[1] == 0) + { + /* do not orphan leadbyte */ + *p++ = ' '; + break; + } + *p++ = highval; + if (--available == 0) + { + break; + } + *p++ = lowval; + } + } + else + { + mbcs_error = 1; + highval = 0; + lowval = ' '; + } + } + else + { + if (_SAFECRT__ISMBBLEAD(lowval)) + { + mbcs_error = 1; + lowval = ' '; + } + } + if (highval == 0) + { + while (*p != 0 && --available > 0) + { + *p++ = lowval; + } + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + if (mbcs_error) + { + _SAFECRT__SET_ERRNO(EILSEQ); return EILSEQ; + } + else + { + return 0; + } +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _strnset_s */ +/* + * _strnset_s, _wcsnset_s ; + * will call _SAFECRT_INVALID_PARAMETER if _Dst is not null terminated. + */ +_SAFECRT__EXTERN_C +errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _strnset_s(char (&_Dst)[_SizeInBytes], int _Value, size_t _Count) +{ + return _strnset_s(_Dst, _SizeInBytes, _Value, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _strnset_s(char *_Dst, size_t _SizeInBytes, int _Value, size_t _Count) +{ + char *p; + size_t available; + + /* validation section */ + if (_Count == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + while (*p != 0 && _Count > 0 && --available > 0) + { + *p++ = (char)_Value; + --_Count; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + if (_Count == 0) + { + *p = 0; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + return 0; +} + +#endif + +/* _wcsnset_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_t _Count); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _wcsnset_s(WCHAR (&_Dst)[_SizeInWords], WCHAR _Value, size_t _Count) +{ + return _wcsnset_s(_Dst, _SizeInWords, _Value, _Count); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _wcsnset_s(WCHAR *_Dst, size_t _SizeInWords, WCHAR _Value, size_t _Count) +{ + WCHAR *p; + size_t available; + + /* validation section */ + if (_Count == 0 && _Dst == nullptr && _SizeInWords == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + + p = _Dst; + available = _SizeInWords; + while (*p != 0 && _Count > 0 && --available > 0) + { + *p++ = (WCHAR)_Value; + --_Count; + } + + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInWords); + } + if (_Count == 0) + { + *p = 0; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, _SizeInWords - available + 1); + return 0; +} + +#endif + +/* _mbsnbset_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInBytes); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsnbset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _Value, size_t _CountInBytes) +{ + return _mbsnbset_s(_Dst, _SizeInBytes, _Value, _CountInBytes); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsnbset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInBytes) +{ + int mbcs_error = 0; + unsigned char *p; + size_t available; + unsigned char highval, lowval; + + /* validation section */ + if (_CountInBytes == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + highval = (unsigned char)(_Value >> 8); + lowval = (unsigned char)(_Value & 0x00ff); + if (highval != 0) + { + if (_SAFECRT__ISMBBLEAD(highval) && lowval != 0) + { + while (*p != 0 && _CountInBytes > 0 && --available > 0) + { + if (_CountInBytes == 1 || p[1] == 0) + { + /* do not orphan leadbyte */ + *p++ = ' '; + --_CountInBytes; + break; + } + *p++ = highval; + if (--available == 0) + { + break; + } + *p++ = lowval; + _CountInBytes -= 2; + } + } + else + { + mbcs_error = 1; + highval = 0; + lowval = ' '; + } + } + else + { + if (_SAFECRT__ISMBBLEAD(lowval)) + { + mbcs_error = 1; + lowval = ' '; + } + } + if (highval == 0) + { + while (*p != 0 && available > 0 && _CountInBytes > 0) + { + *p++ = lowval; + --available; + --_CountInBytes; + } + } + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + if (_CountInBytes == 0) + { + *p = 0; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + if (mbcs_error) + { + _SAFECRT__SET_ERRNO(EILSEQ); return EILSEQ; + } + else + { + return 0; + } +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _mbsnset_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInChars); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbsnset_s(unsigned char (&_Dst)[_SizeInBytes], unsigned int _Value, size_t _CountInChars) +{ + return _mbsnset_s(_Dst, _SizeInBytes, _Value, _CountInChars); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbsnset_s(unsigned char *_Dst, size_t _SizeInBytes, unsigned int _Value, size_t _CountInChars) +{ + int mbcs_error = 0; + unsigned char *p; + size_t available; + unsigned char highval, lowval; + + /* validation section */ + if (_CountInChars == 0 && _Dst == nullptr && _SizeInBytes == 0) + { + /* this case is allowed; nothing to do */ + return 0; + } + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + p = _Dst; + available = _SizeInBytes; + highval = (unsigned char)(_Value >> 8); + lowval = (unsigned char)(_Value & 0x00ff); + if (highval != 0) + { + if (_SAFECRT__ISMBBLEAD(highval) && lowval != 0) + { + while (*p != 0 && _CountInChars > 0 && --available > 0) + { + if (p[1] == 0) + { + /* do not orphan leadbyte */ + *p++ = ' '; + break; + } + *p++ = highval; + if (--available == 0) + { + break; + } + *p++ = lowval; + --_CountInChars; + } + } + else + { + mbcs_error = 1; + highval = 0; + lowval = ' '; + } + } + else + { + if (_SAFECRT__ISMBBLEAD(lowval)) + { + mbcs_error = 1; + lowval = ' '; + } + } + if (highval == 0) + { + while (*p != 0 && available > 0 && _CountInChars > 0) + { + *p++ = lowval; + --available; + --_CountInChars; + } + } + if (available == 0) + { + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_DEST_NOT_NULL_TERMINATED(_Dst, _SizeInBytes); + } + if (_CountInChars == 0) + { + *p = 0; + } + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, _SizeInBytes - available + 1); + if (mbcs_error) + { + _SAFECRT__SET_ERRNO(EILSEQ); return EILSEQ; + } + else + { + return 0; + } +} + +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* _mbccpy_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopied, const unsigned char *_Src); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _mbccpy_s(unsigned char (&_Dst)[_SizeInBytes], int *_PCopied, const unsigned char *_Src) +{ + return _mbccpy_s(_Dst, _SizeInBytes, _PCopied, _Src); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _mbccpy_s(unsigned char *_Dst, size_t _SizeInBytes, int *_PCopied, const unsigned char *_Src) +{ + /* validation section */ + if (_PCopied != nullptr) { *_PCopied = 0; }; + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + if (_Src == nullptr) + { + *_Dst = '\0'; + _SAFECRT__RETURN_EINVAL; + } + + /* copy */ + if (_SAFECRT__ISMBBLEAD(*_Src)) + { + if (_Src[1] == '\0') + { + /* the source string contained a lead byte followed by the null terminator: + we copy only the null terminator and return EILSEQ to indicate the + malformed char */ + *_Dst = '\0'; + if (_PCopied != nullptr) { *_PCopied = 1; }; + _SAFECRT__SET_ERRNO(EILSEQ); return EILSEQ; + } + if (_SizeInBytes < 2) + { + *_Dst = '\0'; + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + } + *_Dst++ = *_Src++; + *_Dst = *_Src; + if (_PCopied != nullptr) { *_PCopied = 2; }; + } + else + { + *_Dst = *_Src; + if (_PCopied != nullptr) { *_PCopied = 1; }; + } + + return 0; +} +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +/* strtok_s */ +/* + * strtok_s, wcstok_s ; + * uses _Context to keep track of the position in the string. + */ +_SAFECRT__EXTERN_C +char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context); + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +char * __cdecl strtok_s(char *_String, const char *_Control, char **_Context) +{ + unsigned char *str; + const unsigned char *ctl = (const unsigned char *)_Control; + unsigned char map[32]; + int count; + + /* validation section */ + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); + _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); + + /* Clear control map */ + for (count = 0; count < 32; count++) + { + map[count] = 0; + } + + /* Set bits in delimiter table */ + do { + map[*ctl >> 3] |= (1 << (*ctl & 7)); + } while (*ctl++); + + /* If string is nullptr, set str to the saved + * pointer (i.e., continue breaking tokens out of the string + * from the last strtok call) */ + if (_String != nullptr) + { + str = (unsigned char *)_String; + } + else + { + str = (unsigned char *)*_Context; + } + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets str to point to the terminal + * null (*str == 0) */ + while ((map[*str >> 3] & (1 << (*str & 7))) && *str != 0) + { + str++; + } + + _String = (char *)str; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *str != 0 ; str++ ) + { + if (map[*str >> 3] & (1 << (*str & 7))) + { + *str++ = 0; + break; + } + } + + /* Update context */ + *_Context = (char *)str; + + /* Determine if a token has been found. */ + if (_String == (char *)str) + { + return nullptr; + } + else + { + return _String; + } +} +#endif + +/* wcstok_s */ +_SAFECRT__EXTERN_C +WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context); + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +WCHAR * __cdecl wcstok_s(WCHAR *_String, const WCHAR *_Control, WCHAR **_Context) +{ + WCHAR *token; + const WCHAR *ctl; + + /* validation section */ + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); + _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); + + /* If string==nullptr, continue with previous string */ + if (!_String) + { + _String = *_Context; + } + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets string to point to the terminal null. */ + for ( ; *_String != 0 ; _String++) + { + for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++) + ; + if (*ctl == 0) + { + break; + } + } + + token = _String; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *_String != 0 ; _String++) + { + for (ctl = _Control; *ctl != 0 && *ctl != *_String; ctl++) + ; + if (*ctl != 0) + { + *_String++ = 0; + break; + } + } + + /* Update the context */ + *_Context = _String; + + /* Determine if a token has been found. */ + if (token == _String) + { + return nullptr; + } + else + { + return token; + } +} +#endif + +/* _mbstok_s */ +#if _SAFECRT_DEFINE_MBS_FUNCTIONS + +_SAFECRT__EXTERN_C +unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_Control, unsigned char **_Context); + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +unsigned char * __cdecl _mbstok_s(unsigned char *_String, const unsigned char *_Control, unsigned char **_Context) +{ + unsigned char *token; + const unsigned char *ctl; + int dbc; + + /* validation section */ + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Context, EINVAL, nullptr); + _SAFECRT__VALIDATE_POINTER_ERROR_RETURN(_Control, EINVAL, nullptr); + _SAFECRT__VALIDATE_CONDITION_ERROR_RETURN(_String != nullptr || *_Context != nullptr, EINVAL, nullptr); + + /* If string==nullptr, continue with previous string */ + if (!_String) + { + _String = *_Context; + } + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets string to point to the terminal null. */ + for ( ; *_String != 0; _String++) + { + for (ctl = _Control; *ctl != 0; ctl++) + { + if (_SAFECRT__ISMBBLEAD(*ctl)) + { + if (*ctl == *_String && (ctl[1] == 0 || ctl[1] == _String[1])) + { + break; + } + ctl++; + } + else + { + if (*ctl == *_String) + { + break; + } + } + } + if (*ctl == 0) + { + break; + } + if (_SAFECRT__ISMBBLEAD(*_String)) + { + _String++; + if (*_String == 0) + { + break; + } + } + } + + token = _String; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *_String != 0; _String++) + { + for (ctl = _Control, dbc = 0; *ctl != 0; ctl++) + { + if (_SAFECRT__ISMBBLEAD(*ctl)) + { + if (*ctl == *_String && (ctl[1] == 0 || ctl[1] == _String[1])) + { + dbc = 1; + break; + } + ctl++; + } + else + { + if (*ctl == *_String) + { + break; + } + } + } + if (*ctl != 0) + { + *_String++ = 0; + if (dbc && ctl[1] != 0) + { + *_String++ = 0; + } + break; + } + if (_SAFECRT__ISMBBLEAD(*_String)) + { + _String++; + if (*_String == 0) + { + break; + } + } + } + + /* Update the context */ + *_Context = _String; + + /* Determine if a token has been found. */ + if (token == _String) + { + return nullptr; + } + else + { + return token; + } +} +#endif + +#endif /* _SAFECRT_DEFINE_MBS_FUNCTIONS */ + +#ifndef PAL_STDCPP_COMPAT +/* strnlen */ +/* + * strnlen, wcsnlen ; + * returns inMaxSize if the null character is not found. + */ +_SAFECRT__EXTERN_C +size_t __cdecl strnlen(const char* inString, size_t inMaxSize); + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +size_t __cdecl strnlen(const char* inString, size_t inMaxSize) +{ + size_t n; + + /* Note that we do not check if s == nullptr, because we do not + * return errno_t... + */ + + for (n = 0; n < inMaxSize && *inString; n++, inString++) + ; + + return n; +} + +#endif + +/* wcsnlen */ +_SAFECRT__EXTERN_C +size_t __cdecl wcsnlen(const WCHAR *inString, size_t inMaxSize); + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +size_t __cdecl wcsnlen(const WCHAR *inString, size_t inMaxSize) +{ + size_t n; + + /* Note that we do not check if s == nullptr, because we do not + * return errno_t... + */ + + for (n = 0; n < inMaxSize && *inString; n++, inString++) + ; + + return n; +} + +#endif +#endif // PAL_STDCPP_COMPAT + +/* _makepath_s */ +/* + * _makepath_s, _wmakepath_s build up a path starting from the specified components; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; + * any of _Drive, _Dir, _Filename and _Ext can be nullptr + */ +_SAFECRT__EXTERN_C +errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, const char *_Dir, const char *_Filename, const char *_Ext); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _makepath_s(char (&_Dst)[_SizeInBytes], const char *_Drive, const char *_Dir, const char *_Filename, const char *_Ext) +{ + return _makepath_s(_Dst, _SizeInBytes, _Drive, _Dir, _Filename, _Ext); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _makepath_s(char *_Dst, size_t _SizeInBytes, const char *_Drive, const char *_Dir, const char *_Filename, const char *_Ext) +{ + size_t written; + const char *p; + char *d; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInBytes); + + /* copy drive */ + written = 0; + d = _Dst; + if (_Drive != nullptr && *_Drive != 0) + { + written += 2; + if(written >= _SizeInBytes) + { + goto error_return; + } + *d++ = *_Drive; + *d++ = ':'; + } + + /* copy dir */ + p = _Dir; + if (p != nullptr && *p != 0) + { + do { + if(++written >= _SizeInBytes) + { + goto error_return; + } + *d++ = *p++; + } while (*p != 0); + + p = (const char *)_SAFECRT__MBSDEC((const unsigned char *)_Dir, (const unsigned char *)p); + if (*p != '/' && *p != '\\') + { + if(++written >= _SizeInBytes) + { + goto error_return; + } + *d++ = '\\'; + } + } + + /* copy fname */ + p = _Filename; + if (p != nullptr) + { + while (*p != 0) + { + if(++written >= _SizeInBytes) + { + goto error_return; + } + *d++ = *p++; + } + } + + /* copy extension; check to see if a '.' needs to be inserted */ + p = _Ext; + if (p != nullptr) + { + if (*p != 0 && *p != '.') + { + if(++written >= _SizeInBytes) + { + goto error_return; + } + *d++ = '.'; + } + while (*p != 0) + { + if(++written >= _SizeInBytes) + { + goto error_return; + } + *d++ = *p++; + } + } + + if(++written > _SizeInBytes) + { + goto error_return; + } + *d = 0; + _SAFECRT__FILL_STRING(_Dst, _SizeInBytes, written); + return 0; + +error_return: + _SAFECRT__RESET_STRING(_Dst, _SizeInBytes); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInBytes); + /* should never happen, but compiler can't tell */ + return EINVAL; +} +#endif + +/* _wmakepath_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Drive, const WCHAR *_Dir, const WCHAR *_Filename, const WCHAR *_Ext); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +errno_t __cdecl _wmakepath_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Drive, const WCHAR *_Dir, const WCHAR *_Filename, const WCHAR *_Ext) +{ + return _wmakepath_s(_Dst, _SizeInWords, _Drive, _Dir, _Filename, _Ext); +} +#endif + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _wmakepath_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Drive, const WCHAR *_Dir, const WCHAR *_Filename, const WCHAR *_Ext) +{ + size_t written; + const WCHAR *p; + WCHAR *d; + + /* validation section */ + _SAFECRT__VALIDATE_STRING(_Dst, _SizeInWords); + + /* copy drive */ + written = 0; + d = _Dst; + if (_Drive != nullptr && *_Drive != 0) + { + written += 2; + if(written >= _SizeInWords) + { + goto error_return; + } + *d++ = *_Drive; + *d++ = L':'; + } + + /* copy dir */ + p = _Dir; + if (p != nullptr && *p != 0) + { + do { + if(++written >= _SizeInWords) + { + goto error_return; + } + *d++ = *p++; + } while (*p != 0); + + p = p - 1; + if (*p != L'/' && *p != L'\\') + { + if(++written >= _SizeInWords) + { + goto error_return; + } + *d++ = L'\\'; + } + } + + /* copy fname */ + p = _Filename; + if (p != nullptr) + { + while (*p != 0) + { + if(++written >= _SizeInWords) + { + goto error_return; + } + *d++ = *p++; + } + } + + /* copy extension; check to see if a '.' needs to be inserted */ + p = _Ext; + if (p != nullptr) + { + if (*p != 0 && *p != L'.') + { + if(++written >= _SizeInWords) + { + goto error_return; + } + *d++ = L'.'; + } + while (*p != 0) + { + if(++written >= _SizeInWords) + { + goto error_return; + } + *d++ = *p++; + } + } + + if(++written > _SizeInWords) + { + goto error_return; + } + *d = 0; + _SAFECRT__FILL_STRING(_Dst, _SizeInWords, written); + return 0; + +error_return: + _SAFECRT__RESET_STRING(_Dst, _SizeInWords); + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Dst, _SizeInWords); + /* should never happen, but compiler can't tell */ + return EINVAL; +} +#endif + +/* _splitpath_s */ +/* + * _splitpath_s, _wsplitpath_s decompose a path into the specified components; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in + * any of _Drive, _Dir, _Filename and _Ext; + * any of _Drive, _Dir, _Filename and _Ext can be nullptr, but the correspondent size must + * be set to 0, e.g. (_Drive == nullptr && _DriveSize == 0) is allowed, but + * (_Drive == nullptr && _DriveSize != 0) is considered an invalid parameter + */ +_SAFECRT__EXTERN_C +errno_t __cdecl _splitpath_s( + const char *_Path, + char *_Drive, size_t _DriveSize, + char *_Dir, size_t _DirSize, + char *_Filename, size_t _FilenameSize, + char *_Ext, size_t _ExtSize +); + +/* no C++ overload for _splitpath_s */ + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _splitpath_s( + const char *_Path, + char *_Drive, size_t _DriveSize, + char *_Dir, size_t _DirSize, + char *_Filename, size_t _FilenameSize, + char *_Ext, size_t _ExtSize +) +{ + const char *tmp; + const char *last_slash; + const char *dot; + int drive_set = 0; + size_t length = 0; + int bEinval = 0; + + /* validation section */ + _SAFECRT__VALIDATE_POINTER(_Path); + if ((_Drive == nullptr && _DriveSize != 0) || (_Drive != nullptr && _DriveSize == 0)) + { + goto error_einval; + } + if ((_Dir == nullptr && _DirSize != 0) || (_Dir != nullptr && _DirSize == 0)) + { + goto error_einval; + } + if ((_Filename == nullptr && _FilenameSize != 0) || (_Filename != nullptr && _FilenameSize == 0)) + { + goto error_einval; + } + if ((_Ext == nullptr && _ExtSize != 0) || (_Ext != nullptr && _ExtSize == 0)) + { + goto error_einval; + } + + /* check if _Path begins with the longpath prefix */ + if (_Path[0] == '\\' && _Path[1] == '\\' && _Path[2] == '?' && _Path[3] == '\\') + { + _Path += 4; + } + + /* extract drive letter and ':', if any */ + if (!drive_set) + { + size_t skip = _MAX_DRIVE - 2; + tmp = _Path; + while (skip > 0 && *tmp != 0) + { + skip--; + tmp++; + } + if (*tmp == ':') + { + if (_Drive != nullptr) + { + if (_DriveSize < _MAX_DRIVE) + { + goto error_erange; + } + strncpy_s(_Drive, _DriveSize, _Path, _MAX_DRIVE - 1); + } + _Path = tmp + 1; + } + else + { + if (_Drive != nullptr) + { + _SAFECRT__RESET_STRING(_Drive, _DriveSize); + } + } + } + + /* extract path string, if any. _Path now points to the first character + * of the path, if any, or the filename or extension, if no path was + * specified. Scan ahead for the last occurence, if any, of a '/' or + * '\' path separator character. If none is found, there is no path. + * We will also note the last '.' character found, if any, to aid in + * handling the extension. + */ + last_slash = nullptr; + dot = nullptr; + tmp = _Path; + for (; *tmp != 0; ++tmp) + { +#if _SAFECRT_DEFINE_MBS_FUNCTIONS +#pragma warning(push) +#pragma warning(disable:4127) + if (_SAFECRT__ISMBBLEAD(*tmp)) +#pragma warning(pop) +#else + if (0) +#endif + { + tmp++; + } + else + { + if (*tmp == '/' || *tmp == '\\') + { + /* point to one beyond for later copy */ + last_slash = tmp + 1; + } + else if (*tmp == '.') + { + dot = tmp; + } + } + } + + if (last_slash != nullptr) + { + /* found a path - copy up through last_slash or max characters + * allowed, whichever is smaller + */ + if (_Dir != nullptr) { + length = (size_t)(last_slash - _Path); + if (_DirSize <= length) + { + goto error_erange; + } + strncpy_s(_Dir, _DirSize, _Path, length); + } + _Path = last_slash; + } + else + { + /* there is no path */ + if (_Dir != nullptr) + { + _SAFECRT__RESET_STRING(_Dir, _DirSize); + } + } + + /* extract file name and extension, if any. Path now points to the + * first character of the file name, if any, or the extension if no + * file name was given. Dot points to the '.' beginning the extension, + * if any. + */ + if (dot != nullptr && (dot >= _Path)) + { + /* found the marker for an extension - copy the file name up to the '.' */ + if (_Filename) + { + length = (size_t)(dot - _Path); + if (_FilenameSize <= length) + { + goto error_erange; + } + strncpy_s(_Filename, _FilenameSize, _Path, length); + } + /* now we can get the extension - remember that tmp still points + * to the terminating nullptr character of path. + */ + if (_Ext) + { + length = (size_t)(tmp - dot); + if (_ExtSize <= length) + { + goto error_erange; + } + strncpy_s(_Ext, _ExtSize, dot, length); + } + } + else + { + /* found no extension, give empty extension and copy rest of + * string into fname. + */ + if (_Filename) + { + length = (size_t)(tmp - _Path); + if (_FilenameSize <= length) + { + goto error_erange; + } + strncpy_s(_Filename, _FilenameSize, _Path, length); + } + if (_Ext) + { + _SAFECRT__RESET_STRING(_Ext, _ExtSize); + } + } + + return 0; + +error_einval: + bEinval = 1; + +error_erange: + if (_Drive != nullptr && _DriveSize > 0) + { + _SAFECRT__RESET_STRING(_Drive, _DriveSize); + } + if (_Dir != nullptr && _DirSize > 0) + { + _SAFECRT__RESET_STRING(_Dir, _DirSize); + } + if (_Filename != nullptr && _FilenameSize > 0) + { + _SAFECRT__RESET_STRING(_Filename, _FilenameSize); + } + if (_Ext != nullptr && _ExtSize > 0) + { + _SAFECRT__RESET_STRING(_Ext, _ExtSize); + } + + if (bEinval) + { + _SAFECRT__RETURN_EINVAL; + } + + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Strings, _StringSizes); + /* should never happen, but compiler can't tell */ + return EINVAL; +} +#endif + +/* _wsplitpath_s */ +_SAFECRT__EXTERN_C +errno_t __cdecl _wsplitpath_s( + const WCHAR *_Path, + WCHAR *_Drive, size_t _DriveSize, + WCHAR *_Dir, size_t _DirSize, + WCHAR *_Filename, size_t _FilenameSize, + WCHAR *_Ext, size_t _ExtSize +); + +/* no C++ overload for _wsplitpath_s */ + +#if _SAFECRT_USE_INLINES || _SAFECRT_IMPL + +_SAFECRT__INLINE +errno_t __cdecl _wsplitpath_s( + const WCHAR *_Path, + WCHAR *_Drive, size_t _DriveSize, + WCHAR *_Dir, size_t _DirSize, + WCHAR *_Filename, size_t _FilenameSize, + WCHAR *_Ext, size_t _ExtSize +) +{ + const WCHAR *tmp; + const WCHAR *last_slash; + const WCHAR *dot; + int drive_set = 0; + size_t length = 0; + int bEinval = 0; + + /* validation section */ + _SAFECRT__VALIDATE_POINTER(_Path); + if ((_Drive == nullptr && _DriveSize != 0) || (_Drive != nullptr && _DriveSize == 0)) + { + goto error_einval; + } + if ((_Dir == nullptr && _DirSize != 0) || (_Dir != nullptr && _DirSize == 0)) + { + goto error_einval; + } + if ((_Filename == nullptr && _FilenameSize != 0) || (_Filename != nullptr && _FilenameSize == 0)) + { + goto error_einval; + } + if ((_Ext == nullptr && _ExtSize != 0) || (_Ext != nullptr && _ExtSize == 0)) + { + goto error_einval; + } + + /* check if _Path begins with the longpath prefix */ + if (_Path[0] == L'\\' && _Path[1] == L'\\' && _Path[2] == L'?' && _Path[3] == L'\\') + { + _Path += 4; + } + + /* extract drive letter and ':', if any */ + if (!drive_set) + { + size_t skip = _MAX_DRIVE - 2; + tmp = _Path; + while (skip > 0 && *tmp != 0) + { + skip--; + tmp++; + } + if (*tmp == L':') + { + if (_Drive != nullptr) + { + if (_DriveSize < _MAX_DRIVE) + { + goto error_erange; + } + wcsncpy_s(_Drive, _DriveSize, _Path, _MAX_DRIVE - 1); + } + _Path = tmp + 1; + } + else + { + if (_Drive != nullptr) + { + _SAFECRT__RESET_STRING(_Drive, _DriveSize); + } + } + } + + /* extract path string, if any. _Path now points to the first character + * of the path, if any, or the filename or extension, if no path was + * specified. Scan ahead for the last occurence, if any, of a '/' or + * '\' path separator character. If none is found, there is no path. + * We will also note the last '.' character found, if any, to aid in + * handling the extension. + */ + last_slash = nullptr; + dot = nullptr; + tmp = _Path; + for (; *tmp != 0; ++tmp) + { + { + if (*tmp == L'/' || *tmp == L'\\') + { + /* point to one beyond for later copy */ + last_slash = tmp + 1; + } + else if (*tmp == L'.') + { + dot = tmp; + } + } + } + + if (last_slash != nullptr) + { + /* found a path - copy up through last_slash or max characters + * allowed, whichever is smaller + */ + if (_Dir != nullptr) { + length = (size_t)(last_slash - _Path); + if (_DirSize <= length) + { + goto error_erange; + } + wcsncpy_s(_Dir, _DirSize, _Path, length); + } + _Path = last_slash; + } + else + { + /* there is no path */ + if (_Dir != nullptr) + { + _SAFECRT__RESET_STRING(_Dir, _DirSize); + } + } + + /* extract file name and extension, if any. Path now points to the + * first character of the file name, if any, or the extension if no + * file name was given. Dot points to the '.' beginning the extension, + * if any. + */ + if (dot != nullptr && (dot >= _Path)) + { + /* found the marker for an extension - copy the file name up to the '.' */ + if (_Filename) + { + length = (size_t)(dot - _Path); + if (_FilenameSize <= length) + { + goto error_erange; + } + wcsncpy_s(_Filename, _FilenameSize, _Path, length); + } + /* now we can get the extension - remember that tmp still points + * to the terminating nullptr character of path. + */ + if (_Ext) + { + length = (size_t)(tmp - dot); + if (_ExtSize <= length) + { + goto error_erange; + } + wcsncpy_s(_Ext, _ExtSize, dot, length); + } + } + else + { + /* found no extension, give empty extension and copy rest of + * string into fname. + */ + if (_Filename) + { + length = (size_t)(tmp - _Path); + if (_FilenameSize <= length) + { + goto error_erange; + } + wcsncpy_s(_Filename, _FilenameSize, _Path, length); + } + if (_Ext) + { + _SAFECRT__RESET_STRING(_Ext, _ExtSize); + } + } + + return 0; + +error_einval: + bEinval = 1; + +error_erange: + if (_Drive != nullptr && _DriveSize > 0) + { + _SAFECRT__RESET_STRING(_Drive, _DriveSize); + } + if (_Dir != nullptr && _DirSize > 0) + { + _SAFECRT__RESET_STRING(_Dir, _DirSize); + } + if (_Filename != nullptr && _FilenameSize > 0) + { + _SAFECRT__RESET_STRING(_Filename, _FilenameSize); + } + if (_Ext != nullptr && _ExtSize > 0) + { + _SAFECRT__RESET_STRING(_Ext, _ExtSize); + } + + if (bEinval) + { + _SAFECRT__RETURN_EINVAL; + } + + _SAFECRT__RETURN_BUFFER_TOO_SMALL(_Strings, _StringSizes); + /* should never happen, but compiler can't tell */ + return EINVAL; +} +#endif + +/* sprintf_s, vsprintf_s */ +/* + * sprintf_s, swprintf_s, vsprintf_s, vswprintf_s format a string and copy it into _Dst; + * need safecrt.lib and msvcrt.dll; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; + * will call _SAFECRT_INVALID_PARAMETER if the format string is malformed; + * the %n format type is not allowed; + * return the length of string _Dst; + * return a negative number if something goes wrong with mbcs conversions (we will not call _SAFECRT_INVALID_PARAMETER); + * _SizeInBytes/_SizeInWords must be <= (INT_MAX / sizeof(char/WCHAR)); + * cannot be used without safecrt.lib + */ +_SAFECRT__EXTERN_C +int __cdecl sprintf_s(char *_Dst, size_t _SizeInBytes, const char *_Format, ...); +_SAFECRT__EXTERN_C +int __cdecl vsprintf_s(char *_Dst, size_t _SizeInBytes, const char *_Format, va_list _ArgList); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +int __cdecl sprintf_s(char (&_Dst)[_SizeInBytes], const char *_Format, ...) +{ + int ret; + va_list _ArgList; + va_start(_ArgList, _Format); + ret = vsprintf_s(_Dst, _SizeInBytes, _Format, _ArgList); + va_end(_ArgList); + return ret; +} + +template +inline +int __cdecl vsprintf_s(char (&_Dst)[_SizeInBytes], const char *_Format, va_list _ArgList) +{ + return vsprintf_s(_Dst, _SizeInBytes, _Format, _ArgList); +} +#endif + +/* no inline version of sprintf_s, vsprintf_s */ + +/* swprintf_s, vswprintf_s */ +_SAFECRT__EXTERN_C +int __cdecl swprintf_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Format, ...); +_SAFECRT__EXTERN_C +int __cdecl vswprintf_s(WCHAR *_Dst, size_t _SizeInWords, const WCHAR *_Format, va_list _ArgList); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +int __cdecl swprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, ...) +{ + int ret; + va_list _ArgList; + va_start(_ArgList, _Format); + ret = vswprintf_s(_Dst, _SizeInWords, _Format, _ArgList); + va_end(_ArgList); + return ret; +} + +template +inline +int __cdecl vswprintf_s(WCHAR (&_Dst)[_SizeInWords], const WCHAR *_Format, va_list _ArgList) +{ + return vswprintf_s(_Dst, _SizeInWords, _Format, _ArgList); +} +#endif + +/* no inline version of swprintf_s, vswprintf_s */ + +/* _snprintf_s, _vsnprintf_s */ +/* + * _snprintf_s, _snwprintf_s, _vsnprintf_s, _vsnwprintf_s format a string and copy at max _Count characters into _Dst; + * need safecrt.lib and msvcrt.dll; + * string _Dst will always be null-terminated; + * will call _SAFECRT_INVALID_PARAMETER if there is not enough space in _Dst; + * will call _SAFECRT_INVALID_PARAMETER if the format string is malformed; + * the %n format type is not allowed; + * return the length of string _Dst; + * return a negative number if something goes wrong with mbcs conversions (we will not call _SAFECRT_INVALID_PARAMETER); + * _SizeInBytes/_SizeInWords must be <= (INT_MAX / sizeof(char/WCHAR)); + * cannot be used without safecrt.lib; + * if _Count == _TRUNCATE, we will copy into _Dst as many characters as we can, and + * return -1 if the formatted string does not entirely fit into _Dst (we will not call _SAFECRT_INVALID_PARAMETER); + * if _Count == 0, then (_Dst == nullptr && _SizeInBytes == 0) is allowed + */ + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +int __cdecl _snprintf_s(char (&_Dst)[_SizeInBytes], size_t _Count, const char *_Format, ...) +{ + int ret; + va_list _ArgList; + va_start(_ArgList, _Format); + ret = _vsnprintf_s(_Dst, _SizeInBytes, _Count, _Format, _ArgList); + va_end(_ArgList); + return ret; +} + +template +inline +int __cdecl _vsnprintf_s(char (&_Dst)[_SizeInBytes], size_t _Count, const char *_Format, va_list _ArgList) +{ + return _vsnprintf_s(_Dst, _SizeInBytes, _Count, _Format, _ArgList); +} +#endif + +/* no inline version of _snprintf_s, _vsnprintf_s */ + +/* _snwprintf_s, _vsnwprintf_s */ +_SAFECRT__EXTERN_C +int __cdecl _vsnwprintf_s(WCHAR *_Dst, size_t _SizeInWords, size_t _Count, const WCHAR *_Format, va_list _ArgList); + +#if defined(__cplusplus) && _SAFECRT_USE_CPP_OVERLOADS +template +inline +int __cdecl _snwprintf_s(WCHAR (&_Dst)[_SizeInWords], size_t _Count, const WCHAR *_Format, ...) +{ + int ret; + va_list _ArgList; + va_start(_ArgList, _Format); + ret = _vsnwprintf_s(_Dst, _SizeInWords, _Count, _Format, _ArgList); + va_end(_ArgList); + return ret; +} + +template +inline +int __cdecl _vsnwprintf_s(char (&_Dst)[_SizeInWords], size_t _Count, const char *_Format, va_list _ArgList) +{ + return _vsnwprintf_s(_Dst, _SizeInWords, _Count, _Format, _ArgList); +} +#endif + +/* no inline version of _snwprintf_s, _vsnwprintf_s */ + +/* scanf_s */ +/* + * read formatted data from the standard input stream; + * need safecrt.lib and msvcrt.dll; + * will call _SAFECRT_INVALID_PARAMETER if the format string is malformed; + * for format types %s, %S, %[, %c and %C, in the argument list the buffer pointer + * need to be followed by the size of the buffer, e.g.: + * #define BUFFSIZE 100 + * char buff[BUFFSIZE]; + * scanf_s("%s", buff, BUFFSIZE); + * as scanf, returns the number of fields successfully converted and assigned; + * if a buffer field is too small, scanf set the buffer to the empty string and returns. + * do not support floating-point, for now + */ +_SAFECRT__EXTERN_C +int __cdecl scanf_s(const char *_Format, ...); + +/* no C++ overload for scanf_s */ + +/* no inline version of scanf_s */ + +/* wscanf_s */ +_SAFECRT__EXTERN_C +int __cdecl wscanf_s(const WCHAR *_Format, ...); + +/* no C++ overload for wscanf_s */ + +/* no inline version of wscanf_s */ + +/* sscanf_s */ +_SAFECRT__EXTERN_C +int __cdecl sscanf_s(const char *_String, const char *_Format, ...); + +/* no C++ overload for sscanf_s */ + +/* no inline version of sscanf_s */ + +/* swscanf_s */ +_SAFECRT__EXTERN_C +int __cdecl swscanf_s(const WCHAR *_String, const WCHAR *_Format, ...); + +/* no C++ overload for swscanf_s */ + +/* no inline version of swscanf_s */ + +/* _snscanf_s */ +_SAFECRT__EXTERN_C +int __cdecl _snscanf_s(const char *_String, size_t _Count, const char *_Format, ...); + +/* no C++ overload for snscanf_s */ + +/* no inline version of snscanf_s */ + +/* _swnscanf_s */ +_SAFECRT__EXTERN_C +int __cdecl _swnscanf_s(const WCHAR *_String, size_t _Count, const WCHAR *_Format, ...); + +/* no C++ overload for _swnscanf_s */ + +/* no inline version of _swnscanf_s */ + +//#endif /* ndef _SAFECRT_IMPL */ + +#endif /* _INC_SAFECRT */ diff --git a/lib/coreclr/src/pal/inc/rt/sal.h b/lib/coreclr/src/pal/inc/rt/sal.h new file mode 100644 index 0000000000..9a8c2a480f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/sal.h @@ -0,0 +1,2953 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*** +*sal.h - markers for documenting the semantics of APIs +* + +* +*Purpose: +* sal.h provides a set of annotations to describe how a function uses its +* parameters - the assumptions it makes about them, and the guarantees it makes +* upon finishing. +****/ +#pragma once + +/*========================================================================== + + The comments in this file are intended to give basic understanding of + the usage of SAL, the Microsoft Source Code Annotation Language. + For more details, please see http://go.microsoft.com/fwlink/?LinkID=242134 + + The macros are defined in 3 layers, plus the structural set: + + _In_/_Out_/_Ret_ Layer: + ---------------------- + This layer provides the highest abstraction and its macros should be used + in most cases. These macros typically start with: + _In_ : input parameter to a function, unmodified by called function + _Out_ : output parameter, written to by called function, pointed-to + location not expected to be initialized prior to call + _Outptr_ : like _Out_ when returned variable is a pointer type + (so param is pointer-to-pointer type). Called function + provides/allocated space. + _Outref_ : like _Outptr_, except param is reference-to-pointer type. + _Inout_ : inout parameter, read from and potentially modified by + called function. + _Ret_ : for return values + _Field_ : class/struct field invariants + For common usage, this class of SAL provides the most concise annotations. + Note that _In_/_Out_/_Inout_/_Outptr_ annotations are designed to be used + with a parameter target. Using them with _At_ to specify non-parameter + targets may yield unexpected results. + + This layer also includes a number of other properties that can be specified + to extend the ability of code analysis, most notably: + -- Designating parameters as format strings for printf/scanf/scanf_s + -- Requesting stricter type checking for C enum parameters + + _Pre_/_Post_ Layer: + ------------------ + The macros of this layer only should be used when there is no suitable macro + in the _In_/_Out_ layer. Its macros start with _Pre_ or _Post_. + This layer provides the most flexibility for annotations. + + Implementation Abstraction Layer: + -------------------------------- + Macros from this layer should never be used directly. The layer only exists + to hide the implementation of the annotation macros. + + Structural Layer: + ---------------- + These annotations, like _At_ and _When_, are used with annotations from + any of the other layers as modifiers, indicating exactly when and where + the annotations apply. + + + Common syntactic conventions: + ---------------------------- + + Usage: + ----- + _In_, _Out_, _Inout_, _Pre_, _Post_, are for formal parameters. + _Ret_, _Deref_ret_ must be used for return values. + + Nullness: + -------- + If the parameter can be NULL as a precondition to the function, the + annotation contains _opt. If the macro does not contain '_opt' the + parameter cannot be NULL. + + If an out/inout parameter returns a null pointer as a postcondition, this is + indicated by _Ret_maybenull_ or _result_maybenull_. If the macro is not + of this form, then the result will not be NULL as a postcondition. + _Outptr_ - output value is not NULL + _Outptr_result_maybenull_ - output value might be NULL + + String Type: + ----------- + _z: NullTerminated string + for _In_ parameters the buffer must have the specified stringtype before the call + for _Out_ parameters the buffer must have the specified stringtype after the call + for _Inout_ parameters both conditions apply + + Extent Syntax: + ------------- + Buffer sizes are expressed as element counts, unless the macro explicitly + contains _byte_ or _bytes_. Some annotations specify two buffer sizes, in + which case the second is used to indicate how much of the buffer is valid + as a postcondition. This table outlines the precondition buffer allocation + size, precondition number of valid elements, postcondition allocation size, + and postcondition number of valid elements for representative buffer size + annotations: + Pre | Pre | Post | Post + alloc | valid | alloc | valid + Annotation elems | elems | elems | elems + ---------- ------------------------------------ + _In_reads_(s) s | s | s | s + _Inout_updates_(s) s | s | s | s + _Inout_updates_to_(s,c) s | s | s | c + _Out_writes_(s) s | 0 | s | s + _Out_writes_to_(s,c) s | 0 | s | c + _Outptr_result_buffer_(s) ? | ? | s | s + _Outptr_result_buffer_to_(s,c) ? | ? | s | c + + For the _Outptr_ annotations, the buffer in question is at one level of + dereference. The called function is responsible for supplying the buffer. + + Success and failure: + ------------------- + The SAL concept of success allows functions to define expressions that can + be tested by the caller, which if it evaluates to non-zero, indicates the + function succeeded, which means that its postconditions are guaranteed to + hold. Otherwise, if the expression evaluates to zero, the function is + considered to have failed, and the postconditions are not guaranteed. + + The success criteria can be specified with the _Success_(expr) annotation: + _Success_(return != FALSE) BOOL + PathCanonicalizeA(_Out_writes_(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath) : + pszBuf is only guaranteed to be NULL-terminated when TRUE is returned, + and FALSE indiates failure. In common practice, callers check for zero + vs. non-zero returns, so it is preferable to express the success + criteria in terms of zero/non-zero, not checked for exactly TRUE. + + Functions can specify that some postconditions will still hold, even when + the function fails, using _On_failure_(anno-list), or postconditions that + hold regardless of success or failure using _Always_(anno-list). + + The annotation _Return_type_success_(expr) may be used with a typedef to + give a default _Success_ criteria to all functions returning that type. + This is the case for common Windows API status types, including + HRESULT and NTSTATUS. This may be overridden on a per-function basis by + specifying a _Success_ annotation locally. + +============================================================================*/ + +#define __ATTR_SAL + +#ifndef _SAL_VERSION /*IFSTRIP=IGN*/ +#define _SAL_VERSION 20 +#endif + +#ifdef _PREFAST_ // [ + +// choose attribute or __declspec implementation +#ifndef _USE_DECLSPECS_FOR_SAL // [ +#define _USE_DECLSPECS_FOR_SAL 1 +#endif // ] + +#if _USE_DECLSPECS_FOR_SAL // [ +#undef _USE_ATTRIBUTES_FOR_SAL +#define _USE_ATTRIBUTES_FOR_SAL 0 +#elif !defined(_USE_ATTRIBUTES_FOR_SAL) // ][ +#if _MSC_VER >= 1400 /*IFSTRIP=IGN*/ // [ +#define _USE_ATTRIBUTES_FOR_SAL 1 +#else // ][ +#define _USE_ATTRIBUTES_FOR_SAL 0 +#endif // ] +#endif // ] + + +#if !_USE_DECLSPECS_FOR_SAL // [ +#if !_USE_ATTRIBUTES_FOR_SAL // [ +#if _MSC_VER >= 1400 /*IFSTRIP=IGN*/ // [ +#undef _USE_ATTRIBUTES_FOR_SAL +#define _USE_ATTRIBUTES_FOR_SAL 1 +#else // ][ +#undef _USE_DECLSPECS_FOR_SAL +#define _USE_DECLSPECS_FOR_SAL 1 +#endif // ] +#endif // ] +#endif // ] + +#else + +// Disable expansion of SAL macros in non-Prefast mode to +// improve compiler throughput. +#ifndef _USE_DECLSPECS_FOR_SAL // [ +#define _USE_DECLSPECS_FOR_SAL 0 +#endif // ] +#ifndef _USE_ATTRIBUTES_FOR_SAL // [ +#define _USE_ATTRIBUTES_FOR_SAL 0 +#endif // ] + +#endif // ] + +// safeguard for MIDL and RC builds +#if _USE_DECLSPECS_FOR_SAL && ( defined( MIDL_PASS ) || defined(__midl) || defined(RC_INVOKED) || !defined(_PREFAST_) ) /*IFSTRIP=IGN*/ // [ +#undef _USE_DECLSPECS_FOR_SAL +#define _USE_DECLSPECS_FOR_SAL 0 +#endif // ] +#if _USE_ATTRIBUTES_FOR_SAL && ( !defined(_MSC_EXTENSIONS) || defined( MIDL_PASS ) || defined(__midl) || defined(RC_INVOKED) ) /*IFSTRIP=IGN*/ // [ +#undef _USE_ATTRIBUTES_FOR_SAL +#define _USE_ATTRIBUTES_FOR_SAL 0 +#endif // ] + +#if _USE_DECLSPECS_FOR_SAL || _USE_ATTRIBUTES_FOR_SAL + +// Special enum type for Y/N/M +enum __SAL_YesNo {_SAL_notpresent, _SAL_no, _SAL_maybe, _SAL_yes, _SAL_default}; + +#endif + +#if defined(BUILD_WINDOWS) && !_USE_ATTRIBUTES_FOR_SAL /*IFSTRIP=IGN*/ +#define _SAL1_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1") _GrouP_(annotes _SAL_nop_impl_) +#define _SAL1_1_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1.1") _GrouP_(annotes _SAL_nop_impl_) +#define _SAL1_2_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1.2") _GrouP_(annotes _SAL_nop_impl_) +#define _SAL2_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "2") _GrouP_(annotes _SAL_nop_impl_) +#else +#define _SAL1_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1") _Group_(annotes _SAL_nop_impl_) +#define _SAL1_1_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1.1") _Group_(annotes _SAL_nop_impl_) +#define _SAL1_2_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "1.2") _Group_(annotes _SAL_nop_impl_) +#define _SAL2_Source_(Name, args, annotes) _SA_annotes3(SAL_name, #Name, "", "2") _Group_(annotes _SAL_nop_impl_) +#endif + +//============================================================================ +// Structural SAL: +// These annotations modify the use of other annotations. They may +// express the annotation target (i.e. what parameter/field the annotation +// applies to) or the condition under which the annotation is applicable. +//============================================================================ + +// _At_(target, annos) specifies that the annotations listed in 'annos' is to +// be applied to 'target' rather than to the identifier which is the current +// lexical target. +#define _At_(target, annos) _At_impl_(target, annos _SAL_nop_impl_) + +// _At_buffer_(target, iter, bound, annos) is similar to _At_, except that +// target names a buffer, and each annotation in annos is applied to each +// element of target up to bound, with the variable named in iter usable +// by the annotations to refer to relevant offsets within target. +#define _At_buffer_(target, iter, bound, annos) _At_buffer_impl_(target, iter, bound, annos _SAL_nop_impl_) + +// _When_(expr, annos) specifies that the annotations listed in 'annos' only +// apply when 'expr' evaluates to non-zero. +#define _When_(expr, annos) _When_impl_(expr, annos _SAL_nop_impl_) +#define _Group_(annos) _Group_impl_(annos _SAL_nop_impl_) +#define _GrouP_(annos) _GrouP_impl_(annos _SAL_nop_impl_) + +// indicates whether normal post conditions apply to a function +#define _Success_(expr) _SAL2_Source_(_Success_, (expr), _Success_impl_(expr)) + +// indicates whether post conditions apply to a function returning +// the type that this annotation is applied to +#define _Return_type_success_(expr) _SAL2_Source_(_Return_type_success_, (expr), _Success_impl_(expr)) + +// Establish postconditions that apply only if the function does not succeed +#define _On_failure_(annos) _On_failure_impl_(annos _SAL_nop_impl_) + +// Establish postconditions that apply in both success and failure cases. +// Only applicable with functions that have _Success_ or _Return_type_succss_. +#define _Always_(annos) _Always_impl_(annos _SAL_nop_impl_) + +// Usable on a function defintion. Asserts that a function declaration is +// in scope, and its annotations are to be used. There are no other annotations +// allowed on the function definition. +#define _Use_decl_annotations_ _Use_decl_anno_impl_ + +// _Notref_ may precede a _Deref_ or "real" annotation, and removes one +// level of dereference if the parameter is a C++ reference (&). If the +// net deref on a "real" annotation is negative, it is simply discarded. +#define _Notref_ _Notref_impl_ + +// Annotations for defensive programming styles. +#define _Pre_defensive_ _SA_annotes0(SAL_pre_defensive) +#define _Post_defensive_ _SA_annotes0(SAL_post_defensive) + +#define _In_defensive_(annotes) _Pre_defensive_ _Group_(annotes) +#define _Out_defensive_(annotes) _Post_defensive_ _Group_(annotes) +#define _Inout_defensive_(annotes) _Pre_defensive_ _Post_defensive_ _Group_(annotes) + +//============================================================================ +// _In_\_Out_ Layer: +//============================================================================ + +// Reserved pointer parameters, must always be NULL. +#define _Reserved_ _SAL2_Source_(_Reserved_, (), _Pre1_impl_(__null_impl)) + +// _Const_ allows specification that any namable memory location is considered +// readonly for a given call. +#define _Const_ _SAL2_Source_(_Const_, (), _Pre1_impl_(__readaccess_impl_notref)) + + +// Input parameters -------------------------- + +// _In_ - Annotations for parameters where data is passed into the function, but not modified. +// _In_ by itself can be used with non-pointer types (although it is redundant). + +// e.g. void SetPoint( _In_ const POINT* pPT ); +#define _In_ _SAL2_Source_(_In_, (), _Pre1_impl_(__notnull_impl_notref) _Pre_valid_impl_ _Deref_pre1_impl_(__readaccess_impl_notref)) +#define _In_opt_ _SAL2_Source_(_In_opt_, (), _Pre1_impl_(__maybenull_impl_notref) _Pre_valid_impl_ _Deref_pre_readonly_) + +// nullterminated 'in' parameters. +// e.g. void CopyStr( _In_z_ const char* szFrom, _Out_z_cap_(cchTo) char* szTo, size_t cchTo ); +#define _In_z_ _SAL2_Source_(_In_z_, (), _In_ _Pre1_impl_(__zterm_impl)) +#define _In_opt_z_ _SAL2_Source_(_In_opt_z_, (), _In_opt_ _Pre1_impl_(__zterm_impl)) + + +// 'input' buffers with given size + +#define _In_reads_(size) _SAL2_Source_(_In_reads_, (size), _Pre_count_(size) _Deref_pre_readonly_) +#define _In_reads_opt_(size) _SAL2_Source_(_In_reads_opt_, (size), _Pre_opt_count_(size) _Deref_pre_readonly_) +#define _In_reads_bytes_(size) _SAL2_Source_(_In_reads_bytes_, (size), _Pre_bytecount_(size) _Deref_pre_readonly_) +#define _In_reads_bytes_opt_(size) _SAL2_Source_(_In_reads_bytes_opt_, (size), _Pre_opt_bytecount_(size) _Deref_pre_readonly_) +#define _In_reads_z_(size) _SAL2_Source_(_In_reads_z_, (size), _In_reads_(size) _Pre_z_) +#define _In_reads_opt_z_(size) _SAL2_Source_(_In_reads_opt_z_, (size), _Pre_opt_count_(size) _Deref_pre_readonly_ _Pre_opt_z_) +#define _In_reads_or_z_(size) _SAL2_Source_(_In_reads_or_z_, (size), _In_ _When_(_String_length_(_Curr_) < (size), _Pre_z_) _When_(_String_length_(_Curr_) >= (size), _Pre1_impl_(__count_impl(size)))) +#define _In_reads_or_z_opt_(size) _SAL2_Source_(_In_reads_or_z_opt_, (size), _In_opt_ _When_(_String_length_(_Curr_) < (size), _Pre_z_) _When_(_String_length_(_Curr_) >= (size), _Pre1_impl_(__count_impl(size)))) + + +// 'input' buffers valid to the given end pointer + +#define _In_reads_to_ptr_(ptr) _SAL2_Source_(_In_reads_to_ptr_, (ptr), _Pre_ptrdiff_count_(ptr) _Deref_pre_readonly_) +#define _In_reads_to_ptr_opt_(ptr) _SAL2_Source_(_In_reads_to_ptr_opt_, (ptr), _Pre_opt_ptrdiff_count_(ptr) _Deref_pre_readonly_) +#define _In_reads_to_ptr_z_(ptr) _SAL2_Source_(_In_reads_to_ptr_z_, (ptr), _In_reads_to_ptr_(ptr) _Pre_z_) +#define _In_reads_to_ptr_opt_z_(ptr) _SAL2_Source_(_In_reads_to_ptr_opt_z_, (ptr), _Pre_opt_ptrdiff_count_(ptr) _Deref_pre_readonly_ _Pre_opt_z_) + + + +// Output parameters -------------------------- + +// _Out_ - Annotations for pointer or reference parameters where data passed back to the caller. +// These are mostly used where the pointer/reference is to a non-pointer type. +// _Outptr_/_Outref) (see below) are typically used to return pointers via parameters. + +// e.g. void GetPoint( _Out_ POINT* pPT ); +#define _Out_ _SAL2_Source_(_Out_, (), _Out_impl_) +#define _Out_opt_ _SAL2_Source_(_Out_opt_, (), _Out_opt_impl_) + +#define _Out_writes_(size) _SAL2_Source_(_Out_writes_, (size), _Pre_cap_(size) _Post_valid_impl_) +#define _Out_writes_opt_(size) _SAL2_Source_(_Out_writes_opt_, (size), _Pre_opt_cap_(size) _Post_valid_impl_) +#define _Out_writes_bytes_(size) _SAL2_Source_(_Out_writes_bytes_, (size), _Pre_bytecap_(size) _Post_valid_impl_) +#define _Out_writes_bytes_opt_(size) _SAL2_Source_(_Out_writes_bytes_opt_, (size), _Pre_opt_bytecap_(size) _Post_valid_impl_) +#define _Out_writes_z_(size) _SAL2_Source_(_Out_writes_z_, (size), _Pre_cap_(size) _Post_valid_impl_ _Post_z_) +#define _Out_writes_opt_z_(size) _SAL2_Source_(_Out_writes_opt_z_, (size), _Pre_opt_cap_(size) _Post_valid_impl_ _Post_z_) + +#define _Out_writes_to_(size,count) _SAL2_Source_(_Out_writes_to_, (size,count), _Pre_cap_(size) _Post_valid_impl_ _Post_count_(count)) +#define _Out_writes_to_opt_(size,count) _SAL2_Source_(_Out_writes_to_opt_, (size,count), _Pre_opt_cap_(size) _Post_valid_impl_ _Post_count_(count)) +#define _Out_writes_all_(size) _SAL2_Source_(_Out_writes_all_, (size), _Out_writes_to_(_Old_(size), _Old_(size))) +#define _Out_writes_all_opt_(size) _SAL2_Source_(_Out_writes_all_opt_, (size), _Out_writes_to_opt_(_Old_(size), _Old_(size))) + +#define _Out_writes_bytes_to_(size,count) _SAL2_Source_(_Out_writes_bytes_to_, (size,count), _Pre_bytecap_(size) _Post_valid_impl_ _Post_bytecount_(count)) +#define _Out_writes_bytes_to_opt_(size,count) _SAL2_Source_(_Out_writes_bytes_to_opt_, (size,count), _Pre_opt_bytecap_(size) _Post_valid_impl_ _Post_bytecount_(count)) +#define _Out_writes_bytes_all_(size) _SAL2_Source_(_Out_writes_bytes_all_, (size), _Out_writes_bytes_to_(_Old_(size), _Old_(size))) +#define _Out_writes_bytes_all_opt_(size) _SAL2_Source_(_Out_writes_bytes_all_opt_, (size), _Out_writes_bytes_to_opt_(_Old_(size), _Old_(size))) + +#define _Out_writes_to_ptr_(ptr) _SAL2_Source_(_Out_writes_to_ptr_, (ptr), _Pre_ptrdiff_cap_(ptr) _Post_valid_impl_) +#define _Out_writes_to_ptr_opt_(ptr) _SAL2_Source_(_Out_writes_to_ptr_opt_, (ptr), _Pre_opt_ptrdiff_cap_(ptr) _Post_valid_impl_) +#define _Out_writes_to_ptr_z_(ptr) _SAL2_Source_(_Out_writes_to_ptr_z_, (ptr), _Pre_ptrdiff_cap_(ptr) _Post_valid_impl_ Post_z_) +#define _Out_writes_to_ptr_opt_z_(ptr) _SAL2_Source_(_Out_writes_to_ptr_opt_z_, (ptr), _Pre_opt_ptrdiff_cap_(ptr) _Post_valid_impl_ Post_z_) + + +// Inout parameters ---------------------------- + +// _Inout_ - Annotations for pointer or reference parameters where data is passed in and +// potentially modified. +// void ModifyPoint( _Inout_ POINT* pPT ); +// void ModifyPointByRef( _Inout_ POINT& pPT ); + +#define _Inout_ _SAL2_Source_(_Inout_, (), _Prepost_valid_) +#define _Inout_opt_ _SAL2_Source_(_Inout_opt_, (), _Prepost_opt_valid_) + +// For modifying string buffers +// void toupper( _Inout_z_ char* sz ); +#define _Inout_z_ _SAL2_Source_(_Inout_z_, (), _Prepost_z_) +#define _Inout_opt_z_ _SAL2_Source_(_Inout_opt_z_, (), _Prepost_opt_z_) + +// For modifying buffers with explicit element size +#define _Inout_updates_(size) _SAL2_Source_(_Inout_updates_, (size), _Pre_cap_(size) _Pre_valid_impl_ _Post_valid_impl_) +#define _Inout_updates_opt_(size) _SAL2_Source_(_Inout_updates_opt_, (size), _Pre_opt_cap_(size) _Pre_valid_impl_ _Post_valid_impl_) +#define _Inout_updates_z_(size) _SAL2_Source_(_Inout_updates_z_, (size), _Pre_cap_(size) _Pre_valid_impl_ _Post_valid_impl_ _Pre1_impl_(__zterm_impl) _Post1_impl_(__zterm_impl)) +#define _Inout_updates_opt_z_(size) _SAL2_Source_(_Inout_updates_opt_z_, (size), _Pre_opt_cap_(size) _Pre_valid_impl_ _Post_valid_impl_ _Pre1_impl_(__zterm_impl) _Post1_impl_(__zterm_impl)) + +#define _Inout_updates_to_(size,count) _SAL2_Source_(_Inout_updates_to_, (size,count), _Out_writes_to_(size,count) _Pre_valid_impl_ _Pre1_impl_(__count_impl(count))) +#define _Inout_updates_to_opt_(size,count) _SAL2_Source_(_Inout_updates_to_opt_, (size,count), _Out_writes_to_opt_(size,count) _Pre_valid_impl_ _Pre1_impl_(__count_impl(count))) + +#define _Inout_updates_all_(size) _SAL2_Source_(_Inout_updates_all_, (size), _Inout_updates_to_(_Old_(size), _Old_(size))) +#define _Inout_updates_all_opt_(size) _SAL2_Source_(_Inout_updates_all_opt_, (size), _Inout_updates_to_opt_(_Old_(size), _Old_(size))) + +// For modifying buffers with explicit byte size +#define _Inout_updates_bytes_(size) _SAL2_Source_(_Inout_updates_bytes_, (size), _Pre_bytecap_(size) _Pre_valid_impl_ _Post_valid_impl_) +#define _Inout_updates_bytes_opt_(size) _SAL2_Source_(_Inout_updates_bytes_opt_, (size), _Pre_opt_bytecap_(size) _Pre_valid_impl_ _Post_valid_impl_) + +#define _Inout_updates_bytes_to_(size,count) _SAL2_Source_(_Inout_updates_bytes_to_, (size,count), _Out_writes_bytes_to_(size,count) _Pre_valid_impl_ _Pre1_impl_(__bytecount_impl(count))) +#define _Inout_updates_bytes_to_opt_(size,count) _SAL2_Source_(_Inout_updates_bytes_to_opt_, (size,count), _Out_writes_bytes_to_opt_(size,count) _Pre_valid_impl_ _Pre1_impl_(__bytecount_impl(count))) + +#define _Inout_updates_bytes_all_(size) _SAL2_Source_(_Inout_updates_bytes_all_, (size), _Inout_updates_bytes_to_(_Old_(size), _Old_(size))) +#define _Inout_updates_bytes_all_opt_(size) _SAL2_Source_(_Inout_updates_bytes_all_opt_, (size), _Inout_updates_bytes_to_opt_(_Old_(size), _Old_(size))) + + +// Pointer to pointer parameters ------------------------- + +// _Outptr_ - Annotations for output params returning pointers +// These describe parameters where the called function provides the buffer: +// HRESULT SHStrDupW(_In_ LPCWSTR psz, _Outptr_ LPWSTR *ppwsz); +// The caller passes the address of an LPWSTR variable as ppwsz, and SHStrDupW allocates +// and initializes memory and returns the pointer to the new LPWSTR in *ppwsz. +// +// _Outptr_opt_ - describes parameters that are allowed to be NULL. +// _Outptr_*_result_maybenull_ - describes parameters where the called function might return NULL to the caller. +// +// Example: +// void MyFunc(_Outptr_opt_ int **ppData1, _Outptr_result_maybenull_ int **ppData2); +// Callers: +// MyFunc(NULL, NULL); // error: parameter 2, ppData2, should not be NULL +// MyFunc(&pData1, &pData2); // ok: both non-NULL +// if (*pData1 == *pData2) ... // error: pData2 might be NULL after call + +#define _Outptr_ _SAL2_Source_(_Outptr_, (), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __count_impl(1))) +#define _Outptr_result_maybenull_ _SAL2_Source_(_Outptr_result_maybenull_, (), _Out_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __count_impl(1))) +#define _Outptr_opt_ _SAL2_Source_(_Outptr_opt_, (), _Out_opt_impl_ _Deref_post2_impl_(__notnull_impl_notref, __count_impl(1))) +#define _Outptr_opt_result_maybenull_ _SAL2_Source_(_Outptr_opt_result_maybenull_, (), _Out_opt_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __count_impl(1))) + +// Annotations for _Outptr_ parameters returning pointers to null terminated strings. + +#define _Outptr_result_z_ _SAL2_Source_(_Outptr_result_z_, (), _Out_impl_ _Deref_post_z_) +#define _Outptr_opt_result_z_ _SAL2_Source_(_Outptr_opt_result_z_, (), _Out_opt_impl_ _Deref_post_z_) +#define _Outptr_result_maybenull_z_ _SAL2_Source_(_Outptr_result_maybenull_z_, (), _Out_impl_ _Deref_post_opt_z_) +#define _Outptr_opt_result_maybenull_z_ _SAL2_Source_(_Outptr_opt_result_maybenull_z_, (), _Out_opt_impl_ _Deref_post_opt_z_) + +// Annotations for _Outptr_ parameters where the output pointer is set to NULL if the function fails. + +#define _Outptr_result_nullonfailure_ _SAL2_Source_(_Outptr_result_nullonfailure_, (), _Outptr_ _On_failure_(_Deref_post_null_)) +#define _Outptr_opt_result_nullonfailure_ _SAL2_Source_(_Outptr_opt_result_nullonfailure_, (), _Outptr_opt_ _On_failure_(_Deref_post_null_)) + +// Annotations for _Outptr_ parameters which return a pointer to a ref-counted COM object, +// following the COM convention of setting the output to NULL on failure. +// The current implementation is identical to _Outptr_result_nullonfailure_. +// For pointers to types that are not COM objects, _Outptr_result_nullonfailure_ is preferred. + +#define _COM_Outptr_ _SAL2_Source_(_COM_Outptr_, (), _Outptr_ _On_failure_(_Deref_post_null_)) +#define _COM_Outptr_result_maybenull_ _SAL2_Source_(_COM_Outptr_result_maybenull_, (), _Outptr_result_maybenull_ _On_failure_(_Deref_post_null_)) +#define _COM_Outptr_opt_ _SAL2_Source_(_COM_Outptr_opt_, (), _Outptr_opt_ _On_failure_(_Deref_post_null_)) +#define _COM_Outptr_opt_result_maybenull_ _SAL2_Source_(_COM_Outptr_opt_result_maybenull_, (), _Outptr_opt_result_maybenull_ _On_failure_(_Deref_post_null_)) + +// Annotations for _Outptr_ parameters returning a pointer to buffer with a specified number of elements/bytes + +#define _Outptr_result_buffer_(size) _SAL2_Source_(_Outptr_result_buffer_, (size), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __cap_impl(size))) +#define _Outptr_opt_result_buffer_(size) _SAL2_Source_(_Outptr_opt_result_buffer_, (size), _Out_opt_impl_ _Deref_post2_impl_(__notnull_impl_notref, __cap_impl(size))) +#define _Outptr_result_buffer_to_(size, count) _SAL2_Source_(_Outptr_result_buffer_to_, (size, count), _Out_impl_ _Deref_post3_impl_(__notnull_impl_notref, __cap_impl(size), __count_impl(count))) +#define _Outptr_opt_result_buffer_to_(size, count) _SAL2_Source_(_Outptr_opt_result_buffer_to_, (size, count), _Out_opt_impl_ _Deref_post3_impl_(__notnull_impl_notref, __cap_impl(size), __count_impl(count))) + +#define _Outptr_result_buffer_all_(size) _SAL2_Source_(_Outptr_result_buffer_all_, (size), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __count_impl(size))) +#define _Outptr_opt_result_buffer_all_(size) _SAL2_Source_(_Outptr_opt_result_buffer_all_, (size), _Out_opt_impl_ _Deref_post2_impl_(__notnull_impl_notref, __count_impl(size))) + +#define _Outptr_result_buffer_maybenull_(size) _SAL2_Source_(_Outptr_result_buffer_maybenull_, (size), _Out_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __cap_impl(size))) +#define _Outptr_opt_result_buffer_maybenull_(size) _SAL2_Source_(_Outptr_opt_result_buffer_maybenull_, (size), _Out_opt_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __cap_impl(size))) +#define _Outptr_result_buffer_to_maybenull_(size, count) _SAL2_Source_(_Outptr_result_buffer_to_maybenull_, (size, count), _Out_impl_ _Deref_post3_impl_(__maybenull_impl_notref, __cap_impl(size), __count_impl(count))) +#define _Outptr_opt_result_buffer_to_maybenull_(size, count) _SAL2_Source_(_Outptr_opt_result_buffer_to_maybenull_, (size, count), _Out_opt_impl_ _Deref_post3_impl_(__maybenull_impl_notref, __cap_impl(size), __count_impl(count))) + +#define _Outptr_result_buffer_all_maybenull_(size) _SAL2_Source_(_Outptr_result_buffer_all_maybenull_, (size), _Out_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __count_impl(size))) +#define _Outptr_opt_result_buffer_all_maybenull_(size) _SAL2_Source_(_Outptr_opt_result_buffer_all_maybenull_, (size), _Out_opt_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __count_impl(size))) + +#define _Outptr_result_bytebuffer_(size) _SAL2_Source_(_Outptr_result_bytebuffer_, (size), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __bytecap_impl(size))) +#define _Outptr_opt_result_bytebuffer_(size) _SAL2_Source_(_Outptr_opt_result_bytebuffer_, (size), _Out_opt_impl_ _Deref_post2_impl_(__notnull_impl_notref, __bytecap_impl(size))) +#define _Outptr_result_bytebuffer_to_(size, count) _SAL2_Source_(_Outptr_result_bytebuffer_to_, (size, count), _Out_impl_ _Deref_post3_impl_(__notnull_impl_notref, __bytecap_impl(size), __bytecount_impl(count))) +#define _Outptr_opt_result_bytebuffer_to_(size, count) _SAL2_Source_(_Outptr_opt_result_bytebuffer_to_, (size, count), _Out_opt_impl_ _Deref_post3_impl_(__notnull_impl_notref, __bytecap_impl(size), __bytecount_impl(count))) + +#define _Outptr_result_bytebuffer_all_(size) _SAL2_Source_(_Outptr_result_bytebuffer_all_, (size), _Out_impl_ _Deref_post2_impl_(__notnull_impl_notref, __bytecount_impl(size))) +#define _Outptr_opt_result_bytebuffer_all_(size) _SAL2_Source_(_Outptr_opt_result_bytebuffer_all_, (size), _Out_opt_impl_ _Deref_post2_impl_(__notnull_impl_notref, __bytecount_impl(size))) + +#define _Outptr_result_bytebuffer_maybenull_(size) _SAL2_Source_(_Outptr_result_bytebuffer_maybenull_, (size), _Out_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __bytecap_impl(size))) +#define _Outptr_opt_result_bytebuffer_maybenull_(size) _SAL2_Source_(_Outptr_opt_result_bytebuffer_maybenull_, (size), _Out_opt_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __bytecap_impl(size))) +#define _Outptr_result_bytebuffer_to_maybenull_(size, count) _SAL2_Source_(_Outptr_result_bytebuffer_to_maybenull_, (size, count), _Out_impl_ _Deref_post3_impl_(__maybenull_impl_notref, __bytecap_impl(size), __bytecount_impl(count))) +#define _Outptr_opt_result_bytebuffer_to_maybenull_(size, count) _SAL2_Source_(_Outptr_opt_result_bytebuffer_to_maybenull_, (size, count), _Out_opt_impl_ _Deref_post3_impl_(__maybenull_impl_notref, __bytecap_impl(size), __bytecount_impl(count))) + +#define _Outptr_result_bytebuffer_all_maybenull_(size) _SAL2_Source_(_Outptr_result_bytebuffer_all_maybenull_, (size), _Out_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __bytecount_impl(size))) +#define _Outptr_opt_result_bytebuffer_all_maybenull_(size) _SAL2_Source_(_Outptr_opt_result_bytebuffer_all_maybenull_, (size), _Out_opt_impl_ _Deref_post2_impl_(__maybenull_impl_notref, __bytecount_impl(size))) + +// Annotations for output reference to pointer parameters. + +#define _Outref_ _SAL2_Source_(_Outref_, (), _Out_impl_ _Post_notnull_) +#define _Outref_result_maybenull_ _SAL2_Source_(_Outref_result_maybenull_, (), _Pre2_impl_(__notnull_impl_notref, __cap_c_one_notref_impl) _Post_maybenull_ _Post_valid_impl_) + +#define _Outref_result_buffer_(size) _SAL2_Source_(_Outref_result_buffer_, (size), _Outref_ _Post1_impl_(__cap_impl(size))) +#define _Outref_result_bytebuffer_(size) _SAL2_Source_(_Outref_result_bytebuffer_, (size), _Outref_ _Post1_impl_(__bytecap_impl(size))) +#define _Outref_result_buffer_to_(size, count) _SAL2_Source_(_Outref_result_buffer_to_, (size, count), _Outref_result_buffer_(size) _Post1_impl_(__count_impl(count))) +#define _Outref_result_bytebuffer_to_(size, count) _SAL2_Source_(_Outref_result_bytebuffer_to_, (size, count), _Outref_result_bytebuffer_(size) _Post1_impl_(__bytecount_impl(count))) +#define _Outref_result_buffer_all_(size) _SAL2_Source_(_Outref_result_buffer_all_, (size), _Outref_result_buffer_to_(size, _Old_(size))) +#define _Outref_result_bytebuffer_all_(size) _SAL2_Source_(_Outref_result_bytebuffer_all_, (size), _Outref_result_bytebuffer_to_(size, _Old_(size))) + +#define _Outref_result_buffer_maybenull_(size) _SAL2_Source_(_Outref_result_buffer_maybenull_, (size), _Outref_result_maybenull_ _Post1_impl_(__cap_impl(size))) +#define _Outref_result_bytebuffer_maybenull_(size) _SAL2_Source_(_Outref_result_bytebuffer_maybenull_, (size), _Outref_result_maybenull_ _Post1_impl_(__bytecap_impl(size))) +#define _Outref_result_buffer_to_maybenull_(size, count) _SAL2_Source_(_Outref_result_buffer_to_maybenull_, (size, count), _Outref_result_buffer_maybenull_(size) _Post1_impl_(__count_impl(count))) +#define _Outref_result_bytebuffer_to_maybenull_(size, count) _SAL2_Source_(_Outref_result_bytebuffer_to_maybenull_, (size, count), _Outref_result_bytebuffer_maybenull_(size) _Post1_impl_(__bytecount_impl(count))) +#define _Outref_result_buffer_all_maybenull_(size) _SAL2_Source_(_Outref_result_buffer_all_maybenull_, (size), _Outref_result_buffer_to_maybenull_(size, _Old_(size))) +#define _Outref_result_bytebuffer_all_maybenull_(size) _SAL2_Source_(_Outref_result_bytebuffer_all_maybenull_, (size), _Outref_result_bytebuffer_to_maybenull_(size, _Old_(size))) + +// Annotations for output reference to pointer parameters that guarantee +// that the pointer is set to NULL on failure. +#define _Outref_result_nullonfailure_ _SAL2_Source_(_Outref_result_nullonfailure_, (), _Outref_ _On_failure_(_Post_null_)) + +// Generic annotations to set output value of a by-pointer or by-reference parameter to null/zero on failure. +#define _Result_nullonfailure_ _SAL2_Source_(_Result_nullonfailure_, (), _On_failure_(_Notref_impl_ _Deref_impl_ _Post_null_)) +#define _Result_zeroonfailure_ _SAL2_Source_(_Result_zeroonfailure_, (), _On_failure_(_Notref_impl_ _Deref_impl_ _Out_range_(==, 0))) + + +// return values ------------------------------- + +// +// _Ret_ annotations +// +// describing conditions that hold for return values after the call + +// e.g. _Ret_z_ CString::operator const WCHAR*() const throw(); +#define _Ret_z_ _SAL2_Source_(_Ret_z_, (), _Ret2_impl_(__notnull_impl, __zterm_impl) _Ret_valid_impl_) +#define _Ret_maybenull_z_ _SAL2_Source_(_Ret_maybenull_z_, (), _Ret2_impl_(__maybenull_impl,__zterm_impl) _Ret_valid_impl_) + +// used with allocated but not yet initialized objects +#define _Ret_notnull_ _SAL2_Source_(_Ret_notnull_, (), _Ret1_impl_(__notnull_impl)) +#define _Ret_maybenull_ _SAL2_Source_(_Ret_maybenull_, (), _Ret1_impl_(__maybenull_impl)) +#define _Ret_null_ _SAL2_Source_(_Ret_null_, (), _Ret1_impl_(__null_impl)) + +// used with allocated and initialized objects +// returns single valid object +#define _Ret_valid_ _SAL2_Source_(_Ret_valid_, (), _Ret1_impl_(__notnull_impl_notref) _Ret_valid_impl_) + +// returns pointer to initialized buffer of specified size +#define _Ret_writes_(size) _SAL2_Source_(_Ret_writes_, (size), _Ret2_impl_(__notnull_impl, __count_impl(size)) _Ret_valid_impl_) +#define _Ret_writes_z_(size) _SAL2_Source_(_Ret_writes_z_, (size), _Ret3_impl_(__notnull_impl, __count_impl(size), __zterm_impl) _Ret_valid_impl_) +#define _Ret_writes_bytes_(size) _SAL2_Source_(_Ret_writes_bytes_, (size), _Ret2_impl_(__notnull_impl, __bytecount_impl(size)) _Ret_valid_impl_) +#define _Ret_writes_maybenull_(size) _SAL2_Source_(_Ret_writes_maybenull_, (size), _Ret2_impl_(__maybenull_impl,__count_impl(size)) _Ret_valid_impl_) +#define _Ret_writes_maybenull_z_(size) _SAL2_Source_(_Ret_writes_maybenull_z_, (size), _Ret3_impl_(__maybenull_impl,__count_impl(size),__zterm_impl) _Ret_valid_impl_) +#define _Ret_writes_bytes_maybenull_(size) _SAL2_Source_(_Ret_writes_bytes_maybenull_, (size), _Ret2_impl_(__maybenull_impl,__bytecount_impl(size)) _Ret_valid_impl_) + +// returns pointer to partially initialized buffer, with total size 'size' and initialized size 'count' +#define _Ret_writes_to_(size,count) _SAL2_Source_(_Ret_writes_to_, (size,count), _Ret3_impl_(__notnull_impl, __cap_impl(size), __count_impl(count)) _Ret_valid_impl_) +#define _Ret_writes_bytes_to_(size,count) _SAL2_Source_(_Ret_writes_bytes_to_, (size,count), _Ret3_impl_(__notnull_impl, __bytecap_impl(size), __bytecount_impl(count)) _Ret_valid_impl_) +#define _Ret_writes_to_maybenull_(size,count) _SAL2_Source_(_Ret_writes_to_maybenull_, (size,count), _Ret3_impl_(__maybenull_impl, __cap_impl(size), __count_impl(count)) _Ret_valid_impl_) +#define _Ret_writes_bytes_to_maybenull_(size,count) _SAL2_Source_(_Ret_writes_bytes_to_maybenull_, (size,count), _Ret3_impl_(__maybenull_impl, __bytecap_impl(size), __bytecount_impl(count)) _Ret_valid_impl_) + + +// Annotations for strict type checking +#define _Points_to_data_ _SAL2_Source_(_Points_to_data_, (), _Pre_ _Points_to_data_impl_) +#define _Literal_ _SAL2_Source_(_Literal_, (), _Pre_ _Literal_impl_) +#define _Notliteral_ _SAL2_Source_(_Notliteral_, (), _Pre_ _Notliteral_impl_) + +// Check the return value of a function e.g. _Check_return_ ErrorCode Foo(); +#define _Check_return_ _SAL2_Source_(_Check_return_, (), _Check_return_impl_) +#define _Must_inspect_result_ _SAL2_Source_(_Must_inspect_result_, (), _Must_inspect_impl_ _Check_return_impl_) + +// e.g. MyPrintF( _Printf_format_string_ const WCHAR* wzFormat, ... ); +#define _Printf_format_string_ _SAL2_Source_(_Printf_format_string_, (), _Printf_format_string_impl_) +#define _Scanf_format_string_ _SAL2_Source_(_Scanf_format_string_, (), _Scanf_format_string_impl_) +#define _Scanf_s_format_string_ _SAL2_Source_(_Scanf_s_format_string_, (), _Scanf_s_format_string_impl_) + +#define _Format_string_impl_(kind,where) _SA_annotes2(SAL_IsFormatString2, kind, where) +#define _Printf_format_string_params_(x) _SAL2_Source_(_Printf_format_string_params_, (x), _Format_string_impl_("printf", x)) +#define _Scanf_format_string_params_(x) _SAL2_Source_(_Scanf_format_string_params_, (x), _Format_string_impl_("scanf", x)) +#define _Scanf_s_format_string_params_(x) _SAL2_Source_(_Scanf_s_format_string_params_, (x), _Format_string_impl_("scanf_s", x)) + +// annotations to express value of integral or pointer parameter +#define _In_range_(lb,ub) _SAL2_Source_(_In_range_, (lb,ub), _In_range_impl_(lb,ub)) +#define _Out_range_(lb,ub) _SAL2_Source_(_Out_range_, (lb,ub), _Out_range_impl_(lb,ub)) +#define _Ret_range_(lb,ub) _SAL2_Source_(_Ret_range_, (lb,ub), _Ret_range_impl_(lb,ub)) +#define _Deref_in_range_(lb,ub) _SAL2_Source_(_Deref_in_range_, (lb,ub), _Deref_in_range_impl_(lb,ub)) +#define _Deref_out_range_(lb,ub) _SAL2_Source_(_Deref_out_range_, (lb,ub), _Deref_out_range_impl_(lb,ub)) +#define _Deref_ret_range_(lb,ub) _SAL2_Source_(_Deref_ret_range_, (lb,ub), _Deref_ret_range_impl_(lb,ub)) +#define _Pre_equal_to_(expr) _SAL2_Source_(_Pre_equal_to_, (expr), _In_range_(==, expr)) +#define _Post_equal_to_(expr) _SAL2_Source_(_Post_equal_to_, (expr), _Out_range_(==, expr)) + +// annotation to express that a value (usually a field of a mutable class) +// is not changed by a function call +#define _Unchanged_(e) _SAL2_Source_(_Unchanged_, (e), _At_(e, _Post_equal_to_(_Old_(e)) _Const_)) + +// Annotations to allow expressing generalized pre and post conditions. +// 'cond' may be any valid SAL expression that is considered to be true as a precondition +// or postcondition (respsectively). +#define _Pre_satisfies_(cond) _SAL2_Source_(_Pre_satisfies_, (cond), _Pre_satisfies_impl_(cond)) +#define _Post_satisfies_(cond) _SAL2_Source_(_Post_satisfies_, (cond), _Post_satisfies_impl_(cond)) + +// Annotations to express struct, class and field invariants +#define _Struct_size_bytes_(size) _SAL2_Source_(_Struct_size_bytes_, (size), _Writable_bytes_(size)) + +#define _Field_size_(size) _SAL2_Source_(_Field_size_, (size), _Notnull_ _Writable_elements_(size)) +#define _Field_size_opt_(size) _SAL2_Source_(_Field_size_opt_, (size), _Maybenull_ _Writable_elements_(size)) +#define _Field_size_part_(size, count) _SAL2_Source_(_Field_size_part_, (size, count), _Notnull_ _Writable_elements_(size) _Readable_elements_(count)) +#define _Field_size_part_opt_(size, count) _SAL2_Source_(_Field_size_part_opt_, (size, count), _Maybenull_ _Writable_elements_(size) _Readable_elements_(count)) +#define _Field_size_full_(size) _SAL2_Source_(_Field_size_full_, (size), _Field_size_part_(size, size)) +#define _Field_size_full_opt_(size) _SAL2_Source_(_Field_size_full_opt_, (size), _Field_size_part_opt_(size, size)) + +#define _Field_size_bytes_(size) _SAL2_Source_(_Field_size_bytes_, (size), _Notnull_ _Writable_bytes_(size)) +#define _Field_size_bytes_opt_(size) _SAL2_Source_(_Field_size_bytes_opt_, (size), _Maybenull_ _Writable_bytes_(size)) +#define _Field_size_bytes_part_(size, count) _SAL2_Source_(_Field_size_bytes_part_, (size, count), _Notnull_ _Writable_bytes_(size) _Readable_bytes_(count)) +#define _Field_size_bytes_part_opt_(size, count) _SAL2_Source_(_Field_size_bytes_part_opt_, (size, count), _Maybenull_ _Writable_bytes_(size) _Readable_bytes_(count)) +#define _Field_size_bytes_full_(size) _SAL2_Source_(_Field_size_bytes_full_, (size), _Field_size_bytes_part_(size, size)) +#define _Field_size_bytes_full_opt_(size) _SAL2_Source_(_Field_size_bytes_full_opt_, (size), _Field_size_bytes_part_opt_(size, size)) + +#define _Field_z_ _SAL2_Source_(_Field_z_, (), _Null_terminated_) + +#define _Field_range_(min,max) _SAL2_Source_(_Field_range_, (min,max), _Field_range_impl_(min,max)) + +//============================================================================ +// _Pre_\_Post_ Layer: +//============================================================================ + +// +// Raw Pre/Post for declaring custom pre/post conditions +// + +#define _Pre_ _Pre_impl_ +#define _Post_ _Post_impl_ + +// +// Validity property +// + +#define _Valid_ _Valid_impl_ +#define _Notvalid_ _Notvalid_impl_ +#define _Maybevalid_ _Maybevalid_impl_ + +// +// Buffer size properties +// + +// Expressing buffer sizes without specifying pre or post condition +#define _Readable_bytes_(size) _SAL2_Source_(_Readable_bytes_, (size), _Readable_bytes_impl_(size)) +#define _Readable_elements_(size) _SAL2_Source_(_Readable_elements_, (size), _Readable_elements_impl_(size)) +#define _Writable_bytes_(size) _SAL2_Source_(_Writable_bytes_, (size), _Writable_bytes_impl_(size)) +#define _Writable_elements_(size) _SAL2_Source_(_Writable_elements_, (size), _Writable_elements_impl_(size)) + +#define _Null_terminated_ _SAL2_Source_(_Null_terminated_, (), _Null_terminated_impl_) +#define _NullNull_terminated_ _SAL2_Source_(_NullNull_terminated_, (), _NullNull_terminated_impl_) + +// Expressing buffer size as pre or post condition +#define _Pre_readable_size_(size) _SAL2_Source_(_Pre_readable_size_, (size), _Pre1_impl_(__count_impl(size)) _Pre_valid_impl_) +#define _Pre_writable_size_(size) _SAL2_Source_(_Pre_writable_size_, (size), _Pre1_impl_(__cap_impl(size))) +#define _Pre_readable_byte_size_(size) _SAL2_Source_(_Pre_readable_byte_size_, (size), _Pre1_impl_(__bytecount_impl(size)) _Pre_valid_impl_) +#define _Pre_writable_byte_size_(size) _SAL2_Source_(_Pre_writable_byte_size_, (size), _Pre1_impl_(__bytecap_impl(size))) + +#define _Post_readable_size_(size) _SAL2_Source_(_Post_readable_size_, (size), _Post1_impl_(__count_impl(size)) _Post_valid_impl_) +#define _Post_writable_size_(size) _SAL2_Source_(_Post_writable_size_, (size), _Post1_impl_(__cap_impl(size))) +#define _Post_readable_byte_size_(size) _SAL2_Source_(_Post_readable_byte_size_, (size), _Post1_impl_(__bytecount_impl(size)) _Post_valid_impl_) +#define _Post_writable_byte_size_(size) _SAL2_Source_(_Post_writable_byte_size_, (size), _Post1_impl_(__bytecap_impl(size))) + +// +// Pointer null-ness properties +// +#define _Null_ _Null_impl_ +#define _Notnull_ _Notnull_impl_ +#define _Maybenull_ _Maybenull_impl_ + +// +// _Pre_ annotations --- +// +// describing conditions that must be met before the call of the function + +// e.g. int strlen( _Pre_z_ const char* sz ); +// buffer is a zero terminated string +#define _Pre_z_ _SAL2_Source_(_Pre_z_, (), _Pre1_impl_(__zterm_impl) _Pre_valid_impl_) + +// valid size unknown or indicated by type (e.g.:LPSTR) +#define _Pre_valid_ _SAL2_Source_(_Pre_valid_, (), _Pre1_impl_(__notnull_impl_notref) _Pre_valid_impl_) +#define _Pre_opt_valid_ _SAL2_Source_(_Pre_opt_valid_, (), _Pre1_impl_(__maybenull_impl_notref) _Pre_valid_impl_) + +#define _Pre_invalid_ _SAL2_Source_(_Pre_invalid_, (), _Deref_pre1_impl_(__notvalid_impl)) + +// Overrides recursive valid when some field is not yet initialized when using _Inout_ +#define _Pre_unknown_ _SAL2_Source_(_Pre_unknown_, (), _Pre1_impl_(__maybevalid_impl)) + +// used with allocated but not yet initialized objects +#define _Pre_notnull_ _SAL2_Source_(_Pre_notnull_, (), _Pre1_impl_(__notnull_impl_notref)) +#define _Pre_maybenull_ _SAL2_Source_(_Pre_maybenull_, (), _Pre1_impl_(__maybenull_impl_notref)) +#define _Pre_null_ _SAL2_Source_(_Pre_null_, (), _Pre1_impl_(__null_impl_notref)) + +// +// _Post_ annotations --- +// +// describing conditions that hold after the function call + +// void CopyStr( _In_z_ const char* szFrom, _Pre_cap_(cch) _Post_z_ char* szFrom, size_t cchFrom ); +// buffer will be a zero-terminated string after the call +#define _Post_z_ _SAL2_Source_(_Post_z_, (), _Post1_impl_(__zterm_impl) _Post_valid_impl_) + +// e.g. HRESULT InitStruct( _Post_valid_ Struct* pobj ); +#define _Post_valid_ _SAL2_Source_(_Post_valid_, (), _Post_valid_impl_) +#define _Post_invalid_ _SAL2_Source_(_Post_invalid_, (), _Deref_post1_impl_(__notvalid_impl)) + +// e.g. void free( _Post_ptr_invalid_ void* pv ); +#define _Post_ptr_invalid_ _SAL2_Source_(_Post_ptr_invalid_, (), _Post1_impl_(__notvalid_impl)) + +// e.g. void ThrowExceptionIfNull( _Post_notnull_ const void* pv ); +#define _Post_notnull_ _SAL2_Source_(_Post_notnull_, (), _Post1_impl_(__notnull_impl)) + +// e.g. HRESULT GetObject(_Outptr_ _On_failure_(_At_(*p, _Post_null_)) T **p); +#define _Post_null_ _SAL2_Source_(_Post_null_, (), _Post1_impl_(__null_impl)) + +#define _Post_maybenull_ _SAL2_Source_(_Post_maybenull_, (), _Post1_impl_(__maybenull_impl)) + +#define _Prepost_z_ _SAL2_Source_(_Prepost_z_, (), _Pre_z_ _Post_z_) + + +// #pragma region Input Buffer SAL 1 compatibility macros + +/*========================================================================== + + This section contains definitions for macros defined for VS2010 and earlier. + Usage of these macros is still supported, but the SAL 2 macros defined above + are recommended instead. This comment block is retained to assist in + understanding SAL that still uses the older syntax. + + The macros are defined in 3 layers: + + _In_\_Out_ Layer: + ---------------- + This layer provides the highest abstraction and its macros should be used + in most cases. Its macros start with _In_, _Out_ or _Inout_. For the + typical case they provide the most concise annotations. + + _Pre_\_Post_ Layer: + ------------------ + The macros of this layer only should be used when there is no suitable macro + in the _In_\_Out_ layer. Its macros start with _Pre_, _Post_, _Ret_, + _Deref_pre_ _Deref_post_ and _Deref_ret_. This layer provides the most + flexibility for annotations. + + Implementation Abstraction Layer: + -------------------------------- + Macros from this layer should never be used directly. The layer only exists + to hide the implementation of the annotation macros. + + + Annotation Syntax: + |--------------|----------|----------------|-----------------------------| + | Usage | Nullness | ZeroTerminated | Extent | + |--------------|----------|----------------|-----------------------------| + | _In_ | <> | <> | <> | + | _Out_ | opt_ | z_ | [byte]cap_[c_|x_]( size ) | + | _Inout_ | | | [byte]count_[c_|x_]( size ) | + | _Deref_out_ | | | ptrdiff_cap_( ptr ) | + |--------------| | | ptrdiff_count_( ptr ) | + | _Ret_ | | | | + | _Deref_ret_ | | | | + |--------------| | | | + | _Pre_ | | | | + | _Post_ | | | | + | _Deref_pre_ | | | | + | _Deref_post_ | | | | + |--------------|----------|----------------|-----------------------------| + + Usage: + ----- + _In_, _Out_, _Inout_, _Pre_, _Post_, _Deref_pre_, _Deref_post_ are for + formal parameters. + _Ret_, _Deref_ret_ must be used for return values. + + Nullness: + -------- + If the pointer can be NULL the annotation contains _opt. If the macro + does not contain '_opt' the pointer may not be NULL. + + String Type: + ----------- + _z: NullTerminated string + for _In_ parameters the buffer must have the specified stringtype before the call + for _Out_ parameters the buffer must have the specified stringtype after the call + for _Inout_ parameters both conditions apply + + Extent Syntax: + |------|---------------|---------------| + | Unit | Writ\Readable | Argument Type | + |------|---------------|---------------| + | <> | cap_ | <> | + | byte | count_ | c_ | + | | | x_ | + |------|---------------|---------------| + + 'cap' (capacity) describes the writable size of the buffer and is typically used + with _Out_. The default unit is elements. Use 'bytecap' if the size is given in bytes + 'count' describes the readable size of the buffer and is typically used with _In_. + The default unit is elements. Use 'bytecount' if the size is given in bytes. + + Argument syntax for cap_, bytecap_, count_, bytecount_: + (|return)[+n] e.g. cch, return, cb+2 + + If the buffer size is a constant expression use the c_ postfix. + E.g. cap_c_(20), count_c_(MAX_PATH), bytecount_c_(16) + + If the buffer size is given by a limiting pointer use the ptrdiff_ versions + of the macros. + + If the buffer size is neither a parameter nor a constant expression use the x_ + postfix. e.g. bytecount_x_(num*size) x_ annotations accept any arbitrary string. + No analysis can be done for x_ annotations but they at least tell the tool that + the buffer has some sort of extent description. x_ annotations might be supported + by future compiler versions. + +============================================================================*/ + +// e.g. void SetCharRange( _In_count_(cch) const char* rgch, size_t cch ) +// valid buffer extent described by another parameter +#define _In_count_(size) _SAL1_1_Source_(_In_count_, (size), _Pre_count_(size) _Deref_pre_readonly_) +#define _In_opt_count_(size) _SAL1_1_Source_(_In_opt_count_, (size), _Pre_opt_count_(size) _Deref_pre_readonly_) +#define _In_bytecount_(size) _SAL1_1_Source_(_In_bytecount_, (size), _Pre_bytecount_(size) _Deref_pre_readonly_) +#define _In_opt_bytecount_(size) _SAL1_1_Source_(_In_opt_bytecount_, (size), _Pre_opt_bytecount_(size) _Deref_pre_readonly_) + +// valid buffer extent described by a constant extression +#define _In_count_c_(size) _SAL1_1_Source_(_In_count_c_, (size), _Pre_count_c_(size) _Deref_pre_readonly_) +#define _In_opt_count_c_(size) _SAL1_1_Source_(_In_opt_count_c_, (size), _Pre_opt_count_c_(size) _Deref_pre_readonly_) +#define _In_bytecount_c_(size) _SAL1_1_Source_(_In_bytecount_c_, (size), _Pre_bytecount_c_(size) _Deref_pre_readonly_) +#define _In_opt_bytecount_c_(size) _SAL1_1_Source_(_In_opt_bytecount_c_, (size), _Pre_opt_bytecount_c_(size) _Deref_pre_readonly_) + +// nullterminated 'input' buffers with given size + +// e.g. void SetCharRange( _In_count_(cch) const char* rgch, size_t cch ) +// nullterminated valid buffer extent described by another parameter +#define _In_z_count_(size) _SAL1_1_Source_(_In_z_count_, (size), _Pre_z_ _Pre_count_(size) _Deref_pre_readonly_) +#define _In_opt_z_count_(size) _SAL1_1_Source_(_In_opt_z_count_, (size), _Pre_opt_z_ _Pre_opt_count_(size) _Deref_pre_readonly_) +#define _In_z_bytecount_(size) _SAL1_1_Source_(_In_z_bytecount_, (size), _Pre_z_ _Pre_bytecount_(size) _Deref_pre_readonly_) +#define _In_opt_z_bytecount_(size) _SAL1_1_Source_(_In_opt_z_bytecount_, (size), _Pre_opt_z_ _Pre_opt_bytecount_(size) _Deref_pre_readonly_) + +// nullterminated valid buffer extent described by a constant extression +#define _In_z_count_c_(size) _SAL1_1_Source_(_In_z_count_c_, (size), _Pre_z_ _Pre_count_c_(size) _Deref_pre_readonly_) +#define _In_opt_z_count_c_(size) _SAL1_1_Source_(_In_opt_z_count_c_, (size), _Pre_opt_z_ _Pre_opt_count_c_(size) _Deref_pre_readonly_) +#define _In_z_bytecount_c_(size) _SAL1_1_Source_(_In_z_bytecount_c_, (size), _Pre_z_ _Pre_bytecount_c_(size) _Deref_pre_readonly_) +#define _In_opt_z_bytecount_c_(size) _SAL1_1_Source_(_In_opt_z_bytecount_c_, (size), _Pre_opt_z_ _Pre_opt_bytecount_c_(size) _Deref_pre_readonly_) + +// buffer capacity is described by another pointer +// e.g. void Foo( _In_ptrdiff_count_(pchMax) const char* pch, const char* pchMax ) { while pch < pchMax ) pch++; } +#define _In_ptrdiff_count_(size) _SAL1_1_Source_(_In_ptrdiff_count_, (size), _Pre_ptrdiff_count_(size) _Deref_pre_readonly_) +#define _In_opt_ptrdiff_count_(size) _SAL1_1_Source_(_In_opt_ptrdiff_count_, (size), _Pre_opt_ptrdiff_count_(size) _Deref_pre_readonly_) + +// 'x' version for complex expressions that are not supported by the current compiler version +// e.g. void Set3ColMatrix( _In_count_x_(3*cRows) const Elem* matrix, int cRows ); +#define _In_count_x_(size) _SAL1_1_Source_(_In_count_x_, (size), _Pre_count_x_(size) _Deref_pre_readonly_) +#define _In_opt_count_x_(size) _SAL1_1_Source_(_In_opt_count_x_, (size), _Pre_opt_count_x_(size) _Deref_pre_readonly_) +#define _In_bytecount_x_(size) _SAL1_1_Source_(_In_bytecount_x_, (size), _Pre_bytecount_x_(size) _Deref_pre_readonly_) +#define _In_opt_bytecount_x_(size) _SAL1_1_Source_(_In_opt_bytecount_x_, (size), _Pre_opt_bytecount_x_(size) _Deref_pre_readonly_) + + +// 'out' with buffer size +// e.g. void GetIndeces( _Out_cap_(cIndeces) int* rgIndeces, size_t cIndices ); +// buffer capacity is described by another parameter +#define _Out_cap_(size) _SAL1_1_Source_(_Out_cap_, (size), _Pre_cap_(size) _Post_valid_impl_) +#define _Out_opt_cap_(size) _SAL1_1_Source_(_Out_opt_cap_, (size), _Pre_opt_cap_(size) _Post_valid_impl_) +#define _Out_bytecap_(size) _SAL1_1_Source_(_Out_bytecap_, (size), _Pre_bytecap_(size) _Post_valid_impl_) +#define _Out_opt_bytecap_(size) _SAL1_1_Source_(_Out_opt_bytecap_, (size), _Pre_opt_bytecap_(size) _Post_valid_impl_) + +// buffer capacity is described by a constant expression +#define _Out_cap_c_(size) _SAL1_1_Source_(_Out_cap_c_, (size), _Pre_cap_c_(size) _Post_valid_impl_) +#define _Out_opt_cap_c_(size) _SAL1_1_Source_(_Out_opt_cap_c_, (size), _Pre_opt_cap_c_(size) _Post_valid_impl_) +#define _Out_bytecap_c_(size) _SAL1_1_Source_(_Out_bytecap_c_, (size), _Pre_bytecap_c_(size) _Post_valid_impl_) +#define _Out_opt_bytecap_c_(size) _SAL1_1_Source_(_Out_opt_bytecap_c_, (size), _Pre_opt_bytecap_c_(size) _Post_valid_impl_) + +// buffer capacity is described by another parameter multiplied by a constant expression +#define _Out_cap_m_(mult,size) _SAL1_1_Source_(_Out_cap_m_, (mult,size), _Pre_cap_m_(mult,size) _Post_valid_impl_) +#define _Out_opt_cap_m_(mult,size) _SAL1_1_Source_(_Out_opt_cap_m_, (mult,size), _Pre_opt_cap_m_(mult,size) _Post_valid_impl_) +#define _Out_z_cap_m_(mult,size) _SAL1_1_Source_(_Out_z_cap_m_, (mult,size), _Pre_cap_m_(mult,size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_cap_m_(mult,size) _SAL1_1_Source_(_Out_opt_z_cap_m_, (mult,size), _Pre_opt_cap_m_(mult,size) _Post_valid_impl_ _Post_z_) + +// buffer capacity is described by another pointer +// e.g. void Foo( _Out_ptrdiff_cap_(pchMax) char* pch, const char* pchMax ) { while pch < pchMax ) pch++; } +#define _Out_ptrdiff_cap_(size) _SAL1_1_Source_(_Out_ptrdiff_cap_, (size), _Pre_ptrdiff_cap_(size) _Post_valid_impl_) +#define _Out_opt_ptrdiff_cap_(size) _SAL1_1_Source_(_Out_opt_ptrdiff_cap_, (size), _Pre_opt_ptrdiff_cap_(size) _Post_valid_impl_) + +// buffer capacity is described by a complex expression +#define _Out_cap_x_(size) _SAL1_1_Source_(_Out_cap_x_, (size), _Pre_cap_x_(size) _Post_valid_impl_) +#define _Out_opt_cap_x_(size) _SAL1_1_Source_(_Out_opt_cap_x_, (size), _Pre_opt_cap_x_(size) _Post_valid_impl_) +#define _Out_bytecap_x_(size) _SAL1_1_Source_(_Out_bytecap_x_, (size), _Pre_bytecap_x_(size) _Post_valid_impl_) +#define _Out_opt_bytecap_x_(size) _SAL1_1_Source_(_Out_opt_bytecap_x_, (size), _Pre_opt_bytecap_x_(size) _Post_valid_impl_) + +// a zero terminated string is filled into a buffer of given capacity +// e.g. void CopyStr( _In_z_ const char* szFrom, _Out_z_cap_(cchTo) char* szTo, size_t cchTo ); +// buffer capacity is described by another parameter +#define _Out_z_cap_(size) _SAL1_1_Source_(_Out_z_cap_, (size), _Pre_cap_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_cap_(size) _SAL1_1_Source_(_Out_opt_z_cap_, (size), _Pre_opt_cap_(size) _Post_valid_impl_ _Post_z_) +#define _Out_z_bytecap_(size) _SAL1_1_Source_(_Out_z_bytecap_, (size), _Pre_bytecap_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_bytecap_(size) _SAL1_1_Source_(_Out_opt_z_bytecap_, (size), _Pre_opt_bytecap_(size) _Post_valid_impl_ _Post_z_) + +// buffer capacity is described by a constant expression +#define _Out_z_cap_c_(size) _SAL1_1_Source_(_Out_z_cap_c_, (size), _Pre_cap_c_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_cap_c_(size) _SAL1_1_Source_(_Out_opt_z_cap_c_, (size), _Pre_opt_cap_c_(size) _Post_valid_impl_ _Post_z_) +#define _Out_z_bytecap_c_(size) _SAL1_1_Source_(_Out_z_bytecap_c_, (size), _Pre_bytecap_c_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_bytecap_c_(size) _SAL1_1_Source_(_Out_opt_z_bytecap_c_, (size), _Pre_opt_bytecap_c_(size) _Post_valid_impl_ _Post_z_) + +// buffer capacity is described by a complex expression +#define _Out_z_cap_x_(size) _SAL1_1_Source_(_Out_z_cap_x_, (size), _Pre_cap_x_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_cap_x_(size) _SAL1_1_Source_(_Out_opt_z_cap_x_, (size), _Pre_opt_cap_x_(size) _Post_valid_impl_ _Post_z_) +#define _Out_z_bytecap_x_(size) _SAL1_1_Source_(_Out_z_bytecap_x_, (size), _Pre_bytecap_x_(size) _Post_valid_impl_ _Post_z_) +#define _Out_opt_z_bytecap_x_(size) _SAL1_1_Source_(_Out_opt_z_bytecap_x_, (size), _Pre_opt_bytecap_x_(size) _Post_valid_impl_ _Post_z_) + +// a zero terminated string is filled into a buffer of given capacity +// e.g. size_t CopyCharRange( _In_count_(cchFrom) const char* rgchFrom, size_t cchFrom, _Out_cap_post_count_(cchTo,return)) char* rgchTo, size_t cchTo ); +#define _Out_cap_post_count_(cap,count) _SAL1_1_Source_(_Out_cap_post_count_, (cap,count), _Pre_cap_(cap) _Post_valid_impl_ _Post_count_(count)) +#define _Out_opt_cap_post_count_(cap,count) _SAL1_1_Source_(_Out_opt_cap_post_count_, (cap,count), _Pre_opt_cap_(cap) _Post_valid_impl_ _Post_count_(count)) +#define _Out_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_bytecap_post_bytecount_, (cap,count), _Pre_bytecap_(cap) _Post_valid_impl_ _Post_bytecount_(count)) +#define _Out_opt_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_opt_bytecap_post_bytecount_, (cap,count), _Pre_opt_bytecap_(cap) _Post_valid_impl_ _Post_bytecount_(count)) + +// a zero terminated string is filled into a buffer of given capacity +// e.g. size_t CopyStr( _In_z_ const char* szFrom, _Out_z_cap_post_count_(cchTo,return+1) char* szTo, size_t cchTo ); +#define _Out_z_cap_post_count_(cap,count) _SAL1_1_Source_(_Out_z_cap_post_count_, (cap,count), _Pre_cap_(cap) _Post_valid_impl_ _Post_z_count_(count)) +#define _Out_opt_z_cap_post_count_(cap,count) _SAL1_1_Source_(_Out_opt_z_cap_post_count_, (cap,count), _Pre_opt_cap_(cap) _Post_valid_impl_ _Post_z_count_(count)) +#define _Out_z_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_z_bytecap_post_bytecount_, (cap,count), _Pre_bytecap_(cap) _Post_valid_impl_ _Post_z_bytecount_(count)) +#define _Out_opt_z_bytecap_post_bytecount_(cap,count) _SAL1_1_Source_(_Out_opt_z_bytecap_post_bytecount_, (cap,count), _Pre_opt_bytecap_(cap) _Post_valid_impl_ _Post_z_bytecount_(count)) + +// only use with dereferenced arguments e.g. '*pcch' +#define _Out_capcount_(capcount) _SAL1_1_Source_(_Out_capcount_, (capcount), _Pre_cap_(capcount) _Post_valid_impl_ _Post_count_(capcount)) +#define _Out_opt_capcount_(capcount) _SAL1_1_Source_(_Out_opt_capcount_, (capcount), _Pre_opt_cap_(capcount) _Post_valid_impl_ _Post_count_(capcount)) +#define _Out_bytecapcount_(capcount) _SAL1_1_Source_(_Out_bytecapcount_, (capcount), _Pre_bytecap_(capcount) _Post_valid_impl_ _Post_bytecount_(capcount)) +#define _Out_opt_bytecapcount_(capcount) _SAL1_1_Source_(_Out_opt_bytecapcount_, (capcount), _Pre_opt_bytecap_(capcount) _Post_valid_impl_ _Post_bytecount_(capcount)) + +#define _Out_capcount_x_(capcount) _SAL1_1_Source_(_Out_capcount_x_, (capcount), _Pre_cap_x_(capcount) _Post_valid_impl_ _Post_count_x_(capcount)) +#define _Out_opt_capcount_x_(capcount) _SAL1_1_Source_(_Out_opt_capcount_x_, (capcount), _Pre_opt_cap_x_(capcount) _Post_valid_impl_ _Post_count_x_(capcount)) +#define _Out_bytecapcount_x_(capcount) _SAL1_1_Source_(_Out_bytecapcount_x_, (capcount), _Pre_bytecap_x_(capcount) _Post_valid_impl_ _Post_bytecount_x_(capcount)) +#define _Out_opt_bytecapcount_x_(capcount) _SAL1_1_Source_(_Out_opt_bytecapcount_x_, (capcount), _Pre_opt_bytecap_x_(capcount) _Post_valid_impl_ _Post_bytecount_x_(capcount)) + +// e.g. GetString( _Out_z_capcount_(*pLen+1) char* sz, size_t* pLen ); +#define _Out_z_capcount_(capcount) _SAL1_1_Source_(_Out_z_capcount_, (capcount), _Pre_cap_(capcount) _Post_valid_impl_ _Post_z_count_(capcount)) +#define _Out_opt_z_capcount_(capcount) _SAL1_1_Source_(_Out_opt_z_capcount_, (capcount), _Pre_opt_cap_(capcount) _Post_valid_impl_ _Post_z_count_(capcount)) +#define _Out_z_bytecapcount_(capcount) _SAL1_1_Source_(_Out_z_bytecapcount_, (capcount), _Pre_bytecap_(capcount) _Post_valid_impl_ _Post_z_bytecount_(capcount)) +#define _Out_opt_z_bytecapcount_(capcount) _SAL1_1_Source_(_Out_opt_z_bytecapcount_, (capcount), _Pre_opt_bytecap_(capcount) _Post_valid_impl_ _Post_z_bytecount_(capcount)) + + +// 'inout' buffers with initialized elements before and after the call +// e.g. void ModifyIndices( _Inout_count_(cIndices) int* rgIndeces, size_t cIndices ); +#define _Inout_count_(size) _SAL1_1_Source_(_Inout_count_, (size), _Prepost_count_(size)) +#define _Inout_opt_count_(size) _SAL1_1_Source_(_Inout_opt_count_, (size), _Prepost_opt_count_(size)) +#define _Inout_bytecount_(size) _SAL1_1_Source_(_Inout_bytecount_, (size), _Prepost_bytecount_(size)) +#define _Inout_opt_bytecount_(size) _SAL1_1_Source_(_Inout_opt_bytecount_, (size), _Prepost_opt_bytecount_(size)) + +#define _Inout_count_c_(size) _SAL1_1_Source_(_Inout_count_c_, (size), _Prepost_count_c_(size)) +#define _Inout_opt_count_c_(size) _SAL1_1_Source_(_Inout_opt_count_c_, (size), _Prepost_opt_count_c_(size)) +#define _Inout_bytecount_c_(size) _SAL1_1_Source_(_Inout_bytecount_c_, (size), _Prepost_bytecount_c_(size)) +#define _Inout_opt_bytecount_c_(size) _SAL1_1_Source_(_Inout_opt_bytecount_c_, (size), _Prepost_opt_bytecount_c_(size)) + +// nullterminated 'inout' buffers with initialized elements before and after the call +// e.g. void ModifyIndices( _Inout_count_(cIndices) int* rgIndeces, size_t cIndices ); +#define _Inout_z_count_(size) _SAL1_1_Source_(_Inout_z_count_, (size), _Prepost_z_ _Prepost_count_(size)) +#define _Inout_opt_z_count_(size) _SAL1_1_Source_(_Inout_opt_z_count_, (size), _Prepost_z_ _Prepost_opt_count_(size)) +#define _Inout_z_bytecount_(size) _SAL1_1_Source_(_Inout_z_bytecount_, (size), _Prepost_z_ _Prepost_bytecount_(size)) +#define _Inout_opt_z_bytecount_(size) _SAL1_1_Source_(_Inout_opt_z_bytecount_, (size), _Prepost_z_ _Prepost_opt_bytecount_(size)) + +#define _Inout_z_count_c_(size) _SAL1_1_Source_(_Inout_z_count_c_, (size), _Prepost_z_ _Prepost_count_c_(size)) +#define _Inout_opt_z_count_c_(size) _SAL1_1_Source_(_Inout_opt_z_count_c_, (size), _Prepost_z_ _Prepost_opt_count_c_(size)) +#define _Inout_z_bytecount_c_(size) _SAL1_1_Source_(_Inout_z_bytecount_c_, (size), _Prepost_z_ _Prepost_bytecount_c_(size)) +#define _Inout_opt_z_bytecount_c_(size) _SAL1_1_Source_(_Inout_opt_z_bytecount_c_, (size), _Prepost_z_ _Prepost_opt_bytecount_c_(size)) + +#define _Inout_ptrdiff_count_(size) _SAL1_1_Source_(_Inout_ptrdiff_count_, (size), _Pre_ptrdiff_count_(size)) +#define _Inout_opt_ptrdiff_count_(size) _SAL1_1_Source_(_Inout_opt_ptrdiff_count_, (size), _Pre_opt_ptrdiff_count_(size)) + +#define _Inout_count_x_(size) _SAL1_1_Source_(_Inout_count_x_, (size), _Prepost_count_x_(size)) +#define _Inout_opt_count_x_(size) _SAL1_1_Source_(_Inout_opt_count_x_, (size), _Prepost_opt_count_x_(size)) +#define _Inout_bytecount_x_(size) _SAL1_1_Source_(_Inout_bytecount_x_, (size), _Prepost_bytecount_x_(size)) +#define _Inout_opt_bytecount_x_(size) _SAL1_1_Source_(_Inout_opt_bytecount_x_, (size), _Prepost_opt_bytecount_x_(size)) + +// e.g. void AppendToLPSTR( _In_ LPCSTR szFrom, _Inout_cap_(cchTo) LPSTR* szTo, size_t cchTo ); +#define _Inout_cap_(size) _SAL1_1_Source_(_Inout_cap_, (size), _Pre_valid_cap_(size) _Post_valid_) +#define _Inout_opt_cap_(size) _SAL1_1_Source_(_Inout_opt_cap_, (size), _Pre_opt_valid_cap_(size) _Post_valid_) +#define _Inout_bytecap_(size) _SAL1_1_Source_(_Inout_bytecap_, (size), _Pre_valid_bytecap_(size) _Post_valid_) +#define _Inout_opt_bytecap_(size) _SAL1_1_Source_(_Inout_opt_bytecap_, (size), _Pre_opt_valid_bytecap_(size) _Post_valid_) + +#define _Inout_cap_c_(size) _SAL1_1_Source_(_Inout_cap_c_, (size), _Pre_valid_cap_c_(size) _Post_valid_) +#define _Inout_opt_cap_c_(size) _SAL1_1_Source_(_Inout_opt_cap_c_, (size), _Pre_opt_valid_cap_c_(size) _Post_valid_) +#define _Inout_bytecap_c_(size) _SAL1_1_Source_(_Inout_bytecap_c_, (size), _Pre_valid_bytecap_c_(size) _Post_valid_) +#define _Inout_opt_bytecap_c_(size) _SAL1_1_Source_(_Inout_opt_bytecap_c_, (size), _Pre_opt_valid_bytecap_c_(size) _Post_valid_) + +#define _Inout_cap_x_(size) _SAL1_1_Source_(_Inout_cap_x_, (size), _Pre_valid_cap_x_(size) _Post_valid_) +#define _Inout_opt_cap_x_(size) _SAL1_1_Source_(_Inout_opt_cap_x_, (size), _Pre_opt_valid_cap_x_(size) _Post_valid_) +#define _Inout_bytecap_x_(size) _SAL1_1_Source_(_Inout_bytecap_x_, (size), _Pre_valid_bytecap_x_(size) _Post_valid_) +#define _Inout_opt_bytecap_x_(size) _SAL1_1_Source_(_Inout_opt_bytecap_x_, (size), _Pre_opt_valid_bytecap_x_(size) _Post_valid_) + +// inout string buffers with writable size +// e.g. void AppendStr( _In_z_ const char* szFrom, _Inout_z_cap_(cchTo) char* szTo, size_t cchTo ); +#define _Inout_z_cap_(size) _SAL1_1_Source_(_Inout_z_cap_, (size), _Pre_z_cap_(size) _Post_z_) +#define _Inout_opt_z_cap_(size) _SAL1_1_Source_(_Inout_opt_z_cap_, (size), _Pre_opt_z_cap_(size) _Post_z_) +#define _Inout_z_bytecap_(size) _SAL1_1_Source_(_Inout_z_bytecap_, (size), _Pre_z_bytecap_(size) _Post_z_) +#define _Inout_opt_z_bytecap_(size) _SAL1_1_Source_(_Inout_opt_z_bytecap_, (size), _Pre_opt_z_bytecap_(size) _Post_z_) + +#define _Inout_z_cap_c_(size) _SAL1_1_Source_(_Inout_z_cap_c_, (size), _Pre_z_cap_c_(size) _Post_z_) +#define _Inout_opt_z_cap_c_(size) _SAL1_1_Source_(_Inout_opt_z_cap_c_, (size), _Pre_opt_z_cap_c_(size) _Post_z_) +#define _Inout_z_bytecap_c_(size) _SAL1_1_Source_(_Inout_z_bytecap_c_, (size), _Pre_z_bytecap_c_(size) _Post_z_) +#define _Inout_opt_z_bytecap_c_(size) _SAL1_1_Source_(_Inout_opt_z_bytecap_c_, (size), _Pre_opt_z_bytecap_c_(size) _Post_z_) + +#define _Inout_z_cap_x_(size) _SAL1_1_Source_(_Inout_z_cap_x_, (size), _Pre_z_cap_x_(size) _Post_z_) +#define _Inout_opt_z_cap_x_(size) _SAL1_1_Source_(_Inout_opt_z_cap_x_, (size), _Pre_opt_z_cap_x_(size) _Post_z_) +#define _Inout_z_bytecap_x_(size) _SAL1_1_Source_(_Inout_z_bytecap_x_, (size), _Pre_z_bytecap_x_(size) _Post_z_) +#define _Inout_opt_z_bytecap_x_(size) _SAL1_1_Source_(_Inout_opt_z_bytecap_x_, (size), _Pre_opt_z_bytecap_x_(size) _Post_z_) + + +// returning pointers to valid objects +#define _Ret_ _SAL1_1_Source_(_Ret_, (), _Ret_valid_) +#define _Ret_opt_ _SAL1_1_Source_(_Ret_opt_, (), _Ret_opt_valid_) + +// annotations to express 'boundedness' of integral value parameter +#define _In_bound_ _SAL1_1_Source_(_In_bound_, (), _In_bound_impl_) +#define _Out_bound_ _SAL1_1_Source_(_Out_bound_, (), _Out_bound_impl_) +#define _Ret_bound_ _SAL1_1_Source_(_Ret_bound_, (), _Ret_bound_impl_) +#define _Deref_in_bound_ _SAL1_1_Source_(_Deref_in_bound_, (), _Deref_in_bound_impl_) +#define _Deref_out_bound_ _SAL1_1_Source_(_Deref_out_bound_, (), _Deref_out_bound_impl_) +#define _Deref_inout_bound_ _SAL1_1_Source_(_Deref_inout_bound_, (), _Deref_in_bound_ _Deref_out_bound_) +#define _Deref_ret_bound_ _SAL1_1_Source_(_Deref_ret_bound_, (), _Deref_ret_bound_impl_) + +// e.g. HRESULT HrCreatePoint( _Deref_out_opt_ POINT** ppPT ); +#define _Deref_out_ _SAL1_1_Source_(_Deref_out_, (), _Out_ _Deref_post_valid_) +#define _Deref_out_opt_ _SAL1_1_Source_(_Deref_out_opt_, (), _Out_ _Deref_post_opt_valid_) +#define _Deref_opt_out_ _SAL1_1_Source_(_Deref_opt_out_, (), _Out_opt_ _Deref_post_valid_) +#define _Deref_opt_out_opt_ _SAL1_1_Source_(_Deref_opt_out_opt_, (), _Out_opt_ _Deref_post_opt_valid_) + +// e.g. void CloneString( _In_z_ const WCHAR* wzFrom, _Deref_out_z_ WCHAR** pWzTo ); +#define _Deref_out_z_ _SAL1_1_Source_(_Deref_out_z_, (), _Out_ _Deref_post_z_) +#define _Deref_out_opt_z_ _SAL1_1_Source_(_Deref_out_opt_z_, (), _Out_ _Deref_post_opt_z_) +#define _Deref_opt_out_z_ _SAL1_1_Source_(_Deref_opt_out_z_, (), _Out_opt_ _Deref_post_z_) +#define _Deref_opt_out_opt_z_ _SAL1_1_Source_(_Deref_opt_out_opt_z_, (), _Out_opt_ _Deref_post_opt_z_) + +// +// _Deref_pre_ --- +// +// describing conditions for array elements of dereferenced pointer parameters that must be met before the call + +// e.g. void SaveStringArray( _In_count_(cStrings) _Deref_pre_z_ const WCHAR* const rgpwch[] ); +#define _Deref_pre_z_ _SAL1_1_Source_(_Deref_pre_z_, (), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__zterm_impl) _Pre_valid_impl_) +#define _Deref_pre_opt_z_ _SAL1_1_Source_(_Deref_pre_opt_z_, (), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__zterm_impl) _Pre_valid_impl_) + +// e.g. void FillInArrayOfStr32( _In_count_(cStrings) _Deref_pre_cap_c_(32) _Deref_post_z_ WCHAR* const rgpwch[] ); +// buffer capacity is described by another parameter +#define _Deref_pre_cap_(size) _SAL1_1_Source_(_Deref_pre_cap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_impl(size))) +#define _Deref_pre_opt_cap_(size) _SAL1_1_Source_(_Deref_pre_opt_cap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_impl(size))) +#define _Deref_pre_bytecap_(size) _SAL1_1_Source_(_Deref_pre_bytecap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_impl(size))) +#define _Deref_pre_opt_bytecap_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_impl(size))) + +// buffer capacity is described by a constant expression +#define _Deref_pre_cap_c_(size) _SAL1_1_Source_(_Deref_pre_cap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_c_impl(size))) +#define _Deref_pre_opt_cap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_cap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_c_impl(size))) +#define _Deref_pre_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_bytecap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_c_impl(size))) +#define _Deref_pre_opt_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_c_impl(size))) + +// buffer capacity is described by a complex condition +#define _Deref_pre_cap_x_(size) _SAL1_1_Source_(_Deref_pre_cap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_x_impl(size))) +#define _Deref_pre_opt_cap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_cap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_x_impl(size))) +#define _Deref_pre_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_bytecap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size))) +#define _Deref_pre_opt_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size))) + +// convenience macros for nullterminated buffers with given capacity +#define _Deref_pre_z_cap_(size) _SAL1_1_Source_(_Deref_pre_z_cap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_cap_(size) _SAL1_1_Source_(_Deref_pre_opt_z_cap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_z_bytecap_(size) _SAL1_1_Source_(_Deref_pre_z_bytecap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_bytecap_(size) _SAL1_1_Source_(_Deref_pre_opt_z_bytecap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_) + +#define _Deref_pre_z_cap_c_(size) _SAL1_1_Source_(_Deref_pre_z_cap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_cap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_z_cap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_z_bytecap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_z_bytecap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_) + +#define _Deref_pre_z_cap_x_(size) _SAL1_1_Source_(_Deref_pre_z_cap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_cap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_z_cap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_z_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_z_bytecap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_z_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_z_bytecap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_) + +// known capacity and valid but unknown readable extent +#define _Deref_pre_valid_cap_(size) _SAL1_1_Source_(_Deref_pre_valid_cap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_cap_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_cap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_valid_bytecap_(size) _SAL1_1_Source_(_Deref_pre_valid_bytecap_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_bytecap_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_bytecap_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_impl(size)) _Pre_valid_impl_) + +#define _Deref_pre_valid_cap_c_(size) _SAL1_1_Source_(_Deref_pre_valid_cap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_cap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_cap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_valid_bytecap_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_bytecap_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_c_impl(size)) _Pre_valid_impl_) + +#define _Deref_pre_valid_cap_x_(size) _SAL1_1_Source_(_Deref_pre_valid_cap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__cap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_cap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_cap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__cap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_valid_bytecap_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_pre_opt_valid_bytecap_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) + +// e.g. void SaveMatrix( _In_count_(n) _Deref_pre_count_(n) const Elem** matrix, size_t n ); +// valid buffer extent is described by another parameter +#define _Deref_pre_count_(size) _SAL1_1_Source_(_Deref_pre_count_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_count_(size) _SAL1_1_Source_(_Deref_pre_opt_count_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_bytecount_(size) _SAL1_1_Source_(_Deref_pre_bytecount_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecount_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_bytecount_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecount_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecount_impl(size)) _Pre_valid_impl_) + +// valid buffer extent is described by a constant expression +#define _Deref_pre_count_c_(size) _SAL1_1_Source_(_Deref_pre_count_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_count_c_(size) _SAL1_1_Source_(_Deref_pre_opt_count_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_bytecount_c_(size) _SAL1_1_Source_(_Deref_pre_bytecount_c_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecount_c_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_bytecount_c_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecount_c_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecount_c_impl(size)) _Pre_valid_impl_) + +// valid buffer extent is described by a complex expression +#define _Deref_pre_count_x_(size) _SAL1_1_Source_(_Deref_pre_count_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__count_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_count_x_(size) _SAL1_1_Source_(_Deref_pre_opt_count_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__count_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_bytecount_x_(size) _SAL1_1_Source_(_Deref_pre_bytecount_x_, (size), _Deref_pre1_impl_(__notnull_impl_notref) _Deref_pre1_impl_(__bytecount_x_impl(size)) _Pre_valid_impl_) +#define _Deref_pre_opt_bytecount_x_(size) _SAL1_1_Source_(_Deref_pre_opt_bytecount_x_, (size), _Deref_pre1_impl_(__maybenull_impl_notref) _Deref_pre1_impl_(__bytecount_x_impl(size)) _Pre_valid_impl_) + +// e.g. void PrintStringArray( _In_count_(cElems) _Deref_pre_valid_ LPCSTR rgStr[], size_t cElems ); +#define _Deref_pre_valid_ _SAL1_1_Source_(_Deref_pre_valid_, (), _Deref_pre1_impl_(__notnull_impl_notref) _Pre_valid_impl_) +#define _Deref_pre_opt_valid_ _SAL1_1_Source_(_Deref_pre_opt_valid_, (), _Deref_pre1_impl_(__maybenull_impl_notref) _Pre_valid_impl_) +#define _Deref_pre_invalid_ _SAL1_1_Source_(_Deref_pre_invalid_, (), _Deref_pre1_impl_(__notvalid_impl)) + +#define _Deref_pre_notnull_ _SAL1_1_Source_(_Deref_pre_notnull_, (), _Deref_pre1_impl_(__notnull_impl_notref)) +#define _Deref_pre_maybenull_ _SAL1_1_Source_(_Deref_pre_maybenull_, (), _Deref_pre1_impl_(__maybenull_impl_notref)) +#define _Deref_pre_null_ _SAL1_1_Source_(_Deref_pre_null_, (), _Deref_pre1_impl_(__null_impl_notref)) + +// restrict access rights +#define _Deref_pre_readonly_ _SAL1_1_Source_(_Deref_pre_readonly_, (), _Deref_pre1_impl_(__readaccess_impl_notref)) +#define _Deref_pre_writeonly_ _SAL1_1_Source_(_Deref_pre_writeonly_, (), _Deref_pre1_impl_(__writeaccess_impl_notref)) + +// +// _Deref_post_ --- +// +// describing conditions for array elements or dereferenced pointer parameters that hold after the call + +// e.g. void CloneString( _In_z_ const Wchar_t* wzIn _Out_ _Deref_post_z_ WCHAR** pWzOut ); +#define _Deref_post_z_ _SAL1_1_Source_(_Deref_post_z_, (), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__zterm_impl) _Post_valid_impl_) +#define _Deref_post_opt_z_ _SAL1_1_Source_(_Deref_post_opt_z_, (), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__zterm_impl) _Post_valid_impl_) + +// e.g. HRESULT HrAllocateMemory( size_t cb, _Out_ _Deref_post_bytecap_(cb) void** ppv ); +// buffer capacity is described by another parameter +#define _Deref_post_cap_(size) _SAL1_1_Source_(_Deref_post_cap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_impl(size))) +#define _Deref_post_opt_cap_(size) _SAL1_1_Source_(_Deref_post_opt_cap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_impl(size))) +#define _Deref_post_bytecap_(size) _SAL1_1_Source_(_Deref_post_bytecap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size))) +#define _Deref_post_opt_bytecap_(size) _SAL1_1_Source_(_Deref_post_opt_bytecap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size))) + +// buffer capacity is described by a constant expression +#define _Deref_post_cap_c_(size) _SAL1_1_Source_(_Deref_post_cap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size))) +#define _Deref_post_opt_cap_c_(size) _SAL1_1_Source_(_Deref_post_opt_cap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size))) +#define _Deref_post_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_bytecap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size))) +#define _Deref_post_opt_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_opt_bytecap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size))) + +// buffer capacity is described by a complex expression +#define _Deref_post_cap_x_(size) _SAL1_1_Source_(_Deref_post_cap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size))) +#define _Deref_post_opt_cap_x_(size) _SAL1_1_Source_(_Deref_post_opt_cap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size))) +#define _Deref_post_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_bytecap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_x_impl(size))) +#define _Deref_post_opt_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_opt_bytecap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_x_impl(size))) + +// convenience macros for nullterminated buffers with given capacity +#define _Deref_post_z_cap_(size) _SAL1_1_Source_(_Deref_post_z_cap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_cap_(size) _SAL1_1_Source_(_Deref_post_opt_z_cap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_impl(size)) _Post_valid_impl_) +#define _Deref_post_z_bytecap_(size) _SAL1_1_Source_(_Deref_post_z_bytecap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_bytecap_(size) _SAL1_1_Source_(_Deref_post_opt_z_bytecap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_impl(size)) _Post_valid_impl_) + +#define _Deref_post_z_cap_c_(size) _SAL1_1_Source_(_Deref_post_z_cap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_cap_c_(size) _SAL1_1_Source_(_Deref_post_opt_z_cap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_z_bytecap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_opt_z_bytecap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Post_valid_impl_) + +#define _Deref_post_z_cap_x_(size) _SAL1_1_Source_(_Deref_post_z_cap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_cap_x_(size) _SAL1_1_Source_(_Deref_post_opt_z_cap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__cap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_z_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_z_bytecap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_z_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_opt_z_bytecap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Post_valid_impl_) + +// known capacity and valid but unknown readable extent +#define _Deref_post_valid_cap_(size) _SAL1_1_Source_(_Deref_post_valid_cap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_cap_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_impl(size)) _Post_valid_impl_) +#define _Deref_post_valid_bytecap_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_bytecap_(size) _SAL1_1_Source_(_Deref_post_opt_valid_bytecap_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_impl(size)) _Post_valid_impl_) + +#define _Deref_post_valid_cap_c_(size) _SAL1_1_Source_(_Deref_post_valid_cap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_cap_c_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_bytecap_c_(size) _SAL1_1_Source_(_Deref_post_opt_valid_bytecap_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_c_impl(size)) _Post_valid_impl_) + +#define _Deref_post_valid_cap_x_(size) _SAL1_1_Source_(_Deref_post_valid_cap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_cap_x_(size) _SAL1_1_Source_(_Deref_post_opt_valid_cap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__cap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_valid_bytecap_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecap_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_post_opt_valid_bytecap_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecap_x_impl(size)) _Post_valid_impl_) + +// e.g. HRESULT HrAllocateZeroInitializedMemory( size_t cb, _Out_ _Deref_post_bytecount_(cb) void** ppv ); +// valid buffer extent is described by another parameter +#define _Deref_post_count_(size) _SAL1_1_Source_(_Deref_post_count_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__count_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_count_(size) _SAL1_1_Source_(_Deref_post_opt_count_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__count_impl(size)) _Post_valid_impl_) +#define _Deref_post_bytecount_(size) _SAL1_1_Source_(_Deref_post_bytecount_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecount_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_bytecount_(size) _SAL1_1_Source_(_Deref_post_opt_bytecount_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecount_impl(size)) _Post_valid_impl_) + +// buffer capacity is described by a constant expression +#define _Deref_post_count_c_(size) _SAL1_1_Source_(_Deref_post_count_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__count_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_count_c_(size) _SAL1_1_Source_(_Deref_post_opt_count_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__count_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_bytecount_c_(size) _SAL1_1_Source_(_Deref_post_bytecount_c_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecount_c_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_bytecount_c_(size) _SAL1_1_Source_(_Deref_post_opt_bytecount_c_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecount_c_impl(size)) _Post_valid_impl_) + +// buffer capacity is described by a complex expression +#define _Deref_post_count_x_(size) _SAL1_1_Source_(_Deref_post_count_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__count_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_count_x_(size) _SAL1_1_Source_(_Deref_post_opt_count_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__count_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_bytecount_x_(size) _SAL1_1_Source_(_Deref_post_bytecount_x_, (size), _Deref_post1_impl_(__notnull_impl_notref) _Deref_post1_impl_(__bytecount_x_impl(size)) _Post_valid_impl_) +#define _Deref_post_opt_bytecount_x_(size) _SAL1_1_Source_(_Deref_post_opt_bytecount_x_, (size), _Deref_post1_impl_(__maybenull_impl_notref) _Deref_post1_impl_(__bytecount_x_impl(size)) _Post_valid_impl_) + +// e.g. void GetStrings( _Out_count_(cElems) _Deref_post_valid_ LPSTR const rgStr[], size_t cElems ); +#define _Deref_post_valid_ _SAL1_1_Source_(_Deref_post_valid_, (), _Deref_post1_impl_(__notnull_impl_notref) _Post_valid_impl_) +#define _Deref_post_opt_valid_ _SAL1_1_Source_(_Deref_post_opt_valid_, (), _Deref_post1_impl_(__maybenull_impl_notref) _Post_valid_impl_) + +#define _Deref_post_notnull_ _SAL1_1_Source_(_Deref_post_notnull_, (), _Deref_post1_impl_(__notnull_impl_notref)) +#define _Deref_post_maybenull_ _SAL1_1_Source_(_Deref_post_maybenull_, (), _Deref_post1_impl_(__maybenull_impl_notref)) +#define _Deref_post_null_ _SAL1_1_Source_(_Deref_post_null_, (), _Deref_post1_impl_(__null_impl_notref)) + +// +// _Deref_ret_ --- +// + +#define _Deref_ret_z_ _SAL1_1_Source_(_Deref_ret_z_, (), _Deref_ret1_impl_(__notnull_impl_notref) _Deref_ret1_impl_(__zterm_impl)) +#define _Deref_ret_opt_z_ _SAL1_1_Source_(_Deref_ret_opt_z_, (), _Deref_ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__zterm_impl)) + +// +// special _Deref_ --- +// +#define _Deref2_pre_readonly_ _SAL1_1_Source_(_Deref2_pre_readonly_, (), _Deref2_pre1_impl_(__readaccess_impl_notref)) + +// +// _Ret_ --- +// + +// e.g. _Ret_opt_valid_ LPSTR void* CloneSTR( _Pre_valid_ LPSTR src ); +#define _Ret_opt_valid_ _SAL1_1_Source_(_Ret_opt_valid_, (), _Ret1_impl_(__maybenull_impl_notref) _Ret_valid_impl_) +#define _Ret_opt_z_ _SAL1_1_Source_(_Ret_opt_z_, (), _Ret2_impl_(__maybenull_impl,__zterm_impl) _Ret_valid_impl_) + +// e.g. _Ret_opt_bytecap_(cb) void* AllocateMemory( size_t cb ); +// Buffer capacity is described by another parameter +#define _Ret_cap_(size) _SAL1_1_Source_(_Ret_cap_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__cap_impl(size))) +#define _Ret_opt_cap_(size) _SAL1_1_Source_(_Ret_opt_cap_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__cap_impl(size))) +#define _Ret_bytecap_(size) _SAL1_1_Source_(_Ret_bytecap_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecap_impl(size))) +#define _Ret_opt_bytecap_(size) _SAL1_1_Source_(_Ret_opt_bytecap_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecap_impl(size))) + +// Buffer capacity is described by a constant expression +#define _Ret_cap_c_(size) _SAL1_1_Source_(_Ret_cap_c_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__cap_c_impl(size))) +#define _Ret_opt_cap_c_(size) _SAL1_1_Source_(_Ret_opt_cap_c_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__cap_c_impl(size))) +#define _Ret_bytecap_c_(size) _SAL1_1_Source_(_Ret_bytecap_c_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecap_c_impl(size))) +#define _Ret_opt_bytecap_c_(size) _SAL1_1_Source_(_Ret_opt_bytecap_c_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecap_c_impl(size))) + +// Buffer capacity is described by a complex condition +#define _Ret_cap_x_(size) _SAL1_1_Source_(_Ret_cap_x_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__cap_x_impl(size))) +#define _Ret_opt_cap_x_(size) _SAL1_1_Source_(_Ret_opt_cap_x_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__cap_x_impl(size))) +#define _Ret_bytecap_x_(size) _SAL1_1_Source_(_Ret_bytecap_x_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecap_x_impl(size))) +#define _Ret_opt_bytecap_x_(size) _SAL1_1_Source_(_Ret_opt_bytecap_x_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecap_x_impl(size))) + +// return value is nullterminated and capacity is given by another parameter +#define _Ret_z_cap_(size) _SAL1_1_Source_(_Ret_z_cap_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret2_impl_(__zterm_impl,__cap_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_z_cap_(size) _SAL1_1_Source_(_Ret_opt_z_cap_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret2_impl_(__zterm_impl,__cap_impl(size)) _Ret_valid_impl_) +#define _Ret_z_bytecap_(size) _SAL1_1_Source_(_Ret_z_bytecap_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret2_impl_(__zterm_impl,__bytecap_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_z_bytecap_(size) _SAL1_1_Source_(_Ret_opt_z_bytecap_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret2_impl_(__zterm_impl,__bytecap_impl(size)) _Ret_valid_impl_) + +// e.g. _Ret_opt_bytecount_(cb) void* AllocateZeroInitializedMemory( size_t cb ); +// Valid Buffer extent is described by another parameter +#define _Ret_count_(size) _SAL1_1_Source_(_Ret_count_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__count_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_count_(size) _SAL1_1_Source_(_Ret_opt_count_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__count_impl(size)) _Ret_valid_impl_) +#define _Ret_bytecount_(size) _SAL1_1_Source_(_Ret_bytecount_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecount_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_bytecount_(size) _SAL1_1_Source_(_Ret_opt_bytecount_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecount_impl(size)) _Ret_valid_impl_) + +// Valid Buffer extent is described by a constant expression +#define _Ret_count_c_(size) _SAL1_1_Source_(_Ret_count_c_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__count_c_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_count_c_(size) _SAL1_1_Source_(_Ret_opt_count_c_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__count_c_impl(size)) _Ret_valid_impl_) +#define _Ret_bytecount_c_(size) _SAL1_1_Source_(_Ret_bytecount_c_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecount_c_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_bytecount_c_(size) _SAL1_1_Source_(_Ret_opt_bytecount_c_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecount_c_impl(size)) _Ret_valid_impl_) + +// Valid Buffer extent is described by a complex expression +#define _Ret_count_x_(size) _SAL1_1_Source_(_Ret_count_x_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__count_x_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_count_x_(size) _SAL1_1_Source_(_Ret_opt_count_x_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__count_x_impl(size)) _Ret_valid_impl_) +#define _Ret_bytecount_x_(size) _SAL1_1_Source_(_Ret_bytecount_x_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret1_impl_(__bytecount_x_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_bytecount_x_(size) _SAL1_1_Source_(_Ret_opt_bytecount_x_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret1_impl_(__bytecount_x_impl(size)) _Ret_valid_impl_) + +// return value is nullterminated and length is given by another parameter +#define _Ret_z_count_(size) _SAL1_1_Source_(_Ret_z_count_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret2_impl_(__zterm_impl,__count_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_z_count_(size) _SAL1_1_Source_(_Ret_opt_z_count_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret2_impl_(__zterm_impl,__count_impl(size)) _Ret_valid_impl_) +#define _Ret_z_bytecount_(size) _SAL1_1_Source_(_Ret_z_bytecount_, (size), _Ret1_impl_(__notnull_impl_notref) _Ret2_impl_(__zterm_impl,__bytecount_impl(size)) _Ret_valid_impl_) +#define _Ret_opt_z_bytecount_(size) _SAL1_1_Source_(_Ret_opt_z_bytecount_, (size), _Ret1_impl_(__maybenull_impl_notref) _Ret2_impl_(__zterm_impl,__bytecount_impl(size)) _Ret_valid_impl_) + + +// _Pre_ annotations --- +#define _Pre_opt_z_ _SAL1_1_Source_(_Pre_opt_z_, (), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__zterm_impl) _Pre_valid_impl_) + +// restrict access rights +#define _Pre_readonly_ _SAL1_1_Source_(_Pre_readonly_, (), _Pre1_impl_(__readaccess_impl_notref)) +#define _Pre_writeonly_ _SAL1_1_Source_(_Pre_writeonly_, (), _Pre1_impl_(__writeaccess_impl_notref)) + +// e.g. void FreeMemory( _Pre_bytecap_(cb) _Post_ptr_invalid_ void* pv, size_t cb ); +// buffer capacity described by another parameter +#define _Pre_cap_(size) _SAL1_1_Source_(_Pre_cap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_impl(size))) +#define _Pre_opt_cap_(size) _SAL1_1_Source_(_Pre_opt_cap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_impl(size))) +#define _Pre_bytecap_(size) _SAL1_1_Source_(_Pre_bytecap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_impl(size))) +#define _Pre_opt_bytecap_(size) _SAL1_1_Source_(_Pre_opt_bytecap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_impl(size))) + +// buffer capacity described by a constant expression +#define _Pre_cap_c_(size) _SAL1_1_Source_(_Pre_cap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_c_impl(size))) +#define _Pre_opt_cap_c_(size) _SAL1_1_Source_(_Pre_opt_cap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_c_impl(size))) +#define _Pre_bytecap_c_(size) _SAL1_1_Source_(_Pre_bytecap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_c_impl(size))) +#define _Pre_opt_bytecap_c_(size) _SAL1_1_Source_(_Pre_opt_bytecap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_c_impl(size))) +#define _Pre_cap_c_one_ _SAL1_1_Source_(_Pre_cap_c_one_, (), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_c_one_notref_impl)) +#define _Pre_opt_cap_c_one_ _SAL1_1_Source_(_Pre_opt_cap_c_one_, (), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_c_one_notref_impl)) + +// buffer capacity is described by another parameter multiplied by a constant expression +#define _Pre_cap_m_(mult,size) _SAL1_1_Source_(_Pre_cap_m_, (mult,size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__mult_impl(mult,size))) +#define _Pre_opt_cap_m_(mult,size) _SAL1_1_Source_(_Pre_opt_cap_m_, (mult,size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__mult_impl(mult,size))) + +// buffer capacity described by size of other buffer, only used by dangerous legacy APIs +// e.g. int strcpy(_Pre_cap_for_(src) char* dst, const char* src); +#define _Pre_cap_for_(param) _SAL1_1_Source_(_Pre_cap_for_, (param), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_for_impl(param))) +#define _Pre_opt_cap_for_(param) _SAL1_1_Source_(_Pre_opt_cap_for_, (param), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_for_impl(param))) + +// buffer capacity described by a complex condition +#define _Pre_cap_x_(size) _SAL1_1_Source_(_Pre_cap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_x_impl(size))) +#define _Pre_opt_cap_x_(size) _SAL1_1_Source_(_Pre_opt_cap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_x_impl(size))) +#define _Pre_bytecap_x_(size) _SAL1_1_Source_(_Pre_bytecap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_x_impl(size))) +#define _Pre_opt_bytecap_x_(size) _SAL1_1_Source_(_Pre_opt_bytecap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_x_impl(size))) + +// buffer capacity described by the difference to another pointer parameter +#define _Pre_ptrdiff_cap_(ptr) _SAL1_1_Source_(_Pre_ptrdiff_cap_, (ptr), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_x_impl(__ptrdiff(ptr)))) +#define _Pre_opt_ptrdiff_cap_(ptr) _SAL1_1_Source_(_Pre_opt_ptrdiff_cap_, (ptr), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_x_impl(__ptrdiff(ptr)))) + +// e.g. void AppendStr( _Pre_z_ const char* szFrom, _Pre_z_cap_(cchTo) _Post_z_ char* szTo, size_t cchTo ); +#define _Pre_z_cap_(size) _SAL1_1_Source_(_Pre_z_cap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_cap_(size) _SAL1_1_Source_(_Pre_opt_z_cap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_impl(size)) _Pre_valid_impl_) +#define _Pre_z_bytecap_(size) _SAL1_1_Source_(_Pre_z_bytecap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_bytecap_(size) _SAL1_1_Source_(_Pre_opt_z_bytecap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_impl(size)) _Pre_valid_impl_) + +#define _Pre_z_cap_c_(size) _SAL1_1_Source_(_Pre_z_cap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_cap_c_(size) _SAL1_1_Source_(_Pre_opt_z_cap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_z_bytecap_c_(size) _SAL1_1_Source_(_Pre_z_bytecap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_bytecap_c_(size) _SAL1_1_Source_(_Pre_opt_z_bytecap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_c_impl(size)) _Pre_valid_impl_) + +#define _Pre_z_cap_x_(size) _SAL1_1_Source_(_Pre_z_cap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_cap_x_(size) _SAL1_1_Source_(_Pre_opt_z_cap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__cap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_z_bytecap_x_(size) _SAL1_1_Source_(_Pre_z_bytecap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_z_bytecap_x_(size) _SAL1_1_Source_(_Pre_opt_z_bytecap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre2_impl_(__zterm_impl,__bytecap_x_impl(size)) _Pre_valid_impl_) + +// known capacity and valid but unknown readable extent +#define _Pre_valid_cap_(size) _SAL1_1_Source_(_Pre_valid_cap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_cap_(size) _SAL1_1_Source_(_Pre_opt_valid_cap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_impl(size)) _Pre_valid_impl_) +#define _Pre_valid_bytecap_(size) _SAL1_1_Source_(_Pre_valid_bytecap_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_bytecap_(size) _SAL1_1_Source_(_Pre_opt_valid_bytecap_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_impl(size)) _Pre_valid_impl_) + +#define _Pre_valid_cap_c_(size) _SAL1_1_Source_(_Pre_valid_cap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_cap_c_(size) _SAL1_1_Source_(_Pre_opt_valid_cap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_valid_bytecap_c_(size) _SAL1_1_Source_(_Pre_valid_bytecap_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_bytecap_c_(size) _SAL1_1_Source_(_Pre_opt_valid_bytecap_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_c_impl(size)) _Pre_valid_impl_) + +#define _Pre_valid_cap_x_(size) _SAL1_1_Source_(_Pre_valid_cap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_cap_x_(size) _SAL1_1_Source_(_Pre_opt_valid_cap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_valid_bytecap_x_(size) _SAL1_1_Source_(_Pre_valid_bytecap_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_valid_bytecap_x_(size) _SAL1_1_Source_(_Pre_opt_valid_bytecap_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecap_x_impl(size)) _Pre_valid_impl_) + +// e.g. void AppendCharRange( _Pre_count_(cchFrom) const char* rgFrom, size_t cchFrom, _Out_z_cap_(cchTo) char* szTo, size_t cchTo ); +// Valid buffer extent described by another parameter +#define _Pre_count_(size) _SAL1_1_Source_(_Pre_count_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_count_(size) _SAL1_1_Source_(_Pre_opt_count_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_impl(size)) _Pre_valid_impl_) +#define _Pre_bytecount_(size) _SAL1_1_Source_(_Pre_bytecount_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecount_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_bytecount_(size) _SAL1_1_Source_(_Pre_opt_bytecount_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecount_impl(size)) _Pre_valid_impl_) + +// Valid buffer extent described by a constant expression +#define _Pre_count_c_(size) _SAL1_1_Source_(_Pre_count_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_count_c_(size) _SAL1_1_Source_(_Pre_opt_count_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_c_impl(size)) _Pre_valid_impl_) +#define _Pre_bytecount_c_(size) _SAL1_1_Source_(_Pre_bytecount_c_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecount_c_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_bytecount_c_(size) _SAL1_1_Source_(_Pre_opt_bytecount_c_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecount_c_impl(size)) _Pre_valid_impl_) + +// Valid buffer extent described by a complex expression +#define _Pre_count_x_(size) _SAL1_1_Source_(_Pre_count_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_count_x_(size) _SAL1_1_Source_(_Pre_opt_count_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_x_impl(size)) _Pre_valid_impl_) +#define _Pre_bytecount_x_(size) _SAL1_1_Source_(_Pre_bytecount_x_, (size), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__bytecount_x_impl(size)) _Pre_valid_impl_) +#define _Pre_opt_bytecount_x_(size) _SAL1_1_Source_(_Pre_opt_bytecount_x_, (size), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__bytecount_x_impl(size)) _Pre_valid_impl_) + +// Valid buffer extent described by the difference to another pointer parameter +#define _Pre_ptrdiff_count_(ptr) _SAL1_1_Source_(_Pre_ptrdiff_count_, (ptr), _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__count_x_impl(__ptrdiff(ptr))) _Pre_valid_impl_) +#define _Pre_opt_ptrdiff_count_(ptr) _SAL1_1_Source_(_Pre_opt_ptrdiff_count_, (ptr), _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__count_x_impl(__ptrdiff(ptr))) _Pre_valid_impl_) + + +// char * strncpy(_Out_cap_(_Count) _Post_maybez_ char * _Dest, _In_z_ const char * _Source, _In_ size_t _Count) +// buffer maybe zero-terminated after the call +#define _Post_maybez_ _SAL1_1_Source_(_Post_maybez_, (), _Post1_impl_(__maybezterm_impl)) + +// e.g. SIZE_T HeapSize( _In_ HANDLE hHeap, DWORD dwFlags, _Pre_notnull_ _Post_bytecap_(return) LPCVOID lpMem ); +#define _Post_cap_(size) _SAL1_1_Source_(_Post_cap_, (size), _Post1_impl_(__cap_impl(size))) +#define _Post_bytecap_(size) _SAL1_1_Source_(_Post_bytecap_, (size), _Post1_impl_(__bytecap_impl(size))) + +// e.g. int strlen( _In_z_ _Post_count_(return+1) const char* sz ); +#define _Post_count_(size) _SAL1_1_Source_(_Post_count_, (size), _Post1_impl_(__count_impl(size)) _Post_valid_impl_) +#define _Post_bytecount_(size) _SAL1_1_Source_(_Post_bytecount_, (size), _Post1_impl_(__bytecount_impl(size)) _Post_valid_impl_) +#define _Post_count_c_(size) _SAL1_1_Source_(_Post_count_c_, (size), _Post1_impl_(__count_c_impl(size)) _Post_valid_impl_) +#define _Post_bytecount_c_(size) _SAL1_1_Source_(_Post_bytecount_c_, (size), _Post1_impl_(__bytecount_c_impl(size)) _Post_valid_impl_) +#define _Post_count_x_(size) _SAL1_1_Source_(_Post_count_x_, (size), _Post1_impl_(__count_x_impl(size)) _Post_valid_impl_) +#define _Post_bytecount_x_(size) _SAL1_1_Source_(_Post_bytecount_x_, (size), _Post1_impl_(__bytecount_x_impl(size)) _Post_valid_impl_) + +// e.g. size_t CopyStr( _In_z_ const char* szFrom, _Pre_cap_(cch) _Post_z_count_(return+1) char* szFrom, size_t cchFrom ); +#define _Post_z_count_(size) _SAL1_1_Source_(_Post_z_count_, (size), _Post2_impl_(__zterm_impl,__count_impl(size)) _Post_valid_impl_) +#define _Post_z_bytecount_(size) _SAL1_1_Source_(_Post_z_bytecount_, (size), _Post2_impl_(__zterm_impl,__bytecount_impl(size)) _Post_valid_impl_) +#define _Post_z_count_c_(size) _SAL1_1_Source_(_Post_z_count_c_, (size), _Post2_impl_(__zterm_impl,__count_c_impl(size)) _Post_valid_impl_) +#define _Post_z_bytecount_c_(size) _SAL1_1_Source_(_Post_z_bytecount_c_, (size), _Post2_impl_(__zterm_impl,__bytecount_c_impl(size)) _Post_valid_impl_) +#define _Post_z_count_x_(size) _SAL1_1_Source_(_Post_z_count_x_, (size), _Post2_impl_(__zterm_impl,__count_x_impl(size)) _Post_valid_impl_) +#define _Post_z_bytecount_x_(size) _SAL1_1_Source_(_Post_z_bytecount_x_, (size), _Post2_impl_(__zterm_impl,__bytecount_x_impl(size)) _Post_valid_impl_) + +// +// _Prepost_ --- +// +// describing conditions that hold before and after the function call + +#define _Prepost_opt_z_ _SAL1_1_Source_(_Prepost_opt_z_, (), _Pre_opt_z_ _Post_z_) + +#define _Prepost_count_(size) _SAL1_1_Source_(_Prepost_count_, (size), _Pre_count_(size) _Post_count_(size)) +#define _Prepost_opt_count_(size) _SAL1_1_Source_(_Prepost_opt_count_, (size), _Pre_opt_count_(size) _Post_count_(size)) +#define _Prepost_bytecount_(size) _SAL1_1_Source_(_Prepost_bytecount_, (size), _Pre_bytecount_(size) _Post_bytecount_(size)) +#define _Prepost_opt_bytecount_(size) _SAL1_1_Source_(_Prepost_opt_bytecount_, (size), _Pre_opt_bytecount_(size) _Post_bytecount_(size)) +#define _Prepost_count_c_(size) _SAL1_1_Source_(_Prepost_count_c_, (size), _Pre_count_c_(size) _Post_count_c_(size)) +#define _Prepost_opt_count_c_(size) _SAL1_1_Source_(_Prepost_opt_count_c_, (size), _Pre_opt_count_c_(size) _Post_count_c_(size)) +#define _Prepost_bytecount_c_(size) _SAL1_1_Source_(_Prepost_bytecount_c_, (size), _Pre_bytecount_c_(size) _Post_bytecount_c_(size)) +#define _Prepost_opt_bytecount_c_(size) _SAL1_1_Source_(_Prepost_opt_bytecount_c_, (size), _Pre_opt_bytecount_c_(size) _Post_bytecount_c_(size)) +#define _Prepost_count_x_(size) _SAL1_1_Source_(_Prepost_count_x_, (size), _Pre_count_x_(size) _Post_count_x_(size)) +#define _Prepost_opt_count_x_(size) _SAL1_1_Source_(_Prepost_opt_count_x_, (size), _Pre_opt_count_x_(size) _Post_count_x_(size)) +#define _Prepost_bytecount_x_(size) _SAL1_1_Source_(_Prepost_bytecount_x_, (size), _Pre_bytecount_x_(size) _Post_bytecount_x_(size)) +#define _Prepost_opt_bytecount_x_(size) _SAL1_1_Source_(_Prepost_opt_bytecount_x_, (size), _Pre_opt_bytecount_x_(size) _Post_bytecount_x_(size)) + +#define _Prepost_valid_ _SAL1_1_Source_(_Prepost_valid_, (), _Pre_valid_ _Post_valid_) +#define _Prepost_opt_valid_ _SAL1_1_Source_(_Prepost_opt_valid_, (), _Pre_opt_valid_ _Post_valid_) + +// +// _Deref_ --- +// +// short version for _Deref_pre_ _Deref_post_ +// describing conditions for array elements or dereferenced pointer parameters that hold before and after the call + +#define _Deref_prepost_z_ _SAL1_1_Source_(_Deref_prepost_z_, (), _Deref_pre_z_ _Deref_post_z_) +#define _Deref_prepost_opt_z_ _SAL1_1_Source_(_Deref_prepost_opt_z_, (), _Deref_pre_opt_z_ _Deref_post_opt_z_) + +#define _Deref_prepost_cap_(size) _SAL1_1_Source_(_Deref_prepost_cap_, (size), _Deref_pre_cap_(size) _Deref_post_cap_(size)) +#define _Deref_prepost_opt_cap_(size) _SAL1_1_Source_(_Deref_prepost_opt_cap_, (size), _Deref_pre_opt_cap_(size) _Deref_post_opt_cap_(size)) +#define _Deref_prepost_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_bytecap_, (size), _Deref_pre_bytecap_(size) _Deref_post_bytecap_(size)) +#define _Deref_prepost_opt_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_opt_bytecap_, (size), _Deref_pre_opt_bytecap_(size) _Deref_post_opt_bytecap_(size)) + +#define _Deref_prepost_cap_x_(size) _SAL1_1_Source_(_Deref_prepost_cap_x_, (size), _Deref_pre_cap_x_(size) _Deref_post_cap_x_(size)) +#define _Deref_prepost_opt_cap_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_cap_x_, (size), _Deref_pre_opt_cap_x_(size) _Deref_post_opt_cap_x_(size)) +#define _Deref_prepost_bytecap_x_(size) _SAL1_1_Source_(_Deref_prepost_bytecap_x_, (size), _Deref_pre_bytecap_x_(size) _Deref_post_bytecap_x_(size)) +#define _Deref_prepost_opt_bytecap_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_bytecap_x_, (size), _Deref_pre_opt_bytecap_x_(size) _Deref_post_opt_bytecap_x_(size)) + +#define _Deref_prepost_z_cap_(size) _SAL1_1_Source_(_Deref_prepost_z_cap_, (size), _Deref_pre_z_cap_(size) _Deref_post_z_cap_(size)) +#define _Deref_prepost_opt_z_cap_(size) _SAL1_1_Source_(_Deref_prepost_opt_z_cap_, (size), _Deref_pre_opt_z_cap_(size) _Deref_post_opt_z_cap_(size)) +#define _Deref_prepost_z_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_z_bytecap_, (size), _Deref_pre_z_bytecap_(size) _Deref_post_z_bytecap_(size)) +#define _Deref_prepost_opt_z_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_opt_z_bytecap_, (size), _Deref_pre_opt_z_bytecap_(size) _Deref_post_opt_z_bytecap_(size)) + +#define _Deref_prepost_valid_cap_(size) _SAL1_1_Source_(_Deref_prepost_valid_cap_, (size), _Deref_pre_valid_cap_(size) _Deref_post_valid_cap_(size)) +#define _Deref_prepost_opt_valid_cap_(size) _SAL1_1_Source_(_Deref_prepost_opt_valid_cap_, (size), _Deref_pre_opt_valid_cap_(size) _Deref_post_opt_valid_cap_(size)) +#define _Deref_prepost_valid_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_valid_bytecap_, (size), _Deref_pre_valid_bytecap_(size) _Deref_post_valid_bytecap_(size)) +#define _Deref_prepost_opt_valid_bytecap_(size) _SAL1_1_Source_(_Deref_prepost_opt_valid_bytecap_, (size), _Deref_pre_opt_valid_bytecap_(size) _Deref_post_opt_valid_bytecap_(size)) + +#define _Deref_prepost_valid_cap_x_(size) _SAL1_1_Source_(_Deref_prepost_valid_cap_x_, (size), _Deref_pre_valid_cap_x_(size) _Deref_post_valid_cap_x_(size)) +#define _Deref_prepost_opt_valid_cap_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_valid_cap_x_, (size), _Deref_pre_opt_valid_cap_x_(size) _Deref_post_opt_valid_cap_x_(size)) +#define _Deref_prepost_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_prepost_valid_bytecap_x_, (size), _Deref_pre_valid_bytecap_x_(size) _Deref_post_valid_bytecap_x_(size)) +#define _Deref_prepost_opt_valid_bytecap_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_valid_bytecap_x_, (size), _Deref_pre_opt_valid_bytecap_x_(size) _Deref_post_opt_valid_bytecap_x_(size)) + +#define _Deref_prepost_count_(size) _SAL1_1_Source_(_Deref_prepost_count_, (size), _Deref_pre_count_(size) _Deref_post_count_(size)) +#define _Deref_prepost_opt_count_(size) _SAL1_1_Source_(_Deref_prepost_opt_count_, (size), _Deref_pre_opt_count_(size) _Deref_post_opt_count_(size)) +#define _Deref_prepost_bytecount_(size) _SAL1_1_Source_(_Deref_prepost_bytecount_, (size), _Deref_pre_bytecount_(size) _Deref_post_bytecount_(size)) +#define _Deref_prepost_opt_bytecount_(size) _SAL1_1_Source_(_Deref_prepost_opt_bytecount_, (size), _Deref_pre_opt_bytecount_(size) _Deref_post_opt_bytecount_(size)) + +#define _Deref_prepost_count_x_(size) _SAL1_1_Source_(_Deref_prepost_count_x_, (size), _Deref_pre_count_x_(size) _Deref_post_count_x_(size)) +#define _Deref_prepost_opt_count_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_count_x_, (size), _Deref_pre_opt_count_x_(size) _Deref_post_opt_count_x_(size)) +#define _Deref_prepost_bytecount_x_(size) _SAL1_1_Source_(_Deref_prepost_bytecount_x_, (size), _Deref_pre_bytecount_x_(size) _Deref_post_bytecount_x_(size)) +#define _Deref_prepost_opt_bytecount_x_(size) _SAL1_1_Source_(_Deref_prepost_opt_bytecount_x_, (size), _Deref_pre_opt_bytecount_x_(size) _Deref_post_opt_bytecount_x_(size)) + +#define _Deref_prepost_valid_ _SAL1_1_Source_(_Deref_prepost_valid_, (), _Deref_pre_valid_ _Deref_post_valid_) +#define _Deref_prepost_opt_valid_ _SAL1_1_Source_(_Deref_prepost_opt_valid_, (), _Deref_pre_opt_valid_ _Deref_post_opt_valid_) + +// +// _Deref_ +// +// used with references to arrays + +#define _Deref_out_z_cap_c_(size) _SAL1_1_Source_(_Deref_out_z_cap_c_, (size), _Deref_pre_cap_c_(size) _Deref_post_z_) +#define _Deref_inout_z_cap_c_(size) _SAL1_1_Source_(_Deref_inout_z_cap_c_, (size), _Deref_pre_z_cap_c_(size) _Deref_post_z_) +#define _Deref_out_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_out_z_bytecap_c_, (size), _Deref_pre_bytecap_c_(size) _Deref_post_z_) +#define _Deref_inout_z_bytecap_c_(size) _SAL1_1_Source_(_Deref_inout_z_bytecap_c_, (size), _Deref_pre_z_bytecap_c_(size) _Deref_post_z_) +#define _Deref_inout_z_ _SAL1_1_Source_(_Deref_inout_z_, (), _Deref_prepost_z_) + +// #pragma endregion Input Buffer SAL 1 compatibility macros + + +//============================================================================ +// Implementation Layer: +//============================================================================ + + +// Naming conventions: +// A symbol the begins with _SA_ is for the machinery of creating any +// annotations; many of those come from sourceannotations.h in the case +// of attributes. + +// A symbol that ends with _impl is the very lowest level macro. It is +// not required to be a legal standalone annotation, and in the case +// of attribute annotations, usually is not. (In the case of some declspec +// annotations, it might be, but it should not be assumed so.) Those +// symols will be used in the _PreN..., _PostN... and _RetN... annotations +// to build up more complete annotations. + +// A symbol ending in _impl_ is reserved to the implementation as well, +// but it does form a complete annotation; usually they are used to build +// up even higher level annotations. + + +#if _USE_ATTRIBUTES_FOR_SAL || _USE_DECLSPECS_FOR_SAL // [ +// Sharable "_impl" macros: these can be shared between the various annotation +// forms but are part of the implementation of the macros. These are collected +// here to assure that only necessary differences in the annotations +// exist. + +#define _Always_impl_(annos) _Group_(annos _SAL_nop_impl_) _On_failure_impl_(annos _SAL_nop_impl_) +#define _Bound_impl_ _SA_annotes0(SAL_bound) +#define _Field_range_impl_(min,max) _Range_impl_(min,max) +#define _Literal_impl_ _SA_annotes1(SAL_constant, __yes) +#define _Maybenull_impl_ _SA_annotes1(SAL_null, __maybe) +#define _Maybevalid_impl_ _SA_annotes1(SAL_valid, __maybe) +#define _Must_inspect_impl_ _Post_impl_ _SA_annotes0(SAL_mustInspect) +#define _Notliteral_impl_ _SA_annotes1(SAL_constant, __no) +#define _Notnull_impl_ _SA_annotes1(SAL_null, __no) +#define _Notvalid_impl_ _SA_annotes1(SAL_valid, __no) +#define _NullNull_terminated_impl_ _Group_(_SA_annotes1(SAL_nullTerminated, __yes) _SA_annotes1(SAL_readableTo,inexpressibleCount("NullNull terminated string"))) +#define _Null_impl_ _SA_annotes1(SAL_null, __yes) +#define _Null_terminated_impl_ _SA_annotes1(SAL_nullTerminated, __yes) +#define _Out_impl_ _Pre1_impl_(__notnull_impl_notref) _Pre1_impl_(__cap_c_one_notref_impl) _Post_valid_impl_ +#define _Out_opt_impl_ _Pre1_impl_(__maybenull_impl_notref) _Pre1_impl_(__cap_c_one_notref_impl) _Post_valid_impl_ +#define _Points_to_data_impl_ _At_(*_Curr_, _SA_annotes1(SAL_mayBePointer, __no)) +#define _Post_satisfies_impl_(cond) _Post_impl_ _Satisfies_impl_(cond) +#define _Post_valid_impl_ _Post1_impl_(__valid_impl) +#define _Pre_satisfies_impl_(cond) _Pre_impl_ _Satisfies_impl_(cond) +#define _Pre_valid_impl_ _Pre1_impl_(__valid_impl) +#define _Range_impl_(min,max) _SA_annotes2(SAL_range, min, max) +#define _Readable_bytes_impl_(size) _SA_annotes1(SAL_readableTo, byteCount(size)) +#define _Readable_elements_impl_(size) _SA_annotes1(SAL_readableTo, elementCount(size)) +#define _Ret_valid_impl_ _Ret1_impl_(__valid_impl) +#define _Satisfies_impl_(cond) _SA_annotes1(SAL_satisfies, cond) +#define _Valid_impl_ _SA_annotes1(SAL_valid, __yes) +#define _Writable_bytes_impl_(size) _SA_annotes1(SAL_writableTo, byteCount(size)) +#define _Writable_elements_impl_(size) _SA_annotes1(SAL_writableTo, elementCount(size)) + +#define _In_range_impl_(min,max) _Pre_impl_ _Range_impl_(min,max) +#define _Out_range_impl_(min,max) _Post_impl_ _Range_impl_(min,max) +#define _Ret_range_impl_(min,max) _Post_impl_ _Range_impl_(min,max) +#define _Deref_in_range_impl_(min,max) _Deref_pre_impl_ _Range_impl_(min,max) +#define _Deref_out_range_impl_(min,max) _Deref_post_impl_ _Range_impl_(min,max) +#define _Deref_ret_range_impl_(min,max) _Deref_post_impl_ _Range_impl_(min,max) + +#define _Deref_pre_impl_ _Pre_impl_ _Notref_impl_ _Deref_impl_ +#define _Deref_post_impl_ _Post_impl_ _Notref_impl_ _Deref_impl_ + +// The following are for the implementation machinery, and are not +// suitable for annotating general code. +// We're tying to phase this out, someday. The parser quotes the param. +#define __AuToQuOtE _SA_annotes0(SAL_AuToQuOtE) + +// Normally the parser does some simple type checking of annotation params, +// defer that check to the plugin. +#define __deferTypecheck _SA_annotes0(SAL_deferTypecheck) + +#define _SA_SPECSTRIZE( x ) #x +#define _SAL_nop_impl_ /* nothing */ +#define __nop_impl(x) x +#endif + + +#if _USE_ATTRIBUTES_FOR_SAL // [ + +// Using attributes for sal + +#include "codeanalysis\sourceannotations.h" + + +#define _SA_annotes0(n) [SAL_annotes(Name=#n)] +#define _SA_annotes1(n,pp1) [SAL_annotes(Name=#n, p1=_SA_SPECSTRIZE(pp1))] +#define _SA_annotes2(n,pp1,pp2) [SAL_annotes(Name=#n, p1=_SA_SPECSTRIZE(pp1), p2=_SA_SPECSTRIZE(pp2))] +#define _SA_annotes3(n,pp1,pp2,pp3) [SAL_annotes(Name=#n, p1=_SA_SPECSTRIZE(pp1), p2=_SA_SPECSTRIZE(pp2), p3=_SA_SPECSTRIZE(pp3))] + +#define _Pre_impl_ [SAL_pre] +#define _Post_impl_ [SAL_post] +#define _Deref_impl_ [SAL_deref] +#define _Notref_impl_ [SAL_notref] + + +// Declare a function to be an annotation or primop (respectively). +// Done this way so that they don't appear in the regular compiler's +// namespace. +#define __ANNOTATION(fun) _SA_annotes0(SAL_annotation) void __SA_##fun; +#define __PRIMOP(type, fun) _SA_annotes0(SAL_primop) type __SA_##fun; +#define __QUALIFIER(fun) _SA_annotes0(SAL_qualifier) void __SA_##fun; + +// Benign declspec needed here for WindowsPREfast +#define __In_impl_ [SA_Pre(Valid=SA_Yes)] [SA_Pre(Deref=1, Notref=1, Access=SA_Read)] __declspec("SAL_pre SAL_valid") + +#elif _USE_DECLSPECS_FOR_SAL // ][ + +// Using declspecs for sal + +#define _SA_annotes0(n) __declspec(#n) +#define _SA_annotes1(n,pp1) __declspec(#n "(" _SA_SPECSTRIZE(pp1) ")" ) +#define _SA_annotes2(n,pp1,pp2) __declspec(#n "(" _SA_SPECSTRIZE(pp1) "," _SA_SPECSTRIZE(pp2) ")") +#define _SA_annotes3(n,pp1,pp2,pp3) __declspec(#n "(" _SA_SPECSTRIZE(pp1) "," _SA_SPECSTRIZE(pp2) "," _SA_SPECSTRIZE(pp3) ")") + +#define _Pre_impl_ _SA_annotes0(SAL_pre) +#define _Post_impl_ _SA_annotes0(SAL_post) +#define _Deref_impl_ _SA_annotes0(SAL_deref) +#define _Notref_impl_ _SA_annotes0(SAL_notref) + +// Declare a function to be an annotation or primop (respectively). +// Done this way so that they don't appear in the regular compiler's +// namespace. +#define __ANNOTATION(fun) _SA_annotes0(SAL_annotation) void __SA_##fun + +#define __PRIMOP(type, fun) _SA_annotes0(SAL_primop) type __SA_##fun + +#define __QUALIFIER(fun) _SA_annotes0(SAL_qualifier) void __SA_##fun; + +#define __In_impl_ _Pre_impl_ _SA_annotes0(SAL_valid) _Pre_impl_ _Deref_impl_ _Notref_impl_ _SA_annotes0(SAL_readonly) + +#else // ][ + +// Using "nothing" for sal + +#define _SA_annotes0(n) +#define _SA_annotes1(n,pp1) +#define _SA_annotes2(n,pp1,pp2) +#define _SA_annotes3(n,pp1,pp2,pp3) + +#define __ANNOTATION(fun) +#define __PRIMOP(type, fun) +#define __QUALIFIER(type, fun) + +#endif // ] + +#if _USE_ATTRIBUTES_FOR_SAL || _USE_DECLSPECS_FOR_SAL // [ + +// Declare annotations that need to be declared. +__ANNOTATION(SAL_useHeader(void)); +__ANNOTATION(SAL_bound(void)); +__ANNOTATION(SAL_allocator(void)); //??? resolve with PFD +__ANNOTATION(SAL_file_parser(__AuToQuOtE __In_impl_ char *, __In_impl_ char *)); +__ANNOTATION(SAL_source_code_content(__In_impl_ char *)); +__ANNOTATION(SAL_analysisHint(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_untrusted_data_source(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_untrusted_data_source_this(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_validated(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_validated_this(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_encoded(void)); +__ANNOTATION(SAL_adt(__AuToQuOtE __In_impl_ char *, __AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_add_adt_property(__AuToQuOtE __In_impl_ char *, __AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_remove_adt_property(__AuToQuOtE __In_impl_ char *, __AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_transfer_adt_property_from(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_post_type(__AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_volatile(void)); +__ANNOTATION(SAL_nonvolatile(void)); +__ANNOTATION(SAL_entrypoint(__AuToQuOtE __In_impl_ char *, __AuToQuOtE __In_impl_ char *)); +__ANNOTATION(SAL_blocksOn(__In_impl_ void*)); +__ANNOTATION(SAL_mustInspect(void)); + +// Only appears in model files, but needs to be declared. +__ANNOTATION(SAL_TypeName(__AuToQuOtE __In_impl_ char *)); + +// To be declared well-known soon. +__ANNOTATION(SAL_interlocked(void);) + +#pragma warning (suppress: 28227 28241) +__ANNOTATION(SAL_name(__In_impl_ char *, __In_impl_ char *, __In_impl_ char *);) + +__PRIMOP(char *, _Macro_value_(__In_impl_ char *)); +__PRIMOP(int, _Macro_defined_(__In_impl_ char *)); +__PRIMOP(char *, _Strstr_(__In_impl_ char *, __In_impl_ char *)); + +#endif // ] + +#if _USE_ATTRIBUTES_FOR_SAL // [ + +#define _Check_return_impl_ [SA_Post(MustCheck=SA_Yes)] + +#define _Success_impl_(expr) [SA_Success(Condition=#expr)] +#define _On_failure_impl_(annos) [SAL_context(p1="SAL_failed")] _Group_(_Post_impl_ _Group_(annos _SAL_nop_impl_)) + +#define _Printf_format_string_impl_ [SA_FormatString(Style="printf")] +#define _Scanf_format_string_impl_ [SA_FormatString(Style="scanf")] +#define _Scanf_s_format_string_impl_ [SA_FormatString(Style="scanf_s")] + +#define _In_bound_impl_ [SA_PreBound(Deref=0)] +#define _Out_bound_impl_ [SA_PostBound(Deref=0)] +#define _Ret_bound_impl_ [SA_PostBound(Deref=0)] +#define _Deref_in_bound_impl_ [SA_PreBound(Deref=1)] +#define _Deref_out_bound_impl_ [SA_PostBound(Deref=1)] +#define _Deref_ret_bound_impl_ [SA_PostBound(Deref=1)] + +#define __valid_impl Valid=SA_Yes +#define __maybevalid_impl Valid=SA_Maybe +#define __notvalid_impl Valid=SA_No + +#define __null_impl Null=SA_Yes +#define __maybenull_impl Null=SA_Maybe +#define __notnull_impl Null=SA_No + +#define __null_impl_notref Null=SA_Yes,Notref=1 +#define __maybenull_impl_notref Null=SA_Maybe,Notref=1 +#define __notnull_impl_notref Null=SA_No,Notref=1 + +#define __zterm_impl NullTerminated=SA_Yes +#define __maybezterm_impl NullTerminated=SA_Maybe +#define __maybzterm_impl NullTerminated=SA_Maybe +#define __notzterm_impl NullTerminated=SA_No + +#define __readaccess_impl Access=SA_Read +#define __writeaccess_impl Access=SA_Write +#define __allaccess_impl Access=SA_ReadWrite + +#define __readaccess_impl_notref Access=SA_Read,Notref=1 +#define __writeaccess_impl_notref Access=SA_Write,Notref=1 +#define __allaccess_impl_notref Access=SA_ReadWrite,Notref=1 + +#if _MSC_VER >= 1610 /*IFSTRIP=IGN*/ // [ + +// For SAL2, we need to expect general expressions. + +#define __cap_impl(size) WritableElements="\n"#size +#define __bytecap_impl(size) WritableBytes="\n"#size +#define __bytecount_impl(size) ValidBytes="\n"#size +#define __count_impl(size) ValidElements="\n"#size + +#else // ][ + +#define __cap_impl(size) WritableElements=#size +#define __bytecap_impl(size) WritableBytes=#size +#define __bytecount_impl(size) ValidBytes=#size +#define __count_impl(size) ValidElements=#size + +#endif // ] + +#define __cap_c_impl(size) WritableElementsConst=size +#define __cap_c_one_notref_impl WritableElementsConst=1,Notref=1 +#define __cap_for_impl(param) WritableElementsLength=#param +#define __cap_x_impl(size) WritableElements="\n@"#size + +#define __bytecap_c_impl(size) WritableBytesConst=size +#define __bytecap_x_impl(size) WritableBytes="\n@"#size + +#define __mult_impl(mult,size) __cap_impl((mult)*(size)) + +#define __count_c_impl(size) ValidElementsConst=size +#define __count_x_impl(size) ValidElements="\n@"#size + +#define __bytecount_c_impl(size) ValidBytesConst=size +#define __bytecount_x_impl(size) ValidBytes="\n@"#size + + +#define _At_impl_(target, annos) [SAL_at(p1=#target)] _Group_(annos) +#define _At_buffer_impl_(target, iter, bound, annos) [SAL_at_buffer(p1=#target, p2=#iter, p3=#bound)] _Group_(annos) +#define _When_impl_(expr, annos) [SAL_when(p1=#expr)] _Group_(annos) + +#define _Group_impl_(annos) [SAL_begin] annos [SAL_end] +#define _GrouP_impl_(annos) [SAL_BEGIN] annos [SAL_END] + +#define _Use_decl_anno_impl_ _SA_annotes0(SAL_useHeader) // this is a special case! + +#define _Pre1_impl_(p1) [SA_Pre(p1)] +#define _Pre2_impl_(p1,p2) [SA_Pre(p1,p2)] +#define _Pre3_impl_(p1,p2,p3) [SA_Pre(p1,p2,p3)] + +#define _Post1_impl_(p1) [SA_Post(p1)] +#define _Post2_impl_(p1,p2) [SA_Post(p1,p2)] +#define _Post3_impl_(p1,p2,p3) [SA_Post(p1,p2,p3)] + +#define _Ret1_impl_(p1) [SA_Post(p1)] +#define _Ret2_impl_(p1,p2) [SA_Post(p1,p2)] +#define _Ret3_impl_(p1,p2,p3) [SA_Post(p1,p2,p3)] + +#define _Deref_pre1_impl_(p1) [SA_Pre(Deref=1,p1)] +#define _Deref_pre2_impl_(p1,p2) [SA_Pre(Deref=1,p1,p2)] +#define _Deref_pre3_impl_(p1,p2,p3) [SA_Pre(Deref=1,p1,p2,p3)] + + +#define _Deref_post1_impl_(p1) [SA_Post(Deref=1,p1)] +#define _Deref_post2_impl_(p1,p2) [SA_Post(Deref=1,p1,p2)] +#define _Deref_post3_impl_(p1,p2,p3) [SA_Post(Deref=1,p1,p2,p3)] + +#define _Deref_ret1_impl_(p1) [SA_Post(Deref=1,p1)] +#define _Deref_ret2_impl_(p1,p2) [SA_Post(Deref=1,p1,p2)] +#define _Deref_ret3_impl_(p1,p2,p3) [SA_Post(Deref=1,p1,p2,p3)] + +#define _Deref2_pre1_impl_(p1) [SA_Pre(Deref=2,Notref=1,p1)] +#define _Deref2_post1_impl_(p1) [SA_Post(Deref=2,Notref=1,p1)] +#define _Deref2_ret1_impl_(p1) [SA_Post(Deref=2,Notref=1,p1)] + +// Obsolete -- may be needed for transition to attributes. +#define __inner_typefix(ctype) [SAL_typefix(p1=_SA_SPECSTRIZE(ctype))] +#define __inner_exceptthat [SAL_except] + + +#elif _USE_DECLSPECS_FOR_SAL // ][ + +#define _Check_return_impl_ __post _SA_annotes0(SAL_checkReturn) + +#define _Success_impl_(expr) _SA_annotes1(SAL_success, expr) +#define _On_failure_impl_(annos) _SA_annotes1(SAL_context, SAL_failed) _Group_(_Post_impl_ _Group_(_SAL_nop_impl_ annos)) + +#define _Printf_format_string_impl_ _SA_annotes1(SAL_IsFormatString, "printf") +#define _Scanf_format_string_impl_ _SA_annotes1(SAL_IsFormatString, "scanf") +#define _Scanf_s_format_string_impl_ _SA_annotes1(SAL_IsFormatString, "scanf_s") + +#define _In_bound_impl_ _Pre_impl_ _Bound_impl_ +#define _Out_bound_impl_ _Post_impl_ _Bound_impl_ +#define _Ret_bound_impl_ _Post_impl_ _Bound_impl_ +#define _Deref_in_bound_impl_ _Deref_pre_impl_ _Bound_impl_ +#define _Deref_out_bound_impl_ _Deref_post_impl_ _Bound_impl_ +#define _Deref_ret_bound_impl_ _Deref_post_impl_ _Bound_impl_ + + +#define __null_impl _SA_annotes0(SAL_null) // _SA_annotes1(SAL_null, __yes) +#define __notnull_impl _SA_annotes0(SAL_notnull) // _SA_annotes1(SAL_null, __no) +#define __maybenull_impl _SA_annotes0(SAL_maybenull) // _SA_annotes1(SAL_null, __maybe) + +#define __valid_impl _SA_annotes0(SAL_valid) // _SA_annotes1(SAL_valid, __yes) +#define __notvalid_impl _SA_annotes0(SAL_notvalid) // _SA_annotes1(SAL_valid, __no) +#define __maybevalid_impl _SA_annotes0(SAL_maybevalid) // _SA_annotes1(SAL_valid, __maybe) + +#define __null_impl_notref _Notref_ _Null_impl_ +#define __maybenull_impl_notref _Notref_ _Maybenull_impl_ +#define __notnull_impl_notref _Notref_ _Notnull_impl_ + +#define __zterm_impl _SA_annotes1(SAL_nullTerminated, __yes) +#define __maybezterm_impl _SA_annotes1(SAL_nullTerminated, __maybe) +#define __maybzterm_impl _SA_annotes1(SAL_nullTerminated, __maybe) +#define __notzterm_impl _SA_annotes1(SAL_nullTerminated, __no) + +#define __readaccess_impl _SA_annotes1(SAL_access, 0x1) +#define __writeaccess_impl _SA_annotes1(SAL_access, 0x2) +#define __allaccess_impl _SA_annotes1(SAL_access, 0x3) + +#define __readaccess_impl_notref _Notref_ _SA_annotes1(SAL_access, 0x1) +#define __writeaccess_impl_notref _Notref_ _SA_annotes1(SAL_access, 0x2) +#define __allaccess_impl_notref _Notref_ _SA_annotes1(SAL_access, 0x3) + +#define __cap_impl(size) _SA_annotes1(SAL_writableTo,elementCount(size)) +#define __cap_c_impl(size) _SA_annotes1(SAL_writableTo,elementCount(size)) +#define __cap_c_one_notref_impl _Notref_ _SA_annotes1(SAL_writableTo,elementCount(1)) +#define __cap_for_impl(param) _SA_annotes1(SAL_writableTo,inexpressibleCount(sizeof(param))) +#define __cap_x_impl(size) _SA_annotes1(SAL_writableTo,inexpressibleCount(#size)) + +#define __bytecap_impl(size) _SA_annotes1(SAL_writableTo,byteCount(size)) +#define __bytecap_c_impl(size) _SA_annotes1(SAL_writableTo,byteCount(size)) +#define __bytecap_x_impl(size) _SA_annotes1(SAL_writableTo,inexpressibleCount(#size)) + +#define __mult_impl(mult,size) _SA_annotes1(SAL_writableTo,(mult)*(size)) + +#define __count_impl(size) _SA_annotes1(SAL_readableTo,elementCount(size)) +#define __count_c_impl(size) _SA_annotes1(SAL_readableTo,elementCount(size)) +#define __count_x_impl(size) _SA_annotes1(SAL_readableTo,inexpressibleCount(#size)) + +#define __bytecount_impl(size) _SA_annotes1(SAL_readableTo,byteCount(size)) +#define __bytecount_c_impl(size) _SA_annotes1(SAL_readableTo,byteCount(size)) +#define __bytecount_x_impl(size) _SA_annotes1(SAL_readableTo,inexpressibleCount(#size)) + +#define _At_impl_(target, annos) _SA_annotes0(SAL_at(target)) _Group_(annos) +#define _At_buffer_impl_(target, iter, bound, annos) _SA_annotes3(SAL_at_buffer, target, iter, bound) _Group_(annos) +#define _Group_impl_(annos) _SA_annotes0(SAL_begin) annos _SA_annotes0(SAL_end) +#define _GrouP_impl_(annos) _SA_annotes0(SAL_BEGIN) annos _SA_annotes0(SAL_END) +#define _When_impl_(expr, annos) _SA_annotes0(SAL_when(expr)) _Group_(annos) + +#define _Use_decl_anno_impl_ __declspec("SAL_useHeader()") // this is a special case! + +#define _Pre1_impl_(p1) _Pre_impl_ p1 +#define _Pre2_impl_(p1,p2) _Pre_impl_ p1 _Pre_impl_ p2 +#define _Pre3_impl_(p1,p2,p3) _Pre_impl_ p1 _Pre_impl_ p2 _Pre_impl_ p3 + +#define _Post1_impl_(p1) _Post_impl_ p1 +#define _Post2_impl_(p1,p2) _Post_impl_ p1 _Post_impl_ p2 +#define _Post3_impl_(p1,p2,p3) _Post_impl_ p1 _Post_impl_ p2 _Post_impl_ p3 + +#define _Ret1_impl_(p1) _Post_impl_ p1 +#define _Ret2_impl_(p1,p2) _Post_impl_ p1 _Post_impl_ p2 +#define _Ret3_impl_(p1,p2,p3) _Post_impl_ p1 _Post_impl_ p2 _Post_impl_ p3 + +#define _Deref_pre1_impl_(p1) _Deref_pre_impl_ p1 +#define _Deref_pre2_impl_(p1,p2) _Deref_pre_impl_ p1 _Deref_pre_impl_ p2 +#define _Deref_pre3_impl_(p1,p2,p3) _Deref_pre_impl_ p1 _Deref_pre_impl_ p2 _Deref_pre_impl_ p3 + +#define _Deref_post1_impl_(p1) _Deref_post_impl_ p1 +#define _Deref_post2_impl_(p1,p2) _Deref_post_impl_ p1 _Deref_post_impl_ p2 +#define _Deref_post3_impl_(p1,p2,p3) _Deref_post_impl_ p1 _Deref_post_impl_ p2 _Deref_post_impl_ p3 + +#define _Deref_ret1_impl_(p1) _Deref_post_impl_ p1 +#define _Deref_ret2_impl_(p1,p2) _Deref_post_impl_ p1 _Deref_post_impl_ p2 +#define _Deref_ret3_impl_(p1,p2,p3) _Deref_post_impl_ p1 _Deref_post_impl_ p2 _Deref_post_impl_ p3 + +#define _Deref2_pre1_impl_(p1) _Deref_pre_impl_ _Notref_impl_ _Deref_impl_ p1 +#define _Deref2_post1_impl_(p1) _Deref_post_impl_ _Notref_impl_ _Deref_impl_ p1 +#define _Deref2_ret1_impl_(p1) _Deref_post_impl_ _Notref_impl_ _Deref_impl_ p1 + +#define __inner_typefix(ctype) _SA_annotes1(SAL_typefix, ctype) +#define __inner_exceptthat _SA_annotes0(SAL_except) + +#elif defined(_MSC_EXTENSIONS) && !defined( MIDL_PASS ) && !defined(__midl) && !defined(RC_INVOKED) && defined(_PFT_VER) && _MSC_VER >= 1400 /*IFSTRIP=IGN*/ // ][ + +// minimum attribute expansion for foreground build + +#pragma push_macro( "SA" ) +#pragma push_macro( "REPEATABLE" ) + +#ifdef __cplusplus // [ +#define SA( id ) id +#define REPEATABLE [repeatable] +#else // !__cplusplus // ][ +#define SA( id ) SA_##id +#define REPEATABLE +#endif // !__cplusplus // ] + +REPEATABLE +[source_annotation_attribute( SA( Parameter ) )] +struct __P_impl +{ +#ifdef __cplusplus // [ + __P_impl(); +#endif // ] + int __d_; +}; +typedef struct __P_impl __P_impl; + +REPEATABLE +[source_annotation_attribute( SA( ReturnValue ) )] +struct __R_impl +{ +#ifdef __cplusplus // [ + __R_impl(); +#endif // ] + int __d_; +}; +typedef struct __R_impl __R_impl; + +[source_annotation_attribute( SA( Method ) )] +struct __M_ +{ +#ifdef __cplusplus // [ + __M_(); +#endif // ] + int __d_; +}; +typedef struct __M_ __M_; + +[source_annotation_attribute( SA( All ) )] +struct __A_ +{ +#ifdef __cplusplus // [ + __A_(); +#endif // ] + int __d_; +}; +typedef struct __A_ __A_; + +[source_annotation_attribute( SA( Field ) )] +struct __F_ +{ +#ifdef __cplusplus // [ + __F_(); +#endif // ] + int __d_; +}; +typedef struct __F_ __F_; + +#pragma pop_macro( "REPEATABLE" ) +#pragma pop_macro( "SA" ) + + +#define _SAL_nop_impl_ + +#define _At_impl_(target, annos) [__A_(__d_=0)] +#define _At_buffer_impl_(target, iter, bound, annos) [__A_(__d_=0)] +#define _When_impl_(expr, annos) annos +#define _Group_impl_(annos) annos +#define _GrouP_impl_(annos) annos +#define _Use_decl_anno_impl_ [__M_(__d_=0)] + +#define _Points_to_data_impl_ [__P_impl(__d_=0)] +#define _Literal_impl_ [__P_impl(__d_=0)] +#define _Notliteral_impl_ [__P_impl(__d_=0)] + +#define _Pre_valid_impl_ [__P_impl(__d_=0)] +#define _Post_valid_impl_ [__P_impl(__d_=0)] +#define _Ret_valid_impl_ [__R_impl(__d_=0)] + +#define _Check_return_impl_ [__R_impl(__d_=0)] +#define _Must_inspect_impl_ [__R_impl(__d_=0)] + +#define _Success_impl_(expr) [__M_(__d_=0)] +#define _On_failure_impl_(expr) [__M_(__d_=0)] +#define _Always_impl_(expr) [__M_(__d_=0)] + +#define _Printf_format_string_impl_ [__P_impl(__d_=0)] +#define _Scanf_format_string_impl_ [__P_impl(__d_=0)] +#define _Scanf_s_format_string_impl_ [__P_impl(__d_=0)] + +#define _Raises_SEH_exception_impl_ [__M_(__d_=0)] +#define _Maybe_raises_SEH_exception_impl_ [__M_(__d_=0)] + +#define _In_bound_impl_ [__P_impl(__d_=0)] +#define _Out_bound_impl_ [__P_impl(__d_=0)] +#define _Ret_bound_impl_ [__R_impl(__d_=0)] +#define _Deref_in_bound_impl_ [__P_impl(__d_=0)] +#define _Deref_out_bound_impl_ [__P_impl(__d_=0)] +#define _Deref_ret_bound_impl_ [__R_impl(__d_=0)] + +#define _Range_impl_(min,max) [__P_impl(__d_=0)] +#define _In_range_impl_(min,max) [__P_impl(__d_=0)] +#define _Out_range_impl_(min,max) [__P_impl(__d_=0)] +#define _Ret_range_impl_(min,max) [__R_impl(__d_=0)] +#define _Deref_in_range_impl_(min,max) [__P_impl(__d_=0)] +#define _Deref_out_range_impl_(min,max) [__P_impl(__d_=0)] +#define _Deref_ret_range_impl_(min,max) [__R_impl(__d_=0)] + +#define _Field_range_impl_(min,max) [__F_(__d_=0)] + +#define _Pre_satisfies_impl_(cond) [__A_(__d_=0)] +#define _Post_satisfies_impl_(cond) [__A_(__d_=0)] +#define _Satisfies_impl_(cond) [__A_(__d_=0)] + +#define _Null_impl_ [__A_(__d_=0)] +#define _Notnull_impl_ [__A_(__d_=0)] +#define _Maybenull_impl_ [__A_(__d_=0)] + +#define _Valid_impl_ [__A_(__d_=0)] +#define _Notvalid_impl_ [__A_(__d_=0)] +#define _Maybevalid_impl_ [__A_(__d_=0)] + +#define _Readable_bytes_impl_(size) [__A_(__d_=0)] +#define _Readable_elements_impl_(size) [__A_(__d_=0)] +#define _Writable_bytes_impl_(size) [__A_(__d_=0)] +#define _Writable_elements_impl_(size) [__A_(__d_=0)] + +#define _Null_terminated_impl_ [__A_(__d_=0)] +#define _NullNull_terminated_impl_ [__A_(__d_=0)] + +#define _Pre_impl_ [__P_impl(__d_=0)] +#define _Pre1_impl_(p1) [__P_impl(__d_=0)] +#define _Pre2_impl_(p1,p2) [__P_impl(__d_=0)] +#define _Pre3_impl_(p1,p2,p3) [__P_impl(__d_=0)] + +#define _Post_impl_ [__P_impl(__d_=0)] +#define _Post1_impl_(p1) [__P_impl(__d_=0)] +#define _Post2_impl_(p1,p2) [__P_impl(__d_=0)] +#define _Post3_impl_(p1,p2,p3) [__P_impl(__d_=0)] + +#define _Ret1_impl_(p1) [__R_impl(__d_=0)] +#define _Ret2_impl_(p1,p2) [__R_impl(__d_=0)] +#define _Ret3_impl_(p1,p2,p3) [__R_impl(__d_=0)] + +#define _Deref_pre1_impl_(p1) [__P_impl(__d_=0)] +#define _Deref_pre2_impl_(p1,p2) [__P_impl(__d_=0)] +#define _Deref_pre3_impl_(p1,p2,p3) [__P_impl(__d_=0)] + +#define _Deref_post1_impl_(p1) [__P_impl(__d_=0)] +#define _Deref_post2_impl_(p1,p2) [__P_impl(__d_=0)] +#define _Deref_post3_impl_(p1,p2,p3) [__P_impl(__d_=0)] + +#define _Deref_ret1_impl_(p1) [__R_impl(__d_=0)] +#define _Deref_ret2_impl_(p1,p2) [__R_impl(__d_=0)] +#define _Deref_ret3_impl_(p1,p2,p3) [__R_impl(__d_=0)] + +#define _Deref2_pre1_impl_(p1) //[__P_impl(__d_=0)] +#define _Deref2_post1_impl_(p1) //[__P_impl(__d_=0)] +#define _Deref2_ret1_impl_(p1) //[__P_impl(__d_=0)] + +#else // ][ + + +#define _SAL_nop_impl_ X + +#define _At_impl_(target, annos) +#define _When_impl_(expr, annos) +#define _Group_impl_(annos) +#define _GrouP_impl_(annos) +#define _At_buffer_impl_(target, iter, bound, annos) +#define _Use_decl_anno_impl_ +#define _Points_to_data_impl_ +#define _Literal_impl_ +#define _Notliteral_impl_ +#define _Notref_impl_ + +#define _Pre_valid_impl_ +#define _Post_valid_impl_ +#define _Ret_valid_impl_ + +#define _Check_return_impl_ +#define _Must_inspect_impl_ + +#define _Success_impl_(expr) +#define _On_failure_impl_(annos) +#define _Always_impl_(annos) + +#define _Printf_format_string_impl_ +#define _Scanf_format_string_impl_ +#define _Scanf_s_format_string_impl_ + +#define _In_bound_impl_ +#define _Out_bound_impl_ +#define _Ret_bound_impl_ +#define _Deref_in_bound_impl_ +#define _Deref_out_bound_impl_ +#define _Deref_ret_bound_impl_ + +#define _Range_impl_(min,max) +#define _In_range_impl_(min,max) +#define _Out_range_impl_(min,max) +#define _Ret_range_impl_(min,max) +#define _Deref_in_range_impl_(min,max) +#define _Deref_out_range_impl_(min,max) +#define _Deref_ret_range_impl_(min,max) + +#define _Satisfies_impl_(expr) +#define _Pre_satisfies_impl_(expr) +#define _Post_satisfies_impl_(expr) + +#define _Null_impl_ +#define _Notnull_impl_ +#define _Maybenull_impl_ + +#define _Valid_impl_ +#define _Notvalid_impl_ +#define _Maybevalid_impl_ + +#define _Field_range_impl_(min,max) + +#define _Pre_impl_ +#define _Pre1_impl_(p1) +#define _Pre2_impl_(p1,p2) +#define _Pre3_impl_(p1,p2,p3) + +#define _Post_impl_ +#define _Post1_impl_(p1) +#define _Post2_impl_(p1,p2) +#define _Post3_impl_(p1,p2,p3) + +#define _Ret1_impl_(p1) +#define _Ret2_impl_(p1,p2) +#define _Ret3_impl_(p1,p2,p3) + +#define _Deref_pre1_impl_(p1) +#define _Deref_pre2_impl_(p1,p2) +#define _Deref_pre3_impl_(p1,p2,p3) + +#define _Deref_post1_impl_(p1) +#define _Deref_post2_impl_(p1,p2) +#define _Deref_post3_impl_(p1,p2,p3) + +#define _Deref_ret1_impl_(p1) +#define _Deref_ret2_impl_(p1,p2) +#define _Deref_ret3_impl_(p1,p2,p3) + +#define _Deref2_pre1_impl_(p1) +#define _Deref2_post1_impl_(p1) +#define _Deref2_ret1_impl_(p1) + +#define _Readable_bytes_impl_(size) +#define _Readable_elements_impl_(size) +#define _Writable_bytes_impl_(size) +#define _Writable_elements_impl_(size) + +#define _Null_terminated_impl_ +#define _NullNull_terminated_impl_ + +// Obsolete -- may be needed for transition to attributes. +#define __inner_typefix(ctype) +#define __inner_exceptthat + +#endif // ] + +// This section contains the deprecated annotations + +/* + ------------------------------------------------------------------------------- + Introduction + + sal.h provides a set of annotations to describe how a function uses its + parameters - the assumptions it makes about them, and the guarantees it makes + upon finishing. + + Annotations may be placed before either a function parameter's type or its return + type, and describe the function's behavior regarding the parameter or return value. + There are two classes of annotations: buffer annotations and advanced annotations. + Buffer annotations describe how functions use their pointer parameters, and + advanced annotations either describe complex/unusual buffer behavior, or provide + additional information about a parameter that is not otherwise expressible. + + ------------------------------------------------------------------------------- + Buffer Annotations + + The most important annotations in sal.h provide a consistent way to annotate + buffer parameters or return values for a function. Each of these annotations describes + a single buffer (which could be a string, a fixed-length or variable-length array, + or just a pointer) that the function interacts with: where it is, how large it is, + how much is initialized, and what the function does with it. + + The appropriate macro for a given buffer can be constructed using the table below. + Just pick the appropriate values from each category, and combine them together + with a leading underscore. Some combinations of values do not make sense as buffer + annotations. Only meaningful annotations can be added to your code; for a list of + these, see the buffer annotation definitions section. + + Only a single buffer annotation should be used for each parameter. + + |------------|------------|---------|--------|----------|----------|---------------| + | Level | Usage | Size | Output | NullTerm | Optional | Parameters | + |------------|------------|---------|--------|----------|----------|---------------| + | <> | <> | <> | <> | _z | <> | <> | + | _deref | _in | _ecount | _full | _nz | _opt | (size) | + | _deref_opt | _out | _bcount | _part | | | (size,length) | + | | _inout | | | | | | + | | | | | | | | + |------------|------------|---------|--------|----------|----------|---------------| + + Level: Describes the buffer pointer's level of indirection from the parameter or + return value 'p'. + + <> : p is the buffer pointer. + _deref : *p is the buffer pointer. p must not be NULL. + _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the rest of + the annotation is ignored. + + Usage: Describes how the function uses the buffer. + + <> : The buffer is not accessed. If used on the return value or with _deref, the + function will provide the buffer, and it will be uninitialized at exit. + Otherwise, the caller must provide the buffer. This should only be used + for alloc and free functions. + _in : The function will only read from the buffer. The caller must provide the + buffer and initialize it. Cannot be used with _deref. + _out : The function will only write to the buffer. If used on the return value or + with _deref, the function will provide the buffer and initialize it. + Otherwise, the caller must provide the buffer, and the function will + initialize it. + _inout : The function may freely read from and write to the buffer. The caller must + provide the buffer and initialize it. If used with _deref, the buffer may + be reallocated by the function. + + Size: Describes the total size of the buffer. This may be less than the space actually + allocated for the buffer, in which case it describes the accessible amount. + + <> : No buffer size is given. If the type specifies the buffer size (such as + with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is one + element long. Must be used with _in, _out, or _inout. + _ecount : The buffer size is an explicit element count. + _bcount : The buffer size is an explicit byte count. + + Output: Describes how much of the buffer will be initialized by the function. For + _inout buffers, this also describes how much is initialized at entry. Omit this + category for _in buffers; they must be fully initialized by the caller. + + <> : The type specifies how much is initialized. For instance, a function initializing + an LPWSTR must NULL-terminate the string. + _full : The function initializes the entire buffer. + _part : The function initializes part of the buffer, and explicitly indicates how much. + + NullTerm: States if the present of a '\0' marks the end of valid elements in the buffer. + _z : A '\0' indicated the end of the buffer + _nz : The buffer may not be null terminated and a '\0' does not indicate the end of the + buffer. + Optional: Describes if the buffer itself is optional. + + <> : The pointer to the buffer must not be NULL. + _opt : The pointer to the buffer might be NULL. It will be checked before being dereferenced. + + Parameters: Gives explicit counts for the size and length of the buffer. + + <> : There is no explicit count. Use when neither _ecount nor _bcount is used. + (size) : Only the buffer's total size is given. Use with _ecount or _bcount but not _part. + (size,length) : The buffer's total size and initialized length are given. Use with _ecount_part + and _bcount_part. + + ------------------------------------------------------------------------------- + Buffer Annotation Examples + + LWSTDAPI_(BOOL) StrToIntExA( + __in LPCSTR pszString, + DWORD dwFlags, + __out int *piRet -- A pointer whose dereference will be filled in. + ); + + void MyPaintingFunction( + __in HWND hwndControl, -- An initialized read-only parameter. + __in_opt HDC hdcOptional, -- An initialized read-only parameter that might be NULL. + __inout IPropertyStore *ppsStore -- An initialized parameter that may be freely used + -- and modified. + ); + + LWSTDAPI_(BOOL) PathCompactPathExA( + __out_ecount(cchMax) LPSTR pszOut, -- A string buffer with cch elements that will + -- be NULL terminated on exit. + __in LPCSTR pszSrc, + UINT cchMax, + DWORD dwFlags + ); + + HRESULT SHLocalAllocBytes( + size_t cb, + __deref_bcount(cb) T **ppv -- A pointer whose dereference will be set to an + -- uninitialized buffer with cb bytes. + ); + + __inout_bcount_full(cb) : A buffer with cb elements that is fully initialized at + entry and exit, and may be written to by this function. + + __out_ecount_part(count, *countOut) : A buffer with count elements that will be + partially initialized by this function. The function indicates how much it + initialized by setting *countOut. + + ------------------------------------------------------------------------------- + Advanced Annotations + + Advanced annotations describe behavior that is not expressible with the regular + buffer macros. These may be used either to annotate buffer parameters that involve + complex or conditional behavior, or to enrich existing annotations with additional + information. + + __success(expr) f : + indicates whether function f succeeded or not. If is true at exit, + all the function's guarantees (as given by other annotations) must hold. If + is false at exit, the caller should not expect any of the function's guarantees + to hold. If not used, the function must always satisfy its guarantees. Added + automatically to functions that indicate success in standard ways, such as by + returning an HRESULT. + + __nullterminated p : + Pointer p is a buffer that may be read or written up to and including the first + NULL character or pointer. May be used on typedefs, which marks valid (properly + initialized) instances of that type as being NULL-terminated. + + __nullnullterminated p : + Pointer p is a buffer that may be read or written up to and including the first + sequence of two NULL characters or pointers. May be used on typedefs, which marks + valid instances of that type as being double-NULL terminated. + + __reserved v : + Value v must be 0/NULL, reserved for future use. + + __checkReturn v : + Return value v must not be ignored by callers of this function. + + __typefix(ctype) v : + Value v should be treated as an instance of ctype, rather than its declared type. + + __override f : + Specify C#-style 'override' behaviour for overriding virtual methods. + + __callback f : + Function f can be used as a function pointer. + + __format_string p : + Pointer p is a string that contains % markers in the style of printf. + + __blocksOn(resource) f : + Function f blocks on the resource 'resource'. + + __fallthrough : + Annotates switch statement labels where fall-through is desired, to distinguish + from forgotten break statements. + + ------------------------------------------------------------------------------- + Advanced Annotation Examples + + __success(return != FALSE) LWSTDAPI_(BOOL) + PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath) : + pszBuf is only guaranteed to be NULL-terminated when TRUE is returned. + + typedef __nullterminated WCHAR* LPWSTR : Initialized LPWSTRs are NULL-terminated strings. + + __out_ecount(cch) __typefix(LPWSTR) void *psz : psz is a buffer parameter which will be + a NULL-terminated WCHAR string at exit, and which initially contains cch WCHARs. + + ------------------------------------------------------------------------------- +*/ + +#define __specstrings + +#ifdef __cplusplus // [ +#ifndef __nothrow // [ +# define __nothrow NOTHROW_DECL +#endif // ] +extern "C" { +#else // ][ +#ifndef __nothrow // [ +# define __nothrow +#endif // ] +#endif /* #ifdef __cplusplus */ // ] + + +/* + ------------------------------------------------------------------------------- + Helper Macro Definitions + + These express behavior common to many of the high-level annotations. + DO NOT USE THESE IN YOUR CODE. + ------------------------------------------------------------------------------- +*/ + +/* + The helper annotations are only understood by the compiler version used by + various defect detection tools. When the regular compiler is running, they + are defined into nothing, and do not affect the compiled code. +*/ + +#if !defined(__midl) && defined(_PREFAST_) // [ + + /* + In the primitive "SAL_*" annotations "SAL" stands for Standard + Annotation Language. These "SAL_*" annotations are the + primitives the compiler understands and high-level MACROs + will decompose into these primivates. + */ + + #define _SA_SPECSTRIZE( x ) #x + + /* + __null p + __notnull p + __maybenull p + + Annotates a pointer p. States that pointer p is null. Commonly used + in the negated form __notnull or the possibly null form __maybenull. + */ + +#ifndef PAL_STDCPP_COMPAT + #define __null _Null_impl_ + #define __notnull _Notnull_impl_ + #define __maybenull _Maybenull_impl_ +#endif // !PAL_STDCPP_COMPAT + + /* + __readonly l + __notreadonly l + __mabyereadonly l + + Annotates a location l. States that location l is not modified after + this point. If the annotation is placed on the precondition state of + a function, the restriction only applies until the postcondition state + of the function. __maybereadonly states that the annotated location + may be modified, whereas __notreadonly states that a location must be + modified. + */ + + #define __readonly _Pre1_impl_(__readaccess_impl) + #define __notreadonly _Pre1_impl_(__allaccess_impl) + #define __maybereadonly _Pre1_impl_(__readaccess_impl) + + /* + __valid v + __notvalid v + __maybevalid v + + Annotates any value v. States that the value satisfies all properties of + valid values of its type. For example, for a string buffer, valid means + that the buffer pointer is either NULL or points to a NULL-terminated string. + */ + + #define __valid _Valid_impl_ + #define __notvalid _Notvalid_impl_ + #define __maybevalid _Maybevalid_impl_ + + /* + __readableTo(extent) p + + Annotates a buffer pointer p. If the buffer can be read, extent describes + how much of the buffer is readable. For a reader of the buffer, this is + an explicit permission to read up to that amount, rather than a restriction to + read only up to it. + */ + + #define __readableTo(extent) _SA_annotes1(SAL_readableTo, extent) + + /* + + __elem_readableTo(size) + + Annotates a buffer pointer p as being readable to size elements. + */ + + #define __elem_readableTo(size) _SA_annotes1(SAL_readableTo, elementCount( size )) + + /* + __byte_readableTo(size) + + Annotates a buffer pointer p as being readable to size bytes. + */ + #define __byte_readableTo(size) _SA_annotes1(SAL_readableTo, byteCount(size)) + + /* + __writableTo(extent) p + + Annotates a buffer pointer p. If the buffer can be modified, extent + describes how much of the buffer is writable (usually the allocation + size). For a writer of the buffer, this is an explicit permission to + write up to that amount, rather than a restriction to write only up to it. + */ + #define __writableTo(size) _SA_annotes1(SAL_writableTo, size) + + /* + __elem_writableTo(size) + + Annotates a buffer pointer p as being writable to size elements. + */ + #define __elem_writableTo(size) _SA_annotes1(SAL_writableTo, elementCount( size )) + + /* + __byte_writableTo(size) + + Annotates a buffer pointer p as being writable to size bytes. + */ + #define __byte_writableTo(size) _SA_annotes1(SAL_writableTo, byteCount( size)) + + /* + __deref p + + Annotates a pointer p. The next annotation applies one dereference down + in the type. If readableTo(p, size) then the next annotation applies to + all elements *(p+i) for which i satisfies the size. If p is a pointer + to a struct, the next annotation applies to all fields of the struct. + */ + #define __deref _Deref_impl_ + + /* + __pre __next_annotation + + The next annotation applies in the precondition state + */ + #define __pre _Pre_impl_ + + /* + __post __next_annotation + + The next annotation applies in the postcondition state + */ + #define __post _Post_impl_ + + /* + __precond() + + When is true, the next annotation applies in the precondition state + (currently not enabled) + */ + #define __precond(expr) __pre + + /* + __postcond() + + When is true, the next annotation applies in the postcondition state + (currently not enabled) + */ + #define __postcond(expr) __post + + /* + __exceptthat + + Given a set of annotations Q containing __exceptthat maybeP, the effect of + the except clause is to erase any P or notP annotations (explicit or + implied) within Q at the same level of dereferencing that the except + clause appears, and to replace it with maybeP. + + Example 1: __valid __pre_except_maybenull on a pointer p means that the + pointer may be null, and is otherwise valid, thus overriding + the implicit notnull annotation implied by __valid on + pointers. + + Example 2: __valid __deref __pre_except_maybenull on an int **p means + that p is not null (implied by valid), but the elements + pointed to by p could be null, and are otherwise valid. + */ + #define __exceptthat __inner_exceptthat + + /* + _refparam + + Added to all out parameter macros to indicate that they are all reference + parameters. + */ + #define __refparam _Notref_ __deref __notreadonly + + /* + __inner_* + + Helper macros that directly correspond to certain high-level annotations. + + */ + + /* + Macros to classify the entrypoints and indicate their category. + + Pre-defined control point categories include: RPC, LPC, DeviceDriver, UserToKernel, ISAPI, COM. + + */ + #define __inner_control_entrypoint(category) _SA_annotes2(SAL_entrypoint, controlEntry, category) + + + /* + Pre-defined data entry point categories include: Registry, File, Network. + */ + #define __inner_data_entrypoint(category) _SA_annotes2(SAL_entrypoint, dataEntry, category) + + #define __inner_override _SA_annotes0(__override) + #define __inner_callback _SA_annotes0(__callback) + #define __inner_blocksOn(resource) _SA_annotes1(SAL_blocksOn, resource) + #define __inner_fallthrough_dec __inline __nothrow void __FallThrough() {} + #define __inner_fallthrough __FallThrough(); + + #define __post_except_maybenull __post __inner_exceptthat _Maybenull_impl_ + #define __pre_except_maybenull __pre __inner_exceptthat _Maybenull_impl_ + + #define __post_deref_except_maybenull __post __deref __inner_exceptthat _Maybenull_impl_ + #define __pre_deref_except_maybenull __pre __deref __inner_exceptthat _Maybenull_impl_ + + #define __inexpressible_readableTo(size) _Readable_elements_impl_(_Inexpressible_(size)) + #define __inexpressible_writableTo(size) _Writable_elements_impl_(_Inexpressible_(size)) + + +#else // ][ +#ifndef PAL_STDCPP_COMPAT + #define __null + #define __notnull + #define __deref +#endif // !PAL_STDCPP_COMPAT + #define __maybenull + #define __readonly + #define __notreadonly + #define __maybereadonly + #define __valid + #define __notvalid + #define __maybevalid + #define __readableTo(extent) + #define __elem_readableTo(size) + #define __byte_readableTo(size) + #define __writableTo(size) + #define __elem_writableTo(size) + #define __byte_writableTo(size) + #define __pre + #define __post + #define __precond(expr) + #define __postcond(expr) + #define __exceptthat + #define __inner_override + #define __inner_callback + #define __inner_blocksOn(resource) + #define __inner_fallthrough_dec + #define __inner_fallthrough + #define __refparam + #define __inner_control_entrypoint(category) + #define __inner_data_entrypoint(category) + + #define __post_except_maybenull + #define __pre_except_maybenull + #define __post_deref_except_maybenull + #define __pre_deref_except_maybenull + + #define __inexpressible_readableTo(size) + #define __inexpressible_writableTo(size) + +#endif /* #if !defined(__midl) && defined(_PREFAST_) */ // ] + +/* +------------------------------------------------------------------------------- +Buffer Annotation Definitions + +Any of these may be used to directly annotate functions, but only one should +be used for each parameter. To determine which annotation to use for a given +buffer, use the table in the buffer annotations section. +------------------------------------------------------------------------------- +*/ + +// These macros conflict with c++ headers. +#ifndef PAL_STDCPP_COMPAT +#define __in _SAL1_Source_(__in, (), _In_) +#define __out _SAL1_Source_(__out, (), _Out_) +#endif // !PAL_STDCPP_COMPAT + +#define __ecount(size) _SAL1_Source_(__ecount, (size), __notnull __elem_writableTo(size)) +#define __bcount(size) _SAL1_Source_(__bcount, (size), __notnull __byte_writableTo(size)) +#define __in_ecount(size) _SAL1_Source_(__in_ecount, (size), _In_reads_(size)) +#define __in_bcount(size) _SAL1_Source_(__in_bcount, (size), _In_reads_bytes_(size)) +#define __in_z _SAL1_Source_(__in_z, (), _In_z_) +#define __in_ecount_z(size) _SAL1_Source_(__in_ecount_z, (size), _In_reads_z_(size)) +#define __in_bcount_z(size) _SAL1_Source_(__in_bcount_z, (size), __in_bcount(size) __pre __nullterminated) +#define __in_nz _SAL1_Source_(__in_nz, (), __in) +#define __in_ecount_nz(size) _SAL1_Source_(__in_ecount_nz, (size), __in_ecount(size)) +#define __in_bcount_nz(size) _SAL1_Source_(__in_bcount_nz, (size), __in_bcount(size)) +#define __out_ecount(size) _SAL1_Source_(__out_ecount, (size), _Out_writes_(size)) +#define __out_bcount(size) _SAL1_Source_(__out_bcount, (size), _Out_writes_bytes_(size)) +#define __out_ecount_part(size,length) _SAL1_Source_(__out_ecount_part, (size,length), _Out_writes_to_(size,length)) +#define __out_bcount_part(size,length) _SAL1_Source_(__out_bcount_part, (size,length), _Out_writes_bytes_to_(size,length)) +#define __out_ecount_full(size) _SAL1_Source_(__out_ecount_full, (size), _Out_writes_all_(size)) +#define __out_bcount_full(size) _SAL1_Source_(__out_bcount_full, (size), _Out_writes_bytes_all_(size)) +#define __out_z _SAL1_Source_(__out_z, (), __post __valid __refparam __post __nullterminated) +#define __out_z_opt _SAL1_Source_(__out_z_opt, (), __post __valid __refparam __post __nullterminated __pre_except_maybenull) +#define __out_ecount_z(size) _SAL1_Source_(__out_ecount_z, (size), __ecount(size) __post __valid __refparam __post __nullterminated) +#define __out_bcount_z(size) _SAL1_Source_(__out_bcount_z, (size), __bcount(size) __post __valid __refparam __post __nullterminated) +#define __out_ecount_part_z(size,length) _SAL1_Source_(__out_ecount_part_z, (size,length), __out_ecount_part(size,length) __post __nullterminated) +#define __out_bcount_part_z(size,length) _SAL1_Source_(__out_bcount_part_z, (size,length), __out_bcount_part(size,length) __post __nullterminated) +#define __out_ecount_full_z(size) _SAL1_Source_(__out_ecount_full_z, (size), __out_ecount_full(size) __post __nullterminated) +#define __out_bcount_full_z(size) _SAL1_Source_(__out_bcount_full_z, (size), __out_bcount_full(size) __post __nullterminated) +#define __out_nz _SAL1_Source_(__out_nz, (), __post __valid __refparam) +#define __out_nz_opt _SAL1_Source_(__out_nz_opt, (), __post __valid __refparam __post_except_maybenull_) +#define __out_ecount_nz(size) _SAL1_Source_(__out_ecount_nz, (size), __ecount(size) __post __valid __refparam) +#define __out_bcount_nz(size) _SAL1_Source_(__out_bcount_nz, (size), __bcount(size) __post __valid __refparam) +#define __inout _SAL1_Source_(__inout, (), _Inout_) +#define __inout_ecount(size) _SAL1_Source_(__inout_ecount, (size), _Inout_updates_(size)) +#define __inout_bcount(size) _SAL1_Source_(__inout_bcount, (size), _Inout_updates_bytes_(size)) +#define __inout_ecount_part(size,length) _SAL1_Source_(__inout_ecount_part, (size,length), _Inout_updates_to_(size,length)) +#define __inout_bcount_part(size,length) _SAL1_Source_(__inout_bcount_part, (size,length), _Inout_updates_bytes_to_(size,length)) +#define __inout_ecount_full(size) _SAL1_Source_(__inout_ecount_full, (size), _Inout_updates_all_(size)) +#define __inout_bcount_full(size) _SAL1_Source_(__inout_bcount_full, (size), _Inout_updates_bytes_all_(size)) +#define __inout_z _SAL1_Source_(__inout_z, (), _Inout_z_) +#define __inout_ecount_z(size) _SAL1_Source_(__inout_ecount_z, (size), _Inout_updates_z_(size)) +#define __inout_bcount_z(size) _SAL1_Source_(__inout_bcount_z, (size), __inout_bcount(size) __pre __nullterminated __post __nullterminated) +#define __inout_nz _SAL1_Source_(__inout_nz, (), __inout) +#define __inout_ecount_nz(size) _SAL1_Source_(__inout_ecount_nz, (size), __inout_ecount(size)) +#define __inout_bcount_nz(size) _SAL1_Source_(__inout_bcount_nz, (size), __inout_bcount(size)) +#define __ecount_opt(size) _SAL1_Source_(__ecount_opt, (size), __ecount(size) __pre_except_maybenull) +#define __bcount_opt(size) _SAL1_Source_(__bcount_opt, (size), __bcount(size) __pre_except_maybenull) +#define __in_opt _SAL1_Source_(__in_opt, (), _In_opt_) +#define __in_ecount_opt(size) _SAL1_Source_(__in_ecount_opt, (size), _In_reads_opt_(size)) +#define __in_bcount_opt(size) _SAL1_Source_(__in_bcount_opt, (size), _In_reads_bytes_opt_(size)) +#define __in_z_opt _SAL1_Source_(__in_z_opt, (), _In_opt_z_) +#define __in_ecount_z_opt(size) _SAL1_Source_(__in_ecount_z_opt, (size), __in_ecount_opt(size) __pre __nullterminated) +#define __in_bcount_z_opt(size) _SAL1_Source_(__in_bcount_z_opt, (size), __in_bcount_opt(size) __pre __nullterminated) +#define __in_nz_opt _SAL1_Source_(__in_nz_opt, (), __in_opt) +#define __in_ecount_nz_opt(size) _SAL1_Source_(__in_ecount_nz_opt, (size), __in_ecount_opt(size)) +#define __in_bcount_nz_opt(size) _SAL1_Source_(__in_bcount_nz_opt, (size), __in_bcount_opt(size)) +#define __out_opt _SAL1_Source_(__out_opt, (), _Out_opt_) +#define __out_ecount_opt(size) _SAL1_Source_(__out_ecount_opt, (size), _Out_writes_opt_(size)) +#define __out_bcount_opt(size) _SAL1_Source_(__out_bcount_opt, (size), _Out_writes_bytes_opt_(size)) +#define __out_ecount_part_opt(size,length) _SAL1_Source_(__out_ecount_part_opt, (size,length), __out_ecount_part(size,length) __pre_except_maybenull) +#define __out_bcount_part_opt(size,length) _SAL1_Source_(__out_bcount_part_opt, (size,length), __out_bcount_part(size,length) __pre_except_maybenull) +#define __out_ecount_full_opt(size) _SAL1_Source_(__out_ecount_full_opt, (size), __out_ecount_full(size) __pre_except_maybenull) +#define __out_bcount_full_opt(size) _SAL1_Source_(__out_bcount_full_opt, (size), __out_bcount_full(size) __pre_except_maybenull) +#define __out_ecount_z_opt(size) _SAL1_Source_(__out_ecount_z_opt, (size), __out_ecount_opt(size) __post __nullterminated) +#define __out_bcount_z_opt(size) _SAL1_Source_(__out_bcount_z_opt, (size), __out_bcount_opt(size) __post __nullterminated) +#define __out_ecount_part_z_opt(size,length) _SAL1_Source_(__out_ecount_part_z_opt, (size,length), __out_ecount_part_opt(size,length) __post __nullterminated) +#define __out_bcount_part_z_opt(size,length) _SAL1_Source_(__out_bcount_part_z_opt, (size,length), __out_bcount_part_opt(size,length) __post __nullterminated) +#define __out_ecount_full_z_opt(size) _SAL1_Source_(__out_ecount_full_z_opt, (size), __out_ecount_full_opt(size) __post __nullterminated) +#define __out_bcount_full_z_opt(size) _SAL1_Source_(__out_bcount_full_z_opt, (size), __out_bcount_full_opt(size) __post __nullterminated) +#define __out_ecount_nz_opt(size) _SAL1_Source_(__out_ecount_nz_opt, (size), __out_ecount_opt(size) __post __nullterminated) +#define __out_bcount_nz_opt(size) _SAL1_Source_(__out_bcount_nz_opt, (size), __out_bcount_opt(size) __post __nullterminated) +#define __inout_opt _SAL1_Source_(__inout_opt, (), _Inout_opt_) +#define __inout_ecount_opt(size) _SAL1_Source_(__inout_ecount_opt, (size), __inout_ecount(size) __pre_except_maybenull) +#define __inout_bcount_opt(size) _SAL1_Source_(__inout_bcount_opt, (size), __inout_bcount(size) __pre_except_maybenull) +#define __inout_ecount_part_opt(size,length) _SAL1_Source_(__inout_ecount_part_opt, (size,length), __inout_ecount_part(size,length) __pre_except_maybenull) +#define __inout_bcount_part_opt(size,length) _SAL1_Source_(__inout_bcount_part_opt, (size,length), __inout_bcount_part(size,length) __pre_except_maybenull) +#define __inout_ecount_full_opt(size) _SAL1_Source_(__inout_ecount_full_opt, (size), __inout_ecount_full(size) __pre_except_maybenull) +#define __inout_bcount_full_opt(size) _SAL1_Source_(__inout_bcount_full_opt, (size), __inout_bcount_full(size) __pre_except_maybenull) +#define __inout_z_opt _SAL1_Source_(__inout_z_opt, (), __inout_opt __pre __nullterminated __post __nullterminated) +#define __inout_ecount_z_opt(size) _SAL1_Source_(__inout_ecount_z_opt, (size), __inout_ecount_opt(size) __pre __nullterminated __post __nullterminated) +#define __inout_ecount_z_opt(size) _SAL1_Source_(__inout_ecount_z_opt, (size), __inout_ecount_opt(size) __pre __nullterminated __post __nullterminated) +#define __inout_bcount_z_opt(size) _SAL1_Source_(__inout_bcount_z_opt, (size), __inout_bcount_opt(size)) +#define __inout_nz_opt _SAL1_Source_(__inout_nz_opt, (), __inout_opt) +#define __inout_ecount_nz_opt(size) _SAL1_Source_(__inout_ecount_nz_opt, (size), __inout_ecount_opt(size)) +#define __inout_bcount_nz_opt(size) _SAL1_Source_(__inout_bcount_nz_opt, (size), __inout_bcount_opt(size)) +#define __deref_ecount(size) _SAL1_Source_(__deref_ecount, (size), _Notref_ __ecount(1) __post _Notref_ __elem_readableTo(1) __post _Notref_ __deref _Notref_ __notnull __post __deref __elem_writableTo(size)) +#define __deref_bcount(size) _SAL1_Source_(__deref_bcount, (size), _Notref_ __ecount(1) __post _Notref_ __elem_readableTo(1) __post _Notref_ __deref _Notref_ __notnull __post __deref __byte_writableTo(size)) +#define __deref_out _SAL1_Source_(__deref_out, (), _Outptr_) +#define __deref_out_ecount(size) _SAL1_Source_(__deref_out_ecount, (size), _Outptr_result_buffer_(size)) +#define __deref_out_bcount(size) _SAL1_Source_(__deref_out_bcount, (size), _Outptr_result_bytebuffer_(size)) +#define __deref_out_ecount_part(size,length) _SAL1_Source_(__deref_out_ecount_part, (size,length), _Outptr_result_buffer_to_(size,length)) +#define __deref_out_bcount_part(size,length) _SAL1_Source_(__deref_out_bcount_part, (size,length), _Outptr_result_bytebuffer_to_(size,length)) +#define __deref_out_ecount_full(size) _SAL1_Source_(__deref_out_ecount_full, (size), __deref_out_ecount_part(size,size)) +#define __deref_out_bcount_full(size) _SAL1_Source_(__deref_out_bcount_full, (size), __deref_out_bcount_part(size,size)) +#define __deref_out_z _SAL1_Source_(__deref_out_z, (), _Outptr_result_z_) +#define __deref_out_ecount_z(size) _SAL1_Source_(__deref_out_ecount_z, (size), __deref_out_ecount(size) __post __deref __nullterminated) +#define __deref_out_bcount_z(size) _SAL1_Source_(__deref_out_bcount_z, (size), __deref_out_bcount(size) __post __deref __nullterminated) +#define __deref_out_nz _SAL1_Source_(__deref_out_nz, (), __deref_out) +#define __deref_out_ecount_nz(size) _SAL1_Source_(__deref_out_ecount_nz, (size), __deref_out_ecount(size)) +#define __deref_out_bcount_nz(size) _SAL1_Source_(__deref_out_bcount_nz, (size), __deref_out_ecount(size)) +#define __deref_inout _SAL1_Source_(__deref_inout, (), _Notref_ __notnull _Notref_ __elem_readableTo(1) __pre __deref __valid __post _Notref_ __deref __valid __refparam) +#define __deref_inout_z _SAL1_Source_(__deref_inout_z, (), __deref_inout __pre __deref __nullterminated __post _Notref_ __deref __nullterminated) +#define __deref_inout_ecount(size) _SAL1_Source_(__deref_inout_ecount, (size), __deref_inout __pre __deref __elem_writableTo(size) __post _Notref_ __deref __elem_writableTo(size)) +#define __deref_inout_bcount(size) _SAL1_Source_(__deref_inout_bcount, (size), __deref_inout __pre __deref __byte_writableTo(size) __post _Notref_ __deref __byte_writableTo(size)) +#define __deref_inout_ecount_part(size,length) _SAL1_Source_(__deref_inout_ecount_part, (size,length), __deref_inout_ecount(size) __pre __deref __elem_readableTo(length) __post __deref __elem_readableTo(length)) +#define __deref_inout_bcount_part(size,length) _SAL1_Source_(__deref_inout_bcount_part, (size,length), __deref_inout_bcount(size) __pre __deref __byte_readableTo(length) __post __deref __byte_readableTo(length)) +#define __deref_inout_ecount_full(size) _SAL1_Source_(__deref_inout_ecount_full, (size), __deref_inout_ecount_part(size,size)) +#define __deref_inout_bcount_full(size) _SAL1_Source_(__deref_inout_bcount_full, (size), __deref_inout_bcount_part(size,size)) +#define __deref_inout_ecount_z(size) _SAL1_Source_(__deref_inout_ecount_z, (size), __deref_inout_ecount(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_inout_bcount_z(size) _SAL1_Source_(__deref_inout_bcount_z, (size), __deref_inout_bcount(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_inout_nz _SAL1_Source_(__deref_inout_nz, (), __deref_inout) +#define __deref_inout_ecount_nz(size) _SAL1_Source_(__deref_inout_ecount_nz, (size), __deref_inout_ecount(size)) +#define __deref_inout_bcount_nz(size) _SAL1_Source_(__deref_inout_bcount_nz, (size), __deref_inout_ecount(size)) +#define __deref_ecount_opt(size) _SAL1_Source_(__deref_ecount_opt, (size), __deref_ecount(size) __post_deref_except_maybenull) +#define __deref_bcount_opt(size) _SAL1_Source_(__deref_bcount_opt, (size), __deref_bcount(size) __post_deref_except_maybenull) +#define __deref_out_opt _SAL1_Source_(__deref_out_opt, (), __deref_out __post_deref_except_maybenull) +#define __deref_out_ecount_opt(size) _SAL1_Source_(__deref_out_ecount_opt, (size), __deref_out_ecount(size) __post_deref_except_maybenull) +#define __deref_out_bcount_opt(size) _SAL1_Source_(__deref_out_bcount_opt, (size), __deref_out_bcount(size) __post_deref_except_maybenull) +#define __deref_out_ecount_part_opt(size,length) _SAL1_Source_(__deref_out_ecount_part_opt, (size,length), __deref_out_ecount_part(size,length) __post_deref_except_maybenull) +#define __deref_out_bcount_part_opt(size,length) _SAL1_Source_(__deref_out_bcount_part_opt, (size,length), __deref_out_bcount_part(size,length) __post_deref_except_maybenull) +#define __deref_out_ecount_full_opt(size) _SAL1_Source_(__deref_out_ecount_full_opt, (size), __deref_out_ecount_full(size) __post_deref_except_maybenull) +#define __deref_out_bcount_full_opt(size) _SAL1_Source_(__deref_out_bcount_full_opt, (size), __deref_out_bcount_full(size) __post_deref_except_maybenull) +#define __deref_out_z_opt _SAL1_Source_(__deref_out_z_opt, (), _Outptr_result_maybenull_z_) +#define __deref_out_ecount_z_opt(size) _SAL1_Source_(__deref_out_ecount_z_opt, (size), __deref_out_ecount_opt(size) __post __deref __nullterminated) +#define __deref_out_bcount_z_opt(size) _SAL1_Source_(__deref_out_bcount_z_opt, (size), __deref_out_bcount_opt(size) __post __deref __nullterminated) +#define __deref_out_nz_opt _SAL1_Source_(__deref_out_nz_opt, (), __deref_out_opt) +#define __deref_out_ecount_nz_opt(size) _SAL1_Source_(__deref_out_ecount_nz_opt, (size), __deref_out_ecount_opt(size)) +#define __deref_out_bcount_nz_opt(size) _SAL1_Source_(__deref_out_bcount_nz_opt, (size), __deref_out_bcount_opt(size)) +#define __deref_inout_opt _SAL1_Source_(__deref_inout_opt, (), __deref_inout __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_ecount_opt(size) _SAL1_Source_(__deref_inout_ecount_opt, (size), __deref_inout_ecount(size) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_bcount_opt(size) _SAL1_Source_(__deref_inout_bcount_opt, (size), __deref_inout_bcount(size) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_ecount_part_opt(size,length) _SAL1_Source_(__deref_inout_ecount_part_opt, (size,length), __deref_inout_ecount_part(size,length) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_bcount_part_opt(size,length) _SAL1_Source_(__deref_inout_bcount_part_opt, (size,length), __deref_inout_bcount_part(size,length) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_ecount_full_opt(size) _SAL1_Source_(__deref_inout_ecount_full_opt, (size), __deref_inout_ecount_full(size) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_bcount_full_opt(size) _SAL1_Source_(__deref_inout_bcount_full_opt, (size), __deref_inout_bcount_full(size) __pre_deref_except_maybenull __post_deref_except_maybenull) +#define __deref_inout_z_opt _SAL1_Source_(__deref_inout_z_opt, (), __deref_inout_opt __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_inout_ecount_z_opt(size) _SAL1_Source_(__deref_inout_ecount_z_opt, (size), __deref_inout_ecount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_inout_bcount_z_opt(size) _SAL1_Source_(__deref_inout_bcount_z_opt, (size), __deref_inout_bcount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_inout_nz_opt _SAL1_Source_(__deref_inout_nz_opt, (), __deref_inout_opt) +#define __deref_inout_ecount_nz_opt(size) _SAL1_Source_(__deref_inout_ecount_nz_opt, (size), __deref_inout_ecount_opt(size)) +#define __deref_inout_bcount_nz_opt(size) _SAL1_Source_(__deref_inout_bcount_nz_opt, (size), __deref_inout_bcount_opt(size)) +#define __deref_opt_ecount(size) _SAL1_Source_(__deref_opt_ecount, (size), __deref_ecount(size) __pre_except_maybenull) +#define __deref_opt_bcount(size) _SAL1_Source_(__deref_opt_bcount, (size), __deref_bcount(size) __pre_except_maybenull) +#define __deref_opt_out _SAL1_Source_(__deref_opt_out, (), _Outptr_opt_) +#define __deref_opt_out_z _SAL1_Source_(__deref_opt_out_z, (), _Outptr_opt_result_z_) +#define __deref_opt_out_ecount(size) _SAL1_Source_(__deref_opt_out_ecount, (size), __deref_out_ecount(size) __pre_except_maybenull) +#define __deref_opt_out_bcount(size) _SAL1_Source_(__deref_opt_out_bcount, (size), __deref_out_bcount(size) __pre_except_maybenull) +#define __deref_opt_out_ecount_part(size,length) _SAL1_Source_(__deref_opt_out_ecount_part, (size,length), __deref_out_ecount_part(size,length) __pre_except_maybenull) +#define __deref_opt_out_bcount_part(size,length) _SAL1_Source_(__deref_opt_out_bcount_part, (size,length), __deref_out_bcount_part(size,length) __pre_except_maybenull) +#define __deref_opt_out_ecount_full(size) _SAL1_Source_(__deref_opt_out_ecount_full, (size), __deref_out_ecount_full(size) __pre_except_maybenull) +#define __deref_opt_out_bcount_full(size) _SAL1_Source_(__deref_opt_out_bcount_full, (size), __deref_out_bcount_full(size) __pre_except_maybenull) +#define __deref_opt_inout _SAL1_Source_(__deref_opt_inout, (), _Inout_opt_) +#define __deref_opt_inout_ecount(size) _SAL1_Source_(__deref_opt_inout_ecount, (size), __deref_inout_ecount(size) __pre_except_maybenull) +#define __deref_opt_inout_bcount(size) _SAL1_Source_(__deref_opt_inout_bcount, (size), __deref_inout_bcount(size) __pre_except_maybenull) +#define __deref_opt_inout_ecount_part(size,length) _SAL1_Source_(__deref_opt_inout_ecount_part, (size,length), __deref_inout_ecount_part(size,length) __pre_except_maybenull) +#define __deref_opt_inout_bcount_part(size,length) _SAL1_Source_(__deref_opt_inout_bcount_part, (size,length), __deref_inout_bcount_part(size,length) __pre_except_maybenull) +#define __deref_opt_inout_ecount_full(size) _SAL1_Source_(__deref_opt_inout_ecount_full, (size), __deref_inout_ecount_full(size) __pre_except_maybenull) +#define __deref_opt_inout_bcount_full(size) _SAL1_Source_(__deref_opt_inout_bcount_full, (size), __deref_inout_bcount_full(size) __pre_except_maybenull) +#define __deref_opt_inout_z _SAL1_Source_(__deref_opt_inout_z, (), __deref_opt_inout __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_ecount_z(size) _SAL1_Source_(__deref_opt_inout_ecount_z, (size), __deref_opt_inout_ecount(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_bcount_z(size) _SAL1_Source_(__deref_opt_inout_bcount_z, (size), __deref_opt_inout_bcount(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_nz _SAL1_Source_(__deref_opt_inout_nz, (), __deref_opt_inout) +#define __deref_opt_inout_ecount_nz(size) _SAL1_Source_(__deref_opt_inout_ecount_nz, (size), __deref_opt_inout_ecount(size)) +#define __deref_opt_inout_bcount_nz(size) _SAL1_Source_(__deref_opt_inout_bcount_nz, (size), __deref_opt_inout_bcount(size)) +#define __deref_opt_ecount_opt(size) _SAL1_Source_(__deref_opt_ecount_opt, (size), __deref_ecount_opt(size) __pre_except_maybenull) +#define __deref_opt_bcount_opt(size) _SAL1_Source_(__deref_opt_bcount_opt, (size), __deref_bcount_opt(size) __pre_except_maybenull) +#define __deref_opt_out_opt _SAL1_Source_(__deref_opt_out_opt, (), _Outptr_opt_result_maybenull_) +#define __deref_opt_out_ecount_opt(size) _SAL1_Source_(__deref_opt_out_ecount_opt, (size), __deref_out_ecount_opt(size) __pre_except_maybenull) +#define __deref_opt_out_bcount_opt(size) _SAL1_Source_(__deref_opt_out_bcount_opt, (size), __deref_out_bcount_opt(size) __pre_except_maybenull) +#define __deref_opt_out_ecount_part_opt(size,length) _SAL1_Source_(__deref_opt_out_ecount_part_opt, (size,length), __deref_out_ecount_part_opt(size,length) __pre_except_maybenull) +#define __deref_opt_out_bcount_part_opt(size,length) _SAL1_Source_(__deref_opt_out_bcount_part_opt, (size,length), __deref_out_bcount_part_opt(size,length) __pre_except_maybenull) +#define __deref_opt_out_ecount_full_opt(size) _SAL1_Source_(__deref_opt_out_ecount_full_opt, (size), __deref_out_ecount_full_opt(size) __pre_except_maybenull) +#define __deref_opt_out_bcount_full_opt(size) _SAL1_Source_(__deref_opt_out_bcount_full_opt, (size), __deref_out_bcount_full_opt(size) __pre_except_maybenull) +#define __deref_opt_out_z_opt _SAL1_Source_(__deref_opt_out_z_opt, (), __post __deref __valid __refparam __pre_except_maybenull __pre_deref_except_maybenull __post_deref_except_maybenull __post __deref __nullterminated) +#define __deref_opt_out_ecount_z_opt(size) _SAL1_Source_(__deref_opt_out_ecount_z_opt, (size), __deref_opt_out_ecount_opt(size) __post __deref __nullterminated) +#define __deref_opt_out_bcount_z_opt(size) _SAL1_Source_(__deref_opt_out_bcount_z_opt, (size), __deref_opt_out_bcount_opt(size) __post __deref __nullterminated) +#define __deref_opt_out_nz_opt _SAL1_Source_(__deref_opt_out_nz_opt, (), __deref_opt_out_opt) +#define __deref_opt_out_ecount_nz_opt(size) _SAL1_Source_(__deref_opt_out_ecount_nz_opt, (size), __deref_opt_out_ecount_opt(size)) +#define __deref_opt_out_bcount_nz_opt(size) _SAL1_Source_(__deref_opt_out_bcount_nz_opt, (size), __deref_opt_out_bcount_opt(size)) +#define __deref_opt_inout_opt _SAL1_Source_(__deref_opt_inout_opt, (), __deref_inout_opt __pre_except_maybenull) +#define __deref_opt_inout_ecount_opt(size) _SAL1_Source_(__deref_opt_inout_ecount_opt, (size), __deref_inout_ecount_opt(size) __pre_except_maybenull) +#define __deref_opt_inout_bcount_opt(size) _SAL1_Source_(__deref_opt_inout_bcount_opt, (size), __deref_inout_bcount_opt(size) __pre_except_maybenull) +#define __deref_opt_inout_ecount_part_opt(size,length) _SAL1_Source_(__deref_opt_inout_ecount_part_opt, (size,length), __deref_inout_ecount_part_opt(size,length) __pre_except_maybenull) +#define __deref_opt_inout_bcount_part_opt(size,length) _SAL1_Source_(__deref_opt_inout_bcount_part_opt, (size,length), __deref_inout_bcount_part_opt(size,length) __pre_except_maybenull) +#define __deref_opt_inout_ecount_full_opt(size) _SAL1_Source_(__deref_opt_inout_ecount_full_opt, (size), __deref_inout_ecount_full_opt(size) __pre_except_maybenull) +#define __deref_opt_inout_bcount_full_opt(size) _SAL1_Source_(__deref_opt_inout_bcount_full_opt, (size), __deref_inout_bcount_full_opt(size) __pre_except_maybenull) +#define __deref_opt_inout_z_opt _SAL1_Source_(__deref_opt_inout_z_opt, (), __deref_opt_inout_opt __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_ecount_z_opt(size) _SAL1_Source_(__deref_opt_inout_ecount_z_opt, (size), __deref_opt_inout_ecount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_bcount_z_opt(size) _SAL1_Source_(__deref_opt_inout_bcount_z_opt, (size), __deref_opt_inout_bcount_opt(size) __pre __deref __nullterminated __post __deref __nullterminated) +#define __deref_opt_inout_nz_opt _SAL1_Source_(__deref_opt_inout_nz_opt, (), __deref_opt_inout_opt) +#define __deref_opt_inout_ecount_nz_opt(size) _SAL1_Source_(__deref_opt_inout_ecount_nz_opt, (size), __deref_opt_inout_ecount_opt(size)) +#define __deref_opt_inout_bcount_nz_opt(size) _SAL1_Source_(__deref_opt_inout_bcount_nz_opt, (size), __deref_opt_inout_bcount_opt(size)) + +/* +------------------------------------------------------------------------------- +Advanced Annotation Definitions + +Any of these may be used to directly annotate functions, and may be used in +combination with each other or with regular buffer macros. For an explanation +of each annotation, see the advanced annotations section. +------------------------------------------------------------------------------- +*/ + +#define __success(expr) _Success_(expr) +#define __nullterminated _Null_terminated_ +#define __nullnullterminated +#define __clr_reserved _SAL1_Source_(__reserved, (), _Reserved_) +#define __checkReturn _SAL1_Source_(__checkReturn, (), _Check_return_) +#define __typefix(ctype) _SAL1_Source_(__typefix, (ctype), __inner_typefix(ctype)) +#define __override __inner_override +#define __callback __inner_callback +#define __format_string _Printf_format_string_ +#define __blocksOn(resource) __inner_blocksOn(resource) +#define __control_entrypoint(category) __inner_control_entrypoint(category) +#define __data_entrypoint(category) __inner_data_entrypoint(category) +#define __useHeader _Use_decl_anno_impl_ +#define __on_failure(annotes) _On_failure_impl_(annotes _SAL_nop_impl_) + +#ifndef __fallthrough // [ + __inner_fallthrough_dec + #define __fallthrough __inner_fallthrough +#endif // ] + +#ifndef __analysis_assume // [ +#ifdef _PREFAST_ // [ +#define __analysis_assume(expr) __assume(expr) +#else // ][ +#define __analysis_assume(expr) +#endif // ] +#endif // ] + +#ifndef _Analysis_assume_ // [ +#ifdef _PREFAST_ // [ +#define _Analysis_assume_(expr) __assume(expr) +#else // ][ +#define _Analysis_assume_(expr) +#endif // ] +#endif // ] + +#define _Analysis_noreturn_ _SAL2_Source_(_Analysis_noreturn_, (), _SA_annotes0(SAL_terminates)) + +#ifdef _PREFAST_ // [ +__inline __nothrow +void __AnalysisAssumeNullterminated(_Post_ __nullterminated void *p); + +#define _Analysis_assume_nullterminated_(x) __AnalysisAssumeNullterminated(x) +#else // ][ +#define _Analysis_assume_nullterminated_(x) +#endif // ] + +// +// Set the analysis mode (global flags to analysis). +// They take effect at the point of declaration; use at global scope +// as a declaration. +// + +// Synthesize a unique symbol. +#define ___MKID(x, y) x ## y +#define __MKID(x, y) ___MKID(x, y) +#define __GENSYM(x) __MKID(x, __COUNTER__) + +__ANNOTATION(SAL_analysisMode(__AuToQuOtE __In_impl_ char *mode);) + +#define _Analysis_mode_impl_(mode) _SA_annotes1(SAL_analysisMode, #mode) + +#define _Analysis_mode_(mode) \ + typedef _Analysis_mode_impl_(mode) int \ + __GENSYM(__prefast_analysis_mode_flag); + +// The following are predefined: +// _Analysis_operator_new_throw_ (operator new throws) +// _Analysis_operator_new_null_ (operator new returns null) +// _Analysis_operator_new_never_fails_ (operator new never fails) +// + +// Function class annotations. +__ANNOTATION(SAL_functionClassNew(__In_impl_ char*);) +__PRIMOP(int, _In_function_class_(__In_impl_ char*);) +#define _In_function_class_(x) _In_function_class_(#x) + +#define _Function_class_(x) _SA_annotes1(SAL_functionClassNew, #x) + +/* + * interlocked operand used in interlocked instructions + */ +//#define _Interlocked_operand_ _Pre_ _SA_annotes0(SAL_interlocked) + +#define _Enum_is_bitflag_ _SA_annotes0(SAL_enumIsBitflag) +#define _Strict_type_match_ _SA_annotes0(SAL_strictType2) + +#define _Maybe_raises_SEH_exception_ _Pre_ _SA_annotes1(SAL_inTry,__yes) +#define _Raises_SEH_exception_ _Group_(_Maybe_raises_SEH_exception_ _Analysis_noreturn_) + +#ifdef __cplusplus // [ +} +#endif // ] diff --git a/lib/coreclr/src/pal/inc/rt/servprov.h b/lib/coreclr/src/pal/inc/rt/servprov.h new file mode 100644 index 0000000000..4dfffb1298 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/servprov.h @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: servprov.h +// +// =========================================================================== +// simplified servprov.h for PAL + +#include "rpc.h" +#include "rpcndr.h" + +#include "unknwn.h" + +#ifndef __IServiceProvider_INTERFACE_DEFINED__ +#define __IServiceProvider_INTERFACE_DEFINED__ + +// 6d5140c1-7436-11ce-8034-00aa006009fa +EXTERN_C const IID IID_IServiceProvider; + +interface IServiceProvider : public IUnknown +{ + virtual /* [local] */ HRESULT STDMETHODCALLTYPE QueryService( + /* [in] */ REFGUID guidService, + /* [in] */ REFIID riid, + /* [out] */ void **ppvObject) = 0; +}; + +#endif // __IServiceProvider_INTERFACE_DEFINED__ diff --git a/lib/coreclr/src/pal/inc/rt/share.h b/lib/coreclr/src/pal/inc/rt/share.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/share.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/shellapi.h b/lib/coreclr/src/pal/inc/rt/shellapi.h new file mode 100644 index 0000000000..5c20f4f847 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/shellapi.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: shellapi.h +// +// =========================================================================== +// dummy shellapi.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/shlobj.h b/lib/coreclr/src/pal/inc/rt/shlobj.h new file mode 100644 index 0000000000..ba60876db4 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/shlobj.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: shlobj.h +// +// =========================================================================== +// dummy shlobj.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/shlwapi.h b/lib/coreclr/src/pal/inc/rt/shlwapi.h new file mode 100644 index 0000000000..d284fd690f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/shlwapi.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: shlwapi.h +// +// =========================================================================== +// dummy shlwapi.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/specstrings.h b/lib/coreclr/src/pal/inc/rt/specstrings.h new file mode 100644 index 0000000000..12feab9331 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/specstrings.h @@ -0,0 +1,533 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +// +#ifndef SPECSTRINGS_H +#define SPECSTRINGS_H + +/*** +*specstrings.h - support for markers for documenting the semantics of APIs +* + +* +* [Public] +****/ + +/************************************************************************* +* See specstrings_strict.h for documentation of all user visible macros. +*************************************************************************/ + +#if _MSC_VER +#pragma once +#endif + +#if !defined(_SAL_VERSION_SAL2) + + #if defined(__BUILDMACHINE__) || defined(_USE_SAL2_ONLY) + #define _SAL_VERSION_SAL2(_A) SAL_2_Clean_Violation_using ## _A + #else + #define _SAL_VERSION_SAL2(_A) + #endif + + #ifdef _USE_SAL2_ONLY + #define _SAL2_STRICT + #define _SAL_VERSION_CHECK(_A) _SAL_VERSION_SAL2(_A) + #else + #define _SAL_VERSION_CHECK(_A) + #endif + + #ifndef SAL_VERSION_CHECK + #define SAL_VERSION_CHECK(_A) _SAL_VERSION_CHECK(_A) + #define SAL_VERSION_SAL2(_A) _SAL_VERSION_SAL2(_A) + #endif + +#endif + +#include + +#ifndef __SAL_H_FULL_VER +#define __SAL_H_FULL_VER 140050727 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* version specific fixes to bring sal.h upto date */ +#if __SAL_H_FULL_VER <= 140050727 + +#if !defined(__midl) && defined(_PREFAST_) && _MSC_VER >= 1000 // [ + +/* Missing from RTM sal.h */ +#define __inner_bound _SA_annotes0(SAL_bound) +#define __inner_range(lb,ub) _SA_annotes2(SAL_range,lb,ub) +#define __inner_assume_bound_dec __inline __nothrow void __AssumeBoundInt(_Post_ __inner_bound int i) {i;} +#define __inner_assume_bound(i) __AssumeBoundInt(i); +#define __inner_allocator _SA_annotes0(SAL_allocator) + +#define __static_context(ctx, annotes) \ + _SA_annotes1(SAL_context,ctx) _Group_(__nop_impl(annotes)) + +#define __failure(x) __static_context(SAL_return_convention, \ + _SA_annotes1(SAL_failure,x)) + +__ANNOTATION(SAL_valueUndefined()); +#define __valueUndefined _SA_annotes0(SAL_valueUndefined) + +enum __SAL_failureKind{__failureUnspecified = 0, __failureUndefined = 1}; + +__ANNOTATION(SAL_failureDefault(enum __SAL_failureKind)); +#define __failureDefault(kind) __static_context(SAL_return_convention, \ + _SA_annotes1(SAL_failureDefault,kind)) + +#else // ][ + +#define __inner_bound +#define __inner_range(lb,ub) +#define __inner_assume_bound_dec +#define __inner_assume_bound(i) +#define __inner_allocator + +#define __static_context(ctx, annotes) +#define __failure(x) +#define __valueUndefined +#define __failureDefault(x) + +#endif // ] + +#define __xcount(size) __notnull __inexpressible_writableTo(size) +#define __in_xcount(size) __in _Pre_ __inexpressible_readableTo(size) +#define __out_xcount(size) __xcount(size) _Post_ __valid __refparam +#define __out_xcount_part(size,length) __out_xcount(size) _Post_ __inexpressible_readableTo(length) +#define __out_xcount_full(size) __out_xcount_part(size,size) +#define __inout_xcount(size) __out_xcount(size) _Pre_ __valid +#define __inout_xcount_part(size,length) __out_xcount_part(size,length) _Pre_ __valid _Pre_ __inexpressible_readableTo(length) +#define __inout_xcount_full(size) __inout_xcount_part(size,size) +#define __xcount_opt(size) __xcount(size) __exceptthat __maybenull +#define __in_xcount_opt(size) __in_xcount(size) __exceptthat __maybenull +#define __out_xcount_opt(size) __out_xcount(size) __exceptthat __maybenull +#define __out_xcount_part_opt(size,length) __out_xcount_part(size,length) __exceptthat __maybenull +#define __out_xcount_full_opt(size) __out_xcount_full(size) __exceptthat __maybenull +#define __inout_xcount_opt(size) __inout_xcount(size) __exceptthat __maybenull +#define __inout_xcount_part_opt(size,length) __inout_xcount_part(size,length) __exceptthat __maybenull +#define __inout_xcount_full_opt(size) __inout_xcount_full(size) __exceptthat __maybenull +#define __deref_xcount(size) __ecount(1) _Post_ __elem_readableTo(1) _Post_ __deref __notnull _Post_ __deref __inexpressible_writableTo(size) +#define __deref_in __in _Pre_ __deref __deref __readonly +#define __deref_in_ecount(size) __deref_in _Pre_ __deref __elem_readableTo(size) +#define __deref_in_bcount(size) __deref_in _Pre_ __deref __byte_readableTo(size) +#define __deref_in_xcount(size) __deref_in _Pre_ __deref __inexpressible_readableTo(size) +#define __deref_out_xcount(size) __deref_xcount(size) _Post_ __deref __valid __refparam +#define __deref_out_xcount_part(size,length) __deref_out_xcount(size) _Post_ __deref __inexpressible_readableTo(length) +#define __deref_out_xcount_full(size) __deref_out_xcount_part(size,size) +#define __deref_out_xcount(size) __deref_xcount(size) _Post_ __deref __valid __refparam +#define __inout_xcount_opt(size) __inout_xcount(size) __exceptthat __maybenull +#define __inout_xcount_part_opt(size,length) __inout_xcount_part(size,length) __exceptthat __maybenull +#define __inout_xcount_full_opt(size) __inout_xcount_full(size) __exceptthat __maybenull +#define __deref_xcount(size) __ecount(1) _Post_ __elem_readableTo(1) _Post_ __deref __notnull _Post_ __deref __inexpressible_writableTo(size) +#define __deref_in __in _Pre_ __deref __deref __readonly +#define __deref_in_ecount(size) __deref_in _Pre_ __deref __elem_readableTo(size) +#define __deref_in_bcount(size) __deref_in _Pre_ __deref __byte_readableTo(size) +#define __deref_in_xcount(size) __deref_in _Pre_ __deref __inexpressible_readableTo(size) +#define __deref_out_xcount(size) __deref_xcount(size) _Post_ __deref __valid __refparam +#define __deref_out_xcount_part(size,length) __deref_out_xcount(size) _Post_ __deref __inexpressible_readableTo(length) +#define __deref_out_xcount_full(size) __deref_out_xcount_part(size,size) +#define __deref_out_xcount(size) __deref_xcount(size) _Post_ __deref __valid __refparam +#define __deref_inout_xcount(size) __deref_inout _Pre_ __deref __inexpressible_writableTo(size) _Post_ __deref __inexpressible_writableTo(size) +#define __deref_inout_xcount_part(size,length) __deref_inout_xcount(size) _Pre_ __deref __inexpressible_readableTo(length) _Post_ __deref __inexpressible_readableTo(length) +#define __deref_inout_xcount_full(size) __deref_inout_xcount_part(size,size) +#define __deref_xcount_opt(size) __deref_xcount(size) _Post_ __deref __exceptthat __maybenull +#define __deref_in_opt __deref_in _Pre_ __deref __exceptthat __maybenull +#define __deref_in_opt_out __deref_inout _Pre_ __deref __exceptthat __maybenull _Post_ __deref __notnull +#define __deref_in_ecount_opt(size) __deref_in_ecount(size) _Pre_ __deref __exceptthat __maybenull +#define __deref_in_bcount_opt(size) __deref_in_bcount(size) _Pre_ __deref __exceptthat __maybenull +#define __deref_in_xcount_opt(size) __deref_in_xcount(size) _Pre_ __deref __exceptthat __maybenull +#define __deref_out_xcount_opt(size) __deref_out_xcount(size) _Post_ __deref __exceptthat __maybenull +#define __deref_out_xcount_part_opt(size,length) __deref_out_xcount_part(size,length) _Post_ __deref __exceptthat __maybenull +#define __deref_out_xcount_full_opt(size) __deref_out_xcount_full(size) _Post_ __deref __exceptthat __maybenull +#define __deref_inout_xcount_opt(size) __deref_inout_xcount(size) _Pre_ __deref __exceptthat __maybenull _Post_ __deref __exceptthat __maybenull +#define __deref_inout_xcount_part_opt(size,length) __deref_inout_xcount_part(size,length) _Pre_ __deref __exceptthat __maybenull _Post_ __deref __exceptthat __maybenull +#define __deref_inout_xcount_full_opt(size) __deref_inout_xcount_full(size) _Pre_ __deref __exceptthat __maybenull _Post_ __deref __exceptthat __maybenull +#define __deref_opt_xcount(size) __deref_xcount(size) __exceptthat __maybenull +#define __deref_opt_in __deref_in __exceptthat __maybenull +#define __deref_opt_in_ecount(size) __deref_in_ecount(size) __exceptthat __maybenull +#define __deref_opt_in_bcount(size) __deref_in_bcount(size) __exceptthat __maybenull +#define __deref_opt_in_xcount(size) __deref_in_xcount(size) __exceptthat __maybenull +#define __deref_opt_out_xcount(size) __deref_out_xcount(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_part(size,length) __deref_out_xcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_out_xcount_full(size) __deref_out_xcount_full(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount(size) __deref_inout_xcount(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_part(size,length) __deref_inout_xcount_part(size,length) __exceptthat __maybenull +#define __deref_opt_inout_xcount_full(size) __deref_inout_xcount_full(size) __exceptthat __maybenull +#define __deref_opt_xcount_opt(size) __deref_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_opt __deref_in_opt __exceptthat __maybenull +#define __deref_opt_in_ecount_opt(size) __deref_in_ecount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_bcount_opt(size) __deref_in_bcount_opt(size) __exceptthat __maybenull +#define __deref_opt_in_xcount_opt(size) __deref_in_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_opt(size) __deref_out_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_out_xcount_part_opt(size,length) __deref_out_xcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_out_xcount_full_opt(size) __deref_out_xcount_full_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_opt(size) __deref_inout_xcount_opt(size) __exceptthat __maybenull +#define __deref_opt_inout_xcount_part_opt(size,length) __deref_inout_xcount_part_opt(size,length) __exceptthat __maybenull +#define __deref_opt_inout_xcount_full_opt(size) __deref_inout_xcount_full_opt(size) __exceptthat __maybenull + +#define __deref_in_ecount_iterator(size, incr) __inout _Pre_ __deref __elem_readableTo(size) __deref_out_range(==, _Old_(*_Curr_) + incr) +#define __deref_out_ecount_iterator(size, incr) __inout _Pre_ __deref __elem_writableTo(size) __deref_out_range(==, _Old_(*_Curr_) + incr) +#define __deref_inout_ecount_iterator(size, incr) __inout _Pre_ __deref __elem_readableTo(size) _Pre_ __deref __elem_writableTo(size) __deref_out_range(==, _Old_(*_Curr_) + incr) + +#define __post_bcount(size) _Post_ __byte_writableTo(size) +#define __post_ecount(size) _Post_ __elem_writableTo(size) + +#define __deref_realloc_bcount(insize, outsize) __inout _Pre_ __deref __byte_readableTo(insize) _Post_ __deref __byte_writableTo(outsize) + +/* __in_ecount_or_z(c) specifies semantics like strncmp, where a string + * parameter is either null terminated, or valid up to c elements. + */ +#define __in_ecount_or_z(c) _When_(_String_length_(_Curr_) < (c), __in_z) \ + _When_(_String_length_(_Curr_) >= (c), __in_ecount(c)) + + +/* Provide default definition to be overridden when needed */ +#define __post_nullnullterminated + +/* Must protect redfinitions of macros to workaround rc.exe issues. */ +#ifndef RC_INVOKED + +#undef __nullnullterminated +#define __nullnullterminated __inexpressible_readableTo("string terminated by two nulls") __nullterminated + +#undef __post_nullnullterminated +#define __post_nullnullterminated _Post_ __inexpressible_readableTo("string terminated by two nulls") _Post_ __nullterminated + +#endif +#endif //__SAL_H_FULL_VER <= 140050727 + +/************************************************************************ + New extensions to sal.h follow here. +*************************************************************************/ + +#if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) + +#define __file_parser(typ) _SA_annotes2(SAL_file_parser,"function",typ) +#define __file_parser_class(typ) _SA_annotes2(SAL_file_parser,"class",typ) +#define __file_parser_library(typ) extern int _SA_annotes2(SAL_file_parser, "library", typ) __iSALFileParserLibrary##typ; +#define __source_code_content(typ) extern int _SA_annotes1(SAL_source_code_content, typ) __iSAL_Source_Code_Content##typ; +#define __class_code_content(typ) _SA_annotes1(SAL_class_code_content, typ) +#define __analysis_assert(e) __assume(e) +#define __analysis_hint(hint) _SA_annotes1(SAL_analysisHint, hint) +// For "breakpoint": doesn't return as far as analysis is concerned. +#define __analysis_noreturn __declspec(noreturn) +/* Internal defintions */ +#define __inner_data_source(src_raw) _SA_annotes1(SAL_untrusted_data_source,src_raw) +#define __inner_this_data_source(src_raw) _SA_annotes1(SAL_untrusted_data_source_this,src_raw) +#define __inner_out_validated(typ_raw) _Post_ _SA_annotes1(SAL_validated,typ_raw) +#define __inner_this_out_validated(typ_raw) _SA_annotes1(SAL_validated_this,typ_raw) +#define __inner_assume_validated_dec __inline __nothrow void __AssumeValidated(__inner_out_validated("BY_DESIGN") const void *p) {p;} +#define __inner_assume_validated(p) __AssumeValidated(p) +#define __inner_transfer(formal) _SA_annotes1(SAL_transfer_adt_property_from,formal) +#define __inner_encoded _SA_annotes0(SAL_encoded) + +#if defined(_MSC_EXTENSIONS) || defined(_PREFAST_) || defined(OACR) +#define __inner_adt_prop(adt,prop) _SA_annotes2(SAL_adt, adt,prop) +#define __inner_adt_add_prop(adt,prop) _SA_annotes2(SAL_add_adt_property,adt,prop) +#define __inner_adt_remove_prop(adt,prop) _SA_annotes2(SAL_remove_adt_property,adt,prop) +#define __inner_adt_transfer_prop(arg) _SA_annotes1(SAL_transfer_adt_property_from,arg) +#define __inner_adt_type_props(typ) _SA_annotes1(SAL_post_type,typ) +#define __inner_volatile _SA_annotes0(SAL_volatile) +#define __inner_nonvolatile _SA_annotes0(SAL_nonvolatile) +#define __inner_possibly_notnullterminated _SA_annotes1(SAL_nullTerminated,__maybe) +#define __inner_analysis_assume_nullterminated_dec __inline __nothrow void __AnalysisAssumeNullterminated(_Post_ __nullterminated void *p) {*(char*)p=0;} +#define __inner_analysis_assume_nullterminated(x) __AnalysisAssumeNullterminated(x); +#endif + +#else + +#define __file_parser(typ) +#define __file_parser_class(typ) +#define __file_parser_library(typ) +#define __source_code_content(typ) +#define __class_code_content(typ) +#define __analysis_assert(e) +#define __analysis_hint(hint) +#define __analysis_noreturn +/* Internal defintions */ +#define __inner_data_source(src_raw) +#define __inner_this_data_source(src_raw) +#define __inner_out_validated(typ_raw) +#define __inner_this_out_validated(typ_raw) +#define __inner_assume_validated_dec +#define __inner_assume_validated(p) +#define __inner_transfer(formal) +#define __inner_encoded +#define __inner_adt_prop(adt,prop) +#define __inner_adt_add_prop(adt,prop) +#define __inner_adt_remove_prop(adt,prop) +#define __inner_adt_transfer_prop(arg) +#define __inner_adt_type_props(typ) +#define __inner_volatile +#define __inner_nonvolatile +#define __inner_possibly_notnullterminated +#define __inner_analysis_assume_nullterminated_dec +#define __inner_analysis_assume_nullterminated(x) + +#endif // #if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) + +#define __field_ecount(size) __notnull __elem_writableTo(size) +#define __field_bcount(size) __notnull __byte_writableTo(size) +#define __field_xcount(size) __notnull __inexpressible_writableTo(size) + +#define __field_ecount_opt(size) __maybenull __elem_writableTo(size) +#define __field_bcount_opt(size) __maybenull __byte_writableTo(size) +#define __field_xcount_opt(size) __maybenull __inexpressible_writableTo(size) + +#define __field_ecount_part(size,init) __notnull __elem_writableTo(size) __elem_readableTo(init) +#define __field_bcount_part(size,init) __notnull __byte_writableTo(size) __byte_readableTo(init) +#define __field_xcount_part(size,init) __notnull __inexpressible_writableTo(size) __inexpressible_readableTo(init) + +#define __field_ecount_part_opt(size,init) __maybenull __elem_writableTo(size) __elem_readableTo(init) +#define __field_bcount_part_opt(size,init) __maybenull __byte_writableTo(size) __byte_readableTo(init) +#define __field_xcount_part_opt(size,init) __maybenull __inexpressible_writableTo(size) __inexpressible_readableTo(init) + +#define __field_ecount_full(size) __field_ecount_part(size,size) +#define __field_bcount_full(size) __field_bcount_part(size,size) +#define __field_xcount_full(size) __field_xcount_part(size,size) + +#define __field_ecount_full_opt(size) __field_ecount_part_opt(size,size) +#define __field_bcount_full_opt(size) __field_bcount_part_opt(size,size) +#define __field_xcount_full_opt(size) __field_xcount_part_opt(size,size) + +#define __field_nullterminated __nullterminated + +#define __struct_bcount(size) __byte_writableTo(size) +#define __struct_xcount(size) __inexpressible_writableTo(size) + +#define __out_awcount(expr,size) _Pre_ __notnull \ + __byte_writableTo((expr) ? (size) : (size) * 2) \ + _Post_ __valid __refparam +#define __in_awcount(expr,size) _Pre_ __valid \ + _Pre_ _Notref_ __deref __readonly \ + __byte_readableTo((expr) ? (size) : (size) * 2) +#define __post_invalid _Post_ __notvalid +/* integer related macros */ +#define __allocator __inner_allocator +#ifndef PAL_STDCPP_COMPAT +#define __deallocate(kind) _Pre_ __notnull __post_invalid +#define __deallocate_opt(kind) _Pre_ __maybenull __post_invalid +#endif +#define __bound __inner_bound +#define __range(lb,ub) __inner_range(lb,ub) +#define __in_bound _Pre_ __inner_bound +#define __out_bound _Post_ __inner_bound +#define __deref_out_bound _Post_ __deref __inner_bound +#define __in_range(lb,ub) _Pre_ __inner_range(lb,ub) +#define __out_range(lb,ub) _Post_ __inner_range(lb,ub) +#define __deref_in_range(lb,ub) _Pre_ __deref __inner_range(lb,ub) +#define __deref_out_range(lb,ub) _Post_ __deref __inner_range(lb,ub) +#define __deref_inout_range(lb,ub) __deref_in_range(lb,ub) __deref_out_range(lb,ub) +#define __field_range(lb,ub) __range(lb,ub) +#define __field_data_source(src_sym) __inner_data_source(#src_sym) + +#define __range_max(a,b) __range(==, a > b ? a : b) +#define __range_min(a,b) __range(==, a < b ? a : b) + + +/* Penetration review macros */ +#define __in_data_source(src_sym) _Pre_ __inner_data_source(#src_sym) +#define __out_data_source(src_sym) _Post_ __inner_data_source(#src_sym) +#define __out_validated(typ_sym) __inner_out_validated(#typ_sym) +#define __this_out_data_source(src_sym) __inner_this_data_source(#src_sym) +#define __this_out_validated(typ_sym) __inner_this_out_validated(#typ_sym) +#define __transfer(formal) _Post_ __inner_transfer(formal) +#define __rpc_entry __inner_control_entrypoint(RPC) +#define __kernel_entry __inner_control_entrypoint(UserToKernel) +#define __gdi_entry __inner_control_entrypoint(GDI) +#define __encoded_pointer __inner_encoded +#define __encoded_array __inner_encoded +#define __field_encoded_pointer __inner_encoded +#define __field_encoded_array __inner_encoded +#if defined(_MSC_EXTENSIONS) || defined(_PREFAST_) || defined(OACR) +#define __type_has_adt_prop(adt,prop) __inner_adt_prop(adt,prop) +#define __out_has_adt_prop(adt,prop) _Post_ __inner_adt_add_prop(adt,prop) +#define __out_not_has_adt_prop(adt,prop) _Post_ __inner_adt_remove_prop(adt,prop) +#define __out_transfer_adt_prop(arg) _Post_ __inner_adt_transfer_prop(arg) +#define __out_has_type_adt_props(typ) _Post_ __inner_adt_type_props(typ) + +/* useful PFD related macros */ +#define __possibly_notnullterminated __inner_possibly_notnullterminated + +/* Windows Internal */ +#define __volatile __inner_volatile +#define __nonvolatile __inner_nonvolatile +#else +#define __out_has_type_adt_props(typ) /* nothing */ +#endif +#define __deref_volatile __deref __volatile +#define __deref_nonvolatile __deref __nonvolatile + +/* declare stub functions for macros */ +__inner_assume_validated_dec +__inner_assume_bound_dec +__inner_analysis_assume_nullterminated_dec +#define __analysis_assume_nullterminated(x) __inner_analysis_assume_nullterminated(x) +#define __assume_validated(p) __inner_assume_validated(p) +#define __assume_bound(i) __inner_assume_bound(i) + + +/************************************************************************** +* SAL 2 extensions for Windows-specific APIs. +***************************************************************************/ + +// Annotation for parameters that are not used in any way by the function. +// Unlike _Reserved_, an _Unreferenced_parameter_ pointer need not be NULL. +#ifndef _Unreferenced_parameter_ +#define _Unreferenced_parameter_ _Const_ +#endif + +// Pointer parameters that are freed by the function, and thus the pointed-to +// memory should not be used after return. +#ifndef _Frees_ptr_ +#define _Frees_ptr_ _Pre_notnull_ _Post_ptr_invalid_ +#endif +#ifndef _Frees_ptr_opt_ +#define _Frees_ptr_opt_ _Pre_maybenull_ _Post_ptr_invalid_ +#endif + +// NLS APIs allow strings to be specified either by an element count or +// null termination. Unlike _In_reads_or_z_, this is not whichever comes +// first, but based on whether the size is negative or not. +#define _In_NLS_string_(size) _When_((size) < 0, _In_z_) \ + _When_((size) >= 0, _In_reads_(size)) + + +// Minifilter CompletionContext parameters on the pre-operation callback +// default to NULL. For return type FLT_PREOP_SUCCESS_WITH_CALLBACK or +// FLT_PREOP_SYNCHRONIZE, it may be set to NULL or a valid pointer. For all +// other returns, it must be NULL. +#define _Flt_CompletionContext_Outptr_ \ + _Outptr_result_maybenull_ _Pre_valid_ \ + _At_(*_Curr_, _Pre_null_ \ + _When_(return != FLT_PREOP_SUCCESS_WITH_CALLBACK && return != FLT_PREOP_SYNCHRONIZE, _Post_null_)) + +// Minifilter ConnectionCookie parameters on the port connect notify callback +// default to NULL. On successful return, it may be set to NULL or non-NULL, +// but it must be NULL on failure. +#define _Flt_ConnectionCookie_Outptr_ \ + _Outptr_result_maybenull_ _Pre_valid_ \ + _At_(*_Curr_, _Pre_null_ _On_failure_(_Post_null_)) + + +// +// A common pattern is to pass an "_Inout_ PCHAR* ppBuf" of size "_Inout_ DWORD* pSize" +// to a function that writes to **pBuf, incrementing *ppBuf to point to one +// past the last written byte. Thus the length of the write is +// (*ppBuf - Old(*ppBuf)). The size of the remaining unwritten capacity +// is written to *pSize. +// +// This pattern is frequently used when progressively filling a +// large buffer in chunks +// (e.g. when reading from a network interface in a driver). +// +// It is expected that these supplementary annotations would be used inside an +// _At_, like so: +// +// _At_(*ppBuf, _Writes_and_advances_ptr_(*pBufSize)) +// HRESULT WriteChunkOfData(_Inout_ PCHAR* ppBuf, _Inout_ DWORD* pBufSize); +// +#ifndef _Writes_and_advances_ptr_ +#define _Writes_and_advances_ptr_(size) \ + _At_((void*)_Curr_, _Inout_) \ + _At_(_Curr_, \ + _Pre_writable_size_(size) \ + _Post_writable_size_(size) \ + _Post_satisfies_(_Curr_ - _Old_(_Curr_) == size)) \ + _At_(_Old_(_Curr_), \ + _Post_readable_size_(_Old_(size) - size)) +#endif + +#ifndef _Writes_bytes_and_advances_ptr_ +#define _Writes_bytes_and_advances_ptr_(size) \ + _At_((void*)_Curr_, _Inout_) \ + _At_(_Curr_, \ + _Pre_writable_byte_size_(size) \ + _Post_writable_byte_size_(size) \ + _Post_satisfies_(((char*)_Curr_) - ((void*)_Old_(_Curr_)) == size)) \ + _At_(_Old_(_Curr_), \ + _Post_readable_byte_size_(_Old_(size) - size)) +#endif + +// +// Gets the current error code (as returned by GetLastError()), and stores +// in _Curr_ as a postcondition. This is currently approximated by assuming +// that GetLastError() always returns a failed error code. This is not a +// completely accurate approximation, but reasonable. +// +#define _Post_equals_last_error_ _Post_satisfies_(_Curr_ != 0) + +#ifdef __cplusplus +} +#endif + +#ifdef _PREFIX_ +/************************************************************************** +* Defintion of __pfx_assume and __pfx_assert. Thse should be the only +* defintions of these functions. +***************************************************************************/ +#if __cplusplus +extern "C" void __pfx_assert(bool, const char *); +extern "C" void __pfx_assume(bool, const char *); +#else +void __pfx_assert(int, const char *); +void __pfx_assume(int, const char *); +#endif +/************************************************************************** +* Redefintion of __analysis_assume and __analysis_assert for PREFIX build +**************************************************************************/ +#undef __analysis_assume +#undef __analysis_assert +#define __analysis_assume(e) (__pfx_assume(e,"pfx_assume"),__assume(e)); +#define __analysis_assert(e) (__pfx_assert(e,"pfx_assert"),__assume(e)); +#endif /* ifdef _PREFIX_ */ + +/************************************************************************** +* This include should always be the last thing in this file. +* Must avoid redfinitions of macros to workaround rc.exe issues. +***************************************************************************/ +#if !(defined(RC_INVOKED) || defined(SORTPP_PASS)) +#include +#endif /* if !(defined(RC_INVOKED) || defined(SORTPP_PASS)) */ + +/* + If no SAL 2 appears to have been defined (_Outptr_ is a representative choice) + then we must be operating in a downlevel build environment (such as VS10). + We also test against the compiler version to identify a downlevel environment, + as VS11 is the minimum required for SAL 2 support. + + If we are operating in a downlevel build environment (such as VS10) + we need to undefine the following symbols before including driverspecs.h + or we will end up referencing SAL 2 implementation symbols and cause + build failures. +*/ +#if (!defined(_Outptr_) || _MSC_VER <= 1600) && !( defined( MIDL_PASS ) || defined(__midl) || defined(RC_INVOKED) ) /*IFSTRIP=IGN*/ +#undef __ANNOTATION +#define __ANNOTATION(fun) /* fun */ +#undef __PRIMOP +#define __PRIMOP(type, fun) +#endif /* !defined(_Outptr_) || _MSC_VER <= 1600 */ + +/* + If no SAL 2 appears to have been defined (_Outptr_ is a representative choice) + then we must be operating in a downlevel build environment (such as VS10). + We also test against the compiler version to identify a downlevel environment, + as VS11 is the minimum required for SAL 2 support. + + If we are in a downlevel environment, we can go ahead and include no_sal2.h + to make all of SAL 2 no-ops to ensure no build failures. +*/ +#if (!defined(_Outptr_) || _MSC_VER <= 1600) && !( defined( MIDL_PASS ) || defined(__midl) || defined(RC_INVOKED) ) && !( defined( _SDV_ ) ) /*IFSTRIP=IGN*/ +#include +#endif /* !defined(_Outptr_) || _MSC_VER <= 1600 */ + +#endif /* #ifndef SPECSTRINGS_H */ + + diff --git a/lib/coreclr/src/pal/inc/rt/specstrings_adt.h b/lib/coreclr/src/pal/inc/rt/specstrings_adt.h new file mode 100644 index 0000000000..b3b949273a --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/specstrings_adt.h @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// + +// +#pragma once +/************************************************************************* +* DEFINITIONS OF NEW TYPES +*************************************************************************/ +#if !defined(__midl) +#define __$compname_props \ + __type_has_adt_prop(compname,nullterminated) \ + __type_has_adt_prop(compname,valid_schars) \ + __type_has_adt_prop(compname,correct_len) \ + __nullterminated +#if defined(UNICODE) || defined(_UNICODE) +#define __$TCHAR unsigned short +#else +#define __$TCHAR char +#endif +// DEVDIV: Windows SDK Vista RTM update: Ignore C4956 warning when compiling with /clr:safe flag +#ifdef _MSC_VER +#pragma warning( disable : 4956 ) +#endif // _MSC_VER +typedef __$compname_props char* ValidCompNameA; +typedef __$compname_props unsigned short* ValidCompNameW; +typedef __$compname_props const unsigned short* ConstValidCompNameW; +typedef __$compname_props __$TCHAR* SAL_ValidCompNameT; +typedef __$compname_props const __$TCHAR* SAL_ConstValidCompNameT; +#ifdef _MSC_VER +#pragma warning(default:4956) +#endif // _MSC_VER +#undef __$compname_props +#undef __$TCHAR +#endif + +/************************************************************************* +* DEFINITIONS OF INLINE FUNCTIONS FOR CASTING TO THE NEW TYPES : USER +*************************************************************************/ +#if (_MSC_VER >= 1000) && !defined(__midl) && defined(_PREFAST_) +#ifdef __cplusplus +extern "C" { +#endif +void __inline __nothrow __SAL_ValidCompNameA(__out_has_type_adt_props(ValidCompNameA) const void *expr) { expr;} +void __inline __nothrow __SAL_ValidCompNameW(__out_has_type_adt_props(ValidCompNameW) const void *expr) { expr;} +#ifdef __cplusplus +} +#endif +#define __assume_ValidCompNameA(expr) __SAL_ValidCompNameA(expr) +#define __assume_ValidCompNameW(expr) __SAL_ValidCompNameW(expr) +#else +#define __assume_ValidCompNameA(expr) +#define __assume_ValidCompNameW(expr) +#endif + + diff --git a/lib/coreclr/src/pal/inc/rt/specstrings_strict.h b/lib/coreclr/src/pal/inc/rt/specstrings_strict.h new file mode 100644 index 0000000000..08d323c589 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/specstrings_strict.h @@ -0,0 +1,1190 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/************************************************************************* +* This file documents all the macros approved for use in windows source +* code. It includes some experimental macros which should only be used by +* experts. +* +* DO NOT include this file directly. This file is include after +* specstrings.h. So we can undefine every possible old definition including +* private internal macros people should not be using, as well as macros from +* sal.h. Macros are redefined here in a way to cause syntax errors when used +* incorrectly during a normal build when specstrings.h is included and +* __SPECSTRINGS_STRICT_LEVEL is defined. +* +* There are several levels of strictness, each level includes the behavior of +* all previous levels. +* +* 0 - Disable strict checking +* 1 - Break on unapproved macros and misuse of statement +* macros such as __fallthrough (default) +* 2 - Deprecated some old macros that should not be used +* 3 - Use VS 2005 Source Annotation to make sure every macro +* is used in the right context. For example placing __in on a return +* parameter will result in an error. +* + +* +************************************************************************/ +#ifndef __SPECSTRINGS_STRICT_LEVEL +#define __SPECSTRINGS_STRICT_LEVEL 1 +#endif +/************************************************************************ +* Introduction +* +* specstrings.h provides a set of annotations to describe how a function uses +* its parameters - the assumptions it makes about them, and the guarantees it +* makes upon finishing. +* +* Annotations must be placed before a function parameter's type or its return +* type. There are two basic classes of common annotations buffer annotations +* and advanced annotations. Buffer annotations describe how functions use +* their pointer parameters, and advanced annotations either describe +* complex/unusual buffer behavior, or provide additional information about a +* parameter that is not otherwise expressible. +* +* Buffer Annotations +* +* The most important annotations in SpecStrings.h provide a consistent way to +* annotate buffer parameters or return values for a function. Each of these +* annotations describes a single buffer (which could be a string, a +* fixed-length or variable-length array, or just a pointer) that the function +* interacts with: where it is, how large it is, how much is initialized, and +* what the function does with it. +* +* The appropriate macro for a given buffer can be constructed using the table +* below. Just pick the appropriate values from each category, and combine +* them together with a leading underscore. Some combinations of values do not +* make sense as buffer annotations. Only meaningful annotations can be added +* to your code; for a list of these, see the buffer annotation definitions +* section. +* +* Only a single buffer annotation should be used for each parameter. +* +* |------------|------------|---------|--------|----------|---------------| +* | Level | Usage | Size | Output | Optional | Parameters | +* |------------|------------|---------|--------|----------|---------------| +* | <> | <> | <> | <> | <> | <> | +* | _deref | _in | _ecount | _full | _opt | (size) | +* | _deref_opt | _out | _bcount | _part | | (size,length) | +* | | _inout | | | | | +* | | | | | | | +* |------------|------------|---------|--------|----------|---------------| +* +* Note: "<>" represents the empty string. +* +* Level: Describes the buffer pointer's level of indirection from the +* parameter or return value 'p'. +* +* <> : p is the buffer pointer. +* _deref : *p is the buffer pointer. p must not be NULL. +* _deref_opt : *p may be the buffer pointer. p may be NULL, in which case the +* rest of the annotation is ignored. +* +* Usage: Describes how the function uses the buffer. +* +* <> : The buffer is not accessed. If used on the return value or with +* _deref, the function will provide the buffer, and it will be uninitialized +* at exit. Otherwise, the caller must provide the buffer. This should only +* be used for alloc and free functions. +* +* _in : The function will only read from the buffer. The caller must provide +* the buffer and initialize it. +* +* _out : The function will only write to the buffer. If used on the return +* value or with _deref, the function will provide the buffer and initialize +* it. Otherwise, the caller must provide the buffer, and the function will +* initialize it. +* +* _inout : The function may freely read from and write to the buffer. The +* caller must provide the buffer and initialize it. If used with _deref, the +* buffer may be reallocated by the function. +* +* Size: Describes the total size of the buffer. This may be less than the +* space actually allocated for the buffer, in which case it describes the +* accessible amount. +* +* <> : No buffer size is given. If the type specifies the buffer size (such +* as with LPSTR and LPWSTR), that amount is used. Otherwise, the buffer is +* one element long. Must be used with _in, _out, or _inout. +* +* _ecount : The buffer size is an explicit element count. +* +* _bcount : The buffer size is an explicit byte count. +* +* Output: Describes how much of the buffer will be initialized by the +* function. For _inout buffers, this also describes how much is initialized +* at entry. Omit this category for _in buffers; they must be fully +* initialized by the caller. +* +* <> : The type specifies how much is initialized. For instance, a function +* initializing an LPWSTR must NULL-terminate the string. +* +* _full : The function initializes the entire buffer. +* +* _part : The function initializes part of the buffer, and explicitly +* indicates how much. +* +* Optional: Describes if the buffer itself is optional. +* +* <> : The pointer to the buffer must not be NULL. +* +* _opt : The pointer to the buffer might be NULL. It will be checked before +* being dereferenced. +* +* Parameters: Gives explicit counts for the size and length of the buffer. +* +* <> : There is no explicit count. Use when neither _ecount nor _bcount is +* used. +* +* (size) : Only the buffer's total size is given. Use with _ecount or _bcount +* but not _part. +* +* (size,length) : The buffer's total size and initialized length are +* given. Use with _ecount_part and _bcount_part. +* +* ---------------------------------------------------------------------------- +* Buffer Annotation Examples +* +* LWSTDAPI_(BOOL) StrToIntExA( +* LPCSTR pszString, // No annotation required, const implies __in. +* DWORD dwFlags, +* __out int *piRet // A pointer whose dereference will be filled in. +* ); +* +* void MyPaintingFunction( +* __in HWND hwndControl, // An initialized read-only parameter. +* __in_opt HDC hdcOptional, // An initialized read-only parameter that +* // might be NULL. +* __inout IPropertyStore *ppsStore // An initialized parameter that +* // may be freely used and modified. +* ); +* +* LWSTDAPI_(BOOL) PathCompactPathExA( +* __out_ecount(cchMax) LPSTR pszOut, // A string buffer with cch elements +* // that will be '\0' terminated +* // on exit. +* LPCSTR pszSrc, // No annotation required, +* // const implies __in. +* UINT cchMax, +* DWORD dwFlags +* ); +* +* HRESULT SHLocalAllocBytes( +* size_t cb, +* __deref_bcount(cb) T **ppv // A pointer whose dereference will be set +* // to an uninitialized buffer with cb bytes. +* ); +* +* __inout_bcount_full(cb) : A buffer with cb elements that is fully +* initialized at entry and exit, and may be written to by this function. +* +* __out_ecount_part(count, *countOut) : A buffer with count elements that +* will be partially initialized by this function. The function indicates how +* much it initialized by setting *countOut. +* +************************************************************************/ + +#if (_MSC_VER >= 1400) && !defined(__midl) && !defined(_PREFAST_) && (__SPECSTRINGS_STRICT_LEVEL > 0) +#pragma once +#include +#define __ecount(size) _SAL_VERSION_CHECK(__ecount) +#define __bcount(size) _SAL_VERSION_CHECK(__bcount) +#define __xcount(size) _SAL_VERSION_CHECK(__xcount) +#define __in _SAL_VERSION_CHECK(__in) +#define __in_ecount(size) _SAL_VERSION_CHECK(__in_ecount) +#define __in_bcount(size) _SAL_VERSION_CHECK(__in_bcount) +#define __in_xcount(size) _SAL_VERSION_CHECK(__in_xcount) +#define __in_z _SAL_VERSION_CHECK(__in_z) +#define __in_ecount_z(size) _SAL_VERSION_CHECK(__in_ecount_z) +#define __in_bcount_z(size) _SAL_VERSION_CHECK(__in_bcount_z) +#define __out _SAL_VERSION_CHECK(__out) +#define __out_ecount(size) _SAL_VERSION_CHECK(__out_ecount) +#define __out_bcount(size) _SAL_VERSION_CHECK(__out_bcount) +#define __out_xcount(size) _SAL_VERSION_CHECK(__out_xcount) +#define __out_ecount_part(size,len) _SAL_VERSION_CHECK(__out_ecount_part) +#define __out_bcount_part(size,len) _SAL_VERSION_CHECK(__out_bcount_part) +#define __out_xcount_part(size,len) _SAL_VERSION_CHECK(__out_xcount_part) +#define __out_ecount_full(size) _SAL_VERSION_CHECK(__out_ecount_full) +#define __out_bcount_full(size) _SAL_VERSION_CHECK(__out_bcount_full) +#define __out_xcount_full(size) _SAL_VERSION_CHECK(__out_xcount_full) +#define __out_z _SAL_VERSION_CHECK(__out_z) +#define __out_ecount_z(size) _SAL_VERSION_CHECK(__out_ecount_z) +#define __out_bcount_z(size) _SAL_VERSION_CHECK(__out_bcount_z) +#define __inout _SAL_VERSION_CHECK(__inout) +#define __inout_ecount(size) _SAL_VERSION_CHECK(__inout_ecount) +#define __inout_bcount(size) _SAL_VERSION_CHECK(__inout_bcount) +#define __inout_xcount(size) _SAL_VERSION_CHECK(__inout_xcount) +#define __inout_ecount_part(size,len) _SAL_VERSION_CHECK(__inout_ecount_part) +#define __inout_bcount_part(size,len) _SAL_VERSION_CHECK(__inout_bcount_part) +#define __inout_xcount_part(size,len) _SAL_VERSION_CHECK(__inout_xcount_part) +#define __inout_ecount_full(size) _SAL_VERSION_CHECK(__inout_ecount_full) +#define __inout_bcount_full(size) _SAL_VERSION_CHECK(__inout_bcount_full) +#define __inout_xcount_full(size) _SAL_VERSION_CHECK(__inout_xcount_full) +#define __inout_z __allowed(on_parameter) +#define __inout_ecount_z(size) __allowed(on_parameter) +#define __inout_bcount_z(size) __allowed(on_parameter) +#define __ecount_opt(size) __allowed(on_parameter) +#define __bcount_opt(size) __allowed(on_parameter) +#define __xcount_opt(size) __allowed(on_parameter) +#define __in_opt _SAL_VERSION_CHECK(__in_opt) +#define __in_ecount_opt(size) _SAL_VERSION_CHECK(__in_ecount_opt) +#define __in_bcount_opt(size) _SAL_VERSION_CHECK(__in_bcount_opt) +#define __in_z_opt __allowed(on_parameter) +#define __in_ecount_z_opt(size) __allowed(on_parameter) +#define __in_bcount_z_opt(size) __allowed(on_parameter) +#define __in_xcount_opt(size) __allowed(on_parameter) +#define __out_opt _SAL_VERSION_CHECK(__out_opt) +#define __out_ecount_opt(size) _SAL_VERSION_CHECK(__out_ecount_opt) +#define __out_bcount_opt(size) _SAL_VERSION_CHECK(__out_bcount_opt) +#define __out_xcount_opt(size) __allowed(on_parameter) +#define __out_ecount_part_opt(size,len) __allowed(on_parameter) +#define __out_bcount_part_opt(size,len) __allowed(on_parameter) +#define __out_xcount_part_opt(size,len) __allowed(on_parameter) +#define __out_ecount_full_opt(size) __allowed(on_parameter) +#define __out_bcount_full_opt(size) __allowed(on_parameter) +#define __out_xcount_full_opt(size) __allowed(on_parameter) +#define __out_ecount_z_opt(size) __allowed(on_parameter) +#define __out_bcount_z_opt(size) __allowed(on_parameter) +#define __inout_opt _SAL_VERSION_CHECK(__inout_opt) +#define __inout_ecount_opt(size) _SAL_VERSION_CHECK(__inout_ecount_opt) +#define __inout_bcount_opt(size) _SAL_VERSION_CHECK(__inout_bcount_opt) +#define __inout_xcount_opt(size) _SAL_VERSION_CHECK(__inout_xcount_opt) +#define __inout_ecount_part_opt(size,len) _SAL_VERSION_CHECK(__inout_ecount_part_opt) +#define __inout_bcount_part_opt(size,len) _SAL_VERSION_CHECK(__inout_bcount_part_opt) +#define __inout_xcount_part_opt(size,len) _SAL_VERSION_CHECK(__inout_xcount_part_opt) +#define __inout_ecount_full_opt(size) _SAL_VERSION_CHECK(__inout_ecount_full_opt) +#define __inout_bcount_full_opt(size) _SAL_VERSION_CHECK(__inout_bcount_full_opt) +#define __inout_xcount_full_opt(size) _SAL_VERSION_CHECK(__inout_xcount_full_opt) +#define __inout_z_opt __allowed(on_parameter) +#define __inout_ecount_z_opt(size) __allowed(on_parameter) +#define __inout_ecount_z_opt(size) __allowed(on_parameter) +#define __inout_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_ecount(size) __allowed(on_parameter) +#define __deref_bcount(size) __allowed(on_parameter) +#define __deref_xcount(size) __allowed(on_parameter) +#define __deref_in _SAL_VERSION_CHECK(__deref_in) +#define __deref_in_ecount(size) _SAL_VERSION_CHECK(__deref_in_ecount) +#define __deref_in_bcount(size) _SAL_VERSION_CHECK(__deref_in_bcount) +#define __deref_in_xcount(size) _SAL_VERSION_CHECK(__deref_in_xcount) +#define __deref_out _SAL_VERSION_CHECK(__deref_out) +#define __deref_out_ecount(size) _SAL_VERSION_CHECK(__deref_out_ecount) +#define __deref_out_bcount(size) _SAL_VERSION_CHECK(__deref_out_bcount) +#define __deref_out_xcount(size) _SAL_VERSION_CHECK(__deref_out_xcount) +#define __deref_out_ecount_part(size,len) _SAL_VERSION_CHECK(__deref_out_ecount_part) +#define __deref_out_bcount_part(size,len) _SAL_VERSION_CHECK(__deref_out_bcount_part) +#define __deref_out_xcount_part(size,len) _SAL_VERSION_CHECK(__deref_out_xcount_part) +#define __deref_out_ecount_full(size) _SAL_VERSION_CHECK(__deref_out_ecount_full) +#define __deref_out_bcount_full(size) _SAL_VERSION_CHECK(__deref_out_bcount_full) +#define __deref_out_xcount_full(size) _SAL_VERSION_CHECK(__deref_out_xcount_full) +#define __deref_out_z __allowed(on_parameter) +#define __deref_out_ecount_z(size) __allowed(on_parameter) +#define __deref_out_bcount_z(size) __allowed(on_parameter) +#define __deref_inout _SAL_VERSION_CHECK(__deref_inout) +#define __deref_inout_ecount(size) _SAL_VERSION_CHECK(__deref_inout_ecount) +#define __deref_inout_bcount(size) _SAL_VERSION_CHECK(__deref_inout_bcount) +#define __deref_inout_xcount(size) _SAL_VERSION_CHECK(__deref_inout_xcount) +#define __deref_inout_ecount_part(size,len) __allowed(on_parameter) +#define __deref_inout_bcount_part(size,len) __allowed(on_parameter) +#define __deref_inout_xcount_part(size,len) __allowed(on_parameter) +#define __deref_inout_ecount_full(size) __allowed(on_parameter) +#define __deref_inout_bcount_full(size) __allowed(on_parameter) +#define __deref_inout_xcount_full(size) __allowed(on_parameter) +#define __deref_inout_z __allowed(on_parameter) +#define __deref_inout_ecount_z(size) __allowed(on_parameter) +#define __deref_inout_bcount_z(size) __allowed(on_parameter) +#define __deref_ecount_opt(size) __allowed(on_parameter) +#define __deref_bcount_opt(size) __allowed(on_parameter) +#define __deref_xcount_opt(size) __allowed(on_parameter) +#define __deref_in_opt __allowed(on_parameter) +#define __deref_in_opt_out __allowed(on_parameter) +#define __deref_in_ecount_opt(size) __allowed(on_parameter) +#define __deref_in_bcount_opt(size) __allowed(on_parameter) +#define __deref_in_xcount_opt(size) __allowed(on_parameter) +#define __deref_out_opt _SAL_VERSION_CHECK(__deref_out_opt) +#define __deref_out_ecount_opt(size) _SAL_VERSION_CHECK(__deref_out_ecount_opt) +#define __deref_out_bcount_opt(size) _SAL_VERSION_CHECK(__deref_out_bcount_opt) +#define __deref_out_xcount_opt(size) _SAL_VERSION_CHECK(__deref_out_xcount_opt) +#define __deref_out_ecount_part_opt(size,len) _SAL_VERSION_CHECK(__deref_out_ecount_part_opt) +#define __deref_out_bcount_part_opt(size,len) _SAL_VERSION_CHECK(__deref_out_bcount_part_opt) +#define __deref_out_xcount_part_opt(size,len) _SAL_VERSION_CHECK(__deref_out_xcount_part_opt) +#define __deref_out_ecount_full_opt(size) _SAL_VERSION_CHECK(__deref_out_ecount_full_opt) +#define __deref_out_bcount_full_opt(size) _SAL_VERSION_CHECK(__deref_out_bcount_full_opt) +#define __deref_out_xcount_full_opt(size) _SAL_VERSION_CHECK(__deref_out_xcount_full_opt) +#define __deref_out_z_opt __allowed(on_parameter) +#define __deref_out_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_out_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_inout_opt __allowed(on_parameter) +#define __deref_inout_ecount_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_opt(size) __allowed(on_parameter) +#define __deref_inout_xcount_opt(size) __allowed(on_parameter) +#define __deref_inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_inout_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_inout_z_opt __allowed(on_parameter) +#define __deref_inout_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_inout_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_ecount(size) __allowed(on_parameter) +#define __deref_opt_bcount(size) __allowed(on_parameter) +#define __deref_opt_xcount(size) __allowed(on_parameter) +#define __deref_opt_in __allowed(on_parameter) +#define __deref_opt_in_ecount(size) __allowed(on_parameter) +#define __deref_opt_in_bcount(size) __allowed(on_parameter) +#define __deref_opt_in_xcount(size) __allowed(on_parameter) +#define __deref_opt_out _SAL_VERSION_CHECK(__deref_opt_out) +#define __deref_opt_out_ecount(size) _SAL_VERSION_CHECK(__deref_opt_out_ecount) +#define __deref_opt_out_bcount(size) _SAL_VERSION_CHECK(__deref_opt_out_bcount) +#define __deref_opt_out_xcount(size) _SAL_VERSION_CHECK(__deref_opt_out_xcount) +#define __deref_opt_out_ecount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_bcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_xcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_out_ecount_full(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_full(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout __allowed(on_parameter) +#define __deref_opt_inout_ecount(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount(size) __allowed(on_parameter) +#define __deref_opt_inout_ecount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_bcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_xcount_part(size,len) __allowed(on_parameter) +#define __deref_opt_inout_ecount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_full(size) __allowed(on_parameter) +#define __deref_opt_inout_z __allowed(on_parameter) +#define __deref_opt_inout_ecount_z(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_z(size) __allowed(on_parameter) +#define __deref_opt_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_opt __allowed(on_parameter) +#define __deref_opt_in_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_in_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_opt __allowed(on_parameter) +#define __deref_opt_out_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_out_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_out_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_out_z_opt __allowed(on_parameter) +#define __deref_opt_out_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_out_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_opt __allowed(on_parameter) +#define __deref_opt_inout_ecount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_ecount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_bcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_xcount_part_opt(size,len) __allowed(on_parameter) +#define __deref_opt_inout_ecount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_xcount_full_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_z_opt __allowed(on_parameter) +#define __deref_opt_inout_ecount_z_opt(size) __allowed(on_parameter) +#define __deref_opt_inout_bcount_z_opt(size) __allowed(on_parameter) +#define __deref_in_ecount_iterator(size,incr) __allowed(on_parameter) +#define __deref_out_ecount_iterator(size,incr) __allowed(on_parameter) +#define __deref_inout_ecount_iterator(size,incr) __allowed(on_parameter) +#define __deref_realloc_bcount(insize,outsize) __allowed(on_parameter) + +/************************************************************************ +* SAL 2 _Ouptr_ family of annotations +************************************************************************/ + +#define _Outptr_ __allowed(on_parameter) +#define _Outptr_result_maybenull_ __allowed(on_parameter) +#define _Outptr_opt_ __allowed(on_parameter) +#define _Outptr_opt_result_maybenull_ __allowed(on_parameter) +#define _Outptr_result_z_ __allowed(on_parameter) +#define _Outptr_opt_result_z_ __allowed(on_parameter) +#define _Outptr_result_maybenull_z_ __allowed(on_parameter) +#define _Outptr_opt_result_maybenull_z_ __allowed(on_parameter) +#define _Outptr_result_nullonfailure_ __allowed(on_parameter) +#define _Outptr_opt_result_nullonfailure_ __allowed(on_parameter) +#define _COM_Outptr_ __allowed(on_parameter) +#define _COM_Outptr_result_maybenull_ __allowed(on_parameter) +#define _COM_Outptr_opt_ __allowed(on_parameter) +#define _COM_Outptr_opt_result_maybenull_ __allowed(on_parameter) +#define _Outptr_result_buffer_(size) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_(size) __allowed(on_parameter) +#define _Outptr_result_buffer_to_(size, count) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_to_(size, count) __allowed(on_parameter) +#define _Outptr_result_buffer_all_(size) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_all_(size) __allowed(on_parameter) +#define _Outptr_result_buffer_maybenull_(size) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_maybenull_(size) __allowed(on_parameter) +#define _Outptr_result_buffer_to_maybenull_(size, count) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_to_maybenull_(size, count) __allowed(on_parameter) +#define _Outptr_result_buffer_all_maybenull_(size) __allowed(on_parameter) +#define _Outptr_opt_result_buffer_all_maybenull_(size) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_(size) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_(size) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_to_(size, count) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_to_(size, count) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_all_(size) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_all_(size) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_maybenull_(size) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_maybenull_(size) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_to_maybenull_(size, count) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_to_maybenull_(size, count) __allowed(on_parameter) +#define _Outptr_result_bytebuffer_all_maybenull_(size) __allowed(on_parameter) +#define _Outptr_opt_result_bytebuffer_all_maybenull_(size) __allowed(on_parameter) + +/************************************************************************ +* Orcas SAL +************************************************************************/ +#define _Deref_out_ _SAL_VERSION_CHECK(_Deref_out_) +#define _Deref_out_opt_ _SAL_VERSION_CHECK(_Deref_out_opt_) +#define _Deref_opt_out_ _SAL_VERSION_CHECK(_Deref_opt_out_) +#define _Deref_opt_out_opt_ _SAL_VERSION_CHECK(_Deref_opt_out_opt_) +#define _In_count_(size) _SAL_VERSION_CHECK(_In_count_) +#define _In_opt_count_(size) _SAL_VERSION_CHECK(_In_opt_count_) +#define _In_bytecount_(size) _SAL_VERSION_CHECK(_In_bytecount_) +#define _In_opt_bytecount_(size) _SAL_VERSION_CHECK(_In_opt_bytecount_) +#define _Out_cap_(size) _SAL_VERSION_CHECK(_Out_cap_) +#define _Out_opt_cap_(size) _SAL_VERSION_CHECK(_Out_opt_cap_) +#define _Out_bytecap_(size) _SAL_VERSION_CHECK(_Out_bytecap_) +#define _Out_opt_bytecap_(size) _SAL_VERSION_CHECK(_Out_opt_bytecap_) +#define _Deref_post_count_(size) _SAL_VERSION_CHECK(_Deref_post_count_) +#define _Deref_post_opt_count_(size) _SAL_VERSION_CHECK(_Deref_post_opt_count_) +#define _Deref_post_bytecount_(size) _SAL_VERSION_CHECK(_Deref_post_bytecount_) +#define _Deref_post_opt_bytecount_(size) _SAL_VERSION_CHECK(_Deref_post_opt_bytecount_) +#define _Deref_post_cap_(size) _SAL_VERSION_CHECK(_Deref_post_cap_) +#define _Deref_post_opt_cap_(size) _SAL_VERSION_CHECK(_Deref_post_opt_cap_) +#define _Deref_post_bytecap_(size) _SAL_VERSION_CHECK(_Deref_post_bytecap_) +#define _Deref_post_opt_bytecap_(size) _SAL_VERSION_CHECK(_Deref_post_opt_bytecap_) + +/************************************************************************ +* Advanced Annotations +* +* Advanced annotations describe behavior that is not expressible with the +* regular buffer macros. These may be used either to annotate buffer +* parameters that involve complex or conditional behavior, or to enrich +* existing annotations with additional information. +* +* _At_(expr, annotes) : annotation list annotes applies to target 'expr' +* +* _When_(expr, annotes) : annotation list annotes applies when 'expr' is true +* +* __success(expr) T f() : indicates whether function f succeeded or +* not. If is true at exit, all the function's guarantees (as given +* by other annotations) must hold. If is false at exit, the caller +* should not expect any of the function's guarantees to hold. If not used, +* the function must always satisfy its guarantees. Added automatically to +* functions that indicate success in standard ways, such as by returning an +* HRESULT. +* +* __out_awcount(expr, size) T *p : Pointer p is a buffer whose size may be +* given in either bytes or elements. If is true, this acts like +* __out_bcount. If is false, this acts like __out_ecount. This +* should only be used to annotate old APIs. +* +* __in_awcount(expr, size) T* p : Pointer p is a buffer whose size may be given +* in either bytes or elements. If is true, this acts like +* __in_bcount. If is false, this acts like __in_ecount. This should +* only be used to annotate old APIs. +* +* __nullterminated T* p : Pointer p is a buffer that may be read or written +* up to and including the first '\0' character or pointer. May be used on +* typedefs, which marks valid (properly initialized) instances of that type +* as being null-terminated. +* +* __nullnullterminated T* p : Pointer p is a buffer that may be read or +* written up to and including the first sequence of two '\0' characters or +* pointers. May be used on typedefs, which marks valid instances of that +* type as being double-null terminated. +* +* __reserved T v : Value v must be 0/NULL, reserved for future use. +* +* __checkReturn T f(); : Return value of f must not be ignored by callers +* of this function. +* +* __typefix(ctype) T v : Value v should be treated as an instance of ctype, +* rather than its declared type when considering validity. +* +* __override T f(); : Specify C#-style 'override' behaviour for overriding +* virtual methods. +* +* __callback T f(); : Function f can be used as a function pointer. +* +* __format_string T p : Pointer p is a string that contains % markers in +* the style of printf. +* +* __blocksOn(resource) f(); : Function f blocks on the resource 'resource'. +* +* __fallthrough : Annotates switch statement labels where fall-through is +* desired, to distinguish from forgotten break statements. +* +* __range(low_bnd, up_bnd) int f(): The return from the function "f" must +* be in the inclusive numeric range [low_bnd, up_bnd]. +* +* __in_range(low_bnd, up_bnd) int i : Precondition that integer i must be +* in the inclusive numeric range [low_bnd, up_bnd]. +* +* __out_range(low_bnd, up_bnd) int i : Postcondition that integer i must be +* in the inclusive numeric range [low_bnd, up_bnd]. +* +* __deref_in_range(low_bnd, up_bnd) int* pi : Precondition that integer *pi +* must be in the inclusive numeric range [low_bnd, up_bnd]. +* +* __deref_out_range(low_bnd, up_bnd) int* pi : Postcondition that integer +* *pi must be in the inclusive numeric range [low_bnd, up_bnd]. +* +* __deref_inout_range(low_bnd, up_bnd) int* pi : Invariant that the integer +* *pi must be in the inclusive numeric range [low_bnd, up_bnd]. +* +* The first argument of a range macro may also be a C relational operator +* (<,>,!=, ==, <=, >=). +* +* __range(rel_op, j) int f(): Postcondition that "f() rel_op j" must be +* true. Note that j may be a expression known only at runtime. +* +* __in_range(rel_op, j) int i : Precondition that "i rel_op j" must be +* true. Note that j may be a expression known only at runtime. +* +* __out_range(rel_op, j) int i : Postcondition that integer "i rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __deref_in_range(rel_op, j) int *pi : Precondition that "*pi rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __deref_out_range(rel_op, j) int *pi : Postcondition that "*pi rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __deref_inout_range(rel_op, j) int *pi : Invariant that "*pi rel_op j" +* must be true. Note that j may be a expression known only at runtime. +* +* __range_max(a, b) int f(): Postcondition f acts as 'max', returns larger +* of a and b. Note that a and b may be expressions known only at runtime. +* +* __range_min(a, b) int f(): Postcondition f acts as 'min', returns smaller +* of a and b. Note that a and b may be expressions known only at runtime. +* +* __in_bound int i : Precondition that integer i must be bound, but the +* exact range can't be specified at compile time. __in_range should be +* used if the range can be explicitly stated. +* +* __out_bound int i : Postcondition that integer i must be bound, but the +* exact range can't be specified at compile time. __out_range should be +* used if the range can be explicitly stated. +* +* __deref_out_bound int pi : Postcondition that integer *pi must be bound, +* but the exact range can't be specified at compile time. +* __deref_out_range should be used if the range can be explicitly stated. +* +* __assume_bound(expr); : Assume that the expression is bound to some known +* range. This can be used to suppress integer overflow warnings on integral +* expressions that are known to be bound due to reasons not explicit in the +* code. Use as a statement in the body of a function. +* +* __analysis_assume_nulltermianted(expr); : Assume that the expression is +* a null terminated buffer. Use this to suppress tool noise specific to +* nulltermination warnings, and capture deeper invariants tools can not +* discover. +* +* __allocator void f(): Function allocates memory using an integral size +* argument +* +* void myfree(__deallocate(Mem) void *p) : Memory is freed, no longer usable +* upon return, and p may not be null. +* +* void myfree(__deallocate_opt(Mem) void *p) : Memory is freed, no longer +* usable upon return, and p may be null. +* +* void free(__post_invalid void* x): Mark memory as untouchable when +* function returns. +* +* ---------------------------------------------------------------------------- +* Advanced Annotation Examples +* +* __success(return == TRUE) LWSTDAPI_(BOOL) +* PathCanonicalizeA(__out_ecount(MAX_PATH) LPSTR pszBuf, LPCSTR pszPath); +* // pszBuf is only guaranteed to be null-terminated when TRUE is returned. +* +* // Initialized LPWSTRs are null-terminated strings. +* typedef __nullterminated WCHAR* LPWSTR; +* +* __out_ecount(cch) __typefix(LPWSTR) void *psz; +* // psz is a buffer parameter which will be a null-terminated WCHAR string +* // at exit, and which initially contains cch WCHARs. +* +************************************************************************/ +#define _At_(expr, annotes) __allowed(on_parameter_or_return) +#define _When_(expr, annotes) __allowed(on_parameter_or_return) +#define __success(expr) _SAL_VERSION_CHECK(__success) +#define __out_awcount(expr,size) __allowed(on_parameter) +#define __in_awcount(expr,size) __allowed(on_parameter) +#define __nullterminated _SAL_VERSION_CHECK(__nullterminated) +#define __nullnullterminated _SAL_VERSION_CHECK(__nullnullterminated) +#define __clr_reserved _SAL_VERSION_CHECK(__reserved) +#define __checkReturn _SAL_VERSION_CHECK(__checkReturn) +#define __typefix(ctype) __allowed(on_parameter_or_return) +#define __override __allowed(on_function) +#define __callback __allowed(on_function) +#define __format_string __allowed(on_parameter_or_return) +#define __blocksOn(resource) __allowed(on_function) +#define __fallthrough __allowed(as_statement) +#define __range(lb,ub) __allowed(on_return) +#define __in_range(lb,ub) _SAL_VERSION_CHECK(__in_range) +#define __out_range(lb,ub) _SAL_VERSION_CHECK(__out_range) +#define __deref_in_range(lb,ub) __allowed(on_parameter) +#define __deref_out_range(lb,ub) _SAL_VERSION_CHECK(__deref_out_range) +#define __deref_inout_range(lb,ub) __allowed(on_parameter) +#define __field_range(lb,ub) _SAL_VERSION_CHECK(__field_range) +#define __range_max(a,b) __allowed(on_return) +#define __range_min(a,b) __allowed(on_return) +#define __bound __allowed(on_return) +#define __in_bound __allowed(on_parameter) +#define __out_bound __allowed(on_parameter) +#define __deref_out_bound __allowed(on_parameter) +#define __assume_bound(i) __allowed(as_statement_with_arg(i)) +#define __analysis_assume_nullterminated(x) \ + __allowed(as_statement_with_arg(x)) +#define __allocator __allowed(on_function) +#define __deallocate(kind) __allowed(on_parameter) +#define __deallocate_opt(kind) __allowed(on_parameter) +#define __post_invalid __allowed(on_parameter_or_return) +#define __post_nullnullterminated \ + __allowed(on_parameter_or_return) +/*************************************************************************** +* Expert Macros +***************************************************************************/ +#define __null __allowed(on_typedecl) +#define __notnull __allowed(on_typedecl) +#define __maybenull __allowed(on_typedecl) +#define __exceptthat __allowed(on_typedecl) +/*************************************************************************** +* Macros to classify fields of structures. +* Structure Annotations +* +* The buffer annotations are a convenient way of describing +* relationships between buffers and their size on a function by +* function basis. Very often struct or class data members have similar +* invariants, which can be expressed directly on the type. +* +* Similar to our buffer annotations we can summarize all the various +* structure annotations by one choosing an element from each column of +* this table to build a composite annotation. +* +* +--------------------------------------------------+ +* | Selector | Units | Size/Init | Optional | +* |----------+---------+------------------+----------| +* | __field | _ecount | (size) | empty | +* |----------+---------+------------------+----------| +* | __struct | _bcount | _full(size) | _opt | +* |----------+---------+------------------+----------| +* | | _xcount | _part(size,init) | | +* +--------------------------------------------------+ +* +* Note that empty represents the empty string. Sometime arguments need +* to be "floated" to the left to give us a valid annotation name. For +* example the naive combination __field_ecount(size)_opt is actually +* written as __field_ecount_opt(size). Not all possible combinations +* are currently supported or sensible. See specstrings_strict.h for +* the currently supported set. Those that are supported are documented +* below. +* +*Summary of Elements +* +* Selector +* +* __field +* The annotation should only be placed in front +* of data members of structures and classes. The +* data members are pointers to a block of data. +* The annotations describe properties about the +* size of the block of data. This can be used for +* +* __struct +* The annotation should only be placed at the +* beginning of the definition of a structure or +* class. These annotations are used when a struct +* or class is used as a "header" that is +* allocated inline with a block of data and there +* is no apparent field that represents the tail +* end of the structure. +* +* Units +* +* _ecount +* All size and initialization values are in terms +* of elements of the appropriate type +* +* _bcount +* All size and initialization values are in terms +* of raw byte sizes. +* +* _xcount +* The size or initialization values cannot be +* properly expressed as a simple byte or element +* count, and instead a place holder is used to +* document the relationship. +* +* Size/Init +* All the size/init expressions can contain references to +* other fields in the struct or class. +* +* (size) +* The size of the buffer is determined by the +* expression size. Unless, the type of the buffer +* provides more information nothing is know about +* how much of this data is initialized. For +* example, if the data member happens to be a +* string type such as LPSTR. It is assumed that +* the data is initialized to the first '\0'. +* +* _full(size) +* The size of the buffer is determined by the +* expression size and all the data in the buffer +* is guaranteed to be initialized. +* +* _part(size,init) +* The size of the buffer is determined by the +* expression size and all the data in the buffer +* is guaranteed to be initialized up to init +* elements or bytes. +* +* Optional +* +* empty +* The pointer to the block of memory is never +* NULL +* +* _opt +* The pointer to the block of memory is may be +* NULL +* +* +* // Basic Usage of Struct Annotations +* #include +* #include +* struct buf_s { +* int sz; +* __field_bcount_full(sz) +* char *buf; +* }; +* void InitBuf(__out struct *buf_s b,int sz) { +* b->buf = calloc(sz,sizeof(char)); +* b->sz = sz; +* } +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(b->buf,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(b->buf,b->sz,sizeof(char),fp); +* } +* +* +* +* // Inline Allocated Buffer +* struct buf_s { +* int sz; +* __field_bcount(sz) +* char buf[1]; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&(b->buf),b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&(b->buf),b->sz,sizeof(char),fp); +* } +* +* +* +* // Embedded Header Structure +* __struct_bcount(sz) +* struct buf_s { +* int sz; +* }; +* void WriteBuf(__in FILE *fp,__in struct *buf_s b) { +* fwrite(&b,b->sz,sizeof(char),fp); +* } +* void ReadBuf(__in FILE *fp,__inout struct *buf_s b) { +* fread(&b,b->sz,sizeof(char),fp); +* } +* +* +****************************************************************************/ +#define __field_ecount(size) _SAL_VERSION_CHECK(__field_ecount) +#define __field_bcount(size) _SAL_VERSION_CHECK(__field_bcount) +#define __field_xcount(size) __allowed(on_field) +#define __field_ecount_opt(size) __allowed(on_field) +#define __field_bcount_opt(size) __allowed(on_field) +#define __field_xcount_opt(size) __allowed(on_field) +#define __field_ecount_part(size,init) __allowed(on_field) +#define __field_bcount_part(size,init) __allowed(on_field) +#define __field_xcount_part(size,init) __allowed(on_field) +#define __field_ecount_part_opt(size,init) __allowed(on_field) +#define __field_bcount_part_opt(size,init) __allowed(on_field) +#define __field_xcount_part_opt(size,init) __allowed(on_field) +#define __field_ecount_full(size) __allowed(on_field) +#define __field_bcount_full(size) __allowed(on_field) +#define __field_xcount_full(size) __allowed(on_field) +#define __field_ecount_full_opt(size) __allowed(on_field) +#define __field_bcount_full_opt(size) __allowed(on_field) +#define __field_xcount_full_opt(size) __allowed(on_field) +#define __field_nullterminated __allowed(on_field) +#define __struct_bcount(size) __allowed(on_struct) +#define __struct_xcount(size) __allowed(on_struct) + +/*************************************************************************** +* Macros to classify the entrypoints and indicate their category. +* +* Pre-defined control point categories include: RPC, KERNEL, GDI. +* +* Pre-defined control point macros include: +* __rpc_entry, __kernel_entry, __gdi_entry. +***************************************************************************/ +#define __control_entrypoint(category) __allowed(on_function) +#define __rpc_entry __allowed(on_function) +#define __kernel_entry __allowed(on_function) +#define __gdi_entry __allowed(on_function) + +/*************************************************************************** +* Macros to track untrusted data and their validation. The list of untrusted +* sources include: +* +* FILE - File reading stream or API +* NETWORK - Socket readers +* INTERNET - WinInet and WinHttp readers +* USER_REGISTRY - HKCU portions of the registry +* USER_MODE - Parameters to kernel entry points +* RPC - Parameters to RPC entry points +* DRIVER - Device driver +***************************************************************************/ +#define __in_data_source(src_sym) __allowed(on_parameter) +#define __out_data_source(src_sym) __allowed(on_parameter) +#define __field_data_source(src_sym) __allowed(on_field) +#define __this_out_data_source(src_syn) __allowed(on_function) + +/************************************************************************** +* Macros to tag file parsing code. Predefined formats include: +* PNG - Portable Network Graphics +* JPEG - Joint Photographic Experts Group +* BMP - Bitmap +* RC_BMP - Resource bitmap +* WMF - Windows Metafile +* EMF - Windows Enhanced Metafile +* GIF - Graphics Interchange Format +* MIME_TYPE - MIME type from header tokens +* MAIL_MONIKER - MAIL information refered by URL moniker +* HTML - HyperText Markup Language +* WMPHOTO - Windows media photo +* OE_VCARD - Outlook Express virtual card +* OE_CONTACT - Outlook Express contact +* MIDI - Musical Instrument Digital Interface +* LDIF - LDAP Data Interchange Format +* AVI - Audio Visual Interchange +* ACM - Audio Compression Manager +**************************************************************************/ +#define __out_validated(filetype_sym) __allowed(on_parameter) +#define __this_out_validated(filetype_sym) __allowed(on_function) +#define __file_parser(filetype_sym) __allowed(on_function) +#define __file_parser_class(filetype_sym) __allowed(on_struct) +#define __file_parser_library(filetype_sym) __allowed(as_global_decl) + +/*************************************************************************** +* Macros to track the code content in the file. The type of code +* contents currently tracked: +* +* NDIS_DRIVER - NDIS Device driver +***************************************************************************/ +#define __source_code_content(codetype_sym) __allowed(as_global_decl) + +/*************************************************************************** +* Macros to track the code content in the class. The type of code +* contents currently tracked: +* +* DCOM - Class implementing DCOM +***************************************************************************/ +#define __class_code_content(codetype_sym) __allowed(on_struct) + +/************************************************************************* +* Macros to tag encoded function pointers +**************************************************************************/ +#define __encoded_pointer +#define __encoded_array +#define __field_encoded_pointer __allowed(on_field) +#define __field_encoded_array __allowed(on_field) + +#define __transfer(formal) __allowed(on_parameter_or_return) +#define __assume_validated(exp) __allowed(as_statement_with_arg(exp)) + +/************************************************************************* +* __analysis_assume(expr) : Expert macro use only when directed. Use this to +* tell static analysis tools like PREfix and PREfast about a non-coded +* assumption that you wish the tools to assume. The assumption will be +* understood by those tools. By default there is no dynamic checking or +* static checking of the assumption in any build. +* +* To obtain dynamic checking wrap this macro in your local version of a debug +* assert. +* Please do not put function calls in the expression because this is not +* supported by all tools: +* __analysis_assume(GetObject () != NULL); // DO NOT DO THIS +* +*************************************************************************/ +#define __analysis_assume(expr) __allowed(as_statement_with_arg(expr)) +#define __analysis_assert(expr) __allowed(as_statement_with_arg(expr)) + +/************************************************************************* +* __analysis_hint(hint_sym) : Expert macro use only when +* directed. Use this to influence certain analysis heuristics +* used by the tools. These hints do not describe the semantics +* of functions but simply direct the tools to act in a certain +* way. +* +* Current hints that are supported are: +* +* INLINE - inline this function during analysis overrides any +* default heuristics +* NOINLINE - do not inline this function during analysis overrides +* and default heuristics +*************************************************************************/ +#define __analysis_hint(hint) __allowed(on_function) + +/************************************************************************* +* Macros to encode abstract properties of values. Used by SALadt.h +*************************************************************************/ +#define __type_has_adt_prop(adt,prop) __allowed(on_typdecl) +#define __out_has_adt_prop(adt,prop) __allowed(on_parameter) +#define __out_not_has_adt_prop(adt,prop) __allowed(on_parameter) +#define __out_transfer_adt_prop(arg) __allowed(on_parameter) +#define __out_has_type_adt_props(typ) __allowed(on_parameter) + +/************************************************************************* +* Macros used by Prefast for Drivers +* +* __possibly_notnullterminated : +* +* Used for return values of parameters or functions that do not +* guarantee nulltermination in all cases. +* +*************************************************************************/ +#define __possibly_notnullterminated __allowed(on_parameter_or_return) + +/************************************************************************* +* Advanced macros +* +* __volatile +* The __volatile annotation identifies a global variable or +* structure field that: +* 1) is not declared volatile; +* 2) is accessed concurrently by multiple threads. +* +* The __deref_volatile annotation identifies a global variable +* or structure field that stores a pointer to some data that: +* 1) is not declared volatile; +* 2) is accessed concurrently by multiple threads. +* +* Prefast uses these annotations to find patterns of code that +* may result in unexpected re-fetching of the global variable +* into a local variable. +* +* We also provide two complimentary annotations __nonvolatile +* and __deref_nonvolatile that could be used to suppress Prefast +* +* re-fetching warnings on variables that are known either: +* 1) not to be in danger of being re-fetched or, +* 2) not to lead to incorrect results if they are re-fetched +* +*************************************************************************/ +#define __volatile __allowed(on_global_or_field) +#define __deref_volatile __allowed(on_global_or_field) +#define __nonvolatile __allowed(on_global_or_field) +#define __deref_nonvolatile __allowed(on_global_or_field) + +/************************************************************************* +* Macros deprecated with strict level greater then 1. +**************************************************************************/ +#if (__SPECSTRINGS_STRICT_LEVEL > 1) +/* Must come before macro defintions */ +#pragma deprecated(__in_nz) +#pragma deprecated(__in_ecount_nz) +#pragma deprecated(__in_bcount_nz) +#pragma deprecated(__out_nz) +#pragma deprecated(__out_nz_opt) +#pragma deprecated(__out_ecount_nz) +#pragma deprecated(__out_bcount_nz) +#pragma deprecated(__inout_nz) +#pragma deprecated(__inout_ecount_nz) +#pragma deprecated(__inout_bcount_nz) +#pragma deprecated(__in_nz_opt) +#pragma deprecated(__in_ecount_nz_opt) +#pragma deprecated(__in_bcount_nz_opt) +#pragma deprecated(__out_ecount_nz_opt) +#pragma deprecated(__out_bcount_nz_opt) +#pragma deprecated(__inout_nz_opt) +#pragma deprecated(__inout_ecount_nz_opt) +#pragma deprecated(__inout_bcount_nz_opt) +#pragma deprecated(__deref_out_nz) +#pragma deprecated(__deref_out_ecount_nz) +#pragma deprecated(__deref_out_bcount_nz) +#pragma deprecated(__deref_inout_nz) +#pragma deprecated(__deref_inout_ecount_nz) +#pragma deprecated(__deref_inout_bcount_nz) +#pragma deprecated(__deref_out_nz_opt) +#pragma deprecated(__deref_out_ecount_nz_opt) +#pragma deprecated(__deref_out_bcount_nz_opt) +#pragma deprecated(__deref_inout_nz_opt) +#pragma deprecated(__deref_inout_ecount_nz_opt) +#pragma deprecated(__deref_inout_bcount_nz_opt) +#pragma deprecated(__deref_opt_inout_nz) +#pragma deprecated(__deref_opt_inout_ecount_nz) +#pragma deprecated(__deref_opt_inout_bcount_nz) +#pragma deprecated(__deref_opt_out_nz_opt) +#pragma deprecated(__deref_opt_out_ecount_nz_opt) +#pragma deprecated(__deref_opt_out_bcount_nz_opt) +#pragma deprecated(__deref_opt_inout_nz_opt) +#pragma deprecated(__deref_opt_inout_ecount_nz_opt) +#pragma deprecated(__deref_opt_inout_bcount_nz_opt) +#pragma deprecated(__deref) +#pragma deprecated(__pre) +#pragma deprecated(__post) +#pragma deprecated(__readableTo) +#pragma deprecated(__writableTo) +#pragma deprecated(__maybevalid) +#pragma deprecated(__data_entrypoint) +#pragma deprecated(__inexpressible_readableTo) +#pragma deprecated(__readonly) +#pragma deprecated(__byte_writableTo) +#pragma deprecated(__byte_readableTo) +#pragma deprecated(__elem_readableTo) +#pragma deprecated(__elem_writableTo) +#pragma deprecated(__valid) +#pragma deprecated(__notvalid) +#pragma deprecated(__refparam) +#pragma deprecated(__precond) +#endif +/* Define soon to be deprecated macros to nops. */ +#define __in_nz +#define __in_ecount_nz(size) +#define __in_bcount_nz(size) +#define __out_nz +#define __out_nz_opt +#define __out_ecount_nz(size) +#define __out_bcount_nz(size) +#define __inout_nz +#define __inout_ecount_nz(size) +#define __inout_bcount_nz(size) +#define __in_nz_opt +#define __in_ecount_nz_opt(size) +#define __in_bcount_nz_opt(size) +#define __out_ecount_nz_opt(size) +#define __out_bcount_nz_opt(size) +#define __inout_nz_opt +#define __inout_ecount_nz_opt(size) +#define __inout_bcount_nz_opt(size) +#define __deref_out_nz +#define __deref_out_ecount_nz(size) +#define __deref_out_bcount_nz(size) +#define __deref_inout_nz +#define __deref_inout_ecount_nz(size) +#define __deref_inout_bcount_nz(size) +#define __deref_out_nz_opt +#define __deref_out_ecount_nz_opt(size) +#define __deref_out_bcount_nz_opt(size) +#define __deref_inout_nz_opt +#define __deref_inout_ecount_nz_opt(size) +#define __deref_inout_bcount_nz_opt(size) +#define __deref_opt_inout_nz +#define __deref_opt_inout_ecount_nz(size) +#define __deref_opt_inout_bcount_nz(size) +#define __deref_opt_out_nz_opt +#define __deref_opt_out_ecount_nz_opt(size) +#define __deref_opt_out_bcount_nz_opt(size) +#define __deref_opt_inout_nz_opt +#define __deref_opt_inout_ecount_nz_opt(size) +#define __deref_opt_inout_bcount_nz_opt(size) +#define __deref +#define __pre +#define __post +#define __readableTo(count) +#define __writableTo(count) +#define __maybevalid +#define __inexpressible_readableTo(string) +#define __data_entrypoint(category) +#define __readonly +#define __byte_writableTo(count) +#define __byte_readableTo(count) +#define __elem_readableTo(count) +#define __elem_writableTo(count) +#define __valid +#define __notvalid +#define __refparam +#define __precond(condition) + +/************************************************************************* +* Definitions to force a compile error when macros are used improperly. +* Relies on VS 2005 source annotations. +*************************************************************************/ +#if !defined(_MSC_EXTENSIONS) && !defined(_PREFAST_) && !defined(OACR) +#define __allowed(p) /* nothing */ +#else +#define __allowed(p) __$allowed_##p +#define __$allowed_as_global_decl /* empty */ +#define __$allowed_as_statement_with_arg(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4548)) \ + do {__noop(x);} while((0,0) __pragma(warning(pop)) ) +#define __$allowed_as_statement __$allowed_as_statement_with_arg(1) + +/************************************************************************** +* This should go away. It's only for __success which we should split into. +* __success and __typdecl_sucess +***************************************************************************/ +#define __$allowed_on_function_or_typedecl /* empty */ +#if (__SPECSTRINGS_STRICT_LEVEL == 1) || (__SPECSTRINGS_STRICT_LEVEL == 2) +#define __$allowed_on_typedecl /* empty */ +#define __$allowed_on_return /* empty */ +#define __$allowed_on_parameter /* empty */ +#define __$allowed_on_function /* empty */ +#define __$allowed_on_struct /* empty */ +#define __$allowed_on_field /* empty */ +#define __$allowed_on_parameter_or_return /* empty */ +#define __$allowed_on_global_or_field /* empty */ +#elif __SPECSTRINGS_STRICT_LEVEL == 3 +#define __$allowed_on_typedecl /* empty */ +/* Define dummy source attributes. Still needs more testing */ +#define __$allowed_on_return [returnvalue: OnReturnOnly] +#define __$allowed_on_parameter [OnParameterOnly] +#define __$allowed_on_function [method: OnFunctionOnly] +#define __$allowed_on_struct [OnStructOnly] +#define __$allowed_on_field [OnFieldOnly] +#define __$allowed_on_parameter_or_return [OnParameterOrReturnOnly] +#define __$allowed_on_global_or_field /* empty */ +#pragma push_macro( "DECL_SA" ) +#pragma push_macro( "SA" ) +#ifdef __cplusplus +#define SA(x) x +#define DECL_SA(name,loc) \ + [repeatable] \ + [source_annotation_attribute( loc )] \ + struct name##Attribute { name##Attribute(); const char* ignored; }; +#else +#define SA(x) SA_##x +#define DECL_SA(name,loc) \ + [source_annotation_attribute( loc )] \ + struct name { const char* ignored; };\ + typedef struct name name; +#endif /* #endif __cplusplus */ +DECL_SA(OnParameterOnly,SA(Parameter)); +DECL_SA(OnReturnOnly,SA(ReturnValue)); +DECL_SA(OnFunctionOnly,SA(Method)); +DECL_SA(OnStructOnly,SA(Struct)); +DECL_SA(OnFieldOnly,SA(Field)); +DECL_SA(OnParameterOrReturnOnly,SA(Parameter) | SA(ReturnValue)); +#pragma pop_macro( "SA" ) +#pragma pop_macro( "DECL_SA" ) +#endif +#endif +#endif diff --git a/lib/coreclr/src/pal/inc/rt/specstrings_undef.h b/lib/coreclr/src/pal/inc/rt/specstrings_undef.h new file mode 100644 index 0000000000..69fc01c15d --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/specstrings_undef.h @@ -0,0 +1,464 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/* + +*/ + +#ifndef PAL_STDCPP_COMPAT +#undef __in +#undef __out +#endif // !PAL_STDCPP_COMPAT + +#undef _At_ +#undef _Deref_out_ +#undef _Deref_out_opt_ +#undef _Deref_opt_out_ +#undef _Deref_opt_out_opt_ +#undef _Deref_post_cap_ +#undef _Deref_post_opt_cap_ +#undef _Deref_post_bytecap_ +#undef _Deref_post_opt_bytecap_ +#undef _Deref_post_count_ +#undef _Deref_post_opt_count_ +#undef _Deref_post_bytecount_ +#undef _Deref_post_opt_bytecount_ +#undef _In_count_ +#undef _In_opt_count_ +#undef _In_bytecount_ +#undef _In_opt_bytecount_ +#undef _Out_cap_ +#undef _Out_opt_cap_ +#undef _Out_bytecap_ +#undef _Out_opt_bytecap_ +#undef _Outptr_ +#undef _Outptr_result_maybenull_ +#undef _Outptr_opt_ +#undef _Outptr_opt_result_maybenull_ +#undef _Outptr_result_z_ +#undef _Outptr_opt_result_z_ +#undef _Outptr_result_maybenull_z_ +#undef _Outptr_opt_result_maybenull_z_ +#undef _Outptr_result_nullonfailure_ +#undef _Outptr_opt_result_nullonfailure_ +#undef _COM_Outptr_ +#undef _COM_Outptr_result_maybenull_ +#undef _COM_Outptr_opt_ +#undef _COM_Outptr_opt_result_maybenull_ +#undef _Outptr_result_buffer_ +#undef _Outptr_opt_result_buffer_ +#undef _Outptr_result_buffer_to_ +#undef _Outptr_opt_result_buffer_to_ +#undef _Outptr_result_buffer_all_ +#undef _Outptr_opt_result_buffer_all_ +#undef _Outptr_result_buffer_maybenull_ +#undef _Outptr_opt_result_buffer_maybenull_ +#undef _Outptr_result_buffer_to_maybenull_ +#undef _Outptr_opt_result_buffer_to_maybenull_ +#undef _Outptr_result_buffer_all_maybenull_ +#undef _Outptr_opt_result_buffer_all_maybenull_ +#undef _Outptr_result_bytebuffer_ +#undef _Outptr_opt_result_bytebuffer_ +#undef _Outptr_result_bytebuffer_to_ +#undef _Outptr_opt_result_bytebuffer_to_ +#undef _Outptr_result_bytebuffer_all_ +#undef _Outptr_opt_result_bytebuffer_all_ +#undef _Outptr_result_bytebuffer_maybenull_ +#undef _Outptr_opt_result_bytebuffer_maybenull_ +#undef _Outptr_result_bytebuffer_to_maybenull_ +#undef _Outptr_opt_result_bytebuffer_to_maybenull_ +#undef _Outptr_result_bytebuffer_all_maybenull_ +#undef _Outptr_opt_result_bytebuffer_all_maybenull_ +#undef _When_ +#undef __allocator +#undef __analysis_assert +#undef __analysis_assume +#undef __analysis_assume_nullterminated +#undef __analysis_hint +#undef __assume_bound +#undef __assume_validated +#undef __bcount +#undef __bcount_opt +#undef __blocksOn +#undef __bound +#undef __byte_readableTo +#undef __byte_writableTo +#undef __callback +#undef __checkReturn +#undef __class_code_content +#undef __control_entrypoint +#undef __data_entrypoint +#undef __deallocate +#undef __deallocate_opt +#undef __deref +#undef __deref_bcount +#undef __deref_bcount_opt +#undef __deref_ecount +#undef __deref_ecount_opt +#undef __deref_in +#undef __deref_in_bcount +#undef __deref_in_bcount_opt +#undef __deref_in_ecount +#undef __deref_in_ecount_opt +#undef __deref_in_ecount_iterator +#undef __deref_in_opt +#undef __deref_in_opt_out +#undef __deref_in_range +#undef __deref_in_xcount +#undef __deref_in_xcount_opt +#undef __deref_inout +#undef __deref_inout_bcount +#undef __deref_inout_bcount_full +#undef __deref_inout_bcount_full_opt +#undef __deref_inout_bcount_nz +#undef __deref_inout_bcount_nz_opt +#undef __deref_inout_bcount_opt +#undef __deref_inout_bcount_part +#undef __deref_inout_bcount_part_opt +#undef __deref_inout_bcount_z +#undef __deref_inout_bcount_z_opt +#undef __deref_inout_ecount +#undef __deref_inout_ecount_full +#undef __deref_inout_ecount_full_opt +#undef __deref_inout_ecount_nz +#undef __deref_inout_ecount_nz_opt +#undef __deref_inout_ecount_opt +#undef __deref_inout_ecount_part +#undef __deref_inout_ecount_part_opt +#undef __deref_inout_ecount_z +#undef __deref_inout_ecount_z_opt +#undef __deref_inout_ecount_iterator +#undef __deref_inout_nz +#undef __deref_inout_nz_opt +#undef __deref_inout_opt +#undef __deref_inout_range +#undef __deref_inout_xcount +#undef __deref_inout_xcount_full +#undef __deref_inout_xcount_full_opt +#undef __deref_inout_xcount_opt +#undef __deref_inout_xcount_part +#undef __deref_inout_xcount_part_opt +#undef __deref_inout_z +#undef __deref_inout_z_opt +#undef __deref_nonvolatile +#undef __deref_opt_bcount +#undef __deref_opt_bcount_opt +#undef __deref_opt_ecount +#undef __deref_opt_ecount_opt +#undef __deref_opt_in +#undef __deref_opt_in_bcount +#undef __deref_opt_in_bcount_opt +#undef __deref_opt_in_ecount +#undef __deref_opt_in_ecount_opt +#undef __deref_opt_in_opt +#undef __deref_opt_in_xcount +#undef __deref_opt_in_xcount_opt +#undef __deref_opt_inout +#undef __deref_opt_inout_bcount +#undef __deref_opt_inout_bcount_full +#undef __deref_opt_inout_bcount_full_opt +#undef __deref_opt_inout_bcount_nz +#undef __deref_opt_inout_bcount_nz_opt +#undef __deref_opt_inout_bcount_opt +#undef __deref_opt_inout_bcount_part +#undef __deref_opt_inout_bcount_part_opt +#undef __deref_opt_inout_bcount_z +#undef __deref_opt_inout_bcount_z_opt +#undef __deref_opt_inout_ecount +#undef __deref_opt_inout_ecount_full +#undef __deref_opt_inout_ecount_full_opt +#undef __deref_opt_inout_ecount_nz +#undef __deref_opt_inout_ecount_nz_opt +#undef __deref_opt_inout_ecount_opt +#undef __deref_opt_inout_ecount_part +#undef __deref_opt_inout_ecount_part_opt +#undef __deref_opt_inout_ecount_z +#undef __deref_opt_inout_ecount_z_opt +#undef __deref_opt_inout_nz +#undef __deref_opt_inout_nz_opt +#undef __deref_opt_inout_opt +#undef __deref_opt_inout_xcount +#undef __deref_opt_inout_xcount_full +#undef __deref_opt_inout_xcount_full_opt +#undef __deref_opt_inout_xcount_opt +#undef __deref_opt_inout_xcount_part +#undef __deref_opt_inout_xcount_part_opt +#undef __deref_opt_inout_z +#undef __deref_opt_inout_z_opt +#undef __deref_opt_out +#undef __deref_opt_out_bcount +#undef __deref_opt_out_bcount_full +#undef __deref_opt_out_bcount_full_opt +#undef __deref_opt_out_bcount_nz_opt +#undef __deref_opt_out_bcount_opt +#undef __deref_opt_out_bcount_part +#undef __deref_opt_out_bcount_part_opt +#undef __deref_opt_out_bcount_z_opt +#undef __deref_opt_out_ecount +#undef __deref_opt_out_ecount_full +#undef __deref_opt_out_ecount_full_opt +#undef __deref_opt_out_ecount_nz_opt +#undef __deref_opt_out_ecount_opt +#undef __deref_opt_out_ecount_part +#undef __deref_opt_out_ecount_part_opt +#undef __deref_opt_out_ecount_z_opt +#undef __deref_opt_out_nz_opt +#undef __deref_opt_out_opt +#undef __deref_opt_out_xcount +#undef __deref_opt_out_xcount_full +#undef __deref_opt_out_xcount_full_opt +#undef __deref_opt_out_xcount_opt +#undef __deref_opt_out_xcount_part +#undef __deref_opt_out_xcount_part_opt +#undef __deref_opt_out_z_opt +#undef __deref_opt_xcount +#undef __deref_opt_xcount_opt +#undef __deref_out +#undef __deref_out_bcount +#undef __deref_out_bcount_full +#undef __deref_out_bcount_full_opt +#undef __deref_out_bcount_nz +#undef __deref_out_bcount_nz_opt +#undef __deref_out_bcount_opt +#undef __deref_out_bcount_part +#undef __deref_out_bcount_part_opt +#undef __deref_out_bcount_z +#undef __deref_out_bcount_z_opt +#undef __deref_out_bound +#undef __deref_out_ecount +#undef __deref_out_ecount_full +#undef __deref_out_ecount_full_opt +#undef __deref_out_ecount_iterator +#undef __deref_out_ecount_nz +#undef __deref_out_ecount_nz_opt +#undef __deref_out_ecount_opt +#undef __deref_out_ecount_part +#undef __deref_out_ecount_part_opt +#undef __deref_out_ecount_z +#undef __deref_out_ecount_z_opt +#undef __deref_out_nz +#undef __deref_out_nz_opt +#undef __deref_out_opt +#undef __deref_out_range +#undef __deref_out_range +#undef __deref_out_xcount +#undef __deref_out_xcount +#undef __deref_out_xcount_full +#undef __deref_out_xcount_full_opt +#undef __deref_out_xcount_opt +#undef __deref_out_xcount_part +#undef __deref_out_xcount_part_opt +#undef __deref_out_z +#undef __deref_out_z_opt +#undef __deref_realloc_bcount +#undef __deref_volatile +#undef __deref_xcount +#undef __deref_xcount_opt +#undef __ecount +#undef __ecount_opt +#undef __elem_readableTo +#undef __elem_writableTo +#undef __encoded_array +#undef __encoded_pointer +#undef __exceptthat +#undef __fallthrough +#undef __field_bcount +#undef __field_bcount_full +#undef __field_bcount_full_opt +#undef __field_bcount_opt +#undef __field_bcount_part +#undef __field_bcount_part_opt +#undef __field_data_source +#undef __field_ecount +#undef __field_ecount_full +#undef __field_ecount_full_opt +#undef __field_ecount_opt +#undef __field_ecount_part +#undef __field_ecount_part_opt +#undef __field_encoded_array +#undef __field_encoded_pointer +#undef __field_nullterminated +#undef __field_range +#undef __field_xcount +#undef __field_xcount_full +#undef __field_xcount_full_opt +#undef __field_xcount_opt +#undef __field_xcount_part +#undef __field_xcount_part_opt +#undef __file_parser +#undef __file_parser_class +#undef __file_parser_library +#undef __format_string +#undef __format_string +#undef __gdi_entry +#undef __in_awcount +#undef __in_bcount +#undef __in_bcount_nz +#undef __in_bcount_nz_opt +#undef __in_bcount_opt +#undef __in_bcount_z +#undef __in_bcount_z_opt +#undef __in_bound +#undef __in_data_source +#undef __in_ecount +#undef __in_ecount_nz +#undef __in_ecount_nz_opt +#undef __in_ecount_opt +#undef __in_ecount_z +#undef __in_ecount_z_opt +#undef __in_nz +#undef __in_nz_opt +#undef __in_opt +#undef __in_range +#undef __in_xcount +#undef __in_xcount_opt +#undef __in_z +#undef __in_z_opt +#undef __inexpressible_readableTo +#undef __inexpressible_writableTo +#undef __inner_adt_add_prop +#undef __inner_adt_prop +#undef __inner_adt_remove_prop +#undef __inner_adt_transfer_prop +#undef __inner_adt_type_props +#undef __inner_analysis_assume_nulltermianted_dec +#undef __inner_analysis_assume_nullterminated +#undef __inner_assume_bound +#undef __inner_assume_bound_dec +#undef __inner_assume_validated +#undef __inner_assume_validated_dec +#undef __inner_blocksOn +#undef __inner_bound +#undef __inner_callback +#undef __inner_checkReturn +#undef __inner_compname_props +#undef __inner_control_entrypoint +#undef __inner_data_entrypoint +#undef __inner_data_source +#undef __inner_encoded +#undef __inner_fallthrough +#undef __inner_fallthrough_dec +#undef __inner_nonvolatile +#undef __inner_out_validated +#undef __inner_override +#undef __inner_possibly_notnullterminated +#undef __inner_range +#undef __inner_success +#undef __inner_transfer +#undef __inner_typefix +#undef __inner_volatile +#undef __inout +#undef __inout_bcount +#undef __inout_bcount_full +#undef __inout_bcount_full_opt +#undef __inout_bcount_nz +#undef __inout_bcount_nz_opt +#undef __inout_bcount_opt +#undef __inout_bcount_part +#undef __inout_bcount_part_opt +#undef __inout_bcount_z +#undef __inout_bcount_z_opt +#undef __inout_ecount +#undef __inout_ecount_full +#undef __inout_ecount_full_opt +#undef __inout_ecount_nz +#undef __inout_ecount_nz_opt +#undef __inout_ecount_opt +#undef __inout_ecount_part +#undef __inout_ecount_part_opt +#undef __inout_ecount_z +#undef __inout_ecount_z_opt +#undef __inout_ecount_z_opt +#undef __inout_nz +#undef __inout_nz_opt +#undef __inout_opt +#undef __inout_xcount +#undef __inout_xcount_full +#undef __inout_xcount_full_opt +#undef __inout_xcount_opt +#undef __inout_xcount_part +#undef __inout_xcount_part_opt +#undef __inout_z +#undef __inout_z_opt +#undef __kernel_entry +#undef __maybenull +#undef __maybereadonly +#undef __maybevalid +#undef __range_max +#undef __range_min +#undef __nonvolatile +#undef __notnull +#undef __notreadonly +#undef __notvalid +#undef __null +#undef __nullnullterminated +#undef __nullterminated +#undef __out_awcount +#undef __out_bcount +#undef __out_bcount_full +#undef __out_bcount_full_opt +#undef __out_bcount_nz +#undef __out_bcount_nz_opt +#undef __out_bcount_opt +#undef __out_bcount_part +#undef __out_bcount_part_opt +#undef __out_bcount_z +#undef __out_bcount_z_opt +#undef __out_bound +#undef __out_data_source +#undef __out_ecount +#undef __out_ecount_full +#undef __out_ecount_full_opt +#undef __out_ecount_nz +#undef __out_ecount_nz_opt +#undef __out_ecount_opt +#undef __out_ecount_part +#undef __out_ecount_part_opt +#undef __out_ecount_z +#undef __out_ecount_z_opt +#undef __out_has_adt_prop +#undef __out_has_type_adt_props +#undef __out_not_has_adt_prop +#undef __out_nz +#undef __out_nz_opt +#undef __out_opt +#undef __out_range +#undef __out_transfer_adt_prop +#undef __out_validated +#undef __out_xcount +#undef __out_xcount_full +#undef __out_xcount_full_opt +#undef __out_xcount_opt +#undef __out_xcount_part +#undef __out_xcount_part_opt +#undef __out_z +#undef __override +#undef __possibly_notnullterminated +#undef __post +#undef __post_invalid +#undef __postcond +#undef __post_nullnullterminated +#undef __pre +#undef __precond +#undef __range +#undef __readableTo +#undef __readonly +#undef __refparam +#undef __clr_reserved +#undef __rpc_entry +#undef __source_code_content +#undef __struct_bcount +#undef __struct_xcount +#undef __success +#undef __this_out_data_source +#undef __this_out_validated +#undef __transfer +#undef __type_has_adt_prop +#undef __typefix +#undef __valid +#undef __volatile +#undef __writableTo +#undef __xcount +#undef __xcount_opt + diff --git a/lib/coreclr/src/pal/inc/rt/symcrypt.h b/lib/coreclr/src/pal/inc/rt/symcrypt.h new file mode 100644 index 0000000000..33c24b2899 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/symcrypt.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: symcrypt.h +// +// =========================================================================== +// dummy symcrypt.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/tchar.h b/lib/coreclr/src/pal/inc/rt/tchar.h new file mode 100644 index 0000000000..5401fabc13 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/tchar.h @@ -0,0 +1,5 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/tlhelp32.h b/lib/coreclr/src/pal/inc/rt/tlhelp32.h new file mode 100644 index 0000000000..721590d302 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/tlhelp32.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: tlhelp32.h +// +// =========================================================================== +// dummy tlhelp32.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/unknwn.h b/lib/coreclr/src/pal/inc/rt/unknwn.h new file mode 100644 index 0000000000..1397cdbec9 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/unknwn.h @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: unknwn.h +// +// =========================================================================== +// simplified unknwn.h for PAL + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __IUnknown_INTERFACE_DEFINED__ +#define __IUnknown_INTERFACE_DEFINED__ + +typedef interface IUnknown IUnknown; + +typedef /* [unique] */ IUnknown *LPUNKNOWN; + +// 00000000-0000-0000-C000-000000000046 +EXTERN_C const IID IID_IUnknown; + +MIDL_INTERFACE("00000000-0000-0000-C000-000000000046") +IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE QueryInterface( + REFIID riid, + void **ppvObject) = 0; + + virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0; + + virtual ULONG STDMETHODCALLTYPE Release( void) = 0; + + template + HRESULT + STDMETHODCALLTYPE + QueryInterface(Q** pp) + { + return QueryInterface(__uuidof(Q), (void **)pp); + } +}; + +#endif // __IUnknown_INTERFACE_DEFINED__ + +#ifndef __IClassFactory_INTERFACE_DEFINED__ +#define __IClassFactory_INTERFACE_DEFINED__ + +// 00000001-0000-0000-C000-000000000046 +EXTERN_C const IID IID_IClassFactory; + +MIDL_INTERFACE("00000001-0000-0000-C000-000000000046") +IClassFactory : public IUnknown +{ + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + IUnknown *pUnkOuter, + REFIID riid, + void **ppvObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE LockServer( + BOOL fLock) = 0; +}; + +#endif // __IClassFactory_INTERFACE_DEFINED__ diff --git a/lib/coreclr/src/pal/inc/rt/urlmon.h b/lib/coreclr/src/pal/inc/rt/urlmon.h new file mode 100644 index 0000000000..827ad0d6ee --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/urlmon.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: urlmon.h +// +// =========================================================================== +// dummy urlmon.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/verrsrc.h b/lib/coreclr/src/pal/inc/rt/verrsrc.h new file mode 100644 index 0000000000..78a53cf886 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/verrsrc.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: verrsrc.h +// +// =========================================================================== +// dummy verrsrc.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/vsassert.h b/lib/coreclr/src/pal/inc/rt/vsassert.h new file mode 100644 index 0000000000..3c50e5925e --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/vsassert.h @@ -0,0 +1,93 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// + +// This is a simple implementation of what's in vsassert.h in vscommon, since +// we don't want to pull in the entire vsassert library. + +#ifndef __VSASSERT_H__ +#define __VSASSERT_H__ + +#define VSASSERT(e, szMsg) \ +do { \ + if (!(e)) { \ + PAL_fprintf (stderr, \ + "ASSERT FAILED:\n" \ + "\tExpression: %s\n" \ + "\tLocation: line %d in %s\n" \ + "\tFunction: %s\n" \ + "\tMessage: %s\n", \ + #e, __LINE__, __FILE__, __FUNCTION__, szMsg); \ + DebugBreak(); \ + } \ +} while (0) + +#define VSFAIL(szMsg) VSASSERT(0, szMsg) +#define VSIMPLIES(fHypothesis, fConclusion, szMsg) VSASSERT(!(fHypothesis) || (fConclusion), szMsg) +#define VSVERIFY(fTest, szMsg) VSASSERT((fTest), (szMsg)) + +#undef VSAlloc +#undef VSAllocZero +#undef VSRealloc +#undef VSReallocZero +#undef VSFree +#undef VSSize +#undef VsDebAlloc +#undef VsDebRealloc +#undef VsDebSafeRealloc +#undef VsDebFree +#undef VsDebHeapSize + +#undef VsDebHeapCreate +#undef VsDebHeapDestroy + +#undef VsDebugInitialize +#undef VsDebugTerminate + +// NOTE: These have changed to use the HeapAlloc family (as opposed to +// LocalAlloc family) because of HeapReAlloc's behavior (a block may move to +// satisfy a realloc request, as opposed to LocalReAlloc's behavior of simply +// failing). + +#define VSAlloc(cb) HeapAlloc(GetProcessHeap(), 0, cb) +#define VSAllocZero(cb) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb) +#define VSRealloc(pv, cb) HeapReAlloc(GetProcessHeap(), 0, pv, cb) +#define VSReallocZero(pv,cb) CoreCLR_pal_doesnt_have_vsrealloczero +#define VSFree(pv) HeapFree(GetProcessHeap(), 0, pv) +#define VSSize(pv) CoreCLR_pal_doesnt_have_heapsize + +#define VsDebAlloc(flags,cb) VSAlloc(cb) +#define VsDebRealloc(pv,flags,cb) VSRealloc(pv,cb) +#define VsDebSafeRealloc(pv,flags,cb) CoreCLR_pal_doenst_have_saferealloc +#define VsDebFree(pv) VSFree(pv) +#define VsDebHeapSize(heap, pv) VSSize(pv) + +#define VsDebHeapCreate(flags, name) CoreCLR_doesnt_have_heapcreate +#define VsDebHeapDestroy(heap, fLeakCheck) CoreCLR_doesnt_have_heapdestroy + +#define VsDebugAllocInternal(hheap,dwFlags,cb,pszFile,uLine,dwInst,pszExtra) \ + HeapAlloc(GetProcessHeap(), dwFlags, cb) + +#define DEFAULT_HEAP 0 +#define INSTANCE_GLOBAL 0 + +#define VsDebugInitialize() do {} while (0) +#define VsDebugTerminate() do {} while (0) + + +// Debug switches +// +#define DEFINE_SWITCH(NAME, PACKAGE, DESC) VSDEFINE_SWITCH(NAME, PACKAGE, DESC) +#define EXTERN_SWITCH(NAME) VSEXTERN_SWITCH(NAME) +#define FSWITCH(NAME) VSFSWITCH(NAME) + +#define VSDEFINE_SWITCH(NAME, PACKAGE, DESC) +#define VSEXTERN_SWITCH(NAME) +#define VSFSWITCH(NAME) FALSE + +#define VsIgnoreAllocs(f) + +#endif // __VSASSERT_H__ diff --git a/lib/coreclr/src/pal/inc/rt/winapifamily.h b/lib/coreclr/src/pal/inc/rt/winapifamily.h new file mode 100644 index 0000000000..234a07bb0b --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winapifamily.h @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: windows.h +// +// =========================================================================== +// dummy winapifamily.h for PAL + +#ifndef _INC_WINAPIFAMILY +#define _INC_WINAPIFAMILY + +// +// Windows APIs can be placed in a partition represented by one of the below bits. The +// WINAPI_FAMILY value determines which partitions are available to the client code. +// + +#define WINAPI_PARTITION_DESKTOP 0x00000001 +#define WINAPI_PARTITION_APP 0x00000002 + +// A family may be defined as the union of multiple families. WINAPI_FAMILY should be set +// to one of these values. +#define WINAPI_FAMILY_APP WINAPI_PARTITION_APP +#define WINAPI_FAMILY_DESKTOP_APP (WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_APP) + +// Provide a default for WINAPI_FAMILY if needed. +#ifndef WINAPI_FAMILY +#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP +#endif + +// Macro to determine if a partition is enabled +#define WINAPI_FAMILY_PARTITION(Partition) ((WINAPI_FAMILY & Partition) == Partition) + +// Macro to determine if only one partition is enabled from a set +#define WINAPI_FAMILY_ONE_PARTITION(PartitionSet, Partition) ((WINAPI_FAMILY & PartitionSet) == Partition) + +#endif diff --git a/lib/coreclr/src/pal/inc/rt/winbase.h b/lib/coreclr/src/pal/inc/rt/winbase.h new file mode 100644 index 0000000000..af9de7c63f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winbase.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winbase.h +// +// =========================================================================== +// dummy winbase.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/wincrypt.h b/lib/coreclr/src/pal/inc/rt/wincrypt.h new file mode 100644 index 0000000000..71caa7d07d --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/wincrypt.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: wincrypt.h +// +// =========================================================================== +// dummy wincrypt.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/windef.h b/lib/coreclr/src/pal/inc/rt/windef.h new file mode 100644 index 0000000000..2ab50f256f --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/windef.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: windef.h +// +// =========================================================================== +// dummy windef.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/windows.h b/lib/coreclr/src/pal/inc/rt/windows.h new file mode 100644 index 0000000000..802fde15e9 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/windows.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: windows.h +// +// =========================================================================== +// dummy windows.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winerror.h b/lib/coreclr/src/pal/inc/rt/winerror.h new file mode 100644 index 0000000000..e8eeed9ced --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winerror.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winerror.h +// +// =========================================================================== +// dummy winerror.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/wininet.h b/lib/coreclr/src/pal/inc/rt/wininet.h new file mode 100644 index 0000000000..e41482fc32 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/wininet.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: wininet.h +// +// =========================================================================== +// dummy wininet.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winnls.h b/lib/coreclr/src/pal/inc/rt/winnls.h new file mode 100644 index 0000000000..57bb2415d5 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winnls.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winnls.h +// +// =========================================================================== +// dummy winnls.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winnt.h b/lib/coreclr/src/pal/inc/rt/winnt.h new file mode 100644 index 0000000000..600338ce2e --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winnt.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winnt.h +// +// =========================================================================== +// dummy winnt.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winresrc.h b/lib/coreclr/src/pal/inc/rt/winresrc.h new file mode 100644 index 0000000000..b8d92706ad --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winresrc.h @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winresrc.h +// +// =========================================================================== +// winresrc.h for PAL +// Included in .rc files. + +#include "winver.h" +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winternl.h b/lib/coreclr/src/pal/inc/rt/winternl.h new file mode 100644 index 0000000000..476e40de0c --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winternl.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winternl.h +// +// =========================================================================== +// dummy winternl.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winuser.h b/lib/coreclr/src/pal/inc/rt/winuser.h new file mode 100644 index 0000000000..fc19f9a55d --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winuser.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winuser.h +// +// =========================================================================== +// dummy winuser.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/winver.h b/lib/coreclr/src/pal/inc/rt/winver.h new file mode 100644 index 0000000000..b315280ef7 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/winver.h @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: winver.h +// +// =========================================================================== +// winver.h for PAL +// Included in .rc files. + +#define VS_VERSION_INFO 1 +#define VS_FFI_FILEFLAGSMASK 0x0000003FL + +#define VS_FF_DEBUG 0x00000001L +#define VS_FF_PRERELEASE 0x00000002L +#define VS_FF_PATCHED 0x00000004L +#define VS_FF_PRIVATEBUILD 0x00000008L +#define VS_FF_INFOINFERRED 0x00000010L +#define VS_FF_SPECIALBUILD 0x00000020L + +#define VFT_UNKNOWN 0x00000000L +#define VFT_APP 0x00000001L +#define VFT_DLL 0x00000002L + +#define VFT2_UNKNOWN 0x00000000L + +#define VOS__WINDOWS32 0x00000004L diff --git a/lib/coreclr/src/pal/inc/rt/wtsapi32.h b/lib/coreclr/src/pal/inc/rt/wtsapi32.h new file mode 100644 index 0000000000..0e41b15abf --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/wtsapi32.h @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +// +// =========================================================================== +// File: wtsapi32.h +// +// =========================================================================== +// dummy wtsapi32.h for PAL + +#include "palrt.h" diff --git a/lib/coreclr/src/pal/inc/rt/x86intrin.h b/lib/coreclr/src/pal/inc/rt/x86intrin.h new file mode 100644 index 0000000000..c88e9fc6e4 --- /dev/null +++ b/lib/coreclr/src/pal/inc/rt/x86intrin.h @@ -0,0 +1 @@ +#include "xmmintrin.h" diff --git a/lib/coreclr/src/pal/inc/strsafe.h b/lib/coreclr/src/pal/inc/strsafe.h new file mode 100644 index 0000000000..f32f5e6549 --- /dev/null +++ b/lib/coreclr/src/pal/inc/strsafe.h @@ -0,0 +1,4162 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*++ + + + + + +--*/ + +/****************************************************************** +* * +* strsafe.h -- This module defines safer C library string * +* routine replacements. These are meant to make C * +* a bit more safe in reference to security and * +* robustness * +* * +******************************************************************/ +#ifndef _STRSAFE_H_INCLUDED_ +#define _STRSAFE_H_INCLUDED_ +#ifdef _MSC_VER +#pragma once +#endif + +#include // for _vsnprintf, getc, getwc +#include // for memset +#include // for va_start, etc. + +#ifndef _SIZE_T_DEFINED +#ifdef _WIN64 +typedef unsigned __int64 size_t; +#else +typedef __w64 unsigned int size_t; +#endif // !_WIN64 +#define _SIZE_T_DEFINED +#endif // !_SIZE_T_DEFINED + +#if !defined(_WCHAR_T_DEFINED) && !defined(_NATIVE_WCHAR_T_DEFINED) +#error Unexpected define. +typedef char16_t WCHAR; +#define _WCHAR_T_DEFINED +#endif + +#ifndef SUCCEEDED +#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0) +#endif + +#ifndef FAILED +#define FAILED(hr) ((HRESULT)(hr) < 0) +#endif + +#ifndef S_OK +#define S_OK ((HRESULT)0x00000000L) +#endif + +#ifdef __cplusplus +#define _STRSAFE_EXTERN_C extern "C" +#else +#define _STRSAFE_EXTERN_C extern +#endif + +// If you do not want to use these functions inline (and instead want to link w/ strsafe.lib), then +// #define STRSAFE_LIB before including this header file. +#if defined(STRSAFE_LIB) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#pragma comment(lib, "strsafe.lib") +#elif defined(STRSAFE_LIB_IMPL) +#define STRSAFEAPI _STRSAFE_EXTERN_C HRESULT __stdcall +#else +#define STRSAFEAPI __inline HRESULT __stdcall +#define STRSAFE_INLINE +#endif + +// Some functions always run inline because they use stdin and we want to avoid building multiple +// versions of strsafe lib depending on if you use msvcrt, libcmt, etc. +#define STRSAFE_INLINE_API __inline HRESULT __stdcall + +// The user can request no "Cb" or no "Cch" fuctions, but not both! +#if defined(STRSAFE_NO_CB_FUNCTIONS) && defined(STRSAFE_NO_CCH_FUNCTIONS) +#error cannot specify both STRSAFE_NO_CB_FUNCTIONS and STRSAFE_NO_CCH_FUNCTIONS !! +#endif + +// This should only be defined when we are building strsafe.lib +#ifdef STRSAFE_LIB_IMPL +#define STRSAFE_INLINE +#endif + + +#define STRSAFE_MAX_CCH 2147483647 // max # of characters we support (same as INT_MAX) + +// STRSAFE error return codes +// +#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL) // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER +#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L) // 0x57 = 87L = ERROR_INVALID_PARAMETER +#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L) // 0x26 = 38L = ERROR_HANDLE_EOF + +// Flags for controling the Ex functions +// +// STRSAFE_FILL_BYTE(0xFF) 0x000000FF // bottom byte specifies fill pattern +#define STRSAFE_IGNORE_NULLS 0x00000100 // treat null as TEXT("") -- don't fault on NULL buffers +#define STRSAFE_FILL_BEHIND_NULL 0x00000200 // fill in extra space behind the null terminator +#define STRSAFE_FILL_ON_FAILURE 0x00000400 // on failure, overwrite pszDest with fill pattern and null terminate it +#define STRSAFE_NULL_ON_FAILURE 0x00000800 // on failure, set *pszDest = TEXT('\0') +#define STRSAFE_NO_TRUNCATION 0x00001000 // instead of returning a truncated result, copy/append nothing to pszDest and null terminate it + +#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION) + +// helper macro to set the fill character and specify buffer filling +#define STRSAFE_FILL_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL)) +#define STRSAFE_FAILURE_BYTE(x) ((unsigned long)((x & 0x000000FF) | STRSAFE_FILL_ON_FAILURE)) + +#define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)(dwFlags & 0x000000FF)) + +// prototypes for the worker functions +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc); +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc); +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc); +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringLengthWorkerW(const WCHAR* psz, size_t cchMax, size_t* pcch); +#endif // STRSAFE_INLINE + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCopy(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string was copied without truncation and null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCopyW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc); +#ifdef UNICODE +#define StringCchCopy StringCchCopyW +#else +#define StringCchCopy StringCchCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCopy(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for strncpy. That function will pad the + destination string with extra null termination characters if the count is + greater than the length of the source string, and it will fail to null + terminate the destination string if the source string length is greater + than or equal to the count. You can not blindly use this instead of strncpy: + it is common for code to use it to "patch" strings and you would introduce + errors if the code started null terminating in the middle of the string. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string was copied without truncation and null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc); +#ifdef UNICODE +#define StringCbCopy StringCbCopyW +#else +#define StringCbCopy StringCbCopyA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyA(char* pszDest, size_t cbDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + // convert to count of characters + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCopyEx(TCHAR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCchCopy, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyEx StringCchCopyExW +#else +#define StringCchCopyEx StringCchCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + cbDest = cchDest * sizeof(WCHAR); + + hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCopyEx(TCHAR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + LPTSTR* ppszDestEnd, + size_t* pcbRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcpy' with + some additional parameters. In addition to functionality provided by + StringCbCopy, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyEx StringCbCopyExW +#else +#define StringCbCopyEx StringCbCopyExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCopyN(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + size_t cchSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the entire string or the first cchSrc characters were copied without + truncation and the resultant destination string was null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(src) + 1) to hold all of the + source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from source string + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCopyNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc); +STRSAFEAPI StringCchCopyNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc); +#ifdef UNICODE +#define StringCchCopyN StringCchCopyNW +#else +#define StringCchCopyN StringCchCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCopyN(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + size_t cbSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the entire string or the first cbSrc characters were copied without + truncation and the resultant destination string was null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + copied to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(src) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCopyEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc); +STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc); +#ifdef UNICODE +#define StringCbCopyN StringCbCopyNW +#else +#define StringCbCopyN StringCbCopyNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerA(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCopyNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + + // convert to count of characters + cchDest = cbDest / sizeof(WCHAR); + cchSrc = cbSrc / sizeof(WCHAR); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNWorkerW(pszDest, cchDest, pszSrc, cchSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCopyNEx(TCHAR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + size_t cchSrc, + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCchCopyN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination + string including the null terminator. The flags parameter allows + additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cchSrc is greater than the length of pszSrc. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszSrc) + 1) to hold all of + the source including the null terminator + + pszSrc - source string + + cchSrc - maximum number of characters to copy from the source + string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCopyNEx StringCchCopyNExW +#else +#define StringCchCopyNEx StringCchCopyNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCopyNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCopyNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + cbDest = cchDest * sizeof(WCHAR); + + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCopyNEx(TCHAR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + size_t cbSrc, + LPTSTR* ppszDestEnd, + size_t* pcbRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncpy' with + some additional parameters. In addition to functionality provided by + StringCbCopyN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + + This routine is meant as a replacement for strncpy, but it does behave + differently. This function will not pad the destination buffer with extra + null termination characters if cbSrc is greater than the size of pszSrc. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszSrc) + 1) * sizeof(TCHAR)) to + hold all of the source including the null terminator + + pszSrc - source string + + cbSrc - maximum number of bytes to copy from source string + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - pcbRemaining is non-null,the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcpy + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any truncated + string returned when the failure is + STRSAFE_E_INSUFFICIENT_BUFFER + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any truncated string + returned when the failure is STRSAFE_E_INSUFFICIENT_BUFFER. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all copied and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the copy operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCopyNEx StringCbCopyNExW +#else +#define StringCbCopyNEx StringCbCopyNExA +#endif // !UNICODE + + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCopyNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + cchSrc = cbSrc / sizeof(char); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCopyNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchSrc; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(WCHAR); + cchSrc = cbSrc / sizeof(WCHAR); + + if ((cchDest > STRSAFE_MAX_CCH) || + (cchSrc > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCopyNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCat(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in characters) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string was concatenated without truncation and null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + appended to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be = (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc); +STRSAFEAPI StringCchCatW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc); +#ifdef UNICODE +#define StringCchCat StringCchCatW +#else +#define StringCchCat StringCchCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCchCatW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCat(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat'. + The size of the destination buffer (in bytes) is a parameter and this + function will not write past the end of this buffer and it will ALWAYS + null terminate the destination buffer (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string was concatenated without truncation and null terminated, otherwise + it will return a failure code. In failure cases as much of pszSrc will be + appended to pszDest as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be = ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator + + pszSrc - source string which must be null terminated + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if there was source data and it was all concatenated and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc); +STRSAFEAPI StringCbCatW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc); +#ifdef UNICODE +#define StringCbCat StringCbCatW +#else +#define StringCbCat StringCbCatA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatA(char* pszDest, size_t cbDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerA(pszDest, cchDest, pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCbCatW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatWorkerW(pszDest, cchDest, pszSrc); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCatEx(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCchCat, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters + length must be (_tcslen(pszDest) + _tcslen(pszSrc) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatEx StringCchCatExW +#else +#define StringCchCatEx StringCchCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatExA(char* pszDest, size_t cchDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + cbDest = cchDest * sizeof(WCHAR); + + hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCatEx(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + LPTSTR* ppszDestEnd, + size_t* pcbRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strcat' with + some additional parameters. In addition to functionality provided by + StringCbCat, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + _tcslen(pszSrc) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string which must be null terminated + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return + the number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + this flag is useful for emulating functions like lstrcat + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if there was source data and it was all concatenated and the + resultant dest string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatEx StringCbCatExW +#else +#define StringCbCatEx StringCbCatExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatExA(char* pszDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatExWorkerA(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatExWorkerW(pszDest, cchDest, cbDest, pszSrc, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCatN(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + size_t cchMaxAppend); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in characters) is a parameter as well as + the maximum number of characters to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns a S_OK + if all of pszSrc or the first cchMaxAppend characters were appended to the + destination string and it was null terminated, otherwise it will return a + failure code. In failure cases as much of pszSrc will be appended to pszDest + as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCchCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters were + concatenated to pszDest and the resultant dest string was + null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend); +STRSAFEAPI StringCchCatNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend); +#ifdef UNICODE +#define StringCchCatN StringCchCatNW +#else +#define StringCchCatN StringCchCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCchCatNW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCatN(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + size_t cbMaxAppend); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat'. + The size of the destination buffer (in bytes) is a parameter as well as + the maximum number of bytes to append, excluding the null terminator. + This function will not write past the end of the destination buffer and it will + ALWAYS null terminate pszDest (unless it is zero length). + + This function returns a hresult, and not a pointer. It returns a S_OK + if all of pszSrc or the first cbMaxAppend bytes were appended to the + destination string and it was null terminated, otherwise it will return a + failure code. In failure cases as much of pszSrc will be appended to pszDest + as possible, and pszDest will be null terminated. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL. See StringCbCatNEx if you require + the handling of NULL values. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string was + null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend); +STRSAFEAPI StringCbCatNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend); +#ifdef UNICODE +#define StringCbCatN StringCbCatNW +#else +#define StringCbCatN StringCbCatNA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNWorkerA(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCbCatNW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend) +{ + HRESULT hr; + size_t cchDest; + + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(WCHAR); + + hr = StringCatNWorkerW(pszDest, cchDest, pszSrc, cchMaxAppend); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchCatNEx(LPTSTR pszDest, + size_t cchDest, + LPCTSTR pszSrc, + size_t cchMaxAppend, + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCchCatN, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cchDest - size of destination buffer in characters. + length must be (_tcslen(pszDest) + min(cchMaxAppend, _tcslen(pszSrc)) + 1) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cchMaxAppend - maximum number of characters to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cchMaxAppend characters were + concatenated to pszDest and the resultant dest string was + null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +STRSAFEAPI StringCchCatNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCchCatNEx StringCchCatNExW +#else +#define StringCchCatNEx StringCchCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchCatNExA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(char) since cchDest < STRSAFE_MAX_CCH and sizeof(char) is 1 + cbDest = cchDest * sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} + +STRSAFEAPI StringCchCatNExW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr; + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cbDest; + + // safe to multiply cchDest * sizeof(WCHAR) since cchDest < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + cbDest = cchDest * sizeof(WCHAR); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, pcchRemaining, dwFlags); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbCatNEx(LPTSTR pszDest, + size_t cbDest, + LPCTSTR pszSrc, + size_t cbMaxAppend + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'strncat', with + some additional parameters. In addition to functionality provided by + StringCbCatN, this routine also returns a pointer to the end of the + destination string and the number of bytes left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string which must be null terminated + + cbDest - size of destination buffer in bytes. + length must be ((_tcslen(pszDest) + min(cbMaxAppend / sizeof(TCHAR), _tcslen(pszSrc)) + 1) * sizeof(TCHAR) + to hold all of the combine string plus the null + terminator. + + pszSrc - source string + + cbMaxAppend - maximum number of bytes to append + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function appended any data, the result will point to the + null termination character + + pcbRemaining - if pcbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")) + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. This will overwrite any pre-existing + or truncated string + + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. This will overwrite any pre-existing or + truncated string + + STRSAFE_NO_TRUNCATION + if the function returns STRSAFE_E_INSUFFICIENT_BUFFER, pszDest + will not contain a truncated string, it will remain unchanged. + +Notes: + Behavior is undefined if source and destination strings overlap. + + pszDest and pszSrc should not be NULL unless the STRSAFE_IGNORE_NULLS flag + is specified. If STRSAFE_IGNORE_NULLS is passed, both pszDest and pszSrc + may be NULL. An error may still be returned even though NULLS are ignored + due to insufficient space. + +Return Value: + + S_OK - if all of pszSrc or the first cbMaxAppend bytes were + concatenated to pszDest and the resultant dest string was + null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all falure cases + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that the operation + failed due to insufficient space. When this error occurs, + the destination buffer is modified to contain a truncated + version of the ideal result and is null terminated. This + is useful for situations where truncation is ok. + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function + +--*/ + +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags); +#ifdef UNICODE +#define StringCbCatNEx StringCbCatNExW +#else +#define StringCbCatNEx StringCbCatNExA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbCatNExA(char* pszDest, size_t cbDest, const char* pszSrc, size_t cbMaxAppend, char** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(char); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(char); + + hr = StringCatNExWorkerA(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(char) since cchRemaining < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcbRemaining = (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)); + } + } + + return hr; +} + +STRSAFEAPI StringCbCatNExW(WCHAR* pszDest, size_t cbDest, const WCHAR* pszSrc, size_t cbMaxAppend, WCHAR** ppszDestEnd, size_t* pcbRemaining, unsigned long dwFlags) +{ + HRESULT hr; + size_t cchDest; + size_t cchRemaining = 0; + + cchDest = cbDest / sizeof(WCHAR); + + if (cchDest > STRSAFE_MAX_CCH) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchMaxAppend; + + cchMaxAppend = cbMaxAppend / sizeof(WCHAR); + + hr = StringCatNExWorkerW(pszDest, cchDest, cbDest, pszSrc, cchMaxAppend, ppszDestEnd, &cchRemaining, dwFlags); + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (pcbRemaining) + { + // safe to multiply cchRemaining * sizeof(WCHAR) since cchRemaining < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcbRemaining = (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)); + } + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchGets(LPTSTR pszDest, + size_t cchDest); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in characters) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns a S_OK + if any characters were read from stdin and copied to pszDest and pszDest was + null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + +Notes: + pszDest should not be NULL. See StringCchGetsEx if you require the handling + of NULL values. + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_END_OF_FILE + - this return value indicates an error or end-of-file condition, + use feof or ferror to determine which one has occurred. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was insufficient + space in the destination buffer to copy any data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#endif // !STRSAFE_NO_CCH_FUNCTIONS + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbGets(LPTSTR pszDest, + size_t cbDest); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets'. + The size of the destination buffer (in bytes) is a parameter and + this function will not write past the end of this buffer and it will + ALWAYS null terminate the destination buffer (unless it is zero length). + + This routine is not a replacement for fgets. That function does not replace + newline characters with a null terminator. + + This function returns a hresult, and not a pointer. It returns a S_OK + if any characters were read from stdin and copied to pszDest and pszDest was + null terminated, otherwise it will return a failure code. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + +Notes: + pszDest should not be NULL. See StringCbGetsEx if you require the handling + of NULL values. + + cbDest must be > sizeof(TCHAR) for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_END_OF_FILE + - this return value indicates an error or end-of-file condition, + use feof or ferror to determine which one has occurred. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was insufficient + space in the destination buffer to copy any data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#endif // !STRSAFE_NO_CB_FUNCTIONS + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchGetsEx(LPTSTR pszDest, + size_t cchDest, + LPTSTR* ppszDestEnd, + size_t* pcchRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCchGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cchDest - size of destination buffer in characters. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcchRemaining - if pcchRemaining is non-null, the function will return the + number of characters left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cchDest must be > 1 for this function to succeed. + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_END_OF_FILE + - this return value indicates an error or end-of-file condition, + use feof or ferror to determine which one has occurred. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was insufficient + space in the destination buffer to copy any data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#endif // !STRSAFE_NO_CCH_FUNCTIONS + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbGetsEx(LPTSTR pszDest, + size_t cbDest, + LPTSTR* ppszDestEnd, + size_t* pcbRemaining, + DWORD dwFlags); + +Routine Description: + + This routine is a safer version of the C built-in function 'gets' with + some additional parameters. In addition to functionality provided by + StringCbGets, this routine also returns a pointer to the end of the + destination string and the number of characters left in the destination string + including the null terminator. The flags parameter allows additional controls. + +Arguments: + + pszDest - destination string + + cbDest - size of destination buffer in bytes. + + ppszDestEnd - if ppszDestEnd is non-null, the function will return a + pointer to the end of the destination string. If the + function copied any data, the result will point to the + null termination character + + pcbRemaining - if pbRemaining is non-null, the function will return the + number of bytes left in the destination string, + including the null terminator + + dwFlags - controls some details of the string copy: + + STRSAFE_FILL_BEHIND_NULL + if the function succeeds, the low byte of dwFlags will be + used to fill the uninitialize part of destination buffer + behind the null terminator + + STRSAFE_IGNORE_NULLS + treat NULL string pointers like empty strings (TEXT("")). + + STRSAFE_FILL_ON_FAILURE + if the function fails, the low byte of dwFlags will be + used to fill all of the destination buffer, and it will + be null terminated. + + STRSAFE_NO_TRUNCATION / + STRSAFE_NULL_ON_FAILURE + if the function fails, the destination buffer will be set + to the empty string. + +Notes: + pszDest should not be NULL unless the STRSAFE_IGNORE_NULLS flag is specified. + If STRSAFE_IGNORE_NULLS is passed and pszDest is NULL, an error may still be + returned even though NULLS are ignored + + cbDest must be > sizeof(TCHAR) for this function to succeed + +Return Value: + + S_OK - data was read from stdin and copied, and the resultant dest + string was null terminated + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + STRSAFE_E_END_OF_FILE + - this return value indicates an error or end-of-file condition, + use feof or ferror to determine which one has occurred. + + STRSAFE_E_INSUFFICIENT_BUFFER / + HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER + - this return value is an indication that there was insufficient + space in the destination buffer to copy any data + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +#endif // !STRSAFE_NO_CB_FUNCTIONS + +#ifndef STRSAFE_NO_CCH_FUNCTIONS +/*++ + +STDAPI StringCchLength(LPCTSTR psz, + size_t cchMax, + size_t* pcch); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in characters not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string is non-null and the length including the null terminator is + less than or equal to cchMax characters. + +Arguments: + + psz - string to check the length of + + cchMax - maximum number of characters including the null terminator + that psz is allowed to contain + + pcch - if the function succeeds and pcch is non-null, the current length + in characters of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) + +Notes: + psz can be null but the function will fail + + cchMax should be greater than zero or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null terminator is + less than or equal to cchMax characters + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCchLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCchLength StringCchLengthW +#else +#define StringCchLength StringCchLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCchLengthA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, pcch); + } + + return hr; +} + +STRSAFEAPI StringCchLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr; + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, pcch); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CCH_FUNCTIONS + + +#ifndef STRSAFE_NO_CB_FUNCTIONS +/*++ + +STDAPI StringCbLength(LPCTSTR psz, + size_t cbMax, + size_t* pcb); + +Routine Description: + + This routine is a safer version of the C built-in function 'strlen'. + It is used to make sure a string is not larger than a given length, and + it optionally returns the current length in bytes not including + the null terminator. + + This function returns a hresult, and not a pointer. It returns a S_OK + if the string is non-null and the length including the null terminator is + less than or equal to cbMax bytes. + +Arguments: + + psz - string to check the length of + + cbMax - maximum number of bytes including the null terminator + that psz is allowed to contain + + pcb - if the function succeeds and pcb is non-null, the current length + in bytes of psz excluding the null terminator will be returned. + This out parameter is equivalent to the return value of strlen(psz) * sizeof(TCHAR) + +Notes: + psz can be null but the function will fail + + cbMax should be greater than or equal to sizeof(TCHAR) or the function will fail + +Return Value: + + S_OK - psz is non-null and the length including the null terminator is + less than or equal to cbMax bytes + + failure - you can use the macro HRESULT_CODE() to get a win32 error + code for all hresult falure cases + + It is strongly recommended to use the SUCCEEDED() / FAILED() macros to test the + return value of this function. + +--*/ + +STRSAFEAPI StringCbLengthA(const char* psz, size_t cchMax, size_t* pcch); +STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cchMax, size_t* pcch); +#ifdef UNICODE +#define StringCbLength StringCbLengthW +#else +#define StringCbLength StringCbLengthA +#endif // !UNICODE + +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCbLengthA(const char* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(char); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerA(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(char) since cch < STRSAFE_MAX_CCH and sizeof(char) is 1 + *pcb = cch * sizeof(char); + } + + return hr; +} + +STRSAFEAPI StringCbLengthW(const WCHAR* psz, size_t cbMax, size_t* pcb) +{ + HRESULT hr; + size_t cchMax; + size_t cch = 0; + + cchMax = cbMax / sizeof(WCHAR); + + if ((psz == NULL) || (cchMax > STRSAFE_MAX_CCH)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = StringLengthWorkerW(psz, cchMax, &cch); + } + + if (SUCCEEDED(hr) && pcb) + { + // safe to multiply cch * sizeof(WCHAR) since cch < STRSAFE_MAX_CCH and sizeof(WCHAR) is 2 + *pcb = cch * sizeof(WCHAR); + } + + return hr; +} +#endif // STRSAFE_INLINE +#endif // !STRSAFE_NO_CB_FUNCTIONS + + +// these are the worker functions that actually do the work +#ifdef STRSAFE_INLINE +STRSAFEAPI StringCopyWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != '\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && (*pszSrc != L'\0')) + { + *pszDest++ = *pszSrc++; + cchDest--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && (*pszSrc != '\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = '\0'; + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + WCHAR* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || + // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = u""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != u'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && (*pszSrc != u'\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = u'\0'; + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != '\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= '\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchSrc) +{ + HRESULT hr = S_OK; + + if (cchDest == 0) + { + // can not null terminate a zero-byte dest buffer + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + while (cchDest && cchSrc && (*pszSrc != L'\0')) + { + *pszDest++= *pszSrc++; + cchDest--; + cchSrc--; + } + + if (cchDest == 0) + { + // we are going to truncate pszDest + pszDest--; + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDest= L'\0'; + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != '\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(char)) + (cbDest % sizeof(char))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = '\0'; + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCopyNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + WCHAR* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || + // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest != 0) || (cbDest != 0)) + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + + if (pszSrc == NULL) + { + pszSrc = u""; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + pszDestEnd = pszDest; + cchRemaining = 0; + + // only fail if there was actually src data to copy + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + while (cchRemaining && cchSrc && (*pszSrc != L'\0')) + { + *pszDestEnd++= *pszSrc++; + cchRemaining--; + cchSrc--; + } + + if (cchRemaining > 0) + { + if (dwFlags & STRSAFE_FILL_BEHIND_NULL) + { + memset(pszDestEnd + 1, STRSAFE_GET_FILL_PATTERN(dwFlags), ((cchRemaining - 1) * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + } + } + else + { + // we are going to truncate pszDest + pszDestEnd--; + cchRemaining++; + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + *pszDestEnd = L'\0'; + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatWorkerA(char* pszDest, size_t cchDest, const char* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc); + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerA() + + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else + if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + WCHAR* pszDestEnd = pszDest; + size_t cchRemaining = 0; + + // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || + // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + size_t cchDestCurrent; + + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = u""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), + pszSrc, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyExWorkerW() + + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & STRSAFE_NULL_ON_FAILURE) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerA(char* pszDest, size_t cchDest, const char* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerA(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNWorkerW(WCHAR* pszDest, size_t cchDest, const WCHAR* pszSrc, size_t cchMaxAppend) +{ + HRESULT hr; + size_t cchDestCurrent; + + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + hr = StringCopyNWorkerW(pszDest + cchDestCurrent, + cchDest - cchDestCurrent, + pszSrc, + cchMaxAppend); + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerA(char* pszDest, size_t cchDest, size_t cbDest, const char* pszSrc, size_t cchMaxAppend, char** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + char* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + // ASSERT(cbDest == (cchDest * sizeof(char)) || + // cbDest == (cchDest * sizeof(char)) + (cbDest % sizeof(char))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = ""; + } + } + else + { + hr = StringLengthWorkerA(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != '\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerA(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(char)) + (cbDest % sizeof(char)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerA() + + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = '\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = '\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringCatNExWorkerW(WCHAR* pszDest, size_t cchDest, size_t cbDest, const WCHAR* pszSrc, size_t cchMaxAppend, WCHAR** ppszDestEnd, size_t* pcchRemaining, unsigned long dwFlags) +{ + HRESULT hr = S_OK; + WCHAR* pszDestEnd = pszDest; + size_t cchRemaining = 0; + size_t cchDestCurrent = 0; + + + // ASSERT(cbDest == (cchDest * sizeof(WCHAR)) || + // cbDest == (cchDest * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR))); + + // only accept valid flags + if (dwFlags & (~STRSAFE_VALID_FLAGS)) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + if (dwFlags & STRSAFE_IGNORE_NULLS) + { + if (pszDest == NULL) + { + if ((cchDest == 0) && (cbDest == 0)) + { + cchDestCurrent = 0; + } + else + { + // NULL pszDest and non-zero cchDest/cbDest is invalid + hr = STRSAFE_E_INVALID_PARAMETER; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (pszSrc == NULL) + { + pszSrc = u""; + } + } + else + { + hr = StringLengthWorkerW(pszDest, cchDest, &cchDestCurrent); + + if (SUCCEEDED(hr)) + { + pszDestEnd = pszDest + cchDestCurrent; + cchRemaining = cchDest - cchDestCurrent; + } + } + + if (SUCCEEDED(hr)) + { + if (cchDest == 0) + { + // only fail if there was actually src data to append + if (*pszSrc != L'\0') + { + if (pszDest == NULL) + { + hr = STRSAFE_E_INVALID_PARAMETER; + } + else + { + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + } + } + else + { + // we handle the STRSAFE_FILL_ON_FAILURE and STRSAFE_NULL_ON_FAILURE cases below, so do not pass + // those flags through + hr = StringCopyNExWorkerW(pszDestEnd, + cchRemaining, + (cchRemaining * sizeof(WCHAR)) + (cbDest % sizeof(WCHAR)), + pszSrc, + cchMaxAppend, + &pszDestEnd, + &cchRemaining, + dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE))); + } + } + } + + if (FAILED(hr)) + { + if (pszDest) + { + // STRSAFE_NO_TRUNCATION is taken care of by StringCopyNExWorkerW() + + if (dwFlags & STRSAFE_FILL_ON_FAILURE) + { + memset(pszDest, STRSAFE_GET_FILL_PATTERN(dwFlags), cbDest); + + if (STRSAFE_GET_FILL_PATTERN(dwFlags) == 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + } + else if (cchDest > 0) + { + pszDestEnd = pszDest + cchDest - 1; + cchRemaining = 1; + + // null terminate the end of the string + *pszDestEnd = L'\0'; + } + } + + if (dwFlags & (STRSAFE_NULL_ON_FAILURE)) + { + if (cchDest > 0) + { + pszDestEnd = pszDest; + cchRemaining = cchDest; + + // null terminate the beginning of the string + *pszDestEnd = L'\0'; + } + } + } + } + + if (SUCCEEDED(hr) || (hr == STRSAFE_E_INSUFFICIENT_BUFFER)) + { + if (ppszDestEnd) + { + *ppszDestEnd = pszDestEnd; + } + + if (pcchRemaining) + { + *pcchRemaining = cchRemaining; + } + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerA(const char* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != '\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} + +STRSAFEAPI StringLengthWorkerW(const WCHAR* psz, size_t cchMax, size_t* pcch) +{ + HRESULT hr = S_OK; + size_t cchMaxPrev = cchMax; + + while (cchMax && (*psz != L'\0')) + { + psz++; + cchMax--; + } + + if (cchMax == 0) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (SUCCEEDED(hr) && pcch) + { + *pcch = cchMaxPrev - cchMax; + } + + return hr; +} +#endif // STRSAFE_INLINE + +#endif // _STRSAFE_H_INCLUDED_ diff --git a/lib/coreclr/src/pal/inc/unixasmmacros.inc b/lib/coreclr/src/pal/inc/unixasmmacros.inc new file mode 100644 index 0000000000..f553840a8d --- /dev/null +++ b/lib/coreclr/src/pal/inc/unixasmmacros.inc @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#define INVALIDGCVALUE 0xCCCCCCCD + +#if defined(__APPLE__) +#define C_FUNC(name) _##name +#define EXTERNAL_C_FUNC(name) C_FUNC(name) +#define LOCAL_LABEL(name) L##name +#else +#define C_FUNC(name) name +#if defined(_AMD64_) || defined(_X86_) +#define EXTERNAL_C_FUNC(name) C_FUNC(name)@plt +#else +#define EXTERNAL_C_FUNC(name) C_FUNC(name) +#endif +#define LOCAL_LABEL(name) .L##name +#endif + +#if defined(__APPLE__) +#define C_PLTFUNC(name) _##name +#else +#define C_PLTFUNC(name) name@PLT +#endif + + +.macro END_PROLOGUE +.endm + +.macro SETALIAS New, Old + .equiv \New, \Old +.endm + +#if defined(_X86_) +#include "unixasmmacrosx86.inc" +#elif defined(_AMD64_) +#include "unixasmmacrosamd64.inc" +#elif defined(_ARM_) +#include "unixasmmacrosarm.inc" +#elif defined(_ARM64_) +#include "unixasmmacrosarm64.inc" +#endif diff --git a/lib/coreclr/src/pal/inc/unixasmmacrosamd64.inc b/lib/coreclr/src/pal/inc/unixasmmacrosamd64.inc new file mode 100644 index 0000000000..040ade1f5c --- /dev/null +++ b/lib/coreclr/src/pal/inc/unixasmmacrosamd64.inc @@ -0,0 +1,364 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler +#if defined(__APPLE__) + .cfi_personality 0x9b, C_FUNC(\Handler) // 0x9b == DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4 +#else + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 +#endif + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +#if defined(__APPLE__) + .set LOCAL_LABEL(\Name\()_Size), . - C_FUNC(\Name) + .section __LD,__compact_unwind,regular,debug + .quad C_FUNC(\Name) + .long LOCAL_LABEL(\Name\()_Size) + .long 0x04000000 # DWARF + .quad 0 + .quad 0 +#endif +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) +#if defined(__APPLE__) + .text +#else + .type \Name, %function +#endif +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro LEAF_END Name, Section +#if !defined(__APPLE__) + .size \Name, .-\Name +#endif + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro NOP_6_BYTE + .byte 0x66 + .byte 0x0F + .byte 0x1F + .byte 0x44 + .byte 0x00 + .byte 0x00 +.endm + +.macro NOP_3_BYTE + nop dword ptr [rax] +.endm + +.macro NOP_2_BYTE + xchg ax, ax +.endm + +.macro REPRET + .byte 0xf3 + .byte 0xc3 +.endm + +.macro TAILJMP_RAX + .byte 0x48 + .byte 0xFF + .byte 0xE0 +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + mov \HelperReg, [rip + C_FUNC(\Name)@GOTPCREL] +.endm + +.macro push_nonvol_reg Register + push \Register + .cfi_adjust_cfa_offset 8 + .cfi_rel_offset \Register, 0 +.endm + +.macro pop_nonvol_reg Register + pop \Register + .cfi_adjust_cfa_offset -8 + .cfi_restore \Register +.endm + +.macro alloc_stack Size +.att_syntax + lea -(\Size)(%rsp), %rsp +.intel_syntax noprefix + .cfi_adjust_cfa_offset \Size +.endm + +.macro free_stack Size +.att_syntax + lea \Size(%rsp), %rsp +.intel_syntax noprefix + .cfi_adjust_cfa_offset -\Size +.endm + +.macro set_cfa_register Reg, Offset + .cfi_def_cfa_register \Reg + .cfi_def_cfa_offset \Offset +.endm + +.macro save_reg_postrsp Reg, Offset + __Offset = \Offset + mov qword ptr [rsp + __Offset], \Reg + .cfi_rel_offset \Reg, __Offset +.endm + +.macro restore_reg Reg, Offset + __Offset = \Offset + mov \Reg, [rsp + __Offset] + .cfi_restore \Reg +.endm + +.macro save_xmm128_postrsp Reg, Offset + __Offset = \Offset + movdqa xmmword ptr [rsp + __Offset], \Reg + // NOTE: We cannot use ".cfi_rel_offset \Reg, __Offset" here, + // the xmm registers are not supported by the libunwind +.endm + +.macro restore_xmm128 Reg, ofs + __Offset = \ofs + movdqa \Reg, xmmword ptr [rsp + __Offset] + // NOTE: We cannot use ".cfi_restore \Reg" here, + // the xmm registers are not supported by the libunwind + +.endm + +.macro PUSH_CALLEE_SAVED_REGISTERS + + push_register rbp + push_register rbx + push_register r15 + push_register r14 + push_register r13 + push_register r12 + +.endm + +.macro POP_CALLEE_SAVED_REGISTERS + + pop_nonvol_reg r12 + pop_nonvol_reg r13 + pop_nonvol_reg r14 + pop_nonvol_reg r15 + pop_nonvol_reg rbx + pop_nonvol_reg rbp + +.endm + +.macro push_register Reg + push \Reg + .cfi_adjust_cfa_offset 8 +.endm + +.macro push_eflags + pushfq + .cfi_adjust_cfa_offset 8 +.endm + +.macro push_argument_register Reg + push_register \Reg +.endm + +.macro PUSH_ARGUMENT_REGISTERS + + push_argument_register r9 + push_argument_register r8 + push_argument_register rcx + push_argument_register rdx + push_argument_register rsi + push_argument_register rdi + +.endm + +.macro pop_register Reg + pop \Reg + .cfi_adjust_cfa_offset -8 +.endm + +.macro pop_eflags + popfq + .cfi_adjust_cfa_offset -8 +.endm + +.macro pop_argument_register Reg + pop_register \Reg +.endm + +.macro POP_ARGUMENT_REGISTERS + + pop_argument_register rdi + pop_argument_register rsi + pop_argument_register rdx + pop_argument_register rcx + pop_argument_register r8 + pop_argument_register r9 + +.endm + +.macro SAVE_FLOAT_ARGUMENT_REGISTERS ofs + + save_xmm128_postrsp xmm0, \ofs + save_xmm128_postrsp xmm1, \ofs + 0x10 + save_xmm128_postrsp xmm2, \ofs + 0x20 + save_xmm128_postrsp xmm3, \ofs + 0x30 + save_xmm128_postrsp xmm4, \ofs + 0x40 + save_xmm128_postrsp xmm5, \ofs + 0x50 + save_xmm128_postrsp xmm6, \ofs + 0x60 + save_xmm128_postrsp xmm7, \ofs + 0x70 + +.endm + +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS ofs + + restore_xmm128 xmm0, \ofs + restore_xmm128 xmm1, \ofs + 0x10 + restore_xmm128 xmm2, \ofs + 0x20 + restore_xmm128 xmm3, \ofs + 0x30 + restore_xmm128 xmm4, \ofs + 0x40 + restore_xmm128 xmm5, \ofs + 0x50 + restore_xmm128 xmm6, \ofs + 0x60 + restore_xmm128 xmm7, \ofs + 0x70 + +.endm + +// Stack layout: +// +// (stack parameters) +// ... +// return address +// CalleeSavedRegisters::rbp +// CalleeSavedRegisters::rbx +// CalleeSavedRegisters::r15 +// CalleeSavedRegisters::r14 +// CalleeSavedRegisters::r13 +// CalleeSavedRegisters::r12 +// ArgumentRegisters::r9 +// ArgumentRegisters::r8 +// ArgumentRegisters::rcx +// ArgumentRegisters::rdx +// ArgumentRegisters::rsi +// ArgumentRegisters::rdi <- __PWTB_StackAlloc, __PWTB_TransitionBlock +// padding to align xmm save area +// xmm7 +// xmm6 +// xmm5 +// xmm4 +// xmm3 +// xmm2 +// xmm1 +// xmm0 <- __PWTB_FloatArgumentRegisters +// extra locals + padding to qword align +.macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, stackAllocOnEntry = 0, stackAllocSpill1, stackAllocSpill2, stackAllocSpill3 + + set_cfa_register rsp, 8 + + __PWTB_FloatArgumentRegisters = \extraLocals + + .if ((__PWTB_FloatArgumentRegisters % 16) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 + .endif + + __PWTB_StackAlloc = __PWTB_FloatArgumentRegisters + 8 * 16 + 8 // 8 floating point registers + __PWTB_TransitionBlock = __PWTB_StackAlloc + + .if \stackAllocOnEntry >= 4*8 + .error "Max supported stackAllocOnEntry is 3*8" + .endif + + .if \stackAllocOnEntry > 0 + .cfi_adjust_cfa_offset \stackAllocOnEntry + .endif + + // PUSH_CALLEE_SAVED_REGISTERS expanded here + + .if \stackAllocOnEntry < 8 + push_nonvol_reg rbp + mov rbp, rsp + .endif + + .if \stackAllocOnEntry < 2*8 + push_nonvol_reg rbx + .endif + + .if \stackAllocOnEntry < 3*8 + push_nonvol_reg r15 + .endif + + push_nonvol_reg r14 + push_nonvol_reg r13 + push_nonvol_reg r12 + + // ArgumentRegisters + PUSH_ARGUMENT_REGISTERS + + .if \stackAllocOnEntry >= 3*8 + mov \stackAllocSpill3, [rsp + 0x48] + save_reg_postrsp r15, 0x48 + .endif + + .if \stackAllocOnEntry >= 2*8 + mov \stackAllocSpill2, [rsp + 0x50] + save_reg_postrsp rbx, 0x50 + .endif + + .if \stackAllocOnEntry >= 8 + mov \stackAllocSpill1, [rsp + 0x58] + save_reg_postrsp rbp, 0x58 + lea rbp, [rsp + 0x58] + .endif + + alloc_stack __PWTB_StackAlloc + SAVE_FLOAT_ARGUMENT_REGISTERS __PWTB_FloatArgumentRegisters + + END_PROLOGUE + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN + + free_stack __PWTB_StackAlloc + POP_ARGUMENT_REGISTERS + POP_CALLEE_SAVED_REGISTERS + ret + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + RESTORE_FLOAT_ARGUMENT_REGISTERS __PWTB_FloatArgumentRegisters + free_stack __PWTB_StackAlloc + POP_ARGUMENT_REGISTERS + POP_CALLEE_SAVED_REGISTERS + +.endm + +.macro RESET_FRAME_WITH_RBP + + mov rsp, rbp + set_cfa_register rsp, 16 + pop_nonvol_reg rbp + .cfi_same_value rbp + +.endm diff --git a/lib/coreclr/src/pal/inc/unixasmmacrosarm.inc b/lib/coreclr/src/pal/inc/unixasmmacrosarm.inc new file mode 100644 index 0000000000..e4a3658b6c --- /dev/null +++ b/lib/coreclr/src/pal/inc/unixasmmacrosarm.inc @@ -0,0 +1,268 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.macro LEAF_ENTRY Name, Section + .thumb_func + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .fnstart +.endm + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .personality C_FUNC(\Handler) + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro NESTED_END_MARKED Name, Section + LEAF_END_MARKED \Name, \Section +.endm + +.macro PATCH_LABEL Name + .thumb_func + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .fnend +.endm + +.macro LEAF_END_MARKED Name, Section + .thumb_func + .global C_FUNC(\Name\()_End) +C_FUNC(\Name\()_End): + LEAF_END \Name, \Section +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + ldr \HelperReg, [pc, #C_FUNC(\Name)@GOTPCREL] +.endm + +.macro push_nonvol_reg Register + push \Register + .save \Register +.endm + +.macro pop_nonvol_reg Register + pop \Register +.endm + +.macro vpush_nonvol_reg Register + vpush \Register + .vsave \Register +.endm + +.macro vpop_nonvol_reg Register + vpop \Register +.endm + +.macro alloc_stack Size + sub sp, sp, (\Size) + .pad #(\Size) +.endm + +.macro free_stack Size + add sp, sp, (\Size) +.endm + +.macro POP_CALLEE_SAVED_REGISTERS + pop_nonvol_reg "{r4-r11, lr}" +.endm + +.macro PUSH_CALLEE_SAVED_REGISTERS + push_nonvol_reg "{r4-r11, lr}" +.endm + +.macro push_register Reg + push \Reg +.endm + +.macro push_argument_register Reg + push_register \Reg +.endm + +.macro PUSH_ARGUMENT_REGISTERS + push {r0-r3} + .save {r0-r3} +.endm + +.macro pop_register Reg + pop \Reg +.endm + +.macro pop_argument_register Reg + pop_register \Reg +.endm + +.macro POP_ARGUMENT_REGISTERS + pop {r0-r3} +.endm + +// Stack layout: +// +// (stack parameters) +// ... +// ArgumentRegisters::r3 +// ArgumentRegisters::r2 +// ArgumentRegisters::r1 +// ArgumentRegisters::r0 +// CalleeSavedRegisters::lr +// CalleeSavedRegisters::r11 +// CalleeSavedRegisters::r10 +// CalleeSavedRegisters::r9 +// CalleeSavedRegisters::r8 +// CalleeSavedRegisters::r7 <- r7 +// CalleeSavedRegisters::r6 +// CalleeSavedRegisters::r5 +// CalleeSavedRegisters::r4 <- __PWTB_StackAlloc, __PWTB_TransitionBlock +// padding to align float save area +// d7 +// d6 +// d5 +// d4 +// d3 +// d2 +// d1 +// d0 <- __PWTB_FloatArgumentRegisters +.macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, saveFpArgs = 1, pushArgRegs = 0 + + __PWTB_FloatArgumentRegisters = \extraLocals + __PWTB_SaveFPArgs = \saveFpArgs + + .if (__PWTB_SaveFPArgs == 1) + .if ((__PWTB_FloatArgumentRegisters % 8) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 4 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + 8 * 8 + 4 // 8 floating point registers + padding + .else + .if ((__PWTB_FloatArgumentRegisters % 8) == 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 4 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + .endif + + __PWTB_StackAlloc = __PWTB_TransitionBlock + + .ifnc \pushArgRegs, DoNotPushArgRegs + PUSH_ARGUMENT_REGISTERS + .endif + + PUSH_CALLEE_SAVED_REGISTERS + PROLOG_STACK_SAVE_OFFSET r7, #12 + // let r7 point the saved r7 in the stack (clang FP style) + + alloc_stack __PWTB_StackAlloc + + .if (__PWTB_SaveFPArgs == 1) + add r6, sp, #(__PWTB_FloatArgumentRegisters) + vstm r6, {d0-d7} + .endif + + CHECK_STACK_ALIGNMENT + + END_PROLOGUE + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN + + free_stack __PWTB_StackAlloc + POP_CALLEE_SAVED_REGISTERS + free_stack 16 + bx lr + +.endm + +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + add r6, sp, #(__PWTB_FloatArgumentRegisters) + vldm r6, {d0-d7} + .endif + + free_stack __PWTB_StackAlloc + POP_CALLEE_SAVED_REGISTERS + POP_ARGUMENT_REGISTERS + +.endm + +.macro EMIT_BREAKPOINT + .inst.w 0xde01 +.endm + +.macro PROLOG_PUSH RegList + push_nonvol_reg "\RegList" +.endm + +.macro PROLOG_VPUSH RegList + vpush_nonvol_reg "\RegList" +.endm + +.macro PROLOG_STACK_SAVE Register + .setfp \Register, sp + mov \Register, sp +.endm + +.macro PROLOG_STACK_SAVE_OFFSET Register, Offset + .setfp \Register, sp, \Offset + add \Register, sp, \Offset +.endm + +.macro EPILOG_STACK_FREE Size + add sp, sp, \Size +.endm + +.macro EPILOG_STACK_RESTORE Register + mov sp, \Register +.endm + +.macro EPILOG_STACK_RESTORE_OFFSET Register, Offset + sub \Register, \Offset + mov sp, \Register +.endm + +.macro EPILOG_BRANCH Target + b \Target +.endm + +.macro EPILOG_BRANCH_REG reg + bx \reg +.endm + +.macro EPILOG_POP RegList + pop_nonvol_reg "\RegList" +.endm + +.macro EPILOG_VPOP RegList + vpop_nonvol_reg "\RegList" +.endm + +//----------------------------------------------------------------------------- +// Macro used to check (in debug builds only) whether the stack is 64-bit aligned (a requirement before calling +// out into C++/OS code). Invoke this directly after your prolog (if the stack frame size is fixed) or directly +// before a call (if you have a frame pointer and a dynamic stack). A breakpoint will be invoked if the stack +// is misaligned. +// +.macro CHECK_STACK_ALIGNMENT + +#ifdef _DEBUG + push {r0} + add r0, sp, #4 + tst r0, #7 + pop {r0} + beq 0f + EMIT_BREAKPOINT +0: +#endif +.endm diff --git a/lib/coreclr/src/pal/inc/unixasmmacrosarm64.inc b/lib/coreclr/src/pal/inc/unixasmmacrosarm64.inc new file mode 100644 index 0000000000..6db1f242f3 --- /dev/null +++ b/lib/coreclr/src/pal/inc/unixasmmacrosarm64.inc @@ -0,0 +1,344 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro PREPARE_EXTERNAL_VAR Name, HelperReg + adrp \HelperReg, \Name + add \HelperReg, \HelperReg, :lo12:\Name +.endm + +.macro PROLOG_STACK_ALLOC Size + sub sp, sp, \Size +.endm + +.macro EPILOG_STACK_FREE Size + add sp, sp, \Size + .cfi_adjust_cfa_offset -\Size +.endm + +.macro EPILOG_STACK_RESTORE + mov sp, fp + .cfi_restore sp +.endm + +.macro PROLOG_SAVE_REG reg, ofs + str \reg, [sp, \ofs] + .cfi_rel_offset \reg, \ofs +.endm + +.macro PROLOG_SAVE_REG_PAIR reg1, reg2, ofs + stp \reg1, \reg2, [sp, \ofs] + .cfi_rel_offset \reg1, \ofs + .cfi_rel_offset \reg2, \ofs + 8 + .ifc \reg1, fp + mov fp, sp + .cfi_def_cfa_register fp + .endif +.endm + +.macro PROLOG_SAVE_REG_PAIR_INDEXED reg1, reg2, ofs + stp \reg1, \reg2, [sp, \ofs]! + .cfi_adjust_cfa_offset -\ofs + .cfi_rel_offset \reg1, 0 + .cfi_rel_offset \reg2, 8 + .ifc \reg1, fp + mov fp, sp + .cfi_def_cfa_register fp + .endif +.endm + +.macro EPILOG_RESTORE_REG reg, ofs + ldr \reg, [sp, \ofs] + .cfi_restore \reg1 +.endm + +.macro EPILOG_RESTORE_REG_PAIR reg1, reg2, ofs + ldp \reg1, \reg2, [sp, \ofs] + .cfi_restore \reg1 + .cfi_restore \reg2 +.endm + +.macro EPILOG_RESTORE_REG_PAIR_INDEXED reg1, reg2, ofs + ldp \reg1, \reg2, [sp], \ofs + .cfi_restore \reg1 + .cfi_restore \reg2 + .cfi_adjust_cfa_offset -\ofs +.endm + +.macro EPILOG_RETURN + ret +.endm + +.macro EMIT_BREAKPOINT + brk #0 +.endm + +//----------------------------------------------------------------------------- +// Define the prolog for a TransitionFrame-based method. This macro should be called first in the method and +// comprises the entire prolog (i.e. don't modify SP after calling this).The locals must be 8 byte aligned +// +// Stack layout: +// +// (stack parameters) +// ... +// fp +// lr +// CalleeSavedRegisters::x28 +// CalleeSavedRegisters::x27 +// CalleeSavedRegisters::x26 +// CalleeSavedRegisters::x25 +// CalleeSavedRegisters::x24 +// CalleeSavedRegisters::x23 +// CalleeSavedRegisters::x22 +// CalleeSavedRegisters::x21 +// CalleeSavedRegisters::x20 +// CalleeSavedRegisters::x19 +// CalleeSavedRegisters::x30 (Lr) +// CalleeSavedRegisters::x29 (Fp) +// ArgumentRegisters::x7 +// ArgumentRegisters::x6 +// ArgumentRegisters::x5 +// ArgumentRegisters::x4 +// ArgumentRegisters::x3 +// ArgumentRegisters::x2 +// ArgumentRegisters::x1 +// ArgumentRegisters::x0 +// FloatRegisters::q7 +// FloatRegisters::q6 +// FloatRegisters::q5 +// FloatRegisters::q4 +// FloatRegisters::q3 +// FloatRegisters::q2 +// FloatRegisters::q1 +// FloatRegisters::q0 +.macro PROLOG_WITH_TRANSITION_BLOCK extraLocals = 0, SaveFPArgs = 1 + + __PWTB_FloatArgumentRegisters = \extraLocals + __PWTB_SaveFPArgs = \SaveFPArgs + + .if ((__PWTB_FloatArgumentRegisters % 16) != 0) + __PWTB_FloatArgumentRegisters = __PWTB_FloatArgumentRegisters + 8 + .endif + + __PWTB_TransitionBlock = __PWTB_FloatArgumentRegisters + + .if (__PWTB_SaveFPArgs == 1) + __PWTB_TransitionBlock = __PWTB_TransitionBlock + SIZEOF__FloatArgumentRegisters + .endif + + __PWTB_StackAlloc = __PWTB_TransitionBlock + __PWTB_ArgumentRegisters = __PWTB_StackAlloc + 104 + __PWTB_ArgumentRegister_FirstArg = __PWTB_ArgumentRegisters + 8 + + PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -176 + // Spill callee saved registers + PROLOG_SAVE_REG_PAIR x19, x20, 16 + PROLOG_SAVE_REG_PAIR x21, x22, 32 + PROLOG_SAVE_REG_PAIR x23, x24, 48 + PROLOG_SAVE_REG_PAIR x25, x26, 64 + PROLOG_SAVE_REG_PAIR x27, x28, 80 + + // Allocate space for the rest of the frame + PROLOG_STACK_ALLOC __PWTB_StackAlloc + + // Spill argument registers. + SAVE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + + .if (__PWTB_SaveFPArgs == 1) + SAVE_FLOAT_ARGUMENT_REGISTERS sp, \extraLocals + .endif + +.endm + +//----------------------------------------------------------------------------- +// The Following sets of SAVE_*_REGISTERS expect the memory to be reserved and +// base address to be passed in $reg +// + +// Reserve 64 bytes of memory before calling SAVE_ARGUMENT_REGISTERS +.macro SAVE_ARGUMENT_REGISTERS reg, ofs + + str x8, [\reg, #(\ofs)] + stp x0, x1, [\reg, #(\ofs + 8)] + stp x2, x3, [\reg, #(\ofs + 24)] + stp x4, x5, [\reg, #(\ofs + 40)] + stp x6, x7, [\reg, #(\ofs + 56)] + +.endm + +// Reserve 128 bytes of memory before calling SAVE_FLOAT_ARGUMENT_REGISTERS +.macro SAVE_FLOAT_ARGUMENT_REGISTERS reg, ofs + + stp q0, q1, [\reg, #(\ofs)] + stp q2, q3, [\reg, #(\ofs + 32)] + stp q4, q5, [\reg, #(\ofs + 64)] + stp q6, q7, [\reg, #(\ofs + 96)] + +.endm + +.macro RESTORE_ARGUMENT_REGISTERS reg, ofs + + ldr x8, [\reg, #(\ofs)] + ldp x0, x1, [\reg, #(\ofs + 8)] + ldp x2, x3, [\reg, #(\ofs + 24)] + ldp x4, x5, [\reg, #(\ofs + 40)] + ldp x6, x7, [\reg, #(\ofs + 56)] + +.endm + +.macro RESTORE_FLOAT_ARGUMENT_REGISTERS reg, ofs + + ldp q0, q1, [\reg, #(\ofs)] + ldp q2, q3, [\reg, #(\ofs + 32)] + ldp q4, q5, [\reg, #(\ofs + 64)] + ldp q6, q7, [\reg, #(\ofs + 96)] + +.endm + +.macro EPILOG_BRANCH Target + b \Target +.endm + +.macro EPILOG_BRANCH_REG reg + + br \reg + +.endm + + +.macro EPILOG_WITH_TRANSITION_BLOCK_RETURN + + EPILOG_STACK_FREE __PWTB_StackAlloc + + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 + ret + +.endm + + +//----------------------------------------------------------------------------- +// Provides a matching epilog to PROLOG_WITH_TRANSITION_BLOCK and ends by preparing for tail-calling. +// Since this is a tail call argument registers are restored. +// +.macro EPILOG_WITH_TRANSITION_BLOCK_TAILCALL + + .if (__PWTB_SaveFPArgs == 1) + RESTORE_FLOAT_ARGUMENT_REGISTERS sp, __PWTB_FloatArgumentRegisters + .endif + + RESTORE_ARGUMENT_REGISTERS sp, __PWTB_ArgumentRegisters + + EPILOG_STACK_FREE __PWTB_StackAlloc + + EPILOG_RESTORE_REG_PAIR x19, x20, 16 + EPILOG_RESTORE_REG_PAIR x21, x22, 32 + EPILOG_RESTORE_REG_PAIR x23, x24, 48 + EPILOG_RESTORE_REG_PAIR x25, x26, 64 + EPILOG_RESTORE_REG_PAIR x27, x28, 80 + EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 176 + +.endm + +// ------------------------------------------------------------------ +// Macro to generate Redirection Stubs +// +// $reason : reason for redirection +// Eg. GCThreadControl +// NOTE: If you edit this macro, make sure you update GetCONTEXTFromRedirectedStubStackFrame. +// This function is used by both the personality routine and the debugger to retrieve the original CONTEXT. +.macro GenerateRedirectedHandledJITCaseStub reason + +#if NOTYET + GBLS __RedirectionStubFuncName + GBLS __RedirectionStubEndFuncName + GBLS __RedirectionFuncName +__RedirectionStubFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_Stub" +__RedirectionStubEndFuncName SETS "RedirectedHandledJITCaseFor":CC:"$reason":CC:"_StubEnd" +__RedirectionFuncName SETS "|?RedirectedHandledJITCaseFor":CC:"$reason":CC:"@Thread@@CAXXZ|" + + IMPORT $__RedirectionFuncName + + NESTED_ENTRY $__RedirectionStubFuncName + PROLOG_SAVE_REG_PAIR fp, lr, -16 + sub sp, sp, #16 // stack slot for CONTEXT * and padding + + //REDIRECTSTUB_SP_OFFSET_CONTEXT is defined in asmconstants.h and is used in GetCONTEXTFromRedirectedStubStackFrame + //If CONTEXT is not saved at 0 offset from SP it must be changed as well. + ASSERT REDIRECTSTUB_SP_OFFSET_CONTEXT == 0 + + // Stack alignment. This check is necessary as this function can be + // entered before complete execution of the prolog of another function. + and x8, fp, #15 + sub sp, sp, x8 + + + // + // Save a copy of the redirect CONTEXT*. + // This is needed for the debugger to unwind the stack. + // + bl GetCurrentSavedRedirectContext + str x0, [sp] + + // + // Fetch the interrupted pc and save it as our return address. + // + ldr x1, [x0, #CONTEXT_Pc] + str x1, [fp, #8] + + // + // Call target, which will do whatever we needed to do in the context + // of the target thread, and will RtlRestoreContext when it is done. + // + bl $__RedirectionFuncName + + EMIT_BREAKPOINT // Unreachable + +// Put a label here to tell the debugger where the end of this function is. +$__RedirectionStubEndFuncName + EXPORT $__RedirectionStubEndFuncName + + NESTED_END +#else + EMIT_BREAKPOINT +#endif + +.endm diff --git a/lib/coreclr/src/pal/inc/unixasmmacrosx86.inc b/lib/coreclr/src/pal/inc/unixasmmacrosx86.inc new file mode 100644 index 0000000000..7730505bc3 --- /dev/null +++ b/lib/coreclr/src/pal/inc/unixasmmacrosx86.inc @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +.macro NESTED_ENTRY Name, Section, Handler + LEAF_ENTRY \Name, \Section + .ifnc \Handler, NoHandler + .cfi_personality 0x1b, C_FUNC(\Handler) // 0x1b == DW_EH_PE_pcrel | DW_EH_PE_sdata4 + .endif +.endm + +.macro NESTED_END Name, Section + LEAF_END \Name, \Section +.endm + +.macro LEAF_ENTRY Name, Section + .global C_FUNC(\Name) + .type \Name, %function +C_FUNC(\Name): + .cfi_startproc +.endm + +.macro PATCH_LABEL Name + .global C_FUNC(\Name) +C_FUNC(\Name): +.endm + +.macro LEAF_END Name, Section + .size \Name, .-\Name + .cfi_endproc +.endm + +.macro LEAF_END_MARKED Name, Section +C_FUNC(\Name\()_End): + .global C_FUNC(\Name\()_End) + LEAF_END \Name, \Section +.endm + +.macro PROLOG_BEG + push ebp + .cfi_def_cfa_offset 8 + .cfi_offset ebp, -8 + mov ebp, esp +.endm + +.macro PROLOG_PUSH Reg + push \Reg + .cfi_adjust_cfa_offset 4 + .cfi_rel_offset \Reg, 0 +.endm + +.macro PROLOG_END + .cfi_def_cfa_register ebp + .cfi_def_cfa_offset 8 +.endm + +.macro EPILOG_BEG +.endm + +.macro EPILOG_POP Reg + pop \Reg + .cfi_restore \Reg +.endm + +.macro EPILOG_END + pop ebp +.endm + +.macro ESP_PROLOG_BEG +.endm + +.macro ESP_PROLOG_PUSH Reg + PROLOG_PUSH \Reg +.endm + +.macro ESP_PROLOG_ALLOC Size + sub esp, \Size + .cfi_adjust_cfa_offset \Size +.endm + +.macro ESP_PROLOG_END + .cfi_def_cfa_register esp +.endm + +.macro ESP_EPILOG_BEG +.endm + +.macro ESP_EPILOG_POP Reg + EPILOG_POP \Reg +.endm + +.macro ESP_EPILOG_FREE Size + add esp, \Size + .cfi_adjust_cfa_offset -\Size +.endm + +.macro ESP_EPILOG_END +.endm + +.macro PREPARE_EXTERNAL_VAR Name, Reg +.att_syntax + call 0f +0: + popl %\Reg +1: + addl $_GLOBAL_OFFSET_TABLE_ + (1b - 0b), %\Reg + movl C_FUNC(\Name)@GOT(%\Reg), %\Reg +.intel_syntax noprefix +.endm + +.macro CHECK_STACK_ALIGNMENT +#ifdef _DEBUG + test esp, 0Fh + je 0f + int3 +0: +#endif // _DEBUG +.endm diff --git a/lib/coreclr/src/pal/prebuilt/inc/CMakeLists.txt b/lib/coreclr/src/pal/prebuilt/inc/CMakeLists.txt new file mode 100644 index 0000000000..ae9892bb77 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.8.12.2) + +project(COREPAL) + +_install (FILES corerror.h corprof.h DESTINATION inc) + diff --git a/lib/coreclr/src/pal/prebuilt/inc/asm_version.h b/lib/coreclr/src/pal/prebuilt/inc/asm_version.h new file mode 100644 index 0000000000..44e09c0e8e --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/asm_version.h @@ -0,0 +1,22 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#if defined(SILVERLIGHT) +#if defined(FEATURE_CORESYSTEM) +#define asm_rmj 4 +#define asm_rmm 0 +#define asm_rup 0 +#define asm_rpt 0 +#else +#define asm_rmj 5 +#define asm_rmm 0 +#define asm_rup 5 +#define asm_rpt 0 +#endif +#else +#define asm_rmj 4 +#define asm_rmm 0 +#define asm_rup 0 +#define asm_rpt 0 +#endif + diff --git a/lib/coreclr/src/pal/prebuilt/inc/buildnumber.h b/lib/coreclr/src/pal/prebuilt/inc/buildnumber.h new file mode 100644 index 0000000000..5aee76ab5e --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/buildnumber.h @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#define BuildNumberMajor 30319 +#define BuildNumberMinor 0 +#define BuildNumberMajor_A "30319" +#define BuildNumberMinor_A "00" +#define BuildNumbers_A "30319.00" +#define BuildNumbers_T TEXT("30319.00") + +#define NDPBuildNumberMajor 30319 +#define NDPBuildNumberMinor 0 +#define NDPBuildNumbers_A "30319.00" +#define NDPBuildNumbers_T TEXT("30319.00") + +#define NDPFileVersionMinor 5 +#define NDPFileVersionBuild 30319 +#define NDPFileVersionRevision 0 + +#define NDPFileVersionMinor_A "5" +#define NDPFileVersionBuild_A "30319" +#define NDPFileVersionRevision_A "00" diff --git a/lib/coreclr/src/pal/prebuilt/inc/clrdata.h b/lib/coreclr/src/pal/prebuilt/inc/clrdata.h new file mode 100644 index 0000000000..5d3a764dfb --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/clrdata.h @@ -0,0 +1,1146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __clrdata_h__ +#define __clrdata_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICLRDataTarget_FWD_DEFINED__ +#define __ICLRDataTarget_FWD_DEFINED__ +typedef interface ICLRDataTarget ICLRDataTarget; + +#endif /* __ICLRDataTarget_FWD_DEFINED__ */ + + +#ifndef __ICLRDataTarget2_FWD_DEFINED__ +#define __ICLRDataTarget2_FWD_DEFINED__ +typedef interface ICLRDataTarget2 ICLRDataTarget2; + +#endif /* __ICLRDataTarget2_FWD_DEFINED__ */ + + +#ifndef __ICLRDataTarget3_FWD_DEFINED__ +#define __ICLRDataTarget3_FWD_DEFINED__ +typedef interface ICLRDataTarget3 ICLRDataTarget3; + +#endif /* __ICLRDataTarget3_FWD_DEFINED__ */ + + +#ifndef __ICLRMetadataLocator_FWD_DEFINED__ +#define __ICLRMetadataLocator_FWD_DEFINED__ +typedef interface ICLRMetadataLocator ICLRMetadataLocator; + +#endif /* __ICLRMetadataLocator_FWD_DEFINED__ */ + + +#ifndef __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ +#define __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ +typedef interface ICLRDataEnumMemoryRegionsCallback ICLRDataEnumMemoryRegionsCallback; + +#endif /* __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ */ + + +#ifndef __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ +#define __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ +typedef interface ICLRDataEnumMemoryRegionsCallback2 ICLRDataEnumMemoryRegionsCallback2; + +#endif /* __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ */ + + +#ifndef __ICLRDataEnumMemoryRegions_FWD_DEFINED__ +#define __ICLRDataEnumMemoryRegions_FWD_DEFINED__ +typedef interface ICLRDataEnumMemoryRegions ICLRDataEnumMemoryRegions; + +#endif /* __ICLRDataEnumMemoryRegions_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_clrdata_0000_0000 */ +/* [local] */ + + + + + + + +typedef ULONG64 CLRDATA_ADDRESS; + +STDAPI CLRDataCreateInstance(REFIID iid, ICLRDataTarget* target, void** iface); +typedef HRESULT (STDAPICALLTYPE* PFN_CLRDataCreateInstance)(REFIID iid, ICLRDataTarget* target, void** iface); + + +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0000_v0_0_s_ifspec; + +#ifndef __ICLRDataTarget_INTERFACE_DEFINED__ +#define __ICLRDataTarget_INTERFACE_DEFINED__ + +/* interface ICLRDataTarget */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataTarget; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3E11CCEE-D08B-43e5-AF01-32717A64DA03") + ICLRDataTarget : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMachineType( + /* [out] */ ULONG32 *machineType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPointerSize( + /* [out] */ ULONG32 *pointerSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetImageBase( + /* [string][in] */ LPCWSTR imagePath, + /* [out] */ CLRDATA_ADDRESS *baseAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesRead) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesWritten) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTLSValue( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTLSValue( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( + /* [out] */ ULONG32 *threadID) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *context) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE *context) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataTargetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataTarget * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataTarget * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataTarget * This); + + HRESULT ( STDMETHODCALLTYPE *GetMachineType )( + ICLRDataTarget * This, + /* [out] */ ULONG32 *machineType); + + HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( + ICLRDataTarget * This, + /* [out] */ ULONG32 *pointerSize); + + HRESULT ( STDMETHODCALLTYPE *GetImageBase )( + ICLRDataTarget * This, + /* [string][in] */ LPCWSTR imagePath, + /* [out] */ CLRDATA_ADDRESS *baseAddress); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + ICLRDataTarget * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesRead); + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + ICLRDataTarget * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesWritten); + + HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( + ICLRDataTarget * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( + ICLRDataTarget * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICLRDataTarget * This, + /* [out] */ ULONG32 *threadID); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICLRDataTarget * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICLRDataTarget * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *Request )( + ICLRDataTarget * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + END_INTERFACE + } ICLRDataTargetVtbl; + + interface ICLRDataTarget + { + CONST_VTBL struct ICLRDataTargetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataTarget_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataTarget_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataTarget_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataTarget_GetMachineType(This,machineType) \ + ( (This)->lpVtbl -> GetMachineType(This,machineType) ) + +#define ICLRDataTarget_GetPointerSize(This,pointerSize) \ + ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) + +#define ICLRDataTarget_GetImageBase(This,imagePath,baseAddress) \ + ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) + +#define ICLRDataTarget_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) + +#define ICLRDataTarget_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ + ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) + +#define ICLRDataTarget_GetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget_SetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget_GetCurrentThreadID(This,threadID) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) + +#define ICLRDataTarget_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) + +#define ICLRDataTarget_SetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + +#define ICLRDataTarget_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataTarget_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDataTarget2_INTERFACE_DEFINED__ +#define __ICLRDataTarget2_INTERFACE_DEFINED__ + +/* interface ICLRDataTarget2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataTarget2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6d05fae3-189c-4630-a6dc-1c251e1c01ab") + ICLRDataTarget2 : public ICLRDataTarget + { + public: + virtual HRESULT STDMETHODCALLTYPE AllocVirtual( + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags, + /* [in] */ ULONG32 protectFlags, + /* [out] */ CLRDATA_ADDRESS *virt) = 0; + + virtual HRESULT STDMETHODCALLTYPE FreeVirtual( + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataTarget2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataTarget2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataTarget2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataTarget2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetMachineType )( + ICLRDataTarget2 * This, + /* [out] */ ULONG32 *machineType); + + HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( + ICLRDataTarget2 * This, + /* [out] */ ULONG32 *pointerSize); + + HRESULT ( STDMETHODCALLTYPE *GetImageBase )( + ICLRDataTarget2 * This, + /* [string][in] */ LPCWSTR imagePath, + /* [out] */ CLRDATA_ADDRESS *baseAddress); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + ICLRDataTarget2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesRead); + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + ICLRDataTarget2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesWritten); + + HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( + ICLRDataTarget2 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( + ICLRDataTarget2 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICLRDataTarget2 * This, + /* [out] */ ULONG32 *threadID); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICLRDataTarget2 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICLRDataTarget2 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *Request )( + ICLRDataTarget2 * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( + ICLRDataTarget2 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags, + /* [in] */ ULONG32 protectFlags, + /* [out] */ CLRDATA_ADDRESS *virt); + + HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( + ICLRDataTarget2 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags); + + END_INTERFACE + } ICLRDataTarget2Vtbl; + + interface ICLRDataTarget2 + { + CONST_VTBL struct ICLRDataTarget2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataTarget2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataTarget2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataTarget2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataTarget2_GetMachineType(This,machineType) \ + ( (This)->lpVtbl -> GetMachineType(This,machineType) ) + +#define ICLRDataTarget2_GetPointerSize(This,pointerSize) \ + ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) + +#define ICLRDataTarget2_GetImageBase(This,imagePath,baseAddress) \ + ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) + +#define ICLRDataTarget2_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) + +#define ICLRDataTarget2_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ + ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) + +#define ICLRDataTarget2_GetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget2_SetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget2_GetCurrentThreadID(This,threadID) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) + +#define ICLRDataTarget2_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) + +#define ICLRDataTarget2_SetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + +#define ICLRDataTarget2_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + + +#define ICLRDataTarget2_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ + ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) + +#define ICLRDataTarget2_FreeVirtual(This,addr,size,typeFlags) \ + ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataTarget2_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDataTarget3_INTERFACE_DEFINED__ +#define __ICLRDataTarget3_INTERFACE_DEFINED__ + +/* interface ICLRDataTarget3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataTarget3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("a5664f95-0af4-4a1b-960e-2f3346b4214c") + ICLRDataTarget3 : public ICLRDataTarget2 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetExceptionRecord( + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *bufferUsed, + /* [size_is][out] */ BYTE *buffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetExceptionContextRecord( + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *bufferUsed, + /* [size_is][out] */ BYTE *buffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetExceptionThreadID( + /* [out] */ ULONG32 *threadID) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataTarget3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataTarget3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataTarget3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataTarget3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetMachineType )( + ICLRDataTarget3 * This, + /* [out] */ ULONG32 *machineType); + + HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( + ICLRDataTarget3 * This, + /* [out] */ ULONG32 *pointerSize); + + HRESULT ( STDMETHODCALLTYPE *GetImageBase )( + ICLRDataTarget3 * This, + /* [string][in] */ LPCWSTR imagePath, + /* [out] */ CLRDATA_ADDRESS *baseAddress); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + ICLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesRead); + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + ICLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesWritten); + + HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICLRDataTarget3 * This, + /* [out] */ ULONG32 *threadID); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *Request )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( + ICLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags, + /* [in] */ ULONG32 protectFlags, + /* [out] */ CLRDATA_ADDRESS *virt); + + HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( + ICLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionRecord )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *bufferUsed, + /* [size_is][out] */ BYTE *buffer); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionContextRecord )( + ICLRDataTarget3 * This, + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *bufferUsed, + /* [size_is][out] */ BYTE *buffer); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionThreadID )( + ICLRDataTarget3 * This, + /* [out] */ ULONG32 *threadID); + + END_INTERFACE + } ICLRDataTarget3Vtbl; + + interface ICLRDataTarget3 + { + CONST_VTBL struct ICLRDataTarget3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataTarget3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataTarget3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataTarget3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataTarget3_GetMachineType(This,machineType) \ + ( (This)->lpVtbl -> GetMachineType(This,machineType) ) + +#define ICLRDataTarget3_GetPointerSize(This,pointerSize) \ + ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) + +#define ICLRDataTarget3_GetImageBase(This,imagePath,baseAddress) \ + ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) + +#define ICLRDataTarget3_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) + +#define ICLRDataTarget3_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ + ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) + +#define ICLRDataTarget3_GetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget3_SetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) + +#define ICLRDataTarget3_GetCurrentThreadID(This,threadID) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) + +#define ICLRDataTarget3_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) + +#define ICLRDataTarget3_SetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + +#define ICLRDataTarget3_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + + +#define ICLRDataTarget3_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ + ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) + +#define ICLRDataTarget3_FreeVirtual(This,addr,size,typeFlags) \ + ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) + + +#define ICLRDataTarget3_GetExceptionRecord(This,bufferSize,bufferUsed,buffer) \ + ( (This)->lpVtbl -> GetExceptionRecord(This,bufferSize,bufferUsed,buffer) ) + +#define ICLRDataTarget3_GetExceptionContextRecord(This,bufferSize,bufferUsed,buffer) \ + ( (This)->lpVtbl -> GetExceptionContextRecord(This,bufferSize,bufferUsed,buffer) ) + +#define ICLRDataTarget3_GetExceptionThreadID(This,threadID) \ + ( (This)->lpVtbl -> GetExceptionThreadID(This,threadID) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataTarget3_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRMetadataLocator_INTERFACE_DEFINED__ +#define __ICLRMetadataLocator_INTERFACE_DEFINED__ + +/* interface ICLRMetadataLocator */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRMetadataLocator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("aa8fa804-bc05-4642-b2c5-c353ed22fc63") + ICLRMetadataLocator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMetadata( + /* [in] */ LPCWSTR imagePath, + /* [in] */ ULONG32 imageTimestamp, + /* [in] */ ULONG32 imageSize, + /* [in] */ GUID *mvid, + /* [in] */ ULONG32 mdRva, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufferSize, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *dataSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRMetadataLocatorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRMetadataLocator * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRMetadataLocator * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRMetadataLocator * This); + + HRESULT ( STDMETHODCALLTYPE *GetMetadata )( + ICLRMetadataLocator * This, + /* [in] */ LPCWSTR imagePath, + /* [in] */ ULONG32 imageTimestamp, + /* [in] */ ULONG32 imageSize, + /* [in] */ GUID *mvid, + /* [in] */ ULONG32 mdRva, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufferSize, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *dataSize); + + END_INTERFACE + } ICLRMetadataLocatorVtbl; + + interface ICLRMetadataLocator + { + CONST_VTBL struct ICLRMetadataLocatorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRMetadataLocator_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRMetadataLocator_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRMetadataLocator_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRMetadataLocator_GetMetadata(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) \ + ( (This)->lpVtbl -> GetMetadata(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRMetadataLocator_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ +#define __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ + +/* interface ICLRDataEnumMemoryRegionsCallback */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BCDD6908-BA2D-4ec5-96CF-DF4D5CDCB4A4") + ICLRDataEnumMemoryRegionsCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 size) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataEnumMemoryRegionsCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataEnumMemoryRegionsCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataEnumMemoryRegionsCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataEnumMemoryRegionsCallback * This); + + HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegion )( + ICLRDataEnumMemoryRegionsCallback * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 size); + + END_INTERFACE + } ICLRDataEnumMemoryRegionsCallbackVtbl; + + interface ICLRDataEnumMemoryRegionsCallback + { + CONST_VTBL struct ICLRDataEnumMemoryRegionsCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataEnumMemoryRegionsCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataEnumMemoryRegionsCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataEnumMemoryRegionsCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataEnumMemoryRegionsCallback_EnumMemoryRegion(This,address,size) \ + ( (This)->lpVtbl -> EnumMemoryRegion(This,address,size) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ +#define __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ + +/* interface ICLRDataEnumMemoryRegionsCallback2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3721A26F-8B91-4D98-A388-DB17B356FADB") + ICLRDataEnumMemoryRegionsCallback2 : public ICLRDataEnumMemoryRegionsCallback + { + public: + virtual HRESULT STDMETHODCALLTYPE UpdateMemoryRegion( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 bufferSize, + /* [size_is][in] */ BYTE *buffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataEnumMemoryRegionsCallback2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataEnumMemoryRegionsCallback2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataEnumMemoryRegionsCallback2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataEnumMemoryRegionsCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegion )( + ICLRDataEnumMemoryRegionsCallback2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 size); + + HRESULT ( STDMETHODCALLTYPE *UpdateMemoryRegion )( + ICLRDataEnumMemoryRegionsCallback2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 bufferSize, + /* [size_is][in] */ BYTE *buffer); + + END_INTERFACE + } ICLRDataEnumMemoryRegionsCallback2Vtbl; + + interface ICLRDataEnumMemoryRegionsCallback2 + { + CONST_VTBL struct ICLRDataEnumMemoryRegionsCallback2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataEnumMemoryRegionsCallback2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataEnumMemoryRegionsCallback2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataEnumMemoryRegionsCallback2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataEnumMemoryRegionsCallback2_EnumMemoryRegion(This,address,size) \ + ( (This)->lpVtbl -> EnumMemoryRegion(This,address,size) ) + + +#define ICLRDataEnumMemoryRegionsCallback2_UpdateMemoryRegion(This,address,bufferSize,buffer) \ + ( (This)->lpVtbl -> UpdateMemoryRegion(This,address,bufferSize,buffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_clrdata_0000_0006 */ +/* [local] */ + +typedef +enum CLRDataEnumMemoryFlags + { + CLRDATA_ENUM_MEM_DEFAULT = 0, + CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, + CLRDATA_ENUM_MEM_HEAP = 0x1, + CLRDATA_ENUM_MEM_TRIAGE = 0x2 + } CLRDataEnumMemoryFlags; + + + +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0006_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0006_v0_0_s_ifspec; + +#ifndef __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ +#define __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ + +/* interface ICLRDataEnumMemoryRegions */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRDataEnumMemoryRegions; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("471c35b4-7c2f-4ef0-a945-00f8c38056f1") + ICLRDataEnumMemoryRegions : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegions( + /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback, + /* [in] */ ULONG32 miniDumpFlags, + /* [in] */ CLRDataEnumMemoryFlags clrFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDataEnumMemoryRegionsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDataEnumMemoryRegions * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDataEnumMemoryRegions * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDataEnumMemoryRegions * This); + + HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegions )( + ICLRDataEnumMemoryRegions * This, + /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback, + /* [in] */ ULONG32 miniDumpFlags, + /* [in] */ CLRDataEnumMemoryFlags clrFlags); + + END_INTERFACE + } ICLRDataEnumMemoryRegionsVtbl; + + interface ICLRDataEnumMemoryRegions + { + CONST_VTBL struct ICLRDataEnumMemoryRegionsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDataEnumMemoryRegions_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDataEnumMemoryRegions_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDataEnumMemoryRegions_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDataEnumMemoryRegions_EnumMemoryRegions(This,callback,miniDumpFlags,clrFlags) \ + ( (This)->lpVtbl -> EnumMemoryRegions(This,callback,miniDumpFlags,clrFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/clrinternal.h b/lib/coreclr/src/pal/prebuilt/inc/clrinternal.h new file mode 100644 index 0000000000..647b899615 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/clrinternal.h @@ -0,0 +1,847 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __clrinternal_h__ +#define __clrinternal_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IExecutionEngine_FWD_DEFINED__ +#define __IExecutionEngine_FWD_DEFINED__ +typedef interface IExecutionEngine IExecutionEngine; + +#endif /* __IExecutionEngine_FWD_DEFINED__ */ + + +#ifndef __IEEMemoryManager_FWD_DEFINED__ +#define __IEEMemoryManager_FWD_DEFINED__ +typedef interface IEEMemoryManager IEEMemoryManager; + +#endif /* __IEEMemoryManager_FWD_DEFINED__ */ + + +#ifndef __IPrivateManagedExceptionReporting_FWD_DEFINED__ +#define __IPrivateManagedExceptionReporting_FWD_DEFINED__ +typedef interface IPrivateManagedExceptionReporting IPrivateManagedExceptionReporting; + +#endif /* __IPrivateManagedExceptionReporting_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "mscoree.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_clrinternal_0000_0000 */ +/* [local] */ + +#if 0 +typedef struct _OSVERSIONINFOA + { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + CHAR szCSDVersion[ 128 ]; + } OSVERSIONINFOA; + +typedef struct _OSVERSIONINFOA *POSVERSIONINFOA; + +typedef struct _OSVERSIONINFOA *LPOSVERSIONINFOA; + +typedef struct _OSVERSIONINFOW + { + DWORD dwOSVersionInfoSize; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + DWORD dwBuildNumber; + DWORD dwPlatformId; + WCHAR szCSDVersion[ 128 ]; + } OSVERSIONINFOW; + +typedef struct _OSVERSIONINFOW *POSVERSIONINFOW; + +typedef struct _OSVERSIONINFOW *LPOSVERSIONINFOW; + +typedef struct _OSVERSIONINFOW RTL_OSVERSIONINFOW; + +typedef struct _OSVERSIONINFOW *PRTL_OSVERSIONINFOW; + +typedef OSVERSIONINFOA OSVERSIONINFO; + +typedef POSVERSIONINFOA POSVERSIONINFO; + +typedef LPOSVERSIONINFOA LPOSVERSIONINFO; + +#endif +EXTERN_GUID(IID_IExecutionEngine, 0x7AF02DAC, 0x2A33, 0x494b, 0xA0, 0x9F, 0x25, 0xE0, 0x0A, 0x93, 0xC6, 0xF8); +EXTERN_GUID(IID_IEEMemoryManager, 0x17713b61, 0xb59f, 0x4e13, 0xba, 0xaf, 0x91, 0x62, 0x3d, 0xc8, 0xad, 0xc0); +EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec); +EXTERN_GUID(CLR_ID_CORECLR, 0x8CB8E075, 0x0A91, 0x408E, 0x92, 0x28, 0xD6, 0x6E, 0x00, 0xA3, 0xBF, 0xF6 ); +EXTERN_GUID(CLR_ID_PHONE_CLR, 0xE7237E9C, 0x31C0, 0x488C, 0xAD, 0x48, 0x32, 0x4D, 0x3E, 0x7E, 0xD9, 0x2A); +EXTERN_GUID(CLR_ID_ONECORE_CLR, 0xb1ee760d, 0x6c4a, 0x4533, 0xba, 0x41, 0x6f, 0x4f, 0x66, 0x1f, 0xab, 0xaf); +EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d, 0x4298, 0x80, 0x01, 0x07, 0xaa, 0x93, 0x50, 0xdc, 0xa4); +typedef void *CRITSEC_COOKIE; + +typedef void *EVENT_COOKIE; + +typedef void *SEMAPHORE_COOKIE; + +typedef void *MUTEX_COOKIE; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_clrinternal_0000_0000_0001 + { + CRST_DEFAULT = 0, + CRST_REENTRANCY = 0x1, + CRST_UNSAFE_SAMELEVEL = 0x2, + CRST_UNSAFE_COOPGC = 0x4, + CRST_UNSAFE_ANYMODE = 0x8, + CRST_DEBUGGER_THREAD = 0x10, + CRST_HOST_BREAKABLE = 0x20, + CRST_TAKEN_DURING_SHUTDOWN = 0x80, + CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, + CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200 + } CrstFlags; + +typedef VOID ( WINAPI *PTLS_CALLBACK_FUNCTION )( + PVOID __MIDL____MIDL_itf_clrinternal_0000_00000000); + + + +extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_s_ifspec; + +#ifndef __IExecutionEngine_INTERFACE_DEFINED__ +#define __IExecutionEngine_INTERFACE_DEFINED__ + +/* interface IExecutionEngine */ +/* [object][local][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IExecutionEngine; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7AF02DAC-2A33-494b-A09F-25E00A93C6F8") + IExecutionEngine : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE TLS_AssociateCallback( + /* [in] */ DWORD slot, + /* [in] */ PTLS_CALLBACK_FUNCTION callback) = 0; + + virtual PVOID *STDMETHODCALLTYPE TLS_GetDataBlock( void) = 0; + + virtual PVOID STDMETHODCALLTYPE TLS_GetValue( + /* [in] */ DWORD slot) = 0; + + virtual BOOL STDMETHODCALLTYPE TLS_CheckValue( + /* [in] */ DWORD slot, + /* [out] */ PVOID *pValue) = 0; + + virtual void STDMETHODCALLTYPE TLS_SetValue( + /* [in] */ DWORD slot, + /* [in] */ PVOID pData) = 0; + + virtual void STDMETHODCALLTYPE TLS_ThreadDetaching( void) = 0; + + virtual CRITSEC_COOKIE STDMETHODCALLTYPE CreateLock( + /* [in] */ LPCSTR szTag, + /* [in] */ LPCSTR level, + /* [in] */ CrstFlags flags) = 0; + + virtual void STDMETHODCALLTYPE DestroyLock( + /* [in] */ CRITSEC_COOKIE lock) = 0; + + virtual void STDMETHODCALLTYPE AcquireLock( + /* [in] */ CRITSEC_COOKIE lock) = 0; + + virtual void STDMETHODCALLTYPE ReleaseLock( + /* [in] */ CRITSEC_COOKIE lock) = 0; + + virtual EVENT_COOKIE STDMETHODCALLTYPE CreateAutoEvent( + /* [in] */ BOOL bInitialState) = 0; + + virtual EVENT_COOKIE STDMETHODCALLTYPE CreateManualEvent( + /* [in] */ BOOL bInitialState) = 0; + + virtual void STDMETHODCALLTYPE CloseEvent( + /* [in] */ EVENT_COOKIE event) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrSetEvent( + /* [in] */ EVENT_COOKIE event) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrResetEvent( + /* [in] */ EVENT_COOKIE event) = 0; + + virtual DWORD STDMETHODCALLTYPE WaitForEvent( + /* [in] */ EVENT_COOKIE event, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable) = 0; + + virtual DWORD STDMETHODCALLTYPE WaitForSingleObject( + /* [in] */ HANDLE handle, + /* [in] */ DWORD dwMilliseconds) = 0; + + virtual SEMAPHORE_COOKIE STDMETHODCALLTYPE ClrCreateSemaphore( + /* [in] */ DWORD dwInitial, + /* [in] */ DWORD dwMax) = 0; + + virtual void STDMETHODCALLTYPE ClrCloseSemaphore( + /* [in] */ SEMAPHORE_COOKIE semaphore) = 0; + + virtual DWORD STDMETHODCALLTYPE ClrWaitForSemaphore( + /* [in] */ SEMAPHORE_COOKIE semaphore, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrReleaseSemaphore( + /* [in] */ SEMAPHORE_COOKIE semaphore, + /* [in] */ LONG lReleaseCount, + /* [in] */ LONG *lpPreviousCount) = 0; + + virtual MUTEX_COOKIE STDMETHODCALLTYPE ClrCreateMutex( + /* [in] */ LPSECURITY_ATTRIBUTES lpMutexAttributes, + /* [in] */ BOOL bInitialOwner, + /* [in] */ LPCTSTR lpName) = 0; + + virtual DWORD STDMETHODCALLTYPE ClrWaitForMutex( + /* [in] */ MUTEX_COOKIE mutex, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrReleaseMutex( + /* [in] */ MUTEX_COOKIE mutex) = 0; + + virtual void STDMETHODCALLTYPE ClrCloseMutex( + /* [in] */ MUTEX_COOKIE mutex) = 0; + + virtual DWORD STDMETHODCALLTYPE ClrSleepEx( + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrAllocationDisallowed( void) = 0; + + virtual void STDMETHODCALLTYPE GetLastThrownObjectExceptionFromThread( + /* [out] */ void **ppvException) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IExecutionEngineVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IExecutionEngine * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IExecutionEngine * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IExecutionEngine * This); + + void ( STDMETHODCALLTYPE *TLS_AssociateCallback )( + IExecutionEngine * This, + /* [in] */ DWORD slot, + /* [in] */ PTLS_CALLBACK_FUNCTION callback); + + PVOID *( STDMETHODCALLTYPE *TLS_GetDataBlock )( + IExecutionEngine * This); + + PVOID ( STDMETHODCALLTYPE *TLS_GetValue )( + IExecutionEngine * This, + /* [in] */ DWORD slot); + + BOOL ( STDMETHODCALLTYPE *TLS_CheckValue )( + IExecutionEngine * This, + /* [in] */ DWORD slot, + /* [out] */ PVOID *pValue); + + void ( STDMETHODCALLTYPE *TLS_SetValue )( + IExecutionEngine * This, + /* [in] */ DWORD slot, + /* [in] */ PVOID pData); + + void ( STDMETHODCALLTYPE *TLS_ThreadDetaching )( + IExecutionEngine * This); + + CRITSEC_COOKIE ( STDMETHODCALLTYPE *CreateLock )( + IExecutionEngine * This, + /* [in] */ LPCSTR szTag, + /* [in] */ LPCSTR level, + /* [in] */ CrstFlags flags); + + void ( STDMETHODCALLTYPE *DestroyLock )( + IExecutionEngine * This, + /* [in] */ CRITSEC_COOKIE lock); + + void ( STDMETHODCALLTYPE *AcquireLock )( + IExecutionEngine * This, + /* [in] */ CRITSEC_COOKIE lock); + + void ( STDMETHODCALLTYPE *ReleaseLock )( + IExecutionEngine * This, + /* [in] */ CRITSEC_COOKIE lock); + + EVENT_COOKIE ( STDMETHODCALLTYPE *CreateAutoEvent )( + IExecutionEngine * This, + /* [in] */ BOOL bInitialState); + + EVENT_COOKIE ( STDMETHODCALLTYPE *CreateManualEvent )( + IExecutionEngine * This, + /* [in] */ BOOL bInitialState); + + void ( STDMETHODCALLTYPE *CloseEvent )( + IExecutionEngine * This, + /* [in] */ EVENT_COOKIE event); + + BOOL ( STDMETHODCALLTYPE *ClrSetEvent )( + IExecutionEngine * This, + /* [in] */ EVENT_COOKIE event); + + BOOL ( STDMETHODCALLTYPE *ClrResetEvent )( + IExecutionEngine * This, + /* [in] */ EVENT_COOKIE event); + + DWORD ( STDMETHODCALLTYPE *WaitForEvent )( + IExecutionEngine * This, + /* [in] */ EVENT_COOKIE event, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable); + + DWORD ( STDMETHODCALLTYPE *WaitForSingleObject )( + IExecutionEngine * This, + /* [in] */ HANDLE handle, + /* [in] */ DWORD dwMilliseconds); + + SEMAPHORE_COOKIE ( STDMETHODCALLTYPE *ClrCreateSemaphore )( + IExecutionEngine * This, + /* [in] */ DWORD dwInitial, + /* [in] */ DWORD dwMax); + + void ( STDMETHODCALLTYPE *ClrCloseSemaphore )( + IExecutionEngine * This, + /* [in] */ SEMAPHORE_COOKIE semaphore); + + DWORD ( STDMETHODCALLTYPE *ClrWaitForSemaphore )( + IExecutionEngine * This, + /* [in] */ SEMAPHORE_COOKIE semaphore, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable); + + BOOL ( STDMETHODCALLTYPE *ClrReleaseSemaphore )( + IExecutionEngine * This, + /* [in] */ SEMAPHORE_COOKIE semaphore, + /* [in] */ LONG lReleaseCount, + /* [in] */ LONG *lpPreviousCount); + + MUTEX_COOKIE ( STDMETHODCALLTYPE *ClrCreateMutex )( + IExecutionEngine * This, + /* [in] */ LPSECURITY_ATTRIBUTES lpMutexAttributes, + /* [in] */ BOOL bInitialOwner, + /* [in] */ LPCTSTR lpName); + + DWORD ( STDMETHODCALLTYPE *ClrWaitForMutex )( + IExecutionEngine * This, + /* [in] */ MUTEX_COOKIE mutex, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable); + + BOOL ( STDMETHODCALLTYPE *ClrReleaseMutex )( + IExecutionEngine * This, + /* [in] */ MUTEX_COOKIE mutex); + + void ( STDMETHODCALLTYPE *ClrCloseMutex )( + IExecutionEngine * This, + /* [in] */ MUTEX_COOKIE mutex); + + DWORD ( STDMETHODCALLTYPE *ClrSleepEx )( + IExecutionEngine * This, + /* [in] */ DWORD dwMilliseconds, + /* [in] */ BOOL bAlertable); + + BOOL ( STDMETHODCALLTYPE *ClrAllocationDisallowed )( + IExecutionEngine * This); + + void ( STDMETHODCALLTYPE *GetLastThrownObjectExceptionFromThread )( + IExecutionEngine * This, + /* [out] */ void **ppvException); + + END_INTERFACE + } IExecutionEngineVtbl; + + interface IExecutionEngine + { + CONST_VTBL struct IExecutionEngineVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IExecutionEngine_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IExecutionEngine_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IExecutionEngine_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IExecutionEngine_TLS_AssociateCallback(This,slot,callback) \ + ( (This)->lpVtbl -> TLS_AssociateCallback(This,slot,callback) ) + +#define IExecutionEngine_TLS_GetDataBlock(This) \ + ( (This)->lpVtbl -> TLS_GetDataBlock(This) ) + +#define IExecutionEngine_TLS_GetValue(This,slot) \ + ( (This)->lpVtbl -> TLS_GetValue(This,slot) ) + +#define IExecutionEngine_TLS_CheckValue(This,slot,pValue) \ + ( (This)->lpVtbl -> TLS_CheckValue(This,slot,pValue) ) + +#define IExecutionEngine_TLS_SetValue(This,slot,pData) \ + ( (This)->lpVtbl -> TLS_SetValue(This,slot,pData) ) + +#define IExecutionEngine_TLS_ThreadDetaching(This) \ + ( (This)->lpVtbl -> TLS_ThreadDetaching(This) ) + +#define IExecutionEngine_CreateLock(This,szTag,level,flags) \ + ( (This)->lpVtbl -> CreateLock(This,szTag,level,flags) ) + +#define IExecutionEngine_DestroyLock(This,lock) \ + ( (This)->lpVtbl -> DestroyLock(This,lock) ) + +#define IExecutionEngine_AcquireLock(This,lock) \ + ( (This)->lpVtbl -> AcquireLock(This,lock) ) + +#define IExecutionEngine_ReleaseLock(This,lock) \ + ( (This)->lpVtbl -> ReleaseLock(This,lock) ) + +#define IExecutionEngine_CreateAutoEvent(This,bInitialState) \ + ( (This)->lpVtbl -> CreateAutoEvent(This,bInitialState) ) + +#define IExecutionEngine_CreateManualEvent(This,bInitialState) \ + ( (This)->lpVtbl -> CreateManualEvent(This,bInitialState) ) + +#define IExecutionEngine_CloseEvent(This,event) \ + ( (This)->lpVtbl -> CloseEvent(This,event) ) + +#define IExecutionEngine_ClrSetEvent(This,event) \ + ( (This)->lpVtbl -> ClrSetEvent(This,event) ) + +#define IExecutionEngine_ClrResetEvent(This,event) \ + ( (This)->lpVtbl -> ClrResetEvent(This,event) ) + +#define IExecutionEngine_WaitForEvent(This,event,dwMilliseconds,bAlertable) \ + ( (This)->lpVtbl -> WaitForEvent(This,event,dwMilliseconds,bAlertable) ) + +#define IExecutionEngine_WaitForSingleObject(This,handle,dwMilliseconds) \ + ( (This)->lpVtbl -> WaitForSingleObject(This,handle,dwMilliseconds) ) + +#define IExecutionEngine_ClrCreateSemaphore(This,dwInitial,dwMax) \ + ( (This)->lpVtbl -> ClrCreateSemaphore(This,dwInitial,dwMax) ) + +#define IExecutionEngine_ClrCloseSemaphore(This,semaphore) \ + ( (This)->lpVtbl -> ClrCloseSemaphore(This,semaphore) ) + +#define IExecutionEngine_ClrWaitForSemaphore(This,semaphore,dwMilliseconds,bAlertable) \ + ( (This)->lpVtbl -> ClrWaitForSemaphore(This,semaphore,dwMilliseconds,bAlertable) ) + +#define IExecutionEngine_ClrReleaseSemaphore(This,semaphore,lReleaseCount,lpPreviousCount) \ + ( (This)->lpVtbl -> ClrReleaseSemaphore(This,semaphore,lReleaseCount,lpPreviousCount) ) + +#define IExecutionEngine_ClrCreateMutex(This,lpMutexAttributes,bInitialOwner,lpName) \ + ( (This)->lpVtbl -> ClrCreateMutex(This,lpMutexAttributes,bInitialOwner,lpName) ) + +#define IExecutionEngine_ClrWaitForMutex(This,mutex,dwMilliseconds,bAlertable) \ + ( (This)->lpVtbl -> ClrWaitForMutex(This,mutex,dwMilliseconds,bAlertable) ) + +#define IExecutionEngine_ClrReleaseMutex(This,mutex) \ + ( (This)->lpVtbl -> ClrReleaseMutex(This,mutex) ) + +#define IExecutionEngine_ClrCloseMutex(This,mutex) \ + ( (This)->lpVtbl -> ClrCloseMutex(This,mutex) ) + +#define IExecutionEngine_ClrSleepEx(This,dwMilliseconds,bAlertable) \ + ( (This)->lpVtbl -> ClrSleepEx(This,dwMilliseconds,bAlertable) ) + +#define IExecutionEngine_ClrAllocationDisallowed(This) \ + ( (This)->lpVtbl -> ClrAllocationDisallowed(This) ) + +#define IExecutionEngine_GetLastThrownObjectExceptionFromThread(This,ppvException) \ + ( (This)->lpVtbl -> GetLastThrownObjectExceptionFromThread(This,ppvException) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IExecutionEngine_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_clrinternal_0000_0001 */ +/* [local] */ + +#if !defined(_WINNT_) && !defined(_NTMMAPI_) +typedef void *PMEMORY_BASIC_INFORMATION; + +#endif + + +extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0001_v0_0_s_ifspec; + +#ifndef __IEEMemoryManager_INTERFACE_DEFINED__ +#define __IEEMemoryManager_INTERFACE_DEFINED__ + +/* interface IEEMemoryManager */ +/* [object][local][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IEEMemoryManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("17713B61-B59F-4e13-BAAF-91623DC8ADC0") + IEEMemoryManager : public IUnknown + { + public: + virtual LPVOID STDMETHODCALLTYPE ClrVirtualAlloc( + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flAllocationType, + /* [in] */ DWORD flProtect) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrVirtualFree( + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD dwFreeType) = 0; + + virtual SIZE_T STDMETHODCALLTYPE ClrVirtualQuery( + /* [in] */ const void *lpAddress, + /* [in] */ PMEMORY_BASIC_INFORMATION lpBuffer, + /* [in] */ SIZE_T dwLength) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrVirtualProtect( + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flNewProtect, + /* [in] */ DWORD *lpflOldProtect) = 0; + + virtual HANDLE STDMETHODCALLTYPE ClrGetProcessHeap( void) = 0; + + virtual HANDLE STDMETHODCALLTYPE ClrHeapCreate( + /* [in] */ DWORD flOptions, + /* [in] */ SIZE_T dwInitialSize, + /* [in] */ SIZE_T dwMaximumSize) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrHeapDestroy( + /* [in] */ HANDLE hHeap) = 0; + + virtual LPVOID STDMETHODCALLTYPE ClrHeapAlloc( + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ SIZE_T dwBytes) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrHeapFree( + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ LPVOID lpMem) = 0; + + virtual BOOL STDMETHODCALLTYPE ClrHeapValidate( + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ const void *lpMem) = 0; + + virtual HANDLE STDMETHODCALLTYPE ClrGetProcessExecutableHeap( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IEEMemoryManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IEEMemoryManager * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IEEMemoryManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IEEMemoryManager * This); + + LPVOID ( STDMETHODCALLTYPE *ClrVirtualAlloc )( + IEEMemoryManager * This, + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flAllocationType, + /* [in] */ DWORD flProtect); + + BOOL ( STDMETHODCALLTYPE *ClrVirtualFree )( + IEEMemoryManager * This, + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD dwFreeType); + + SIZE_T ( STDMETHODCALLTYPE *ClrVirtualQuery )( + IEEMemoryManager * This, + /* [in] */ const void *lpAddress, + /* [in] */ PMEMORY_BASIC_INFORMATION lpBuffer, + /* [in] */ SIZE_T dwLength); + + BOOL ( STDMETHODCALLTYPE *ClrVirtualProtect )( + IEEMemoryManager * This, + /* [in] */ LPVOID lpAddress, + /* [in] */ SIZE_T dwSize, + /* [in] */ DWORD flNewProtect, + /* [in] */ DWORD *lpflOldProtect); + + HANDLE ( STDMETHODCALLTYPE *ClrGetProcessHeap )( + IEEMemoryManager * This); + + HANDLE ( STDMETHODCALLTYPE *ClrHeapCreate )( + IEEMemoryManager * This, + /* [in] */ DWORD flOptions, + /* [in] */ SIZE_T dwInitialSize, + /* [in] */ SIZE_T dwMaximumSize); + + BOOL ( STDMETHODCALLTYPE *ClrHeapDestroy )( + IEEMemoryManager * This, + /* [in] */ HANDLE hHeap); + + LPVOID ( STDMETHODCALLTYPE *ClrHeapAlloc )( + IEEMemoryManager * This, + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ SIZE_T dwBytes); + + BOOL ( STDMETHODCALLTYPE *ClrHeapFree )( + IEEMemoryManager * This, + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ LPVOID lpMem); + + BOOL ( STDMETHODCALLTYPE *ClrHeapValidate )( + IEEMemoryManager * This, + /* [in] */ HANDLE hHeap, + /* [in] */ DWORD dwFlags, + /* [in] */ const void *lpMem); + + HANDLE ( STDMETHODCALLTYPE *ClrGetProcessExecutableHeap )( + IEEMemoryManager * This); + + END_INTERFACE + } IEEMemoryManagerVtbl; + + interface IEEMemoryManager + { + CONST_VTBL struct IEEMemoryManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IEEMemoryManager_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IEEMemoryManager_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IEEMemoryManager_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IEEMemoryManager_ClrVirtualAlloc(This,lpAddress,dwSize,flAllocationType,flProtect) \ + ( (This)->lpVtbl -> ClrVirtualAlloc(This,lpAddress,dwSize,flAllocationType,flProtect) ) + +#define IEEMemoryManager_ClrVirtualFree(This,lpAddress,dwSize,dwFreeType) \ + ( (This)->lpVtbl -> ClrVirtualFree(This,lpAddress,dwSize,dwFreeType) ) + +#define IEEMemoryManager_ClrVirtualQuery(This,lpAddress,lpBuffer,dwLength) \ + ( (This)->lpVtbl -> ClrVirtualQuery(This,lpAddress,lpBuffer,dwLength) ) + +#define IEEMemoryManager_ClrVirtualProtect(This,lpAddress,dwSize,flNewProtect,lpflOldProtect) \ + ( (This)->lpVtbl -> ClrVirtualProtect(This,lpAddress,dwSize,flNewProtect,lpflOldProtect) ) + +#define IEEMemoryManager_ClrGetProcessHeap(This) \ + ( (This)->lpVtbl -> ClrGetProcessHeap(This) ) + +#define IEEMemoryManager_ClrHeapCreate(This,flOptions,dwInitialSize,dwMaximumSize) \ + ( (This)->lpVtbl -> ClrHeapCreate(This,flOptions,dwInitialSize,dwMaximumSize) ) + +#define IEEMemoryManager_ClrHeapDestroy(This,hHeap) \ + ( (This)->lpVtbl -> ClrHeapDestroy(This,hHeap) ) + +#define IEEMemoryManager_ClrHeapAlloc(This,hHeap,dwFlags,dwBytes) \ + ( (This)->lpVtbl -> ClrHeapAlloc(This,hHeap,dwFlags,dwBytes) ) + +#define IEEMemoryManager_ClrHeapFree(This,hHeap,dwFlags,lpMem) \ + ( (This)->lpVtbl -> ClrHeapFree(This,hHeap,dwFlags,lpMem) ) + +#define IEEMemoryManager_ClrHeapValidate(This,hHeap,dwFlags,lpMem) \ + ( (This)->lpVtbl -> ClrHeapValidate(This,hHeap,dwFlags,lpMem) ) + +#define IEEMemoryManager_ClrGetProcessExecutableHeap(This) \ + ( (This)->lpVtbl -> ClrGetProcessExecutableHeap(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IEEMemoryManager_INTERFACE_DEFINED__ */ + + +#ifndef __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ +#define __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ + +/* interface IPrivateManagedExceptionReporting */ +/* [object][local][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IPrivateManagedExceptionReporting; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AD76A023-332D-4298-8001-07AA9350DCA4") + IPrivateManagedExceptionReporting : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetBucketParametersForCurrentException( + /* [out] */ BucketParameters *pParams) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IPrivateManagedExceptionReportingVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IPrivateManagedExceptionReporting * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IPrivateManagedExceptionReporting * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IPrivateManagedExceptionReporting * This); + + HRESULT ( STDMETHODCALLTYPE *GetBucketParametersForCurrentException )( + IPrivateManagedExceptionReporting * This, + /* [out] */ BucketParameters *pParams); + + END_INTERFACE + } IPrivateManagedExceptionReportingVtbl; + + interface IPrivateManagedExceptionReporting + { + CONST_VTBL struct IPrivateManagedExceptionReportingVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPrivateManagedExceptionReporting_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IPrivateManagedExceptionReporting_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IPrivateManagedExceptionReporting_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IPrivateManagedExceptionReporting_GetBucketParametersForCurrentException(This,pParams) \ + ( (This)->lpVtbl -> GetBucketParametersForCurrentException(This,pParams) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/clrprivbinding.h b/lib/coreclr/src/pal/prebuilt/inc/clrprivbinding.h new file mode 100644 index 0000000000..ceb11feaff --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/clrprivbinding.h @@ -0,0 +1,1057 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __CLRPrivBinding_h__ +#define __CLRPrivBinding_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICLRPrivBinder_FWD_DEFINED__ +#define __ICLRPrivBinder_FWD_DEFINED__ +typedef interface ICLRPrivBinder ICLRPrivBinder; + +#endif /* __ICLRPrivBinder_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivAssembly_FWD_DEFINED__ +#define __ICLRPrivAssembly_FWD_DEFINED__ +typedef interface ICLRPrivAssembly ICLRPrivAssembly; + +#endif /* __ICLRPrivAssembly_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivResource_FWD_DEFINED__ +#define __ICLRPrivResource_FWD_DEFINED__ +typedef interface ICLRPrivResource ICLRPrivResource; + +#endif /* __ICLRPrivResource_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivResourcePath_FWD_DEFINED__ +#define __ICLRPrivResourcePath_FWD_DEFINED__ +typedef interface ICLRPrivResourcePath ICLRPrivResourcePath; + +#endif /* __ICLRPrivResourcePath_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivResourceStream_FWD_DEFINED__ +#define __ICLRPrivResourceStream_FWD_DEFINED__ +typedef interface ICLRPrivResourceStream ICLRPrivResourceStream; + +#endif /* __ICLRPrivResourceStream_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivResourceHMODULE_FWD_DEFINED__ +#define __ICLRPrivResourceHMODULE_FWD_DEFINED__ +typedef interface ICLRPrivResourceHMODULE ICLRPrivResourceHMODULE; + +#endif /* __ICLRPrivResourceHMODULE_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivResourceAssembly_FWD_DEFINED__ +#define __ICLRPrivResourceAssembly_FWD_DEFINED__ +typedef interface ICLRPrivResourceAssembly ICLRPrivResourceAssembly; + +#endif /* __ICLRPrivResourceAssembly_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivAssemblyInfo_FWD_DEFINED__ +#define __ICLRPrivAssemblyInfo_FWD_DEFINED__ +typedef interface ICLRPrivAssemblyInfo ICLRPrivAssemblyInfo; + +#endif /* __ICLRPrivAssemblyInfo_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivAssemblyID_WinRT_FWD_DEFINED__ +#define __ICLRPrivAssemblyID_WinRT_FWD_DEFINED__ +typedef interface ICLRPrivAssemblyID_WinRT ICLRPrivAssemblyID_WinRT; + +#endif /* __ICLRPrivAssemblyID_WinRT_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ +#define __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ +typedef interface ICLRPrivWinRtTypeBinder ICLRPrivWinRtTypeBinder; + +#endif /* __ICLRPrivWinRtTypeBinder_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "objidl.h" +#include "fusion.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_CLRPrivBinding_0000_0000 */ +/* [local] */ + + + + + + + + +typedef LPCSTR LPCUTF8; + + + +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0000_v0_0_s_ifspec; + +#ifndef __ICLRPrivBinder_INTERFACE_DEFINED__ +#define __ICLRPrivBinder_INTERFACE_DEFINED__ + +/* interface ICLRPrivBinder */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivBinder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8542") + ICLRPrivBinder : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BindAssemblyByName( + /* [in] */ IAssemblyName *pAssemblyName, + /* [retval][out] */ ICLRPrivAssembly **ppAssembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBinderID( + /* [retval][out] */ UINT_PTR *pBinderId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLoaderAllocator( + /* [retval][out] */ LPVOID* pLoaderAllocator) = 0; + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivBinderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivBinder * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivBinder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivBinder * This); + + HRESULT ( STDMETHODCALLTYPE *BindAssemblyByName )( + ICLRPrivBinder * This, + /* [in] */ IAssemblyName *pAssemblyName, + /* [retval][out] */ ICLRPrivAssembly **ppAssembly); + + HRESULT ( STDMETHODCALLTYPE *GetBinderID )( + ICLRPrivBinder * This, + /* [retval][out] */ UINT_PTR *pBinderId); + + HRESULT(STDMETHODCALLTYPE *GetLoaderAllocator)( + ICLRPrivBinder * This, + /* [retval][out] */ LPVOID *pLoaderAllocator) = 0; + + END_INTERFACE + } ICLRPrivBinderVtbl; + + interface ICLRPrivBinder + { + CONST_VTBL struct ICLRPrivBinderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivBinder_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivBinder_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivBinder_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivBinder_BindAssemblyByName(This,pAssemblyName,ppAssembly) \ + ( (This)->lpVtbl -> BindAssemblyByName(This,pAssemblyName,ppAssembly) ) + +#define ICLRPrivBinder_GetBinderID(This,pBinderId) \ + ( (This)->lpVtbl -> GetBinderID(This,pBinderId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivBinder_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_CLRPrivBinding_0000_0001 */ +/* [local] */ + + +enum ASSEMBLY_IMAGE_TYPES + { + ASSEMBLY_IMAGE_TYPE_IL = 0x1, + ASSEMBLY_IMAGE_TYPE_NATIVE = 0x2, + ASSEMBLY_IMAGE_TYPE_DEFAULT = 0x3, + ASSEMBLY_IMAGE_TYPE_ASSEMBLY = 0x4 + } ; + + +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivBinding_0000_0001_v0_0_s_ifspec; + +#ifndef __ICLRPrivAssembly_INTERFACE_DEFINED__ +#define __ICLRPrivAssembly_INTERFACE_DEFINED__ + +/* interface ICLRPrivAssembly */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivAssembly; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8543") + ICLRPrivAssembly : public ICLRPrivBinder + { + public: + virtual HRESULT STDMETHODCALLTYPE IsShareable( + /* [retval][out] */ BOOL *pbIsShareable) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAvailableImageTypes( + /* [retval][out] */ LPDWORD pdwImageTypes) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetImageResource( + /* [in] */ DWORD dwImageType, + /* [out] */ DWORD *pdwImageType, + /* [retval][out] */ ICLRPrivResource **ppIResource) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivAssemblyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivAssembly * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivAssembly * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivAssembly * This); + + HRESULT ( STDMETHODCALLTYPE *BindAssemblyByName )( + ICLRPrivAssembly * This, + /* [in] */ IAssemblyName *pAssemblyName, + /* [retval][out] */ ICLRPrivAssembly **ppAssembly); + + HRESULT ( STDMETHODCALLTYPE *GetBinderID )( + ICLRPrivAssembly * This, + /* [retval][out] */ UINT_PTR *pBinderId); + + HRESULT ( STDMETHODCALLTYPE *IsShareable )( + ICLRPrivAssembly * This, + /* [retval][out] */ BOOL *pbIsShareable); + + HRESULT ( STDMETHODCALLTYPE *GetAvailableImageTypes )( + ICLRPrivAssembly * This, + /* [retval][out] */ LPDWORD pdwImageTypes); + + HRESULT ( STDMETHODCALLTYPE *GetImageResource )( + ICLRPrivAssembly * This, + /* [in] */ DWORD dwImageType, + /* [out] */ DWORD *pdwImageType, + /* [retval][out] */ ICLRPrivResource **ppIResource); + + END_INTERFACE + } ICLRPrivAssemblyVtbl; + + interface ICLRPrivAssembly + { + CONST_VTBL struct ICLRPrivAssemblyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivAssembly_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivAssembly_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivAssembly_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivAssembly_BindAssemblyByName(This,pAssemblyName,ppAssembly) \ + ( (This)->lpVtbl -> BindAssemblyByName(This,pAssemblyName,ppAssembly) ) + +#define ICLRPrivAssembly_GetBinderID(This,pBinderId) \ + ( (This)->lpVtbl -> GetBinderID(This,pBinderId) ) + + +#define ICLRPrivAssembly_IsShareable(This,pbIsShareable) \ + ( (This)->lpVtbl -> IsShareable(This,pbIsShareable) ) + +#define ICLRPrivAssembly_GetAvailableImageTypes(This,pdwImageTypes) \ + ( (This)->lpVtbl -> GetAvailableImageTypes(This,pdwImageTypes) ) + +#define ICLRPrivAssembly_GetImageResource(This,dwImageType,pdwImageType,ppIResource) \ + ( (This)->lpVtbl -> GetImageResource(This,dwImageType,pdwImageType,ppIResource) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivAssembly_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivResource_INTERFACE_DEFINED__ +#define __ICLRPrivResource_INTERFACE_DEFINED__ + +/* interface ICLRPrivResource */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivResource; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8547") + ICLRPrivResource : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetResourceType( + /* [retval][out] */ IID *pIID) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivResourceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivResource * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivResource * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivResource * This); + + HRESULT ( STDMETHODCALLTYPE *GetResourceType )( + ICLRPrivResource * This, + /* [retval][out] */ IID *pIID); + + END_INTERFACE + } ICLRPrivResourceVtbl; + + interface ICLRPrivResource + { + CONST_VTBL struct ICLRPrivResourceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivResource_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivResource_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivResource_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivResource_GetResourceType(This,pIID) \ + ( (This)->lpVtbl -> GetResourceType(This,pIID) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivResource_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivResourcePath_INTERFACE_DEFINED__ +#define __ICLRPrivResourcePath_INTERFACE_DEFINED__ + +/* interface ICLRPrivResourcePath */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivResourcePath; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8544") + ICLRPrivResourcePath : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetPath( + /* [in] */ DWORD cchBuffer, + /* [out] */ LPDWORD pcchBuffer, + /* [optional][string][length_is][size_is][out] */ LPWSTR wzBuffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivResourcePathVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivResourcePath * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivResourcePath * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivResourcePath * This); + + HRESULT ( STDMETHODCALLTYPE *GetPath )( + ICLRPrivResourcePath * This, + /* [in] */ DWORD cchBuffer, + /* [out] */ LPDWORD pcchBuffer, + /* [optional][string][length_is][size_is][out] */ LPWSTR wzBuffer); + + END_INTERFACE + } ICLRPrivResourcePathVtbl; + + interface ICLRPrivResourcePath + { + CONST_VTBL struct ICLRPrivResourcePathVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivResourcePath_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivResourcePath_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivResourcePath_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivResourcePath_GetPath(This,cchBuffer,pcchBuffer,wzBuffer) \ + ( (This)->lpVtbl -> GetPath(This,cchBuffer,pcchBuffer,wzBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivResourcePath_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivResourceStream_INTERFACE_DEFINED__ +#define __ICLRPrivResourceStream_INTERFACE_DEFINED__ + +/* interface ICLRPrivResourceStream */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivResourceStream; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8545") + ICLRPrivResourceStream : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetStream( + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppvStream) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivResourceStreamVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivResourceStream * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivResourceStream * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivResourceStream * This); + + HRESULT ( STDMETHODCALLTYPE *GetStream )( + ICLRPrivResourceStream * This, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppvStream); + + END_INTERFACE + } ICLRPrivResourceStreamVtbl; + + interface ICLRPrivResourceStream + { + CONST_VTBL struct ICLRPrivResourceStreamVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivResourceStream_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivResourceStream_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivResourceStream_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivResourceStream_GetStream(This,riid,ppvStream) \ + ( (This)->lpVtbl -> GetStream(This,riid,ppvStream) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivResourceStream_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ +#define __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ + +/* interface ICLRPrivResourceHMODULE */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivResourceHMODULE; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2601F621-E462-404C-B299-3E1DE72F8546") + ICLRPrivResourceHMODULE : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetHMODULE( + /* [retval][out] */ HMODULE *phModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivResourceHMODULEVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivResourceHMODULE * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivResourceHMODULE * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivResourceHMODULE * This); + + HRESULT ( STDMETHODCALLTYPE *GetHMODULE )( + ICLRPrivResourceHMODULE * This, + /* [retval][out] */ HMODULE *phModule); + + END_INTERFACE + } ICLRPrivResourceHMODULEVtbl; + + interface ICLRPrivResourceHMODULE + { + CONST_VTBL struct ICLRPrivResourceHMODULEVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivResourceHMODULE_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivResourceHMODULE_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivResourceHMODULE_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivResourceHMODULE_GetHMODULE(This,phModule) \ + ( (This)->lpVtbl -> GetHMODULE(This,phModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivResourceHMODULE_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivResourceAssembly_INTERFACE_DEFINED__ +#define __ICLRPrivResourceAssembly_INTERFACE_DEFINED__ + +/* interface ICLRPrivResourceAssembly */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivResourceAssembly; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8d2d3cc9-1249-4ad4-977d-b772bd4e8a94") + ICLRPrivResourceAssembly : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAssembly( + /* [retval][out] */ LPVOID *pAssembly) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivResourceAssemblyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivResourceAssembly * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivResourceAssembly * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivResourceAssembly * This); + + HRESULT ( STDMETHODCALLTYPE *GetAssembly )( + ICLRPrivResourceAssembly * This, + /* [retval][out] */ LPVOID *pAssembly); + + END_INTERFACE + } ICLRPrivResourceAssemblyVtbl; + + interface ICLRPrivResourceAssembly + { + CONST_VTBL struct ICLRPrivResourceAssemblyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivResourceAssembly_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivResourceAssembly_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivResourceAssembly_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivResourceAssembly_GetAssembly(This,pAssembly) \ + ( (This)->lpVtbl -> GetAssembly(This,pAssembly) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivResourceAssembly_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivAssemblyInfo_INTERFACE_DEFINED__ +#define __ICLRPrivAssemblyInfo_INTERFACE_DEFINED__ + +/* interface ICLRPrivAssemblyInfo */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivAssemblyInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5653946E-800B-48B7-8B09-B1B879B54F68") + ICLRPrivAssemblyInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAssemblyName( + /* [in] */ DWORD cchBuffer, + /* [out] */ LPDWORD pcchBuffer, + /* [optional][string][out] */ LPWSTR wzBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyVersion( + /* [out] */ USHORT *pMajor, + /* [out] */ USHORT *pMinor, + /* [out] */ USHORT *pBuild, + /* [out] */ USHORT *pRevision) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyPublicKey( + /* [in] */ DWORD cbBuffer, + /* [out] */ LPDWORD pcbBuffer, + /* [optional][length_is][size_is][out] */ BYTE *pbBuffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivAssemblyInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivAssemblyInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivAssemblyInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivAssemblyInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyName )( + ICLRPrivAssemblyInfo * This, + /* [in] */ DWORD cchBuffer, + /* [out] */ LPDWORD pcchBuffer, + /* [optional][string][out] */ LPWSTR wzBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyVersion )( + ICLRPrivAssemblyInfo * This, + /* [out] */ USHORT *pMajor, + /* [out] */ USHORT *pMinor, + /* [out] */ USHORT *pBuild, + /* [out] */ USHORT *pRevision); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyPublicKey )( + ICLRPrivAssemblyInfo * This, + /* [in] */ DWORD cbBuffer, + /* [out] */ LPDWORD pcbBuffer, + /* [optional][length_is][size_is][out] */ BYTE *pbBuffer); + + END_INTERFACE + } ICLRPrivAssemblyInfoVtbl; + + interface ICLRPrivAssemblyInfo + { + CONST_VTBL struct ICLRPrivAssemblyInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivAssemblyInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivAssemblyInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivAssemblyInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivAssemblyInfo_GetAssemblyName(This,cchBuffer,pcchBuffer,wzBuffer) \ + ( (This)->lpVtbl -> GetAssemblyName(This,cchBuffer,pcchBuffer,wzBuffer) ) + +#define ICLRPrivAssemblyInfo_GetAssemblyVersion(This,pMajor,pMinor,pBuild,pRevision) \ + ( (This)->lpVtbl -> GetAssemblyVersion(This,pMajor,pMinor,pBuild,pRevision) ) + +#define ICLRPrivAssemblyInfo_GetAssemblyPublicKey(This,cbBuffer,pcbBuffer,pbBuffer) \ + ( (This)->lpVtbl -> GetAssemblyPublicKey(This,cbBuffer,pcbBuffer,pbBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivAssemblyInfo_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivAssemblyID_WinRT_INTERFACE_DEFINED__ +#define __ICLRPrivAssemblyID_WinRT_INTERFACE_DEFINED__ + +/* interface ICLRPrivAssemblyID_WinRT */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivAssemblyID_WinRT; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4372D277-9906-4FED-BF53-30C0B4010896") + ICLRPrivAssemblyID_WinRT : public IUnknown + { + public: + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivAssemblyID_WinRTVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivAssemblyID_WinRT * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivAssemblyID_WinRT * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivAssemblyID_WinRT * This); + + END_INTERFACE + } ICLRPrivAssemblyID_WinRTVtbl; + + interface ICLRPrivAssemblyID_WinRT + { + CONST_VTBL struct ICLRPrivAssemblyID_WinRTVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivAssemblyID_WinRT_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivAssemblyID_WinRT_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivAssemblyID_WinRT_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivAssemblyID_WinRT_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ +#define __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ + +/* interface ICLRPrivWinRtTypeBinder */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivWinRtTypeBinder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6DE2A085-EFF4-4078-9F60-B9D366736398") + ICLRPrivWinRtTypeBinder : public IUnknown + { + public: + virtual void *STDMETHODCALLTYPE FindAssemblyForWinRtTypeIfLoaded( + void *pAppDomain, + LPCUTF8 szNamespace, + LPCUTF8 szClassName) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivWinRtTypeBinderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivWinRtTypeBinder * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivWinRtTypeBinder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivWinRtTypeBinder * This); + + void *( STDMETHODCALLTYPE *FindAssemblyForWinRtTypeIfLoaded )( + ICLRPrivWinRtTypeBinder * This, + void *pAppDomain, + LPCUTF8 szNamespace, + LPCUTF8 szClassName); + + END_INTERFACE + } ICLRPrivWinRtTypeBinderVtbl; + + interface ICLRPrivWinRtTypeBinder + { + CONST_VTBL struct ICLRPrivWinRtTypeBinderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivWinRtTypeBinder_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivWinRtTypeBinder_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivWinRtTypeBinder_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivWinRtTypeBinder_FindAssemblyForWinRtTypeIfLoaded(This,pAppDomain,szNamespace,szClassName) \ + ( (This)->lpVtbl -> FindAssemblyForWinRtTypeIfLoaded(This,pAppDomain,szNamespace,szClassName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivWinRtTypeBinder_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/clrprivhosting.h b/lib/coreclr/src/pal/prebuilt/inc/clrprivhosting.h new file mode 100644 index 0000000000..c0c3fd36b6 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/clrprivhosting.h @@ -0,0 +1,236 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __CLRPrivHosting_h__ +#define __CLRPrivHosting_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __CLRPrivRuntime_FWD_DEFINED__ +#define __CLRPrivRuntime_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CLRPrivRuntime CLRPrivRuntime; +#else +typedef struct CLRPrivRuntime CLRPrivRuntime; +#endif /* __cplusplus */ + +#endif /* __CLRPrivRuntime_FWD_DEFINED__ */ + + +#ifndef __ICLRPrivRuntime_FWD_DEFINED__ +#define __ICLRPrivRuntime_FWD_DEFINED__ +typedef interface ICLRPrivRuntime ICLRPrivRuntime; + +#endif /* __ICLRPrivRuntime_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "clrprivbinding.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_CLRPrivHosting_0000_0000 */ +/* [local] */ + + + + +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivHosting_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_CLRPrivHosting_0000_0000_v0_0_s_ifspec; + + +#ifndef __CLRPrivHosting_LIBRARY_DEFINED__ +#define __CLRPrivHosting_LIBRARY_DEFINED__ + +/* library CLRPrivHosting */ +/* [uuid] */ + + +EXTERN_C const IID LIBID_CLRPrivHosting; + +EXTERN_C const CLSID CLSID_CLRPrivRuntime; + +#ifdef __cplusplus + +class DECLSPEC_UUID("BC1B53A8-DCBC-43B2-BB17-1E4061447AE8") +CLRPrivRuntime; +#endif +#endif /* __CLRPrivHosting_LIBRARY_DEFINED__ */ + +#ifndef __ICLRPrivRuntime_INTERFACE_DEFINED__ +#define __ICLRPrivRuntime_INTERFACE_DEFINED__ + +/* interface ICLRPrivRuntime */ +/* [object][local][version][uuid] */ + + +EXTERN_C const IID IID_ICLRPrivRuntime; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BC1B53A8-DCBC-43B2-BB17-1E4061447AE9") + ICLRPrivRuntime : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetInterface( + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( + /* [string][in] */ LPCWSTR pwzFriendlyName, + /* [in] */ ICLRPrivBinder *pBinder, + /* [retval][out] */ LPDWORD pdwAppDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateDelegate( + /* [in] */ DWORD appDomainID, + /* [string][in] */ LPCWSTR wszAssemblyName, + /* [string][in] */ LPCWSTR wszClassName, + /* [string][in] */ LPCWSTR wszMethodName, + /* [retval][out] */ LPVOID *ppvDelegate) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteMain( + /* [in] */ ICLRPrivBinder *pBinder, + /* [retval][out] */ int *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRPrivRuntimeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRPrivRuntime * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRPrivRuntime * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRPrivRuntime * This); + + HRESULT ( STDMETHODCALLTYPE *GetInterface )( + ICLRPrivRuntime * This, + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk); + + HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( + ICLRPrivRuntime * This, + /* [string][in] */ LPCWSTR pwzFriendlyName, + /* [in] */ ICLRPrivBinder *pBinder, + /* [retval][out] */ LPDWORD pdwAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( + ICLRPrivRuntime * This, + /* [in] */ DWORD appDomainID, + /* [string][in] */ LPCWSTR wszAssemblyName, + /* [string][in] */ LPCWSTR wszClassName, + /* [string][in] */ LPCWSTR wszMethodName, + /* [retval][out] */ LPVOID *ppvDelegate); + + HRESULT ( STDMETHODCALLTYPE *ExecuteMain )( + ICLRPrivRuntime * This, + /* [in] */ ICLRPrivBinder *pBinder, + /* [retval][out] */ int *pRetVal); + + END_INTERFACE + } ICLRPrivRuntimeVtbl; + + interface ICLRPrivRuntime + { + CONST_VTBL struct ICLRPrivRuntimeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRPrivRuntime_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRPrivRuntime_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRPrivRuntime_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRPrivRuntime_GetInterface(This,rclsid,riid,ppUnk) \ + ( (This)->lpVtbl -> GetInterface(This,rclsid,riid,ppUnk) ) + +#define ICLRPrivRuntime_CreateAppDomain(This,pwzFriendlyName,pBinder,pdwAppDomainId) \ + ( (This)->lpVtbl -> CreateAppDomain(This,pwzFriendlyName,pBinder,pdwAppDomainId) ) + +#define ICLRPrivRuntime_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,ppvDelegate) \ + ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,ppvDelegate) ) + +#define ICLRPrivRuntime_ExecuteMain(This,pBinder,pRetVal) \ + ( (This)->lpVtbl -> ExecuteMain(This,pBinder,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRPrivRuntime_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/clrprivruntimebinders.h b/lib/coreclr/src/pal/prebuilt/inc/clrprivruntimebinders.h new file mode 100644 index 0000000000..dc4324a5c6 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/clrprivruntimebinders.h @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __CLRPrivRuntimeBinders_h__ +#define __CLRPrivRuntimeBinders_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __CLRPrivAppXBinder_FWD_DEFINED__ +#define __CLRPrivAppXBinder_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CLRPrivAppXBinder CLRPrivAppXBinder; +#else +typedef struct CLRPrivAppXBinder CLRPrivAppXBinder; +#endif /* __cplusplus */ + +#endif /* __CLRPrivAppXBinder_FWD_DEFINED__ */ + + +#ifndef __CLRPrivFusionBinder_FWD_DEFINED__ +#define __CLRPrivFusionBinder_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CLRPrivFusionBinder CLRPrivFusionBinder; +#else +typedef struct CLRPrivFusionBinder CLRPrivFusionBinder; +#endif /* __cplusplus */ + +#endif /* __CLRPrivFusionBinder_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "clrprivbinding.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + + +#ifndef __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ +#define __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ + +/* library CLRPrivRuntimeBinders */ +/* [uuid] */ + + +EXTERN_C const IID LIBID_CLRPrivRuntimeBinders; + +EXTERN_C const CLSID CLSID_CLRPrivAppXBinder; + +#ifdef __cplusplus + +class DECLSPEC_UUID("E990F732-2D0A-48AC-87FC-EF12B618981A") +CLRPrivAppXBinder; +#endif + +EXTERN_C const CLSID CLSID_CLRPrivFusionBinder; + +#ifdef __cplusplus + +class DECLSPEC_UUID("E990F732-2D0A-48AC-87FC-EF12B618981C") +CLRPrivFusionBinder; +#endif +#endif /* __CLRPrivRuntimeBinders_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/cordebug.h b/lib/coreclr/src/pal/prebuilt/inc/cordebug.h new file mode 100644 index 0000000000..96dc9c0eb1 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/cordebug.h @@ -0,0 +1,18527 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for E:/repos/coreclr2/src/inc/cordebug.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __cordebug_h__ +#define __cordebug_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICorDebugDataTarget_FWD_DEFINED__ +#define __ICorDebugDataTarget_FWD_DEFINED__ +typedef interface ICorDebugDataTarget ICorDebugDataTarget; + +#endif /* __ICorDebugDataTarget_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStaticFieldSymbol_FWD_DEFINED__ +#define __ICorDebugStaticFieldSymbol_FWD_DEFINED__ +typedef interface ICorDebugStaticFieldSymbol ICorDebugStaticFieldSymbol; + +#endif /* __ICorDebugStaticFieldSymbol_FWD_DEFINED__ */ + + +#ifndef __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ +#define __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ +typedef interface ICorDebugInstanceFieldSymbol ICorDebugInstanceFieldSymbol; + +#endif /* __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ */ + + +#ifndef __ICorDebugVariableSymbol_FWD_DEFINED__ +#define __ICorDebugVariableSymbol_FWD_DEFINED__ +typedef interface ICorDebugVariableSymbol ICorDebugVariableSymbol; + +#endif /* __ICorDebugVariableSymbol_FWD_DEFINED__ */ + + +#ifndef __ICorDebugMemoryBuffer_FWD_DEFINED__ +#define __ICorDebugMemoryBuffer_FWD_DEFINED__ +typedef interface ICorDebugMemoryBuffer ICorDebugMemoryBuffer; + +#endif /* __ICorDebugMemoryBuffer_FWD_DEFINED__ */ + + +#ifndef __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ +#define __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ +typedef interface ICorDebugMergedAssemblyRecord ICorDebugMergedAssemblyRecord; + +#endif /* __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ */ + + +#ifndef __ICorDebugSymbolProvider_FWD_DEFINED__ +#define __ICorDebugSymbolProvider_FWD_DEFINED__ +typedef interface ICorDebugSymbolProvider ICorDebugSymbolProvider; + +#endif /* __ICorDebugSymbolProvider_FWD_DEFINED__ */ + + +#ifndef __ICorDebugSymbolProvider2_FWD_DEFINED__ +#define __ICorDebugSymbolProvider2_FWD_DEFINED__ +typedef interface ICorDebugSymbolProvider2 ICorDebugSymbolProvider2; + +#endif /* __ICorDebugSymbolProvider2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugVirtualUnwinder_FWD_DEFINED__ +#define __ICorDebugVirtualUnwinder_FWD_DEFINED__ +typedef interface ICorDebugVirtualUnwinder ICorDebugVirtualUnwinder; + +#endif /* __ICorDebugVirtualUnwinder_FWD_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget2_FWD_DEFINED__ +#define __ICorDebugDataTarget2_FWD_DEFINED__ +typedef interface ICorDebugDataTarget2 ICorDebugDataTarget2; + +#endif /* __ICorDebugDataTarget2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugLoadedModule_FWD_DEFINED__ +#define __ICorDebugLoadedModule_FWD_DEFINED__ +typedef interface ICorDebugLoadedModule ICorDebugLoadedModule; + +#endif /* __ICorDebugLoadedModule_FWD_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget3_FWD_DEFINED__ +#define __ICorDebugDataTarget3_FWD_DEFINED__ +typedef interface ICorDebugDataTarget3 ICorDebugDataTarget3; + +#endif /* __ICorDebugDataTarget3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget4_FWD_DEFINED__ +#define __ICorDebugDataTarget4_FWD_DEFINED__ +typedef interface ICorDebugDataTarget4 ICorDebugDataTarget4; + +#endif /* __ICorDebugDataTarget4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugMutableDataTarget_FWD_DEFINED__ +#define __ICorDebugMutableDataTarget_FWD_DEFINED__ +typedef interface ICorDebugMutableDataTarget ICorDebugMutableDataTarget; + +#endif /* __ICorDebugMutableDataTarget_FWD_DEFINED__ */ + + +#ifndef __ICorDebugMetaDataLocator_FWD_DEFINED__ +#define __ICorDebugMetaDataLocator_FWD_DEFINED__ +typedef interface ICorDebugMetaDataLocator ICorDebugMetaDataLocator; + +#endif /* __ICorDebugMetaDataLocator_FWD_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback_FWD_DEFINED__ +#define __ICorDebugManagedCallback_FWD_DEFINED__ +typedef interface ICorDebugManagedCallback ICorDebugManagedCallback; + +#endif /* __ICorDebugManagedCallback_FWD_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback3_FWD_DEFINED__ +#define __ICorDebugManagedCallback3_FWD_DEFINED__ +typedef interface ICorDebugManagedCallback3 ICorDebugManagedCallback3; + +#endif /* __ICorDebugManagedCallback3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback4_FWD_DEFINED__ +#define __ICorDebugManagedCallback4_FWD_DEFINED__ +typedef interface ICorDebugManagedCallback4 ICorDebugManagedCallback4; + +#endif /* __ICorDebugManagedCallback4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback2_FWD_DEFINED__ +#define __ICorDebugManagedCallback2_FWD_DEFINED__ +typedef interface ICorDebugManagedCallback2 ICorDebugManagedCallback2; + +#endif /* __ICorDebugManagedCallback2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugUnmanagedCallback_FWD_DEFINED__ +#define __ICorDebugUnmanagedCallback_FWD_DEFINED__ +typedef interface ICorDebugUnmanagedCallback ICorDebugUnmanagedCallback; + +#endif /* __ICorDebugUnmanagedCallback_FWD_DEFINED__ */ + + +#ifndef __ICorDebug_FWD_DEFINED__ +#define __ICorDebug_FWD_DEFINED__ +typedef interface ICorDebug ICorDebug; + +#endif /* __ICorDebug_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRemoteTarget_FWD_DEFINED__ +#define __ICorDebugRemoteTarget_FWD_DEFINED__ +typedef interface ICorDebugRemoteTarget ICorDebugRemoteTarget; + +#endif /* __ICorDebugRemoteTarget_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRemote_FWD_DEFINED__ +#define __ICorDebugRemote_FWD_DEFINED__ +typedef interface ICorDebugRemote ICorDebugRemote; + +#endif /* __ICorDebugRemote_FWD_DEFINED__ */ + + +#ifndef __ICorDebug2_FWD_DEFINED__ +#define __ICorDebug2_FWD_DEFINED__ +typedef interface ICorDebug2 ICorDebug2; + +#endif /* __ICorDebug2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugController_FWD_DEFINED__ +#define __ICorDebugController_FWD_DEFINED__ +typedef interface ICorDebugController ICorDebugController; + +#endif /* __ICorDebugController_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain_FWD_DEFINED__ +#define __ICorDebugAppDomain_FWD_DEFINED__ +typedef interface ICorDebugAppDomain ICorDebugAppDomain; + +#endif /* __ICorDebugAppDomain_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain2_FWD_DEFINED__ +#define __ICorDebugAppDomain2_FWD_DEFINED__ +typedef interface ICorDebugAppDomain2 ICorDebugAppDomain2; + +#endif /* __ICorDebugAppDomain2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEnum_FWD_DEFINED__ +#define __ICorDebugEnum_FWD_DEFINED__ +typedef interface ICorDebugEnum ICorDebugEnum; + +#endif /* __ICorDebugEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugGuidToTypeEnum_FWD_DEFINED__ +#define __ICorDebugGuidToTypeEnum_FWD_DEFINED__ +typedef interface ICorDebugGuidToTypeEnum ICorDebugGuidToTypeEnum; + +#endif /* __ICorDebugGuidToTypeEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain3_FWD_DEFINED__ +#define __ICorDebugAppDomain3_FWD_DEFINED__ +typedef interface ICorDebugAppDomain3 ICorDebugAppDomain3; + +#endif /* __ICorDebugAppDomain3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain4_FWD_DEFINED__ +#define __ICorDebugAppDomain4_FWD_DEFINED__ +typedef interface ICorDebugAppDomain4 ICorDebugAppDomain4; + +#endif /* __ICorDebugAppDomain4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAssembly_FWD_DEFINED__ +#define __ICorDebugAssembly_FWD_DEFINED__ +typedef interface ICorDebugAssembly ICorDebugAssembly; + +#endif /* __ICorDebugAssembly_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAssembly2_FWD_DEFINED__ +#define __ICorDebugAssembly2_FWD_DEFINED__ +typedef interface ICorDebugAssembly2 ICorDebugAssembly2; + +#endif /* __ICorDebugAssembly2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAssembly3_FWD_DEFINED__ +#define __ICorDebugAssembly3_FWD_DEFINED__ +typedef interface ICorDebugAssembly3 ICorDebugAssembly3; + +#endif /* __ICorDebugAssembly3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapEnum_FWD_DEFINED__ +#define __ICorDebugHeapEnum_FWD_DEFINED__ +typedef interface ICorDebugHeapEnum ICorDebugHeapEnum; + +#endif /* __ICorDebugHeapEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapSegmentEnum_FWD_DEFINED__ +#define __ICorDebugHeapSegmentEnum_FWD_DEFINED__ +typedef interface ICorDebugHeapSegmentEnum ICorDebugHeapSegmentEnum; + +#endif /* __ICorDebugHeapSegmentEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugGCReferenceEnum_FWD_DEFINED__ +#define __ICorDebugGCReferenceEnum_FWD_DEFINED__ +typedef interface ICorDebugGCReferenceEnum ICorDebugGCReferenceEnum; + +#endif /* __ICorDebugGCReferenceEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess_FWD_DEFINED__ +#define __ICorDebugProcess_FWD_DEFINED__ +typedef interface ICorDebugProcess ICorDebugProcess; + +#endif /* __ICorDebugProcess_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess2_FWD_DEFINED__ +#define __ICorDebugProcess2_FWD_DEFINED__ +typedef interface ICorDebugProcess2 ICorDebugProcess2; + +#endif /* __ICorDebugProcess2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess3_FWD_DEFINED__ +#define __ICorDebugProcess3_FWD_DEFINED__ +typedef interface ICorDebugProcess3 ICorDebugProcess3; + +#endif /* __ICorDebugProcess3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess5_FWD_DEFINED__ +#define __ICorDebugProcess5_FWD_DEFINED__ +typedef interface ICorDebugProcess5 ICorDebugProcess5; + +#endif /* __ICorDebugProcess5_FWD_DEFINED__ */ + + +#ifndef __ICorDebugDebugEvent_FWD_DEFINED__ +#define __ICorDebugDebugEvent_FWD_DEFINED__ +typedef interface ICorDebugDebugEvent ICorDebugDebugEvent; + +#endif /* __ICorDebugDebugEvent_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess6_FWD_DEFINED__ +#define __ICorDebugProcess6_FWD_DEFINED__ +typedef interface ICorDebugProcess6 ICorDebugProcess6; + +#endif /* __ICorDebugProcess6_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess7_FWD_DEFINED__ +#define __ICorDebugProcess7_FWD_DEFINED__ +typedef interface ICorDebugProcess7 ICorDebugProcess7; + +#endif /* __ICorDebugProcess7_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess8_FWD_DEFINED__ +#define __ICorDebugProcess8_FWD_DEFINED__ +typedef interface ICorDebugProcess8 ICorDebugProcess8; + +#endif /* __ICorDebugProcess8_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess10_FWD_DEFINED__ +#define __ICorDebugProcess10_FWD_DEFINED__ +typedef interface ICorDebugProcess10 ICorDebugProcess10; + +#endif /* __ICorDebugProcess10_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModuleDebugEvent_FWD_DEFINED__ +#define __ICorDebugModuleDebugEvent_FWD_DEFINED__ +typedef interface ICorDebugModuleDebugEvent ICorDebugModuleDebugEvent; + +#endif /* __ICorDebugModuleDebugEvent_FWD_DEFINED__ */ + + +#ifndef __ICorDebugExceptionDebugEvent_FWD_DEFINED__ +#define __ICorDebugExceptionDebugEvent_FWD_DEFINED__ +typedef interface ICorDebugExceptionDebugEvent ICorDebugExceptionDebugEvent; + +#endif /* __ICorDebugExceptionDebugEvent_FWD_DEFINED__ */ + + +#ifndef __ICorDebugBreakpoint_FWD_DEFINED__ +#define __ICorDebugBreakpoint_FWD_DEFINED__ +typedef interface ICorDebugBreakpoint ICorDebugBreakpoint; + +#endif /* __ICorDebugBreakpoint_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunctionBreakpoint_FWD_DEFINED__ +#define __ICorDebugFunctionBreakpoint_FWD_DEFINED__ +typedef interface ICorDebugFunctionBreakpoint ICorDebugFunctionBreakpoint; + +#endif /* __ICorDebugFunctionBreakpoint_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModuleBreakpoint_FWD_DEFINED__ +#define __ICorDebugModuleBreakpoint_FWD_DEFINED__ +typedef interface ICorDebugModuleBreakpoint ICorDebugModuleBreakpoint; + +#endif /* __ICorDebugModuleBreakpoint_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValueBreakpoint_FWD_DEFINED__ +#define __ICorDebugValueBreakpoint_FWD_DEFINED__ +typedef interface ICorDebugValueBreakpoint ICorDebugValueBreakpoint; + +#endif /* __ICorDebugValueBreakpoint_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStepper_FWD_DEFINED__ +#define __ICorDebugStepper_FWD_DEFINED__ +typedef interface ICorDebugStepper ICorDebugStepper; + +#endif /* __ICorDebugStepper_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStepper2_FWD_DEFINED__ +#define __ICorDebugStepper2_FWD_DEFINED__ +typedef interface ICorDebugStepper2 ICorDebugStepper2; + +#endif /* __ICorDebugStepper2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRegisterSet_FWD_DEFINED__ +#define __ICorDebugRegisterSet_FWD_DEFINED__ +typedef interface ICorDebugRegisterSet ICorDebugRegisterSet; + +#endif /* __ICorDebugRegisterSet_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRegisterSet2_FWD_DEFINED__ +#define __ICorDebugRegisterSet2_FWD_DEFINED__ +typedef interface ICorDebugRegisterSet2 ICorDebugRegisterSet2; + +#endif /* __ICorDebugRegisterSet2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread_FWD_DEFINED__ +#define __ICorDebugThread_FWD_DEFINED__ +typedef interface ICorDebugThread ICorDebugThread; + +#endif /* __ICorDebugThread_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread2_FWD_DEFINED__ +#define __ICorDebugThread2_FWD_DEFINED__ +typedef interface ICorDebugThread2 ICorDebugThread2; + +#endif /* __ICorDebugThread2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread3_FWD_DEFINED__ +#define __ICorDebugThread3_FWD_DEFINED__ +typedef interface ICorDebugThread3 ICorDebugThread3; + +#endif /* __ICorDebugThread3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread4_FWD_DEFINED__ +#define __ICorDebugThread4_FWD_DEFINED__ +typedef interface ICorDebugThread4 ICorDebugThread4; + +#endif /* __ICorDebugThread4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStackWalk_FWD_DEFINED__ +#define __ICorDebugStackWalk_FWD_DEFINED__ +typedef interface ICorDebugStackWalk ICorDebugStackWalk; + +#endif /* __ICorDebugStackWalk_FWD_DEFINED__ */ + + +#ifndef __ICorDebugChain_FWD_DEFINED__ +#define __ICorDebugChain_FWD_DEFINED__ +typedef interface ICorDebugChain ICorDebugChain; + +#endif /* __ICorDebugChain_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFrame_FWD_DEFINED__ +#define __ICorDebugFrame_FWD_DEFINED__ +typedef interface ICorDebugFrame ICorDebugFrame; + +#endif /* __ICorDebugFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame_FWD_DEFINED__ +#define __ICorDebugInternalFrame_FWD_DEFINED__ +typedef interface ICorDebugInternalFrame ICorDebugInternalFrame; + +#endif /* __ICorDebugInternalFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame2_FWD_DEFINED__ +#define __ICorDebugInternalFrame2_FWD_DEFINED__ +typedef interface ICorDebugInternalFrame2 ICorDebugInternalFrame2; + +#endif /* __ICorDebugInternalFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame_FWD_DEFINED__ +#define __ICorDebugILFrame_FWD_DEFINED__ +typedef interface ICorDebugILFrame ICorDebugILFrame; + +#endif /* __ICorDebugILFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame2_FWD_DEFINED__ +#define __ICorDebugILFrame2_FWD_DEFINED__ +typedef interface ICorDebugILFrame2 ICorDebugILFrame2; + +#endif /* __ICorDebugILFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame3_FWD_DEFINED__ +#define __ICorDebugILFrame3_FWD_DEFINED__ +typedef interface ICorDebugILFrame3 ICorDebugILFrame3; + +#endif /* __ICorDebugILFrame3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame4_FWD_DEFINED__ +#define __ICorDebugILFrame4_FWD_DEFINED__ +typedef interface ICorDebugILFrame4 ICorDebugILFrame4; + +#endif /* __ICorDebugILFrame4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugNativeFrame_FWD_DEFINED__ +#define __ICorDebugNativeFrame_FWD_DEFINED__ +typedef interface ICorDebugNativeFrame ICorDebugNativeFrame; + +#endif /* __ICorDebugNativeFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugNativeFrame2_FWD_DEFINED__ +#define __ICorDebugNativeFrame2_FWD_DEFINED__ +typedef interface ICorDebugNativeFrame2 ICorDebugNativeFrame2; + +#endif /* __ICorDebugNativeFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModule3_FWD_DEFINED__ +#define __ICorDebugModule3_FWD_DEFINED__ +typedef interface ICorDebugModule3 ICorDebugModule3; + +#endif /* __ICorDebugModule3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ +#define __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ +typedef interface ICorDebugRuntimeUnwindableFrame ICorDebugRuntimeUnwindableFrame; + +#endif /* __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModule_FWD_DEFINED__ +#define __ICorDebugModule_FWD_DEFINED__ +typedef interface ICorDebugModule ICorDebugModule; + +#endif /* __ICorDebugModule_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModule2_FWD_DEFINED__ +#define __ICorDebugModule2_FWD_DEFINED__ +typedef interface ICorDebugModule2 ICorDebugModule2; + +#endif /* __ICorDebugModule2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunction_FWD_DEFINED__ +#define __ICorDebugFunction_FWD_DEFINED__ +typedef interface ICorDebugFunction ICorDebugFunction; + +#endif /* __ICorDebugFunction_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunction2_FWD_DEFINED__ +#define __ICorDebugFunction2_FWD_DEFINED__ +typedef interface ICorDebugFunction2 ICorDebugFunction2; + +#endif /* __ICorDebugFunction2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunction3_FWD_DEFINED__ +#define __ICorDebugFunction3_FWD_DEFINED__ +typedef interface ICorDebugFunction3 ICorDebugFunction3; + +#endif /* __ICorDebugFunction3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunction4_FWD_DEFINED__ +#define __ICorDebugFunction4_FWD_DEFINED__ +typedef interface ICorDebugFunction4 ICorDebugFunction4; + +#endif /* __ICorDebugFunction4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugCode_FWD_DEFINED__ +#define __ICorDebugCode_FWD_DEFINED__ +typedef interface ICorDebugCode ICorDebugCode; + +#endif /* __ICorDebugCode_FWD_DEFINED__ */ + + +#ifndef __ICorDebugCode2_FWD_DEFINED__ +#define __ICorDebugCode2_FWD_DEFINED__ +typedef interface ICorDebugCode2 ICorDebugCode2; + +#endif /* __ICorDebugCode2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugCode3_FWD_DEFINED__ +#define __ICorDebugCode3_FWD_DEFINED__ +typedef interface ICorDebugCode3 ICorDebugCode3; + +#endif /* __ICorDebugCode3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugCode4_FWD_DEFINED__ +#define __ICorDebugCode4_FWD_DEFINED__ +typedef interface ICorDebugCode4 ICorDebugCode4; + +#endif /* __ICorDebugCode4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILCode_FWD_DEFINED__ +#define __ICorDebugILCode_FWD_DEFINED__ +typedef interface ICorDebugILCode ICorDebugILCode; + +#endif /* __ICorDebugILCode_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILCode2_FWD_DEFINED__ +#define __ICorDebugILCode2_FWD_DEFINED__ +typedef interface ICorDebugILCode2 ICorDebugILCode2; + +#endif /* __ICorDebugILCode2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugClass_FWD_DEFINED__ +#define __ICorDebugClass_FWD_DEFINED__ +typedef interface ICorDebugClass ICorDebugClass; + +#endif /* __ICorDebugClass_FWD_DEFINED__ */ + + +#ifndef __ICorDebugClass2_FWD_DEFINED__ +#define __ICorDebugClass2_FWD_DEFINED__ +typedef interface ICorDebugClass2 ICorDebugClass2; + +#endif /* __ICorDebugClass2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEval_FWD_DEFINED__ +#define __ICorDebugEval_FWD_DEFINED__ +typedef interface ICorDebugEval ICorDebugEval; + +#endif /* __ICorDebugEval_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEval2_FWD_DEFINED__ +#define __ICorDebugEval2_FWD_DEFINED__ +typedef interface ICorDebugEval2 ICorDebugEval2; + +#endif /* __ICorDebugEval2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValue_FWD_DEFINED__ +#define __ICorDebugValue_FWD_DEFINED__ +typedef interface ICorDebugValue ICorDebugValue; + +#endif /* __ICorDebugValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValue2_FWD_DEFINED__ +#define __ICorDebugValue2_FWD_DEFINED__ +typedef interface ICorDebugValue2 ICorDebugValue2; + +#endif /* __ICorDebugValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValue3_FWD_DEFINED__ +#define __ICorDebugValue3_FWD_DEFINED__ +typedef interface ICorDebugValue3 ICorDebugValue3; + +#endif /* __ICorDebugValue3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugGenericValue_FWD_DEFINED__ +#define __ICorDebugGenericValue_FWD_DEFINED__ +typedef interface ICorDebugGenericValue ICorDebugGenericValue; + +#endif /* __ICorDebugGenericValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugReferenceValue_FWD_DEFINED__ +#define __ICorDebugReferenceValue_FWD_DEFINED__ +typedef interface ICorDebugReferenceValue ICorDebugReferenceValue; + +#endif /* __ICorDebugReferenceValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue_FWD_DEFINED__ +#define __ICorDebugHeapValue_FWD_DEFINED__ +typedef interface ICorDebugHeapValue ICorDebugHeapValue; + +#endif /* __ICorDebugHeapValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue2_FWD_DEFINED__ +#define __ICorDebugHeapValue2_FWD_DEFINED__ +typedef interface ICorDebugHeapValue2 ICorDebugHeapValue2; + +#endif /* __ICorDebugHeapValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue3_FWD_DEFINED__ +#define __ICorDebugHeapValue3_FWD_DEFINED__ +typedef interface ICorDebugHeapValue3 ICorDebugHeapValue3; + +#endif /* __ICorDebugHeapValue3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugObjectValue_FWD_DEFINED__ +#define __ICorDebugObjectValue_FWD_DEFINED__ +typedef interface ICorDebugObjectValue ICorDebugObjectValue; + +#endif /* __ICorDebugObjectValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugObjectValue2_FWD_DEFINED__ +#define __ICorDebugObjectValue2_FWD_DEFINED__ +typedef interface ICorDebugObjectValue2 ICorDebugObjectValue2; + +#endif /* __ICorDebugObjectValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugDelegateObjectValue_FWD_DEFINED__ +#define __ICorDebugDelegateObjectValue_FWD_DEFINED__ +typedef interface ICorDebugDelegateObjectValue ICorDebugDelegateObjectValue; + +#endif /* __ICorDebugDelegateObjectValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugBoxValue_FWD_DEFINED__ +#define __ICorDebugBoxValue_FWD_DEFINED__ +typedef interface ICorDebugBoxValue ICorDebugBoxValue; + +#endif /* __ICorDebugBoxValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStringValue_FWD_DEFINED__ +#define __ICorDebugStringValue_FWD_DEFINED__ +typedef interface ICorDebugStringValue ICorDebugStringValue; + +#endif /* __ICorDebugStringValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugArrayValue_FWD_DEFINED__ +#define __ICorDebugArrayValue_FWD_DEFINED__ +typedef interface ICorDebugArrayValue ICorDebugArrayValue; + +#endif /* __ICorDebugArrayValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugVariableHome_FWD_DEFINED__ +#define __ICorDebugVariableHome_FWD_DEFINED__ +typedef interface ICorDebugVariableHome ICorDebugVariableHome; + +#endif /* __ICorDebugVariableHome_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHandleValue_FWD_DEFINED__ +#define __ICorDebugHandleValue_FWD_DEFINED__ +typedef interface ICorDebugHandleValue ICorDebugHandleValue; + +#endif /* __ICorDebugHandleValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugContext_FWD_DEFINED__ +#define __ICorDebugContext_FWD_DEFINED__ +typedef interface ICorDebugContext ICorDebugContext; + +#endif /* __ICorDebugContext_FWD_DEFINED__ */ + + +#ifndef __ICorDebugComObjectValue_FWD_DEFINED__ +#define __ICorDebugComObjectValue_FWD_DEFINED__ +typedef interface ICorDebugComObjectValue ICorDebugComObjectValue; + +#endif /* __ICorDebugComObjectValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugObjectEnum_FWD_DEFINED__ +#define __ICorDebugObjectEnum_FWD_DEFINED__ +typedef interface ICorDebugObjectEnum ICorDebugObjectEnum; + +#endif /* __ICorDebugObjectEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugBreakpointEnum_FWD_DEFINED__ +#define __ICorDebugBreakpointEnum_FWD_DEFINED__ +typedef interface ICorDebugBreakpointEnum ICorDebugBreakpointEnum; + +#endif /* __ICorDebugBreakpointEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStepperEnum_FWD_DEFINED__ +#define __ICorDebugStepperEnum_FWD_DEFINED__ +typedef interface ICorDebugStepperEnum ICorDebugStepperEnum; + +#endif /* __ICorDebugStepperEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcessEnum_FWD_DEFINED__ +#define __ICorDebugProcessEnum_FWD_DEFINED__ +typedef interface ICorDebugProcessEnum ICorDebugProcessEnum; + +#endif /* __ICorDebugProcessEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThreadEnum_FWD_DEFINED__ +#define __ICorDebugThreadEnum_FWD_DEFINED__ +typedef interface ICorDebugThreadEnum ICorDebugThreadEnum; + +#endif /* __ICorDebugThreadEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFrameEnum_FWD_DEFINED__ +#define __ICorDebugFrameEnum_FWD_DEFINED__ +typedef interface ICorDebugFrameEnum ICorDebugFrameEnum; + +#endif /* __ICorDebugFrameEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugChainEnum_FWD_DEFINED__ +#define __ICorDebugChainEnum_FWD_DEFINED__ +typedef interface ICorDebugChainEnum ICorDebugChainEnum; + +#endif /* __ICorDebugChainEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModuleEnum_FWD_DEFINED__ +#define __ICorDebugModuleEnum_FWD_DEFINED__ +typedef interface ICorDebugModuleEnum ICorDebugModuleEnum; + +#endif /* __ICorDebugModuleEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValueEnum_FWD_DEFINED__ +#define __ICorDebugValueEnum_FWD_DEFINED__ +typedef interface ICorDebugValueEnum ICorDebugValueEnum; + +#endif /* __ICorDebugValueEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugVariableHomeEnum_FWD_DEFINED__ +#define __ICorDebugVariableHomeEnum_FWD_DEFINED__ +typedef interface ICorDebugVariableHomeEnum ICorDebugVariableHomeEnum; + +#endif /* __ICorDebugVariableHomeEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugCodeEnum_FWD_DEFINED__ +#define __ICorDebugCodeEnum_FWD_DEFINED__ +typedef interface ICorDebugCodeEnum ICorDebugCodeEnum; + +#endif /* __ICorDebugCodeEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugTypeEnum_FWD_DEFINED__ +#define __ICorDebugTypeEnum_FWD_DEFINED__ +typedef interface ICorDebugTypeEnum ICorDebugTypeEnum; + +#endif /* __ICorDebugTypeEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugType_FWD_DEFINED__ +#define __ICorDebugType_FWD_DEFINED__ +typedef interface ICorDebugType ICorDebugType; + +#endif /* __ICorDebugType_FWD_DEFINED__ */ + + +#ifndef __ICorDebugType2_FWD_DEFINED__ +#define __ICorDebugType2_FWD_DEFINED__ +typedef interface ICorDebugType2 ICorDebugType2; + +#endif /* __ICorDebugType2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugErrorInfoEnum_FWD_DEFINED__ +#define __ICorDebugErrorInfoEnum_FWD_DEFINED__ +typedef interface ICorDebugErrorInfoEnum ICorDebugErrorInfoEnum; + +#endif /* __ICorDebugErrorInfoEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomainEnum_FWD_DEFINED__ +#define __ICorDebugAppDomainEnum_FWD_DEFINED__ +typedef interface ICorDebugAppDomainEnum ICorDebugAppDomainEnum; + +#endif /* __ICorDebugAppDomainEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAssemblyEnum_FWD_DEFINED__ +#define __ICorDebugAssemblyEnum_FWD_DEFINED__ +typedef interface ICorDebugAssemblyEnum ICorDebugAssemblyEnum; + +#endif /* __ICorDebugAssemblyEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugBlockingObjectEnum_FWD_DEFINED__ +#define __ICorDebugBlockingObjectEnum_FWD_DEFINED__ +typedef interface ICorDebugBlockingObjectEnum ICorDebugBlockingObjectEnum; + +#endif /* __ICorDebugBlockingObjectEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugMDA_FWD_DEFINED__ +#define __ICorDebugMDA_FWD_DEFINED__ +typedef interface ICorDebugMDA ICorDebugMDA; + +#endif /* __ICorDebugMDA_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ +#define __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ +typedef interface ICorDebugEditAndContinueErrorInfo ICorDebugEditAndContinueErrorInfo; + +#endif /* __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ +#define __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ +typedef interface ICorDebugEditAndContinueSnapshot ICorDebugEditAndContinueSnapshot; + +#endif /* __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ */ + + +#ifndef __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ +#define __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ +typedef interface ICorDebugExceptionObjectCallStackEnum ICorDebugExceptionObjectCallStackEnum; + +#endif /* __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ */ + + +#ifndef __ICorDebugExceptionObjectValue_FWD_DEFINED__ +#define __ICorDebugExceptionObjectValue_FWD_DEFINED__ +typedef interface ICorDebugExceptionObjectValue ICorDebugExceptionObjectValue; + +#endif /* __ICorDebugExceptionObjectValue_FWD_DEFINED__ */ + + +#ifndef __CorDebug_FWD_DEFINED__ +#define __CorDebug_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorDebug CorDebug; +#else +typedef struct CorDebug CorDebug; +#endif /* __cplusplus */ + +#endif /* __CorDebug_FWD_DEFINED__ */ + + +#ifndef __EmbeddedCLRCorDebug_FWD_DEFINED__ +#define __EmbeddedCLRCorDebug_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class EmbeddedCLRCorDebug EmbeddedCLRCorDebug; +#else +typedef struct EmbeddedCLRCorDebug EmbeddedCLRCorDebug; +#endif /* __cplusplus */ + +#endif /* __EmbeddedCLRCorDebug_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValue_FWD_DEFINED__ +#define __ICorDebugValue_FWD_DEFINED__ +typedef interface ICorDebugValue ICorDebugValue; + +#endif /* __ICorDebugValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugReferenceValue_FWD_DEFINED__ +#define __ICorDebugReferenceValue_FWD_DEFINED__ +typedef interface ICorDebugReferenceValue ICorDebugReferenceValue; + +#endif /* __ICorDebugReferenceValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue_FWD_DEFINED__ +#define __ICorDebugHeapValue_FWD_DEFINED__ +typedef interface ICorDebugHeapValue ICorDebugHeapValue; + +#endif /* __ICorDebugHeapValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStringValue_FWD_DEFINED__ +#define __ICorDebugStringValue_FWD_DEFINED__ +typedef interface ICorDebugStringValue ICorDebugStringValue; + +#endif /* __ICorDebugStringValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugGenericValue_FWD_DEFINED__ +#define __ICorDebugGenericValue_FWD_DEFINED__ +typedef interface ICorDebugGenericValue ICorDebugGenericValue; + +#endif /* __ICorDebugGenericValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugBoxValue_FWD_DEFINED__ +#define __ICorDebugBoxValue_FWD_DEFINED__ +typedef interface ICorDebugBoxValue ICorDebugBoxValue; + +#endif /* __ICorDebugBoxValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugArrayValue_FWD_DEFINED__ +#define __ICorDebugArrayValue_FWD_DEFINED__ +typedef interface ICorDebugArrayValue ICorDebugArrayValue; + +#endif /* __ICorDebugArrayValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFrame_FWD_DEFINED__ +#define __ICorDebugFrame_FWD_DEFINED__ +typedef interface ICorDebugFrame ICorDebugFrame; + +#endif /* __ICorDebugFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame_FWD_DEFINED__ +#define __ICorDebugILFrame_FWD_DEFINED__ +typedef interface ICorDebugILFrame ICorDebugILFrame; + +#endif /* __ICorDebugILFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame_FWD_DEFINED__ +#define __ICorDebugInternalFrame_FWD_DEFINED__ +typedef interface ICorDebugInternalFrame ICorDebugInternalFrame; + +#endif /* __ICorDebugInternalFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame2_FWD_DEFINED__ +#define __ICorDebugInternalFrame2_FWD_DEFINED__ +typedef interface ICorDebugInternalFrame2 ICorDebugInternalFrame2; + +#endif /* __ICorDebugInternalFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugNativeFrame_FWD_DEFINED__ +#define __ICorDebugNativeFrame_FWD_DEFINED__ +typedef interface ICorDebugNativeFrame ICorDebugNativeFrame; + +#endif /* __ICorDebugNativeFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugNativeFrame2_FWD_DEFINED__ +#define __ICorDebugNativeFrame2_FWD_DEFINED__ +typedef interface ICorDebugNativeFrame2 ICorDebugNativeFrame2; + +#endif /* __ICorDebugNativeFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ +#define __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ +typedef interface ICorDebugRuntimeUnwindableFrame ICorDebugRuntimeUnwindableFrame; + +#endif /* __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback2_FWD_DEFINED__ +#define __ICorDebugManagedCallback2_FWD_DEFINED__ +typedef interface ICorDebugManagedCallback2 ICorDebugManagedCallback2; + +#endif /* __ICorDebugManagedCallback2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain2_FWD_DEFINED__ +#define __ICorDebugAppDomain2_FWD_DEFINED__ +typedef interface ICorDebugAppDomain2 ICorDebugAppDomain2; + +#endif /* __ICorDebugAppDomain2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain3_FWD_DEFINED__ +#define __ICorDebugAppDomain3_FWD_DEFINED__ +typedef interface ICorDebugAppDomain3 ICorDebugAppDomain3; + +#endif /* __ICorDebugAppDomain3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugAssembly2_FWD_DEFINED__ +#define __ICorDebugAssembly2_FWD_DEFINED__ +typedef interface ICorDebugAssembly2 ICorDebugAssembly2; + +#endif /* __ICorDebugAssembly2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugProcess2_FWD_DEFINED__ +#define __ICorDebugProcess2_FWD_DEFINED__ +typedef interface ICorDebugProcess2 ICorDebugProcess2; + +#endif /* __ICorDebugProcess2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugStepper2_FWD_DEFINED__ +#define __ICorDebugStepper2_FWD_DEFINED__ +typedef interface ICorDebugStepper2 ICorDebugStepper2; + +#endif /* __ICorDebugStepper2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread2_FWD_DEFINED__ +#define __ICorDebugThread2_FWD_DEFINED__ +typedef interface ICorDebugThread2 ICorDebugThread2; + +#endif /* __ICorDebugThread2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugThread3_FWD_DEFINED__ +#define __ICorDebugThread3_FWD_DEFINED__ +typedef interface ICorDebugThread3 ICorDebugThread3; + +#endif /* __ICorDebugThread3_FWD_DEFINED__ */ + + +#ifndef __ICorDebugILFrame2_FWD_DEFINED__ +#define __ICorDebugILFrame2_FWD_DEFINED__ +typedef interface ICorDebugILFrame2 ICorDebugILFrame2; + +#endif /* __ICorDebugILFrame2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModule2_FWD_DEFINED__ +#define __ICorDebugModule2_FWD_DEFINED__ +typedef interface ICorDebugModule2 ICorDebugModule2; + +#endif /* __ICorDebugModule2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugFunction2_FWD_DEFINED__ +#define __ICorDebugFunction2_FWD_DEFINED__ +typedef interface ICorDebugFunction2 ICorDebugFunction2; + +#endif /* __ICorDebugFunction2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugClass2_FWD_DEFINED__ +#define __ICorDebugClass2_FWD_DEFINED__ +typedef interface ICorDebugClass2 ICorDebugClass2; + +#endif /* __ICorDebugClass2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugEval2_FWD_DEFINED__ +#define __ICorDebugEval2_FWD_DEFINED__ +typedef interface ICorDebugEval2 ICorDebugEval2; + +#endif /* __ICorDebugEval2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugValue2_FWD_DEFINED__ +#define __ICorDebugValue2_FWD_DEFINED__ +typedef interface ICorDebugValue2 ICorDebugValue2; + +#endif /* __ICorDebugValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugObjectValue2_FWD_DEFINED__ +#define __ICorDebugObjectValue2_FWD_DEFINED__ +typedef interface ICorDebugObjectValue2 ICorDebugObjectValue2; + +#endif /* __ICorDebugObjectValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHandleValue_FWD_DEFINED__ +#define __ICorDebugHandleValue_FWD_DEFINED__ +typedef interface ICorDebugHandleValue ICorDebugHandleValue; + +#endif /* __ICorDebugHandleValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue2_FWD_DEFINED__ +#define __ICorDebugHeapValue2_FWD_DEFINED__ +typedef interface ICorDebugHeapValue2 ICorDebugHeapValue2; + +#endif /* __ICorDebugHeapValue2_FWD_DEFINED__ */ + + +#ifndef __ICorDebugComObjectValue_FWD_DEFINED__ +#define __ICorDebugComObjectValue_FWD_DEFINED__ +typedef interface ICorDebugComObjectValue ICorDebugComObjectValue; + +#endif /* __ICorDebugComObjectValue_FWD_DEFINED__ */ + + +#ifndef __ICorDebugModule3_FWD_DEFINED__ +#define __ICorDebugModule3_FWD_DEFINED__ +typedef interface ICorDebugModule3 ICorDebugModule3; + +#endif /* __ICorDebugModule3_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "objidl.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_cordebug_0000_0000 */ +/* [local] */ + +#if 0 +typedef UINT32 mdToken; + +typedef mdToken mdModule; + +typedef SIZE_T mdScope; + +typedef mdToken mdTypeDef; + +typedef mdToken mdSourceFile; + +typedef mdToken mdMemberRef; + +typedef mdToken mdMethodDef; + +typedef mdToken mdFieldDef; + +typedef mdToken mdSignature; + +typedef ULONG CorElementType; + +typedef SIZE_T PCCOR_SIGNATURE; + +typedef SIZE_T LPDEBUG_EVENT; + +typedef SIZE_T LPSTARTUPINFOW; + +typedef SIZE_T LPPROCESS_INFORMATION; + +typedef const void *LPCVOID; + +#endif +typedef /* [wire_marshal] */ void *HPROCESS; + +typedef /* [wire_marshal] */ void *HTHREAD; + +typedef UINT64 TASKID; + +typedef DWORD CONNID; + +#ifndef _COR_IL_MAP +#define _COR_IL_MAP +typedef struct _COR_IL_MAP + { + ULONG32 oldOffset; + ULONG32 newOffset; + BOOL fAccurate; + } COR_IL_MAP; + +#endif //_COR_IL_MAP +#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ +#define _COR_DEBUG_IL_TO_NATIVE_MAP_ +typedef +enum CorDebugIlToNativeMappingTypes + { + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3 + } CorDebugIlToNativeMappingTypes; + +typedef struct COR_DEBUG_IL_TO_NATIVE_MAP + { + ULONG32 ilOffset; + ULONG32 nativeStartOffset; + ULONG32 nativeEndOffset; + } COR_DEBUG_IL_TO_NATIVE_MAP; + +#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ +#define REMOTE_DEBUGGING_DLL_ENTRY L"Software\\Microsoft\\.NETFramework\\Debugger\\ActivateRemoteDebugging" +typedef +enum CorDebugJITCompilerFlags + { + CORDEBUG_JIT_DEFAULT = 0x1, + CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3, + CORDEBUG_JIT_ENABLE_ENC = 0x7 + } CorDebugJITCompilerFlags; + +typedef +enum CorDebugJITCompilerFlagsDecprecated + { + CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1 + } CorDebugJITCompilerFlagsDeprecated; + +typedef +enum CorDebugNGENPolicy + { + DISABLE_LOCAL_NIC = 1 + } CorDebugNGENPolicy; + +#pragma warning(push) +#pragma warning(disable:28718) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#pragma warning(pop) +typedef ULONG64 CORDB_ADDRESS; + +typedef ULONG64 CORDB_REGISTER; + +typedef DWORD CORDB_CONTINUE_STATUS; + +typedef +enum CorDebugBlockingReason + { + BLOCKING_NONE = 0, + BLOCKING_MONITOR_CRITICAL_SECTION = 0x1, + BLOCKING_MONITOR_EVENT = 0x2 + } CorDebugBlockingReason; + +typedef struct CorDebugBlockingObject + { + ICorDebugValue *pBlockingObject; + DWORD dwTimeout; + CorDebugBlockingReason blockingReason; + } CorDebugBlockingObject; + +typedef struct CorDebugExceptionObjectStackFrame + { + ICorDebugModule *pModule; + CORDB_ADDRESS ip; + mdMethodDef methodDef; + BOOL isLastForeignExceptionFrame; + } CorDebugExceptionObjectStackFrame; + +typedef struct CorDebugGuidToTypeMapping + { + GUID iid; + ICorDebugType *pType; + } CorDebugGuidToTypeMapping; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_s_ifspec; + +#ifndef __ICorDebugDataTarget_INTERFACE_DEFINED__ +#define __ICorDebugDataTarget_INTERFACE_DEFINED__ + +/* interface ICorDebugDataTarget */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugPlatform + { + CORDB_PLATFORM_WINDOWS_X86 = 0, + CORDB_PLATFORM_WINDOWS_AMD64 = ( CORDB_PLATFORM_WINDOWS_X86 + 1 ) , + CORDB_PLATFORM_WINDOWS_IA64 = ( CORDB_PLATFORM_WINDOWS_AMD64 + 1 ) , + CORDB_PLATFORM_MAC_PPC = ( CORDB_PLATFORM_WINDOWS_IA64 + 1 ) , + CORDB_PLATFORM_MAC_X86 = ( CORDB_PLATFORM_MAC_PPC + 1 ) , + CORDB_PLATFORM_WINDOWS_ARM = ( CORDB_PLATFORM_MAC_X86 + 1 ) , + CORDB_PLATFORM_MAC_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM + 1 ) , + CORDB_PLATFORM_WINDOWS_ARM64 = ( CORDB_PLATFORM_MAC_AMD64 + 1 ) , + CORDB_PLATFORM_POSIX_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM64 + 1 ) , + CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , + CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , + CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) + } CorDebugPlatform; + + +EXTERN_C const IID IID_ICorDebugDataTarget; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FE06DC28-49FB-4636-A4A3-E80DB4AE116C") + ICorDebugDataTarget : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetPlatform( + /* [out] */ CorDebugPlatform *pTargetPlatform) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadVirtual( + /* [in] */ CORDB_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *pBuffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *pBytesRead) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ DWORD dwThreadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *pContext) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDataTargetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDataTarget * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDataTarget * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDataTarget * This); + + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + ICorDebugDataTarget * This, + /* [out] */ CorDebugPlatform *pTargetPlatform); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + ICorDebugDataTarget * This, + /* [in] */ CORDB_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *pBuffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *pBytesRead); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorDebugDataTarget * This, + /* [in] */ DWORD dwThreadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *pContext); + + END_INTERFACE + } ICorDebugDataTargetVtbl; + + interface ICorDebugDataTarget + { + CONST_VTBL struct ICorDebugDataTargetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDataTarget_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDataTarget_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDataTarget_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDataTarget_GetPlatform(This,pTargetPlatform) \ + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + +#define ICorDebugDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + +#define ICorDebugDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDataTarget_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ +#define __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ + +/* interface ICorDebugStaticFieldSymbol */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B") + ICorDebugStaticFieldSymbol : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcbSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddress( + /* [out] */ CORDB_ADDRESS *pRVA) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStaticFieldSymbolVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStaticFieldSymbol * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStaticFieldSymbol * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStaticFieldSymbol * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugStaticFieldSymbol * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugStaticFieldSymbol * This, + /* [out] */ ULONG32 *pcbSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugStaticFieldSymbol * This, + /* [out] */ CORDB_ADDRESS *pRVA); + + END_INTERFACE + } ICorDebugStaticFieldSymbolVtbl; + + interface ICorDebugStaticFieldSymbol + { + CONST_VTBL struct ICorDebugStaticFieldSymbolVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStaticFieldSymbol_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStaticFieldSymbol_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStaticFieldSymbol_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStaticFieldSymbol_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugStaticFieldSymbol_GetSize(This,pcbSize) \ + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + +#define ICorDebugStaticFieldSymbol_GetAddress(This,pRVA) \ + ( (This)->lpVtbl -> GetAddress(This,pRVA) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ +#define __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ + +/* interface ICorDebugInstanceFieldSymbol */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A074096B-3ADC-4485-81DA-68C7A4EA52DB") + ICorDebugInstanceFieldSymbol : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcbSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOffset( + /* [out] */ ULONG32 *pcbOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugInstanceFieldSymbolVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugInstanceFieldSymbol * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugInstanceFieldSymbol * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugInstanceFieldSymbol * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugInstanceFieldSymbol * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugInstanceFieldSymbol * This, + /* [out] */ ULONG32 *pcbSize); + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( + ICorDebugInstanceFieldSymbol * This, + /* [out] */ ULONG32 *pcbOffset); + + END_INTERFACE + } ICorDebugInstanceFieldSymbolVtbl; + + interface ICorDebugInstanceFieldSymbol + { + CONST_VTBL struct ICorDebugInstanceFieldSymbolVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugInstanceFieldSymbol_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugInstanceFieldSymbol_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugInstanceFieldSymbol_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugInstanceFieldSymbol_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugInstanceFieldSymbol_GetSize(This,pcbSize) \ + ( (This)->lpVtbl -> GetSize(This,pcbSize) ) + +#define ICorDebugInstanceFieldSymbol_GetOffset(This,pcbOffset) \ + ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugVariableSymbol_INTERFACE_DEFINED__ +#define __ICorDebugVariableSymbol_INTERFACE_DEFINED__ + +/* interface ICorDebugVariableSymbol */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugVariableSymbol; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("707E8932-1163-48D9-8A93-F5B1F480FBB7") + ICorDebugVariableSymbol : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcbValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetValue( + /* [in] */ ULONG32 offset, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 cbValue, + /* [out] */ ULONG32 *pcbValue, + /* [length_is][size_is][out] */ BYTE pValue[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetValue( + /* [in] */ ULONG32 offset, + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 cbValue, + /* [size_is][in] */ BYTE pValue[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + /* [out] */ ULONG32 *pSlotIndex) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVariableSymbolVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVariableSymbol * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVariableSymbol * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVariableSymbol * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugVariableSymbol * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugVariableSymbol * This, + /* [out] */ ULONG32 *pcbValue); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + ICorDebugVariableSymbol * This, + /* [in] */ ULONG32 offset, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 cbValue, + /* [out] */ ULONG32 *pcbValue, + /* [length_is][size_is][out] */ BYTE pValue[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetValue )( + ICorDebugVariableSymbol * This, + /* [in] */ ULONG32 offset, + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 cbValue, + /* [size_is][in] */ BYTE pValue[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + ICorDebugVariableSymbol * This, + /* [out] */ ULONG32 *pSlotIndex); + + END_INTERFACE + } ICorDebugVariableSymbolVtbl; + + interface ICorDebugVariableSymbol + { + CONST_VTBL struct ICorDebugVariableSymbolVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVariableSymbol_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVariableSymbol_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVariableSymbol_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVariableSymbol_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugVariableSymbol_GetSize(This,pcbValue) \ + ( (This)->lpVtbl -> GetSize(This,pcbValue) ) + +#define ICorDebugVariableSymbol_GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) \ + ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) + +#define ICorDebugVariableSymbol_SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) \ + ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) + +#define ICorDebugVariableSymbol_GetSlotIndex(This,pSlotIndex) \ + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVariableSymbol_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ +#define __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ + +/* interface ICorDebugMemoryBuffer */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugMemoryBuffer; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("677888B3-D160-4B8C-A73B-D79E6AAA1D13") + ICorDebugMemoryBuffer : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetStartAddress( + /* [out] */ LPCVOID *address) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcbBufferLength) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugMemoryBufferVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugMemoryBuffer * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugMemoryBuffer * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugMemoryBuffer * This); + + HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( + ICorDebugMemoryBuffer * This, + /* [out] */ LPCVOID *address); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugMemoryBuffer * This, + /* [out] */ ULONG32 *pcbBufferLength); + + END_INTERFACE + } ICorDebugMemoryBufferVtbl; + + interface ICorDebugMemoryBuffer + { + CONST_VTBL struct ICorDebugMemoryBufferVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugMemoryBuffer_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugMemoryBuffer_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugMemoryBuffer_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugMemoryBuffer_GetStartAddress(This,address) \ + ( (This)->lpVtbl -> GetStartAddress(This,address) ) + +#define ICorDebugMemoryBuffer_GetSize(This,pcbBufferLength) \ + ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ +#define __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ + +/* interface ICorDebugMergedAssemblyRecord */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FAA8637B-3BBE-4671-8E26-3B59875B922A") + ICorDebugMergedAssemblyRecord : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSimpleName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersion( + /* [out] */ USHORT *pMajor, + /* [out] */ USHORT *pMinor, + /* [out] */ USHORT *pBuild, + /* [out] */ USHORT *pRevision) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCulture( + /* [in] */ ULONG32 cchCulture, + /* [out] */ ULONG32 *pcchCulture, + /* [length_is][size_is][out] */ WCHAR szCulture[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPublicKey( + /* [in] */ ULONG32 cbPublicKey, + /* [out] */ ULONG32 *pcbPublicKey, + /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( + /* [in] */ ULONG32 cbPublicKeyToken, + /* [out] */ ULONG32 *pcbPublicKeyToken, + /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetIndex( + /* [out] */ ULONG32 *pIndex) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugMergedAssemblyRecordVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugMergedAssemblyRecord * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugMergedAssemblyRecord * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugMergedAssemblyRecord * This); + + HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( + ICorDebugMergedAssemblyRecord * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( + ICorDebugMergedAssemblyRecord * This, + /* [out] */ USHORT *pMajor, + /* [out] */ USHORT *pMinor, + /* [out] */ USHORT *pBuild, + /* [out] */ USHORT *pRevision); + + HRESULT ( STDMETHODCALLTYPE *GetCulture )( + ICorDebugMergedAssemblyRecord * This, + /* [in] */ ULONG32 cchCulture, + /* [out] */ ULONG32 *pcchCulture, + /* [length_is][size_is][out] */ WCHAR szCulture[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( + ICorDebugMergedAssemblyRecord * This, + /* [in] */ ULONG32 cbPublicKey, + /* [out] */ ULONG32 *pcbPublicKey, + /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( + ICorDebugMergedAssemblyRecord * This, + /* [in] */ ULONG32 cbPublicKeyToken, + /* [out] */ ULONG32 *pcbPublicKeyToken, + /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetIndex )( + ICorDebugMergedAssemblyRecord * This, + /* [out] */ ULONG32 *pIndex); + + END_INTERFACE + } ICorDebugMergedAssemblyRecordVtbl; + + interface ICorDebugMergedAssemblyRecord + { + CONST_VTBL struct ICorDebugMergedAssemblyRecordVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugMergedAssemblyRecord_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugMergedAssemblyRecord_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugMergedAssemblyRecord_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugMergedAssemblyRecord_GetSimpleName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) + +#define ICorDebugMergedAssemblyRecord_GetVersion(This,pMajor,pMinor,pBuild,pRevision) \ + ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) + +#define ICorDebugMergedAssemblyRecord_GetCulture(This,cchCulture,pcchCulture,szCulture) \ + ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) + +#define ICorDebugMergedAssemblyRecord_GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) \ + ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) + +#define ICorDebugMergedAssemblyRecord_GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) \ + ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) + +#define ICorDebugMergedAssemblyRecord_GetIndex(This,pIndex) \ + ( (This)->lpVtbl -> GetIndex(This,pIndex) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugSymbolProvider_INTERFACE_DEFINED__ +#define __ICorDebugSymbolProvider_INTERFACE_DEFINED__ + +/* interface ICorDebugSymbolProvider */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugSymbolProvider; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3948A999-FD8A-4C38-A708-8A71E9B04DBB") + ICorDebugSymbolProvider : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( + /* [in] */ ULONG32 nativeRVA, + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( + /* [in] */ ULONG32 nativeRVA, + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( + /* [in] */ ULONG32 cRequestedRecords, + /* [out] */ ULONG32 *pcFetchedRecords, + /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodProps( + /* [in] */ ULONG32 codeRva, + /* [out] */ mdToken *pMethodToken, + /* [out] */ ULONG32 *pcGenericParams, + /* [in] */ ULONG32 cbSignature, + /* [out] */ ULONG32 *pcbSignature, + /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeProps( + /* [in] */ ULONG32 vtableRva, + /* [in] */ ULONG32 cbSignature, + /* [out] */ ULONG32 *pcbSignature, + /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeRange( + /* [in] */ ULONG32 codeRva, + /* [out] */ ULONG32 *pCodeStartAddress, + ULONG32 *pCodeSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( + /* [in] */ CORDB_ADDRESS rva, + /* [in] */ ULONG32 length, + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize( + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [out] */ ULONG32 *pObjectSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugSymbolProviderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugSymbolProvider * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugSymbolProvider * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugSymbolProvider * This); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 nativeRVA, + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 nativeRVA, + /* [in] */ ULONG32 cRequestedSymbols, + /* [out] */ ULONG32 *pcFetchedSymbols, + /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 cRequestedRecords, + /* [out] */ ULONG32 *pcFetchedRecords, + /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 codeRva, + /* [out] */ mdToken *pMethodToken, + /* [out] */ ULONG32 *pcGenericParams, + /* [in] */ ULONG32 cbSignature, + /* [out] */ ULONG32 *pcbSignature, + /* [length_is][size_is][out] */ BYTE signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 vtableRva, + /* [in] */ ULONG32 cbSignature, + /* [out] */ ULONG32 *pcbSignature, + /* [length_is][size_is][out] */ BYTE signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 codeRva, + /* [out] */ ULONG32 *pCodeStartAddress, + ULONG32 *pCodeSize); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( + ICorDebugSymbolProvider * This, + /* [in] */ CORDB_ADDRESS rva, + /* [in] */ ULONG32 length, + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorDebugSymbolProvider * This, + /* [in] */ ULONG32 cbSignature, + /* [size_is][in] */ BYTE typeSig[ ], + /* [out] */ ULONG32 *pObjectSize); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( + ICorDebugSymbolProvider * This, + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); + + END_INTERFACE + } ICorDebugSymbolProviderVtbl; + + interface ICorDebugSymbolProvider + { + CONST_VTBL struct ICorDebugSymbolProviderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugSymbolProvider_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugSymbolProvider_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugSymbolProvider_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugSymbolProvider_GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ + ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + +#define ICorDebugSymbolProvider_GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ + ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + +#define ICorDebugSymbolProvider_GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ + ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + +#define ICorDebugSymbolProvider_GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ + ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) + +#define ICorDebugSymbolProvider_GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) \ + ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) + +#define ICorDebugSymbolProvider_GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) \ + ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) + +#define ICorDebugSymbolProvider_GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) \ + ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) + +#define ICorDebugSymbolProvider_GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) \ + ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) + +#define ICorDebugSymbolProvider_GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) \ + ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) + +#define ICorDebugSymbolProvider_GetObjectSize(This,cbSignature,typeSig,pObjectSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) + +#define ICorDebugSymbolProvider_GetAssemblyImageMetadata(This,ppMemoryBuffer) \ + ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugSymbolProvider_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ +#define __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ + +/* interface ICorDebugSymbolProvider2 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugSymbolProvider2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F9801807-4764-4330-9E67-4F685094165E") + ICorDebugSymbolProvider2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFrameProps( + /* [in] */ ULONG32 codeRva, + /* [out] */ ULONG32 *pCodeStartRva, + /* [out] */ ULONG32 *pParentFrameStartRva) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugSymbolProvider2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugSymbolProvider2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugSymbolProvider2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugSymbolProvider2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( + ICorDebugSymbolProvider2 * This, + /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( + ICorDebugSymbolProvider2 * This, + /* [in] */ ULONG32 codeRva, + /* [out] */ ULONG32 *pCodeStartRva, + /* [out] */ ULONG32 *pParentFrameStartRva); + + END_INTERFACE + } ICorDebugSymbolProvider2Vtbl; + + interface ICorDebugSymbolProvider2 + { + CONST_VTBL struct ICorDebugSymbolProvider2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugSymbolProvider2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugSymbolProvider2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugSymbolProvider2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugSymbolProvider2_GetGenericDictionaryInfo(This,ppMemoryBuffer) \ + ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) + +#define ICorDebugSymbolProvider2_GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) \ + ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ +#define __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ + +/* interface ICorDebugVirtualUnwinder */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugVirtualUnwinder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F69126B7-C787-4F6B-AE96-A569786FC670") + ICorDebugVirtualUnwinder : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 cbContextBuf, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVirtualUnwinderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVirtualUnwinder * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVirtualUnwinder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVirtualUnwinder * This); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + ICorDebugVirtualUnwinder * This, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 cbContextBuf, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugVirtualUnwinder * This); + + END_INTERFACE + } ICorDebugVirtualUnwinderVtbl; + + interface ICorDebugVirtualUnwinder + { + CONST_VTBL struct ICorDebugVirtualUnwinderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVirtualUnwinder_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVirtualUnwinder_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVirtualUnwinder_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVirtualUnwinder_GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) \ + ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) + +#define ICorDebugVirtualUnwinder_Next(This) \ + ( (This)->lpVtbl -> Next(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget2_INTERFACE_DEFINED__ +#define __ICorDebugDataTarget2_INTERFACE_DEFINED__ + +/* interface ICorDebugDataTarget2 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugDataTarget2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2eb364da-605b-4e8d-b333-3394c4828d41") + ICorDebugDataTarget2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( + /* [in] */ CORDB_ADDRESS addr, + /* [out] */ CORDB_ADDRESS *pImageBase, + /* [out] */ ULONG32 *pSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetImageLocation( + /* [in] */ CORDB_ADDRESS baseAddress, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( + /* [in] */ CORDB_ADDRESS imageBaseAddress, + /* [out] */ ICorDebugSymbolProvider **ppSymProvider) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( + /* [in] */ ULONG32 cThreadIds, + /* [out] */ ULONG32 *pcThreadIds, + /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( + /* [in] */ DWORD nativeThreadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE initialContext[ ], + /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDataTarget2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDataTarget2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDataTarget2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDataTarget2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( + ICorDebugDataTarget2 * This, + /* [in] */ CORDB_ADDRESS addr, + /* [out] */ CORDB_ADDRESS *pImageBase, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( + ICorDebugDataTarget2 * This, + /* [in] */ CORDB_ADDRESS baseAddress, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( + ICorDebugDataTarget2 * This, + /* [in] */ CORDB_ADDRESS imageBaseAddress, + /* [out] */ ICorDebugSymbolProvider **ppSymProvider); + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( + ICorDebugDataTarget2 * This, + /* [in] */ ULONG32 cThreadIds, + /* [out] */ ULONG32 *pcThreadIds, + /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( + ICorDebugDataTarget2 * This, + /* [in] */ DWORD nativeThreadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 cbContext, + /* [size_is][in] */ BYTE initialContext[ ], + /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder); + + END_INTERFACE + } ICorDebugDataTarget2Vtbl; + + interface ICorDebugDataTarget2 + { + CONST_VTBL struct ICorDebugDataTarget2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDataTarget2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDataTarget2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDataTarget2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDataTarget2_GetImageFromPointer(This,addr,pImageBase,pSize) \ + ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) + +#define ICorDebugDataTarget2_GetImageLocation(This,baseAddress,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) + +#define ICorDebugDataTarget2_GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) \ + ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) + +#define ICorDebugDataTarget2_EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) \ + ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) + +#define ICorDebugDataTarget2_CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) \ + ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDataTarget2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugLoadedModule_INTERFACE_DEFINED__ +#define __ICorDebugLoadedModule_INTERFACE_DEFINED__ + +/* interface ICorDebugLoadedModule */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugLoadedModule; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("817F343A-6630-4578-96C5-D11BC0EC5EE2") + ICorDebugLoadedModule : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + /* [out] */ CORDB_ADDRESS *pAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcBytes) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugLoadedModuleVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugLoadedModule * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugLoadedModule * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugLoadedModule * This); + + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + ICorDebugLoadedModule * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugLoadedModule * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugLoadedModule * This, + /* [out] */ ULONG32 *pcBytes); + + END_INTERFACE + } ICorDebugLoadedModuleVtbl; + + interface ICorDebugLoadedModule + { + CONST_VTBL struct ICorDebugLoadedModuleVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugLoadedModule_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugLoadedModule_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugLoadedModule_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugLoadedModule_GetBaseAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + +#define ICorDebugLoadedModule_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugLoadedModule_GetSize(This,pcBytes) \ + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugLoadedModule_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget3_INTERFACE_DEFINED__ +#define __ICorDebugDataTarget3_INTERFACE_DEFINED__ + +/* interface ICorDebugDataTarget3 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugDataTarget3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D05E60C3-848C-4E7D-894E-623320FF6AFA") + ICorDebugDataTarget3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( + /* [in] */ ULONG32 cRequestedModules, + /* [out] */ ULONG32 *pcFetchedModules, + /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDataTarget3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDataTarget3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDataTarget3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDataTarget3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( + ICorDebugDataTarget3 * This, + /* [in] */ ULONG32 cRequestedModules, + /* [out] */ ULONG32 *pcFetchedModules, + /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]); + + END_INTERFACE + } ICorDebugDataTarget3Vtbl; + + interface ICorDebugDataTarget3 + { + CONST_VTBL struct ICorDebugDataTarget3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDataTarget3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDataTarget3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDataTarget3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDataTarget3_GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) \ + ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDataTarget3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugDataTarget4_INTERFACE_DEFINED__ +#define __ICorDebugDataTarget4_INTERFACE_DEFINED__ + +/* interface ICorDebugDataTarget4 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugDataTarget4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E799DC06-E099-4713-BDD9-906D3CC02CF2") + ICorDebugDataTarget4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( + /* [in] */ DWORD threadId, + /* [in] */ ULONG32 contextSize, + /* [size_is][out][in] */ BYTE *context) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDataTarget4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDataTarget4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDataTarget4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDataTarget4 * This); + + HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( + ICorDebugDataTarget4 * This, + /* [in] */ DWORD threadId, + /* [in] */ ULONG32 contextSize, + /* [size_is][out][in] */ BYTE *context); + + END_INTERFACE + } ICorDebugDataTarget4Vtbl; + + interface ICorDebugDataTarget4 + { + CONST_VTBL struct ICorDebugDataTarget4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDataTarget4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDataTarget4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDataTarget4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDataTarget4_VirtualUnwind(This,threadId,contextSize,context) \ + ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDataTarget4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ +#define __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ + +/* interface ICorDebugMutableDataTarget */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_ICorDebugMutableDataTarget; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A1B8A756-3CB6-4CCB-979F-3DF999673A59") + ICorDebugMutableDataTarget : public ICorDebugDataTarget + { + public: + virtual HRESULT STDMETHODCALLTYPE WriteVirtual( + /* [in] */ CORDB_ADDRESS address, + /* [size_is][in] */ const BYTE *pBuffer, + /* [in] */ ULONG32 bytesRequested) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + /* [in] */ DWORD dwThreadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ const BYTE *pContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( + /* [in] */ DWORD dwThreadId, + /* [in] */ CORDB_CONTINUE_STATUS continueStatus) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugMutableDataTargetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugMutableDataTarget * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugMutableDataTarget * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugMutableDataTarget * This); + + HRESULT ( STDMETHODCALLTYPE *GetPlatform )( + ICorDebugMutableDataTarget * This, + /* [out] */ CorDebugPlatform *pTargetPlatform); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + ICorDebugMutableDataTarget * This, + /* [in] */ CORDB_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *pBuffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *pBytesRead); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorDebugMutableDataTarget * This, + /* [in] */ DWORD dwThreadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *pContext); + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + ICorDebugMutableDataTarget * This, + /* [in] */ CORDB_ADDRESS address, + /* [size_is][in] */ const BYTE *pBuffer, + /* [in] */ ULONG32 bytesRequested); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICorDebugMutableDataTarget * This, + /* [in] */ DWORD dwThreadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ const BYTE *pContext); + + HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( + ICorDebugMutableDataTarget * This, + /* [in] */ DWORD dwThreadId, + /* [in] */ CORDB_CONTINUE_STATUS continueStatus); + + END_INTERFACE + } ICorDebugMutableDataTargetVtbl; + + interface ICorDebugMutableDataTarget + { + CONST_VTBL struct ICorDebugMutableDataTargetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugMutableDataTarget_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugMutableDataTarget_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugMutableDataTarget_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugMutableDataTarget_GetPlatform(This,pTargetPlatform) \ + ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) + +#define ICorDebugMutableDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) + +#define ICorDebugMutableDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ + ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) + + +#define ICorDebugMutableDataTarget_WriteVirtual(This,address,pBuffer,bytesRequested) \ + ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) + +#define ICorDebugMutableDataTarget_SetThreadContext(This,dwThreadID,contextSize,pContext) \ + ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) + +#define ICorDebugMutableDataTarget_ContinueStatusChanged(This,dwThreadId,continueStatus) \ + ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ +#define __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ + +/* interface ICorDebugMetaDataLocator */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugMetaDataLocator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7cef8ba9-2ef7-42bf-973f-4171474f87d9") + ICorDebugMetaDataLocator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMetaData( + /* [in] */ LPCWSTR wszImagePath, + /* [in] */ DWORD dwImageTimeStamp, + /* [in] */ DWORD dwImageSize, + /* [in] */ ULONG32 cchPathBuffer, + /* [annotation][out] */ + _Out_ ULONG32 *pcchPathBuffer, + /* [annotation][length_is][size_is][out] */ + _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugMetaDataLocatorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugMetaDataLocator * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugMetaDataLocator * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugMetaDataLocator * This); + + HRESULT ( STDMETHODCALLTYPE *GetMetaData )( + ICorDebugMetaDataLocator * This, + /* [in] */ LPCWSTR wszImagePath, + /* [in] */ DWORD dwImageTimeStamp, + /* [in] */ DWORD dwImageSize, + /* [in] */ ULONG32 cchPathBuffer, + /* [annotation][out] */ + _Out_ ULONG32 *pcchPathBuffer, + /* [annotation][length_is][size_is][out] */ + _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]); + + END_INTERFACE + } ICorDebugMetaDataLocatorVtbl; + + interface ICorDebugMetaDataLocator + { + CONST_VTBL struct ICorDebugMetaDataLocatorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugMetaDataLocator_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugMetaDataLocator_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugMetaDataLocator_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugMetaDataLocator_GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) \ + ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0015 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec; + +#ifndef __ICorDebugManagedCallback_INTERFACE_DEFINED__ +#define __ICorDebugManagedCallback_INTERFACE_DEFINED__ + +/* interface ICorDebugManagedCallback */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugStepReason + { + STEP_NORMAL = 0, + STEP_RETURN = ( STEP_NORMAL + 1 ) , + STEP_CALL = ( STEP_RETURN + 1 ) , + STEP_EXCEPTION_FILTER = ( STEP_CALL + 1 ) , + STEP_EXCEPTION_HANDLER = ( STEP_EXCEPTION_FILTER + 1 ) , + STEP_INTERCEPT = ( STEP_EXCEPTION_HANDLER + 1 ) , + STEP_EXIT = ( STEP_INTERCEPT + 1 ) + } CorDebugStepReason; + +typedef +enum LoggingLevelEnum + { + LTraceLevel0 = 0, + LTraceLevel1 = ( LTraceLevel0 + 1 ) , + LTraceLevel2 = ( LTraceLevel1 + 1 ) , + LTraceLevel3 = ( LTraceLevel2 + 1 ) , + LTraceLevel4 = ( LTraceLevel3 + 1 ) , + LStatusLevel0 = 20, + LStatusLevel1 = ( LStatusLevel0 + 1 ) , + LStatusLevel2 = ( LStatusLevel1 + 1 ) , + LStatusLevel3 = ( LStatusLevel2 + 1 ) , + LStatusLevel4 = ( LStatusLevel3 + 1 ) , + LWarningLevel = 40, + LErrorLevel = 50, + LPanicLevel = 100 + } LoggingLevelEnum; + +typedef +enum LogSwitchCallReason + { + SWITCH_CREATE = 0, + SWITCH_MODIFY = ( SWITCH_CREATE + 1 ) , + SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) + } LogSwitchCallReason; + + +EXTERN_C const IID IID_ICorDebugManagedCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3d6f5f60-7538-11d3-8d5b-00104b35e7ef") + ICorDebugManagedCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Breakpoint( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugBreakpoint *pBreakpoint) = 0; + + virtual HRESULT STDMETHODCALLTYPE StepComplete( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugStepper *pStepper, + /* [in] */ CorDebugStepReason reason) = 0; + + virtual HRESULT STDMETHODCALLTYPE Break( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread) = 0; + + virtual HRESULT STDMETHODCALLTYPE Exception( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ BOOL unhandled) = 0; + + virtual HRESULT STDMETHODCALLTYPE EvalComplete( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugEval *pEval) = 0; + + virtual HRESULT STDMETHODCALLTYPE EvalException( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugEval *pEval) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( + /* [in] */ ICorDebugProcess *pProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitProcess( + /* [in] */ ICorDebugProcess *pProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateThread( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitThread( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadModule( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadModule( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadClass( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugClass *c) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadClass( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugClass *c) = 0; + + virtual HRESULT STDMETHODCALLTYPE DebuggerError( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ HRESULT errorHR, + /* [in] */ DWORD errorCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE LogMessage( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ LONG lLevel, + /* [in] */ WCHAR *pLogSwitchName, + /* [in] */ WCHAR *pMessage) = 0; + + virtual HRESULT STDMETHODCALLTYPE LogSwitch( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ LONG lLevel, + /* [in] */ ULONG ulReason, + /* [in] */ WCHAR *pLogSwitchName, + /* [in] */ WCHAR *pParentName) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadAssembly( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugAssembly *pAssembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugAssembly *pAssembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE ControlCTrap( + /* [in] */ ICorDebugProcess *pProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE NameChange( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule, + /* [in] */ IStream *pSymbolStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ BOOL fAccurate) = 0; + + virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugBreakpoint *pBreakpoint, + /* [in] */ DWORD dwError) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugManagedCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugManagedCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugManagedCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugManagedCallback * This); + + HRESULT ( STDMETHODCALLTYPE *Breakpoint )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugBreakpoint *pBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *StepComplete )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugStepper *pStepper, + /* [in] */ CorDebugStepReason reason); + + HRESULT ( STDMETHODCALLTYPE *Break )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread); + + HRESULT ( STDMETHODCALLTYPE *Exception )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ BOOL unhandled); + + HRESULT ( STDMETHODCALLTYPE *EvalComplete )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugEval *pEval); + + HRESULT ( STDMETHODCALLTYPE *EvalException )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugEval *pEval); + + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess); + + HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess); + + HRESULT ( STDMETHODCALLTYPE *CreateThread )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread); + + HRESULT ( STDMETHODCALLTYPE *ExitThread )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *thread); + + HRESULT ( STDMETHODCALLTYPE *LoadModule )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule); + + HRESULT ( STDMETHODCALLTYPE *UnloadModule )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule); + + HRESULT ( STDMETHODCALLTYPE *LoadClass )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugClass *c); + + HRESULT ( STDMETHODCALLTYPE *UnloadClass )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugClass *c); + + HRESULT ( STDMETHODCALLTYPE *DebuggerError )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ HRESULT errorHR, + /* [in] */ DWORD errorCode); + + HRESULT ( STDMETHODCALLTYPE *LogMessage )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ LONG lLevel, + /* [in] */ WCHAR *pLogSwitchName, + /* [in] */ WCHAR *pMessage); + + HRESULT ( STDMETHODCALLTYPE *LogSwitch )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ LONG lLevel, + /* [in] */ ULONG ulReason, + /* [in] */ WCHAR *pLogSwitchName, + /* [in] */ WCHAR *pParentName); + + HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugAppDomain *pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugAppDomain *pAppDomain); + + HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugAssembly *pAssembly); + + HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugAssembly *pAssembly); + + HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugProcess *pProcess); + + HRESULT ( STDMETHODCALLTYPE *NameChange )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread); + + HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugModule *pModule, + /* [in] */ IStream *pSymbolStream); + + HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ BOOL fAccurate); + + HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( + ICorDebugManagedCallback * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugBreakpoint *pBreakpoint, + /* [in] */ DWORD dwError); + + END_INTERFACE + } ICorDebugManagedCallbackVtbl; + + interface ICorDebugManagedCallback + { + CONST_VTBL struct ICorDebugManagedCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugManagedCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugManagedCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugManagedCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugManagedCallback_Breakpoint(This,pAppDomain,pThread,pBreakpoint) \ + ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) + +#define ICorDebugManagedCallback_StepComplete(This,pAppDomain,pThread,pStepper,reason) \ + ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) + +#define ICorDebugManagedCallback_Break(This,pAppDomain,thread) \ + ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) + +#define ICorDebugManagedCallback_Exception(This,pAppDomain,pThread,unhandled) \ + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) + +#define ICorDebugManagedCallback_EvalComplete(This,pAppDomain,pThread,pEval) \ + ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) + +#define ICorDebugManagedCallback_EvalException(This,pAppDomain,pThread,pEval) \ + ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) + +#define ICorDebugManagedCallback_CreateProcess(This,pProcess) \ + ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) + +#define ICorDebugManagedCallback_ExitProcess(This,pProcess) \ + ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) + +#define ICorDebugManagedCallback_CreateThread(This,pAppDomain,thread) \ + ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) + +#define ICorDebugManagedCallback_ExitThread(This,pAppDomain,thread) \ + ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) + +#define ICorDebugManagedCallback_LoadModule(This,pAppDomain,pModule) \ + ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) + +#define ICorDebugManagedCallback_UnloadModule(This,pAppDomain,pModule) \ + ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) + +#define ICorDebugManagedCallback_LoadClass(This,pAppDomain,c) \ + ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) + +#define ICorDebugManagedCallback_UnloadClass(This,pAppDomain,c) \ + ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) + +#define ICorDebugManagedCallback_DebuggerError(This,pProcess,errorHR,errorCode) \ + ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) + +#define ICorDebugManagedCallback_LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) \ + ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) + +#define ICorDebugManagedCallback_LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) \ + ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) + +#define ICorDebugManagedCallback_CreateAppDomain(This,pProcess,pAppDomain) \ + ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) + +#define ICorDebugManagedCallback_ExitAppDomain(This,pProcess,pAppDomain) \ + ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) + +#define ICorDebugManagedCallback_LoadAssembly(This,pAppDomain,pAssembly) \ + ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) + +#define ICorDebugManagedCallback_UnloadAssembly(This,pAppDomain,pAssembly) \ + ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) + +#define ICorDebugManagedCallback_ControlCTrap(This,pProcess) \ + ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) + +#define ICorDebugManagedCallback_NameChange(This,pAppDomain,pThread) \ + ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) + +#define ICorDebugManagedCallback_UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) \ + ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) + +#define ICorDebugManagedCallback_EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) \ + ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) + +#define ICorDebugManagedCallback_BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) \ + ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugManagedCallback_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0016 */ +/* [local] */ + +#pragma warning(pop) +#pragma warning(push) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec; + +#ifndef __ICorDebugManagedCallback3_INTERFACE_DEFINED__ +#define __ICorDebugManagedCallback3_INTERFACE_DEFINED__ + +/* interface ICorDebugManagedCallback3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugManagedCallback3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("264EA0FC-2591-49AA-868E-835E6515323F") + ICorDebugManagedCallback3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CustomNotification( + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugManagedCallback3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugManagedCallback3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugManagedCallback3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugManagedCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *CustomNotification )( + ICorDebugManagedCallback3 * This, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugAppDomain *pAppDomain); + + END_INTERFACE + } ICorDebugManagedCallback3Vtbl; + + interface ICorDebugManagedCallback3 + { + CONST_VTBL struct ICorDebugManagedCallback3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugManagedCallback3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugManagedCallback3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugManagedCallback3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugManagedCallback3_CustomNotification(This,pThread,pAppDomain) \ + ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugManagedCallback3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugManagedCallback4_INTERFACE_DEFINED__ +#define __ICorDebugManagedCallback4_INTERFACE_DEFINED__ + +/* interface ICorDebugManagedCallback4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugManagedCallback4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("322911AE-16A5-49BA-84A3-ED69678138A3") + ICorDebugManagedCallback4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( + /* [in] */ ICorDebugProcess *pProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( + /* [in] */ ICorDebugProcess *pProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ BYTE *pContext, + /* [in] */ ULONG32 contextSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugManagedCallback4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugManagedCallback4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugManagedCallback4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugManagedCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( + ICorDebugManagedCallback4 * This, + /* [in] */ ICorDebugProcess *pProcess); + + HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( + ICorDebugManagedCallback4 * This, + /* [in] */ ICorDebugProcess *pProcess); + + HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( + ICorDebugManagedCallback4 * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ BYTE *pContext, + /* [in] */ ULONG32 contextSize); + + END_INTERFACE + } ICorDebugManagedCallback4Vtbl; + + interface ICorDebugManagedCallback4 + { + CONST_VTBL struct ICorDebugManagedCallback4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugManagedCallback4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugManagedCallback4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugManagedCallback4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugManagedCallback4_BeforeGarbageCollection(This,pProcess) \ + ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) + +#define ICorDebugManagedCallback4_AfterGarbageCollection(This,pProcess) \ + ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) + +#define ICorDebugManagedCallback4_DataBreakpoint(This,pProcess,pThread,pContext,contextSize) \ + ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugManagedCallback4_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0018 */ +/* [local] */ + +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec; + +#ifndef __ICorDebugManagedCallback2_INTERFACE_DEFINED__ +#define __ICorDebugManagedCallback2_INTERFACE_DEFINED__ + +/* interface ICorDebugManagedCallback2 */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugExceptionCallbackType + { + DEBUG_EXCEPTION_FIRST_CHANCE = 1, + DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2, + DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3, + DEBUG_EXCEPTION_UNHANDLED = 4 + } CorDebugExceptionCallbackType; + +typedef +enum CorDebugExceptionFlags + { + DEBUG_EXCEPTION_NONE = 0, + DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x1 + } CorDebugExceptionFlags; + +typedef +enum CorDebugExceptionUnwindCallbackType + { + DEBUG_EXCEPTION_UNWIND_BEGIN = 1, + DEBUG_EXCEPTION_INTERCEPTED = 2 + } CorDebugExceptionUnwindCallbackType; + + +EXTERN_C const IID IID_ICorDebugManagedCallback2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("250E5EEA-DB5C-4C76-B6F3-8C46F12E3203") + ICorDebugManagedCallback2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pOldFunction, + /* [in] */ ICorDebugFunction *pNewFunction, + /* [in] */ ULONG32 oldILOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateConnection( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId, + /* [in] */ WCHAR *pConnName) = 0; + + virtual HRESULT STDMETHODCALLTYPE ChangeConnection( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyConnection( + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE Exception( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFrame *pFrame, + /* [in] */ ULONG32 nOffset, + /* [in] */ CorDebugExceptionCallbackType dwEventType, + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE MDANotification( + /* [in] */ ICorDebugController *pController, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugMDA *pMDA) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugManagedCallback2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugManagedCallback2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugManagedCallback2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugManagedCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pOldFunction, + /* [in] */ ICorDebugFunction *pNewFunction, + /* [in] */ ULONG32 oldILOffset); + + HRESULT ( STDMETHODCALLTYPE *CreateConnection )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId, + /* [in] */ WCHAR *pConnName); + + HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId); + + HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugProcess *pProcess, + /* [in] */ CONNID dwConnectionId); + + HRESULT ( STDMETHODCALLTYPE *Exception )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFrame *pFrame, + /* [in] */ ULONG32 nOffset, + /* [in] */ CorDebugExceptionCallbackType dwEventType, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugAppDomain *pAppDomain, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugFunction *pFunction); + + HRESULT ( STDMETHODCALLTYPE *MDANotification )( + ICorDebugManagedCallback2 * This, + /* [in] */ ICorDebugController *pController, + /* [in] */ ICorDebugThread *pThread, + /* [in] */ ICorDebugMDA *pMDA); + + END_INTERFACE + } ICorDebugManagedCallback2Vtbl; + + interface ICorDebugManagedCallback2 + { + CONST_VTBL struct ICorDebugManagedCallback2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugManagedCallback2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugManagedCallback2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugManagedCallback2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugManagedCallback2_FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) \ + ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) + +#define ICorDebugManagedCallback2_CreateConnection(This,pProcess,dwConnectionId,pConnName) \ + ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) + +#define ICorDebugManagedCallback2_ChangeConnection(This,pProcess,dwConnectionId) \ + ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) + +#define ICorDebugManagedCallback2_DestroyConnection(This,pProcess,dwConnectionId) \ + ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) + +#define ICorDebugManagedCallback2_Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) \ + ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) + +#define ICorDebugManagedCallback2_ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) \ + ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) + +#define ICorDebugManagedCallback2_FunctionRemapComplete(This,pAppDomain,pThread,pFunction) \ + ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) + +#define ICorDebugManagedCallback2_MDANotification(This,pController,pThread,pMDA) \ + ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugManagedCallback2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0019 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec; + +#ifndef __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ +#define __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ + +/* interface ICorDebugUnmanagedCallback */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugUnmanagedCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5263E909-8CB5-11d3-BD2F-0000F80849BD") + ICorDebugUnmanagedCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE DebugEvent( + /* [in] */ LPDEBUG_EVENT pDebugEvent, + /* [in] */ BOOL fOutOfBand) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugUnmanagedCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugUnmanagedCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugUnmanagedCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugUnmanagedCallback * This); + + HRESULT ( STDMETHODCALLTYPE *DebugEvent )( + ICorDebugUnmanagedCallback * This, + /* [in] */ LPDEBUG_EVENT pDebugEvent, + /* [in] */ BOOL fOutOfBand); + + END_INTERFACE + } ICorDebugUnmanagedCallbackVtbl; + + interface ICorDebugUnmanagedCallback + { + CONST_VTBL struct ICorDebugUnmanagedCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugUnmanagedCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugUnmanagedCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugUnmanagedCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugUnmanagedCallback_DebugEvent(This,pDebugEvent,fOutOfBand) \ + ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0020 */ +/* [local] */ + +typedef +enum CorDebugCreateProcessFlags + { + DEBUG_NO_SPECIAL_OPTIONS = 0 + } CorDebugCreateProcessFlags; + +typedef +enum CorDebugHandleType + { + HANDLE_STRONG = 1, + HANDLE_WEAK_TRACK_RESURRECTION = 2 + } CorDebugHandleType; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_s_ifspec; + +#ifndef __ICorDebug_INTERFACE_DEFINED__ +#define __ICorDebug_INTERFACE_DEFINED__ + +/* interface ICorDebug */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebug; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3d6f5f61-7538-11d3-8d5b-00104b35e7ef") + ICorDebug : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Initialize( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Terminate( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( + /* [in] */ ICorDebugManagedCallback *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( + /* [in] */ ICorDebugUnmanagedCallback *pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateProcess( + /* [in] */ LPCWSTR lpApplicationName, + /* [in] */ LPWSTR lpCommandLine, + /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, + /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, + /* [in] */ BOOL bInheritHandles, + /* [in] */ DWORD dwCreationFlags, + /* [in] */ PVOID lpEnvironment, + /* [in] */ LPCWSTR lpCurrentDirectory, + /* [in] */ LPSTARTUPINFOW lpStartupInfo, + /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, + /* [in] */ CorDebugCreateProcessFlags debuggingFlags, + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( + /* [in] */ DWORD id, + /* [in] */ BOOL win32Attach, + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( + /* [out] */ ICorDebugProcessEnum **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [in] */ DWORD dwProcessId, + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( + /* [in] */ DWORD dwProcessId, + /* [in] */ BOOL win32DebuggingEnabled) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebug * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebug * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebug * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorDebug * This); + + HRESULT ( STDMETHODCALLTYPE *Terminate )( + ICorDebug * This); + + HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( + ICorDebug * This, + /* [in] */ ICorDebugManagedCallback *pCallback); + + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( + ICorDebug * This, + /* [in] */ ICorDebugUnmanagedCallback *pCallback); + + HRESULT ( STDMETHODCALLTYPE *CreateProcess )( + ICorDebug * This, + /* [in] */ LPCWSTR lpApplicationName, + /* [in] */ LPWSTR lpCommandLine, + /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, + /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, + /* [in] */ BOOL bInheritHandles, + /* [in] */ DWORD dwCreationFlags, + /* [in] */ PVOID lpEnvironment, + /* [in] */ LPCWSTR lpCurrentDirectory, + /* [in] */ LPSTARTUPINFOW lpStartupInfo, + /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, + /* [in] */ CorDebugCreateProcessFlags debuggingFlags, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( + ICorDebug * This, + /* [in] */ DWORD id, + /* [in] */ BOOL win32Attach, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( + ICorDebug * This, + /* [out] */ ICorDebugProcessEnum **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorDebug * This, + /* [in] */ DWORD dwProcessId, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( + ICorDebug * This, + /* [in] */ DWORD dwProcessId, + /* [in] */ BOOL win32DebuggingEnabled); + + END_INTERFACE + } ICorDebugVtbl; + + interface ICorDebug + { + CONST_VTBL struct ICorDebugVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebug_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebug_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebug_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebug_Initialize(This) \ + ( (This)->lpVtbl -> Initialize(This) ) + +#define ICorDebug_Terminate(This) \ + ( (This)->lpVtbl -> Terminate(This) ) + +#define ICorDebug_SetManagedHandler(This,pCallback) \ + ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) + +#define ICorDebug_SetUnmanagedHandler(This,pCallback) \ + ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) + +#define ICorDebug_CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ + ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + +#define ICorDebug_DebugActiveProcess(This,id,win32Attach,ppProcess) \ + ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) + +#define ICorDebug_EnumerateProcesses(This,ppProcess) \ + ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) + +#define ICorDebug_GetProcess(This,dwProcessId,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) + +#define ICorDebug_CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) \ + ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebug_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0021 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_s_ifspec; + +#ifndef __ICorDebugRemoteTarget_INTERFACE_DEFINED__ +#define __ICorDebugRemoteTarget_INTERFACE_DEFINED__ + +/* interface ICorDebugRemoteTarget */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugRemoteTarget; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C3ED8383-5A49-4cf5-B4B7-01864D9E582D") + ICorDebugRemoteTarget : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetHostName( + /* [in] */ ULONG32 cchHostName, + /* [annotation][out] */ + _Out_ ULONG32 *pcchHostName, + /* [annotation][length_is][size_is][out] */ + _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugRemoteTargetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugRemoteTarget * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugRemoteTarget * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugRemoteTarget * This); + + HRESULT ( STDMETHODCALLTYPE *GetHostName )( + ICorDebugRemoteTarget * This, + /* [in] */ ULONG32 cchHostName, + /* [annotation][out] */ + _Out_ ULONG32 *pcchHostName, + /* [annotation][length_is][size_is][out] */ + _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]); + + END_INTERFACE + } ICorDebugRemoteTargetVtbl; + + interface ICorDebugRemoteTarget + { + CONST_VTBL struct ICorDebugRemoteTargetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugRemoteTarget_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugRemoteTarget_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugRemoteTarget_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugRemoteTarget_GetHostName(This,cchHostName,pcchHostName,szHostName) \ + ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugRemoteTarget_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugRemote_INTERFACE_DEFINED__ +#define __ICorDebugRemote_INTERFACE_DEFINED__ + +/* interface ICorDebugRemote */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugRemote; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64") + ICorDebugRemote : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( + /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, + /* [in] */ LPCWSTR lpApplicationName, + /* [annotation][in] */ + _In_ LPWSTR lpCommandLine, + /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, + /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, + /* [in] */ BOOL bInheritHandles, + /* [in] */ DWORD dwCreationFlags, + /* [in] */ PVOID lpEnvironment, + /* [in] */ LPCWSTR lpCurrentDirectory, + /* [in] */ LPSTARTUPINFOW lpStartupInfo, + /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, + /* [in] */ CorDebugCreateProcessFlags debuggingFlags, + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( + /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, + /* [in] */ DWORD dwProcessId, + /* [in] */ BOOL fWin32Attach, + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugRemoteVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugRemote * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugRemote * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugRemote * This); + + HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( + ICorDebugRemote * This, + /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, + /* [in] */ LPCWSTR lpApplicationName, + /* [annotation][in] */ + _In_ LPWSTR lpCommandLine, + /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, + /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, + /* [in] */ BOOL bInheritHandles, + /* [in] */ DWORD dwCreationFlags, + /* [in] */ PVOID lpEnvironment, + /* [in] */ LPCWSTR lpCurrentDirectory, + /* [in] */ LPSTARTUPINFOW lpStartupInfo, + /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, + /* [in] */ CorDebugCreateProcessFlags debuggingFlags, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( + ICorDebugRemote * This, + /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, + /* [in] */ DWORD dwProcessId, + /* [in] */ BOOL fWin32Attach, + /* [out] */ ICorDebugProcess **ppProcess); + + END_INTERFACE + } ICorDebugRemoteVtbl; + + interface ICorDebugRemote + { + CONST_VTBL struct ICorDebugRemoteVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugRemote_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugRemote_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugRemote_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugRemote_CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ + ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) + +#define ICorDebugRemote_DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) \ + ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugRemote_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0023 */ +/* [local] */ + +typedef struct _COR_VERSION + { + DWORD dwMajor; + DWORD dwMinor; + DWORD dwBuild; + DWORD dwSubBuild; + } COR_VERSION; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec; + +#ifndef __ICorDebug2_INTERFACE_DEFINED__ +#define __ICorDebug2_INTERFACE_DEFINED__ + +/* interface ICorDebug2 */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugInterfaceVersion + { + CorDebugInvalidVersion = 0, + CorDebugVersion_1_0 = ( CorDebugInvalidVersion + 1 ) , + ver_ICorDebugManagedCallback = CorDebugVersion_1_0, + ver_ICorDebugUnmanagedCallback = CorDebugVersion_1_0, + ver_ICorDebug = CorDebugVersion_1_0, + ver_ICorDebugController = CorDebugVersion_1_0, + ver_ICorDebugAppDomain = CorDebugVersion_1_0, + ver_ICorDebugAssembly = CorDebugVersion_1_0, + ver_ICorDebugProcess = CorDebugVersion_1_0, + ver_ICorDebugBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugFunctionBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugModuleBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugValueBreakpoint = CorDebugVersion_1_0, + ver_ICorDebugStepper = CorDebugVersion_1_0, + ver_ICorDebugRegisterSet = CorDebugVersion_1_0, + ver_ICorDebugThread = CorDebugVersion_1_0, + ver_ICorDebugChain = CorDebugVersion_1_0, + ver_ICorDebugFrame = CorDebugVersion_1_0, + ver_ICorDebugILFrame = CorDebugVersion_1_0, + ver_ICorDebugNativeFrame = CorDebugVersion_1_0, + ver_ICorDebugModule = CorDebugVersion_1_0, + ver_ICorDebugFunction = CorDebugVersion_1_0, + ver_ICorDebugCode = CorDebugVersion_1_0, + ver_ICorDebugClass = CorDebugVersion_1_0, + ver_ICorDebugEval = CorDebugVersion_1_0, + ver_ICorDebugValue = CorDebugVersion_1_0, + ver_ICorDebugGenericValue = CorDebugVersion_1_0, + ver_ICorDebugReferenceValue = CorDebugVersion_1_0, + ver_ICorDebugHeapValue = CorDebugVersion_1_0, + ver_ICorDebugObjectValue = CorDebugVersion_1_0, + ver_ICorDebugBoxValue = CorDebugVersion_1_0, + ver_ICorDebugStringValue = CorDebugVersion_1_0, + ver_ICorDebugArrayValue = CorDebugVersion_1_0, + ver_ICorDebugContext = CorDebugVersion_1_0, + ver_ICorDebugEnum = CorDebugVersion_1_0, + ver_ICorDebugObjectEnum = CorDebugVersion_1_0, + ver_ICorDebugBreakpointEnum = CorDebugVersion_1_0, + ver_ICorDebugStepperEnum = CorDebugVersion_1_0, + ver_ICorDebugProcessEnum = CorDebugVersion_1_0, + ver_ICorDebugThreadEnum = CorDebugVersion_1_0, + ver_ICorDebugFrameEnum = CorDebugVersion_1_0, + ver_ICorDebugChainEnum = CorDebugVersion_1_0, + ver_ICorDebugModuleEnum = CorDebugVersion_1_0, + ver_ICorDebugValueEnum = CorDebugVersion_1_0, + ver_ICorDebugCodeEnum = CorDebugVersion_1_0, + ver_ICorDebugTypeEnum = CorDebugVersion_1_0, + ver_ICorDebugErrorInfoEnum = CorDebugVersion_1_0, + ver_ICorDebugAppDomainEnum = CorDebugVersion_1_0, + ver_ICorDebugAssemblyEnum = CorDebugVersion_1_0, + ver_ICorDebugEditAndContinueErrorInfo = CorDebugVersion_1_0, + ver_ICorDebugEditAndContinueSnapshot = CorDebugVersion_1_0, + CorDebugVersion_1_1 = ( CorDebugVersion_1_0 + 1 ) , + CorDebugVersion_2_0 = ( CorDebugVersion_1_1 + 1 ) , + ver_ICorDebugManagedCallback2 = CorDebugVersion_2_0, + ver_ICorDebugAppDomain2 = CorDebugVersion_2_0, + ver_ICorDebugAssembly2 = CorDebugVersion_2_0, + ver_ICorDebugProcess2 = CorDebugVersion_2_0, + ver_ICorDebugStepper2 = CorDebugVersion_2_0, + ver_ICorDebugRegisterSet2 = CorDebugVersion_2_0, + ver_ICorDebugThread2 = CorDebugVersion_2_0, + ver_ICorDebugILFrame2 = CorDebugVersion_2_0, + ver_ICorDebugInternalFrame = CorDebugVersion_2_0, + ver_ICorDebugModule2 = CorDebugVersion_2_0, + ver_ICorDebugFunction2 = CorDebugVersion_2_0, + ver_ICorDebugCode2 = CorDebugVersion_2_0, + ver_ICorDebugClass2 = CorDebugVersion_2_0, + ver_ICorDebugValue2 = CorDebugVersion_2_0, + ver_ICorDebugEval2 = CorDebugVersion_2_0, + ver_ICorDebugObjectValue2 = CorDebugVersion_2_0, + CorDebugVersion_4_0 = ( CorDebugVersion_2_0 + 1 ) , + ver_ICorDebugThread3 = CorDebugVersion_4_0, + ver_ICorDebugThread4 = CorDebugVersion_4_0, + ver_ICorDebugStackWalk = CorDebugVersion_4_0, + ver_ICorDebugNativeFrame2 = CorDebugVersion_4_0, + ver_ICorDebugInternalFrame2 = CorDebugVersion_4_0, + ver_ICorDebugRuntimeUnwindableFrame = CorDebugVersion_4_0, + ver_ICorDebugHeapValue3 = CorDebugVersion_4_0, + ver_ICorDebugBlockingObjectEnum = CorDebugVersion_4_0, + ver_ICorDebugValue3 = CorDebugVersion_4_0, + CorDebugVersion_4_5 = ( CorDebugVersion_4_0 + 1 ) , + ver_ICorDebugComObjectValue = CorDebugVersion_4_5, + ver_ICorDebugAppDomain3 = CorDebugVersion_4_5, + ver_ICorDebugCode3 = CorDebugVersion_4_5, + ver_ICorDebugILFrame3 = CorDebugVersion_4_5, + CorDebugLatestVersion = CorDebugVersion_4_5 + } CorDebugInterfaceVersion; + + +EXTERN_C const IID IID_ICorDebug2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ECCCCF2E-B286-4b3e-A983-860A8793D105") + ICorDebug2 : public IUnknown + { + public: + }; + + +#else /* C style interface */ + + typedef struct ICorDebug2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebug2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebug2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebug2 * This); + + END_INTERFACE + } ICorDebug2Vtbl; + + interface ICorDebug2 + { + CONST_VTBL struct ICorDebug2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebug2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebug2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebug2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebug2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0024 */ +/* [local] */ + +typedef +enum CorDebugThreadState + { + THREAD_RUN = 0, + THREAD_SUSPEND = ( THREAD_RUN + 1 ) + } CorDebugThreadState; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec; + +#ifndef __ICorDebugController_INTERFACE_DEFINED__ +#define __ICorDebugController_INTERFACE_DEFINED__ + +/* interface ICorDebugController */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugController; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3d6f5f62-7538-11d3-8d5b-00104b35e7ef") + ICorDebugController : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Stop( + /* [in] */ DWORD dwTimeoutIgnored) = 0; + + virtual HRESULT STDMETHODCALLTYPE Continue( + /* [in] */ BOOL fIsOutOfBand) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsRunning( + /* [out] */ BOOL *pbRunning) = 0; + + virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( + /* [in] */ ICorDebugThread *pThread, + /* [out] */ BOOL *pbQueued) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( + /* [out] */ ICorDebugThreadEnum **ppThreads) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( + /* [in] */ CorDebugThreadState state, + /* [in] */ ICorDebugThread *pExceptThisThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE Detach( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Terminate( + /* [in] */ UINT exitCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; + + virtual HRESULT STDMETHODCALLTYPE CommitChanges( + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugControllerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugController * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugController * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugController * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorDebugController * This, + /* [in] */ DWORD dwTimeoutIgnored); + + HRESULT ( STDMETHODCALLTYPE *Continue )( + ICorDebugController * This, + /* [in] */ BOOL fIsOutOfBand); + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( + ICorDebugController * This, + /* [out] */ BOOL *pbRunning); + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + ICorDebugController * This, + /* [in] */ ICorDebugThread *pThread, + /* [out] */ BOOL *pbQueued); + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + ICorDebugController * This, + /* [out] */ ICorDebugThreadEnum **ppThreads); + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + ICorDebugController * This, + /* [in] */ CorDebugThreadState state, + /* [in] */ ICorDebugThread *pExceptThisThread); + + HRESULT ( STDMETHODCALLTYPE *Detach )( + ICorDebugController * This); + + HRESULT ( STDMETHODCALLTYPE *Terminate )( + ICorDebugController * This, + /* [in] */ UINT exitCode); + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + ICorDebugController * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + ICorDebugController * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + END_INTERFACE + } ICorDebugControllerVtbl; + + interface ICorDebugController + { + CONST_VTBL struct ICorDebugControllerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugController_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugController_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugController_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugController_Stop(This,dwTimeoutIgnored) \ + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + +#define ICorDebugController_Continue(This,fIsOutOfBand) \ + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + +#define ICorDebugController_IsRunning(This,pbRunning) \ + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + +#define ICorDebugController_HasQueuedCallbacks(This,pThread,pbQueued) \ + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + +#define ICorDebugController_EnumerateThreads(This,ppThreads) \ + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + +#define ICorDebugController_SetAllThreadsDebugState(This,state,pExceptThisThread) \ + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + +#define ICorDebugController_Detach(This) \ + ( (This)->lpVtbl -> Detach(This) ) + +#define ICorDebugController_Terminate(This,exitCode) \ + ( (This)->lpVtbl -> Terminate(This,exitCode) ) + +#define ICorDebugController_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + +#define ICorDebugController_CommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugController_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0025 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_s_ifspec; + +#ifndef __ICorDebugAppDomain_INTERFACE_DEFINED__ +#define __ICorDebugAppDomain_INTERFACE_DEFINED__ + +/* interface ICorDebugAppDomain */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAppDomain; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3d6f5f63-7538-11d3-8d5b-00104b35e7ef") + ICorDebugAppDomain : public ICorDebugController + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( + /* [out] */ ICorDebugAssemblyEnum **ppAssemblies) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( + /* [in] */ IUnknown *pIMetaData, + /* [out] */ ICorDebugModule **ppModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( + /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( + /* [out] */ ICorDebugStepperEnum **ppSteppers) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsAttached( + /* [out] */ BOOL *pbAttached) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObject( + /* [out] */ ICorDebugValue **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE Attach( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetID( + /* [out] */ ULONG32 *pId) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAppDomainVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAppDomain * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAppDomain * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAppDomain * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorDebugAppDomain * This, + /* [in] */ DWORD dwTimeoutIgnored); + + HRESULT ( STDMETHODCALLTYPE *Continue )( + ICorDebugAppDomain * This, + /* [in] */ BOOL fIsOutOfBand); + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( + ICorDebugAppDomain * This, + /* [out] */ BOOL *pbRunning); + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + ICorDebugAppDomain * This, + /* [in] */ ICorDebugThread *pThread, + /* [out] */ BOOL *pbQueued); + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugThreadEnum **ppThreads); + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + ICorDebugAppDomain * This, + /* [in] */ CorDebugThreadState state, + /* [in] */ ICorDebugThread *pExceptThisThread); + + HRESULT ( STDMETHODCALLTYPE *Detach )( + ICorDebugAppDomain * This); + + HRESULT ( STDMETHODCALLTYPE *Terminate )( + ICorDebugAppDomain * This, + /* [in] */ UINT exitCode); + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + ICorDebugAppDomain * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + ICorDebugAppDomain * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugAssemblyEnum **ppAssemblies); + + HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( + ICorDebugAppDomain * This, + /* [in] */ IUnknown *pIMetaData, + /* [out] */ ICorDebugModule **ppModule); + + HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints); + + HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugStepperEnum **ppSteppers); + + HRESULT ( STDMETHODCALLTYPE *IsAttached )( + ICorDebugAppDomain * This, + /* [out] */ BOOL *pbAttached); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugAppDomain * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObject )( + ICorDebugAppDomain * This, + /* [out] */ ICorDebugValue **ppObject); + + HRESULT ( STDMETHODCALLTYPE *Attach )( + ICorDebugAppDomain * This); + + HRESULT ( STDMETHODCALLTYPE *GetID )( + ICorDebugAppDomain * This, + /* [out] */ ULONG32 *pId); + + END_INTERFACE + } ICorDebugAppDomainVtbl; + + interface ICorDebugAppDomain + { + CONST_VTBL struct ICorDebugAppDomainVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAppDomain_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAppDomain_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAppDomain_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAppDomain_Stop(This,dwTimeoutIgnored) \ + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + +#define ICorDebugAppDomain_Continue(This,fIsOutOfBand) \ + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + +#define ICorDebugAppDomain_IsRunning(This,pbRunning) \ + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + +#define ICorDebugAppDomain_HasQueuedCallbacks(This,pThread,pbQueued) \ + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + +#define ICorDebugAppDomain_EnumerateThreads(This,ppThreads) \ + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + +#define ICorDebugAppDomain_SetAllThreadsDebugState(This,state,pExceptThisThread) \ + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + +#define ICorDebugAppDomain_Detach(This) \ + ( (This)->lpVtbl -> Detach(This) ) + +#define ICorDebugAppDomain_Terminate(This,exitCode) \ + ( (This)->lpVtbl -> Terminate(This,exitCode) ) + +#define ICorDebugAppDomain_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + +#define ICorDebugAppDomain_CommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + + +#define ICorDebugAppDomain_GetProcess(This,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + +#define ICorDebugAppDomain_EnumerateAssemblies(This,ppAssemblies) \ + ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) + +#define ICorDebugAppDomain_GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) \ + ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) + +#define ICorDebugAppDomain_EnumerateBreakpoints(This,ppBreakpoints) \ + ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) + +#define ICorDebugAppDomain_EnumerateSteppers(This,ppSteppers) \ + ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) + +#define ICorDebugAppDomain_IsAttached(This,pbAttached) \ + ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) + +#define ICorDebugAppDomain_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugAppDomain_GetObject(This,ppObject) \ + ( (This)->lpVtbl -> GetObject(This,ppObject) ) + +#define ICorDebugAppDomain_Attach(This) \ + ( (This)->lpVtbl -> Attach(This) ) + +#define ICorDebugAppDomain_GetID(This,pId) \ + ( (This)->lpVtbl -> GetID(This,pId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAppDomain_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0026 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_s_ifspec; + +#ifndef __ICorDebugAppDomain2_INTERFACE_DEFINED__ +#define __ICorDebugAppDomain2_INTERFACE_DEFINED__ + +/* interface ICorDebugAppDomain2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAppDomain2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("096E81D5-ECDA-4202-83F5-C65980A9EF75") + ICorDebugAppDomain2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( + /* [in] */ CorElementType elementType, + /* [in] */ ULONG32 nRank, + /* [in] */ ICorDebugType *pTypeArg, + /* [out] */ ICorDebugType **ppType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [out] */ ICorDebugType **ppType) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAppDomain2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAppDomain2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAppDomain2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAppDomain2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( + ICorDebugAppDomain2 * This, + /* [in] */ CorElementType elementType, + /* [in] */ ULONG32 nRank, + /* [in] */ ICorDebugType *pTypeArg, + /* [out] */ ICorDebugType **ppType); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( + ICorDebugAppDomain2 * This, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [out] */ ICorDebugType **ppType); + + END_INTERFACE + } ICorDebugAppDomain2Vtbl; + + interface ICorDebugAppDomain2 + { + CONST_VTBL struct ICorDebugAppDomain2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAppDomain2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAppDomain2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAppDomain2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAppDomain2_GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) \ + ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) + +#define ICorDebugAppDomain2_GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) \ + ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAppDomain2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugEnum_INTERFACE_DEFINED__ +#define __ICorDebugEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB01-8A68-11d2-983C-0000F808342D") + ICorDebugEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorDebugEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugEnum * This, + /* [out] */ ULONG *pcelt); + + END_INTERFACE + } ICorDebugEnumVtbl; + + interface ICorDebugEnum + { + CONST_VTBL struct ICorDebugEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ +#define __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugGuidToTypeEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6164D242-1015-4BD6-8CBE-D0DBD4B8275A") + ICorDebugGuidToTypeEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugGuidToTypeEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugGuidToTypeEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugGuidToTypeEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugGuidToTypeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugGuidToTypeEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugGuidToTypeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugGuidToTypeEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugGuidToTypeEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugGuidToTypeEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugGuidToTypeEnumVtbl; + + interface ICorDebugGuidToTypeEnum + { + CONST_VTBL struct ICorDebugGuidToTypeEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugGuidToTypeEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugGuidToTypeEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugGuidToTypeEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugGuidToTypeEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugGuidToTypeEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugGuidToTypeEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugGuidToTypeEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugGuidToTypeEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain3_INTERFACE_DEFINED__ +#define __ICorDebugAppDomain3_INTERFACE_DEFINED__ + +/* interface ICorDebugAppDomain3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAppDomain3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8CB96A16-B588-42E2-B71C-DD849FC2ECCC") + ICorDebugAppDomain3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( + /* [in] */ ULONG32 cReqTypes, + /* [size_is][in] */ GUID *iidsToResolve, + /* [out] */ ICorDebugTypeEnum **ppTypesEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( + /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAppDomain3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAppDomain3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAppDomain3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAppDomain3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( + ICorDebugAppDomain3 * This, + /* [in] */ ULONG32 cReqTypes, + /* [size_is][in] */ GUID *iidsToResolve, + /* [out] */ ICorDebugTypeEnum **ppTypesEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( + ICorDebugAppDomain3 * This, + /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum); + + END_INTERFACE + } ICorDebugAppDomain3Vtbl; + + interface ICorDebugAppDomain3 + { + CONST_VTBL struct ICorDebugAppDomain3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAppDomain3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAppDomain3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAppDomain3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAppDomain3_GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) \ + ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) + +#define ICorDebugAppDomain3_GetCachedWinRTTypes(This,ppGuidToTypeEnum) \ + ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAppDomain3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugAppDomain4_INTERFACE_DEFINED__ +#define __ICorDebugAppDomain4_INTERFACE_DEFINED__ + +/* interface ICorDebugAppDomain4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAppDomain4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FB99CC40-83BE-4724-AB3B-768E796EBAC2") + ICorDebugAppDomain4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( + /* [in] */ CORDB_ADDRESS ccwPointer, + /* [out] */ ICorDebugValue **ppManagedObject) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAppDomain4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAppDomain4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAppDomain4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAppDomain4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( + ICorDebugAppDomain4 * This, + /* [in] */ CORDB_ADDRESS ccwPointer, + /* [out] */ ICorDebugValue **ppManagedObject); + + END_INTERFACE + } ICorDebugAppDomain4Vtbl; + + interface ICorDebugAppDomain4 + { + CONST_VTBL struct ICorDebugAppDomain4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAppDomain4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAppDomain4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAppDomain4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAppDomain4_GetObjectForCCW(This,ccwPointer,ppManagedObject) \ + ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAppDomain4_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0030 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_s_ifspec; + +#ifndef __ICorDebugAssembly_INTERFACE_DEFINED__ +#define __ICorDebugAssembly_INTERFACE_DEFINED__ + +/* interface ICorDebugAssembly */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAssembly; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("df59507c-d47a-459e-bce2-6427eac8fd06") + ICorDebugAssembly : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateModules( + /* [out] */ ICorDebugModuleEnum **ppModules) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeBase( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAssemblyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAssembly * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAssembly * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAssembly * This); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorDebugAssembly * This, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + ICorDebugAssembly * This, + /* [out] */ ICorDebugAppDomain **ppAppDomain); + + HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( + ICorDebugAssembly * This, + /* [out] */ ICorDebugModuleEnum **ppModules); + + HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( + ICorDebugAssembly * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugAssembly * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + END_INTERFACE + } ICorDebugAssemblyVtbl; + + interface ICorDebugAssembly + { + CONST_VTBL struct ICorDebugAssemblyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAssembly_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAssembly_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAssembly_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAssembly_GetProcess(This,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + +#define ICorDebugAssembly_GetAppDomain(This,ppAppDomain) \ + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + +#define ICorDebugAssembly_EnumerateModules(This,ppModules) \ + ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) + +#define ICorDebugAssembly_GetCodeBase(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) + +#define ICorDebugAssembly_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAssembly_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0031 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_s_ifspec; + +#ifndef __ICorDebugAssembly2_INTERFACE_DEFINED__ +#define __ICorDebugAssembly2_INTERFACE_DEFINED__ + +/* interface ICorDebugAssembly2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAssembly2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("426d1f9e-6dd4-44c8-aec7-26cdbaf4e398") + ICorDebugAssembly2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( + /* [out] */ BOOL *pbFullyTrusted) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAssembly2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAssembly2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAssembly2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAssembly2 * This); + + HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( + ICorDebugAssembly2 * This, + /* [out] */ BOOL *pbFullyTrusted); + + END_INTERFACE + } ICorDebugAssembly2Vtbl; + + interface ICorDebugAssembly2 + { + CONST_VTBL struct ICorDebugAssembly2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAssembly2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAssembly2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAssembly2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAssembly2_IsFullyTrusted(This,pbFullyTrusted) \ + ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAssembly2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugAssembly3_INTERFACE_DEFINED__ +#define __ICorDebugAssembly3_INTERFACE_DEFINED__ + +/* interface ICorDebugAssembly3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAssembly3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("76361AB2-8C86-4FE9-96F2-F73D8843570A") + ICorDebugAssembly3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( + ICorDebugAssembly **ppAssembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( + ICorDebugAssemblyEnum **ppAssemblies) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAssembly3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAssembly3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAssembly3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAssembly3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( + ICorDebugAssembly3 * This, + ICorDebugAssembly **ppAssembly); + + HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( + ICorDebugAssembly3 * This, + ICorDebugAssemblyEnum **ppAssemblies); + + END_INTERFACE + } ICorDebugAssembly3Vtbl; + + interface ICorDebugAssembly3 + { + CONST_VTBL struct ICorDebugAssembly3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAssembly3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAssembly3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAssembly3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAssembly3_GetContainerAssembly(This,ppAssembly) \ + ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) + +#define ICorDebugAssembly3_EnumerateContainedAssemblies(This,ppAssemblies) \ + ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAssembly3_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0033 */ +/* [local] */ + +#ifndef _DEF_COR_TYPEID_ +#define _DEF_COR_TYPEID_ +typedef struct COR_TYPEID + { + UINT64 token1; + UINT64 token2; + } COR_TYPEID; + +#endif // _DEF_COR_TYPEID_ +typedef struct _COR_HEAPOBJECT + { + CORDB_ADDRESS address; + ULONG64 size; + COR_TYPEID type; + } COR_HEAPOBJECT; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec; + +#ifndef __ICorDebugHeapEnum_INTERFACE_DEFINED__ +#define __ICorDebugHeapEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugHeapEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHeapEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("76D7DAB8-D044-11DF-9A15-7E29DFD72085") + ICorDebugHeapEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHeapEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHeapEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHeapEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHeapEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugHeapEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugHeapEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugHeapEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugHeapEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugHeapEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugHeapEnumVtbl; + + interface ICorDebugHeapEnum + { + CONST_VTBL struct ICorDebugHeapEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHeapEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHeapEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHeapEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHeapEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugHeapEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugHeapEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugHeapEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugHeapEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHeapEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0034 */ +/* [local] */ + +typedef +enum CorDebugGenerationTypes + { + CorDebug_Gen0 = 0, + CorDebug_Gen1 = 1, + CorDebug_Gen2 = 2, + CorDebug_LOH = 3 + } CorDebugGenerationTypes; + +typedef struct _COR_SEGMENT + { + CORDB_ADDRESS start; + CORDB_ADDRESS end; + CorDebugGenerationTypes type; + ULONG heap; + } COR_SEGMENT; + +typedef +enum CorDebugGCType + { + CorDebugWorkstationGC = 0, + CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) + } CorDebugGCType; + +typedef struct _COR_HEAPINFO + { + BOOL areGCStructuresValid; + DWORD pointerSize; + DWORD numHeaps; + BOOL concurrent; + CorDebugGCType gcType; + } COR_HEAPINFO; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec; + +#ifndef __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ +#define __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugHeapSegmentEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085") + ICorDebugHeapSegmentEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHeapSegmentEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHeapSegmentEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHeapSegmentEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHeapSegmentEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugHeapSegmentEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugHeapSegmentEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugHeapSegmentEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugHeapSegmentEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugHeapSegmentEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugHeapSegmentEnumVtbl; + + interface ICorDebugHeapSegmentEnum + { + CONST_VTBL struct ICorDebugHeapSegmentEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHeapSegmentEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHeapSegmentEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHeapSegmentEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHeapSegmentEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugHeapSegmentEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugHeapSegmentEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugHeapSegmentEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugHeapSegmentEnum_Next(This,celt,segments,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0035 */ +/* [local] */ + +typedef +enum CorGCReferenceType + { + CorHandleStrong = ( 1 << 0 ) , + CorHandleStrongPinning = ( 1 << 1 ) , + CorHandleWeakShort = ( 1 << 2 ) , + CorHandleWeakLong = ( 1 << 3 ) , + CorHandleWeakRefCount = ( 1 << 4 ) , + CorHandleStrongRefCount = ( 1 << 5 ) , + CorHandleStrongDependent = ( 1 << 6 ) , + CorHandleStrongAsyncPinned = ( 1 << 7 ) , + CorHandleStrongSizedByref = ( 1 << 8 ) , + CorHandleWeakWinRT = ( 1 << 9 ) , + CorReferenceStack = 0x80000001, + CorReferenceFinalizer = 80000002, + CorHandleStrongOnly = 0x1e3, + CorHandleWeakOnly = 0x21c, + CorHandleAll = 0x7fffffff + } CorGCReferenceType; + +#ifndef _DEF_COR_GC_REFERENCE_ +#define _DEF_COR_GC_REFERENCE_ +typedef struct COR_GC_REFERENCE + { + ICorDebugAppDomain *Domain; + ICorDebugValue *Location; + CorGCReferenceType Type; + UINT64 ExtraData; + } COR_GC_REFERENCE; + +#endif // _DEF_COR_GC_REFERENCE_ + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec; + +#ifndef __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ +#define __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugGCReferenceEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugGCReferenceEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C") + ICorDebugGCReferenceEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugGCReferenceEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugGCReferenceEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugGCReferenceEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugGCReferenceEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugGCReferenceEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugGCReferenceEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugGCReferenceEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugGCReferenceEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugGCReferenceEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugGCReferenceEnumVtbl; + + interface ICorDebugGCReferenceEnum + { + CONST_VTBL struct ICorDebugGCReferenceEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugGCReferenceEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugGCReferenceEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugGCReferenceEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugGCReferenceEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugGCReferenceEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugGCReferenceEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugGCReferenceEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugGCReferenceEnum_Next(This,celt,roots,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0036 */ +/* [local] */ + +#ifndef _DEF_COR_ARRAY_LAYOUT_ +#define _DEF_COR_ARRAY_LAYOUT_ +typedef struct COR_ARRAY_LAYOUT + { + COR_TYPEID componentID; + CorElementType componentType; + ULONG32 firstElementOffset; + ULONG32 elementSize; + ULONG32 countOffset; + ULONG32 rankSize; + ULONG32 numRanks; + ULONG32 rankOffset; + } COR_ARRAY_LAYOUT; + +#endif // _DEF_COR_ARRAY_LAYOUT_ +#ifndef _DEF_COR_TYPE_LAYOUT_ +#define _DEF_COR_TYPE_LAYOUT_ +typedef struct COR_TYPE_LAYOUT + { + COR_TYPEID parentID; + ULONG32 objectSize; + ULONG32 numFields; + ULONG32 boxOffset; + CorElementType type; + } COR_TYPE_LAYOUT; + +#endif // _DEF_COR_TYPE_LAYOUT_ +#ifndef _DEF_COR_FIELD_ +#define _DEF_COR_FIELD_ +typedef struct COR_FIELD + { + mdFieldDef token; + ULONG32 offset; + COR_TYPEID id; + CorElementType fieldType; + } COR_FIELD; + +#endif // _DEF_COR_FIELD_ +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_s_ifspec; + +#ifndef __ICorDebugProcess_INTERFACE_DEFINED__ +#define __ICorDebugProcess_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3d6f5f64-7538-11d3-8d5b-00104b35e7ef") + ICorDebugProcess : public ICorDebugController + { + public: + virtual HRESULT STDMETHODCALLTYPE GetID( + /* [out] */ DWORD *pdwProcessId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandle( + /* [out] */ HPROCESS *phProcessHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThread( + /* [in] */ DWORD dwThreadId, + /* [out] */ ICorDebugThread **ppThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( + /* [out] */ ICorDebugObjectEnum **ppObjects) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( + /* [in] */ CORDB_ADDRESS address, + /* [out] */ BOOL *pbTransitionStub) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( + /* [in] */ DWORD threadID, + /* [out] */ BOOL *pbSuspended) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadMemory( + /* [in] */ CORDB_ADDRESS address, + /* [in] */ DWORD size, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ SIZE_T *read) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteMemory( + /* [in] */ CORDB_ADDRESS address, + /* [in] */ DWORD size, + /* [size_is][in] */ BYTE buffer[ ], + /* [out] */ SIZE_T *written) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( + /* [in] */ DWORD threadID) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( + /* [in] */ BOOL fOnOff) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( + /* [annotation][in] */ + _In_ WCHAR *pLogSwitchName, + /* [in] */ LONG lLevel) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( + /* [out] */ ICorDebugAppDomainEnum **ppAppDomains) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObject( + /* [out] */ ICorDebugValue **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( + /* [in] */ DWORD fiberCookie, + /* [out] */ ICorDebugThread **ppThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( + /* [out] */ DWORD *pThreadID) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcessVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorDebugProcess * This, + /* [in] */ DWORD dwTimeoutIgnored); + + HRESULT ( STDMETHODCALLTYPE *Continue )( + ICorDebugProcess * This, + /* [in] */ BOOL fIsOutOfBand); + + HRESULT ( STDMETHODCALLTYPE *IsRunning )( + ICorDebugProcess * This, + /* [out] */ BOOL *pbRunning); + + HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( + ICorDebugProcess * This, + /* [in] */ ICorDebugThread *pThread, + /* [out] */ BOOL *pbQueued); + + HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( + ICorDebugProcess * This, + /* [out] */ ICorDebugThreadEnum **ppThreads); + + HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( + ICorDebugProcess * This, + /* [in] */ CorDebugThreadState state, + /* [in] */ ICorDebugThread *pExceptThisThread); + + HRESULT ( STDMETHODCALLTYPE *Detach )( + ICorDebugProcess * This); + + HRESULT ( STDMETHODCALLTYPE *Terminate )( + ICorDebugProcess * This, + /* [in] */ UINT exitCode); + + HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( + ICorDebugProcess * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + HRESULT ( STDMETHODCALLTYPE *CommitChanges )( + ICorDebugProcess * This, + /* [in] */ ULONG cSnapshots, + /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], + /* [out] */ ICorDebugErrorInfoEnum **pError); + + HRESULT ( STDMETHODCALLTYPE *GetID )( + ICorDebugProcess * This, + /* [out] */ DWORD *pdwProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetHandle )( + ICorDebugProcess * This, + /* [out] */ HPROCESS *phProcessHandle); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugProcess * This, + /* [in] */ DWORD dwThreadId, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( + ICorDebugProcess * This, + /* [out] */ ICorDebugObjectEnum **ppObjects); + + HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( + ICorDebugProcess * This, + /* [in] */ CORDB_ADDRESS address, + /* [out] */ BOOL *pbTransitionStub); + + HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( + ICorDebugProcess * This, + /* [in] */ DWORD threadID, + /* [out] */ BOOL *pbSuspended); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorDebugProcess * This, + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][out][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICorDebugProcess * This, + /* [in] */ DWORD threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *ReadMemory )( + ICorDebugProcess * This, + /* [in] */ CORDB_ADDRESS address, + /* [in] */ DWORD size, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ SIZE_T *read); + + HRESULT ( STDMETHODCALLTYPE *WriteMemory )( + ICorDebugProcess * This, + /* [in] */ CORDB_ADDRESS address, + /* [in] */ DWORD size, + /* [size_is][in] */ BYTE buffer[ ], + /* [out] */ SIZE_T *written); + + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + ICorDebugProcess * This, + /* [in] */ DWORD threadID); + + HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( + ICorDebugProcess * This, + /* [in] */ BOOL fOnOff); + + HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( + ICorDebugProcess * This, + /* [annotation][in] */ + _In_ WCHAR *pLogSwitchName, + /* [in] */ LONG lLevel); + + HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( + ICorDebugProcess * This, + /* [out] */ ICorDebugAppDomainEnum **ppAppDomains); + + HRESULT ( STDMETHODCALLTYPE *GetObject )( + ICorDebugProcess * This, + /* [out] */ ICorDebugValue **ppObject); + + HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( + ICorDebugProcess * This, + /* [in] */ DWORD fiberCookie, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( + ICorDebugProcess * This, + /* [out] */ DWORD *pThreadID); + + END_INTERFACE + } ICorDebugProcessVtbl; + + interface ICorDebugProcess + { + CONST_VTBL struct ICorDebugProcessVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess_Stop(This,dwTimeoutIgnored) \ + ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) + +#define ICorDebugProcess_Continue(This,fIsOutOfBand) \ + ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) + +#define ICorDebugProcess_IsRunning(This,pbRunning) \ + ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) + +#define ICorDebugProcess_HasQueuedCallbacks(This,pThread,pbQueued) \ + ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) + +#define ICorDebugProcess_EnumerateThreads(This,ppThreads) \ + ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) + +#define ICorDebugProcess_SetAllThreadsDebugState(This,state,pExceptThisThread) \ + ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) + +#define ICorDebugProcess_Detach(This) \ + ( (This)->lpVtbl -> Detach(This) ) + +#define ICorDebugProcess_Terminate(This,exitCode) \ + ( (This)->lpVtbl -> Terminate(This,exitCode) ) + +#define ICorDebugProcess_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) + +#define ICorDebugProcess_CommitChanges(This,cSnapshots,pSnapshots,pError) \ + ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) + + +#define ICorDebugProcess_GetID(This,pdwProcessId) \ + ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) + +#define ICorDebugProcess_GetHandle(This,phProcessHandle) \ + ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) + +#define ICorDebugProcess_GetThread(This,dwThreadId,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) + +#define ICorDebugProcess_EnumerateObjects(This,ppObjects) \ + ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) + +#define ICorDebugProcess_IsTransitionStub(This,address,pbTransitionStub) \ + ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) + +#define ICorDebugProcess_IsOSSuspended(This,threadID,pbSuspended) \ + ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) + +#define ICorDebugProcess_GetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) + +#define ICorDebugProcess_SetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + +#define ICorDebugProcess_ReadMemory(This,address,size,buffer,read) \ + ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) + +#define ICorDebugProcess_WriteMemory(This,address,size,buffer,written) \ + ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) + +#define ICorDebugProcess_ClearCurrentException(This,threadID) \ + ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) + +#define ICorDebugProcess_EnableLogMessages(This,fOnOff) \ + ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) + +#define ICorDebugProcess_ModifyLogSwitch(This,pLogSwitchName,lLevel) \ + ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) + +#define ICorDebugProcess_EnumerateAppDomains(This,ppAppDomains) \ + ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) + +#define ICorDebugProcess_GetObject(This,ppObject) \ + ( (This)->lpVtbl -> GetObject(This,ppObject) ) + +#define ICorDebugProcess_ThreadForFiberCookie(This,fiberCookie,ppThread) \ + ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) + +#define ICorDebugProcess_GetHelperThreadID(This,pThreadID) \ + ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0037 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_s_ifspec; + +#ifndef __ICorDebugProcess2_INTERFACE_DEFINED__ +#define __ICorDebugProcess2_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AD1B3588-0EF0-4744-A496-AA09A9F80371") + ICorDebugProcess2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( + /* [in] */ TASKID taskid, + /* [out] */ ICorDebugThread2 **ppThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersion( + /* [out] */ COR_VERSION *version) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( + /* [in] */ CORDB_ADDRESS address, + /* [in] */ ULONG32 bufsize, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ ULONG32 *bufLen) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( + /* [in] */ CORDB_ADDRESS address) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( + /* [in] */ DWORD pdwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( + /* [out] */ DWORD *pdwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( + /* [in] */ UINT_PTR handle, + /* [out] */ ICorDebugReferenceValue **pOutValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( + ICorDebugProcess2 * This, + /* [in] */ TASKID taskid, + /* [out] */ ICorDebugThread2 **ppThread); + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( + ICorDebugProcess2 * This, + /* [out] */ COR_VERSION *version); + + HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( + ICorDebugProcess2 * This, + /* [in] */ CORDB_ADDRESS address, + /* [in] */ ULONG32 bufsize, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ ULONG32 *bufLen); + + HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( + ICorDebugProcess2 * This, + /* [in] */ CORDB_ADDRESS address); + + HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( + ICorDebugProcess2 * This, + /* [in] */ DWORD pdwFlags); + + HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( + ICorDebugProcess2 * This, + /* [out] */ DWORD *pdwFlags); + + HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( + ICorDebugProcess2 * This, + /* [in] */ UINT_PTR handle, + /* [out] */ ICorDebugReferenceValue **pOutValue); + + END_INTERFACE + } ICorDebugProcess2Vtbl; + + interface ICorDebugProcess2 + { + CONST_VTBL struct ICorDebugProcess2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess2_GetThreadForTaskID(This,taskid,ppThread) \ + ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) + +#define ICorDebugProcess2_GetVersion(This,version) \ + ( (This)->lpVtbl -> GetVersion(This,version) ) + +#define ICorDebugProcess2_SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) \ + ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) + +#define ICorDebugProcess2_ClearUnmanagedBreakpoint(This,address) \ + ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) + +#define ICorDebugProcess2_SetDesiredNGENCompilerFlags(This,pdwFlags) \ + ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) + +#define ICorDebugProcess2_GetDesiredNGENCompilerFlags(This,pdwFlags) \ + ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) + +#define ICorDebugProcess2_GetReferenceValueFromGCHandle(This,handle,pOutValue) \ + ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugProcess3_INTERFACE_DEFINED__ +#define __ICorDebugProcess3_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2EE06488-C0D4-42B1-B26D-F3795EF606FB") + ICorDebugProcess3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( + ICorDebugClass *pClass, + BOOL fEnable) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess3 * This); + + HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( + ICorDebugProcess3 * This, + ICorDebugClass *pClass, + BOOL fEnable); + + END_INTERFACE + } ICorDebugProcess3Vtbl; + + interface ICorDebugProcess3 + { + CONST_VTBL struct ICorDebugProcess3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess3_SetEnableCustomNotification(This,pClass,fEnable) \ + ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugProcess5_INTERFACE_DEFINED__ +#define __ICorDebugProcess5_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess5 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("21e9d9c0-fcb8-11df-8cff-0800200c9a66") + ICorDebugProcess5 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( + /* [out] */ COR_HEAPINFO *pHeapInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( + /* [out] */ ICorDebugHeapEnum **ppObjects) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( + /* [out] */ ICorDebugHeapSegmentEnum **ppRegions) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObject( + /* [in] */ CORDB_ADDRESS addr, + /* [out] */ ICorDebugObjectValue **pObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( + /* [in] */ BOOL enumerateWeakReferences, + /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( + /* [in] */ CorGCReferenceType types, + /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeID( + /* [in] */ CORDB_ADDRESS obj, + /* [out] */ COR_TYPEID *pId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( + /* [in] */ COR_TYPEID id, + /* [out] */ ICorDebugType **ppType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( + /* [in] */ COR_TYPEID id, + /* [out] */ COR_ARRAY_LAYOUT *pLayout) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( + /* [in] */ COR_TYPEID id, + /* [out] */ COR_TYPE_LAYOUT *pLayout) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeFields( + /* [in] */ COR_TYPEID id, + ULONG32 celt, + COR_FIELD fields[ ], + ULONG32 *pceltNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( + /* [in] */ CorDebugNGENPolicy ePolicy) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess5 * This); + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( + ICorDebugProcess5 * This, + /* [out] */ COR_HEAPINFO *pHeapInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( + ICorDebugProcess5 * This, + /* [out] */ ICorDebugHeapEnum **ppObjects); + + HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( + ICorDebugProcess5 * This, + /* [out] */ ICorDebugHeapSegmentEnum **ppRegions); + + HRESULT ( STDMETHODCALLTYPE *GetObject )( + ICorDebugProcess5 * This, + /* [in] */ CORDB_ADDRESS addr, + /* [out] */ ICorDebugObjectValue **pObject); + + HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( + ICorDebugProcess5 * This, + /* [in] */ BOOL enumerateWeakReferences, + /* [out] */ ICorDebugGCReferenceEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( + ICorDebugProcess5 * This, + /* [in] */ CorGCReferenceType types, + /* [out] */ ICorDebugGCReferenceEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + ICorDebugProcess5 * This, + /* [in] */ CORDB_ADDRESS obj, + /* [out] */ COR_TYPEID *pId); + + HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( + ICorDebugProcess5 * This, + /* [in] */ COR_TYPEID id, + /* [out] */ ICorDebugType **ppType); + + HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( + ICorDebugProcess5 * This, + /* [in] */ COR_TYPEID id, + /* [out] */ COR_ARRAY_LAYOUT *pLayout); + + HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( + ICorDebugProcess5 * This, + /* [in] */ COR_TYPEID id, + /* [out] */ COR_TYPE_LAYOUT *pLayout); + + HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( + ICorDebugProcess5 * This, + /* [in] */ COR_TYPEID id, + ULONG32 celt, + COR_FIELD fields[ ], + ULONG32 *pceltNeeded); + + HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( + ICorDebugProcess5 * This, + /* [in] */ CorDebugNGENPolicy ePolicy); + + END_INTERFACE + } ICorDebugProcess5Vtbl; + + interface ICorDebugProcess5 + { + CONST_VTBL struct ICorDebugProcess5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess5_GetGCHeapInformation(This,pHeapInfo) \ + ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) + +#define ICorDebugProcess5_EnumerateHeap(This,ppObjects) \ + ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) + +#define ICorDebugProcess5_EnumerateHeapRegions(This,ppRegions) \ + ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) + +#define ICorDebugProcess5_GetObject(This,addr,pObject) \ + ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) + +#define ICorDebugProcess5_EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) \ + ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) + +#define ICorDebugProcess5_EnumerateHandles(This,types,ppEnum) \ + ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) + +#define ICorDebugProcess5_GetTypeID(This,obj,pId) \ + ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) + +#define ICorDebugProcess5_GetTypeForTypeID(This,id,ppType) \ + ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) + +#define ICorDebugProcess5_GetArrayLayout(This,id,pLayout) \ + ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) + +#define ICorDebugProcess5_GetTypeLayout(This,id,pLayout) \ + ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) + +#define ICorDebugProcess5_GetTypeFields(This,id,celt,fields,pceltNeeded) \ + ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) + +#define ICorDebugProcess5_EnableNGENPolicy(This,ePolicy) \ + ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess5_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0040 */ +/* [local] */ + +typedef +enum CorDebugRecordFormat + { + FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, + FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2 + } CorDebugRecordFormat; + +typedef +enum CorDebugDecodeEventFlagsWindows + { + IS_FIRST_CHANCE = 1 + } CorDebugDecodeEventFlagsWindows; + +typedef +enum CorDebugDebugEventKind + { + DEBUG_EVENT_KIND_MODULE_LOADED = 1, + DEBUG_EVENT_KIND_MODULE_UNLOADED = 2, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_FIRST_CHANCE = 3, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_USER_FIRST_CHANCE = 4, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_CATCH_HANDLER_FOUND = 5, + DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 + } CorDebugDebugEventKind; + +typedef +enum CorDebugStateChange + { + PROCESS_RUNNING = 0x1, + FLUSH_ALL = 0x2 + } CorDebugStateChange; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec; + +#ifndef __ICorDebugDebugEvent_INTERFACE_DEFINED__ +#define __ICorDebugDebugEvent_INTERFACE_DEFINED__ + +/* interface ICorDebugDebugEvent */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugDebugEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("41BD395D-DE99-48F1-BF7A-CC0F44A6D281") + ICorDebugDebugEvent : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEventKind( + /* [out] */ CorDebugDebugEventKind *pDebugEventKind) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThread( + /* [out] */ ICorDebugThread **ppThread) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDebugEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDebugEvent * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDebugEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDebugEvent * This); + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + ICorDebugDebugEvent * This, + /* [out] */ CorDebugDebugEventKind *pDebugEventKind); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugDebugEvent * This, + /* [out] */ ICorDebugThread **ppThread); + + END_INTERFACE + } ICorDebugDebugEventVtbl; + + interface ICorDebugDebugEvent + { + CONST_VTBL struct ICorDebugDebugEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDebugEvent_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDebugEvent_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDebugEvent_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDebugEvent_GetEventKind(This,pDebugEventKind) \ + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + +#define ICorDebugDebugEvent_GetThread(This,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,ppThread) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDebugEvent_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0041 */ +/* [local] */ + +typedef +enum CorDebugCodeInvokeKind + { + CODE_INVOKE_KIND_NONE = 0, + CODE_INVOKE_KIND_RETURN = ( CODE_INVOKE_KIND_NONE + 1 ) , + CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) + } CorDebugCodeInvokeKind; + +typedef +enum CorDebugCodeInvokePurpose + { + CODE_INVOKE_PURPOSE_NONE = 0, + CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION = ( CODE_INVOKE_PURPOSE_NONE + 1 ) , + CODE_INVOKE_PURPOSE_CLASS_INIT = ( CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION + 1 ) , + CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) + } CorDebugCodeInvokePurpose; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_s_ifspec; + +#ifndef __ICorDebugProcess6_INTERFACE_DEFINED__ +#define __ICorDebugProcess6_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess6 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess6; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("11588775-7205-4CEB-A41A-93753C3153E9") + ICorDebugProcess6 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE DecodeEvent( + /* [size_is][length_is][in] */ const BYTE pRecord[ ], + /* [in] */ DWORD countBytes, + /* [in] */ CorDebugRecordFormat format, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwThreadId, + /* [out] */ ICorDebugDebugEvent **ppEvent) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( + /* [in] */ CorDebugStateChange change) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [in] */ CORDB_ADDRESS codeAddress, + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( + BOOL enableSplitting) = 0; + + virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( + BOOL fIsAttached) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( + /* [in] */ LPCWSTR pszExportName, + /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, + /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess6Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess6 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess6 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess6 * This); + + HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( + ICorDebugProcess6 * This, + /* [size_is][length_is][in] */ const BYTE pRecord[ ], + /* [in] */ DWORD countBytes, + /* [in] */ CorDebugRecordFormat format, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwThreadId, + /* [out] */ ICorDebugDebugEvent **ppEvent); + + HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( + ICorDebugProcess6 * This, + /* [in] */ CorDebugStateChange change); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugProcess6 * This, + /* [in] */ CORDB_ADDRESS codeAddress, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( + ICorDebugProcess6 * This, + BOOL enableSplitting); + + HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( + ICorDebugProcess6 * This, + BOOL fIsAttached); + + HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( + ICorDebugProcess6 * This, + /* [in] */ LPCWSTR pszExportName, + /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, + /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose); + + END_INTERFACE + } ICorDebugProcess6Vtbl; + + interface ICorDebugProcess6 + { + CONST_VTBL struct ICorDebugProcess6Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess6_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess6_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess6_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess6_DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) \ + ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) + +#define ICorDebugProcess6_ProcessStateChanged(This,change) \ + ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) + +#define ICorDebugProcess6_GetCode(This,codeAddress,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) + +#define ICorDebugProcess6_EnableVirtualModuleSplitting(This,enableSplitting) \ + ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) + +#define ICorDebugProcess6_MarkDebuggerAttached(This,fIsAttached) \ + ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) + +#define ICorDebugProcess6_GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) \ + ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess6_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0042 */ +/* [local] */ + +typedef +enum WriteableMetadataUpdateMode + { + LegacyCompatPolicy = 0, + AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) + } WriteableMetadataUpdateMode; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_s_ifspec; + +#ifndef __ICorDebugProcess7_INTERFACE_DEFINED__ +#define __ICorDebugProcess7_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess7 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess7; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9B2C54E4-119F-4D6F-B402-527603266D69") + ICorDebugProcess7 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( + WriteableMetadataUpdateMode flags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess7Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess7 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess7 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess7 * This); + + HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( + ICorDebugProcess7 * This, + WriteableMetadataUpdateMode flags); + + END_INTERFACE + } ICorDebugProcess7Vtbl; + + interface ICorDebugProcess7 + { + CONST_VTBL struct ICorDebugProcess7Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess7_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess7_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess7_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess7_SetWriteableMetadataUpdateMode(This,flags) \ + ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess7_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugProcess8_INTERFACE_DEFINED__ +#define __ICorDebugProcess8_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess8 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess8; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2E6F28C1-85EB-4141-80AD-0A90944B9639") + ICorDebugProcess8 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( + /* [in] */ BOOL enableExceptionsOutsideOfJMC) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess8Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess8 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess8 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess8 * This); + + HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( + ICorDebugProcess8 * This, + /* [in] */ BOOL enableExceptionsOutsideOfJMC); + + END_INTERFACE + } ICorDebugProcess8Vtbl; + + interface ICorDebugProcess8 + { + CONST_VTBL struct ICorDebugProcess8Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess8_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess8_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess8_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess8_EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) \ + ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess8_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugProcess10_INTERFACE_DEFINED__ +#define __ICorDebugProcess10_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess10 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess10; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8F378F6F-1017-4461-9890-ECF64C54079F") + ICorDebugProcess10 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( + BOOL fEnable) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess10Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess10 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess10 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess10 * This); + + HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( + ICorDebugProcess10 * This, + BOOL fEnable); + + END_INTERFACE + } ICorDebugProcess10Vtbl; + + interface ICorDebugProcess10 + { + CONST_VTBL struct ICorDebugProcess10Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess10_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess10_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess10_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess10_EnableGCNotificationEvents(This,fEnable) \ + ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess10_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ +#define __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ + +/* interface ICorDebugModuleDebugEvent */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModuleDebugEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("51A15E8D-9FFF-4864-9B87-F4FBDEA747A2") + ICorDebugModuleDebugEvent : public ICorDebugDebugEvent + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ ICorDebugModule **ppModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModuleDebugEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModuleDebugEvent * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModuleDebugEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModuleDebugEvent * This); + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + ICorDebugModuleDebugEvent * This, + /* [out] */ CorDebugDebugEventKind *pDebugEventKind); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugModuleDebugEvent * This, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ICorDebugModuleDebugEvent * This, + /* [out] */ ICorDebugModule **ppModule); + + END_INTERFACE + } ICorDebugModuleDebugEventVtbl; + + interface ICorDebugModuleDebugEvent + { + CONST_VTBL struct ICorDebugModuleDebugEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModuleDebugEvent_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModuleDebugEvent_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModuleDebugEvent_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModuleDebugEvent_GetEventKind(This,pDebugEventKind) \ + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + +#define ICorDebugModuleDebugEvent_GetThread(This,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,ppThread) ) + + +#define ICorDebugModuleDebugEvent_GetModule(This,ppModule) \ + ( (This)->lpVtbl -> GetModule(This,ppModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ +#define __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ + +/* interface ICorDebugExceptionDebugEvent */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AF79EC94-4752-419C-A626-5FB1CC1A5AB7") + ICorDebugExceptionDebugEvent : public ICorDebugDebugEvent + { + public: + virtual HRESULT STDMETHODCALLTYPE GetStackPointer( + /* [out] */ CORDB_ADDRESS *pStackPointer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNativeIP( + /* [out] */ CORDB_ADDRESS *pIP) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ CorDebugExceptionFlags *pdwFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugExceptionDebugEventVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugExceptionDebugEvent * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugExceptionDebugEvent * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugExceptionDebugEvent * This); + + HRESULT ( STDMETHODCALLTYPE *GetEventKind )( + ICorDebugExceptionDebugEvent * This, + /* [out] */ CorDebugDebugEventKind *pDebugEventKind); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugExceptionDebugEvent * This, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( + ICorDebugExceptionDebugEvent * This, + /* [out] */ CORDB_ADDRESS *pStackPointer); + + HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( + ICorDebugExceptionDebugEvent * This, + /* [out] */ CORDB_ADDRESS *pIP); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + ICorDebugExceptionDebugEvent * This, + /* [out] */ CorDebugExceptionFlags *pdwFlags); + + END_INTERFACE + } ICorDebugExceptionDebugEventVtbl; + + interface ICorDebugExceptionDebugEvent + { + CONST_VTBL struct ICorDebugExceptionDebugEventVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugExceptionDebugEvent_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugExceptionDebugEvent_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugExceptionDebugEvent_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugExceptionDebugEvent_GetEventKind(This,pDebugEventKind) \ + ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) + +#define ICorDebugExceptionDebugEvent_GetThread(This,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,ppThread) ) + + +#define ICorDebugExceptionDebugEvent_GetStackPointer(This,pStackPointer) \ + ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) + +#define ICorDebugExceptionDebugEvent_GetNativeIP(This,pIP) \ + ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) + +#define ICorDebugExceptionDebugEvent_GetFlags(This,pdwFlags) \ + ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugBreakpoint_INTERFACE_DEFINED__ +#define __ICorDebugBreakpoint_INTERFACE_DEFINED__ + +/* interface ICorDebugBreakpoint */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugBreakpoint; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAE8-8A68-11d2-983C-0000F808342D") + ICorDebugBreakpoint : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Activate( + /* [in] */ BOOL bActive) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsActive( + /* [out] */ BOOL *pbActive) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugBreakpointVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugBreakpoint * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugBreakpoint * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugBreakpoint * This); + + HRESULT ( STDMETHODCALLTYPE *Activate )( + ICorDebugBreakpoint * This, + /* [in] */ BOOL bActive); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugBreakpoint * This, + /* [out] */ BOOL *pbActive); + + END_INTERFACE + } ICorDebugBreakpointVtbl; + + interface ICorDebugBreakpoint + { + CONST_VTBL struct ICorDebugBreakpointVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugBreakpoint_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugBreakpoint_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugBreakpoint_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugBreakpoint_Activate(This,bActive) \ + ( (This)->lpVtbl -> Activate(This,bActive) ) + +#define ICorDebugBreakpoint_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugBreakpoint_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ +#define __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ + +/* interface ICorDebugFunctionBreakpoint */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAE9-8A68-11d2-983C-0000F808342D") + ICorDebugFunctionBreakpoint : public ICorDebugBreakpoint + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFunction( + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOffset( + /* [out] */ ULONG32 *pnOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFunctionBreakpointVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFunctionBreakpoint * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFunctionBreakpoint * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFunctionBreakpoint * This); + + HRESULT ( STDMETHODCALLTYPE *Activate )( + ICorDebugFunctionBreakpoint * This, + /* [in] */ BOOL bActive); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugFunctionBreakpoint * This, + /* [out] */ BOOL *pbActive); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugFunctionBreakpoint * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( + ICorDebugFunctionBreakpoint * This, + /* [out] */ ULONG32 *pnOffset); + + END_INTERFACE + } ICorDebugFunctionBreakpointVtbl; + + interface ICorDebugFunctionBreakpoint + { + CONST_VTBL struct ICorDebugFunctionBreakpointVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFunctionBreakpoint_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFunctionBreakpoint_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFunctionBreakpoint_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFunctionBreakpoint_Activate(This,bActive) \ + ( (This)->lpVtbl -> Activate(This,bActive) ) + +#define ICorDebugFunctionBreakpoint_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + + +#define ICorDebugFunctionBreakpoint_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugFunctionBreakpoint_GetOffset(This,pnOffset) \ + ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ +#define __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ + +/* interface ICorDebugModuleBreakpoint */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModuleBreakpoint; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAEA-8A68-11d2-983C-0000F808342D") + ICorDebugModuleBreakpoint : public ICorDebugBreakpoint + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ ICorDebugModule **ppModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModuleBreakpointVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModuleBreakpoint * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModuleBreakpoint * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModuleBreakpoint * This); + + HRESULT ( STDMETHODCALLTYPE *Activate )( + ICorDebugModuleBreakpoint * This, + /* [in] */ BOOL bActive); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugModuleBreakpoint * This, + /* [out] */ BOOL *pbActive); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ICorDebugModuleBreakpoint * This, + /* [out] */ ICorDebugModule **ppModule); + + END_INTERFACE + } ICorDebugModuleBreakpointVtbl; + + interface ICorDebugModuleBreakpoint + { + CONST_VTBL struct ICorDebugModuleBreakpointVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModuleBreakpoint_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModuleBreakpoint_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModuleBreakpoint_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModuleBreakpoint_Activate(This,bActive) \ + ( (This)->lpVtbl -> Activate(This,bActive) ) + +#define ICorDebugModuleBreakpoint_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + + +#define ICorDebugModuleBreakpoint_GetModule(This,ppModule) \ + ( (This)->lpVtbl -> GetModule(This,ppModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ +#define __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ + +/* interface ICorDebugValueBreakpoint */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugValueBreakpoint; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAEB-8A68-11d2-983C-0000F808342D") + ICorDebugValueBreakpoint : public ICorDebugBreakpoint + { + public: + virtual HRESULT STDMETHODCALLTYPE GetValue( + /* [out] */ ICorDebugValue **ppValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugValueBreakpointVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugValueBreakpoint * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugValueBreakpoint * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugValueBreakpoint * This); + + HRESULT ( STDMETHODCALLTYPE *Activate )( + ICorDebugValueBreakpoint * This, + /* [in] */ BOOL bActive); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugValueBreakpoint * This, + /* [out] */ BOOL *pbActive); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + ICorDebugValueBreakpoint * This, + /* [out] */ ICorDebugValue **ppValue); + + END_INTERFACE + } ICorDebugValueBreakpointVtbl; + + interface ICorDebugValueBreakpoint + { + CONST_VTBL struct ICorDebugValueBreakpointVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugValueBreakpoint_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugValueBreakpoint_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugValueBreakpoint_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugValueBreakpoint_Activate(This,bActive) \ + ( (This)->lpVtbl -> Activate(This,bActive) ) + +#define ICorDebugValueBreakpoint_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + + +#define ICorDebugValueBreakpoint_GetValue(This,ppValue) \ + ( (This)->lpVtbl -> GetValue(This,ppValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugStepper_INTERFACE_DEFINED__ +#define __ICorDebugStepper_INTERFACE_DEFINED__ + +/* interface ICorDebugStepper */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugIntercept + { + INTERCEPT_NONE = 0, + INTERCEPT_CLASS_INIT = 0x1, + INTERCEPT_EXCEPTION_FILTER = 0x2, + INTERCEPT_SECURITY = 0x4, + INTERCEPT_CONTEXT_POLICY = 0x8, + INTERCEPT_INTERCEPTION = 0x10, + INTERCEPT_ALL = 0xffff + } CorDebugIntercept; + +typedef +enum CorDebugUnmappedStop + { + STOP_NONE = 0, + STOP_PROLOG = 0x1, + STOP_EPILOG = 0x2, + STOP_NO_MAPPING_INFO = 0x4, + STOP_OTHER_UNMAPPED = 0x8, + STOP_UNMANAGED = 0x10, + STOP_ALL = 0xffff + } CorDebugUnmappedStop; + +typedef struct COR_DEBUG_STEP_RANGE + { + ULONG32 startOffset; + ULONG32 endOffset; + } COR_DEBUG_STEP_RANGE; + + +EXTERN_C const IID IID_ICorDebugStepper; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAEC-8A68-11d2-983C-0000F808342D") + ICorDebugStepper : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsActive( + /* [out] */ BOOL *pbActive) = 0; + + virtual HRESULT STDMETHODCALLTYPE Deactivate( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( + /* [in] */ CorDebugIntercept mask) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( + /* [in] */ CorDebugUnmappedStop mask) = 0; + + virtual HRESULT STDMETHODCALLTYPE Step( + /* [in] */ BOOL bStepIn) = 0; + + virtual HRESULT STDMETHODCALLTYPE StepRange( + /* [in] */ BOOL bStepIn, + /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], + /* [in] */ ULONG32 cRangeCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE StepOut( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetRangeIL( + /* [in] */ BOOL bIL) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStepperVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStepper * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStepper * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStepper * This); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugStepper * This, + /* [out] */ BOOL *pbActive); + + HRESULT ( STDMETHODCALLTYPE *Deactivate )( + ICorDebugStepper * This); + + HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( + ICorDebugStepper * This, + /* [in] */ CorDebugIntercept mask); + + HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( + ICorDebugStepper * This, + /* [in] */ CorDebugUnmappedStop mask); + + HRESULT ( STDMETHODCALLTYPE *Step )( + ICorDebugStepper * This, + /* [in] */ BOOL bStepIn); + + HRESULT ( STDMETHODCALLTYPE *StepRange )( + ICorDebugStepper * This, + /* [in] */ BOOL bStepIn, + /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], + /* [in] */ ULONG32 cRangeCount); + + HRESULT ( STDMETHODCALLTYPE *StepOut )( + ICorDebugStepper * This); + + HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( + ICorDebugStepper * This, + /* [in] */ BOOL bIL); + + END_INTERFACE + } ICorDebugStepperVtbl; + + interface ICorDebugStepper + { + CONST_VTBL struct ICorDebugStepperVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStepper_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStepper_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStepper_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStepper_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + +#define ICorDebugStepper_Deactivate(This) \ + ( (This)->lpVtbl -> Deactivate(This) ) + +#define ICorDebugStepper_SetInterceptMask(This,mask) \ + ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) + +#define ICorDebugStepper_SetUnmappedStopMask(This,mask) \ + ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) + +#define ICorDebugStepper_Step(This,bStepIn) \ + ( (This)->lpVtbl -> Step(This,bStepIn) ) + +#define ICorDebugStepper_StepRange(This,bStepIn,ranges,cRangeCount) \ + ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) + +#define ICorDebugStepper_StepOut(This) \ + ( (This)->lpVtbl -> StepOut(This) ) + +#define ICorDebugStepper_SetRangeIL(This,bIL) \ + ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStepper_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugStepper2_INTERFACE_DEFINED__ +#define __ICorDebugStepper2_INTERFACE_DEFINED__ + +/* interface ICorDebugStepper2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugStepper2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7") + ICorDebugStepper2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetJMC( + /* [in] */ BOOL fIsJMCStepper) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStepper2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStepper2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStepper2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStepper2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetJMC )( + ICorDebugStepper2 * This, + /* [in] */ BOOL fIsJMCStepper); + + END_INTERFACE + } ICorDebugStepper2Vtbl; + + interface ICorDebugStepper2 + { + CONST_VTBL struct ICorDebugStepper2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStepper2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStepper2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStepper2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStepper2_SetJMC(This,fIsJMCStepper) \ + ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStepper2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugRegisterSet_INTERFACE_DEFINED__ +#define __ICorDebugRegisterSet_INTERFACE_DEFINED__ + +/* interface ICorDebugRegisterSet */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugRegister + { + REGISTER_INSTRUCTION_POINTER = 0, + REGISTER_STACK_POINTER = ( REGISTER_INSTRUCTION_POINTER + 1 ) , + REGISTER_FRAME_POINTER = ( REGISTER_STACK_POINTER + 1 ) , + REGISTER_X86_EIP = 0, + REGISTER_X86_ESP = ( REGISTER_X86_EIP + 1 ) , + REGISTER_X86_EBP = ( REGISTER_X86_ESP + 1 ) , + REGISTER_X86_EAX = ( REGISTER_X86_EBP + 1 ) , + REGISTER_X86_ECX = ( REGISTER_X86_EAX + 1 ) , + REGISTER_X86_EDX = ( REGISTER_X86_ECX + 1 ) , + REGISTER_X86_EBX = ( REGISTER_X86_EDX + 1 ) , + REGISTER_X86_ESI = ( REGISTER_X86_EBX + 1 ) , + REGISTER_X86_EDI = ( REGISTER_X86_ESI + 1 ) , + REGISTER_X86_FPSTACK_0 = ( REGISTER_X86_EDI + 1 ) , + REGISTER_X86_FPSTACK_1 = ( REGISTER_X86_FPSTACK_0 + 1 ) , + REGISTER_X86_FPSTACK_2 = ( REGISTER_X86_FPSTACK_1 + 1 ) , + REGISTER_X86_FPSTACK_3 = ( REGISTER_X86_FPSTACK_2 + 1 ) , + REGISTER_X86_FPSTACK_4 = ( REGISTER_X86_FPSTACK_3 + 1 ) , + REGISTER_X86_FPSTACK_5 = ( REGISTER_X86_FPSTACK_4 + 1 ) , + REGISTER_X86_FPSTACK_6 = ( REGISTER_X86_FPSTACK_5 + 1 ) , + REGISTER_X86_FPSTACK_7 = ( REGISTER_X86_FPSTACK_6 + 1 ) , + REGISTER_AMD64_RIP = 0, + REGISTER_AMD64_RSP = ( REGISTER_AMD64_RIP + 1 ) , + REGISTER_AMD64_RBP = ( REGISTER_AMD64_RSP + 1 ) , + REGISTER_AMD64_RAX = ( REGISTER_AMD64_RBP + 1 ) , + REGISTER_AMD64_RCX = ( REGISTER_AMD64_RAX + 1 ) , + REGISTER_AMD64_RDX = ( REGISTER_AMD64_RCX + 1 ) , + REGISTER_AMD64_RBX = ( REGISTER_AMD64_RDX + 1 ) , + REGISTER_AMD64_RSI = ( REGISTER_AMD64_RBX + 1 ) , + REGISTER_AMD64_RDI = ( REGISTER_AMD64_RSI + 1 ) , + REGISTER_AMD64_R8 = ( REGISTER_AMD64_RDI + 1 ) , + REGISTER_AMD64_R9 = ( REGISTER_AMD64_R8 + 1 ) , + REGISTER_AMD64_R10 = ( REGISTER_AMD64_R9 + 1 ) , + REGISTER_AMD64_R11 = ( REGISTER_AMD64_R10 + 1 ) , + REGISTER_AMD64_R12 = ( REGISTER_AMD64_R11 + 1 ) , + REGISTER_AMD64_R13 = ( REGISTER_AMD64_R12 + 1 ) , + REGISTER_AMD64_R14 = ( REGISTER_AMD64_R13 + 1 ) , + REGISTER_AMD64_R15 = ( REGISTER_AMD64_R14 + 1 ) , + REGISTER_AMD64_XMM0 = ( REGISTER_AMD64_R15 + 1 ) , + REGISTER_AMD64_XMM1 = ( REGISTER_AMD64_XMM0 + 1 ) , + REGISTER_AMD64_XMM2 = ( REGISTER_AMD64_XMM1 + 1 ) , + REGISTER_AMD64_XMM3 = ( REGISTER_AMD64_XMM2 + 1 ) , + REGISTER_AMD64_XMM4 = ( REGISTER_AMD64_XMM3 + 1 ) , + REGISTER_AMD64_XMM5 = ( REGISTER_AMD64_XMM4 + 1 ) , + REGISTER_AMD64_XMM6 = ( REGISTER_AMD64_XMM5 + 1 ) , + REGISTER_AMD64_XMM7 = ( REGISTER_AMD64_XMM6 + 1 ) , + REGISTER_AMD64_XMM8 = ( REGISTER_AMD64_XMM7 + 1 ) , + REGISTER_AMD64_XMM9 = ( REGISTER_AMD64_XMM8 + 1 ) , + REGISTER_AMD64_XMM10 = ( REGISTER_AMD64_XMM9 + 1 ) , + REGISTER_AMD64_XMM11 = ( REGISTER_AMD64_XMM10 + 1 ) , + REGISTER_AMD64_XMM12 = ( REGISTER_AMD64_XMM11 + 1 ) , + REGISTER_AMD64_XMM13 = ( REGISTER_AMD64_XMM12 + 1 ) , + REGISTER_AMD64_XMM14 = ( REGISTER_AMD64_XMM13 + 1 ) , + REGISTER_AMD64_XMM15 = ( REGISTER_AMD64_XMM14 + 1 ) , + REGISTER_IA64_BSP = REGISTER_FRAME_POINTER, + REGISTER_IA64_R0 = ( REGISTER_IA64_BSP + 1 ) , + REGISTER_IA64_F0 = ( REGISTER_IA64_R0 + 128 ) , + REGISTER_ARM_PC = 0, + REGISTER_ARM_SP = ( REGISTER_ARM_PC + 1 ) , + REGISTER_ARM_R0 = ( REGISTER_ARM_SP + 1 ) , + REGISTER_ARM_R1 = ( REGISTER_ARM_R0 + 1 ) , + REGISTER_ARM_R2 = ( REGISTER_ARM_R1 + 1 ) , + REGISTER_ARM_R3 = ( REGISTER_ARM_R2 + 1 ) , + REGISTER_ARM_R4 = ( REGISTER_ARM_R3 + 1 ) , + REGISTER_ARM_R5 = ( REGISTER_ARM_R4 + 1 ) , + REGISTER_ARM_R6 = ( REGISTER_ARM_R5 + 1 ) , + REGISTER_ARM_R7 = ( REGISTER_ARM_R6 + 1 ) , + REGISTER_ARM_R8 = ( REGISTER_ARM_R7 + 1 ) , + REGISTER_ARM_R9 = ( REGISTER_ARM_R8 + 1 ) , + REGISTER_ARM_R10 = ( REGISTER_ARM_R9 + 1 ) , + REGISTER_ARM_R11 = ( REGISTER_ARM_R10 + 1 ) , + REGISTER_ARM_R12 = ( REGISTER_ARM_R11 + 1 ) , + REGISTER_ARM_LR = ( REGISTER_ARM_R12 + 1 ) , + REGISTER_ARM_D0 = ( REGISTER_ARM_LR + 1 ) , + REGISTER_ARM_D1 = ( REGISTER_ARM_D0 + 1 ) , + REGISTER_ARM_D2 = ( REGISTER_ARM_D1 + 1 ) , + REGISTER_ARM_D3 = ( REGISTER_ARM_D2 + 1 ) , + REGISTER_ARM_D4 = ( REGISTER_ARM_D3 + 1 ) , + REGISTER_ARM_D5 = ( REGISTER_ARM_D4 + 1 ) , + REGISTER_ARM_D6 = ( REGISTER_ARM_D5 + 1 ) , + REGISTER_ARM_D7 = ( REGISTER_ARM_D6 + 1 ) , + REGISTER_ARM_D8 = ( REGISTER_ARM_D7 + 1 ) , + REGISTER_ARM_D9 = ( REGISTER_ARM_D8 + 1 ) , + REGISTER_ARM_D10 = ( REGISTER_ARM_D9 + 1 ) , + REGISTER_ARM_D11 = ( REGISTER_ARM_D10 + 1 ) , + REGISTER_ARM_D12 = ( REGISTER_ARM_D11 + 1 ) , + REGISTER_ARM_D13 = ( REGISTER_ARM_D12 + 1 ) , + REGISTER_ARM_D14 = ( REGISTER_ARM_D13 + 1 ) , + REGISTER_ARM_D15 = ( REGISTER_ARM_D14 + 1 ) , + REGISTER_ARM_D16 = ( REGISTER_ARM_D15 + 1 ) , + REGISTER_ARM_D17 = ( REGISTER_ARM_D16 + 1 ) , + REGISTER_ARM_D18 = ( REGISTER_ARM_D17 + 1 ) , + REGISTER_ARM_D19 = ( REGISTER_ARM_D18 + 1 ) , + REGISTER_ARM_D20 = ( REGISTER_ARM_D19 + 1 ) , + REGISTER_ARM_D21 = ( REGISTER_ARM_D20 + 1 ) , + REGISTER_ARM_D22 = ( REGISTER_ARM_D21 + 1 ) , + REGISTER_ARM_D23 = ( REGISTER_ARM_D22 + 1 ) , + REGISTER_ARM_D24 = ( REGISTER_ARM_D23 + 1 ) , + REGISTER_ARM_D25 = ( REGISTER_ARM_D24 + 1 ) , + REGISTER_ARM_D26 = ( REGISTER_ARM_D25 + 1 ) , + REGISTER_ARM_D27 = ( REGISTER_ARM_D26 + 1 ) , + REGISTER_ARM_D28 = ( REGISTER_ARM_D27 + 1 ) , + REGISTER_ARM_D29 = ( REGISTER_ARM_D28 + 1 ) , + REGISTER_ARM_D30 = ( REGISTER_ARM_D29 + 1 ) , + REGISTER_ARM_D31 = ( REGISTER_ARM_D30 + 1 ) , + REGISTER_ARM64_PC = 0, + REGISTER_ARM64_SP = ( REGISTER_ARM64_PC + 1 ) , + REGISTER_ARM64_FP = ( REGISTER_ARM64_SP + 1 ) , + REGISTER_ARM64_X0 = ( REGISTER_ARM64_FP + 1 ) , + REGISTER_ARM64_X1 = ( REGISTER_ARM64_X0 + 1 ) , + REGISTER_ARM64_X2 = ( REGISTER_ARM64_X1 + 1 ) , + REGISTER_ARM64_X3 = ( REGISTER_ARM64_X2 + 1 ) , + REGISTER_ARM64_X4 = ( REGISTER_ARM64_X3 + 1 ) , + REGISTER_ARM64_X5 = ( REGISTER_ARM64_X4 + 1 ) , + REGISTER_ARM64_X6 = ( REGISTER_ARM64_X5 + 1 ) , + REGISTER_ARM64_X7 = ( REGISTER_ARM64_X6 + 1 ) , + REGISTER_ARM64_X8 = ( REGISTER_ARM64_X7 + 1 ) , + REGISTER_ARM64_X9 = ( REGISTER_ARM64_X8 + 1 ) , + REGISTER_ARM64_X10 = ( REGISTER_ARM64_X9 + 1 ) , + REGISTER_ARM64_X11 = ( REGISTER_ARM64_X10 + 1 ) , + REGISTER_ARM64_X12 = ( REGISTER_ARM64_X11 + 1 ) , + REGISTER_ARM64_X13 = ( REGISTER_ARM64_X12 + 1 ) , + REGISTER_ARM64_X14 = ( REGISTER_ARM64_X13 + 1 ) , + REGISTER_ARM64_X15 = ( REGISTER_ARM64_X14 + 1 ) , + REGISTER_ARM64_X16 = ( REGISTER_ARM64_X15 + 1 ) , + REGISTER_ARM64_X17 = ( REGISTER_ARM64_X16 + 1 ) , + REGISTER_ARM64_X18 = ( REGISTER_ARM64_X17 + 1 ) , + REGISTER_ARM64_X19 = ( REGISTER_ARM64_X18 + 1 ) , + REGISTER_ARM64_X20 = ( REGISTER_ARM64_X19 + 1 ) , + REGISTER_ARM64_X21 = ( REGISTER_ARM64_X20 + 1 ) , + REGISTER_ARM64_X22 = ( REGISTER_ARM64_X21 + 1 ) , + REGISTER_ARM64_X23 = ( REGISTER_ARM64_X22 + 1 ) , + REGISTER_ARM64_X24 = ( REGISTER_ARM64_X23 + 1 ) , + REGISTER_ARM64_X25 = ( REGISTER_ARM64_X24 + 1 ) , + REGISTER_ARM64_X26 = ( REGISTER_ARM64_X25 + 1 ) , + REGISTER_ARM64_X27 = ( REGISTER_ARM64_X26 + 1 ) , + REGISTER_ARM64_X28 = ( REGISTER_ARM64_X27 + 1 ) , + REGISTER_ARM64_LR = ( REGISTER_ARM64_X28 + 1 ) , + REGISTER_ARM64_V0 = ( REGISTER_ARM64_LR + 1 ) , + REGISTER_ARM64_V1 = ( REGISTER_ARM64_V0 + 1 ) , + REGISTER_ARM64_V2 = ( REGISTER_ARM64_V1 + 1 ) , + REGISTER_ARM64_V3 = ( REGISTER_ARM64_V2 + 1 ) , + REGISTER_ARM64_V4 = ( REGISTER_ARM64_V3 + 1 ) , + REGISTER_ARM64_V5 = ( REGISTER_ARM64_V4 + 1 ) , + REGISTER_ARM64_V6 = ( REGISTER_ARM64_V5 + 1 ) , + REGISTER_ARM64_V7 = ( REGISTER_ARM64_V6 + 1 ) , + REGISTER_ARM64_V8 = ( REGISTER_ARM64_V7 + 1 ) , + REGISTER_ARM64_V9 = ( REGISTER_ARM64_V8 + 1 ) , + REGISTER_ARM64_V10 = ( REGISTER_ARM64_V9 + 1 ) , + REGISTER_ARM64_V11 = ( REGISTER_ARM64_V10 + 1 ) , + REGISTER_ARM64_V12 = ( REGISTER_ARM64_V11 + 1 ) , + REGISTER_ARM64_V13 = ( REGISTER_ARM64_V12 + 1 ) , + REGISTER_ARM64_V14 = ( REGISTER_ARM64_V13 + 1 ) , + REGISTER_ARM64_V15 = ( REGISTER_ARM64_V14 + 1 ) , + REGISTER_ARM64_V16 = ( REGISTER_ARM64_V15 + 1 ) , + REGISTER_ARM64_V17 = ( REGISTER_ARM64_V16 + 1 ) , + REGISTER_ARM64_V18 = ( REGISTER_ARM64_V17 + 1 ) , + REGISTER_ARM64_V19 = ( REGISTER_ARM64_V18 + 1 ) , + REGISTER_ARM64_V20 = ( REGISTER_ARM64_V19 + 1 ) , + REGISTER_ARM64_V21 = ( REGISTER_ARM64_V20 + 1 ) , + REGISTER_ARM64_V22 = ( REGISTER_ARM64_V21 + 1 ) , + REGISTER_ARM64_V23 = ( REGISTER_ARM64_V22 + 1 ) , + REGISTER_ARM64_V24 = ( REGISTER_ARM64_V23 + 1 ) , + REGISTER_ARM64_V25 = ( REGISTER_ARM64_V24 + 1 ) , + REGISTER_ARM64_V26 = ( REGISTER_ARM64_V25 + 1 ) , + REGISTER_ARM64_V27 = ( REGISTER_ARM64_V26 + 1 ) , + REGISTER_ARM64_V28 = ( REGISTER_ARM64_V27 + 1 ) , + REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , + REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , + REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) + } CorDebugRegister; + + +EXTERN_C const IID IID_ICorDebugRegisterSet; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB0B-8A68-11d2-983C-0000F808342D") + ICorDebugRegisterSet : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + /* [out] */ ULONG64 *pAvailable) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( + /* [in] */ ULONG64 mask, + /* [in] */ ULONG32 regCount, + /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( + /* [in] */ ULONG64 mask, + /* [in] */ ULONG32 regCount, + /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetThreadContext( + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][in] */ BYTE context[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugRegisterSetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugRegisterSet * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugRegisterSet * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugRegisterSet * This); + + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + ICorDebugRegisterSet * This, + /* [out] */ ULONG64 *pAvailable); + + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + ICorDebugRegisterSet * This, + /* [in] */ ULONG64 mask, + /* [in] */ ULONG32 regCount, + /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + ICorDebugRegisterSet * This, + /* [in] */ ULONG64 mask, + /* [in] */ ULONG32 regCount, + /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorDebugRegisterSet * This, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][out][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + ICorDebugRegisterSet * This, + /* [in] */ ULONG32 contextSize, + /* [size_is][length_is][in] */ BYTE context[ ]); + + END_INTERFACE + } ICorDebugRegisterSetVtbl; + + interface ICorDebugRegisterSet + { + CONST_VTBL struct ICorDebugRegisterSetVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugRegisterSet_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugRegisterSet_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugRegisterSet_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugRegisterSet_GetRegistersAvailable(This,pAvailable) \ + ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) + +#define ICorDebugRegisterSet_GetRegisters(This,mask,regCount,regBuffer) \ + ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) + +#define ICorDebugRegisterSet_SetRegisters(This,mask,regCount,regBuffer) \ + ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) + +#define ICorDebugRegisterSet_GetThreadContext(This,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) + +#define ICorDebugRegisterSet_SetThreadContext(This,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugRegisterSet_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugRegisterSet2_INTERFACE_DEFINED__ +#define __ICorDebugRegisterSet2_INTERFACE_DEFINED__ + +/* interface ICorDebugRegisterSet2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugRegisterSet2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6DC7BA3F-89BA-4459-9EC1-9D60937B468D") + ICorDebugRegisterSet2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( + /* [in] */ ULONG32 numChunks, + /* [size_is][out] */ BYTE availableRegChunks[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisters( + /* [in] */ ULONG32 maskCount, + /* [size_is][in] */ BYTE mask[ ], + /* [in] */ ULONG32 regCount, + /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetRegisters( + /* [in] */ ULONG32 maskCount, + /* [size_is][in] */ BYTE mask[ ], + /* [in] */ ULONG32 regCount, + /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugRegisterSet2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugRegisterSet2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugRegisterSet2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugRegisterSet2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( + ICorDebugRegisterSet2 * This, + /* [in] */ ULONG32 numChunks, + /* [size_is][out] */ BYTE availableRegChunks[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetRegisters )( + ICorDebugRegisterSet2 * This, + /* [in] */ ULONG32 maskCount, + /* [size_is][in] */ BYTE mask[ ], + /* [in] */ ULONG32 regCount, + /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetRegisters )( + ICorDebugRegisterSet2 * This, + /* [in] */ ULONG32 maskCount, + /* [size_is][in] */ BYTE mask[ ], + /* [in] */ ULONG32 regCount, + /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); + + END_INTERFACE + } ICorDebugRegisterSet2Vtbl; + + interface ICorDebugRegisterSet2 + { + CONST_VTBL struct ICorDebugRegisterSet2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugRegisterSet2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugRegisterSet2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugRegisterSet2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugRegisterSet2_GetRegistersAvailable(This,numChunks,availableRegChunks) \ + ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) + +#define ICorDebugRegisterSet2_GetRegisters(This,maskCount,mask,regCount,regBuffer) \ + ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) + +#define ICorDebugRegisterSet2_SetRegisters(This,maskCount,mask,regCount,regBuffer) \ + ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugRegisterSet2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugThread_INTERFACE_DEFINED__ +#define __ICorDebugThread_INTERFACE_DEFINED__ + +/* interface ICorDebugThread */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugUserState + { + USER_STOP_REQUESTED = 0x1, + USER_SUSPEND_REQUESTED = 0x2, + USER_BACKGROUND = 0x4, + USER_UNSTARTED = 0x8, + USER_STOPPED = 0x10, + USER_WAIT_SLEEP_JOIN = 0x20, + USER_SUSPENDED = 0x40, + USER_UNSAFE_POINT = 0x80, + USER_THREADPOOL = 0x100 + } CorDebugUserState; + + +EXTERN_C const IID IID_ICorDebugThread; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("938c6d66-7fb6-4f69-b389-425b8987329b") + ICorDebugThread : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetID( + /* [out] */ DWORD *pdwThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandle( + /* [out] */ HTHREAD *phThreadHandle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDebugState( + /* [in] */ CorDebugThreadState state) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDebugState( + /* [out] */ CorDebugThreadState *pState) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUserState( + /* [out] */ CorDebugUserState *pState) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentException( + /* [out] */ ICorDebugValue **ppExceptionObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( + /* [out] */ ICorDebugStepper **ppStepper) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateChains( + /* [out] */ ICorDebugChainEnum **ppChains) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetActiveChain( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + /* [out] */ ICorDebugFrame **ppFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateEval( + /* [out] */ ICorDebugEval **ppEval) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObject( + /* [out] */ ICorDebugValue **ppObject) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThreadVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThread * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThread * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThread * This); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorDebugThread * This, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *GetID )( + ICorDebugThread * This, + /* [out] */ DWORD *pdwThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetHandle )( + ICorDebugThread * This, + /* [out] */ HTHREAD *phThreadHandle); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + ICorDebugThread * This, + /* [out] */ ICorDebugAppDomain **ppAppDomain); + + HRESULT ( STDMETHODCALLTYPE *SetDebugState )( + ICorDebugThread * This, + /* [in] */ CorDebugThreadState state); + + HRESULT ( STDMETHODCALLTYPE *GetDebugState )( + ICorDebugThread * This, + /* [out] */ CorDebugThreadState *pState); + + HRESULT ( STDMETHODCALLTYPE *GetUserState )( + ICorDebugThread * This, + /* [out] */ CorDebugUserState *pState); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( + ICorDebugThread * This, + /* [out] */ ICorDebugValue **ppExceptionObject); + + HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( + ICorDebugThread * This); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugThread * This, + /* [out] */ ICorDebugStepper **ppStepper); + + HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( + ICorDebugThread * This, + /* [out] */ ICorDebugChainEnum **ppChains); + + HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( + ICorDebugThread * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + ICorDebugThread * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + ICorDebugThread * This, + /* [out] */ ICorDebugRegisterSet **ppRegisters); + + HRESULT ( STDMETHODCALLTYPE *CreateEval )( + ICorDebugThread * This, + /* [out] */ ICorDebugEval **ppEval); + + HRESULT ( STDMETHODCALLTYPE *GetObject )( + ICorDebugThread * This, + /* [out] */ ICorDebugValue **ppObject); + + END_INTERFACE + } ICorDebugThreadVtbl; + + interface ICorDebugThread + { + CONST_VTBL struct ICorDebugThreadVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThread_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThread_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThread_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThread_GetProcess(This,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + +#define ICorDebugThread_GetID(This,pdwThreadId) \ + ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) + +#define ICorDebugThread_GetHandle(This,phThreadHandle) \ + ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) + +#define ICorDebugThread_GetAppDomain(This,ppAppDomain) \ + ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) + +#define ICorDebugThread_SetDebugState(This,state) \ + ( (This)->lpVtbl -> SetDebugState(This,state) ) + +#define ICorDebugThread_GetDebugState(This,pState) \ + ( (This)->lpVtbl -> GetDebugState(This,pState) ) + +#define ICorDebugThread_GetUserState(This,pState) \ + ( (This)->lpVtbl -> GetUserState(This,pState) ) + +#define ICorDebugThread_GetCurrentException(This,ppExceptionObject) \ + ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) + +#define ICorDebugThread_ClearCurrentException(This) \ + ( (This)->lpVtbl -> ClearCurrentException(This) ) + +#define ICorDebugThread_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + +#define ICorDebugThread_EnumerateChains(This,ppChains) \ + ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) + +#define ICorDebugThread_GetActiveChain(This,ppChain) \ + ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) + +#define ICorDebugThread_GetActiveFrame(This,ppFrame) \ + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + +#define ICorDebugThread_GetRegisterSet(This,ppRegisters) \ + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + +#define ICorDebugThread_CreateEval(This,ppEval) \ + ( (This)->lpVtbl -> CreateEval(This,ppEval) ) + +#define ICorDebugThread_GetObject(This,ppObject) \ + ( (This)->lpVtbl -> GetObject(This,ppObject) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThread_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugThread2_INTERFACE_DEFINED__ +#define __ICorDebugThread2_INTERFACE_DEFINED__ + +/* interface ICorDebugThread2 */ +/* [unique][uuid][local][object] */ + +typedef struct _COR_ACTIVE_FUNCTION + { + ICorDebugAppDomain *pAppDomain; + ICorDebugModule *pModule; + ICorDebugFunction2 *pFunction; + ULONG32 ilOffset; + ULONG32 flags; + } COR_ACTIVE_FUNCTION; + + +EXTERN_C const IID IID_ICorDebugThread2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2BD956D9-7B07-4bef-8A98-12AA862417C5") + ICorDebugThread2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( + /* [in] */ ULONG32 cFunctions, + /* [out] */ ULONG32 *pcFunctions, + /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetConnectionID( + /* [out] */ CONNID *pdwConnectionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTaskID( + /* [out] */ TASKID *pTaskId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( + /* [out] */ DWORD *pdwTid) = 0; + + virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( + /* [in] */ ICorDebugFrame *pFrame) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThread2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThread2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThread2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThread2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( + ICorDebugThread2 * This, + /* [in] */ ULONG32 cFunctions, + /* [out] */ ULONG32 *pcFunctions, + /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( + ICorDebugThread2 * This, + /* [out] */ CONNID *pdwConnectionId); + + HRESULT ( STDMETHODCALLTYPE *GetTaskID )( + ICorDebugThread2 * This, + /* [out] */ TASKID *pTaskId); + + HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( + ICorDebugThread2 * This, + /* [out] */ DWORD *pdwTid); + + HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( + ICorDebugThread2 * This, + /* [in] */ ICorDebugFrame *pFrame); + + END_INTERFACE + } ICorDebugThread2Vtbl; + + interface ICorDebugThread2 + { + CONST_VTBL struct ICorDebugThread2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThread2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThread2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThread2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThread2_GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) \ + ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) + +#define ICorDebugThread2_GetConnectionID(This,pdwConnectionId) \ + ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) + +#define ICorDebugThread2_GetTaskID(This,pTaskId) \ + ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) + +#define ICorDebugThread2_GetVolatileOSThreadID(This,pdwTid) \ + ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) + +#define ICorDebugThread2_InterceptCurrentException(This,pFrame) \ + ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThread2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugThread3_INTERFACE_DEFINED__ +#define __ICorDebugThread3_INTERFACE_DEFINED__ + +/* interface ICorDebugThread3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugThread3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5") + ICorDebugThread3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( + /* [out] */ ICorDebugStackWalk **ppStackWalk) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( + /* [in] */ ULONG32 cInternalFrames, + /* [out] */ ULONG32 *pcInternalFrames, + /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThread3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThread3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThread3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThread3 * This); + + HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( + ICorDebugThread3 * This, + /* [out] */ ICorDebugStackWalk **ppStackWalk); + + HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( + ICorDebugThread3 * This, + /* [in] */ ULONG32 cInternalFrames, + /* [out] */ ULONG32 *pcInternalFrames, + /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]); + + END_INTERFACE + } ICorDebugThread3Vtbl; + + interface ICorDebugThread3 + { + CONST_VTBL struct ICorDebugThread3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThread3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThread3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThread3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThread3_CreateStackWalk(This,ppStackWalk) \ + ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) + +#define ICorDebugThread3_GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) \ + ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThread3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugThread4_INTERFACE_DEFINED__ +#define __ICorDebugThread4_INTERFACE_DEFINED__ + +/* interface ICorDebugThread4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugThread4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1A1F204B-1C66-4637-823F-3EE6C744A69C") + ICorDebugThread4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE HasUnhandledException( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( + /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( + /* [out] */ ICorDebugValue **ppNotificationObject) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThread4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThread4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThread4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThread4 * This); + + HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( + ICorDebugThread4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( + ICorDebugThread4 * This, + /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( + ICorDebugThread4 * This, + /* [out] */ ICorDebugValue **ppNotificationObject); + + END_INTERFACE + } ICorDebugThread4Vtbl; + + interface ICorDebugThread4 + { + CONST_VTBL struct ICorDebugThread4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThread4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThread4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThread4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThread4_HasUnhandledException(This) \ + ( (This)->lpVtbl -> HasUnhandledException(This) ) + +#define ICorDebugThread4_GetBlockingObjects(This,ppBlockingObjectEnum) \ + ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) + +#define ICorDebugThread4_GetCurrentCustomDebuggerNotification(This,ppNotificationObject) \ + ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThread4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugStackWalk_INTERFACE_DEFINED__ +#define __ICorDebugStackWalk_INTERFACE_DEFINED__ + +/* interface ICorDebugStackWalk */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugSetContextFlag + { + SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, + SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2 + } CorDebugSetContextFlag; + + +EXTERN_C const IID IID_ICorDebugStackWalk; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A0647DE9-55DE-4816-929C-385271C64CF7") + ICorDebugStackWalk : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContext( + /* [in] */ CorDebugSetContextFlag flag, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFrame( + /* [out] */ ICorDebugFrame **pFrame) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStackWalkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStackWalk * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStackWalk * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStackWalk * This); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + ICorDebugStackWalk * This, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetContext )( + ICorDebugStackWalk * This, + /* [in] */ CorDebugSetContextFlag flag, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugStackWalk * This); + + HRESULT ( STDMETHODCALLTYPE *GetFrame )( + ICorDebugStackWalk * This, + /* [out] */ ICorDebugFrame **pFrame); + + END_INTERFACE + } ICorDebugStackWalkVtbl; + + interface ICorDebugStackWalk + { + CONST_VTBL struct ICorDebugStackWalkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStackWalk_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStackWalk_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStackWalk_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + +#define ICorDebugStackWalk_SetContext(This,flag,contextSize,context) \ + ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) + +#define ICorDebugStackWalk_Next(This) \ + ( (This)->lpVtbl -> Next(This) ) + +#define ICorDebugStackWalk_GetFrame(This,pFrame) \ + ( (This)->lpVtbl -> GetFrame(This,pFrame) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStackWalk_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugChain_INTERFACE_DEFINED__ +#define __ICorDebugChain_INTERFACE_DEFINED__ + +/* interface ICorDebugChain */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugChainReason + { + CHAIN_NONE = 0, + CHAIN_CLASS_INIT = 0x1, + CHAIN_EXCEPTION_FILTER = 0x2, + CHAIN_SECURITY = 0x4, + CHAIN_CONTEXT_POLICY = 0x8, + CHAIN_INTERCEPTION = 0x10, + CHAIN_PROCESS_START = 0x20, + CHAIN_THREAD_START = 0x40, + CHAIN_ENTER_MANAGED = 0x80, + CHAIN_ENTER_UNMANAGED = 0x100, + CHAIN_DEBUGGER_EVAL = 0x200, + CHAIN_CONTEXT_SWITCH = 0x400, + CHAIN_FUNC_EVAL = 0x800 + } CorDebugChainReason; + + +EXTERN_C const IID IID_ICorDebugChain; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAEE-8A68-11d2-983C-0000F808342D") + ICorDebugChain : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetThread( + /* [out] */ ICorDebugThread **ppThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [out] */ ICorDebugContext **ppContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCaller( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCallee( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPrevious( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNext( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsManaged( + /* [out] */ BOOL *pManaged) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( + /* [out] */ ICorDebugFrameEnum **ppFrames) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( + /* [out] */ ICorDebugFrame **ppFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReason( + /* [out] */ CorDebugChainReason *pReason) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugChainVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugChain * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugChain * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugChain * This); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugChain * This, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugChain * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + ICorDebugChain * This, + /* [out] */ ICorDebugContext **ppContext); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugChain * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugChain * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetPrevious )( + ICorDebugChain * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetNext )( + ICorDebugChain * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *IsManaged )( + ICorDebugChain * This, + /* [out] */ BOOL *pManaged); + + HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( + ICorDebugChain * This, + /* [out] */ ICorDebugFrameEnum **ppFrames); + + HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( + ICorDebugChain * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + ICorDebugChain * This, + /* [out] */ ICorDebugRegisterSet **ppRegisters); + + HRESULT ( STDMETHODCALLTYPE *GetReason )( + ICorDebugChain * This, + /* [out] */ CorDebugChainReason *pReason); + + END_INTERFACE + } ICorDebugChainVtbl; + + interface ICorDebugChain + { + CONST_VTBL struct ICorDebugChainVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugChain_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugChain_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugChain_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugChain_GetThread(This,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,ppThread) ) + +#define ICorDebugChain_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugChain_GetContext(This,ppContext) \ + ( (This)->lpVtbl -> GetContext(This,ppContext) ) + +#define ICorDebugChain_GetCaller(This,ppChain) \ + ( (This)->lpVtbl -> GetCaller(This,ppChain) ) + +#define ICorDebugChain_GetCallee(This,ppChain) \ + ( (This)->lpVtbl -> GetCallee(This,ppChain) ) + +#define ICorDebugChain_GetPrevious(This,ppChain) \ + ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) + +#define ICorDebugChain_GetNext(This,ppChain) \ + ( (This)->lpVtbl -> GetNext(This,ppChain) ) + +#define ICorDebugChain_IsManaged(This,pManaged) \ + ( (This)->lpVtbl -> IsManaged(This,pManaged) ) + +#define ICorDebugChain_EnumerateFrames(This,ppFrames) \ + ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) + +#define ICorDebugChain_GetActiveFrame(This,ppFrame) \ + ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) + +#define ICorDebugChain_GetRegisterSet(This,ppRegisters) \ + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + +#define ICorDebugChain_GetReason(This,pReason) \ + ( (This)->lpVtbl -> GetReason(This,pReason) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugChain_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFrame_INTERFACE_DEFINED__ +#define __ICorDebugFrame_INTERFACE_DEFINED__ + +/* interface ICorDebugFrame */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAEF-8A68-11d2-983C-0000F808342D") + ICorDebugFrame : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetChain( + /* [out] */ ICorDebugChain **ppChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunction( + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( + /* [out] */ mdMethodDef *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackRange( + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCaller( + /* [out] */ ICorDebugFrame **ppFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCallee( + /* [out] */ ICorDebugFrame **ppFrame) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStepper( + /* [out] */ ICorDebugStepper **ppStepper) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetChain )( + ICorDebugFrame * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugFrame * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugFrame * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + ICorDebugFrame * This, + /* [out] */ mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugFrame * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugFrame * This, + /* [out] */ ICorDebugStepper **ppStepper); + + END_INTERFACE + } ICorDebugFrameVtbl; + + interface ICorDebugFrame + { + CONST_VTBL struct ICorDebugFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFrame_GetChain(This,ppChain) \ + ( (This)->lpVtbl -> GetChain(This,ppChain) ) + +#define ICorDebugFrame_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugFrame_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugFrame_GetFunctionToken(This,pToken) \ + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + +#define ICorDebugFrame_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugFrame_GetCaller(This,ppFrame) \ + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + +#define ICorDebugFrame_GetCallee(This,ppFrame) \ + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + +#define ICorDebugFrame_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFrame_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame_INTERFACE_DEFINED__ +#define __ICorDebugInternalFrame_INTERFACE_DEFINED__ + +/* interface ICorDebugInternalFrame */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugInternalFrameType + { + STUBFRAME_NONE = 0, + STUBFRAME_M2U = 0x1, + STUBFRAME_U2M = 0x2, + STUBFRAME_APPDOMAIN_TRANSITION = 0x3, + STUBFRAME_LIGHTWEIGHT_FUNCTION = 0x4, + STUBFRAME_FUNC_EVAL = 0x5, + STUBFRAME_INTERNALCALL = 0x6, + STUBFRAME_CLASS_INIT = 0x7, + STUBFRAME_EXCEPTION = 0x8, + STUBFRAME_SECURITY = 0x9, + STUBFRAME_JIT_COMPILATION = 0xa + } CorDebugInternalFrameType; + + +EXTERN_C const IID IID_ICorDebugInternalFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4") + ICorDebugInternalFrame : public ICorDebugFrame + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFrameType( + /* [out] */ CorDebugInternalFrameType *pType) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugInternalFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugInternalFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugInternalFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugInternalFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetChain )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + ICorDebugInternalFrame * This, + /* [out] */ mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugInternalFrame * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugInternalFrame * This, + /* [out] */ ICorDebugStepper **ppStepper); + + HRESULT ( STDMETHODCALLTYPE *GetFrameType )( + ICorDebugInternalFrame * This, + /* [out] */ CorDebugInternalFrameType *pType); + + END_INTERFACE + } ICorDebugInternalFrameVtbl; + + interface ICorDebugInternalFrame + { + CONST_VTBL struct ICorDebugInternalFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugInternalFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugInternalFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugInternalFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugInternalFrame_GetChain(This,ppChain) \ + ( (This)->lpVtbl -> GetChain(This,ppChain) ) + +#define ICorDebugInternalFrame_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugInternalFrame_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugInternalFrame_GetFunctionToken(This,pToken) \ + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + +#define ICorDebugInternalFrame_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugInternalFrame_GetCaller(This,ppFrame) \ + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + +#define ICorDebugInternalFrame_GetCallee(This,ppFrame) \ + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + +#define ICorDebugInternalFrame_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + + +#define ICorDebugInternalFrame_GetFrameType(This,pType) \ + ( (This)->lpVtbl -> GetFrameType(This,pType) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugInternalFrame_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugInternalFrame2_INTERFACE_DEFINED__ +#define __ICorDebugInternalFrame2_INTERFACE_DEFINED__ + +/* interface ICorDebugInternalFrame2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugInternalFrame2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C0815BDC-CFAB-447e-A779-C116B454EB5B") + ICorDebugInternalFrame2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAddress( + /* [out] */ CORDB_ADDRESS *pAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( + /* [in] */ ICorDebugFrame *pFrameToCompare, + /* [out] */ BOOL *pIsCloser) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugInternalFrame2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugInternalFrame2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugInternalFrame2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugInternalFrame2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugInternalFrame2 * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( + ICorDebugInternalFrame2 * This, + /* [in] */ ICorDebugFrame *pFrameToCompare, + /* [out] */ BOOL *pIsCloser); + + END_INTERFACE + } ICorDebugInternalFrame2Vtbl; + + interface ICorDebugInternalFrame2 + { + CONST_VTBL struct ICorDebugInternalFrame2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugInternalFrame2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugInternalFrame2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugInternalFrame2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugInternalFrame2_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugInternalFrame2_IsCloserToLeaf(This,pFrameToCompare,pIsCloser) \ + ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugInternalFrame2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugILFrame_INTERFACE_DEFINED__ +#define __ICorDebugILFrame_INTERFACE_DEFINED__ + +/* interface ICorDebugILFrame */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugMappingResult + { + MAPPING_PROLOG = 0x1, + MAPPING_EPILOG = 0x2, + MAPPING_NO_INFO = 0x4, + MAPPING_UNMAPPED_ADDRESS = 0x8, + MAPPING_EXACT = 0x10, + MAPPING_APPROXIMATE = 0x20 + } CorDebugMappingResult; + + +EXTERN_C const IID IID_ICorDebugILFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("03E26311-4F76-11d3-88C6-006097945418") + ICorDebugILFrame : public ICorDebugFrame + { + public: + virtual HRESULT STDMETHODCALLTYPE GetIP( + /* [out] */ ULONG32 *pnOffset, + /* [out] */ CorDebugMappingResult *pMappingResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetIP( + /* [in] */ ULONG32 nOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( + /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( + /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgument( + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackDepth( + /* [out] */ ULONG32 *pDepth) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackValue( + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( + /* [in] */ ULONG32 nOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetChain )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + ICorDebugILFrame * This, + /* [out] */ mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugILFrame * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugStepper **ppStepper); + + HRESULT ( STDMETHODCALLTYPE *GetIP )( + ICorDebugILFrame * This, + /* [out] */ ULONG32 *pnOffset, + /* [out] */ CorDebugMappingResult *pMappingResult); + + HRESULT ( STDMETHODCALLTYPE *SetIP )( + ICorDebugILFrame * This, + /* [in] */ ULONG32 nOffset); + + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugValueEnum **ppValueEnum); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( + ICorDebugILFrame * This, + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( + ICorDebugILFrame * This, + /* [out] */ ICorDebugValueEnum **ppValueEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArgument )( + ICorDebugILFrame * This, + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( + ICorDebugILFrame * This, + /* [out] */ ULONG32 *pDepth); + + HRESULT ( STDMETHODCALLTYPE *GetStackValue )( + ICorDebugILFrame * This, + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + ICorDebugILFrame * This, + /* [in] */ ULONG32 nOffset); + + END_INTERFACE + } ICorDebugILFrameVtbl; + + interface ICorDebugILFrame + { + CONST_VTBL struct ICorDebugILFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILFrame_GetChain(This,ppChain) \ + ( (This)->lpVtbl -> GetChain(This,ppChain) ) + +#define ICorDebugILFrame_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugILFrame_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugILFrame_GetFunctionToken(This,pToken) \ + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + +#define ICorDebugILFrame_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugILFrame_GetCaller(This,ppFrame) \ + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + +#define ICorDebugILFrame_GetCallee(This,ppFrame) \ + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + +#define ICorDebugILFrame_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + + +#define ICorDebugILFrame_GetIP(This,pnOffset,pMappingResult) \ + ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) + +#define ICorDebugILFrame_SetIP(This,nOffset) \ + ( (This)->lpVtbl -> SetIP(This,nOffset) ) + +#define ICorDebugILFrame_EnumerateLocalVariables(This,ppValueEnum) \ + ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) + +#define ICorDebugILFrame_GetLocalVariable(This,dwIndex,ppValue) \ + ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) + +#define ICorDebugILFrame_EnumerateArguments(This,ppValueEnum) \ + ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) + +#define ICorDebugILFrame_GetArgument(This,dwIndex,ppValue) \ + ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) + +#define ICorDebugILFrame_GetStackDepth(This,pDepth) \ + ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) + +#define ICorDebugILFrame_GetStackValue(This,dwIndex,ppValue) \ + ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) + +#define ICorDebugILFrame_CanSetIP(This,nOffset) \ + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILFrame_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugILFrame2_INTERFACE_DEFINED__ +#define __ICorDebugILFrame2_INTERFACE_DEFINED__ + +/* interface ICorDebugILFrame2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugILFrame2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5D88A994-6C30-479b-890F-BCEF88B129A5") + ICorDebugILFrame2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE RemapFunction( + /* [in] */ ULONG32 newILOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILFrame2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILFrame2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILFrame2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILFrame2 * This); + + HRESULT ( STDMETHODCALLTYPE *RemapFunction )( + ICorDebugILFrame2 * This, + /* [in] */ ULONG32 newILOffset); + + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + ICorDebugILFrame2 * This, + /* [out] */ ICorDebugTypeEnum **ppTyParEnum); + + END_INTERFACE + } ICorDebugILFrame2Vtbl; + + interface ICorDebugILFrame2 + { + CONST_VTBL struct ICorDebugILFrame2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILFrame2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILFrame2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILFrame2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILFrame2_RemapFunction(This,newILOffset) \ + ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) + +#define ICorDebugILFrame2_EnumerateTypeParameters(This,ppTyParEnum) \ + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILFrame2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugILFrame3_INTERFACE_DEFINED__ +#define __ICorDebugILFrame3_INTERFACE_DEFINED__ + +/* interface ICorDebugILFrame3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugILFrame3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24") + ICorDebugILFrame3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( + ULONG32 ILoffset, + /* [out] */ ICorDebugValue **ppReturnValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILFrame3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILFrame3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILFrame3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILFrame3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( + ICorDebugILFrame3 * This, + ULONG32 ILoffset, + /* [out] */ ICorDebugValue **ppReturnValue); + + END_INTERFACE + } ICorDebugILFrame3Vtbl; + + interface ICorDebugILFrame3 + { + CONST_VTBL struct ICorDebugILFrame3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILFrame3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILFrame3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILFrame3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILFrame3_GetReturnValueForILOffset(This,ILoffset,ppReturnValue) \ + ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILFrame3_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0067 */ +/* [local] */ + +typedef +enum ILCodeKind + { + ILCODE_ORIGINAL_IL = 0x1, + ILCODE_REJIT_IL = 0x2 + } ILCodeKind; + + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0067_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0067_v0_0_s_ifspec; + +#ifndef __ICorDebugILFrame4_INTERFACE_DEFINED__ +#define __ICorDebugILFrame4_INTERFACE_DEFINED__ + +/* interface ICorDebugILFrame4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugILFrame4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45") + ICorDebugILFrame4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( + /* [in] */ ILCodeKind flags, + /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( + /* [in] */ ILCodeKind flags, + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeEx( + /* [in] */ ILCodeKind flags, + /* [out] */ ICorDebugCode **ppCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILFrame4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILFrame4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILFrame4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILFrame4 * This); + + HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( + ICorDebugILFrame4 * This, + /* [in] */ ILCodeKind flags, + /* [out] */ ICorDebugValueEnum **ppValueEnum); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( + ICorDebugILFrame4 * This, + /* [in] */ ILCodeKind flags, + /* [in] */ DWORD dwIndex, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( + ICorDebugILFrame4 * This, + /* [in] */ ILCodeKind flags, + /* [out] */ ICorDebugCode **ppCode); + + END_INTERFACE + } ICorDebugILFrame4Vtbl; + + interface ICorDebugILFrame4 + { + CONST_VTBL struct ICorDebugILFrame4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILFrame4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILFrame4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILFrame4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILFrame4_EnumerateLocalVariablesEx(This,flags,ppValueEnum) \ + ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) + +#define ICorDebugILFrame4_GetLocalVariableEx(This,flags,dwIndex,ppValue) \ + ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) + +#define ICorDebugILFrame4_GetCodeEx(This,flags,ppCode) \ + ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILFrame4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugNativeFrame_INTERFACE_DEFINED__ +#define __ICorDebugNativeFrame_INTERFACE_DEFINED__ + +/* interface ICorDebugNativeFrame */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugNativeFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("03E26314-4F76-11d3-88C6-006097945418") + ICorDebugNativeFrame : public ICorDebugFrame + { + public: + virtual HRESULT STDMETHODCALLTYPE GetIP( + /* [out] */ ULONG32 *pnOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetIP( + /* [in] */ ULONG32 nOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( + /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( + /* [in] */ CorDebugRegister reg, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( + /* [in] */ CorDebugRegister highWordReg, + /* [in] */ CorDebugRegister lowWordReg, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( + /* [in] */ CORDB_ADDRESS address, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( + /* [in] */ CorDebugRegister highWordReg, + /* [in] */ CORDB_ADDRESS lowWordAddress, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( + /* [in] */ CORDB_ADDRESS highWordAddress, + /* [in] */ CorDebugRegister lowWordRegister, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanSetIP( + /* [in] */ ULONG32 nOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugNativeFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugNativeFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugNativeFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugNativeFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetChain )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + ICorDebugNativeFrame * This, + /* [out] */ mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugNativeFrame * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugStepper **ppStepper); + + HRESULT ( STDMETHODCALLTYPE *GetIP )( + ICorDebugNativeFrame * This, + /* [out] */ ULONG32 *pnOffset); + + HRESULT ( STDMETHODCALLTYPE *SetIP )( + ICorDebugNativeFrame * This, + /* [in] */ ULONG32 nOffset); + + HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( + ICorDebugNativeFrame * This, + /* [out] */ ICorDebugRegisterSet **ppRegisters); + + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( + ICorDebugNativeFrame * This, + /* [in] */ CorDebugRegister reg, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( + ICorDebugNativeFrame * This, + /* [in] */ CorDebugRegister highWordReg, + /* [in] */ CorDebugRegister lowWordReg, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( + ICorDebugNativeFrame * This, + /* [in] */ CORDB_ADDRESS address, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( + ICorDebugNativeFrame * This, + /* [in] */ CorDebugRegister highWordReg, + /* [in] */ CORDB_ADDRESS lowWordAddress, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( + ICorDebugNativeFrame * This, + /* [in] */ CORDB_ADDRESS highWordAddress, + /* [in] */ CorDebugRegister lowWordRegister, + /* [in] */ ULONG cbSigBlob, + /* [in] */ PCCOR_SIGNATURE pvSigBlob, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *CanSetIP )( + ICorDebugNativeFrame * This, + /* [in] */ ULONG32 nOffset); + + END_INTERFACE + } ICorDebugNativeFrameVtbl; + + interface ICorDebugNativeFrame + { + CONST_VTBL struct ICorDebugNativeFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugNativeFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugNativeFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugNativeFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugNativeFrame_GetChain(This,ppChain) \ + ( (This)->lpVtbl -> GetChain(This,ppChain) ) + +#define ICorDebugNativeFrame_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugNativeFrame_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugNativeFrame_GetFunctionToken(This,pToken) \ + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + +#define ICorDebugNativeFrame_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugNativeFrame_GetCaller(This,ppFrame) \ + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + +#define ICorDebugNativeFrame_GetCallee(This,ppFrame) \ + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + +#define ICorDebugNativeFrame_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + + +#define ICorDebugNativeFrame_GetIP(This,pnOffset) \ + ( (This)->lpVtbl -> GetIP(This,pnOffset) ) + +#define ICorDebugNativeFrame_SetIP(This,nOffset) \ + ( (This)->lpVtbl -> SetIP(This,nOffset) ) + +#define ICorDebugNativeFrame_GetRegisterSet(This,ppRegisters) \ + ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) + +#define ICorDebugNativeFrame_GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) \ + ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) + +#define ICorDebugNativeFrame_GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) \ + ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) + +#define ICorDebugNativeFrame_GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) \ + ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) + +#define ICorDebugNativeFrame_GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) \ + ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) + +#define ICorDebugNativeFrame_GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) \ + ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) + +#define ICorDebugNativeFrame_CanSetIP(This,nOffset) \ + ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugNativeFrame_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0069 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0069_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0069_v0_0_s_ifspec; + +#ifndef __ICorDebugNativeFrame2_INTERFACE_DEFINED__ +#define __ICorDebugNativeFrame2_INTERFACE_DEFINED__ + +/* interface ICorDebugNativeFrame2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugNativeFrame2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("35389FF1-3684-4c55-A2EE-210F26C60E5E") + ICorDebugNativeFrame2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsChild( + /* [out] */ BOOL *pIsChild) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( + /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, + /* [out] */ BOOL *pIsParent) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( + /* [out] */ ULONG32 *pSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugNativeFrame2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugNativeFrame2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugNativeFrame2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugNativeFrame2 * This); + + HRESULT ( STDMETHODCALLTYPE *IsChild )( + ICorDebugNativeFrame2 * This, + /* [out] */ BOOL *pIsChild); + + HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( + ICorDebugNativeFrame2 * This, + /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, + /* [out] */ BOOL *pIsParent); + + HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( + ICorDebugNativeFrame2 * This, + /* [out] */ ULONG32 *pSize); + + END_INTERFACE + } ICorDebugNativeFrame2Vtbl; + + interface ICorDebugNativeFrame2 + { + CONST_VTBL struct ICorDebugNativeFrame2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugNativeFrame2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugNativeFrame2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugNativeFrame2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugNativeFrame2_IsChild(This,pIsChild) \ + ( (This)->lpVtbl -> IsChild(This,pIsChild) ) + +#define ICorDebugNativeFrame2_IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) \ + ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) + +#define ICorDebugNativeFrame2_GetStackParameterSize(This,pSize) \ + ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugNativeFrame2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugModule3_INTERFACE_DEFINED__ +#define __ICorDebugModule3_INTERFACE_DEFINED__ + +/* interface ICorDebugModule3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModule3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("86F012BF-FF15-4372-BD30-B6F11CAAE1DD") + ICorDebugModule3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppObj) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModule3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModule3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModule3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModule3 * This); + + HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( + ICorDebugModule3 * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppObj); + + END_INTERFACE + } ICorDebugModule3Vtbl; + + interface ICorDebugModule3 + { + CONST_VTBL struct ICorDebugModule3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModule3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModule3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModule3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModule3_CreateReaderForInMemorySymbols(This,riid,ppObj) \ + ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModule3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ +#define __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ + +/* interface ICorDebugRuntimeUnwindableFrame */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("879CAC0A-4A53-4668-B8E3-CB8473CB187F") + ICorDebugRuntimeUnwindableFrame : public ICorDebugFrame + { + public: + }; + + +#else /* C style interface */ + + typedef struct ICorDebugRuntimeUnwindableFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugRuntimeUnwindableFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugRuntimeUnwindableFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugRuntimeUnwindableFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetChain )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugChain **ppChain); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetStackRange )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ CORDB_ADDRESS *pStart, + /* [out] */ CORDB_ADDRESS *pEnd); + + HRESULT ( STDMETHODCALLTYPE *GetCaller )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *GetCallee )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugFrame **ppFrame); + + HRESULT ( STDMETHODCALLTYPE *CreateStepper )( + ICorDebugRuntimeUnwindableFrame * This, + /* [out] */ ICorDebugStepper **ppStepper); + + END_INTERFACE + } ICorDebugRuntimeUnwindableFrameVtbl; + + interface ICorDebugRuntimeUnwindableFrame + { + CONST_VTBL struct ICorDebugRuntimeUnwindableFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugRuntimeUnwindableFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugRuntimeUnwindableFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugRuntimeUnwindableFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugRuntimeUnwindableFrame_GetChain(This,ppChain) \ + ( (This)->lpVtbl -> GetChain(This,ppChain) ) + +#define ICorDebugRuntimeUnwindableFrame_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugRuntimeUnwindableFrame_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugRuntimeUnwindableFrame_GetFunctionToken(This,pToken) \ + ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) + +#define ICorDebugRuntimeUnwindableFrame_GetStackRange(This,pStart,pEnd) \ + ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) + +#define ICorDebugRuntimeUnwindableFrame_GetCaller(This,ppFrame) \ + ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) + +#define ICorDebugRuntimeUnwindableFrame_GetCallee(This,ppFrame) \ + ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) + +#define ICorDebugRuntimeUnwindableFrame_CreateStepper(This,ppStepper) \ + ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugModule_INTERFACE_DEFINED__ +#define __ICorDebugModule_INTERFACE_DEFINED__ + +/* interface ICorDebugModule */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModule; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("dba2d8c1-e5c5-4069-8c13-10a7c6abf43d") + ICorDebugModule : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ ICorDebugProcess **ppProcess) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( + /* [out] */ CORDB_ADDRESS *pAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssembly( + /* [out] */ ICorDebugAssembly **ppAssembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( + /* [in] */ BOOL bTrackJITInfo, + /* [in] */ BOOL bAllowJitOpts) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( + /* [in] */ BOOL bClassLoadCallbacks) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( + /* [in] */ mdMethodDef methodDef, + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( + /* [in] */ CORDB_ADDRESS rva, + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( + /* [in] */ mdTypeDef typeDef, + /* [out] */ ICorDebugClass **ppClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( + /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppObj) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetToken( + /* [out] */ mdModule *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsDynamic( + /* [out] */ BOOL *pDynamic) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( + /* [in] */ mdFieldDef fieldDef, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcBytes) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsInMemory( + /* [out] */ BOOL *pInMemory) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModuleVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModule * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModule * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModule * This); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorDebugModule * This, + /* [out] */ ICorDebugProcess **ppProcess); + + HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( + ICorDebugModule * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAssembly )( + ICorDebugModule * This, + /* [out] */ ICorDebugAssembly **ppAssembly); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugModule * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( + ICorDebugModule * This, + /* [in] */ BOOL bTrackJITInfo, + /* [in] */ BOOL bAllowJitOpts); + + HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( + ICorDebugModule * This, + /* [in] */ BOOL bClassLoadCallbacks); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorDebugModule * This, + /* [in] */ mdMethodDef methodDef, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( + ICorDebugModule * This, + /* [in] */ CORDB_ADDRESS rva, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorDebugModule * This, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ICorDebugClass **ppClass); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugModule * This, + /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( + ICorDebugModule * This, + /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); + + HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( + ICorDebugModule * This, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppObj); + + HRESULT ( STDMETHODCALLTYPE *GetToken )( + ICorDebugModule * This, + /* [out] */ mdModule *pToken); + + HRESULT ( STDMETHODCALLTYPE *IsDynamic )( + ICorDebugModule * This, + /* [out] */ BOOL *pDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( + ICorDebugModule * This, + /* [in] */ mdFieldDef fieldDef, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugModule * This, + /* [out] */ ULONG32 *pcBytes); + + HRESULT ( STDMETHODCALLTYPE *IsInMemory )( + ICorDebugModule * This, + /* [out] */ BOOL *pInMemory); + + END_INTERFACE + } ICorDebugModuleVtbl; + + interface ICorDebugModule + { + CONST_VTBL struct ICorDebugModuleVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModule_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModule_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModule_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModule_GetProcess(This,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) + +#define ICorDebugModule_GetBaseAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) + +#define ICorDebugModule_GetAssembly(This,ppAssembly) \ + ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) + +#define ICorDebugModule_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugModule_EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) \ + ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) + +#define ICorDebugModule_EnableClassLoadCallbacks(This,bClassLoadCallbacks) \ + ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) + +#define ICorDebugModule_GetFunctionFromToken(This,methodDef,ppFunction) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) + +#define ICorDebugModule_GetFunctionFromRVA(This,rva,ppFunction) \ + ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) + +#define ICorDebugModule_GetClassFromToken(This,typeDef,ppClass) \ + ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) + +#define ICorDebugModule_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + +#define ICorDebugModule_GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) \ + ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) + +#define ICorDebugModule_GetMetaDataInterface(This,riid,ppObj) \ + ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) + +#define ICorDebugModule_GetToken(This,pToken) \ + ( (This)->lpVtbl -> GetToken(This,pToken) ) + +#define ICorDebugModule_IsDynamic(This,pDynamic) \ + ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) + +#define ICorDebugModule_GetGlobalVariableValue(This,fieldDef,ppValue) \ + ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) + +#define ICorDebugModule_GetSize(This,pcBytes) \ + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + +#define ICorDebugModule_IsInMemory(This,pInMemory) \ + ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModule_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0073 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0073_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0073_v0_0_s_ifspec; + +#ifndef __ICorDebugModule2_INTERFACE_DEFINED__ +#define __ICorDebugModule2_INTERFACE_DEFINED__ + +/* interface ICorDebugModule2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModule2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7") + ICorDebugModule2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + /* [in] */ BOOL bIsJustMyCode, + /* [in] */ ULONG32 cTokens, + /* [size_is][in] */ mdToken pTokens[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE ApplyChanges( + /* [in] */ ULONG cbMetadata, + /* [size_is][in] */ BYTE pbMetadata[ ], + /* [in] */ ULONG cbIL, + /* [size_is][in] */ BYTE pbIL[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( + /* [out] */ DWORD *pdwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( + /* [in] */ mdToken tkAssemblyRef, + /* [out] */ ICorDebugAssembly **ppAssembly) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModule2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModule2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModule2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModule2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + ICorDebugModule2 * This, + /* [in] */ BOOL bIsJustMyCode, + /* [in] */ ULONG32 cTokens, + /* [size_is][in] */ mdToken pTokens[ ]); + + HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( + ICorDebugModule2 * This, + /* [in] */ ULONG cbMetadata, + /* [size_is][in] */ BYTE pbMetadata[ ], + /* [in] */ ULONG cbIL, + /* [size_is][in] */ BYTE pbIL[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( + ICorDebugModule2 * This, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( + ICorDebugModule2 * This, + /* [out] */ DWORD *pdwFlags); + + HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( + ICorDebugModule2 * This, + /* [in] */ mdToken tkAssemblyRef, + /* [out] */ ICorDebugAssembly **ppAssembly); + + END_INTERFACE + } ICorDebugModule2Vtbl; + + interface ICorDebugModule2 + { + CONST_VTBL struct ICorDebugModule2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModule2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModule2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModule2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModule2_SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) \ + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) + +#define ICorDebugModule2_ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) \ + ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) + +#define ICorDebugModule2_SetJITCompilerFlags(This,dwFlags) \ + ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) + +#define ICorDebugModule2_GetJITCompilerFlags(This,pdwFlags) \ + ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) + +#define ICorDebugModule2_ResolveAssembly(This,tkAssemblyRef,ppAssembly) \ + ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModule2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFunction_INTERFACE_DEFINED__ +#define __ICorDebugFunction_INTERFACE_DEFINED__ + +/* interface ICorDebugFunction */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFunction; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF3-8A68-11d2-983C-0000F808342D") + ICorDebugFunction : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ ICorDebugModule **ppModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClass( + /* [out] */ ICorDebugClass **ppClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetToken( + /* [out] */ mdMethodDef *pMethodDef) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILCode( + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNativeCode( + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + /* [out] */ mdSignature *pmdSig) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( + /* [out] */ ULONG32 *pnCurrentVersion) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFunctionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFunction * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFunction * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFunction * This); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ICorDebugFunction * This, + /* [out] */ ICorDebugModule **ppModule); + + HRESULT ( STDMETHODCALLTYPE *GetClass )( + ICorDebugFunction * This, + /* [out] */ ICorDebugClass **ppClass); + + HRESULT ( STDMETHODCALLTYPE *GetToken )( + ICorDebugFunction * This, + /* [out] */ mdMethodDef *pMethodDef); + + HRESULT ( STDMETHODCALLTYPE *GetILCode )( + ICorDebugFunction * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( + ICorDebugFunction * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugFunction * This, + /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + ICorDebugFunction * This, + /* [out] */ mdSignature *pmdSig); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( + ICorDebugFunction * This, + /* [out] */ ULONG32 *pnCurrentVersion); + + END_INTERFACE + } ICorDebugFunctionVtbl; + + interface ICorDebugFunction + { + CONST_VTBL struct ICorDebugFunctionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFunction_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFunction_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFunction_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFunction_GetModule(This,ppModule) \ + ( (This)->lpVtbl -> GetModule(This,ppModule) ) + +#define ICorDebugFunction_GetClass(This,ppClass) \ + ( (This)->lpVtbl -> GetClass(This,ppClass) ) + +#define ICorDebugFunction_GetToken(This,pMethodDef) \ + ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) + +#define ICorDebugFunction_GetILCode(This,ppCode) \ + ( (This)->lpVtbl -> GetILCode(This,ppCode) ) + +#define ICorDebugFunction_GetNativeCode(This,ppCode) \ + ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) + +#define ICorDebugFunction_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + +#define ICorDebugFunction_GetLocalVarSigToken(This,pmdSig) \ + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + +#define ICorDebugFunction_GetCurrentVersionNumber(This,pnCurrentVersion) \ + ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFunction_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFunction2_INTERFACE_DEFINED__ +#define __ICorDebugFunction2_INTERFACE_DEFINED__ + +/* interface ICorDebugFunction2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFunction2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("EF0C490B-94C3-4e4d-B629-DDC134C532D8") + ICorDebugFunction2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + /* [in] */ BOOL bIsJustMyCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( + /* [out] */ BOOL *pbIsJustMyCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( + /* [out] */ ICorDebugCodeEnum **ppCodeEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + /* [out] */ ULONG32 *pnVersion) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFunction2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFunction2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFunction2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFunction2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + ICorDebugFunction2 * This, + /* [in] */ BOOL bIsJustMyCode); + + HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( + ICorDebugFunction2 * This, + /* [out] */ BOOL *pbIsJustMyCode); + + HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( + ICorDebugFunction2 * This, + /* [out] */ ICorDebugCodeEnum **ppCodeEnum); + + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + ICorDebugFunction2 * This, + /* [out] */ ULONG32 *pnVersion); + + END_INTERFACE + } ICorDebugFunction2Vtbl; + + interface ICorDebugFunction2 + { + CONST_VTBL struct ICorDebugFunction2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFunction2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFunction2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFunction2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFunction2_SetJMCStatus(This,bIsJustMyCode) \ + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + +#define ICorDebugFunction2_GetJMCStatus(This,pbIsJustMyCode) \ + ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) + +#define ICorDebugFunction2_EnumerateNativeCode(This,ppCodeEnum) \ + ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) + +#define ICorDebugFunction2_GetVersionNumber(This,pnVersion) \ + ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFunction2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFunction3_INTERFACE_DEFINED__ +#define __ICorDebugFunction3_INTERFACE_DEFINED__ + +/* interface ICorDebugFunction3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFunction3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("09B70F28-E465-482D-99E0-81A165EB0532") + ICorDebugFunction3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( + ICorDebugILCode **ppReJitedILCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFunction3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFunction3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFunction3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFunction3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( + ICorDebugFunction3 * This, + ICorDebugILCode **ppReJitedILCode); + + END_INTERFACE + } ICorDebugFunction3Vtbl; + + interface ICorDebugFunction3 + { + CONST_VTBL struct ICorDebugFunction3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFunction3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFunction3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFunction3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFunction3_GetActiveReJitRequestILCode(This,ppReJitedILCode) \ + ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFunction3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFunction4_INTERFACE_DEFINED__ +#define __ICorDebugFunction4_INTERFACE_DEFINED__ + +/* interface ICorDebugFunction4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFunction4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("72965963-34fd-46e9-9434-b817fe6e7f43") + ICorDebugFunction4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( + ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFunction4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFunction4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFunction4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFunction4 * This); + + HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( + ICorDebugFunction4 * This, + ICorDebugFunctionBreakpoint **ppBreakpoint); + + END_INTERFACE + } ICorDebugFunction4Vtbl; + + interface ICorDebugFunction4 + { + CONST_VTBL struct ICorDebugFunction4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFunction4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFunction4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFunction4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFunction4_CreateNativeBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFunction4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugCode_INTERFACE_DEFINED__ +#define __ICorDebugCode_INTERFACE_DEFINED__ + +/* interface ICorDebugCode */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugCode; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF4-8A68-11d2-983C-0000F808342D") + ICorDebugCode : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsIL( + /* [out] */ BOOL *pbIL) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunction( + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddress( + /* [out] */ CORDB_ADDRESS *pStart) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pcBytes) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + /* [in] */ ULONG32 offset, + /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset, + /* [in] */ ULONG32 cBufferAlloc, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ ULONG32 *pcBufferSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( + /* [out] */ ULONG32 *nVersion) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ ULONG32 offsets[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCodeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCode * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCode * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCode * This); + + HRESULT ( STDMETHODCALLTYPE *IsIL )( + ICorDebugCode * This, + /* [out] */ BOOL *pbIL); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugCode * This, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugCode * This, + /* [out] */ CORDB_ADDRESS *pStart); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugCode * This, + /* [out] */ ULONG32 *pcBytes); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugCode * This, + /* [in] */ ULONG32 offset, + /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugCode * This, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset, + /* [in] */ ULONG32 cBufferAlloc, + /* [length_is][size_is][out] */ BYTE buffer[ ], + /* [out] */ ULONG32 *pcBufferSize); + + HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( + ICorDebugCode * This, + /* [out] */ ULONG32 *nVersion); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorDebugCode * This, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( + ICorDebugCode * This, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ ULONG32 offsets[ ]); + + END_INTERFACE + } ICorDebugCodeVtbl; + + interface ICorDebugCode + { + CONST_VTBL struct ICorDebugCodeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCode_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCode_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCode_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCode_IsIL(This,pbIL) \ + ( (This)->lpVtbl -> IsIL(This,pbIL) ) + +#define ICorDebugCode_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#define ICorDebugCode_GetAddress(This,pStart) \ + ( (This)->lpVtbl -> GetAddress(This,pStart) ) + +#define ICorDebugCode_GetSize(This,pcBytes) \ + ( (This)->lpVtbl -> GetSize(This,pcBytes) ) + +#define ICorDebugCode_CreateBreakpoint(This,offset,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) + +#define ICorDebugCode_GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) \ + ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) + +#define ICorDebugCode_GetVersionNumber(This,nVersion) \ + ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) + +#define ICorDebugCode_GetILToNativeMapping(This,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) + +#define ICorDebugCode_GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) \ + ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCode_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugCode2_INTERFACE_DEFINED__ +#define __ICorDebugCode2_INTERFACE_DEFINED__ + +/* interface ICorDebugCode2 */ +/* [unique][uuid][local][object] */ + +typedef struct _CodeChunkInfo + { + CORDB_ADDRESS startAddr; + ULONG32 length; + } CodeChunkInfo; + + +EXTERN_C const IID IID_ICorDebugCode2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5F696509-452F-4436-A3FE-4D11FE7E2347") + ICorDebugCode2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( + /* [in] */ ULONG32 cbufSize, + /* [out] */ ULONG32 *pcnumChunks, + /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( + /* [out] */ DWORD *pdwFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCode2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCode2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCode2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCode2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( + ICorDebugCode2 * This, + /* [in] */ ULONG32 cbufSize, + /* [out] */ ULONG32 *pcnumChunks, + /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( + ICorDebugCode2 * This, + /* [out] */ DWORD *pdwFlags); + + END_INTERFACE + } ICorDebugCode2Vtbl; + + interface ICorDebugCode2 + { + CONST_VTBL struct ICorDebugCode2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCode2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCode2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCode2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCode2_GetCodeChunks(This,cbufSize,pcnumChunks,chunks) \ + ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) + +#define ICorDebugCode2_GetCompilerFlags(This,pdwFlags) \ + ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCode2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugCode3_INTERFACE_DEFINED__ +#define __ICorDebugCode3_INTERFACE_DEFINED__ + +/* interface ICorDebugCode3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugCode3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D13D3E88-E1F2-4020-AA1D-3D162DCBE966") + ICorDebugCode3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( + /* [in] */ ULONG32 ILoffset, + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *pFetched, + /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCode3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCode3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCode3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCode3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( + ICorDebugCode3 * This, + /* [in] */ ULONG32 ILoffset, + /* [in] */ ULONG32 bufferSize, + /* [out] */ ULONG32 *pFetched, + /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]); + + END_INTERFACE + } ICorDebugCode3Vtbl; + + interface ICorDebugCode3 + { + CONST_VTBL struct ICorDebugCode3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCode3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCode3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCode3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCode3_GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) \ + ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCode3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugCode4_INTERFACE_DEFINED__ +#define __ICorDebugCode4_INTERFACE_DEFINED__ + +/* interface ICorDebugCode4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugCode4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("18221fa4-20cb-40fa-b19d-9f91c4fa8c14") + ICorDebugCode4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( + /* [out] */ ICorDebugVariableHomeEnum **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCode4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCode4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCode4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCode4 * This); + + HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( + ICorDebugCode4 * This, + /* [out] */ ICorDebugVariableHomeEnum **ppEnum); + + END_INTERFACE + } ICorDebugCode4Vtbl; + + interface ICorDebugCode4 + { + CONST_VTBL struct ICorDebugCode4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCode4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCode4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCode4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCode4_EnumerateVariableHomes(This,ppEnum) \ + ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCode4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugILCode_INTERFACE_DEFINED__ +#define __ICorDebugILCode_INTERFACE_DEFINED__ + +/* interface ICorDebugILCode */ +/* [unique][uuid][local][object] */ + +typedef struct _CorDebugEHClause + { + ULONG32 Flags; + ULONG32 TryOffset; + ULONG32 TryLength; + ULONG32 HandlerOffset; + ULONG32 HandlerLength; + ULONG32 ClassToken; + ULONG32 FilterOffset; + } CorDebugEHClause; + + +EXTERN_C const IID IID_ICorDebugILCode; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("598D46C2-C877-42A7-89D2-3D0C7F1C1264") + ICorDebugILCode : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEHClauses( + /* [in] */ ULONG32 cClauses, + /* [out] */ ULONG32 *pcClauses, + /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILCodeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILCode * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILCode * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILCode * This); + + HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( + ICorDebugILCode * This, + /* [in] */ ULONG32 cClauses, + /* [out] */ ULONG32 *pcClauses, + /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]); + + END_INTERFACE + } ICorDebugILCodeVtbl; + + interface ICorDebugILCode + { + CONST_VTBL struct ICorDebugILCodeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILCode_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILCode_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILCode_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILCode_GetEHClauses(This,cClauses,pcClauses,clauses) \ + ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILCode_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugILCode2_INTERFACE_DEFINED__ +#define __ICorDebugILCode2_INTERFACE_DEFINED__ + +/* interface ICorDebugILCode2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugILCode2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("46586093-D3F5-4DB6-ACDB-955BCE228C15") + ICorDebugILCode2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( + /* [out] */ mdSignature *pmdSig) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_IL_MAP map[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugILCode2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugILCode2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugILCode2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugILCode2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( + ICorDebugILCode2 * This, + /* [out] */ mdSignature *pmdSig); + + HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( + ICorDebugILCode2 * This, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_IL_MAP map[ ]); + + END_INTERFACE + } ICorDebugILCode2Vtbl; + + interface ICorDebugILCode2 + { + CONST_VTBL struct ICorDebugILCode2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugILCode2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugILCode2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugILCode2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugILCode2_GetLocalVarSigToken(This,pmdSig) \ + ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) + +#define ICorDebugILCode2_GetInstrumentedILMap(This,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugILCode2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugClass_INTERFACE_DEFINED__ +#define __ICorDebugClass_INTERFACE_DEFINED__ + +/* interface ICorDebugClass */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugClass; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF5-8A68-11d2-983C-0000F808342D") + ICorDebugClass : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ ICorDebugModule **pModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetToken( + /* [out] */ mdTypeDef *pTypeDef) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + /* [in] */ mdFieldDef fieldDef, + /* [in] */ ICorDebugFrame *pFrame, + /* [out] */ ICorDebugValue **ppValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugClassVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugClass * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugClass * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugClass * This); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ICorDebugClass * This, + /* [out] */ ICorDebugModule **pModule); + + HRESULT ( STDMETHODCALLTYPE *GetToken )( + ICorDebugClass * This, + /* [out] */ mdTypeDef *pTypeDef); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + ICorDebugClass * This, + /* [in] */ mdFieldDef fieldDef, + /* [in] */ ICorDebugFrame *pFrame, + /* [out] */ ICorDebugValue **ppValue); + + END_INTERFACE + } ICorDebugClassVtbl; + + interface ICorDebugClass + { + CONST_VTBL struct ICorDebugClassVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugClass_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugClass_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugClass_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugClass_GetModule(This,pModule) \ + ( (This)->lpVtbl -> GetModule(This,pModule) ) + +#define ICorDebugClass_GetToken(This,pTypeDef) \ + ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) + +#define ICorDebugClass_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugClass_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugClass2_INTERFACE_DEFINED__ +#define __ICorDebugClass2_INTERFACE_DEFINED__ + +/* interface ICorDebugClass2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugClass2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B008EA8D-7AB1-43f7-BB20-FBB5A04038AE") + ICorDebugClass2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( + /* [in] */ CorElementType elementType, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [out] */ ICorDebugType **ppType) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( + /* [in] */ BOOL bIsJustMyCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugClass2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugClass2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugClass2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugClass2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( + ICorDebugClass2 * This, + /* [in] */ CorElementType elementType, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [out] */ ICorDebugType **ppType); + + HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( + ICorDebugClass2 * This, + /* [in] */ BOOL bIsJustMyCode); + + END_INTERFACE + } ICorDebugClass2Vtbl; + + interface ICorDebugClass2 + { + CONST_VTBL struct ICorDebugClass2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugClass2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugClass2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugClass2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugClass2_GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) \ + ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) + +#define ICorDebugClass2_SetJMCStatus(This,bIsJustMyCode) \ + ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugClass2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugEval_INTERFACE_DEFINED__ +#define __ICorDebugEval_INTERFACE_DEFINED__ + +/* interface ICorDebugEval */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugEval; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF6-8A68-11d2-983C-0000F808342D") + ICorDebugEval : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CallFunction( + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewObject( + /* [in] */ ICorDebugFunction *pConstructor, + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( + /* [in] */ ICorDebugClass *pClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewString( + /* [in] */ LPCWSTR string) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewArray( + /* [in] */ CorElementType elementType, + /* [in] */ ICorDebugClass *pElementClass, + /* [in] */ ULONG32 rank, + /* [size_is][in] */ ULONG32 dims[ ], + /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsActive( + /* [out] */ BOOL *pbActive) = 0; + + virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetResult( + /* [out] */ ICorDebugValue **ppResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThread( + /* [out] */ ICorDebugThread **ppThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateValue( + /* [in] */ CorElementType elementType, + /* [in] */ ICorDebugClass *pElementClass, + /* [out] */ ICorDebugValue **ppValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugEvalVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugEval * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugEval * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugEval * This); + + HRESULT ( STDMETHODCALLTYPE *CallFunction )( + ICorDebugEval * This, + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *NewObject )( + ICorDebugEval * This, + /* [in] */ ICorDebugFunction *pConstructor, + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( + ICorDebugEval * This, + /* [in] */ ICorDebugClass *pClass); + + HRESULT ( STDMETHODCALLTYPE *NewString )( + ICorDebugEval * This, + /* [in] */ LPCWSTR string); + + HRESULT ( STDMETHODCALLTYPE *NewArray )( + ICorDebugEval * This, + /* [in] */ CorElementType elementType, + /* [in] */ ICorDebugClass *pElementClass, + /* [in] */ ULONG32 rank, + /* [size_is][in] */ ULONG32 dims[ ], + /* [size_is][in] */ ULONG32 lowBounds[ ]); + + HRESULT ( STDMETHODCALLTYPE *IsActive )( + ICorDebugEval * This, + /* [out] */ BOOL *pbActive); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + ICorDebugEval * This); + + HRESULT ( STDMETHODCALLTYPE *GetResult )( + ICorDebugEval * This, + /* [out] */ ICorDebugValue **ppResult); + + HRESULT ( STDMETHODCALLTYPE *GetThread )( + ICorDebugEval * This, + /* [out] */ ICorDebugThread **ppThread); + + HRESULT ( STDMETHODCALLTYPE *CreateValue )( + ICorDebugEval * This, + /* [in] */ CorElementType elementType, + /* [in] */ ICorDebugClass *pElementClass, + /* [out] */ ICorDebugValue **ppValue); + + END_INTERFACE + } ICorDebugEvalVtbl; + + interface ICorDebugEval + { + CONST_VTBL struct ICorDebugEvalVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugEval_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugEval_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugEval_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugEval_CallFunction(This,pFunction,nArgs,ppArgs) \ + ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) + +#define ICorDebugEval_NewObject(This,pConstructor,nArgs,ppArgs) \ + ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) + +#define ICorDebugEval_NewObjectNoConstructor(This,pClass) \ + ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) + +#define ICorDebugEval_NewString(This,string) \ + ( (This)->lpVtbl -> NewString(This,string) ) + +#define ICorDebugEval_NewArray(This,elementType,pElementClass,rank,dims,lowBounds) \ + ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) + +#define ICorDebugEval_IsActive(This,pbActive) \ + ( (This)->lpVtbl -> IsActive(This,pbActive) ) + +#define ICorDebugEval_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + +#define ICorDebugEval_GetResult(This,ppResult) \ + ( (This)->lpVtbl -> GetResult(This,ppResult) ) + +#define ICorDebugEval_GetThread(This,ppThread) \ + ( (This)->lpVtbl -> GetThread(This,ppThread) ) + +#define ICorDebugEval_CreateValue(This,elementType,pElementClass,ppValue) \ + ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugEval_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugEval2_INTERFACE_DEFINED__ +#define __ICorDebugEval2_INTERFACE_DEFINED__ + +/* interface ICorDebugEval2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugEval2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FB0D9CE7-BE66-4683-9D32-A42A04E2FD91") + ICorDebugEval2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateValueForType( + /* [in] */ ICorDebugType *pType, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( + /* [in] */ ICorDebugFunction *pConstructor, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( + /* [in] */ ICorDebugClass *pClass, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( + /* [in] */ ICorDebugType *pElementType, + /* [in] */ ULONG32 rank, + /* [size_is][in] */ ULONG32 dims[ ], + /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( + /* [in] */ LPCWSTR string, + /* [in] */ UINT uiLength) = 0; + + virtual HRESULT STDMETHODCALLTYPE RudeAbort( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugEval2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugEval2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugEval2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugEval2 * This); + + HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( + ICorDebugEval2 * This, + /* [in] */ ICorDebugFunction *pFunction, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( + ICorDebugEval2 * This, + /* [in] */ ICorDebugType *pType, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( + ICorDebugEval2 * This, + /* [in] */ ICorDebugFunction *pConstructor, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], + /* [in] */ ULONG32 nArgs, + /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( + ICorDebugEval2 * This, + /* [in] */ ICorDebugClass *pClass, + /* [in] */ ULONG32 nTypeArgs, + /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( + ICorDebugEval2 * This, + /* [in] */ ICorDebugType *pElementType, + /* [in] */ ULONG32 rank, + /* [size_is][in] */ ULONG32 dims[ ], + /* [size_is][in] */ ULONG32 lowBounds[ ]); + + HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( + ICorDebugEval2 * This, + /* [in] */ LPCWSTR string, + /* [in] */ UINT uiLength); + + HRESULT ( STDMETHODCALLTYPE *RudeAbort )( + ICorDebugEval2 * This); + + END_INTERFACE + } ICorDebugEval2Vtbl; + + interface ICorDebugEval2 + { + CONST_VTBL struct ICorDebugEval2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugEval2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugEval2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugEval2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugEval2_CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ + ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + +#define ICorDebugEval2_CreateValueForType(This,pType,ppValue) \ + ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) + +#define ICorDebugEval2_NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ + ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) + +#define ICorDebugEval2_NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) \ + ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) + +#define ICorDebugEval2_NewParameterizedArray(This,pElementType,rank,dims,lowBounds) \ + ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) + +#define ICorDebugEval2_NewStringWithLength(This,string,uiLength) \ + ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) + +#define ICorDebugEval2_RudeAbort(This) \ + ( (This)->lpVtbl -> RudeAbort(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugEval2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugValue_INTERFACE_DEFINED__ +#define __ICorDebugValue_INTERFACE_DEFINED__ + +/* interface ICorDebugValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF7-8A68-11d2-983C-0000F808342D") + ICorDebugValue : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetType( + /* [out] */ CorElementType *pType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG32 *pSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddress( + /* [out] */ CORDB_ADDRESS *pAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + END_INTERFACE + } ICorDebugValueVtbl; + + interface ICorDebugValue + { + CONST_VTBL struct ICorDebugValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugValue2_INTERFACE_DEFINED__ +#define __ICorDebugValue2_INTERFACE_DEFINED__ + +/* interface ICorDebugValue2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugValue2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5E0B54E7-D88A-4626-9420-A691E0A78B49") + ICorDebugValue2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetExactType( + /* [out] */ ICorDebugType **ppType) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugValue2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugValue2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugValue2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugValue2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetExactType )( + ICorDebugValue2 * This, + /* [out] */ ICorDebugType **ppType); + + END_INTERFACE + } ICorDebugValue2Vtbl; + + interface ICorDebugValue2 + { + CONST_VTBL struct ICorDebugValue2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugValue2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugValue2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugValue2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugValue2_GetExactType(This,ppType) \ + ( (This)->lpVtbl -> GetExactType(This,ppType) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugValue2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugValue3_INTERFACE_DEFINED__ +#define __ICorDebugValue3_INTERFACE_DEFINED__ + +/* interface ICorDebugValue3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugValue3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("565005FC-0F8A-4F3E-9EDB-83102B156595") + ICorDebugValue3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSize64( + /* [out] */ ULONG64 *pSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugValue3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugValue3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugValue3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugValue3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetSize64 )( + ICorDebugValue3 * This, + /* [out] */ ULONG64 *pSize); + + END_INTERFACE + } ICorDebugValue3Vtbl; + + interface ICorDebugValue3 + { + CONST_VTBL struct ICorDebugValue3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugValue3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugValue3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugValue3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugValue3_GetSize64(This,pSize) \ + ( (This)->lpVtbl -> GetSize64(This,pSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugValue3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugGenericValue_INTERFACE_DEFINED__ +#define __ICorDebugGenericValue_INTERFACE_DEFINED__ + +/* interface ICorDebugGenericValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugGenericValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF8-8A68-11d2-983C-0000F808342D") + ICorDebugGenericValue : public ICorDebugValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetValue( + /* [out] */ void *pTo) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetValue( + /* [in] */ void *pFrom) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugGenericValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugGenericValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugGenericValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugGenericValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugGenericValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugGenericValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugGenericValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugGenericValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + ICorDebugGenericValue * This, + /* [out] */ void *pTo); + + HRESULT ( STDMETHODCALLTYPE *SetValue )( + ICorDebugGenericValue * This, + /* [in] */ void *pFrom); + + END_INTERFACE + } ICorDebugGenericValueVtbl; + + interface ICorDebugGenericValue + { + CONST_VTBL struct ICorDebugGenericValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugGenericValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugGenericValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugGenericValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugGenericValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugGenericValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugGenericValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugGenericValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugGenericValue_GetValue(This,pTo) \ + ( (This)->lpVtbl -> GetValue(This,pTo) ) + +#define ICorDebugGenericValue_SetValue(This,pFrom) \ + ( (This)->lpVtbl -> SetValue(This,pFrom) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugGenericValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugReferenceValue_INTERFACE_DEFINED__ +#define __ICorDebugReferenceValue_INTERFACE_DEFINED__ + +/* interface ICorDebugReferenceValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugReferenceValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAF9-8A68-11d2-983C-0000F808342D") + ICorDebugReferenceValue : public ICorDebugValue + { + public: + virtual HRESULT STDMETHODCALLTYPE IsNull( + /* [out] */ BOOL *pbNull) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetValue( + /* [out] */ CORDB_ADDRESS *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetValue( + /* [in] */ CORDB_ADDRESS value) = 0; + + virtual HRESULT STDMETHODCALLTYPE Dereference( + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( + /* [out] */ ICorDebugValue **ppValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugReferenceValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugReferenceValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugReferenceValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugReferenceValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugReferenceValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugReferenceValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugReferenceValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugReferenceValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsNull )( + ICorDebugReferenceValue * This, + /* [out] */ BOOL *pbNull); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + ICorDebugReferenceValue * This, + /* [out] */ CORDB_ADDRESS *pValue); + + HRESULT ( STDMETHODCALLTYPE *SetValue )( + ICorDebugReferenceValue * This, + /* [in] */ CORDB_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *Dereference )( + ICorDebugReferenceValue * This, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + ICorDebugReferenceValue * This, + /* [out] */ ICorDebugValue **ppValue); + + END_INTERFACE + } ICorDebugReferenceValueVtbl; + + interface ICorDebugReferenceValue + { + CONST_VTBL struct ICorDebugReferenceValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugReferenceValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugReferenceValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugReferenceValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugReferenceValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugReferenceValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugReferenceValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugReferenceValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugReferenceValue_IsNull(This,pbNull) \ + ( (This)->lpVtbl -> IsNull(This,pbNull) ) + +#define ICorDebugReferenceValue_GetValue(This,pValue) \ + ( (This)->lpVtbl -> GetValue(This,pValue) ) + +#define ICorDebugReferenceValue_SetValue(This,value) \ + ( (This)->lpVtbl -> SetValue(This,value) ) + +#define ICorDebugReferenceValue_Dereference(This,ppValue) \ + ( (This)->lpVtbl -> Dereference(This,ppValue) ) + +#define ICorDebugReferenceValue_DereferenceStrong(This,ppValue) \ + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugReferenceValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue_INTERFACE_DEFINED__ +#define __ICorDebugHeapValue_INTERFACE_DEFINED__ + +/* interface ICorDebugHeapValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHeapValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAFA-8A68-11d2-983C-0000F808342D") + ICorDebugHeapValue : public ICorDebugValue + { + public: + virtual HRESULT STDMETHODCALLTYPE IsValid( + /* [out] */ BOOL *pbValid) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHeapValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHeapValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHeapValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHeapValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugHeapValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugHeapValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugHeapValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugHeapValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsValid )( + ICorDebugHeapValue * This, + /* [out] */ BOOL *pbValid); + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + ICorDebugHeapValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + END_INTERFACE + } ICorDebugHeapValueVtbl; + + interface ICorDebugHeapValue + { + CONST_VTBL struct ICorDebugHeapValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHeapValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHeapValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHeapValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHeapValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugHeapValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugHeapValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugHeapValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugHeapValue_IsValid(This,pbValid) \ + ( (This)->lpVtbl -> IsValid(This,pbValid) ) + +#define ICorDebugHeapValue_CreateRelocBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHeapValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue2_INTERFACE_DEFINED__ +#define __ICorDebugHeapValue2_INTERFACE_DEFINED__ + +/* interface ICorDebugHeapValue2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHeapValue2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E3AC4D6C-9CB7-43e6-96CC-B21540E5083C") + ICorDebugHeapValue2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateHandle( + /* [in] */ CorDebugHandleType type, + /* [out] */ ICorDebugHandleValue **ppHandle) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHeapValue2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHeapValue2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHeapValue2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHeapValue2 * This); + + HRESULT ( STDMETHODCALLTYPE *CreateHandle )( + ICorDebugHeapValue2 * This, + /* [in] */ CorDebugHandleType type, + /* [out] */ ICorDebugHandleValue **ppHandle); + + END_INTERFACE + } ICorDebugHeapValue2Vtbl; + + interface ICorDebugHeapValue2 + { + CONST_VTBL struct ICorDebugHeapValue2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHeapValue2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHeapValue2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHeapValue2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHeapValue2_CreateHandle(This,type,ppHandle) \ + ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHeapValue2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugHeapValue3_INTERFACE_DEFINED__ +#define __ICorDebugHeapValue3_INTERFACE_DEFINED__ + +/* interface ICorDebugHeapValue3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHeapValue3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A69ACAD8-2374-46e9-9FF8-B1F14120D296") + ICorDebugHeapValue3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( + /* [out] */ ICorDebugThread **ppThread, + /* [out] */ DWORD *pAcquisitionCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( + /* [out] */ ICorDebugThreadEnum **ppThreadEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHeapValue3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHeapValue3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHeapValue3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHeapValue3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( + ICorDebugHeapValue3 * This, + /* [out] */ ICorDebugThread **ppThread, + /* [out] */ DWORD *pAcquisitionCount); + + HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( + ICorDebugHeapValue3 * This, + /* [out] */ ICorDebugThreadEnum **ppThreadEnum); + + END_INTERFACE + } ICorDebugHeapValue3Vtbl; + + interface ICorDebugHeapValue3 + { + CONST_VTBL struct ICorDebugHeapValue3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHeapValue3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHeapValue3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHeapValue3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHeapValue3_GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) \ + ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) + +#define ICorDebugHeapValue3_GetMonitorEventWaitList(This,ppThreadEnum) \ + ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHeapValue3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugObjectValue_INTERFACE_DEFINED__ +#define __ICorDebugObjectValue_INTERFACE_DEFINED__ + +/* interface ICorDebugObjectValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugObjectValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("18AD3D6E-B7D2-11d2-BD04-0000F80849BD") + ICorDebugObjectValue : public ICorDebugValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetClass( + /* [out] */ ICorDebugClass **ppClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldValue( + /* [in] */ ICorDebugClass *pClass, + /* [in] */ mdFieldDef fieldDef, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( + /* [in] */ mdMemberRef memberRef, + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [out] */ ICorDebugContext **ppContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsValueClass( + /* [out] */ BOOL *pbIsValueClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( + /* [out] */ IUnknown **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( + /* [in] */ IUnknown *pObject) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugObjectValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugObjectValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugObjectValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugObjectValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugObjectValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugObjectValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugObjectValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugObjectValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetClass )( + ICorDebugObjectValue * This, + /* [out] */ ICorDebugClass **ppClass); + + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + ICorDebugObjectValue * This, + /* [in] */ ICorDebugClass *pClass, + /* [in] */ mdFieldDef fieldDef, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + ICorDebugObjectValue * This, + /* [in] */ mdMemberRef memberRef, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + ICorDebugObjectValue * This, + /* [out] */ ICorDebugContext **ppContext); + + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + ICorDebugObjectValue * This, + /* [out] */ BOOL *pbIsValueClass); + + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + ICorDebugObjectValue * This, + /* [out] */ IUnknown **ppObject); + + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + ICorDebugObjectValue * This, + /* [in] */ IUnknown *pObject); + + END_INTERFACE + } ICorDebugObjectValueVtbl; + + interface ICorDebugObjectValue + { + CONST_VTBL struct ICorDebugObjectValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugObjectValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugObjectValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugObjectValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugObjectValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugObjectValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugObjectValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugObjectValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugObjectValue_GetClass(This,ppClass) \ + ( (This)->lpVtbl -> GetClass(This,ppClass) ) + +#define ICorDebugObjectValue_GetFieldValue(This,pClass,fieldDef,ppValue) \ + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + +#define ICorDebugObjectValue_GetVirtualMethod(This,memberRef,ppFunction) \ + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + +#define ICorDebugObjectValue_GetContext(This,ppContext) \ + ( (This)->lpVtbl -> GetContext(This,ppContext) ) + +#define ICorDebugObjectValue_IsValueClass(This,pbIsValueClass) \ + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + +#define ICorDebugObjectValue_GetManagedCopy(This,ppObject) \ + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + +#define ICorDebugObjectValue_SetFromManagedCopy(This,pObject) \ + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugObjectValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugObjectValue2_INTERFACE_DEFINED__ +#define __ICorDebugObjectValue2_INTERFACE_DEFINED__ + +/* interface ICorDebugObjectValue2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugObjectValue2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("49E4A320-4A9B-4eca-B105-229FB7D5009F") + ICorDebugObjectValue2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( + /* [in] */ mdMemberRef memberRef, + /* [out] */ ICorDebugFunction **ppFunction, + /* [out] */ ICorDebugType **ppType) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugObjectValue2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugObjectValue2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugObjectValue2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugObjectValue2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( + ICorDebugObjectValue2 * This, + /* [in] */ mdMemberRef memberRef, + /* [out] */ ICorDebugFunction **ppFunction, + /* [out] */ ICorDebugType **ppType); + + END_INTERFACE + } ICorDebugObjectValue2Vtbl; + + interface ICorDebugObjectValue2 + { + CONST_VTBL struct ICorDebugObjectValue2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugObjectValue2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugObjectValue2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugObjectValue2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugObjectValue2_GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) \ + ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugObjectValue2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ +#define __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ + +/* interface ICorDebugDelegateObjectValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugDelegateObjectValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3AF70CC7-6047-47F6-A5C5-090A1A622638") + ICorDebugDelegateObjectValue : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTarget( + /* [out] */ ICorDebugReferenceValue **ppObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunction( + /* [out] */ ICorDebugFunction **ppFunction) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugDelegateObjectValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugDelegateObjectValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugDelegateObjectValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugDelegateObjectValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetTarget )( + ICorDebugDelegateObjectValue * This, + /* [out] */ ICorDebugReferenceValue **ppObject); + + HRESULT ( STDMETHODCALLTYPE *GetFunction )( + ICorDebugDelegateObjectValue * This, + /* [out] */ ICorDebugFunction **ppFunction); + + END_INTERFACE + } ICorDebugDelegateObjectValueVtbl; + + interface ICorDebugDelegateObjectValue + { + CONST_VTBL struct ICorDebugDelegateObjectValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugDelegateObjectValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugDelegateObjectValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugDelegateObjectValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugDelegateObjectValue_GetTarget(This,ppObject) \ + ( (This)->lpVtbl -> GetTarget(This,ppObject) ) + +#define ICorDebugDelegateObjectValue_GetFunction(This,ppFunction) \ + ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugBoxValue_INTERFACE_DEFINED__ +#define __ICorDebugBoxValue_INTERFACE_DEFINED__ + +/* interface ICorDebugBoxValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugBoxValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAFC-8A68-11d2-983C-0000F808342D") + ICorDebugBoxValue : public ICorDebugHeapValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetObject( + /* [out] */ ICorDebugObjectValue **ppObject) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugBoxValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugBoxValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugBoxValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugBoxValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugBoxValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugBoxValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugBoxValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugBoxValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsValid )( + ICorDebugBoxValue * This, + /* [out] */ BOOL *pbValid); + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + ICorDebugBoxValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetObject )( + ICorDebugBoxValue * This, + /* [out] */ ICorDebugObjectValue **ppObject); + + END_INTERFACE + } ICorDebugBoxValueVtbl; + + interface ICorDebugBoxValue + { + CONST_VTBL struct ICorDebugBoxValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugBoxValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugBoxValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugBoxValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugBoxValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugBoxValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugBoxValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugBoxValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugBoxValue_IsValid(This,pbValid) \ + ( (This)->lpVtbl -> IsValid(This,pbValid) ) + +#define ICorDebugBoxValue_CreateRelocBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugBoxValue_GetObject(This,ppObject) \ + ( (This)->lpVtbl -> GetObject(This,ppObject) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugBoxValue_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0100 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0100_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0100_v0_0_s_ifspec; + +#ifndef __ICorDebugStringValue_INTERFACE_DEFINED__ +#define __ICorDebugStringValue_INTERFACE_DEFINED__ + +/* interface ICorDebugStringValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugStringValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCAFD-8A68-11d2-983C-0000F808342D") + ICorDebugStringValue : public ICorDebugHeapValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetLength( + /* [out] */ ULONG32 *pcchString) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetString( + /* [in] */ ULONG32 cchString, + /* [out] */ ULONG32 *pcchString, + /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStringValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStringValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStringValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStringValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugStringValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugStringValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugStringValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugStringValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsValid )( + ICorDebugStringValue * This, + /* [out] */ BOOL *pbValid); + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + ICorDebugStringValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetLength )( + ICorDebugStringValue * This, + /* [out] */ ULONG32 *pcchString); + + HRESULT ( STDMETHODCALLTYPE *GetString )( + ICorDebugStringValue * This, + /* [in] */ ULONG32 cchString, + /* [out] */ ULONG32 *pcchString, + /* [length_is][size_is][out] */ WCHAR szString[ ]); + + END_INTERFACE + } ICorDebugStringValueVtbl; + + interface ICorDebugStringValue + { + CONST_VTBL struct ICorDebugStringValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStringValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStringValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStringValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStringValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugStringValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugStringValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugStringValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugStringValue_IsValid(This,pbValid) \ + ( (This)->lpVtbl -> IsValid(This,pbValid) ) + +#define ICorDebugStringValue_CreateRelocBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugStringValue_GetLength(This,pcchString) \ + ( (This)->lpVtbl -> GetLength(This,pcchString) ) + +#define ICorDebugStringValue_GetString(This,cchString,pcchString,szString) \ + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStringValue_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0101 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0101_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0101_v0_0_s_ifspec; + +#ifndef __ICorDebugArrayValue_INTERFACE_DEFINED__ +#define __ICorDebugArrayValue_INTERFACE_DEFINED__ + +/* interface ICorDebugArrayValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugArrayValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0405B0DF-A660-11d2-BD02-0000F80849BD") + ICorDebugArrayValue : public ICorDebugHeapValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetElementType( + /* [out] */ CorElementType *pType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRank( + /* [out] */ ULONG32 *pnRank) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG32 *pnCount) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDimensions( + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][out] */ ULONG32 dims[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( + /* [out] */ BOOL *pbHasBaseIndicies) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][out] */ ULONG32 indicies[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetElement( + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][in] */ ULONG32 indices[ ], + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( + /* [in] */ ULONG32 nPosition, + /* [out] */ ICorDebugValue **ppValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugArrayValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugArrayValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugArrayValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugArrayValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugArrayValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugArrayValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugArrayValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugArrayValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsValid )( + ICorDebugArrayValue * This, + /* [out] */ BOOL *pbValid); + + HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( + ICorDebugArrayValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetElementType )( + ICorDebugArrayValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetRank )( + ICorDebugArrayValue * This, + /* [out] */ ULONG32 *pnRank); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugArrayValue * This, + /* [out] */ ULONG32 *pnCount); + + HRESULT ( STDMETHODCALLTYPE *GetDimensions )( + ICorDebugArrayValue * This, + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][out] */ ULONG32 dims[ ]); + + HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( + ICorDebugArrayValue * This, + /* [out] */ BOOL *pbHasBaseIndicies); + + HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( + ICorDebugArrayValue * This, + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][out] */ ULONG32 indicies[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetElement )( + ICorDebugArrayValue * This, + /* [in] */ ULONG32 cdim, + /* [length_is][size_is][in] */ ULONG32 indices[ ], + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( + ICorDebugArrayValue * This, + /* [in] */ ULONG32 nPosition, + /* [out] */ ICorDebugValue **ppValue); + + END_INTERFACE + } ICorDebugArrayValueVtbl; + + interface ICorDebugArrayValue + { + CONST_VTBL struct ICorDebugArrayValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugArrayValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugArrayValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugArrayValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugArrayValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugArrayValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugArrayValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugArrayValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugArrayValue_IsValid(This,pbValid) \ + ( (This)->lpVtbl -> IsValid(This,pbValid) ) + +#define ICorDebugArrayValue_CreateRelocBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugArrayValue_GetElementType(This,pType) \ + ( (This)->lpVtbl -> GetElementType(This,pType) ) + +#define ICorDebugArrayValue_GetRank(This,pnRank) \ + ( (This)->lpVtbl -> GetRank(This,pnRank) ) + +#define ICorDebugArrayValue_GetCount(This,pnCount) \ + ( (This)->lpVtbl -> GetCount(This,pnCount) ) + +#define ICorDebugArrayValue_GetDimensions(This,cdim,dims) \ + ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) + +#define ICorDebugArrayValue_HasBaseIndicies(This,pbHasBaseIndicies) \ + ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) + +#define ICorDebugArrayValue_GetBaseIndicies(This,cdim,indicies) \ + ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indicies) ) + +#define ICorDebugArrayValue_GetElement(This,cdim,indices,ppValue) \ + ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) + +#define ICorDebugArrayValue_GetElementAtPosition(This,nPosition,ppValue) \ + ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugArrayValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugVariableHome_INTERFACE_DEFINED__ +#define __ICorDebugVariableHome_INTERFACE_DEFINED__ + +/* interface ICorDebugVariableHome */ +/* [unique][uuid][local][object] */ + +typedef +enum VariableLocationType + { + VLT_REGISTER = 0, + VLT_REGISTER_RELATIVE = ( VLT_REGISTER + 1 ) , + VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) + } VariableLocationType; + + +EXTERN_C const IID IID_ICorDebugVariableHome; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("50847b8d-f43f-41b0-924c-6383a5f2278b") + ICorDebugVariableHome : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [out] */ ICorDebugCode **ppCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( + /* [out] */ ULONG32 *pSlotIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( + /* [out] */ ULONG32 *pArgumentIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLiveRange( + /* [out] */ ULONG32 *pStartOffset, + /* [out] */ ULONG32 *pEndOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocationType( + /* [out] */ VariableLocationType *pLocationType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegister( + /* [out] */ CorDebugRegister *pRegister) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOffset( + /* [out] */ LONG *pOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVariableHomeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVariableHome * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVariableHome * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVariableHome * This); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + ICorDebugVariableHome * This, + /* [out] */ ICorDebugCode **ppCode); + + HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pSlotIndex); + + HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pArgumentIndex); + + HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( + ICorDebugVariableHome * This, + /* [out] */ ULONG32 *pStartOffset, + /* [out] */ ULONG32 *pEndOffset); + + HRESULT ( STDMETHODCALLTYPE *GetLocationType )( + ICorDebugVariableHome * This, + /* [out] */ VariableLocationType *pLocationType); + + HRESULT ( STDMETHODCALLTYPE *GetRegister )( + ICorDebugVariableHome * This, + /* [out] */ CorDebugRegister *pRegister); + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( + ICorDebugVariableHome * This, + /* [out] */ LONG *pOffset); + + END_INTERFACE + } ICorDebugVariableHomeVtbl; + + interface ICorDebugVariableHome + { + CONST_VTBL struct ICorDebugVariableHomeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVariableHome_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVariableHome_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVariableHome_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVariableHome_GetCode(This,ppCode) \ + ( (This)->lpVtbl -> GetCode(This,ppCode) ) + +#define ICorDebugVariableHome_GetSlotIndex(This,pSlotIndex) \ + ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) + +#define ICorDebugVariableHome_GetArgumentIndex(This,pArgumentIndex) \ + ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) + +#define ICorDebugVariableHome_GetLiveRange(This,pStartOffset,pEndOffset) \ + ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) + +#define ICorDebugVariableHome_GetLocationType(This,pLocationType) \ + ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) + +#define ICorDebugVariableHome_GetRegister(This,pRegister) \ + ( (This)->lpVtbl -> GetRegister(This,pRegister) ) + +#define ICorDebugVariableHome_GetOffset(This,pOffset) \ + ( (This)->lpVtbl -> GetOffset(This,pOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVariableHome_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugHandleValue_INTERFACE_DEFINED__ +#define __ICorDebugHandleValue_INTERFACE_DEFINED__ + +/* interface ICorDebugHandleValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugHandleValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("029596E8-276B-46a1-9821-732E96BBB00B") + ICorDebugHandleValue : public ICorDebugReferenceValue + { + public: + virtual HRESULT STDMETHODCALLTYPE GetHandleType( + /* [out] */ CorDebugHandleType *pType) = 0; + + virtual HRESULT STDMETHODCALLTYPE Dispose( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugHandleValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugHandleValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugHandleValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugHandleValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugHandleValue * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugHandleValue * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugHandleValue * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugHandleValue * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *IsNull )( + ICorDebugHandleValue * This, + /* [out] */ BOOL *pbNull); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + ICorDebugHandleValue * This, + /* [out] */ CORDB_ADDRESS *pValue); + + HRESULT ( STDMETHODCALLTYPE *SetValue )( + ICorDebugHandleValue * This, + /* [in] */ CORDB_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *Dereference )( + ICorDebugHandleValue * This, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( + ICorDebugHandleValue * This, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetHandleType )( + ICorDebugHandleValue * This, + /* [out] */ CorDebugHandleType *pType); + + HRESULT ( STDMETHODCALLTYPE *Dispose )( + ICorDebugHandleValue * This); + + END_INTERFACE + } ICorDebugHandleValueVtbl; + + interface ICorDebugHandleValue + { + CONST_VTBL struct ICorDebugHandleValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugHandleValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugHandleValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugHandleValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugHandleValue_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugHandleValue_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugHandleValue_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugHandleValue_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugHandleValue_IsNull(This,pbNull) \ + ( (This)->lpVtbl -> IsNull(This,pbNull) ) + +#define ICorDebugHandleValue_GetValue(This,pValue) \ + ( (This)->lpVtbl -> GetValue(This,pValue) ) + +#define ICorDebugHandleValue_SetValue(This,value) \ + ( (This)->lpVtbl -> SetValue(This,value) ) + +#define ICorDebugHandleValue_Dereference(This,ppValue) \ + ( (This)->lpVtbl -> Dereference(This,ppValue) ) + +#define ICorDebugHandleValue_DereferenceStrong(This,ppValue) \ + ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) + + +#define ICorDebugHandleValue_GetHandleType(This,pType) \ + ( (This)->lpVtbl -> GetHandleType(This,pType) ) + +#define ICorDebugHandleValue_Dispose(This) \ + ( (This)->lpVtbl -> Dispose(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugHandleValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugContext_INTERFACE_DEFINED__ +#define __ICorDebugContext_INTERFACE_DEFINED__ + +/* interface ICorDebugContext */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB00-8A68-11d2-983C-0000F808342D") + ICorDebugContext : public ICorDebugObjectValue + { + public: + }; + + +#else /* C style interface */ + + typedef struct ICorDebugContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugContext * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugContext * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugContext * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugContext * This, + /* [out] */ CorElementType *pType); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + ICorDebugContext * This, + /* [out] */ ULONG32 *pSize); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + ICorDebugContext * This, + /* [out] */ CORDB_ADDRESS *pAddress); + + HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( + ICorDebugContext * This, + /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); + + HRESULT ( STDMETHODCALLTYPE *GetClass )( + ICorDebugContext * This, + /* [out] */ ICorDebugClass **ppClass); + + HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( + ICorDebugContext * This, + /* [in] */ ICorDebugClass *pClass, + /* [in] */ mdFieldDef fieldDef, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( + ICorDebugContext * This, + /* [in] */ mdMemberRef memberRef, + /* [out] */ ICorDebugFunction **ppFunction); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + ICorDebugContext * This, + /* [out] */ ICorDebugContext **ppContext); + + HRESULT ( STDMETHODCALLTYPE *IsValueClass )( + ICorDebugContext * This, + /* [out] */ BOOL *pbIsValueClass); + + HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( + ICorDebugContext * This, + /* [out] */ IUnknown **ppObject); + + HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( + ICorDebugContext * This, + /* [in] */ IUnknown *pObject); + + END_INTERFACE + } ICorDebugContextVtbl; + + interface ICorDebugContext + { + CONST_VTBL struct ICorDebugContextVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugContext_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugContext_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugContext_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugContext_GetType(This,pType) \ + ( (This)->lpVtbl -> GetType(This,pType) ) + +#define ICorDebugContext_GetSize(This,pSize) \ + ( (This)->lpVtbl -> GetSize(This,pSize) ) + +#define ICorDebugContext_GetAddress(This,pAddress) \ + ( (This)->lpVtbl -> GetAddress(This,pAddress) ) + +#define ICorDebugContext_CreateBreakpoint(This,ppBreakpoint) \ + ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) + + +#define ICorDebugContext_GetClass(This,ppClass) \ + ( (This)->lpVtbl -> GetClass(This,ppClass) ) + +#define ICorDebugContext_GetFieldValue(This,pClass,fieldDef,ppValue) \ + ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) + +#define ICorDebugContext_GetVirtualMethod(This,memberRef,ppFunction) \ + ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) + +#define ICorDebugContext_GetContext(This,ppContext) \ + ( (This)->lpVtbl -> GetContext(This,ppContext) ) + +#define ICorDebugContext_IsValueClass(This,pbIsValueClass) \ + ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) + +#define ICorDebugContext_GetManagedCopy(This,ppObject) \ + ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) + +#define ICorDebugContext_SetFromManagedCopy(This,pObject) \ + ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) + + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugContext_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugComObjectValue_INTERFACE_DEFINED__ +#define __ICorDebugComObjectValue_INTERFACE_DEFINED__ + +/* interface ICorDebugComObjectValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugComObjectValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5F69C5E5-3E12-42DF-B371-F9D761D6EE24") + ICorDebugComObjectValue : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( + /* [in] */ BOOL bIInspectableOnly, + /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( + /* [in] */ BOOL bIInspectableOnly, + /* [in] */ ULONG32 celt, + /* [out] */ ULONG32 *pcEltFetched, + /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugComObjectValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugComObjectValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugComObjectValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugComObjectValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( + ICorDebugComObjectValue * This, + /* [in] */ BOOL bIInspectableOnly, + /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( + ICorDebugComObjectValue * This, + /* [in] */ BOOL bIInspectableOnly, + /* [in] */ ULONG32 celt, + /* [out] */ ULONG32 *pcEltFetched, + /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs); + + END_INTERFACE + } ICorDebugComObjectValueVtbl; + + interface ICorDebugComObjectValue + { + CONST_VTBL struct ICorDebugComObjectValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugComObjectValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugComObjectValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugComObjectValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugComObjectValue_GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) \ + ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) + +#define ICorDebugComObjectValue_GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) \ + ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugComObjectValue_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugObjectEnum_INTERFACE_DEFINED__ +#define __ICorDebugObjectEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugObjectEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugObjectEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB02-8A68-11d2-983C-0000F808342D") + ICorDebugObjectEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugObjectEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugObjectEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugObjectEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugObjectEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugObjectEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugObjectEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugObjectEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugObjectEnumVtbl; + + interface ICorDebugObjectEnum + { + CONST_VTBL struct ICorDebugObjectEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugObjectEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugObjectEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugObjectEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugObjectEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugObjectEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugObjectEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugObjectEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugObjectEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugObjectEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ +#define __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugBreakpointEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugBreakpointEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB03-8A68-11d2-983C-0000F808342D") + ICorDebugBreakpointEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugBreakpointEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugBreakpointEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugBreakpointEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugBreakpointEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugBreakpointEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugBreakpointEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugBreakpointEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugBreakpointEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugBreakpointEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugBreakpointEnumVtbl; + + interface ICorDebugBreakpointEnum + { + CONST_VTBL struct ICorDebugBreakpointEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugBreakpointEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugBreakpointEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugBreakpointEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugBreakpointEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugBreakpointEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugBreakpointEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugBreakpointEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugBreakpointEnum_Next(This,celt,breakpoints,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugStepperEnum_INTERFACE_DEFINED__ +#define __ICorDebugStepperEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugStepperEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugStepperEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB04-8A68-11d2-983C-0000F808342D") + ICorDebugStepperEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugStepperEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugStepperEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugStepperEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugStepperEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugStepperEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugStepperEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugStepperEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugStepperEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugStepperEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugStepperEnumVtbl; + + interface ICorDebugStepperEnum + { + CONST_VTBL struct ICorDebugStepperEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugStepperEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugStepperEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugStepperEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugStepperEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugStepperEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugStepperEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugStepperEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugStepperEnum_Next(This,celt,steppers,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugStepperEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugProcessEnum_INTERFACE_DEFINED__ +#define __ICorDebugProcessEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugProcessEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcessEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB05-8A68-11d2-983C-0000F808342D") + ICorDebugProcessEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcessEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcessEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcessEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcessEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugProcessEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugProcessEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugProcessEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugProcessEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugProcessEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugProcessEnumVtbl; + + interface ICorDebugProcessEnum + { + CONST_VTBL struct ICorDebugProcessEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcessEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcessEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcessEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcessEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugProcessEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugProcessEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugProcessEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugProcessEnum_Next(This,celt,processes,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcessEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugThreadEnum_INTERFACE_DEFINED__ +#define __ICorDebugThreadEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugThreadEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugThreadEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB06-8A68-11d2-983C-0000F808342D") + ICorDebugThreadEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugThreadEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugThreadEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugThreadEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugThreadEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugThreadEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugThreadEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugThreadEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugThreadEnumVtbl; + + interface ICorDebugThreadEnum + { + CONST_VTBL struct ICorDebugThreadEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugThreadEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugThreadEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugThreadEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugThreadEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugThreadEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugThreadEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugThreadEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugThreadEnum_Next(This,celt,threads,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugThreadEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugFrameEnum_INTERFACE_DEFINED__ +#define __ICorDebugFrameEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugFrameEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugFrameEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB07-8A68-11d2-983C-0000F808342D") + ICorDebugFrameEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugFrameEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugFrameEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugFrameEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugFrameEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugFrameEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugFrameEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugFrameEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugFrameEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugFrameEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugFrameEnumVtbl; + + interface ICorDebugFrameEnum + { + CONST_VTBL struct ICorDebugFrameEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugFrameEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugFrameEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugFrameEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugFrameEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugFrameEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugFrameEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugFrameEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugFrameEnum_Next(This,celt,frames,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugFrameEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugChainEnum_INTERFACE_DEFINED__ +#define __ICorDebugChainEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugChainEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugChainEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB08-8A68-11d2-983C-0000F808342D") + ICorDebugChainEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugChainEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugChainEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugChainEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugChainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugChainEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugChainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugChainEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugChainEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugChainEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugChainEnumVtbl; + + interface ICorDebugChainEnum + { + CONST_VTBL struct ICorDebugChainEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugChainEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugChainEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugChainEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugChainEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugChainEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugChainEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugChainEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugChainEnum_Next(This,celt,chains,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugChainEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugModuleEnum_INTERFACE_DEFINED__ +#define __ICorDebugModuleEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugModuleEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugModuleEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB09-8A68-11d2-983C-0000F808342D") + ICorDebugModuleEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugModuleEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugModuleEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugModuleEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugModuleEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugModuleEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugModuleEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugModuleEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugModuleEnumVtbl; + + interface ICorDebugModuleEnum + { + CONST_VTBL struct ICorDebugModuleEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugModuleEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugModuleEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugModuleEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugModuleEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugModuleEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugModuleEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugModuleEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugModuleEnum_Next(This,celt,modules,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugModuleEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugValueEnum_INTERFACE_DEFINED__ +#define __ICorDebugValueEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugValueEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugValueEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC7BCB0A-8A68-11d2-983C-0000F808342D") + ICorDebugValueEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugValue *values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugValueEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugValueEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugValueEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugValueEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugValueEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugValueEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugValueEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugValueEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugValueEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugValue *values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugValueEnumVtbl; + + interface ICorDebugValueEnum + { + CONST_VTBL struct ICorDebugValueEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugValueEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugValueEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugValueEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugValueEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugValueEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugValueEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugValueEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugValueEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugValueEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ +#define __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugVariableHomeEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugVariableHomeEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e76b7a57-4f7a-4309-85a7-5d918c3deaf7") + ICorDebugVariableHomeEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugVariableHomeEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugVariableHomeEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugVariableHomeEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugVariableHomeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugVariableHomeEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugVariableHomeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugVariableHomeEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugVariableHomeEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugVariableHomeEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugVariableHomeEnumVtbl; + + interface ICorDebugVariableHomeEnum + { + CONST_VTBL struct ICorDebugVariableHomeEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugVariableHomeEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugVariableHomeEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugVariableHomeEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugVariableHomeEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugVariableHomeEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugVariableHomeEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugVariableHomeEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugVariableHomeEnum_Next(This,celt,homes,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugCodeEnum_INTERFACE_DEFINED__ +#define __ICorDebugCodeEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugCodeEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugCodeEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("55E96461-9645-45e4-A2FF-0367877ABCDE") + ICorDebugCodeEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugCode *values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugCodeEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugCodeEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugCodeEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugCodeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugCodeEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugCodeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugCodeEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugCodeEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugCodeEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugCode *values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugCodeEnumVtbl; + + interface ICorDebugCodeEnum + { + CONST_VTBL struct ICorDebugCodeEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugCodeEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugCodeEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugCodeEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugCodeEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugCodeEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugCodeEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugCodeEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugCodeEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugCodeEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugTypeEnum_INTERFACE_DEFINED__ +#define __ICorDebugTypeEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugTypeEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugTypeEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("10F27499-9DF2-43ce-8333-A321D7C99CB4") + ICorDebugTypeEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugType *values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugTypeEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugTypeEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugTypeEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugTypeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugTypeEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugTypeEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugTypeEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugTypeEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugTypeEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugType *values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugTypeEnumVtbl; + + interface ICorDebugTypeEnum + { + CONST_VTBL struct ICorDebugTypeEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugTypeEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugTypeEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugTypeEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugTypeEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugTypeEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugTypeEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugTypeEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugTypeEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugTypeEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugType_INTERFACE_DEFINED__ +#define __ICorDebugType_INTERFACE_DEFINED__ + +/* interface ICorDebugType */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugType; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5") + ICorDebugType : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetType( + /* [out] */ CorElementType *ty) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClass( + /* [out] */ ICorDebugClass **ppClass) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( + /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( + /* [out] */ ICorDebugType **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBase( + /* [out] */ ICorDebugType **pBase) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( + /* [in] */ mdFieldDef fieldDef, + /* [in] */ ICorDebugFrame *pFrame, + /* [out] */ ICorDebugValue **ppValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRank( + /* [out] */ ULONG32 *pnRank) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugTypeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugType * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugType * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugType * This); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + ICorDebugType * This, + /* [out] */ CorElementType *ty); + + HRESULT ( STDMETHODCALLTYPE *GetClass )( + ICorDebugType * This, + /* [out] */ ICorDebugClass **ppClass); + + HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( + ICorDebugType * This, + /* [out] */ ICorDebugTypeEnum **ppTyParEnum); + + HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( + ICorDebugType * This, + /* [out] */ ICorDebugType **value); + + HRESULT ( STDMETHODCALLTYPE *GetBase )( + ICorDebugType * This, + /* [out] */ ICorDebugType **pBase); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( + ICorDebugType * This, + /* [in] */ mdFieldDef fieldDef, + /* [in] */ ICorDebugFrame *pFrame, + /* [out] */ ICorDebugValue **ppValue); + + HRESULT ( STDMETHODCALLTYPE *GetRank )( + ICorDebugType * This, + /* [out] */ ULONG32 *pnRank); + + END_INTERFACE + } ICorDebugTypeVtbl; + + interface ICorDebugType + { + CONST_VTBL struct ICorDebugTypeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugType_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugType_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugType_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugType_GetType(This,ty) \ + ( (This)->lpVtbl -> GetType(This,ty) ) + +#define ICorDebugType_GetClass(This,ppClass) \ + ( (This)->lpVtbl -> GetClass(This,ppClass) ) + +#define ICorDebugType_EnumerateTypeParameters(This,ppTyParEnum) \ + ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) + +#define ICorDebugType_GetFirstTypeParameter(This,value) \ + ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) + +#define ICorDebugType_GetBase(This,pBase) \ + ( (This)->lpVtbl -> GetBase(This,pBase) ) + +#define ICorDebugType_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ + ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) + +#define ICorDebugType_GetRank(This,pnRank) \ + ( (This)->lpVtbl -> GetRank(This,pnRank) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugType_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugType2_INTERFACE_DEFINED__ +#define __ICorDebugType2_INTERFACE_DEFINED__ + +/* interface ICorDebugType2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugType2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e6e91d79-693d-48bc-b417-8284b4f10fb5") + ICorDebugType2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTypeID( + /* [out] */ COR_TYPEID *id) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugType2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugType2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugType2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugType2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeID )( + ICorDebugType2 * This, + /* [out] */ COR_TYPEID *id); + + END_INTERFACE + } ICorDebugType2Vtbl; + + interface ICorDebugType2 + { + CONST_VTBL struct ICorDebugType2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugType2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugType2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugType2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugType2_GetTypeID(This,id) \ + ( (This)->lpVtbl -> GetTypeID(This,id) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugType2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ +#define __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugErrorInfoEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugErrorInfoEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F0E18809-72B5-11d2-976F-00A0C9B4D50C") + ICorDebugErrorInfoEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugErrorInfoEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugErrorInfoEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugErrorInfoEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugErrorInfoEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugErrorInfoEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugErrorInfoEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugErrorInfoEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugErrorInfoEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugErrorInfoEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugErrorInfoEnumVtbl; + + interface ICorDebugErrorInfoEnum + { + CONST_VTBL struct ICorDebugErrorInfoEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugErrorInfoEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugErrorInfoEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugErrorInfoEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugErrorInfoEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugErrorInfoEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugErrorInfoEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugErrorInfoEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugErrorInfoEnum_Next(This,celt,errors,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ +#define __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugAppDomainEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAppDomainEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("63ca1b24-4359-4883-bd57-13f815f58744") + ICorDebugAppDomainEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAppDomainEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAppDomainEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAppDomainEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAppDomainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugAppDomainEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugAppDomainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugAppDomainEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugAppDomainEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugAppDomainEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugAppDomainEnumVtbl; + + interface ICorDebugAppDomainEnum + { + CONST_VTBL struct ICorDebugAppDomainEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAppDomainEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAppDomainEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAppDomainEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAppDomainEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugAppDomainEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugAppDomainEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugAppDomainEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugAppDomainEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ +#define __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugAssemblyEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugAssemblyEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83") + ICorDebugAssemblyEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugAssemblyEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugAssemblyEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugAssemblyEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugAssemblyEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugAssemblyEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugAssemblyEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugAssemblyEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugAssemblyEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugAssemblyEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugAssemblyEnumVtbl; + + interface ICorDebugAssemblyEnum + { + CONST_VTBL struct ICorDebugAssemblyEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugAssemblyEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugAssemblyEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugAssemblyEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugAssemblyEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugAssemblyEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugAssemblyEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugAssemblyEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugAssemblyEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ +#define __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugBlockingObjectEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("976A6278-134A-4a81-81A3-8F277943F4C3") + ICorDebugBlockingObjectEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugBlockingObjectEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugBlockingObjectEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugBlockingObjectEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugBlockingObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugBlockingObjectEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugBlockingObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugBlockingObjectEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugBlockingObjectEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugBlockingObjectEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugBlockingObjectEnumVtbl; + + interface ICorDebugBlockingObjectEnum + { + CONST_VTBL struct ICorDebugBlockingObjectEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugBlockingObjectEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugBlockingObjectEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugBlockingObjectEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugBlockingObjectEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugBlockingObjectEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugBlockingObjectEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugBlockingObjectEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugBlockingObjectEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0125 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0125_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0125_v0_0_s_ifspec; + +#ifndef __ICorDebugMDA_INTERFACE_DEFINED__ +#define __ICorDebugMDA_INTERFACE_DEFINED__ + +/* interface ICorDebugMDA */ +/* [unique][uuid][local][object] */ + +typedef +enum CorDebugMDAFlags + { + MDA_FLAG_SLIP = 0x2 + } CorDebugMDAFlags; + + +EXTERN_C const IID IID_ICorDebugMDA; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC726F2F-1DB7-459b-B0EC-05F01D841B42") + ICorDebugMDA : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDescription( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetXML( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [in] */ CorDebugMDAFlags *pFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( + /* [out] */ DWORD *pOsTid) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugMDAVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugMDA * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugMDA * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugMDA * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorDebugMDA * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetDescription )( + ICorDebugMDA * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetXML )( + ICorDebugMDA * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + ICorDebugMDA * This, + /* [in] */ CorDebugMDAFlags *pFlags); + + HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( + ICorDebugMDA * This, + /* [out] */ DWORD *pOsTid); + + END_INTERFACE + } ICorDebugMDAVtbl; + + interface ICorDebugMDA + { + CONST_VTBL struct ICorDebugMDAVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugMDA_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugMDA_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugMDA_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugMDA_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ICorDebugMDA_GetDescription(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) + +#define ICorDebugMDA_GetXML(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) + +#define ICorDebugMDA_GetFlags(This,pFlags) \ + ( (This)->lpVtbl -> GetFlags(This,pFlags) ) + +#define ICorDebugMDA_GetOSThreadId(This,pOsTid) \ + ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugMDA_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0126 */ +/* [local] */ + +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0126_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0126_v0_0_s_ifspec; + +#ifndef __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ +#define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ + +/* interface ICorDebugEditAndContinueErrorInfo */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8D600D41-F4F6-4cb3-B7EC-7BD164944036") + ICorDebugEditAndContinueErrorInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ ICorDebugModule **ppModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetToken( + /* [out] */ mdToken *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetErrorCode( + /* [out] */ HRESULT *pHr) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetString( + /* [in] */ ULONG32 cchString, + /* [out] */ ULONG32 *pcchString, + /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugEditAndContinueErrorInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugEditAndContinueErrorInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugEditAndContinueErrorInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugEditAndContinueErrorInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ICorDebugEditAndContinueErrorInfo * This, + /* [out] */ ICorDebugModule **ppModule); + + HRESULT ( STDMETHODCALLTYPE *GetToken )( + ICorDebugEditAndContinueErrorInfo * This, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( + ICorDebugEditAndContinueErrorInfo * This, + /* [out] */ HRESULT *pHr); + + HRESULT ( STDMETHODCALLTYPE *GetString )( + ICorDebugEditAndContinueErrorInfo * This, + /* [in] */ ULONG32 cchString, + /* [out] */ ULONG32 *pcchString, + /* [length_is][size_is][out] */ WCHAR szString[ ]); + + END_INTERFACE + } ICorDebugEditAndContinueErrorInfoVtbl; + + interface ICorDebugEditAndContinueErrorInfo + { + CONST_VTBL struct ICorDebugEditAndContinueErrorInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugEditAndContinueErrorInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugEditAndContinueErrorInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugEditAndContinueErrorInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugEditAndContinueErrorInfo_GetModule(This,ppModule) \ + ( (This)->lpVtbl -> GetModule(This,ppModule) ) + +#define ICorDebugEditAndContinueErrorInfo_GetToken(This,pToken) \ + ( (This)->lpVtbl -> GetToken(This,pToken) ) + +#define ICorDebugEditAndContinueErrorInfo_GetErrorCode(This,pHr) \ + ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) + +#define ICorDebugEditAndContinueErrorInfo_GetString(This,cchString,pcchString,szString) \ + ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_cordebug_0000_0127 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0127_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0127_v0_0_s_ifspec; + +#ifndef __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ +#define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ + +/* interface ICorDebugEditAndContinueSnapshot */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6DC3FA01-D7CB-11d2-8A95-0080C792E5D8") + ICorDebugEditAndContinueSnapshot : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CopyMetaData( + /* [in] */ IStream *pIStream, + /* [out] */ GUID *pMvid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMvid( + /* [out] */ GUID *pMvid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( + /* [out] */ ULONG32 *pRoDataRVA) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( + /* [out] */ ULONG32 *pRwDataRVA) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPEBytes( + /* [in] */ IStream *pIStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILMap( + /* [in] */ mdToken mdFunction, + /* [in] */ ULONG cMapSize, + /* [size_is][in] */ COR_IL_MAP map[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( + /* [in] */ IStream *pIStream) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugEditAndContinueSnapshotVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugEditAndContinueSnapshot * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugEditAndContinueSnapshot * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugEditAndContinueSnapshot * This); + + HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( + ICorDebugEditAndContinueSnapshot * This, + /* [in] */ IStream *pIStream, + /* [out] */ GUID *pMvid); + + HRESULT ( STDMETHODCALLTYPE *GetMvid )( + ICorDebugEditAndContinueSnapshot * This, + /* [out] */ GUID *pMvid); + + HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( + ICorDebugEditAndContinueSnapshot * This, + /* [out] */ ULONG32 *pRoDataRVA); + + HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( + ICorDebugEditAndContinueSnapshot * This, + /* [out] */ ULONG32 *pRwDataRVA); + + HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( + ICorDebugEditAndContinueSnapshot * This, + /* [in] */ IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *SetILMap )( + ICorDebugEditAndContinueSnapshot * This, + /* [in] */ mdToken mdFunction, + /* [in] */ ULONG cMapSize, + /* [size_is][in] */ COR_IL_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( + ICorDebugEditAndContinueSnapshot * This, + /* [in] */ IStream *pIStream); + + END_INTERFACE + } ICorDebugEditAndContinueSnapshotVtbl; + + interface ICorDebugEditAndContinueSnapshot + { + CONST_VTBL struct ICorDebugEditAndContinueSnapshotVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugEditAndContinueSnapshot_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugEditAndContinueSnapshot_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugEditAndContinueSnapshot_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugEditAndContinueSnapshot_CopyMetaData(This,pIStream,pMvid) \ + ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) + +#define ICorDebugEditAndContinueSnapshot_GetMvid(This,pMvid) \ + ( (This)->lpVtbl -> GetMvid(This,pMvid) ) + +#define ICorDebugEditAndContinueSnapshot_GetRoDataRVA(This,pRoDataRVA) \ + ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) + +#define ICorDebugEditAndContinueSnapshot_GetRwDataRVA(This,pRwDataRVA) \ + ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) + +#define ICorDebugEditAndContinueSnapshot_SetPEBytes(This,pIStream) \ + ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) + +#define ICorDebugEditAndContinueSnapshot_SetILMap(This,mdFunction,cMapSize,map) \ + ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) + +#define ICorDebugEditAndContinueSnapshot_SetPESymbolBytes(This,pIStream) \ + ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ +#define __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ + +/* interface ICorDebugExceptionObjectCallStackEnum */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ED775530-4DC4-41F7-86D0-9E2DEF7DFC66") + ICorDebugExceptionObjectCallStackEnum : public ICorDebugEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugExceptionObjectCallStackEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugExceptionObjectCallStackEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugExceptionObjectCallStackEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugExceptionObjectCallStackEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorDebugExceptionObjectCallStackEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorDebugExceptionObjectCallStackEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorDebugExceptionObjectCallStackEnum * This, + /* [out] */ ICorDebugEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorDebugExceptionObjectCallStackEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorDebugExceptionObjectCallStackEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorDebugExceptionObjectCallStackEnumVtbl; + + interface ICorDebugExceptionObjectCallStackEnum + { + CONST_VTBL struct ICorDebugExceptionObjectCallStackEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugExceptionObjectCallStackEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugExceptionObjectCallStackEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugExceptionObjectCallStackEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugExceptionObjectCallStackEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorDebugExceptionObjectCallStackEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorDebugExceptionObjectCallStackEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorDebugExceptionObjectCallStackEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorDebugExceptionObjectCallStackEnum_Next(This,celt,values,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ +#define __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ + +/* interface ICorDebugExceptionObjectValue */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugExceptionObjectValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AE4CA65D-59DD-42A2-83A5-57E8A08D8719") + ICorDebugExceptionObjectValue : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( + /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugExceptionObjectValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugExceptionObjectValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugExceptionObjectValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugExceptionObjectValue * This); + + HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( + ICorDebugExceptionObjectValue * This, + /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum); + + END_INTERFACE + } ICorDebugExceptionObjectValueVtbl; + + interface ICorDebugExceptionObjectValue + { + CONST_VTBL struct ICorDebugExceptionObjectValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugExceptionObjectValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugExceptionObjectValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugExceptionObjectValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugExceptionObjectValue_EnumerateExceptionCallStack(This,ppCallStackEnum) \ + ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ */ + + + +#ifndef __CORDBLib_LIBRARY_DEFINED__ +#define __CORDBLib_LIBRARY_DEFINED__ + +/* library CORDBLib */ +/* [helpstring][version][uuid] */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EXTERN_C const IID LIBID_CORDBLib; + +EXTERN_C const CLSID CLSID_CorDebug; + +#ifdef __cplusplus + +class DECLSPEC_UUID("6fef44d0-39e7-4c77-be8e-c9f8cf988630") +CorDebug; +#endif + +EXTERN_C const CLSID CLSID_EmbeddedCLRCorDebug; + +#ifdef __cplusplus + +class DECLSPEC_UUID("211f1254-bc7e-4af5-b9aa-067308d83dd1") +EmbeddedCLRCorDebug; +#endif +#endif /* __CORDBLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/corerror.h b/lib/coreclr/src/pal/prebuilt/inc/corerror.h new file mode 100644 index 0000000000..15dc301546 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/corerror.h @@ -0,0 +1,421 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__ +#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__ + +#include + + +// +//This file is AutoGenerated -- Do Not Edit by hand!!! +// +//Add new HRESULTS along with their corresponding error messages to +//corerror.xml +// + +#ifndef FACILITY_URT +#define FACILITY_URT 0x13 +#endif +#ifndef EMAKEHR +#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val) +#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val) +#endif + +#define CLDB_S_TRUNCATION SMAKEHR(0x1106) +#define META_S_DUPLICATE SMAKEHR(0x1197) +#define CORDBG_S_BAD_START_SEQUENCE_POINT SMAKEHR(0x130b) +#define CORDBG_S_BAD_END_SEQUENCE_POINT SMAKEHR(0x130c) +#define CORDBG_S_FUNC_EVAL_HAS_NO_RESULT SMAKEHR(0x1316) +#define CORDBG_S_VALUE_POINTS_TO_VOID SMAKEHR(0x1317) +#define CORDBG_S_FUNC_EVAL_ABORTED SMAKEHR(0x1319) +#define CORDBG_S_AT_END_OF_STACK SMAKEHR(0x1324) +#define CORDBG_S_NOT_ALL_BITS_SET SMAKEHR(0x1c13) +#define CEE_E_CVTRES_NOT_FOUND EMAKEHR(0x1001) +#define COR_E_TYPEUNLOADED EMAKEHR(0x1013) +#define COR_E_APPDOMAINUNLOADED EMAKEHR(0x1014) +#define COR_E_CANNOTUNLOADAPPDOMAIN EMAKEHR(0x1015) +#define MSEE_E_ASSEMBLYLOADINPROGRESS EMAKEHR(0x1016) +#define COR_E_ASSEMBLYEXPECTED EMAKEHR(0x1018) +#define COR_E_FIXUPSINEXE EMAKEHR(0x1019) +#define COR_E_NEWER_RUNTIME EMAKEHR(0x101b) +#define COR_E_MULTIMODULEASSEMBLIESDIALLOWED EMAKEHR(0x101e) +#define HOST_E_DEADLOCK EMAKEHR(0x1020) +#define HOST_E_INVALIDOPERATION EMAKEHR(0x1022) +#define HOST_E_CLRNOTAVAILABLE EMAKEHR(0x1023) +#define HOST_E_EXITPROCESS_THREADABORT EMAKEHR(0x1027) +#define HOST_E_EXITPROCESS_ADUNLOAD EMAKEHR(0x1028) +#define HOST_E_EXITPROCESS_TIMEOUT EMAKEHR(0x1029) +#define HOST_E_EXITPROCESS_OUTOFMEMORY EMAKEHR(0x102a) +#define COR_E_MODULE_HASH_CHECK_FAILED EMAKEHR(0x1039) +#define FUSION_E_REF_DEF_MISMATCH EMAKEHR(0x1040) +#define FUSION_E_INVALID_PRIVATE_ASM_LOCATION EMAKEHR(0x1041) +#define FUSION_E_ASM_MODULE_MISSING EMAKEHR(0x1042) +#define FUSION_E_PRIVATE_ASM_DISALLOWED EMAKEHR(0x1044) +#define FUSION_E_SIGNATURE_CHECK_FAILED EMAKEHR(0x1045) +#define FUSION_E_INVALID_NAME EMAKEHR(0x1047) +#define FUSION_E_CODE_DOWNLOAD_DISABLED EMAKEHR(0x1048) +#define FUSION_E_HOST_GAC_ASM_MISMATCH EMAKEHR(0x1050) +#define FUSION_E_LOADFROM_BLOCKED EMAKEHR(0x1051) +#define FUSION_E_CACHEFILE_FAILED EMAKEHR(0x1052) +#define FUSION_E_APP_DOMAIN_LOCKED EMAKEHR(0x1053) +#define FUSION_E_CONFIGURATION_ERROR EMAKEHR(0x1054) +#define FUSION_E_MANIFEST_PARSE_ERROR EMAKEHR(0x1055) +#define COR_E_LOADING_REFERENCE_ASSEMBLY EMAKEHR(0x1058) +#define COR_E_NI_AND_RUNTIME_VERSION_MISMATCH EMAKEHR(0x1059) +#define COR_E_LOADING_WINMD_REFERENCE_ASSEMBLY EMAKEHR(0x1069) +#define COR_E_AMBIGUOUSIMPLEMENTATION EMAKEHR(0x106a) +#define CLDB_E_FILE_BADREAD EMAKEHR(0x1100) +#define CLDB_E_FILE_BADWRITE EMAKEHR(0x1101) +#define CLDB_E_FILE_OLDVER EMAKEHR(0x1107) +#define CLDB_E_SMDUPLICATE EMAKEHR(0x110a) +#define CLDB_E_NO_DATA EMAKEHR(0x110b) +#define CLDB_E_INCOMPATIBLE EMAKEHR(0x110d) +#define CLDB_E_FILE_CORRUPT EMAKEHR(0x110e) +#define CLDB_E_BADUPDATEMODE EMAKEHR(0x1110) +#define CLDB_E_INDEX_NOTFOUND EMAKEHR(0x1124) +#define CLDB_E_RECORD_NOTFOUND EMAKEHR(0x1130) +#define CLDB_E_RECORD_OUTOFORDER EMAKEHR(0x1135) +#define CLDB_E_TOO_BIG EMAKEHR(0x1154) +#define META_E_INVALID_TOKEN_TYPE EMAKEHR(0x115f) +#define TLBX_E_LIBNOTREGISTERED EMAKEHR(0x1165) +#define META_E_BADMETADATA EMAKEHR(0x118a) +#define META_E_BAD_SIGNATURE EMAKEHR(0x1192) +#define META_E_BAD_INPUT_PARAMETER EMAKEHR(0x1193) +#define META_E_CANNOTRESOLVETYPEREF EMAKEHR(0x1196) +#define META_E_STRINGSPACE_FULL EMAKEHR(0x1198) +#define META_E_HAS_UNMARKALL EMAKEHR(0x119a) +#define META_E_MUST_CALL_UNMARKALL EMAKEHR(0x119b) +#define META_E_CA_INVALID_TARGET EMAKEHR(0x11c0) +#define META_E_CA_INVALID_VALUE EMAKEHR(0x11c1) +#define META_E_CA_INVALID_BLOB EMAKEHR(0x11c2) +#define META_E_CA_REPEATED_ARG EMAKEHR(0x11c3) +#define META_E_CA_UNKNOWN_ARGUMENT EMAKEHR(0x11c4) +#define META_E_CA_UNEXPECTED_TYPE EMAKEHR(0x11c7) +#define META_E_CA_INVALID_ARGTYPE EMAKEHR(0x11c8) +#define META_E_CA_INVALID_ARG_FOR_TYPE EMAKEHR(0x11c9) +#define META_E_CA_INVALID_UUID EMAKEHR(0x11ca) +#define META_E_CA_INVALID_MARSHALAS_FIELDS EMAKEHR(0x11cb) +#define META_E_CA_NT_FIELDONLY EMAKEHR(0x11cc) +#define META_E_CA_NEGATIVE_PARAMINDEX EMAKEHR(0x11cd) +#define META_E_CA_NEGATIVE_CONSTSIZE EMAKEHR(0x11cf) +#define META_E_CA_FIXEDSTR_SIZE_REQUIRED EMAKEHR(0x11d0) +#define META_E_CA_CUSTMARSH_TYPE_REQUIRED EMAKEHR(0x11d1) +#define META_E_NOT_IN_ENC_MODE EMAKEHR(0x11d4) +#define META_E_CA_BAD_FRIENDS_ARGS EMAKEHR(0x11e5) +#define META_E_CA_FRIENDS_SN_REQUIRED EMAKEHR(0x11e6) +#define VLDTR_E_RID_OUTOFRANGE EMAKEHR(0x1203) +#define VLDTR_E_STRING_INVALID EMAKEHR(0x1206) +#define VLDTR_E_GUID_INVALID EMAKEHR(0x1207) +#define VLDTR_E_BLOB_INVALID EMAKEHR(0x1208) +#define VLDTR_E_MR_BADCALLINGCONV EMAKEHR(0x1224) +#define VLDTR_E_SIGNULL EMAKEHR(0x1237) +#define VLDTR_E_MD_BADCALLINGCONV EMAKEHR(0x1239) +#define VLDTR_E_MD_THISSTATIC EMAKEHR(0x123a) +#define VLDTR_E_MD_NOTTHISNOTSTATIC EMAKEHR(0x123b) +#define VLDTR_E_MD_NOARGCNT EMAKEHR(0x123c) +#define VLDTR_E_SIG_MISSELTYPE EMAKEHR(0x123d) +#define VLDTR_E_SIG_MISSTKN EMAKEHR(0x123e) +#define VLDTR_E_SIG_TKNBAD EMAKEHR(0x123f) +#define VLDTR_E_SIG_MISSFPTR EMAKEHR(0x1240) +#define VLDTR_E_SIG_MISSFPTRARGCNT EMAKEHR(0x1241) +#define VLDTR_E_SIG_MISSRANK EMAKEHR(0x1242) +#define VLDTR_E_SIG_MISSNSIZE EMAKEHR(0x1243) +#define VLDTR_E_SIG_MISSSIZE EMAKEHR(0x1244) +#define VLDTR_E_SIG_MISSNLBND EMAKEHR(0x1245) +#define VLDTR_E_SIG_MISSLBND EMAKEHR(0x1246) +#define VLDTR_E_SIG_BADELTYPE EMAKEHR(0x1247) +#define VLDTR_E_TD_ENCLNOTNESTED EMAKEHR(0x1256) +#define VLDTR_E_FMD_PINVOKENOTSTATIC EMAKEHR(0x1277) +#define VLDTR_E_SIG_SENTINMETHODDEF EMAKEHR(0x12df) +#define VLDTR_E_SIG_SENTMUSTVARARG EMAKEHR(0x12e0) +#define VLDTR_E_SIG_MULTSENTINELS EMAKEHR(0x12e1) +#define VLDTR_E_SIG_MISSARG EMAKEHR(0x12e3) +#define VLDTR_E_SIG_BYREFINFIELD EMAKEHR(0x12e4) +#define CORDBG_E_UNRECOVERABLE_ERROR EMAKEHR(0x1300) +#define CORDBG_E_PROCESS_TERMINATED EMAKEHR(0x1301) +#define CORDBG_E_PROCESS_NOT_SYNCHRONIZED EMAKEHR(0x1302) +#define CORDBG_E_CLASS_NOT_LOADED EMAKEHR(0x1303) +#define CORDBG_E_IL_VAR_NOT_AVAILABLE EMAKEHR(0x1304) +#define CORDBG_E_BAD_REFERENCE_VALUE EMAKEHR(0x1305) +#define CORDBG_E_FIELD_NOT_AVAILABLE EMAKEHR(0x1306) +#define CORDBG_E_NON_NATIVE_FRAME EMAKEHR(0x1307) +#define CORDBG_E_CODE_NOT_AVAILABLE EMAKEHR(0x1309) +#define CORDBG_E_FUNCTION_NOT_IL EMAKEHR(0x130a) +#define CORDBG_E_CANT_SET_IP_INTO_FINALLY EMAKEHR(0x130e) +#define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY EMAKEHR(0x130f) +#define CORDBG_E_CANT_SET_IP_INTO_CATCH EMAKEHR(0x1310) +#define CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1311) +#define CORDBG_E_SET_IP_IMPOSSIBLE EMAKEHR(0x1312) +#define CORDBG_E_FUNC_EVAL_BAD_START_POINT EMAKEHR(0x1313) +#define CORDBG_E_INVALID_OBJECT EMAKEHR(0x1314) +#define CORDBG_E_FUNC_EVAL_NOT_COMPLETE EMAKEHR(0x1315) +#define CORDBG_E_STATIC_VAR_NOT_AVAILABLE EMAKEHR(0x131a) +#define CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER EMAKEHR(0x131c) +#define CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE EMAKEHR(0x131d) +#define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 EMAKEHR(0x131e) +#define CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 EMAKEHR(0x131f) +#define CORDBG_E_CANT_SET_TO_JMC EMAKEHR(0x1323) +#define CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME EMAKEHR(0x1325) +#define CORDBG_E_NOT_CHILD_FRAME EMAKEHR(0x1326) +#define CORDBG_E_NON_MATCHING_CONTEXT EMAKEHR(0x1327) +#define CORDBG_E_PAST_END_OF_STACK EMAKEHR(0x1328) +#define CORDBG_E_FUNC_EVAL_CANNOT_UPDATE_REGISTER_IN_NONLEAF_FRAME EMAKEHR(0x1329) +#define CORDBG_E_BAD_THREAD_STATE EMAKEHR(0x132d) +#define CORDBG_E_DEBUGGER_ALREADY_ATTACHED EMAKEHR(0x132e) +#define CORDBG_E_SUPERFLOUS_CONTINUE EMAKEHR(0x132f) +#define CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1330) +#define CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED EMAKEHR(0x1332) +#define CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION EMAKEHR(0x1333) +#define CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL EMAKEHR(0x1334) +#define CORDBG_E_PROCESS_DETACHED EMAKEHR(0x1335) +#define CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS EMAKEHR(0x1338) +#define CORDBG_E_FIELD_NOT_STATIC EMAKEHR(0x133b) +#define CORDBG_E_FIELD_NOT_INSTANCE EMAKEHR(0x133c) +#define CORDBG_E_ENC_JIT_CANT_UPDATE EMAKEHR(0x133f) +#define CORDBG_E_ENC_INTERNAL_ERROR EMAKEHR(0x1341) +#define CORDBG_E_ENC_HANGING_FIELD EMAKEHR(0x1342) +#define CORDBG_E_MODULE_NOT_LOADED EMAKEHR(0x1343) +#define CORDBG_E_UNABLE_TO_SET_BREAKPOINT EMAKEHR(0x1345) +#define CORDBG_E_DEBUGGING_NOT_POSSIBLE EMAKEHR(0x1346) +#define CORDBG_E_KERNEL_DEBUGGER_ENABLED EMAKEHR(0x1347) +#define CORDBG_E_KERNEL_DEBUGGER_PRESENT EMAKEHR(0x1348) +#define CORDBG_E_INCOMPATIBLE_PROTOCOL EMAKEHR(0x134b) +#define CORDBG_E_TOO_MANY_PROCESSES EMAKEHR(0x134c) +#define CORDBG_E_INTEROP_NOT_SUPPORTED EMAKEHR(0x134d) +#define CORDBG_E_NO_REMAP_BREAKPIONT EMAKEHR(0x134e) +#define CORDBG_E_OBJECT_NEUTERED EMAKEHR(0x134f) +#define CORPROF_E_FUNCTION_NOT_COMPILED EMAKEHR(0x1350) +#define CORPROF_E_DATAINCOMPLETE EMAKEHR(0x1351) +#define CORPROF_E_FUNCTION_NOT_IL EMAKEHR(0x1354) +#define CORPROF_E_NOT_MANAGED_THREAD EMAKEHR(0x1355) +#define CORPROF_E_CALL_ONLY_FROM_INIT EMAKEHR(0x1356) +#define CORPROF_E_NOT_YET_AVAILABLE EMAKEHR(0x135b) +#define CORPROF_E_TYPE_IS_PARAMETERIZED EMAKEHR(0x135c) +#define CORPROF_E_FUNCTION_IS_PARAMETERIZED EMAKEHR(0x135d) +#define CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD EMAKEHR(0x135e) +#define CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX EMAKEHR(0x135f) +#define CORPROF_E_STACKSNAPSHOT_UNSAFE EMAKEHR(0x1360) +#define CORPROF_E_STACKSNAPSHOT_ABORTED EMAKEHR(0x1361) +#define CORPROF_E_LITERALS_HAVE_NO_ADDRESS EMAKEHR(0x1362) +#define CORPROF_E_UNSUPPORTED_CALL_SEQUENCE EMAKEHR(0x1363) +#define CORPROF_E_ASYNCHRONOUS_UNSAFE EMAKEHR(0x1364) +#define CORPROF_E_CLASSID_IS_ARRAY EMAKEHR(0x1365) +#define CORPROF_E_CLASSID_IS_COMPOSITE EMAKEHR(0x1366) +#define CORPROF_E_PROFILER_DETACHING EMAKEHR(0x1367) +#define CORPROF_E_PROFILER_NOT_ATTACHABLE EMAKEHR(0x1368) +#define CORPROF_E_UNRECOGNIZED_PIPE_MSG_FORMAT EMAKEHR(0x1369) +#define CORPROF_E_PROFILER_ALREADY_ACTIVE EMAKEHR(0x136a) +#define CORPROF_E_PROFILEE_INCOMPATIBLE_WITH_TRIGGER EMAKEHR(0x136b) +#define CORPROF_E_IPC_FAILED EMAKEHR(0x136c) +#define CORPROF_E_PROFILEE_PROCESS_NOT_FOUND EMAKEHR(0x136d) +#define CORPROF_E_CALLBACK3_REQUIRED EMAKEHR(0x136e) +#define CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER EMAKEHR(0x136f) +#define CORPROF_E_IRREVERSIBLE_INSTRUMENTATION_PRESENT EMAKEHR(0x1370) +#define CORPROF_E_RUNTIME_UNINITIALIZED EMAKEHR(0x1371) +#define CORPROF_E_IMMUTABLE_FLAGS_SET EMAKEHR(0x1372) +#define CORPROF_E_PROFILER_NOT_YET_INITIALIZED EMAKEHR(0x1373) +#define CORPROF_E_INCONSISTENT_WITH_FLAGS EMAKEHR(0x1374) +#define CORPROF_E_PROFILER_CANCEL_ACTIVATION EMAKEHR(0x1375) +#define CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE EMAKEHR(0x1376) +#define CORPROF_E_DEBUGGING_DISABLED EMAKEHR(0x1378) +#define CORPROF_E_TIMEOUT_WAITING_FOR_CONCURRENT_GC EMAKEHR(0x1379) +#define CORPROF_E_MODULE_IS_DYNAMIC EMAKEHR(0x137a) +#define CORPROF_E_CALLBACK4_REQUIRED EMAKEHR(0x137b) +#define CORPROF_E_REJIT_NOT_ENABLED EMAKEHR(0x137c) +#define CORPROF_E_FUNCTION_IS_COLLECTIBLE EMAKEHR(0x137e) +#define CORPROF_E_CALLBACK6_REQUIRED EMAKEHR(0x1380) +#define CORPROF_E_CALLBACK7_REQUIRED EMAKEHR(0x1382) +#define CORPROF_E_REJIT_INLINING_DISABLED EMAKEHR(0x1383) +#define CORDIAGIPC_E_BAD_ENCODING EMAKEHR(0x1384) +#define CORDIAGIPC_E_UNKNOWN_COMMAND EMAKEHR(0x1385) +#define CORDIAGIPC_E_UNKNOWN_MAGIC EMAKEHR(0x1386) +#define CORDIAGIPC_E_UNKNOWN_ERROR EMAKEHR(0x1387) +#define CORPROF_E_SUSPENSION_IN_PROGRESS EMAKEHR(0x1388) +#define SECURITY_E_INCOMPATIBLE_SHARE EMAKEHR(0x1401) +#define SECURITY_E_UNVERIFIABLE EMAKEHR(0x1402) +#define SECURITY_E_INCOMPATIBLE_EVIDENCE EMAKEHR(0x1403) +#define CORSEC_E_POLICY_EXCEPTION EMAKEHR(0x1416) +#define CORSEC_E_MIN_GRANT_FAIL EMAKEHR(0x1417) +#define CORSEC_E_NO_EXEC_PERM EMAKEHR(0x1418) +#define CORSEC_E_XMLSYNTAX EMAKEHR(0x1419) +#define CORSEC_E_INVALID_STRONGNAME EMAKEHR(0x141a) +#define CORSEC_E_MISSING_STRONGNAME EMAKEHR(0x141b) +#define CORSEC_E_INVALID_IMAGE_FORMAT EMAKEHR(0x141d) +#define CORSEC_E_INVALID_PUBLICKEY EMAKEHR(0x141e) +#define CORSEC_E_SIGNATURE_MISMATCH EMAKEHR(0x1420) +#define CORSEC_E_CRYPTO EMAKEHR(0x1430) +#define CORSEC_E_CRYPTO_UNEX_OPER EMAKEHR(0x1431) +#define CORSECATTR_E_BAD_ACTION EMAKEHR(0x1442) +#define COR_E_EXCEPTION EMAKEHR(0x1500) +#define COR_E_SYSTEM EMAKEHR(0x1501) +#define COR_E_ARGUMENTOUTOFRANGE EMAKEHR(0x1502) +#define COR_E_ARRAYTYPEMISMATCH EMAKEHR(0x1503) +#define COR_E_CONTEXTMARSHAL EMAKEHR(0x1504) +#define COR_E_TIMEOUT EMAKEHR(0x1505) +#define COR_E_EXECUTIONENGINE EMAKEHR(0x1506) +#define COR_E_FIELDACCESS EMAKEHR(0x1507) +#define COR_E_INDEXOUTOFRANGE EMAKEHR(0x1508) +#define COR_E_INVALIDOPERATION EMAKEHR(0x1509) +#define COR_E_SECURITY EMAKEHR(0x150a) +#define COR_E_SERIALIZATION EMAKEHR(0x150c) +#define COR_E_VERIFICATION EMAKEHR(0x150d) +#define COR_E_METHODACCESS EMAKEHR(0x1510) +#define COR_E_MISSINGFIELD EMAKEHR(0x1511) +#define COR_E_MISSINGMEMBER EMAKEHR(0x1512) +#define COR_E_MISSINGMETHOD EMAKEHR(0x1513) +#define COR_E_MULTICASTNOTSUPPORTED EMAKEHR(0x1514) +#define COR_E_NOTSUPPORTED EMAKEHR(0x1515) +#define COR_E_OVERFLOW EMAKEHR(0x1516) +#define COR_E_RANK EMAKEHR(0x1517) +#define COR_E_SYNCHRONIZATIONLOCK EMAKEHR(0x1518) +#define COR_E_THREADINTERRUPTED EMAKEHR(0x1519) +#define COR_E_MEMBERACCESS EMAKEHR(0x151a) +#define COR_E_THREADSTATE EMAKEHR(0x1520) +#define COR_E_THREADSTOP EMAKEHR(0x1521) +#define COR_E_TYPELOAD EMAKEHR(0x1522) +#define COR_E_ENTRYPOINTNOTFOUND EMAKEHR(0x1523) +#define COR_E_DLLNOTFOUND EMAKEHR(0x1524) +#define COR_E_THREADSTART EMAKEHR(0x1525) +#define COR_E_INVALIDCOMOBJECT EMAKEHR(0x1527) +#define COR_E_NOTFINITENUMBER EMAKEHR(0x1528) +#define COR_E_DUPLICATEWAITOBJECT EMAKEHR(0x1529) +#define COR_E_SEMAPHOREFULL EMAKEHR(0x152b) +#define COR_E_WAITHANDLECANNOTBEOPENED EMAKEHR(0x152c) +#define COR_E_ABANDONEDMUTEX EMAKEHR(0x152d) +#define COR_E_THREADABORTED EMAKEHR(0x1530) +#define COR_E_INVALIDOLEVARIANTTYPE EMAKEHR(0x1531) +#define COR_E_MISSINGMANIFESTRESOURCE EMAKEHR(0x1532) +#define COR_E_SAFEARRAYTYPEMISMATCH EMAKEHR(0x1533) +#define COR_E_TYPEINITIALIZATION EMAKEHR(0x1534) +#define COR_E_MARSHALDIRECTIVE EMAKEHR(0x1535) +#define COR_E_MISSINGSATELLITEASSEMBLY EMAKEHR(0x1536) +#define COR_E_FORMAT EMAKEHR(0x1537) +#define COR_E_SAFEARRAYRANKMISMATCH EMAKEHR(0x1538) +#define COR_E_PLATFORMNOTSUPPORTED EMAKEHR(0x1539) +#define COR_E_INVALIDPROGRAM EMAKEHR(0x153a) +#define COR_E_OPERATIONCANCELED EMAKEHR(0x153b) +#define COR_E_INSUFFICIENTMEMORY EMAKEHR(0x153d) +#define COR_E_RUNTIMEWRAPPED EMAKEHR(0x153e) +#define COR_E_DATAMISALIGNED EMAKEHR(0x1541) +#define COR_E_CODECONTRACTFAILED EMAKEHR(0x1542) +#define COR_E_TYPEACCESS EMAKEHR(0x1543) +#define COR_E_ACCESSING_CCW EMAKEHR(0x1544) +#define COR_E_KEYNOTFOUND EMAKEHR(0x1577) +#define COR_E_INSUFFICIENTEXECUTIONSTACK EMAKEHR(0x1578) +#define COR_E_APPLICATION EMAKEHR(0x1600) +#define COR_E_INVALIDFILTERCRITERIA EMAKEHR(0x1601) +#define COR_E_REFLECTIONTYPELOAD EMAKEHR(0x1602) +#define COR_E_TARGET EMAKEHR(0x1603) +#define COR_E_TARGETINVOCATION EMAKEHR(0x1604) +#define COR_E_CUSTOMATTRIBUTEFORMAT EMAKEHR(0x1605) +#define COR_E_IO EMAKEHR(0x1620) +#define COR_E_FILELOAD EMAKEHR(0x1621) +#define COR_E_OBJECTDISPOSED EMAKEHR(0x1622) +#define COR_E_FAILFAST EMAKEHR(0x1623) +#define COR_E_HOSTPROTECTION EMAKEHR(0x1640) +#define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641) +#define CLR_E_SHIM_RUNTIMELOAD EMAKEHR(0x1700) +#define CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND EMAKEHR(0x1704) +#define VER_E_FIELD_SIG EMAKEHR(0x1815) +#define VER_E_CIRCULAR_VAR_CONSTRAINTS EMAKEHR(0x18ce) +#define VER_E_CIRCULAR_MVAR_CONSTRAINTS EMAKEHR(0x18cf) +#define COR_E_Data EMAKEHR(0x1920) +#define VLDTR_E_SIG_BADVOID EMAKEHR(0x1b24) +#define VLDTR_E_GP_ILLEGAL_VARIANT_MVAR EMAKEHR(0x1b2d) +#define CORDBG_E_THREAD_NOT_SCHEDULED EMAKEHR(0x1c00) +#define CORDBG_E_HANDLE_HAS_BEEN_DISPOSED EMAKEHR(0x1c01) +#define CORDBG_E_NONINTERCEPTABLE_EXCEPTION EMAKEHR(0x1c02) +#define CORDBG_E_INTERCEPT_FRAME_ALREADY_SET EMAKEHR(0x1c04) +#define CORDBG_E_NO_NATIVE_PATCH_AT_ADDR EMAKEHR(0x1c05) +#define CORDBG_E_MUST_BE_INTEROP_DEBUGGING EMAKEHR(0x1c06) +#define CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR EMAKEHR(0x1c07) +#define CORDBG_E_TIMEOUT EMAKEHR(0x1c08) +#define CORDBG_E_CANT_CALL_ON_THIS_THREAD EMAKEHR(0x1c09) +#define CORDBG_E_ENC_INFOLESS_METHOD EMAKEHR(0x1c0a) +#define CORDBG_E_ENC_IN_FUNCLET EMAKEHR(0x1c0c) +#define CORDBG_E_ENC_EDIT_NOT_SUPPORTED EMAKEHR(0x1c0e) +#define CORDBG_E_NOTREADY EMAKEHR(0x1c10) +#define CORDBG_E_CANNOT_RESOLVE_ASSEMBLY EMAKEHR(0x1c11) +#define CORDBG_E_MUST_BE_IN_LOAD_MODULE EMAKEHR(0x1c12) +#define CORDBG_E_CANNOT_BE_ON_ATTACH EMAKEHR(0x1c13) +#define CORDBG_E_NGEN_NOT_SUPPORTED EMAKEHR(0x1c14) +#define CORDBG_E_ILLEGAL_SHUTDOWN_ORDER EMAKEHR(0x1c15) +#define CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS EMAKEHR(0x1c16) +#define CORDBG_E_MUST_BE_IN_CREATE_PROCESS EMAKEHR(0x1c17) +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS EMAKEHR(0x1c18) +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS EMAKEHR(0x1c19) +#define CORDBG_E_CANT_INTEROP_STEP_OUT EMAKEHR(0x1c20) +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS EMAKEHR(0x1c21) +#define CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW EMAKEHR(0x1c22) +#define CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT EMAKEHR(0x1c23) +#define CORDBG_E_ILLEGAL_IN_PROLOG EMAKEHR(0x1c24) +#define CORDBG_E_ILLEGAL_IN_NATIVE_CODE EMAKEHR(0x1c25) +#define CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE EMAKEHR(0x1c26) +#define CORDBG_E_APPDOMAIN_MISMATCH EMAKEHR(0x1c28) +#define CORDBG_E_CONTEXT_UNVAILABLE EMAKEHR(0x1c29) +#define CORDBG_E_UNCOMPATIBLE_PLATFORMS EMAKEHR(0x1c30) +#define CORDBG_E_DEBUGGING_DISABLED EMAKEHR(0x1c31) +#define CORDBG_E_DETACH_FAILED_ON_ENC EMAKEHR(0x1c32) +#define CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE EMAKEHR(0x1c33) +#define CORDBG_E_HELPER_MAY_DEADLOCK EMAKEHR(0x1c34) +#define CORDBG_E_MISSING_METADATA EMAKEHR(0x1c35) +#define CORDBG_E_TARGET_INCONSISTENT EMAKEHR(0x1c36) +#define CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES EMAKEHR(0x1c37) +#define CORDBG_E_TARGET_READONLY EMAKEHR(0x1c38) +#define CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS EMAKEHR(0x1c39) +#define CORDBG_E_MODULE_LOADED_FROM_DISK EMAKEHR(0x1c3a) +#define CORDBG_E_SYMBOLS_NOT_AVAILABLE EMAKEHR(0x1c3b) +#define CORDBG_E_DEBUG_COMPONENT_MISSING EMAKEHR(0x1c3c) +#define CORDBG_E_LIBRARY_PROVIDER_ERROR EMAKEHR(0x1c43) +#define CORDBG_E_NOT_CLR EMAKEHR(0x1c44) +#define CORDBG_E_MISSING_DATA_TARGET_INTERFACE EMAKEHR(0x1c45) +#define CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL EMAKEHR(0x1c46) +#define CORDBG_E_UNSUPPORTED_FORWARD_COMPAT EMAKEHR(0x1c47) +#define CORDBG_E_UNSUPPORTED_VERSION_STRUCT EMAKEHR(0x1c48) +#define CORDBG_E_READVIRTUAL_FAILURE EMAKEHR(0x1c49) +#define CORDBG_E_VALUE_POINTS_TO_FUNCTION EMAKEHR(0x1c4a) +#define CORDBG_E_CORRUPT_OBJECT EMAKEHR(0x1c4b) +#define CORDBG_E_GC_STRUCTURES_INVALID EMAKEHR(0x1c4c) +#define CORDBG_E_INVALID_OPCODE EMAKEHR(0x1c4d) +#define CORDBG_E_UNSUPPORTED EMAKEHR(0x1c4e) +#define CORDBG_E_MISSING_DEBUGGER_EXPORTS EMAKEHR(0x1c4f) +#define CORDBG_E_DATA_TARGET_ERROR EMAKEHR(0x1c61) +#define CORDBG_E_NO_IMAGE_AVAILABLE EMAKEHR(0x1c64) +#define CORDBG_E_UNSUPPORTED_DELEGATE EMAKEHR(0x1c68) +#define PEFMT_E_64BIT EMAKEHR(0x1d02) +#define PEFMT_E_32BIT EMAKEHR(0x1d0b) +#define NGEN_E_SYS_ASM_NI_MISSING EMAKEHR(0x1f06) +#define CLDB_E_INTERNALERROR EMAKEHR(0x1fff) +#define CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW EMAKEHR(0x2000) +#define CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH EMAKEHR(0x2001) +#define CLR_E_BIND_IMAGE_UNAVAILABLE EMAKEHR(0x2002) +#define CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT EMAKEHR(0x2003) +#define CLR_E_BIND_ASSEMBLY_NOT_FOUND EMAKEHR(0x2004) +#define CLR_E_BIND_TYPE_NOT_FOUND EMAKEHR(0x2005) +#define CLR_E_BIND_SYS_ASM_NI_MISSING EMAKEHR(0x2006) +#define CLR_E_BIND_NI_SECURITY_FAILURE EMAKEHR(0x2007) +#define CLR_E_BIND_NI_DEP_IDENTITY_MISMATCH EMAKEHR(0x2008) +#define CLR_E_GC_OOM EMAKEHR(0x2009) +#define CLR_E_GC_BAD_AFFINITY_CONFIG EMAKEHR(0x200a) +#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT EMAKEHR(0x200b) +#define CLR_E_CROSSGEN_NO_IBC_DATA_FOUND EMAKEHR(0x200c) +#define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED +#define COR_E_ARGUMENT E_INVALIDARG +#define COR_E_INVALIDCAST E_NOINTERFACE +#define COR_E_OUTOFMEMORY E_OUTOFMEMORY +#define COR_E_NULLREFERENCE E_POINTER +#define COR_E_ARITHMETIC __HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW) +#define COR_E_PATHTOOLONG __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) +#define COR_E_FILENOTFOUND __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) +#define COR_E_ENDOFSTREAM __HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) +#define COR_E_DIRECTORYNOTFOUND __HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) +#define COR_E_STACKOVERFLOW __HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW) +#define COR_E_AMBIGUOUSMATCH _HRESULT_TYPEDEF_(0x8000211DL) +#define COR_E_TARGETPARAMCOUNT _HRESULT_TYPEDEF_(0x8002000EL) +#define COR_E_DIVIDEBYZERO _HRESULT_TYPEDEF_(0x80020012L) +#define COR_E_BADIMAGEFORMAT _HRESULT_TYPEDEF_(0x8007000BL) + + +#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__ diff --git a/lib/coreclr/src/pal/prebuilt/inc/corprof.h b/lib/coreclr/src/pal/prebuilt/inc/corprof.h new file mode 100644 index 0000000000..2717067ed3 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/corprof.h @@ -0,0 +1,16493 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/git/coreclr/src/inc/corprof.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __corprof_h__ +#define __corprof_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICorProfilerCallback_FWD_DEFINED__ +#define __ICorProfilerCallback_FWD_DEFINED__ +typedef interface ICorProfilerCallback ICorProfilerCallback; + +#endif /* __ICorProfilerCallback_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback2_FWD_DEFINED__ +#define __ICorProfilerCallback2_FWD_DEFINED__ +typedef interface ICorProfilerCallback2 ICorProfilerCallback2; + +#endif /* __ICorProfilerCallback2_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback3_FWD_DEFINED__ +#define __ICorProfilerCallback3_FWD_DEFINED__ +typedef interface ICorProfilerCallback3 ICorProfilerCallback3; + +#endif /* __ICorProfilerCallback3_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback4_FWD_DEFINED__ +#define __ICorProfilerCallback4_FWD_DEFINED__ +typedef interface ICorProfilerCallback4 ICorProfilerCallback4; + +#endif /* __ICorProfilerCallback4_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback5_FWD_DEFINED__ +#define __ICorProfilerCallback5_FWD_DEFINED__ +typedef interface ICorProfilerCallback5 ICorProfilerCallback5; + +#endif /* __ICorProfilerCallback5_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback6_FWD_DEFINED__ +#define __ICorProfilerCallback6_FWD_DEFINED__ +typedef interface ICorProfilerCallback6 ICorProfilerCallback6; + +#endif /* __ICorProfilerCallback6_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback7_FWD_DEFINED__ +#define __ICorProfilerCallback7_FWD_DEFINED__ +typedef interface ICorProfilerCallback7 ICorProfilerCallback7; + +#endif /* __ICorProfilerCallback7_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback8_FWD_DEFINED__ +#define __ICorProfilerCallback8_FWD_DEFINED__ +typedef interface ICorProfilerCallback8 ICorProfilerCallback8; + +#endif /* __ICorProfilerCallback8_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerCallback9_FWD_DEFINED__ +#define __ICorProfilerCallback9_FWD_DEFINED__ +typedef interface ICorProfilerCallback9 ICorProfilerCallback9; + +#endif /* __ICorProfilerCallback9_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo_FWD_DEFINED__ +#define __ICorProfilerInfo_FWD_DEFINED__ +typedef interface ICorProfilerInfo ICorProfilerInfo; + +#endif /* __ICorProfilerInfo_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo2_FWD_DEFINED__ +#define __ICorProfilerInfo2_FWD_DEFINED__ +typedef interface ICorProfilerInfo2 ICorProfilerInfo2; + +#endif /* __ICorProfilerInfo2_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo3_FWD_DEFINED__ +#define __ICorProfilerInfo3_FWD_DEFINED__ +typedef interface ICorProfilerInfo3 ICorProfilerInfo3; + +#endif /* __ICorProfilerInfo3_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerObjectEnum_FWD_DEFINED__ +#define __ICorProfilerObjectEnum_FWD_DEFINED__ +typedef interface ICorProfilerObjectEnum ICorProfilerObjectEnum; + +#endif /* __ICorProfilerObjectEnum_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionEnum_FWD_DEFINED__ +#define __ICorProfilerFunctionEnum_FWD_DEFINED__ +typedef interface ICorProfilerFunctionEnum ICorProfilerFunctionEnum; + +#endif /* __ICorProfilerFunctionEnum_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerModuleEnum_FWD_DEFINED__ +#define __ICorProfilerModuleEnum_FWD_DEFINED__ +typedef interface ICorProfilerModuleEnum ICorProfilerModuleEnum; + +#endif /* __ICorProfilerModuleEnum_FWD_DEFINED__ */ + + +#ifndef __IMethodMalloc_FWD_DEFINED__ +#define __IMethodMalloc_FWD_DEFINED__ +typedef interface IMethodMalloc IMethodMalloc; + +#endif /* __IMethodMalloc_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionControl_FWD_DEFINED__ +#define __ICorProfilerFunctionControl_FWD_DEFINED__ +typedef interface ICorProfilerFunctionControl ICorProfilerFunctionControl; + +#endif /* __ICorProfilerFunctionControl_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo4_FWD_DEFINED__ +#define __ICorProfilerInfo4_FWD_DEFINED__ +typedef interface ICorProfilerInfo4 ICorProfilerInfo4; + +#endif /* __ICorProfilerInfo4_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo5_FWD_DEFINED__ +#define __ICorProfilerInfo5_FWD_DEFINED__ +typedef interface ICorProfilerInfo5 ICorProfilerInfo5; + +#endif /* __ICorProfilerInfo5_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo6_FWD_DEFINED__ +#define __ICorProfilerInfo6_FWD_DEFINED__ +typedef interface ICorProfilerInfo6 ICorProfilerInfo6; + +#endif /* __ICorProfilerInfo6_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo7_FWD_DEFINED__ +#define __ICorProfilerInfo7_FWD_DEFINED__ +typedef interface ICorProfilerInfo7 ICorProfilerInfo7; + +#endif /* __ICorProfilerInfo7_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo8_FWD_DEFINED__ +#define __ICorProfilerInfo8_FWD_DEFINED__ +typedef interface ICorProfilerInfo8 ICorProfilerInfo8; + +#endif /* __ICorProfilerInfo8_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo9_FWD_DEFINED__ +#define __ICorProfilerInfo9_FWD_DEFINED__ +typedef interface ICorProfilerInfo9 ICorProfilerInfo9; + +#endif /* __ICorProfilerInfo9_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerInfo10_FWD_DEFINED__ +#define __ICorProfilerInfo10_FWD_DEFINED__ +typedef interface ICorProfilerInfo10 ICorProfilerInfo10; + +#endif /* __ICorProfilerInfo10_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerMethodEnum_FWD_DEFINED__ +#define __ICorProfilerMethodEnum_FWD_DEFINED__ +typedef interface ICorProfilerMethodEnum ICorProfilerMethodEnum; + +#endif /* __ICorProfilerMethodEnum_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerThreadEnum_FWD_DEFINED__ +#define __ICorProfilerThreadEnum_FWD_DEFINED__ +typedef interface ICorProfilerThreadEnum ICorProfilerThreadEnum; + +#endif /* __ICorProfilerThreadEnum_FWD_DEFINED__ */ + + +#ifndef __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ +#define __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ +typedef interface ICorProfilerAssemblyReferenceProvider ICorProfilerAssemblyReferenceProvider; + +#endif /* __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_corprof_0000_0000 */ +/* [local] */ + +#define CorDB_CONTROL_Profiling "Cor_Enable_Profiling" +#define CorDB_CONTROL_ProfilingL L"Cor_Enable_Profiling" +#if 0 +typedef LONG32 mdToken; + +typedef mdToken mdModule; + +typedef mdToken mdTypeDef; + +typedef mdToken mdMethodDef; + +typedef mdToken mdFieldDef; + +typedef ULONG CorElementType; + + +typedef /* [public][public][public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0001 + { + DWORD dwOSPlatformId; + DWORD dwOSMajorVersion; + DWORD dwOSMinorVersion; + } OSINFO; + +typedef /* [public][public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0002 + { + USHORT usMajorVersion; + USHORT usMinorVersion; + USHORT usBuildNumber; + USHORT usRevisionNumber; + LPWSTR szLocale; + ULONG cbLocale; + DWORD *rProcessor; + ULONG ulProcessor; + OSINFO *rOS; + ULONG ulOS; + } ASSEMBLYMETADATA; + +#endif +typedef const BYTE *LPCBYTE; + +typedef BYTE *LPBYTE; + +typedef BYTE COR_SIGNATURE; + +typedef COR_SIGNATURE *PCOR_SIGNATURE; + +typedef const COR_SIGNATURE *PCCOR_SIGNATURE; + +#ifndef _COR_IL_MAP +#define _COR_IL_MAP +typedef struct _COR_IL_MAP + { + ULONG32 oldOffset; + ULONG32 newOffset; + BOOL fAccurate; + } COR_IL_MAP; + +#endif //_COR_IL_MAP +#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ +#define _COR_DEBUG_IL_TO_NATIVE_MAP_ +typedef +enum CorDebugIlToNativeMappingTypes + { + NO_MAPPING = -1, + PROLOG = -2, + EPILOG = -3 + } CorDebugIlToNativeMappingTypes; + +typedef struct COR_DEBUG_IL_TO_NATIVE_MAP + { + ULONG32 ilOffset; + ULONG32 nativeStartOffset; + ULONG32 nativeEndOffset; + } COR_DEBUG_IL_TO_NATIVE_MAP; + +#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ +#ifndef _COR_FIELD_OFFSET_ +#define _COR_FIELD_OFFSET_ +typedef struct _COR_FIELD_OFFSET + { + mdFieldDef ridOfField; + ULONG ulOffset; + } COR_FIELD_OFFSET; + +#endif // _COR_FIELD_OFFSET_ +typedef UINT_PTR ProcessID; + +typedef UINT_PTR AssemblyID; + +typedef UINT_PTR AppDomainID; + +typedef UINT_PTR ModuleID; + +typedef UINT_PTR ClassID; + +typedef UINT_PTR ThreadID; + +typedef UINT_PTR ContextID; + +typedef UINT_PTR FunctionID; + +typedef UINT_PTR ObjectID; + +typedef UINT_PTR GCHandleID; + +typedef UINT_PTR COR_PRF_ELT_INFO; + +typedef UINT_PTR ReJITID; + +typedef /* [public][public][public][public][public][public][public][public][public][public][public][public][public] */ union __MIDL___MIDL_itf_corprof_0000_0000_0003 + { + FunctionID functionID; + UINT_PTR clientID; + } FunctionIDOrClientID; + +typedef UINT_PTR __stdcall __stdcall FunctionIDMapper( + FunctionID funcId, + BOOL *pbHookFunction); + +typedef UINT_PTR __stdcall __stdcall FunctionIDMapper2( + FunctionID funcId, + void *clientData, + BOOL *pbHookFunction); + +typedef +enum _COR_PRF_SNAPSHOT_INFO + { + COR_PRF_SNAPSHOT_DEFAULT = 0, + COR_PRF_SNAPSHOT_REGISTER_CONTEXT = 0x1, + COR_PRF_SNAPSHOT_X86_OPTIMIZED = 0x2 + } COR_PRF_SNAPSHOT_INFO; + +typedef UINT_PTR COR_PRF_FRAME_INFO; + +typedef struct _COR_PRF_FUNCTION_ARGUMENT_RANGE + { + UINT_PTR startAddress; + ULONG length; + } COR_PRF_FUNCTION_ARGUMENT_RANGE; + +typedef struct _COR_PRF_FUNCTION_ARGUMENT_INFO + { + ULONG numRanges; + ULONG totalArgumentSize; + COR_PRF_FUNCTION_ARGUMENT_RANGE ranges[ 1 ]; + } COR_PRF_FUNCTION_ARGUMENT_INFO; + +typedef struct _COR_PRF_CODE_INFO + { + UINT_PTR startAddress; + SIZE_T size; + } COR_PRF_CODE_INFO; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0004 + { + COR_PRF_FIELD_NOT_A_STATIC = 0, + COR_PRF_FIELD_APP_DOMAIN_STATIC = 0x1, + COR_PRF_FIELD_THREAD_STATIC = 0x2, + COR_PRF_FIELD_CONTEXT_STATIC = 0x4, + COR_PRF_FIELD_RVA_STATIC = 0x8 + } COR_PRF_STATIC_TYPE; + +typedef struct _COR_PRF_FUNCTION + { + FunctionID functionId; + ReJITID reJitId; + } COR_PRF_FUNCTION; + +typedef struct _COR_PRF_ASSEMBLY_REFERENCE_INFO + { + void *pbPublicKeyOrToken; + ULONG cbPublicKeyOrToken; + LPCWSTR szName; + ASSEMBLYMETADATA *pMetaData; + void *pbHashValue; + ULONG cbHashValue; + DWORD dwAssemblyRefFlags; + } COR_PRF_ASSEMBLY_REFERENCE_INFO; + +typedef struct _COR_PRF_METHOD + { + ModuleID moduleId; + mdMethodDef methodId; + } COR_PRF_METHOD; + +typedef void FunctionEnter( + FunctionID funcID); + +typedef void FunctionLeave( + FunctionID funcID); + +typedef void FunctionTailcall( + FunctionID funcID); + +typedef void FunctionEnter2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, + COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo); + +typedef void FunctionLeave2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func, + COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange); + +typedef void FunctionTailcall2( + FunctionID funcId, + UINT_PTR clientData, + COR_PRF_FRAME_INFO func); + +typedef void FunctionEnter3( + FunctionIDOrClientID functionIDOrClientID); + +typedef void FunctionLeave3( + FunctionIDOrClientID functionIDOrClientID); + +typedef void FunctionTailcall3( + FunctionIDOrClientID functionIDOrClientID); + +typedef void FunctionEnter3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +typedef void FunctionLeave3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +typedef void FunctionTailcall3WithInfo( + FunctionIDOrClientID functionIDOrClientID, + COR_PRF_ELT_INFO eltInfo); + +typedef HRESULT __stdcall __stdcall StackSnapshotCallback( + FunctionID funcId, + UINT_PTR ip, + COR_PRF_FRAME_INFO frameInfo, + ULONG32 contextSize, + BYTE context[ ], + void *clientData); + +typedef BOOL ObjectReferenceCallback( + ObjectID root, + ObjectID *reference, + void *clientData); + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0005 + { + COR_PRF_MONITOR_NONE = 0, + COR_PRF_MONITOR_FUNCTION_UNLOADS = 0x1, + COR_PRF_MONITOR_CLASS_LOADS = 0x2, + COR_PRF_MONITOR_MODULE_LOADS = 0x4, + COR_PRF_MONITOR_ASSEMBLY_LOADS = 0x8, + COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x10, + COR_PRF_MONITOR_JIT_COMPILATION = 0x20, + COR_PRF_MONITOR_EXCEPTIONS = 0x40, + COR_PRF_MONITOR_GC = 0x80, + COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x100, + COR_PRF_MONITOR_THREADS = 0x200, + COR_PRF_MONITOR_REMOTING = 0x400, + COR_PRF_MONITOR_CODE_TRANSITIONS = 0x800, + COR_PRF_MONITOR_ENTERLEAVE = 0x1000, + COR_PRF_MONITOR_CCW = 0x2000, + COR_PRF_MONITOR_REMOTING_COOKIE = ( 0x4000 | COR_PRF_MONITOR_REMOTING ) , + COR_PRF_MONITOR_REMOTING_ASYNC = ( 0x8000 | COR_PRF_MONITOR_REMOTING ) , + COR_PRF_MONITOR_SUSPENDS = 0x10000, + COR_PRF_MONITOR_CACHE_SEARCHES = 0x20000, + COR_PRF_ENABLE_REJIT = 0x40000, + COR_PRF_ENABLE_INPROC_DEBUGGING = 0x80000, + COR_PRF_ENABLE_JIT_MAPS = 0x100000, + COR_PRF_DISABLE_INLINING = 0x200000, + COR_PRF_DISABLE_OPTIMIZATIONS = 0x400000, + COR_PRF_ENABLE_OBJECT_ALLOCATED = 0x800000, + COR_PRF_MONITOR_CLR_EXCEPTIONS = 0x1000000, + COR_PRF_MONITOR_ALL = 0x107ffff, + COR_PRF_ENABLE_FUNCTION_ARGS = 0x2000000, + COR_PRF_ENABLE_FUNCTION_RETVAL = 0x4000000, + COR_PRF_ENABLE_FRAME_INFO = 0x8000000, + COR_PRF_ENABLE_STACK_SNAPSHOT = 0x10000000, + COR_PRF_USE_PROFILE_IMAGES = 0x20000000, + COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST = 0x40000000, + COR_PRF_DISABLE_ALL_NGEN_IMAGES = 0x80000000, + COR_PRF_ALL = 0x8fffffff, + COR_PRF_REQUIRE_PROFILE_IMAGE = ( ( COR_PRF_USE_PROFILE_IMAGES | COR_PRF_MONITOR_CODE_TRANSITIONS ) | COR_PRF_MONITOR_ENTERLEAVE ) , + COR_PRF_ALLOWABLE_AFTER_ATTACH = ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_MODULE_LOADS ) | COR_PRF_MONITOR_ASSEMBLY_LOADS ) | COR_PRF_MONITOR_APPDOMAIN_LOADS ) | COR_PRF_ENABLE_STACK_SNAPSHOT ) | COR_PRF_MONITOR_GC ) | COR_PRF_MONITOR_SUSPENDS ) | COR_PRF_MONITOR_CLASS_LOADS ) | COR_PRF_MONITOR_EXCEPTIONS ) | COR_PRF_MONITOR_JIT_COMPILATION ) | COR_PRF_ENABLE_REJIT ) , + COR_PRF_MONITOR_IMMUTABLE = ( ( ( ( ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_REMOTING ) | COR_PRF_MONITOR_REMOTING_COOKIE ) | COR_PRF_MONITOR_REMOTING_ASYNC ) | COR_PRF_ENABLE_INPROC_DEBUGGING ) | COR_PRF_ENABLE_JIT_MAPS ) | COR_PRF_DISABLE_OPTIMIZATIONS ) | COR_PRF_DISABLE_INLINING ) | COR_PRF_ENABLE_OBJECT_ALLOCATED ) | COR_PRF_ENABLE_FUNCTION_ARGS ) | COR_PRF_ENABLE_FUNCTION_RETVAL ) | COR_PRF_ENABLE_FRAME_INFO ) | COR_PRF_USE_PROFILE_IMAGES ) | COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST ) | COR_PRF_DISABLE_ALL_NGEN_IMAGES ) + } COR_PRF_MONITOR; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0006 + { + COR_PRF_HIGH_MONITOR_NONE = 0, + COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x1, + COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x2, + COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS = 0x4, + COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x8, + COR_PRF_HIGH_BASIC_GC = 0x10, + COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS = 0x20, + COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0, + COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x40, + COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) | COR_PRF_HIGH_BASIC_GC ) | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED ) , + COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION + } COR_PRF_HIGH_MONITOR; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0007 + { + PROFILER_PARENT_UNKNOWN = 0xfffffffd, + PROFILER_GLOBAL_CLASS = 0xfffffffe, + PROFILER_GLOBAL_MODULE = 0xffffffff + } COR_PRF_MISC; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0008 + { + COR_PRF_CACHED_FUNCTION_FOUND = 0, + COR_PRF_CACHED_FUNCTION_NOT_FOUND = ( COR_PRF_CACHED_FUNCTION_FOUND + 1 ) + } COR_PRF_JIT_CACHE; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0009 + { + COR_PRF_TRANSITION_CALL = 0, + COR_PRF_TRANSITION_RETURN = ( COR_PRF_TRANSITION_CALL + 1 ) + } COR_PRF_TRANSITION_REASON; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0010 + { + COR_PRF_SUSPEND_OTHER = 0, + COR_PRF_SUSPEND_FOR_GC = 1, + COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN = 2, + COR_PRF_SUSPEND_FOR_CODE_PITCHING = 3, + COR_PRF_SUSPEND_FOR_SHUTDOWN = 4, + COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, + COR_PRF_SUSPEND_FOR_GC_PREP = 7, + COR_PRF_SUSPEND_FOR_REJIT = 8 + } COR_PRF_SUSPEND_REASON; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0011 + { + COR_PRF_DESKTOP_CLR = 0x1, + COR_PRF_CORE_CLR = 0x2 + } COR_PRF_RUNTIME_TYPE; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0000_0012 + { + COR_PRF_REJIT_BLOCK_INLINING = 0x1, + COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 + } COR_PRF_REJIT_FLAGS; + + + + + + + + + + + + + + + + + + + +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0000_v0_0_s_ifspec; + +#ifndef __ICorProfilerCallback_INTERFACE_DEFINED__ +#define __ICorProfilerCallback_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("176FBED1-A55C-4796-98CA-A9DA0EF883E7") + ICorProfilerCallback : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Initialize( + /* [in] */ IUnknown *pICorProfilerInfoUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE Shutdown( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE AppDomainCreationStarted( + /* [in] */ AppDomainID appDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE AppDomainCreationFinished( + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownStarted( + /* [in] */ AppDomainID appDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownFinished( + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE AssemblyLoadStarted( + /* [in] */ AssemblyID assemblyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE AssemblyLoadFinished( + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadStarted( + /* [in] */ AssemblyID assemblyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished( + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModuleLoadStarted( + /* [in] */ ModuleID moduleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModuleLoadFinished( + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModuleUnloadStarted( + /* [in] */ ModuleID moduleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModuleUnloadFinished( + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModuleAttachedToAssembly( + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClassLoadStarted( + /* [in] */ ClassID classId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClassLoadFinished( + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClassUnloadStarted( + /* [in] */ ClassID classId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClassUnloadFinished( + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE FunctionUnloadStarted( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITCompilationStarted( + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITCompilationFinished( + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchStarted( + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchFinished( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITFunctionPitched( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE JITInlining( + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline) = 0; + + virtual HRESULT STDMETHODCALLTYPE ThreadCreated( + /* [in] */ ThreadID threadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ThreadDestroyed( + /* [in] */ ThreadID threadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread( + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingClientSendingMessage( + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingClientReceivingReply( + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingServerReceivingMessage( + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemotingServerSendingReply( + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason) = 0; + + virtual HRESULT STDMETHODCALLTYPE ManagedToUnmanagedTransition( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendStarted( + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeResumeStarted( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeResumeFinished( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeThreadSuspended( + /* [in] */ ThreadID threadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE RuntimeThreadResumed( + /* [in] */ ThreadID threadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE MovedReferences( + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE ObjectAllocated( + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass( + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE ObjectReferences( + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE RootReferences( + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionThrown( + /* [in] */ ObjectID thrownObjectId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionEnter( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterEnter( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionSearchCatcherFound( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerEnter( + /* [in] */ UINT_PTR __unused) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerLeave( + /* [in] */ UINT_PTR __unused) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionEnter( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyEnter( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter( + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE COMClassicVTableCreated( + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots) = 0; + + virtual HRESULT STDMETHODCALLTYPE COMClassicVTableDestroyed( + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallbackVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback * This); + + END_INTERFACE + } ICorProfilerCallbackVtbl; + + interface ICorProfilerCallback + { + CONST_VTBL struct ICorProfilerCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corprof_0000_0001 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0001 + { + COR_PRF_GC_ROOT_STACK = 1, + COR_PRF_GC_ROOT_FINALIZER = 2, + COR_PRF_GC_ROOT_HANDLE = 3, + COR_PRF_GC_ROOT_OTHER = 0 + } COR_PRF_GC_ROOT_KIND; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0002 + { + COR_PRF_GC_ROOT_PINNING = 0x1, + COR_PRF_GC_ROOT_WEAKREF = 0x2, + COR_PRF_GC_ROOT_INTERIOR = 0x4, + COR_PRF_GC_ROOT_REFCOUNTED = 0x8 + } COR_PRF_GC_ROOT_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0003 + { + COR_PRF_FINALIZER_CRITICAL = 0x1 + } COR_PRF_FINALIZER_FLAGS; + +typedef /* [public][public][public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0004 + { + COR_PRF_GC_GEN_0 = 0, + COR_PRF_GC_GEN_1 = 1, + COR_PRF_GC_GEN_2 = 2, + COR_PRF_GC_LARGE_OBJECT_HEAP = 3 + } COR_PRF_GC_GENERATION; + +typedef struct COR_PRF_GC_GENERATION_RANGE + { + COR_PRF_GC_GENERATION generation; + ObjectID rangeStart; + UINT_PTR rangeLength; + UINT_PTR rangeLengthReserved; + } COR_PRF_GC_GENERATION_RANGE; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0005 + { + COR_PRF_CLAUSE_NONE = 0, + COR_PRF_CLAUSE_FILTER = 1, + COR_PRF_CLAUSE_CATCH = 2, + COR_PRF_CLAUSE_FINALLY = 3 + } COR_PRF_CLAUSE_TYPE; + +typedef struct COR_PRF_EX_CLAUSE_INFO + { + COR_PRF_CLAUSE_TYPE clauseType; + UINT_PTR programCounter; + UINT_PTR framePointer; + UINT_PTR shadowStackPointer; + } COR_PRF_EX_CLAUSE_INFO; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0006 + { + COR_PRF_GC_INDUCED = 1, + COR_PRF_GC_OTHER = 0 + } COR_PRF_GC_REASON; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0001_0007 + { + COR_PRF_MODULE_DISK = 0x1, + COR_PRF_MODULE_NGEN = 0x2, + COR_PRF_MODULE_DYNAMIC = 0x4, + COR_PRF_MODULE_COLLECTIBLE = 0x8, + COR_PRF_MODULE_RESOURCE = 0x10, + COR_PRF_MODULE_FLAT_LAYOUT = 0x20, + COR_PRF_MODULE_WINDOWS_RUNTIME = 0x40 + } COR_PRF_MODULE_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0001_v0_0_s_ifspec; + +#ifndef __ICorProfilerCallback2_INTERFACE_DEFINED__ +#define __ICorProfilerCallback2_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback2 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8A8CC829-CCF2-49fe-BBAE-0F022228071A") + ICorProfilerCallback2 : public ICorProfilerCallback + { + public: + virtual HRESULT STDMETHODCALLTYPE ThreadNameChanged( + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted( + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason) = 0; + + virtual HRESULT STDMETHODCALLTYPE SurvivingReferences( + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinalizeableObjectQueued( + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID) = 0; + + virtual HRESULT STDMETHODCALLTYPE RootReferences2( + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE HandleCreated( + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId) = 0; + + virtual HRESULT STDMETHODCALLTYPE HandleDestroyed( + /* [in] */ GCHandleID handleId) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback2 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback2 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback2 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback2 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback2 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback2 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback2 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback2 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback2 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback2 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback2 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback2 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback2 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback2 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback2 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback2 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback2 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback2 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback2 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback2 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback2 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback2 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback2 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback2 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback2 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback2 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback2 * This, + /* [in] */ GCHandleID handleId); + + END_INTERFACE + } ICorProfilerCallback2Vtbl; + + interface ICorProfilerCallback2 + { + CONST_VTBL struct ICorProfilerCallback2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback2_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback2_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback2_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback2_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback2_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback2_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback2_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback2_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback2_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback2_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback2_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback2_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback2_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback2_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback2_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback2_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback2_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback2_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback2_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback2_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback2_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback2_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback2_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback2_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback2_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback2_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback2_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback2_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback2_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback2_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback2_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback2_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback2_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback2_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback2_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback2_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback2_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback2_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback2_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback2_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback2_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback2_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback2_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback2_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback2_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback2_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback2_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback2_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback2_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback2_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback2_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback2_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback2_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback2_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback2_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback2_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback2_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback2_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback2_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback2_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback2_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback2_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback2_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback2_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback2_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback2_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback2_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback2_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback2_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback2_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback2_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback2_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback2_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback2_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback2_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback2_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback2_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback3_INTERFACE_DEFINED__ +#define __ICorProfilerCallback3_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback3 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4FD2ED52-7731-4b8d-9469-03D2CC3086C5") + ICorProfilerCallback3 : public ICorProfilerCallback2 + { + public: + virtual HRESULT STDMETHODCALLTYPE InitializeForAttach( + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProfilerAttachComplete( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback3 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback3 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback3 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback3 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback3 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback3 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback3 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback3 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback3 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback3 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback3 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback3 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback3 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback3 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback3 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback3 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback3 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback3 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback3 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback3 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback3 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback3 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback3 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback3 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback3 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback3 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback3 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback3 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback3 * This); + + END_INTERFACE + } ICorProfilerCallback3Vtbl; + + interface ICorProfilerCallback3 + { + CONST_VTBL struct ICorProfilerCallback3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback3_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback3_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback3_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback3_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback3_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback3_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback3_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback3_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback3_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback3_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback3_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback3_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback3_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback3_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback3_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback3_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback3_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback3_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback3_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback3_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback3_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback3_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback3_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback3_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback3_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback3_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback3_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback3_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback3_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback3_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback3_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback3_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback3_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback3_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback3_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback3_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback3_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback3_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback3_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback3_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback3_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback3_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback3_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback3_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback3_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback3_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback3_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback3_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback3_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback3_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback3_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback3_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback3_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback3_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback3_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback3_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback3_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback3_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback3_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback3_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback3_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback3_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback3_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback3_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback3_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback3_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback3_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback3_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback3_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback3_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback3_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback3_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback3_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback3_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback3_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback3_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback3_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback3_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback3_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback3_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback4_INTERFACE_DEFINED__ +#define __ICorProfilerCallback4_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback4 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7B63B2E3-107D-4d48-B2F6-F61E229470D2") + ICorProfilerCallback4 : public ICorProfilerCallback3 + { + public: + virtual HRESULT STDMETHODCALLTYPE ReJITCompilationStarted( + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReJITParameters( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReJITCompilationFinished( + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReJITError( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE MovedReferences2( + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SurvivingReferences2( + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback4 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback4 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback4 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback4 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback4 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback4 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback4 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback4 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback4 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback4 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback4 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback4 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback4 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback4 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback4 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback4 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback4 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback4 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback4 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback4 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback4 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback4 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback4 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback4 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + END_INTERFACE + } ICorProfilerCallback4Vtbl; + + interface ICorProfilerCallback4 + { + CONST_VTBL struct ICorProfilerCallback4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback4_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback4_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback4_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback4_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback4_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback4_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback4_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback4_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback4_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback4_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback4_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback4_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback4_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback4_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback4_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback4_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback4_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback4_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback4_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback4_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback4_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback4_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback4_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback4_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback4_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback4_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback4_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback4_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback4_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback4_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback4_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback4_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback4_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback4_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback4_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback4_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback4_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback4_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback4_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback4_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback4_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback4_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback4_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback4_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback4_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback4_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback4_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback4_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback4_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback4_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback4_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback4_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback4_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback4_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback4_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback4_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback4_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback4_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback4_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback4_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback4_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback4_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback4_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback4_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback4_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback4_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback4_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback4_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback4_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback4_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback4_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback4_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback4_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback4_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback4_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback4_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback4_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback4_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback4_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback4_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback4_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback4_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback4_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback4_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback4_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback4_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback5_INTERFACE_DEFINED__ +#define __ICorProfilerCallback5_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback5 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8DFBA405-8C9F-45F8-BFFA-83B14CEF78B5") + ICorProfilerCallback5 : public ICorProfilerCallback4 + { + public: + virtual HRESULT STDMETHODCALLTYPE ConditionalWeakTableElementReferences( + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback5 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback5 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback5 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback5 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback5 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback5 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback5 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback5 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback5 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback5 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback5 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback5 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback5 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback5 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback5 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback5 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback5 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback5 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback5 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback5 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback5 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback5 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback5 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback5 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + END_INTERFACE + } ICorProfilerCallback5Vtbl; + + interface ICorProfilerCallback5 + { + CONST_VTBL struct ICorProfilerCallback5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback5_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback5_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback5_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback5_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback5_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback5_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback5_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback5_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback5_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback5_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback5_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback5_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback5_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback5_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback5_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback5_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback5_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback5_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback5_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback5_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback5_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback5_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback5_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback5_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback5_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback5_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback5_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback5_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback5_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback5_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback5_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback5_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback5_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback5_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback5_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback5_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback5_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback5_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback5_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback5_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback5_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback5_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback5_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback5_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback5_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback5_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback5_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback5_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback5_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback5_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback5_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback5_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback5_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback5_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback5_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback5_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback5_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback5_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback5_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback5_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback5_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback5_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback5_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback5_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback5_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback5_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback5_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback5_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback5_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback5_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback5_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback5_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback5_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback5_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback5_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback5_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback5_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback5_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback5_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback5_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback5_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback5_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback5_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback5_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback5_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback5_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback5_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback5_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback6_INTERFACE_DEFINED__ +#define __ICorProfilerCallback6_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback6 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback6; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FC13DF4B-4448-4F4F-950C-BA8D19D00C36") + ICorProfilerCallback6 : public ICorProfilerCallback5 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAssemblyReferences( + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback6Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback6 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback6 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback6 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback6 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback6 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback6 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback6 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback6 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback6 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback6 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback6 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback6 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback6 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback6 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback6 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback6 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback6 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback6 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback6 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback6 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback6 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback6 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback6 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback6 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback6 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback6 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( + ICorProfilerCallback6 * This, + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); + + END_INTERFACE + } ICorProfilerCallback6Vtbl; + + interface ICorProfilerCallback6 + { + CONST_VTBL struct ICorProfilerCallback6Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback6_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback6_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback6_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback6_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback6_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback6_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback6_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback6_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback6_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback6_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback6_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback6_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback6_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback6_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback6_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback6_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback6_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback6_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback6_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback6_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback6_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback6_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback6_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback6_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback6_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback6_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback6_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback6_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback6_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback6_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback6_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback6_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback6_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback6_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback6_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback6_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback6_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback6_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback6_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback6_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback6_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback6_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback6_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback6_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback6_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback6_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback6_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback6_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback6_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback6_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback6_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback6_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback6_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback6_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback6_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback6_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback6_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback6_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback6_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback6_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback6_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback6_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback6_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback6_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback6_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback6_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback6_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback6_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback6_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback6_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback6_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback6_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback6_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback6_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback6_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback6_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback6_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback6_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback6_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback6_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback6_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback6_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback6_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback6_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback6_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback6_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback6_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback6_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback6_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback6_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + + +#define ICorProfilerCallback6_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ + ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback6_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback7_INTERFACE_DEFINED__ +#define __ICorProfilerCallback7_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback7 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback7; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F76A2DBA-1D52-4539-866C-2AA518F9EFC3") + ICorProfilerCallback7 : public ICorProfilerCallback6 + { + public: + virtual HRESULT STDMETHODCALLTYPE ModuleInMemorySymbolsUpdated( + ModuleID moduleId) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback7Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback7 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback7 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback7 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback7 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback7 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback7 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback7 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback7 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback7 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback7 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback7 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback7 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback7 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback7 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback7 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback7 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback7 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback7 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback7 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback7 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback7 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback7 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback7 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback7 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback7 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback7 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( + ICorProfilerCallback7 * This, + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); + + HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( + ICorProfilerCallback7 * This, + ModuleID moduleId); + + END_INTERFACE + } ICorProfilerCallback7Vtbl; + + interface ICorProfilerCallback7 + { + CONST_VTBL struct ICorProfilerCallback7Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback7_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback7_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback7_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback7_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback7_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback7_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback7_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback7_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback7_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback7_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback7_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback7_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback7_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback7_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback7_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback7_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback7_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback7_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback7_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback7_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback7_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback7_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback7_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback7_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback7_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback7_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback7_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback7_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback7_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback7_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback7_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback7_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback7_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback7_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback7_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback7_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback7_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback7_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback7_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback7_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback7_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback7_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback7_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback7_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback7_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback7_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback7_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback7_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback7_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback7_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback7_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback7_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback7_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback7_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback7_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback7_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback7_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback7_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback7_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback7_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback7_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback7_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback7_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback7_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback7_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback7_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback7_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback7_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback7_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback7_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback7_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback7_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback7_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback7_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback7_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback7_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback7_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback7_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback7_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback7_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback7_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback7_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback7_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback7_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback7_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback7_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback7_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback7_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback7_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback7_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + + +#define ICorProfilerCallback7_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ + ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) + + +#define ICorProfilerCallback7_ModuleInMemorySymbolsUpdated(This,moduleId) \ + ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback7_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback8_INTERFACE_DEFINED__ +#define __ICorProfilerCallback8_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback8 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback8; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5BED9B15-C079-4D47-BFE2-215A140C07E0") + ICorProfilerCallback8 : public ICorProfilerCallback7 + { + public: + virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationStarted( + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock, + /* [in] */ LPCBYTE pILHeader, + /* [in] */ ULONG cbILHeader) = 0; + + virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationFinished( + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback8Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback8 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback8 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback8 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback8 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback8 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback8 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback8 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback8 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback8 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback8 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback8 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback8 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback8 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback8 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback8 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback8 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( + ICorProfilerCallback8 * This, + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); + + HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( + ICorProfilerCallback8 * This, + ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock, + /* [in] */ LPCBYTE pILHeader, + /* [in] */ ULONG cbILHeader); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( + ICorProfilerCallback8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + END_INTERFACE + } ICorProfilerCallback8Vtbl; + + interface ICorProfilerCallback8 + { + CONST_VTBL struct ICorProfilerCallback8Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback8_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback8_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback8_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback8_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback8_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback8_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback8_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback8_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback8_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback8_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback8_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback8_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback8_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback8_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback8_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback8_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback8_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback8_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback8_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback8_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback8_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback8_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback8_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback8_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback8_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback8_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback8_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback8_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback8_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback8_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback8_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback8_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback8_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback8_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback8_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback8_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback8_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback8_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback8_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback8_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback8_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback8_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback8_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback8_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback8_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback8_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback8_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback8_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback8_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback8_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback8_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback8_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback8_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback8_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback8_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback8_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback8_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback8_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback8_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback8_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback8_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback8_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback8_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback8_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback8_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback8_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback8_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback8_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback8_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback8_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback8_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback8_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback8_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback8_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback8_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback8_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback8_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback8_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback8_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback8_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback8_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + + +#define ICorProfilerCallback8_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ + ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) + + +#define ICorProfilerCallback8_ModuleInMemorySymbolsUpdated(This,moduleId) \ + ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) + + +#define ICorProfilerCallback8_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) + +#define ICorProfilerCallback8_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback8_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerCallback9_INTERFACE_DEFINED__ +#define __ICorProfilerCallback9_INTERFACE_DEFINED__ + +/* interface ICorProfilerCallback9 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerCallback9; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("27583EC3-C8F5-482F-8052-194B8CE4705A") + ICorProfilerCallback9 : public ICorProfilerCallback8 + { + public: + virtual HRESULT STDMETHODCALLTYPE DynamicMethodUnloaded( + /* [in] */ FunctionID functionId) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerCallback9Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerCallback9 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerCallback9 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + ICorProfilerCallback9 * This, + /* [in] */ IUnknown *pICorProfilerInfoUnk); + + HRESULT ( STDMETHODCALLTYPE *Shutdown )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( + ICorProfilerCallback9 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( + ICorProfilerCallback9 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( + ICorProfilerCallback9 * This, + /* [in] */ AppDomainID appDomainId); + + HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( + ICorProfilerCallback9 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ AssemblyID assemblyId); + + HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ AssemblyID AssemblyId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID classId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *pbUseCachedFunction); + + HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_JIT_CACHE result); + + HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *JITInlining )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID callerId, + /* [in] */ FunctionID calleeId, + /* [out] */ BOOL *pfShouldInline); + + HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID managedThreadId, + /* [in] */ DWORD osThreadId); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( + ICorProfilerCallback9 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( + ICorProfilerCallback9 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( + ICorProfilerCallback9 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( + ICorProfilerCallback9 * This, + /* [in] */ GUID *pCookie, + /* [in] */ BOOL fIsAsync); + + HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_TRANSITION_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( + ICorProfilerCallback9 * This, + /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID threadId); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( + ICorProfilerCallback9 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId); + + HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cClassCount, + /* [size_is][in] */ ClassID classIds[ ], + /* [size_is][in] */ ULONG cObjects[ ]); + + HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( + ICorProfilerCallback9 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ClassID classId, + /* [in] */ ULONG cObjectRefs, + /* [size_is][in] */ ObjectID objectRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RootReferences )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( + ICorProfilerCallback9 * This, + /* [in] */ ObjectID thrownObjectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( + ICorProfilerCallback9 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( + ICorProfilerCallback9 * This, + /* [in] */ UINT_PTR __unused); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ObjectID objectId); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable, + /* [in] */ ULONG cSlots); + + HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( + ICorProfilerCallback9 * This, + /* [in] */ ClassID wrappedClassId, + /* [in] */ REFGUID implementedIID, + /* [in] */ void *pVTable); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( + ICorProfilerCallback9 * This, + /* [in] */ ThreadID threadId, + /* [in] */ ULONG cchName, + /* [annotation][in] */ + _In_reads_opt_(cchName) WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( + ICorProfilerCallback9 * This, + /* [in] */ int cGenerations, + /* [size_is][in] */ BOOL generationCollected[ ], + /* [in] */ COR_PRF_GC_REASON reason); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( + ICorProfilerCallback9 * This, + /* [in] */ DWORD finalizerFlags, + /* [in] */ ObjectID objectID); + + HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID rootRefIds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], + /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], + /* [size_is][in] */ UINT_PTR rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *HandleCreated )( + ICorProfilerCallback9 * This, + /* [in] */ GCHandleID handleId, + /* [in] */ ObjectID initialObjectId); + + HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( + ICorProfilerCallback9 * This, + /* [in] */ GCHandleID handleId); + + HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( + ICorProfilerCallback9 * This, + /* [in] */ IUnknown *pCorProfilerInfoUnk, + /* [in] */ void *pvClientData, + /* [in] */ UINT cbClientData); + + HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( + ICorProfilerCallback9 * This); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ ICorProfilerFunctionControl *pFunctionControl); + + HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID rejitId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *ReJITError )( + ICorProfilerCallback9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus); + + HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cMovedObjectIDRanges, + /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], + /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cSurvivingObjectIDRanges, + /* [size_is][in] */ ObjectID objectIDRangeStart[ ], + /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); + + HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( + ICorProfilerCallback9 * This, + /* [in] */ ULONG cRootRefs, + /* [size_is][in] */ ObjectID keyRefIds[ ], + /* [size_is][in] */ ObjectID valueRefIds[ ], + /* [size_is][in] */ GCHandleID rootIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( + ICorProfilerCallback9 * This, + /* [string][in] */ const WCHAR *wszAssemblyPath, + /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); + + HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( + ICorProfilerCallback9 * This, + ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fIsSafeToBlock, + /* [in] */ LPCBYTE pILHeader, + /* [in] */ ULONG cbILHeader); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ HRESULT hrStatus, + /* [in] */ BOOL fIsSafeToBlock); + + HRESULT ( STDMETHODCALLTYPE *DynamicMethodUnloaded )( + ICorProfilerCallback9 * This, + /* [in] */ FunctionID functionId); + + END_INTERFACE + } ICorProfilerCallback9Vtbl; + + interface ICorProfilerCallback9 + { + CONST_VTBL struct ICorProfilerCallback9Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerCallback9_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerCallback9_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerCallback9_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerCallback9_Initialize(This,pICorProfilerInfoUnk) \ + ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) + +#define ICorProfilerCallback9_Shutdown(This) \ + ( (This)->lpVtbl -> Shutdown(This) ) + +#define ICorProfilerCallback9_AppDomainCreationStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) + +#define ICorProfilerCallback9_AppDomainCreationFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback9_AppDomainShutdownStarted(This,appDomainId) \ + ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) + +#define ICorProfilerCallback9_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ + ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) + +#define ICorProfilerCallback9_AssemblyLoadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) + +#define ICorProfilerCallback9_AssemblyLoadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback9_AssemblyUnloadStarted(This,assemblyId) \ + ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) + +#define ICorProfilerCallback9_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ + ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) + +#define ICorProfilerCallback9_ModuleLoadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) + +#define ICorProfilerCallback9_ModuleLoadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback9_ModuleUnloadStarted(This,moduleId) \ + ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) + +#define ICorProfilerCallback9_ModuleUnloadFinished(This,moduleId,hrStatus) \ + ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) + +#define ICorProfilerCallback9_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ + ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) + +#define ICorProfilerCallback9_ClassLoadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) + +#define ICorProfilerCallback9_ClassLoadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback9_ClassUnloadStarted(This,classId) \ + ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) + +#define ICorProfilerCallback9_ClassUnloadFinished(This,classId,hrStatus) \ + ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) + +#define ICorProfilerCallback9_FunctionUnloadStarted(This,functionId) \ + ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) + +#define ICorProfilerCallback9_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) + +#define ICorProfilerCallback9_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback9_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) + +#define ICorProfilerCallback9_JITCachedFunctionSearchFinished(This,functionId,result) \ + ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) + +#define ICorProfilerCallback9_JITFunctionPitched(This,functionId) \ + ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) + +#define ICorProfilerCallback9_JITInlining(This,callerId,calleeId,pfShouldInline) \ + ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) + +#define ICorProfilerCallback9_ThreadCreated(This,threadId) \ + ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) + +#define ICorProfilerCallback9_ThreadDestroyed(This,threadId) \ + ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) + +#define ICorProfilerCallback9_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ + ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) + +#define ICorProfilerCallback9_RemotingClientInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) + +#define ICorProfilerCallback9_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback9_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback9_RemotingClientInvocationFinished(This) \ + ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) + +#define ICorProfilerCallback9_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback9_RemotingServerInvocationStarted(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) + +#define ICorProfilerCallback9_RemotingServerInvocationReturned(This) \ + ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) + +#define ICorProfilerCallback9_RemotingServerSendingReply(This,pCookie,fIsAsync) \ + ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) + +#define ICorProfilerCallback9_UnmanagedToManagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback9_ManagedToUnmanagedTransition(This,functionId,reason) \ + ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) + +#define ICorProfilerCallback9_RuntimeSuspendStarted(This,suspendReason) \ + ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) + +#define ICorProfilerCallback9_RuntimeSuspendFinished(This) \ + ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) + +#define ICorProfilerCallback9_RuntimeSuspendAborted(This) \ + ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) + +#define ICorProfilerCallback9_RuntimeResumeStarted(This) \ + ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) + +#define ICorProfilerCallback9_RuntimeResumeFinished(This) \ + ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) + +#define ICorProfilerCallback9_RuntimeThreadSuspended(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) + +#define ICorProfilerCallback9_RuntimeThreadResumed(This,threadId) \ + ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) + +#define ICorProfilerCallback9_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback9_ObjectAllocated(This,objectId,classId) \ + ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) + +#define ICorProfilerCallback9_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ + ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) + +#define ICorProfilerCallback9_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ + ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) + +#define ICorProfilerCallback9_RootReferences(This,cRootRefs,rootRefIds) \ + ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) + +#define ICorProfilerCallback9_ExceptionThrown(This,thrownObjectId) \ + ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) + +#define ICorProfilerCallback9_ExceptionSearchFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback9_ExceptionSearchFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) + +#define ICorProfilerCallback9_ExceptionSearchFilterEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) + +#define ICorProfilerCallback9_ExceptionSearchFilterLeave(This) \ + ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) + +#define ICorProfilerCallback9_ExceptionSearchCatcherFound(This,functionId) \ + ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) + +#define ICorProfilerCallback9_ExceptionOSHandlerEnter(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) + +#define ICorProfilerCallback9_ExceptionOSHandlerLeave(This,__unused) \ + ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) + +#define ICorProfilerCallback9_ExceptionUnwindFunctionEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) + +#define ICorProfilerCallback9_ExceptionUnwindFunctionLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) + +#define ICorProfilerCallback9_ExceptionUnwindFinallyEnter(This,functionId) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) + +#define ICorProfilerCallback9_ExceptionUnwindFinallyLeave(This) \ + ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) + +#define ICorProfilerCallback9_ExceptionCatcherEnter(This,functionId,objectId) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) + +#define ICorProfilerCallback9_ExceptionCatcherLeave(This) \ + ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) + +#define ICorProfilerCallback9_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ + ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) + +#define ICorProfilerCallback9_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ + ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) + +#define ICorProfilerCallback9_ExceptionCLRCatcherFound(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) + +#define ICorProfilerCallback9_ExceptionCLRCatcherExecute(This) \ + ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) + + +#define ICorProfilerCallback9_ThreadNameChanged(This,threadId,cchName,name) \ + ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) + +#define ICorProfilerCallback9_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ + ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) + +#define ICorProfilerCallback9_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback9_GarbageCollectionFinished(This) \ + ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) + +#define ICorProfilerCallback9_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ + ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) + +#define ICorProfilerCallback9_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ + ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) + +#define ICorProfilerCallback9_HandleCreated(This,handleId,initialObjectId) \ + ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) + +#define ICorProfilerCallback9_HandleDestroyed(This,handleId) \ + ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) + + +#define ICorProfilerCallback9_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ + ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) + +#define ICorProfilerCallback9_ProfilerAttachComplete(This) \ + ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) + +#define ICorProfilerCallback9_ProfilerDetachSucceeded(This) \ + ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) + + +#define ICorProfilerCallback9_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) + +#define ICorProfilerCallback9_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ + ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) + +#define ICorProfilerCallback9_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) + +#define ICorProfilerCallback9_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ + ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) + +#define ICorProfilerCallback9_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) + +#define ICorProfilerCallback9_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ + ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) + + +#define ICorProfilerCallback9_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ + ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) + + +#define ICorProfilerCallback9_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ + ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) + + +#define ICorProfilerCallback9_ModuleInMemorySymbolsUpdated(This,moduleId) \ + ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) + + +#define ICorProfilerCallback9_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) + +#define ICorProfilerCallback9_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ + ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) + + +#define ICorProfilerCallback9_DynamicMethodUnloaded(This,functionId) \ + ( (This)->lpVtbl -> DynamicMethodUnloaded(This,functionId) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerCallback9_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corprof_0000_0009 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_corprof_0000_0009_0001 + { + COR_PRF_CODEGEN_DISABLE_INLINING = 0x1, + COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x2 + } COR_PRF_CODEGEN_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0009_v0_0_s_ifspec; + +#ifndef __ICorProfilerInfo_INTERFACE_DEFINED__ +#define __ICorProfilerInfo_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48") + ICorProfilerInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo( + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEventMask( + /* [out] */ DWORD *pdwEvents) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize( + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsArrayClass( + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( + /* [out] */ ThreadID *pThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo( + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo( + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEventMask( + /* [in] */ DWORD dwEvents) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks( + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( + /* [in] */ FunctionIDMapper *pFunc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTokenAndMetaDataFromFunction( + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleInfo( + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleMetaData( + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILFunctionBody( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainInfo( + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyInfo( + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( + /* [in] */ FunctionID functionId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ForceGC( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( + /* [out] */ IUnknown **ppicd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( + /* [out] */ IUnknown **ppicd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadContext( + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( + /* [in] */ DWORD dwProfilerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + END_INTERFACE + } ICorProfilerInfoVtbl; + + interface ICorProfilerInfo + { + CONST_VTBL struct ICorProfilerInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo2_INTERFACE_DEFINED__ +#define __ICorProfilerInfo2_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo2 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CC0935CD-A518-487d-B0BB-A93214E65478") + ICorProfilerInfo2 : public ICorProfilerInfo + { + public: + virtual HRESULT STDMETHODCALLTYPE DoStackSnapshot( + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks2( + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo2( + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStringLayout( + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassLayout( + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo2( + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo2( + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClassFromTokenAndTypeArgs( + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromTokenAndTypeArgs( + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArrayObjectInfo( + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRVAStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContextStaticAddress( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldInfo( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGenerationBounds( + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo2 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo2 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo2 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo2 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo2 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo2 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo2 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo2 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo2 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo2 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo2 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo2 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo2 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo2 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo2 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo2 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo2 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo2 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo2 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo2 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo2 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo2 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo2 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo2 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo2 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + END_INTERFACE + } ICorProfilerInfo2Vtbl; + + interface ICorProfilerInfo2 + { + CONST_VTBL struct ICorProfilerInfo2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo2_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo2_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo2_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo2_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo2_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo2_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo2_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo2_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo2_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo2_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo2_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo2_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo2_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo2_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo2_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo2_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo2_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo2_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo2_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo2_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo2_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo2_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo2_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo2_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo2_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo2_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo2_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo2_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo2_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo2_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo2_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo2_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo2_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo2_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo2_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo2_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo2_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo2_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo2_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo2_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo2_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo2_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo2_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo2_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo2_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo2_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo2_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo2_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo2_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo2_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo2_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo2_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo2_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo3_INTERFACE_DEFINED__ +#define __ICorProfilerInfo3_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo3 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B555ED4F-452A-4E54-8B39-B5360BAD32A0") + ICorProfilerInfo3 : public ICorProfilerInfo2 + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( + /* [in] */ DWORD dwExpectedCompletionMilliseconds) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3( + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3WithInfo( + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionEnter3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionLeave3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionTailcall3Info( + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumModules( + /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRuntimeInformation( + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress2( + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainsContainingModule( + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleInfo2( + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo3 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo3 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo3 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo3 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo3 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo3 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo3 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo3 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo3 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo3 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo3 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo3 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo3 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo3 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo3 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo3 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo3 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo3 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo3 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo3 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo3 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo3 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + END_INTERFACE + } ICorProfilerInfo3Vtbl; + + interface ICorProfilerInfo3 + { + CONST_VTBL struct ICorProfilerInfo3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo3_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo3_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo3_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo3_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo3_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo3_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo3_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo3_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo3_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo3_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo3_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo3_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo3_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo3_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo3_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo3_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo3_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo3_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo3_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo3_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo3_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo3_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo3_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo3_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo3_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo3_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo3_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo3_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo3_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo3_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo3_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo3_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo3_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo3_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo3_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo3_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo3_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo3_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo3_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo3_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo3_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo3_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo3_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo3_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo3_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo3_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo3_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo3_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo3_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo3_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo3_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo3_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo3_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo3_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo3_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo3_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo3_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo3_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo3_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo3_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo3_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo3_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo3_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo3_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerObjectEnum_INTERFACE_DEFINED__ +#define __ICorProfilerObjectEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerObjectEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerObjectEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2C6269BD-2D13-4321-AE12-6686365FD6AF") + ICorProfilerObjectEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ObjectID objects[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerObjectEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerObjectEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerObjectEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerObjectEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerObjectEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerObjectEnum * This, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerObjectEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerObjectEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ObjectID objects[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerObjectEnumVtbl; + + interface ICorProfilerObjectEnum + { + CONST_VTBL struct ICorProfilerObjectEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerObjectEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerObjectEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerObjectEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerObjectEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerObjectEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerObjectEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerObjectEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerObjectEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerObjectEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ +#define __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerFunctionEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerFunctionEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FF71301A-B994-429D-A10B-B345A65280EF") + ICorProfilerFunctionEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerFunctionEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerFunctionEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerFunctionEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerFunctionEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerFunctionEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerFunctionEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerFunctionEnum * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerFunctionEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerFunctionEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerFunctionEnumVtbl; + + interface ICorProfilerFunctionEnum + { + CONST_VTBL struct ICorProfilerFunctionEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerFunctionEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerFunctionEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerFunctionEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerFunctionEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerFunctionEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerFunctionEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerFunctionEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerFunctionEnum_Next(This,celt,ids,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerModuleEnum_INTERFACE_DEFINED__ +#define __ICorProfilerModuleEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerModuleEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerModuleEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("b0266d75-2081-4493-af7f-028ba34db891") + ICorProfilerModuleEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ModuleID ids[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerModuleEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerModuleEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerModuleEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerModuleEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerModuleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerModuleEnum * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerModuleEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerModuleEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ModuleID ids[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerModuleEnumVtbl; + + interface ICorProfilerModuleEnum + { + CONST_VTBL struct ICorProfilerModuleEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerModuleEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerModuleEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerModuleEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerModuleEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerModuleEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerModuleEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerModuleEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerModuleEnum_Next(This,celt,ids,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerModuleEnum_INTERFACE_DEFINED__ */ + + +#ifndef __IMethodMalloc_INTERFACE_DEFINED__ +#define __IMethodMalloc_INTERFACE_DEFINED__ + +/* interface IMethodMalloc */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_IMethodMalloc; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8") + IMethodMalloc : public IUnknown + { + public: + virtual PVOID STDMETHODCALLTYPE Alloc( + /* [in] */ ULONG cb) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IMethodMallocVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IMethodMalloc * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IMethodMalloc * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IMethodMalloc * This); + + PVOID ( STDMETHODCALLTYPE *Alloc )( + IMethodMalloc * This, + /* [in] */ ULONG cb); + + END_INTERFACE + } IMethodMallocVtbl; + + interface IMethodMalloc + { + CONST_VTBL struct IMethodMallocVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IMethodMalloc_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IMethodMalloc_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IMethodMalloc_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IMethodMalloc_Alloc(This,cb) \ + ( (This)->lpVtbl -> Alloc(This,cb) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IMethodMalloc_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerFunctionControl_INTERFACE_DEFINED__ +#define __ICorProfilerFunctionControl_INTERFACE_DEFINED__ + +/* interface ICorProfilerFunctionControl */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerFunctionControl; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F0963021-E1EA-4732-8581-E01B0BD3C0C6") + ICorProfilerFunctionControl : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetCodegenFlags( + /* [in] */ DWORD flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( + /* [in] */ ULONG cbNewILMethodHeader, + /* [size_is][in] */ LPCBYTE pbNewILMethodHeader) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerFunctionControlVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerFunctionControl * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerFunctionControl * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerFunctionControl * This); + + HRESULT ( STDMETHODCALLTYPE *SetCodegenFlags )( + ICorProfilerFunctionControl * This, + /* [in] */ DWORD flags); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerFunctionControl * This, + /* [in] */ ULONG cbNewILMethodHeader, + /* [size_is][in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerFunctionControl * This, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + END_INTERFACE + } ICorProfilerFunctionControlVtbl; + + interface ICorProfilerFunctionControl + { + CONST_VTBL struct ICorProfilerFunctionControlVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerFunctionControl_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerFunctionControl_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerFunctionControl_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerFunctionControl_SetCodegenFlags(This,flags) \ + ( (This)->lpVtbl -> SetCodegenFlags(This,flags) ) + +#define ICorProfilerFunctionControl_SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) ) + +#define ICorProfilerFunctionControl_SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerFunctionControl_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo4_INTERFACE_DEFINED__ +#define __ICorProfilerInfo4_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo4 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0d8fdcaa-6257-47bf-b1bf-94dac88466ee") + ICorProfilerInfo4 : public ICorProfilerInfo3 + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumThreads( + /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestReJIT( + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestRevert( + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo3( + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP2( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReJITIDs( + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping2( + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( + /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo4 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo4 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo4 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo4 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo4 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo4 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo4 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo4 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo4 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo4 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo4 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo4 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo4 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo4 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo4 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo4 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo4 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo4 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo4 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo4 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo4 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo4 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo4 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + END_INTERFACE + } ICorProfilerInfo4Vtbl; + + interface ICorProfilerInfo4 + { + CONST_VTBL struct ICorProfilerInfo4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo4_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo4_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo4_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo4_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo4_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo4_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo4_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo4_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo4_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo4_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo4_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo4_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo4_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo4_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo4_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo4_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo4_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo4_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo4_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo4_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo4_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo4_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo4_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo4_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo4_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo4_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo4_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo4_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo4_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo4_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo4_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo4_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo4_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo4_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo4_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo4_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo4_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo4_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo4_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo4_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo4_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo4_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo4_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo4_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo4_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo4_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo4_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo4_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo4_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo4_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo4_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo4_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo4_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo4_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo4_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo4_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo4_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo4_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo4_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo4_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo4_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo4_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo4_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo4_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo4_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo4_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo4_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo4_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo4_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo4_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo4_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo4_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo4_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo4_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo5_INTERFACE_DEFINED__ +#define __ICorProfilerInfo5_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo5 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("07602928-CE38-4B83-81E7-74ADAF781214") + ICorProfilerInfo5 : public ICorProfilerInfo4 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEventMask2( + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetEventMask2( + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo5 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo5 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo5 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo5 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo5 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo5 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo5 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo5 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo5 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo5 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo5 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo5 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo5 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo5 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo5 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo5 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo5 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo5 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo5 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo5 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo5 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo5 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo5 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo5 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo5 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo5 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo5 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo5 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo5 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo5 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo5 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo5 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo5 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo5 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo5 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo5 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo5 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo5 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo5 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo5 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo5 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + END_INTERFACE + } ICorProfilerInfo5Vtbl; + + interface ICorProfilerInfo5 + { + CONST_VTBL struct ICorProfilerInfo5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo5_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo5_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo5_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo5_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo5_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo5_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo5_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo5_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo5_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo5_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo5_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo5_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo5_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo5_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo5_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo5_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo5_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo5_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo5_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo5_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo5_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo5_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo5_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo5_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo5_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo5_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo5_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo5_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo5_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo5_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo5_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo5_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo5_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo5_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo5_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo5_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo5_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo5_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo5_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo5_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo5_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo5_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo5_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo5_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo5_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo5_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo5_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo5_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo5_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo5_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo5_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo5_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo5_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo5_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo5_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo5_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo5_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo5_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo5_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo5_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo5_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo5_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo5_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo5_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo5_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo5_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo5_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo5_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo5_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo5_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo5_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo5_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo5_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo5_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo5_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo5_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo5_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo6_INTERFACE_DEFINED__ +#define __ICorProfilerInfo6_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo6 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo6; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F30A070D-BFFB-46A7-B1D8-8781EF7B698A") + ICorProfilerInfo6 : public ICorProfilerInfo5 + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumNgenModuleMethodsInliningThisMethod( + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo6Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo6 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo6 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo6 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo6 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo6 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo6 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo6 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo6 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo6 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo6 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo6 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo6 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo6 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo6 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo6 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo6 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo6 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo6 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo6 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo6 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo6 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo6 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo6 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo6 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo6 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo6 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo6 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo6 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo6 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo6 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo6 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo6 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo6 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo6 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo6 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo6 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo6 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo6 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo6 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo6 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo6 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo6 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo6 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + END_INTERFACE + } ICorProfilerInfo6Vtbl; + + interface ICorProfilerInfo6 + { + CONST_VTBL struct ICorProfilerInfo6Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo6_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo6_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo6_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo6_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo6_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo6_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo6_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo6_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo6_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo6_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo6_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo6_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo6_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo6_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo6_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo6_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo6_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo6_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo6_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo6_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo6_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo6_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo6_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo6_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo6_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo6_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo6_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo6_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo6_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo6_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo6_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo6_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo6_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo6_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo6_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo6_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo6_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo6_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo6_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo6_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo6_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo6_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo6_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo6_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo6_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo6_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo6_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo6_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo6_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo6_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo6_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo6_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo6_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo6_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo6_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo6_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo6_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo6_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo6_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo6_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo6_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo6_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo6_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo6_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo6_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo6_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo6_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo6_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo6_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo6_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo6_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo6_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo6_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo6_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo6_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo6_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo6_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo6_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo6_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo6_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo6_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo7_INTERFACE_DEFINED__ +#define __ICorProfilerInfo7_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo7 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo7; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9AEECC0D-63E0-4187-8C00-E312F503F663") + ICorProfilerInfo7 : public ICorProfilerInfo6 + { + public: + virtual HRESULT STDMETHODCALLTYPE ApplyMetaData( + /* [in] */ ModuleID moduleId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInMemorySymbolsLength( + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReadInMemorySymbols( + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo7Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo7 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo7 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo7 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo7 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo7 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo7 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo7 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo7 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo7 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo7 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo7 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo7 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo7 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo7 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo7 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo7 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo7 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo7 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo7 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo7 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo7 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo7 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo7 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo7 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo7 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo7 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo7 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo7 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo7 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo7 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo7 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo7 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo7 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo7 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo7 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo7 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo7 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo7 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo7 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo7 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo7 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo7 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo7 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + END_INTERFACE + } ICorProfilerInfo7Vtbl; + + interface ICorProfilerInfo7 + { + CONST_VTBL struct ICorProfilerInfo7Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo7_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo7_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo7_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo7_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo7_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo7_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo7_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo7_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo7_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo7_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo7_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo7_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo7_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo7_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo7_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo7_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo7_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo7_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo7_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo7_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo7_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo7_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo7_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo7_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo7_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo7_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo7_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo7_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo7_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo7_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo7_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo7_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo7_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo7_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo7_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo7_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo7_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo7_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo7_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo7_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo7_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo7_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo7_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo7_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo7_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo7_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo7_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo7_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo7_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo7_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo7_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo7_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo7_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo7_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo7_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo7_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo7_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo7_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo7_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo7_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo7_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo7_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo7_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo7_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo7_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo7_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo7_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo7_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo7_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo7_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo7_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo7_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo7_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo7_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo7_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo7_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo7_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo7_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo7_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo7_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo7_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo7_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo7_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo7_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo8_INTERFACE_DEFINED__ +#define __ICorProfilerInfo8_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo8 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo8; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C5AC80A6-782E-4716-8044-39598C60CFBF") + ICorProfilerInfo8 : public ICorProfilerInfo7 + { + public: + virtual HRESULT STDMETHODCALLTYPE IsFunctionDynamic( + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP3( + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDynamicFunctionInfo( + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo8Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo8 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo8 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo8 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo8 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo8 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo8 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo8 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo8 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo8 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo8 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo8 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo8 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo8 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo8 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo8 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo8 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo8 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo8 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo8 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo8 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo8 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo8 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo8 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo8 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo8 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo8 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo8 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo8 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo8 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo8 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo8 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo8 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo8 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo8 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo8 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo8 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo8 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo8 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo8 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo8 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo8 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo8 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo8 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo8 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + + END_INTERFACE + } ICorProfilerInfo8Vtbl; + + interface ICorProfilerInfo8 + { + CONST_VTBL struct ICorProfilerInfo8Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo8_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo8_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo8_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo8_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo8_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo8_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo8_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo8_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo8_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo8_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo8_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo8_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo8_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo8_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo8_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo8_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo8_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo8_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo8_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo8_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo8_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo8_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo8_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo8_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo8_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo8_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo8_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo8_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo8_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo8_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo8_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo8_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo8_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo8_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo8_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo8_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo8_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo8_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo8_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo8_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo8_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo8_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo8_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo8_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo8_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo8_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo8_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo8_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo8_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo8_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo8_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo8_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo8_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo8_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo8_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo8_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo8_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo8_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo8_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo8_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo8_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo8_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo8_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo8_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo8_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo8_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo8_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo8_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo8_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo8_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo8_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo8_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo8_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo8_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo8_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo8_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo8_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo8_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo8_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo8_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo8_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo8_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo8_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + + +#define ICorProfilerInfo8_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo8_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo8_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo8_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo9_INTERFACE_DEFINED__ +#define __ICorProfilerInfo9_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo9 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo9; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("008170DB-F8CC-4796-9A51-DC8AA0B47012") + ICorProfilerInfo9 : public ICorProfilerInfo8 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetNativeCodeStartAddresses( + FunctionID functionID, + ReJITID reJitId, + ULONG32 cCodeStartAddresses, + ULONG32 *pcCodeStartAddresses, + UINT_PTR codeStartAddresses[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping3( + UINT_PTR pNativeCodeStartAddress, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeInfo4( + UINT_PTR pNativeCodeStartAddress, + ULONG32 cCodeInfos, + ULONG32 *pcCodeInfos, + COR_PRF_CODE_INFO codeInfos[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo9Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo9 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo9 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo9 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo9 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo9 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo9 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo9 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo9 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo9 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo9 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo9 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo9 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo9 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo9 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo9 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo9 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo9 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo9 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo9 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo9 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo9 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo9 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo9 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo9 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo9 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo9 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo9 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo9 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo9 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo9 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo9 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo9 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo9 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo9 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo9 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo9 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo9 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo9 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo9 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo9 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo9 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo9 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo9 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo9 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( + ICorProfilerInfo9 * This, + FunctionID functionID, + ReJITID reJitId, + ULONG32 cCodeStartAddresses, + ULONG32 *pcCodeStartAddresses, + UINT_PTR codeStartAddresses[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( + ICorProfilerInfo9 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( + ICorProfilerInfo9 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cCodeInfos, + ULONG32 *pcCodeInfos, + COR_PRF_CODE_INFO codeInfos[ ]); + + END_INTERFACE + } ICorProfilerInfo9Vtbl; + + interface ICorProfilerInfo9 + { + CONST_VTBL struct ICorProfilerInfo9Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo9_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo9_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo9_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo9_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo9_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo9_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo9_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo9_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo9_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo9_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo9_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo9_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo9_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo9_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo9_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo9_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo9_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo9_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo9_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo9_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo9_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo9_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo9_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo9_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo9_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo9_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo9_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo9_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo9_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo9_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo9_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo9_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo9_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo9_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo9_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo9_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo9_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo9_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo9_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo9_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo9_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo9_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo9_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo9_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo9_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo9_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo9_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo9_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo9_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo9_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo9_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo9_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo9_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo9_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo9_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo9_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo9_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo9_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo9_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo9_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo9_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo9_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo9_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo9_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo9_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo9_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo9_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo9_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo9_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo9_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo9_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo9_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo9_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo9_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo9_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo9_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo9_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo9_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo9_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo9_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo9_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo9_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo9_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo9_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo9_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo9_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo9_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + + +#define ICorProfilerInfo9_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo9_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo9_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + + +#define ICorProfilerInfo9_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ + ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) + +#define ICorProfilerInfo9_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) + +#define ICorProfilerInfo9_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo9_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerInfo10_INTERFACE_DEFINED__ +#define __ICorProfilerInfo10_INTERFACE_DEFINED__ + +/* interface ICorProfilerInfo10 */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerInfo10; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2F1B5152-C869-40C9-AA5F-3ABE026BD720") + ICorProfilerInfo10 : public ICorProfilerInfo9 + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumerateObjectReferences( + ObjectID objectId, + ObjectReferenceCallback callback, + void *clientData) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsFrozenObject( + ObjectID objectId, + BOOL *pbFrozen) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLOHObjectSizeThreshold( + DWORD *pThreshold) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestReJITWithInliners( + /* [in] */ DWORD dwRejitFlags, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SuspendRuntime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResumeRuntime( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerInfo10Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerInfo10 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerInfo10 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerInfo10 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( + ICorProfilerInfo10 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdTypeDef typeDef, + /* [out] */ ClassID *pClassId); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [out] */ LPCBYTE *pStart, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask )( + ICorProfilerInfo10 * This, + /* [out] */ DWORD *pdwEvents); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( + ICorProfilerInfo10 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdToken token, + /* [out] */ FunctionID *pFunctionId); + + HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( + ICorProfilerInfo10 * This, + /* [in] */ ThreadID threadId, + /* [out] */ HANDLE *phThread); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( + ICorProfilerInfo10 * This, + /* [in] */ ObjectID objectId, + /* [out] */ ULONG *pcSize); + + HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [out] */ CorElementType *pBaseElemType, + /* [out] */ ClassID *pBaseClassId, + /* [out] */ ULONG *pcRank); + + HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( + ICorProfilerInfo10 * This, + /* [in] */ ThreadID threadId, + /* [out] */ DWORD *pdwWin32ThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + ICorProfilerInfo10 * This, + /* [out] */ ThreadID *pThreadId); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask )( + ICorProfilerInfo10 * This, + /* [in] */ DWORD dwEvents); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionEnter *pFuncEnter, + /* [in] */ FunctionLeave *pFuncLeave, + /* [in] */ FunctionTailcall *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionIDMapper *pFunc); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppImport, + /* [out] */ mdToken *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId); + + HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD dwOpenFlags, + /* [in] */ REFIID riid, + /* [out] */ IUnknown **ppOut); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodId, + /* [out] */ LPCBYTE *ppMethodHeader, + /* [out] */ ULONG *pcbMethodSize); + + HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ IMethodMalloc **ppMalloc); + + HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ mdMethodDef methodid, + /* [in] */ LPCBYTE pbNewILMethodHeader); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( + ICorProfilerInfo10 * This, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ ProcessID *pProcessId); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( + ICorProfilerInfo10 * This, + /* [in] */ AssemblyID assemblyId, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AppDomainID *pAppDomainId, + /* [out] */ ModuleID *pModuleId); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId); + + HRESULT ( STDMETHODCALLTYPE *ForceGC )( + ICorProfilerInfo10 * This); + + HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ BOOL fStartJit, + /* [in] */ ULONG cILMapEntries, + /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( + ICorProfilerInfo10 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( + ICorProfilerInfo10 * This, + /* [out] */ IUnknown **ppicd); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + ICorProfilerInfo10 * This, + /* [in] */ ThreadID threadId, + /* [out] */ ContextID *pContextId); + + HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( + ICorProfilerInfo10 * This, + /* [in] */ BOOL fThisThreadOnly, + /* [out] */ DWORD *pdwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( + ICorProfilerInfo10 * This, + /* [in] */ DWORD dwProfilerContext); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( + ICorProfilerInfo10 * This, + /* [in] */ ThreadID thread, + /* [in] */ StackSnapshotCallback *callback, + /* [in] */ ULONG32 infoFlags, + /* [in] */ void *clientData, + /* [size_is][in] */ BYTE context[ ], + /* [in] */ ULONG32 contextSize); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionEnter2 *pFuncEnter, + /* [in] */ FunctionLeave2 *pFuncLeave, + /* [in] */ FunctionTailcall2 *pFuncTailcall); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID funcId, + /* [in] */ COR_PRF_FRAME_INFO frameInfo, + /* [out] */ ClassID *pClassId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdToken *pToken, + /* [in] */ ULONG32 cTypeArgs, + /* [out] */ ULONG32 *pcTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( + ICorProfilerInfo10 * This, + /* [out] */ ULONG *pBufferLengthOffset, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classID, + /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], + /* [in] */ ULONG cFieldOffset, + /* [out] */ ULONG *pcFieldOffset, + /* [out] */ ULONG *pulClassSize); + + HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [out] */ ModuleID *pModuleId, + /* [out] */ mdTypeDef *pTypeDefToken, + /* [out] */ ClassID *pParentClassId, + /* [in] */ ULONG32 cNumTypeArgs, + /* [out] */ ULONG32 *pcNumTypeArgs, + /* [out] */ ClassID typeArgs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdTypeDef typeDef, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ ClassID *pClassID); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleID, + /* [in] */ mdMethodDef funcDef, + /* [in] */ ClassID classId, + /* [in] */ ULONG32 cTypeArgs, + /* [size_is][in] */ ClassID typeArgs[ ], + /* [out] */ FunctionID *pFunctionID); + + HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleID, + /* [out] */ ICorProfilerObjectEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( + ICorProfilerInfo10 * This, + /* [in] */ ObjectID objectId, + /* [in] */ ULONG32 cDimensions, + /* [size_is][out] */ ULONG32 pDimensionSizes[ ], + /* [size_is][out] */ int pDimensionLowerBounds[ ], + /* [out] */ BYTE **ppData); + + HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [out] */ ULONG32 *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( + ICorProfilerInfo10 * This, + /* [in] */ ThreadID threadId, + /* [out] */ AppDomainID *pAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ ContextID contextId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); + + HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( + ICorProfilerInfo10 * This, + /* [in] */ ULONG cObjectRanges, + /* [out] */ ULONG *pcObjectRanges, + /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( + ICorProfilerInfo10 * This, + /* [in] */ ObjectID objectId, + /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); + + HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( + ICorProfilerInfo10 * This, + /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( + ICorProfilerInfo10 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( + ICorProfilerInfo10 * This, + /* [in] */ DWORD dwExpectedCompletionMilliseconds); + + HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionIDMapper2 *pFunc, + /* [in] */ void *clientData); + + HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( + ICorProfilerInfo10 * This, + /* [out] */ ULONG *pStringLengthOffset, + /* [out] */ ULONG *pBufferOffset); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionEnter3 *pFuncEnter3, + /* [in] */ FunctionLeave3 *pFuncLeave3, + /* [in] */ FunctionTailcall3 *pFuncTailcall3); + + HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, + /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, + /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out][in] */ ULONG *pcbArgumentInfo, + /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, + /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ COR_PRF_ELT_INFO eltInfo, + /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); + + HRESULT ( STDMETHODCALLTYPE *EnumModules )( + ICorProfilerInfo10 * This, + /* [out] */ ICorProfilerModuleEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( + ICorProfilerInfo10 * This, + /* [out] */ USHORT *pClrInstanceId, + /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, + /* [out] */ USHORT *pMajorVersion, + /* [out] */ USHORT *pMinorVersion, + /* [out] */ USHORT *pBuildNumber, + /* [out] */ USHORT *pQFEVersion, + /* [in] */ ULONG cchVersionString, + /* [out] */ ULONG *pcchVersionString, + /* [annotation][out] */ + _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( + ICorProfilerInfo10 * This, + /* [in] */ ClassID classId, + /* [in] */ mdFieldDef fieldToken, + /* [in] */ AppDomainID appDomainId, + /* [in] */ ThreadID threadId, + /* [out] */ void **ppAddress); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ ULONG32 cAppDomainIds, + /* [out] */ ULONG32 *pcAppDomainIds, + /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ LPCBYTE *ppBaseLoadAddress, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [annotation][out] */ + _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], + /* [out] */ AssemblyID *pAssemblyId, + /* [out] */ DWORD *pdwModuleFlags); + + HRESULT ( STDMETHODCALLTYPE *EnumThreads )( + ICorProfilerInfo10 * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( + ICorProfilerInfo10 * This); + + HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( + ICorProfilerInfo10 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *RequestRevert )( + ICorProfilerInfo10 * This, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ], + /* [size_is][out] */ HRESULT status[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionID, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cCodeInfos, + /* [out] */ ULONG32 *pcCodeInfos, + /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( + ICorProfilerInfo10 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *pFunctionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ULONG cReJitIds, + /* [out] */ ULONG *pcReJitIds, + /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [in] */ ReJITID reJitId, + /* [in] */ ULONG32 cMap, + /* [out] */ ULONG32 *pcMap, + /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( + ICorProfilerInfo10 * This, + /* [out] */ ICorProfilerFunctionEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( + ICorProfilerInfo10 * This, + /* [in] */ ObjectID objectId, + /* [out] */ SIZE_T *pcSize); + + HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( + ICorProfilerInfo10 * This, + /* [out] */ DWORD *pdwEventsLow, + /* [out] */ DWORD *pdwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( + ICorProfilerInfo10 * This, + /* [in] */ DWORD dwEventsLow, + /* [in] */ DWORD dwEventsHigh); + + HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID inlinersModuleId, + /* [in] */ ModuleID inlineeModuleId, + /* [in] */ mdMethodDef inlineeMethodId, + /* [out] */ BOOL *incompleteData, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId); + + HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [out] */ DWORD *pCountSymbolBytes); + + HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( + ICorProfilerInfo10 * This, + /* [in] */ ModuleID moduleId, + /* [in] */ DWORD symbolsReadOffset, + /* [out] */ BYTE *pSymbolBytes, + /* [in] */ DWORD countSymbolBytes, + /* [out] */ DWORD *pCountSymbolBytesRead); + + HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [out] */ BOOL *isDynamic); + + HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( + ICorProfilerInfo10 * This, + /* [in] */ LPCBYTE ip, + /* [out] */ FunctionID *functionId, + /* [out] */ ReJITID *pReJitId); + + HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( + ICorProfilerInfo10 * This, + /* [in] */ FunctionID functionId, + /* [out] */ ModuleID *moduleId, + /* [out] */ PCCOR_SIGNATURE *ppvSig, + /* [out] */ ULONG *pbSig, + /* [in] */ ULONG cchName, + /* [out] */ ULONG *pcchName, + /* [out] */ WCHAR wszName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( + ICorProfilerInfo10 * This, + FunctionID functionID, + ReJITID reJitId, + ULONG32 cCodeStartAddresses, + ULONG32 *pcCodeStartAddresses, + UINT_PTR codeStartAddresses[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( + ICorProfilerInfo10 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cMap, + ULONG32 *pcMap, + COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( + ICorProfilerInfo10 * This, + UINT_PTR pNativeCodeStartAddress, + ULONG32 cCodeInfos, + ULONG32 *pcCodeInfos, + COR_PRF_CODE_INFO codeInfos[ ]); + + HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( + ICorProfilerInfo10 * This, + ObjectID objectId, + ObjectReferenceCallback callback, + void *clientData); + + HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( + ICorProfilerInfo10 * This, + ObjectID objectId, + BOOL *pbFrozen); + + HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( + ICorProfilerInfo10 * This, + DWORD *pThreshold); + + HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( + ICorProfilerInfo10 * This, + /* [in] */ DWORD dwRejitFlags, + /* [in] */ ULONG cFunctions, + /* [size_is][in] */ ModuleID moduleIds[ ], + /* [size_is][in] */ mdMethodDef methodIds[ ]); + + HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( + ICorProfilerInfo10 * This); + + HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( + ICorProfilerInfo10 * This); + + END_INTERFACE + } ICorProfilerInfo10Vtbl; + + interface ICorProfilerInfo10 + { + CONST_VTBL struct ICorProfilerInfo10Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerInfo10_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerInfo10_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerInfo10_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerInfo10_GetClassFromObject(This,objectId,pClassId) \ + ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) + +#define ICorProfilerInfo10_GetClassFromToken(This,moduleId,typeDef,pClassId) \ + ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) + +#define ICorProfilerInfo10_GetCodeInfo(This,functionId,pStart,pcSize) \ + ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) + +#define ICorProfilerInfo10_GetEventMask(This,pdwEvents) \ + ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) + +#define ICorProfilerInfo10_GetFunctionFromIP(This,ip,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) + +#define ICorProfilerInfo10_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ + ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) + +#define ICorProfilerInfo10_GetHandleFromThread(This,threadId,phThread) \ + ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) + +#define ICorProfilerInfo10_GetObjectSize(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) + +#define ICorProfilerInfo10_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ + ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) + +#define ICorProfilerInfo10_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ + ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) + +#define ICorProfilerInfo10_GetCurrentThreadID(This,pThreadId) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) + +#define ICorProfilerInfo10_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ + ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) + +#define ICorProfilerInfo10_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ + ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) + +#define ICorProfilerInfo10_SetEventMask(This,dwEvents) \ + ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) + +#define ICorProfilerInfo10_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo10_SetFunctionIDMapper(This,pFunc) \ + ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) + +#define ICorProfilerInfo10_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ + ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) + +#define ICorProfilerInfo10_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ + ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) + +#define ICorProfilerInfo10_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ + ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) + +#define ICorProfilerInfo10_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ + ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) + +#define ICorProfilerInfo10_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ + ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) + +#define ICorProfilerInfo10_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ + ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) + +#define ICorProfilerInfo10_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ + ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) + +#define ICorProfilerInfo10_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ + ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) + +#define ICorProfilerInfo10_SetFunctionReJIT(This,functionId) \ + ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) + +#define ICorProfilerInfo10_ForceGC(This) \ + ( (This)->lpVtbl -> ForceGC(This) ) + +#define ICorProfilerInfo10_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ + ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) + +#define ICorProfilerInfo10_GetInprocInspectionInterface(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) + +#define ICorProfilerInfo10_GetInprocInspectionIThisThread(This,ppicd) \ + ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) + +#define ICorProfilerInfo10_GetThreadContext(This,threadId,pContextId) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) + +#define ICorProfilerInfo10_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ + ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) + +#define ICorProfilerInfo10_EndInprocDebugging(This,dwProfilerContext) \ + ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) + +#define ICorProfilerInfo10_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) + + +#define ICorProfilerInfo10_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ + ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) + +#define ICorProfilerInfo10_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) + +#define ICorProfilerInfo10_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) + +#define ICorProfilerInfo10_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo10_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ + ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) + +#define ICorProfilerInfo10_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ + ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) + +#define ICorProfilerInfo10_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo10_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ + ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) + +#define ICorProfilerInfo10_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ + ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) + +#define ICorProfilerInfo10_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ + ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) + +#define ICorProfilerInfo10_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ + ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) + +#define ICorProfilerInfo10_GetBoxClassLayout(This,classId,pBufferOffset) \ + ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) + +#define ICorProfilerInfo10_GetThreadAppDomain(This,threadId,pAppDomainId) \ + ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) + +#define ICorProfilerInfo10_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ + ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) + +#define ICorProfilerInfo10_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ + ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) + +#define ICorProfilerInfo10_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) + +#define ICorProfilerInfo10_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ + ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) + +#define ICorProfilerInfo10_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ + ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) + +#define ICorProfilerInfo10_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ + ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) + +#define ICorProfilerInfo10_GetObjectGeneration(This,objectId,range) \ + ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) + +#define ICorProfilerInfo10_GetNotifiedExceptionClauseInfo(This,pinfo) \ + ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) + + +#define ICorProfilerInfo10_EnumJITedFunctions(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) + +#define ICorProfilerInfo10_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ + ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) + +#define ICorProfilerInfo10_SetFunctionIDMapper2(This,pFunc,clientData) \ + ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) + +#define ICorProfilerInfo10_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ + ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) + +#define ICorProfilerInfo10_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) + +#define ICorProfilerInfo10_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ + ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) + +#define ICorProfilerInfo10_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ + ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) + +#define ICorProfilerInfo10_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ + ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) + +#define ICorProfilerInfo10_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ + ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) + +#define ICorProfilerInfo10_EnumModules(This,ppEnum) \ + ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) + +#define ICorProfilerInfo10_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ + ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) + +#define ICorProfilerInfo10_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ + ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) + +#define ICorProfilerInfo10_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ + ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) + +#define ICorProfilerInfo10_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ + ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) + + +#define ICorProfilerInfo10_EnumThreads(This,ppEnum) \ + ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) + +#define ICorProfilerInfo10_InitializeCurrentThread(This) \ + ( (This)->lpVtbl -> InitializeCurrentThread(This) ) + +#define ICorProfilerInfo10_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo10_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ + ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) + +#define ICorProfilerInfo10_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) + +#define ICorProfilerInfo10_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) + +#define ICorProfilerInfo10_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ + ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) + +#define ICorProfilerInfo10_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) + +#define ICorProfilerInfo10_EnumJITedFunctions2(This,ppEnum) \ + ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) + +#define ICorProfilerInfo10_GetObjectSize2(This,objectId,pcSize) \ + ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) + + +#define ICorProfilerInfo10_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ + ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) + +#define ICorProfilerInfo10_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ + ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) + + +#define ICorProfilerInfo10_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ + ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) + + +#define ICorProfilerInfo10_ApplyMetaData(This,moduleId) \ + ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) + +#define ICorProfilerInfo10_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ + ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) + +#define ICorProfilerInfo10_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ + ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) + + +#define ICorProfilerInfo10_IsFunctionDynamic(This,functionId,isDynamic) \ + ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) + +#define ICorProfilerInfo10_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ + ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) + +#define ICorProfilerInfo10_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ + ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) + + +#define ICorProfilerInfo10_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ + ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) + +#define ICorProfilerInfo10_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ + ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) + +#define ICorProfilerInfo10_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ + ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) + + +#define ICorProfilerInfo10_EnumerateObjectReferences(This,objectId,callback,clientData) \ + ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) + +#define ICorProfilerInfo10_IsFrozenObject(This,objectId,pbFrozen) \ + ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) + +#define ICorProfilerInfo10_GetLOHObjectSizeThreshold(This,pThreshold) \ + ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) + +#define ICorProfilerInfo10_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ + ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) + +#define ICorProfilerInfo10_SuspendRuntime(This) \ + ( (This)->lpVtbl -> SuspendRuntime(This) ) + +#define ICorProfilerInfo10_ResumeRuntime(This) \ + ( (This)->lpVtbl -> ResumeRuntime(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerInfo10_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerMethodEnum_INTERFACE_DEFINED__ +#define __ICorProfilerMethodEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerMethodEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerMethodEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FCCEE788-0088-454B-A811-C99F298D1942") + ICorProfilerMethodEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_METHOD elements[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerMethodEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerMethodEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerMethodEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerMethodEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerMethodEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerMethodEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerMethodEnum * This, + /* [out] */ ICorProfilerMethodEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerMethodEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerMethodEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ COR_PRF_METHOD elements[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerMethodEnumVtbl; + + interface ICorProfilerMethodEnum + { + CONST_VTBL struct ICorProfilerMethodEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerMethodEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerMethodEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerMethodEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerMethodEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerMethodEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerMethodEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerMethodEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerMethodEnum_Next(This,celt,elements,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,elements,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerMethodEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerThreadEnum_INTERFACE_DEFINED__ +#define __ICorProfilerThreadEnum_INTERFACE_DEFINED__ + +/* interface ICorProfilerThreadEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerThreadEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("571194f7-25ed-419f-aa8b-7016b3159701") + ICorProfilerThreadEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ThreadID ids[ ], + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerThreadEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerThreadEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerThreadEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorProfilerThreadEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorProfilerThreadEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorProfilerThreadEnum * This, + /* [out] */ ICorProfilerThreadEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorProfilerThreadEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorProfilerThreadEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ThreadID ids[ ], + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorProfilerThreadEnumVtbl; + + interface ICorProfilerThreadEnum + { + CONST_VTBL struct ICorProfilerThreadEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerThreadEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerThreadEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerThreadEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerThreadEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorProfilerThreadEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorProfilerThreadEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorProfilerThreadEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#define ICorProfilerThreadEnum_Next(This,celt,ids,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerThreadEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ +#define __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ + +/* interface ICorProfilerAssemblyReferenceProvider */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorProfilerAssemblyReferenceProvider; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("66A78C24-2EEF-4F65-B45F-DD1D8038BF3C") + ICorProfilerAssemblyReferenceProvider : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddAssemblyReference( + const COR_PRF_ASSEMBLY_REFERENCE_INFO *pAssemblyRefInfo) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorProfilerAssemblyReferenceProviderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorProfilerAssemblyReferenceProvider * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorProfilerAssemblyReferenceProvider * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorProfilerAssemblyReferenceProvider * This); + + HRESULT ( STDMETHODCALLTYPE *AddAssemblyReference )( + ICorProfilerAssemblyReferenceProvider * This, + const COR_PRF_ASSEMBLY_REFERENCE_INFO *pAssemblyRefInfo); + + END_INTERFACE + } ICorProfilerAssemblyReferenceProviderVtbl; + + interface ICorProfilerAssemblyReferenceProvider + { + CONST_VTBL struct ICorProfilerAssemblyReferenceProviderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorProfilerAssemblyReferenceProvider_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorProfilerAssemblyReferenceProvider_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorProfilerAssemblyReferenceProvider_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorProfilerAssemblyReferenceProvider_AddAssemblyReference(This,pAssemblyRefInfo) \ + ( (This)->lpVtbl -> AddAssemblyReference(This,pAssemblyRefInfo) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/corpub.h b/lib/coreclr/src/pal/prebuilt/inc/corpub.h new file mode 100644 index 0000000000..94c01c660a --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/corpub.h @@ -0,0 +1,821 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __corpub_h__ +#define __corpub_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __CorpubPublish_FWD_DEFINED__ +#define __CorpubPublish_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorpubPublish CorpubPublish; +#else +typedef struct CorpubPublish CorpubPublish; +#endif /* __cplusplus */ + +#endif /* __CorpubPublish_FWD_DEFINED__ */ + + +#ifndef __ICorPublish_FWD_DEFINED__ +#define __ICorPublish_FWD_DEFINED__ +typedef interface ICorPublish ICorPublish; + +#endif /* __ICorPublish_FWD_DEFINED__ */ + + +#ifndef __ICorPublishEnum_FWD_DEFINED__ +#define __ICorPublishEnum_FWD_DEFINED__ +typedef interface ICorPublishEnum ICorPublishEnum; + +#endif /* __ICorPublishEnum_FWD_DEFINED__ */ + + +#ifndef __ICorPublishProcess_FWD_DEFINED__ +#define __ICorPublishProcess_FWD_DEFINED__ +typedef interface ICorPublishProcess ICorPublishProcess; + +#endif /* __ICorPublishProcess_FWD_DEFINED__ */ + + +#ifndef __ICorPublishAppDomain_FWD_DEFINED__ +#define __ICorPublishAppDomain_FWD_DEFINED__ +typedef interface ICorPublishAppDomain ICorPublishAppDomain; + +#endif /* __ICorPublishAppDomain_FWD_DEFINED__ */ + + +#ifndef __ICorPublishProcessEnum_FWD_DEFINED__ +#define __ICorPublishProcessEnum_FWD_DEFINED__ +typedef interface ICorPublishProcessEnum ICorPublishProcessEnum; + +#endif /* __ICorPublishProcessEnum_FWD_DEFINED__ */ + + +#ifndef __ICorPublishAppDomainEnum_FWD_DEFINED__ +#define __ICorPublishAppDomainEnum_FWD_DEFINED__ +typedef interface ICorPublishAppDomainEnum ICorPublishAppDomainEnum; + +#endif /* __ICorPublishAppDomainEnum_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_corpub_0000_0000 */ +/* [local] */ + +#if 0 +#endif +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_corpub_0000_0000_0001 + { + COR_PUB_MANAGEDONLY = 0x1 + } COR_PUB_ENUMPROCESS; + +#pragma warning(push) +#pragma warning(disable:28718) + + + + + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0000_v0_0_s_ifspec; + + +#ifndef __CorpubProcessLib_LIBRARY_DEFINED__ +#define __CorpubProcessLib_LIBRARY_DEFINED__ + +/* library CorpubProcessLib */ +/* [helpstring][version][uuid] */ + + +EXTERN_C const IID LIBID_CorpubProcessLib; + +EXTERN_C const CLSID CLSID_CorpubPublish; + +#ifdef __cplusplus + +class DECLSPEC_UUID("047a9a40-657e-11d3-8d5b-00104b35e7ef") +CorpubPublish; +#endif +#endif /* __CorpubProcessLib_LIBRARY_DEFINED__ */ + +#ifndef __ICorPublish_INTERFACE_DEFINED__ +#define __ICorPublish_INTERFACE_DEFINED__ + +/* interface ICorPublish */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublish; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9613A0E7-5A68-11d3-8F84-00A0C9B4D50C") + ICorPublish : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnumProcesses( + /* [in] */ COR_PUB_ENUMPROCESS Type, + /* [out] */ ICorPublishProcessEnum **ppIEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [in] */ unsigned int pid, + /* [out] */ ICorPublishProcess **ppProcess) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublish * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublish * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublish * This); + + HRESULT ( STDMETHODCALLTYPE *EnumProcesses )( + ICorPublish * This, + /* [in] */ COR_PUB_ENUMPROCESS Type, + /* [out] */ ICorPublishProcessEnum **ppIEnum); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + ICorPublish * This, + /* [in] */ unsigned int pid, + /* [out] */ ICorPublishProcess **ppProcess); + + END_INTERFACE + } ICorPublishVtbl; + + interface ICorPublish + { + CONST_VTBL struct ICorPublishVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublish_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublish_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublish_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublish_EnumProcesses(This,Type,ppIEnum) \ + ( (This)->lpVtbl -> EnumProcesses(This,Type,ppIEnum) ) + +#define ICorPublish_GetProcess(This,pid,ppProcess) \ + ( (This)->lpVtbl -> GetProcess(This,pid,ppProcess) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublish_INTERFACE_DEFINED__ */ + + +#ifndef __ICorPublishEnum_INTERFACE_DEFINED__ +#define __ICorPublishEnum_INTERFACE_DEFINED__ + +/* interface ICorPublishEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublishEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C0B22967-5A69-11d3-8F84-00A0C9B4D50C") + ICorPublishEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ ICorPublishEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ ULONG *pcelt) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublishEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublishEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublishEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorPublishEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorPublishEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorPublishEnum * This, + /* [out] */ ICorPublishEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorPublishEnum * This, + /* [out] */ ULONG *pcelt); + + END_INTERFACE + } ICorPublishEnumVtbl; + + interface ICorPublishEnum + { + CONST_VTBL struct ICorPublishEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublishEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublishEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublishEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublishEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorPublishEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorPublishEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorPublishEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublishEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corpub_0000_0003 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0003_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0003_v0_0_s_ifspec; + +#ifndef __ICorPublishProcess_INTERFACE_DEFINED__ +#define __ICorPublishProcess_INTERFACE_DEFINED__ + +/* interface ICorPublishProcess */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublishProcess; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("18D87AF1-5A6A-11d3-8F84-00A0C9B4D50C") + ICorPublishProcess : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsManaged( + /* [out] */ BOOL *pbManaged) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAppDomains( + /* [out] */ ICorPublishAppDomainEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProcessID( + /* [out] */ unsigned int *pid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDisplayName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR *szName) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishProcessVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublishProcess * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublishProcess * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublishProcess * This); + + HRESULT ( STDMETHODCALLTYPE *IsManaged )( + ICorPublishProcess * This, + /* [out] */ BOOL *pbManaged); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomains )( + ICorPublishProcess * This, + /* [out] */ ICorPublishAppDomainEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetProcessID )( + ICorPublishProcess * This, + /* [out] */ unsigned int *pid); + + HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( + ICorPublishProcess * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR *szName); + + END_INTERFACE + } ICorPublishProcessVtbl; + + interface ICorPublishProcess + { + CONST_VTBL struct ICorPublishProcessVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublishProcess_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublishProcess_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublishProcess_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublishProcess_IsManaged(This,pbManaged) \ + ( (This)->lpVtbl -> IsManaged(This,pbManaged) ) + +#define ICorPublishProcess_EnumAppDomains(This,ppEnum) \ + ( (This)->lpVtbl -> EnumAppDomains(This,ppEnum) ) + +#define ICorPublishProcess_GetProcessID(This,pid) \ + ( (This)->lpVtbl -> GetProcessID(This,pid) ) + +#define ICorPublishProcess_GetDisplayName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetDisplayName(This,cchName,pcchName,szName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublishProcess_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corpub_0000_0004 */ +/* [local] */ + +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0004_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0004_v0_0_s_ifspec; + +#ifndef __ICorPublishAppDomain_INTERFACE_DEFINED__ +#define __ICorPublishAppDomain_INTERFACE_DEFINED__ + +/* interface ICorPublishAppDomain */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublishAppDomain; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D6315C8F-5A6A-11d3-8F84-00A0C9B4D50C") + ICorPublishAppDomain : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetID( + /* [out] */ ULONG32 *puId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR *szName) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishAppDomainVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublishAppDomain * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublishAppDomain * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublishAppDomain * This); + + HRESULT ( STDMETHODCALLTYPE *GetID )( + ICorPublishAppDomain * This, + /* [out] */ ULONG32 *puId); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + ICorPublishAppDomain * This, + /* [in] */ ULONG32 cchName, + /* [out] */ ULONG32 *pcchName, + /* [length_is][size_is][out] */ WCHAR *szName); + + END_INTERFACE + } ICorPublishAppDomainVtbl; + + interface ICorPublishAppDomain + { + CONST_VTBL struct ICorPublishAppDomainVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublishAppDomain_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublishAppDomain_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublishAppDomain_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublishAppDomain_GetID(This,puId) \ + ( (This)->lpVtbl -> GetID(This,puId) ) + +#define ICorPublishAppDomain_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublishAppDomain_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corpub_0000_0005 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0005_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0005_v0_0_s_ifspec; + +#ifndef __ICorPublishProcessEnum_INTERFACE_DEFINED__ +#define __ICorPublishProcessEnum_INTERFACE_DEFINED__ + +/* interface ICorPublishProcessEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublishProcessEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A37FBD41-5A69-11d3-8F84-00A0C9B4D50C") + ICorPublishProcessEnum : public ICorPublishEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorPublishProcess **objects, + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishProcessEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublishProcessEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublishProcessEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublishProcessEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorPublishProcessEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorPublishProcessEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorPublishProcessEnum * This, + /* [out] */ ICorPublishEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorPublishProcessEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorPublishProcessEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorPublishProcess **objects, + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorPublishProcessEnumVtbl; + + interface ICorPublishProcessEnum + { + CONST_VTBL struct ICorPublishProcessEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublishProcessEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublishProcessEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublishProcessEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublishProcessEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorPublishProcessEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorPublishProcessEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorPublishProcessEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorPublishProcessEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublishProcessEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ +#define __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ + +/* interface ICorPublishAppDomainEnum */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorPublishAppDomainEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9F0C98F5-5A6A-11d3-8F84-00A0C9B4D50C") + ICorPublishAppDomainEnum : public ICorPublishEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorPublishAppDomain **objects, + /* [out] */ ULONG *pceltFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorPublishAppDomainEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorPublishAppDomainEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorPublishAppDomainEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorPublishAppDomainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ICorPublishAppDomainEnum * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ICorPublishAppDomainEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + ICorPublishAppDomainEnum * This, + /* [out] */ ICorPublishEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ICorPublishAppDomainEnum * This, + /* [out] */ ULONG *pcelt); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ICorPublishAppDomainEnum * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ICorPublishAppDomain **objects, + /* [out] */ ULONG *pceltFetched); + + END_INTERFACE + } ICorPublishAppDomainEnumVtbl; + + interface ICorPublishAppDomainEnum + { + CONST_VTBL struct ICorPublishAppDomainEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorPublishAppDomainEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorPublishAppDomainEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorPublishAppDomainEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorPublishAppDomainEnum_Skip(This,celt) \ + ( (This)->lpVtbl -> Skip(This,celt) ) + +#define ICorPublishAppDomainEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ICorPublishAppDomainEnum_Clone(This,ppEnum) \ + ( (This)->lpVtbl -> Clone(This,ppEnum) ) + +#define ICorPublishAppDomainEnum_GetCount(This,pcelt) \ + ( (This)->lpVtbl -> GetCount(This,pcelt) ) + + +#define ICorPublishAppDomainEnum_Next(This,celt,objects,pceltFetched) \ + ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/corsym.h b/lib/coreclr/src/pal/prebuilt/inc/corsym.h new file mode 100644 index 0000000000..dd80eae55d --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/corsym.h @@ -0,0 +1,5706 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0601 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __corsym_h__ +#define __corsym_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __CorSymWriter_deprecated_FWD_DEFINED__ +#define __CorSymWriter_deprecated_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymWriter_deprecated CorSymWriter_deprecated; +#else +typedef struct CorSymWriter_deprecated CorSymWriter_deprecated; +#endif /* __cplusplus */ + +#endif /* __CorSymWriter_deprecated_FWD_DEFINED__ */ + + +#ifndef __CorSymReader_deprecated_FWD_DEFINED__ +#define __CorSymReader_deprecated_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymReader_deprecated CorSymReader_deprecated; +#else +typedef struct CorSymReader_deprecated CorSymReader_deprecated; +#endif /* __cplusplus */ + +#endif /* __CorSymReader_deprecated_FWD_DEFINED__ */ + + +#ifndef __CorSymBinder_deprecated_FWD_DEFINED__ +#define __CorSymBinder_deprecated_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymBinder_deprecated CorSymBinder_deprecated; +#else +typedef struct CorSymBinder_deprecated CorSymBinder_deprecated; +#endif /* __cplusplus */ + +#endif /* __CorSymBinder_deprecated_FWD_DEFINED__ */ + + +#ifndef __CorSymWriter_SxS_FWD_DEFINED__ +#define __CorSymWriter_SxS_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymWriter_SxS CorSymWriter_SxS; +#else +typedef struct CorSymWriter_SxS CorSymWriter_SxS; +#endif /* __cplusplus */ + +#endif /* __CorSymWriter_SxS_FWD_DEFINED__ */ + + +#ifndef __CorSymReader_SxS_FWD_DEFINED__ +#define __CorSymReader_SxS_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymReader_SxS CorSymReader_SxS; +#else +typedef struct CorSymReader_SxS CorSymReader_SxS; +#endif /* __cplusplus */ + +#endif /* __CorSymReader_SxS_FWD_DEFINED__ */ + + +#ifndef __CorSymBinder_SxS_FWD_DEFINED__ +#define __CorSymBinder_SxS_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class CorSymBinder_SxS CorSymBinder_SxS; +#else +typedef struct CorSymBinder_SxS CorSymBinder_SxS; +#endif /* __cplusplus */ + +#endif /* __CorSymBinder_SxS_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedBinder_FWD_DEFINED__ +#define __ISymUnmanagedBinder_FWD_DEFINED__ +typedef interface ISymUnmanagedBinder ISymUnmanagedBinder; + +#endif /* __ISymUnmanagedBinder_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedBinder2_FWD_DEFINED__ +#define __ISymUnmanagedBinder2_FWD_DEFINED__ +typedef interface ISymUnmanagedBinder2 ISymUnmanagedBinder2; + +#endif /* __ISymUnmanagedBinder2_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedBinder3_FWD_DEFINED__ +#define __ISymUnmanagedBinder3_FWD_DEFINED__ +typedef interface ISymUnmanagedBinder3 ISymUnmanagedBinder3; + +#endif /* __ISymUnmanagedBinder3_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedDispose_FWD_DEFINED__ +#define __ISymUnmanagedDispose_FWD_DEFINED__ +typedef interface ISymUnmanagedDispose ISymUnmanagedDispose; + +#endif /* __ISymUnmanagedDispose_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedDocument_FWD_DEFINED__ +#define __ISymUnmanagedDocument_FWD_DEFINED__ +typedef interface ISymUnmanagedDocument ISymUnmanagedDocument; + +#endif /* __ISymUnmanagedDocument_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedDocumentWriter_FWD_DEFINED__ +#define __ISymUnmanagedDocumentWriter_FWD_DEFINED__ +typedef interface ISymUnmanagedDocumentWriter ISymUnmanagedDocumentWriter; + +#endif /* __ISymUnmanagedDocumentWriter_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedMethod_FWD_DEFINED__ +#define __ISymUnmanagedMethod_FWD_DEFINED__ +typedef interface ISymUnmanagedMethod ISymUnmanagedMethod; + +#endif /* __ISymUnmanagedMethod_FWD_DEFINED__ */ + + +#ifndef __ISymENCUnmanagedMethod_FWD_DEFINED__ +#define __ISymENCUnmanagedMethod_FWD_DEFINED__ +typedef interface ISymENCUnmanagedMethod ISymENCUnmanagedMethod; + +#endif /* __ISymENCUnmanagedMethod_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedNamespace_FWD_DEFINED__ +#define __ISymUnmanagedNamespace_FWD_DEFINED__ +typedef interface ISymUnmanagedNamespace ISymUnmanagedNamespace; + +#endif /* __ISymUnmanagedNamespace_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedReader_FWD_DEFINED__ +#define __ISymUnmanagedReader_FWD_DEFINED__ +typedef interface ISymUnmanagedReader ISymUnmanagedReader; + +#endif /* __ISymUnmanagedReader_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedSourceServerModule_FWD_DEFINED__ +#define __ISymUnmanagedSourceServerModule_FWD_DEFINED__ +typedef interface ISymUnmanagedSourceServerModule ISymUnmanagedSourceServerModule; + +#endif /* __ISymUnmanagedSourceServerModule_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedENCUpdate_FWD_DEFINED__ +#define __ISymUnmanagedENCUpdate_FWD_DEFINED__ +typedef interface ISymUnmanagedENCUpdate ISymUnmanagedENCUpdate; + +#endif /* __ISymUnmanagedENCUpdate_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ +#define __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ +typedef interface ISymUnmanagedReaderSymbolSearchInfo ISymUnmanagedReaderSymbolSearchInfo; + +#endif /* __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedScope_FWD_DEFINED__ +#define __ISymUnmanagedScope_FWD_DEFINED__ +typedef interface ISymUnmanagedScope ISymUnmanagedScope; + +#endif /* __ISymUnmanagedScope_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedConstant_FWD_DEFINED__ +#define __ISymUnmanagedConstant_FWD_DEFINED__ +typedef interface ISymUnmanagedConstant ISymUnmanagedConstant; + +#endif /* __ISymUnmanagedConstant_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedScope2_FWD_DEFINED__ +#define __ISymUnmanagedScope2_FWD_DEFINED__ +typedef interface ISymUnmanagedScope2 ISymUnmanagedScope2; + +#endif /* __ISymUnmanagedScope2_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedVariable_FWD_DEFINED__ +#define __ISymUnmanagedVariable_FWD_DEFINED__ +typedef interface ISymUnmanagedVariable ISymUnmanagedVariable; + +#endif /* __ISymUnmanagedVariable_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ +#define __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ +typedef interface ISymUnmanagedSymbolSearchInfo ISymUnmanagedSymbolSearchInfo; + +#endif /* __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter_FWD_DEFINED__ +#define __ISymUnmanagedWriter_FWD_DEFINED__ +typedef interface ISymUnmanagedWriter ISymUnmanagedWriter; + +#endif /* __ISymUnmanagedWriter_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter2_FWD_DEFINED__ +#define __ISymUnmanagedWriter2_FWD_DEFINED__ +typedef interface ISymUnmanagedWriter2 ISymUnmanagedWriter2; + +#endif /* __ISymUnmanagedWriter2_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter3_FWD_DEFINED__ +#define __ISymUnmanagedWriter3_FWD_DEFINED__ +typedef interface ISymUnmanagedWriter3 ISymUnmanagedWriter3; + +#endif /* __ISymUnmanagedWriter3_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter4_FWD_DEFINED__ +#define __ISymUnmanagedWriter4_FWD_DEFINED__ +typedef interface ISymUnmanagedWriter4 ISymUnmanagedWriter4; + +#endif /* __ISymUnmanagedWriter4_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter5_FWD_DEFINED__ +#define __ISymUnmanagedWriter5_FWD_DEFINED__ +typedef interface ISymUnmanagedWriter5 ISymUnmanagedWriter5; + +#endif /* __ISymUnmanagedWriter5_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedReader2_FWD_DEFINED__ +#define __ISymUnmanagedReader2_FWD_DEFINED__ +typedef interface ISymUnmanagedReader2 ISymUnmanagedReader2; + +#endif /* __ISymUnmanagedReader2_FWD_DEFINED__ */ + + +#ifndef __ISymNGenWriter_FWD_DEFINED__ +#define __ISymNGenWriter_FWD_DEFINED__ +typedef interface ISymNGenWriter ISymNGenWriter; + +#endif /* __ISymNGenWriter_FWD_DEFINED__ */ + + +#ifndef __ISymNGenWriter2_FWD_DEFINED__ +#define __ISymNGenWriter2_FWD_DEFINED__ +typedef interface ISymNGenWriter2 ISymNGenWriter2; + +#endif /* __ISymNGenWriter2_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ +#define __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ +typedef interface ISymUnmanagedAsyncMethodPropertiesWriter ISymUnmanagedAsyncMethodPropertiesWriter; + +#endif /* __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ */ + + +#ifndef __ISymUnmanagedAsyncMethod_FWD_DEFINED__ +#define __ISymUnmanagedAsyncMethod_FWD_DEFINED__ +typedef interface ISymUnmanagedAsyncMethod ISymUnmanagedAsyncMethod; + +#endif /* __ISymUnmanagedAsyncMethod_FWD_DEFINED__ */ + + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_corsym_0000_0000 */ +/* [local] */ + +#if 0 +typedef typedef unsigned int UINT32; +; + +typedef mdToken mdTypeDef; + +typedef mdToken mdMethodDef; + +typedef typedef ULONG_PTR SIZE_T; +; + +#endif +#ifndef __CORHDR_H__ +typedef mdToken mdSignature; + +#endif +#pragma once +#pragma once +#pragma region Input Buffer SAL 1 compatibility macros +#pragma endregion Input Buffer SAL 1 compatibility macros +#pragma once +#pragma once +EXTERN_GUID(CorSym_LanguageType_C, 0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); +EXTERN_GUID(CorSym_LanguageType_CPlusPlus, 0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); +EXTERN_GUID(CorSym_LanguageType_CSharp, 0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); +EXTERN_GUID(CorSym_LanguageType_Basic, 0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); +EXTERN_GUID(CorSym_LanguageType_Java, 0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); +EXTERN_GUID(CorSym_LanguageType_Cobol, 0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); +EXTERN_GUID(CorSym_LanguageType_Pascal, 0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); +EXTERN_GUID(CorSym_LanguageType_ILAssembly, 0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); +EXTERN_GUID(CorSym_LanguageType_JScript, 0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x00, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); +EXTERN_GUID(CorSym_LanguageType_SMC, 0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd); +EXTERN_GUID(CorSym_LanguageType_MCPlusPlus, 0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); +EXTERN_GUID(CorSym_LanguageVendor_Microsoft, 0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); +EXTERN_GUID(CorSym_DocumentType_Text, 0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd); +EXTERN_GUID(CorSym_DocumentType_MC, 0xeb40cb65, 0x3c1f, 0x4352, 0x9d, 0x7b, 0xba, 0xf, 0xc4, 0x7a, 0x9d, 0x77); +EXTERN_GUID(CorSym_SourceHash_MD5, 0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99); +EXTERN_GUID(CorSym_SourceHash_SHA1, 0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60); + + + + + + + + + + + + +typedef +enum CorSymAddrKind + { + ADDR_IL_OFFSET = 1, + ADDR_NATIVE_RVA = 2, + ADDR_NATIVE_REGISTER = 3, + ADDR_NATIVE_REGREL = 4, + ADDR_NATIVE_OFFSET = 5, + ADDR_NATIVE_REGREG = 6, + ADDR_NATIVE_REGSTK = 7, + ADDR_NATIVE_STKREG = 8, + ADDR_BITFIELD = 9, + ADDR_NATIVE_ISECTOFFSET = 10 + } CorSymAddrKind; + +typedef +enum CorSymVarFlag + { + VAR_IS_COMP_GEN = 1 + } CorSymVarFlag; + + + +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0000_v0_0_s_ifspec; + + +#ifndef __CorSymLib_LIBRARY_DEFINED__ +#define __CorSymLib_LIBRARY_DEFINED__ + +/* library CorSymLib */ +/* [helpstring][version][uuid] */ + + +EXTERN_C const IID LIBID_CorSymLib; + +EXTERN_C const CLSID CLSID_CorSymWriter_deprecated; + +#ifdef __cplusplus + +class DECLSPEC_UUID("108296C1-281E-11d3-BD22-0000F80849BD") +CorSymWriter_deprecated; +#endif + +EXTERN_C const CLSID CLSID_CorSymReader_deprecated; + +#ifdef __cplusplus + +class DECLSPEC_UUID("108296C2-281E-11d3-BD22-0000F80849BD") +CorSymReader_deprecated; +#endif + +EXTERN_C const CLSID CLSID_CorSymBinder_deprecated; + +#ifdef __cplusplus + +class DECLSPEC_UUID("AA544D41-28CB-11d3-BD22-0000F80849BD") +CorSymBinder_deprecated; +#endif + +EXTERN_C const CLSID CLSID_CorSymWriter_SxS; + +#ifdef __cplusplus + +class DECLSPEC_UUID("0AE2DEB0-F901-478b-BB9F-881EE8066788") +CorSymWriter_SxS; +#endif + +EXTERN_C const CLSID CLSID_CorSymReader_SxS; + +#ifdef __cplusplus + +class DECLSPEC_UUID("0A3976C5-4529-4ef8-B0B0-42EED37082CD") +CorSymReader_SxS; +#endif + +EXTERN_C const CLSID CLSID_CorSymBinder_SxS; + +#ifdef __cplusplus + +class DECLSPEC_UUID("0A29FF9E-7F9C-4437-8B11-F424491E3931") +CorSymBinder_SxS; +#endif +#endif /* __CorSymLib_LIBRARY_DEFINED__ */ + +#ifndef __ISymUnmanagedBinder_INTERFACE_DEFINED__ +#define __ISymUnmanagedBinder_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedBinder */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedBinder; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AA544D42-28CB-11d3-BD22-0000F80849BD") + ISymUnmanagedBinder : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetReaderForFile( + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetReaderFromStream( + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in_opt IStream *pstream, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedBinderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedBinder * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedBinder * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedBinder * This); + + HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( + __RPC__in ISymUnmanagedBinder * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( + __RPC__in ISymUnmanagedBinder * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in_opt IStream *pstream, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + END_INTERFACE + } ISymUnmanagedBinderVtbl; + + interface ISymUnmanagedBinder + { + CONST_VTBL struct ISymUnmanagedBinderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedBinder_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedBinder_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedBinder_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedBinder_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ + ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) + +#define ISymUnmanagedBinder_GetReaderFromStream(This,importer,pstream,pRetVal) \ + ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedBinder_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corsym_0000_0002 */ +/* [local] */ + +typedef +enum CorSymSearchPolicyAttributes + { + AllowRegistryAccess = 0x1, + AllowSymbolServerAccess = 0x2, + AllowOriginalPathAccess = 0x4, + AllowReferencePathAccess = 0x8 + } CorSymSearchPolicyAttributes; + + + +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0002_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0002_v0_0_s_ifspec; + +#ifndef __ISymUnmanagedBinder2_INTERFACE_DEFINED__ +#define __ISymUnmanagedBinder2_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedBinder2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedBinder2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434") + ISymUnmanagedBinder2 : public ISymUnmanagedBinder + { + public: + virtual HRESULT STDMETHODCALLTYPE GetReaderForFile2( + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ ULONG32 searchPolicy, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedBinder2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedBinder2 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedBinder2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedBinder2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( + __RPC__in ISymUnmanagedBinder2 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( + __RPC__in ISymUnmanagedBinder2 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in_opt IStream *pstream, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderForFile2 )( + __RPC__in ISymUnmanagedBinder2 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ ULONG32 searchPolicy, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + END_INTERFACE + } ISymUnmanagedBinder2Vtbl; + + interface ISymUnmanagedBinder2 + { + CONST_VTBL struct ISymUnmanagedBinder2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedBinder2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedBinder2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedBinder2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedBinder2_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ + ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) + +#define ISymUnmanagedBinder2_GetReaderFromStream(This,importer,pstream,pRetVal) \ + ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) + + +#define ISymUnmanagedBinder2_GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) \ + ( (This)->lpVtbl -> GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedBinder2_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedBinder3_INTERFACE_DEFINED__ +#define __ISymUnmanagedBinder3_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedBinder3 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedBinder3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("28AD3D43-B601-4d26-8A1B-25F9165AF9D7") + ISymUnmanagedBinder3 : public ISymUnmanagedBinder2 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetReaderFromCallback( + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ ULONG32 searchPolicy, + /* [in] */ __RPC__in_opt IUnknown *callback, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedBinder3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedBinder3 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedBinder3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedBinder3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( + __RPC__in ISymUnmanagedBinder3 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( + __RPC__in ISymUnmanagedBinder3 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in_opt IStream *pstream, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderForFile2 )( + __RPC__in ISymUnmanagedBinder3 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ ULONG32 searchPolicy, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetReaderFromCallback )( + __RPC__in ISymUnmanagedBinder3 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *fileName, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ ULONG32 searchPolicy, + /* [in] */ __RPC__in_opt IUnknown *callback, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); + + END_INTERFACE + } ISymUnmanagedBinder3Vtbl; + + interface ISymUnmanagedBinder3 + { + CONST_VTBL struct ISymUnmanagedBinder3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedBinder3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedBinder3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedBinder3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedBinder3_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ + ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) + +#define ISymUnmanagedBinder3_GetReaderFromStream(This,importer,pstream,pRetVal) \ + ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) + + +#define ISymUnmanagedBinder3_GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) \ + ( (This)->lpVtbl -> GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) ) + + +#define ISymUnmanagedBinder3_GetReaderFromCallback(This,importer,fileName,searchPath,searchPolicy,callback,pRetVal) \ + ( (This)->lpVtbl -> GetReaderFromCallback(This,importer,fileName,searchPath,searchPolicy,callback,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedBinder3_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_corsym_0000_0004 */ +/* [local] */ + +static const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead); + + +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0004_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0004_v0_0_s_ifspec; + +#ifndef __ISymUnmanagedDispose_INTERFACE_DEFINED__ +#define __ISymUnmanagedDispose_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedDispose */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedDispose; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("969708D2-05E5-4861-A3B0-96E473CDF63F") + ISymUnmanagedDispose : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Destroy( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedDisposeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedDispose * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedDispose * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedDispose * This); + + HRESULT ( STDMETHODCALLTYPE *Destroy )( + __RPC__in ISymUnmanagedDispose * This); + + END_INTERFACE + } ISymUnmanagedDisposeVtbl; + + interface ISymUnmanagedDispose + { + CONST_VTBL struct ISymUnmanagedDisposeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedDispose_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedDispose_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedDispose_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedDispose_Destroy(This) \ + ( (This)->lpVtbl -> Destroy(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedDispose_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedDocument_INTERFACE_DEFINED__ +#define __ISymUnmanagedDocument_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedDocument */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedDocument; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08") + ISymUnmanagedDocument : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetURL( + /* [in] */ ULONG32 cchUrl, + /* [out] */ __RPC__out ULONG32 *pcchUrl, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchUrl, *pcchUrl) WCHAR szUrl[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDocumentType( + /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLanguage( + /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLanguageVendor( + /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCheckSumAlgorithmId( + /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCheckSum( + /* [in] */ ULONG32 cData, + /* [out] */ __RPC__out ULONG32 *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE FindClosestLine( + /* [in] */ ULONG32 line, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE HasEmbeddedSource( + /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceLength( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceRange( + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn, + /* [in] */ ULONG32 cSourceBytes, + /* [out] */ __RPC__out ULONG32 *pcSourceBytes, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSourceBytes, *pcSourceBytes) BYTE source[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedDocumentVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedDocument * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedDocument * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedDocument * This); + + HRESULT ( STDMETHODCALLTYPE *GetURL )( + __RPC__in ISymUnmanagedDocument * This, + /* [in] */ ULONG32 cchUrl, + /* [out] */ __RPC__out ULONG32 *pcchUrl, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchUrl, *pcchUrl) WCHAR szUrl[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetDocumentType )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out GUID *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLanguage )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out GUID *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLanguageVendor )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out GUID *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetCheckSumAlgorithmId )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out GUID *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetCheckSum )( + __RPC__in ISymUnmanagedDocument * This, + /* [in] */ ULONG32 cData, + /* [out] */ __RPC__out ULONG32 *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *FindClosestLine )( + __RPC__in ISymUnmanagedDocument * This, + /* [in] */ ULONG32 line, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *HasEmbeddedSource )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSourceLength )( + __RPC__in ISymUnmanagedDocument * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSourceRange )( + __RPC__in ISymUnmanagedDocument * This, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn, + /* [in] */ ULONG32 cSourceBytes, + /* [out] */ __RPC__out ULONG32 *pcSourceBytes, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSourceBytes, *pcSourceBytes) BYTE source[ ]); + + END_INTERFACE + } ISymUnmanagedDocumentVtbl; + + interface ISymUnmanagedDocument + { + CONST_VTBL struct ISymUnmanagedDocumentVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedDocument_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedDocument_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedDocument_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedDocument_GetURL(This,cchUrl,pcchUrl,szUrl) \ + ( (This)->lpVtbl -> GetURL(This,cchUrl,pcchUrl,szUrl) ) + +#define ISymUnmanagedDocument_GetDocumentType(This,pRetVal) \ + ( (This)->lpVtbl -> GetDocumentType(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetLanguage(This,pRetVal) \ + ( (This)->lpVtbl -> GetLanguage(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetLanguageVendor(This,pRetVal) \ + ( (This)->lpVtbl -> GetLanguageVendor(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetCheckSumAlgorithmId(This,pRetVal) \ + ( (This)->lpVtbl -> GetCheckSumAlgorithmId(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetCheckSum(This,cData,pcData,data) \ + ( (This)->lpVtbl -> GetCheckSum(This,cData,pcData,data) ) + +#define ISymUnmanagedDocument_FindClosestLine(This,line,pRetVal) \ + ( (This)->lpVtbl -> FindClosestLine(This,line,pRetVal) ) + +#define ISymUnmanagedDocument_HasEmbeddedSource(This,pRetVal) \ + ( (This)->lpVtbl -> HasEmbeddedSource(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetSourceLength(This,pRetVal) \ + ( (This)->lpVtbl -> GetSourceLength(This,pRetVal) ) + +#define ISymUnmanagedDocument_GetSourceRange(This,startLine,startColumn,endLine,endColumn,cSourceBytes,pcSourceBytes,source) \ + ( (This)->lpVtbl -> GetSourceRange(This,startLine,startColumn,endLine,endColumn,cSourceBytes,pcSourceBytes,source) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedDocument_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ +#define __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedDocumentWriter */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedDocumentWriter; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006") + ISymUnmanagedDocumentWriter : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetSource( + /* [in] */ ULONG32 sourceSize, + /* [size_is][in] */ __RPC__in_ecount_full(sourceSize) BYTE source[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCheckSum( + /* [in] */ GUID algorithmId, + /* [in] */ ULONG32 checkSumSize, + /* [size_is][in] */ __RPC__in_ecount_full(checkSumSize) BYTE checkSum[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedDocumentWriterVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedDocumentWriter * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedDocumentWriter * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedDocumentWriter * This); + + HRESULT ( STDMETHODCALLTYPE *SetSource )( + __RPC__in ISymUnmanagedDocumentWriter * This, + /* [in] */ ULONG32 sourceSize, + /* [size_is][in] */ __RPC__in_ecount_full(sourceSize) BYTE source[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetCheckSum )( + __RPC__in ISymUnmanagedDocumentWriter * This, + /* [in] */ GUID algorithmId, + /* [in] */ ULONG32 checkSumSize, + /* [size_is][in] */ __RPC__in_ecount_full(checkSumSize) BYTE checkSum[ ]); + + END_INTERFACE + } ISymUnmanagedDocumentWriterVtbl; + + interface ISymUnmanagedDocumentWriter + { + CONST_VTBL struct ISymUnmanagedDocumentWriterVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedDocumentWriter_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedDocumentWriter_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedDocumentWriter_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedDocumentWriter_SetSource(This,sourceSize,source) \ + ( (This)->lpVtbl -> SetSource(This,sourceSize,source) ) + +#define ISymUnmanagedDocumentWriter_SetCheckSum(This,algorithmId,checkSumSize,checkSum) \ + ( (This)->lpVtbl -> SetCheckSum(This,algorithmId,checkSumSize,checkSum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedMethod_INTERFACE_DEFINED__ +#define __ISymUnmanagedMethod_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedMethod */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedMethod; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B62B923C-B500-3158-A543-24F307A8B7E1") + ISymUnmanagedMethod : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetToken( + /* [retval][out] */ __RPC__out mdMethodDef *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSequencePointCount( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRootScope( + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetScopeFromOffset( + /* [in] */ ULONG32 offset, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOffset( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRanges( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 cRanges, + /* [out] */ __RPC__out ULONG32 *pcRanges, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cRanges, *pcRanges) ULONG32 ranges[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetParameters( + /* [in] */ ULONG32 cParams, + /* [out] */ __RPC__out ULONG32 *pcParams, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cParams, *pcParams) ISymUnmanagedVariable *params[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNamespace( + /* [out] */ __RPC__deref_out_opt ISymUnmanagedNamespace **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceStartEnd( + /* [in] */ __RPC__in_ecount_full(2) ISymUnmanagedDocument *docs[ 2 ], + /* [in] */ __RPC__in_ecount_full(2) ULONG32 lines[ 2 ], + /* [in] */ __RPC__in_ecount_full(2) ULONG32 columns[ 2 ], + /* [out] */ __RPC__out BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSequencePoints( + /* [in] */ ULONG32 cPoints, + /* [out] */ __RPC__out ULONG32 *pcPoints, + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ISymUnmanagedDocument *documents[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endColumns[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedMethodVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedMethod * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedMethod * This); + + HRESULT ( STDMETHODCALLTYPE *GetToken )( + __RPC__in ISymUnmanagedMethod * This, + /* [retval][out] */ __RPC__out mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetSequencePointCount )( + __RPC__in ISymUnmanagedMethod * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetRootScope )( + __RPC__in ISymUnmanagedMethod * This, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetScopeFromOffset )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ ULONG32 offset, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetOffset )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetRanges )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 cRanges, + /* [out] */ __RPC__out ULONG32 *pcRanges, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cRanges, *pcRanges) ULONG32 ranges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetParameters )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ ULONG32 cParams, + /* [out] */ __RPC__out ULONG32 *pcParams, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cParams, *pcParams) ISymUnmanagedVariable *params[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespace )( + __RPC__in ISymUnmanagedMethod * This, + /* [out] */ __RPC__deref_out_opt ISymUnmanagedNamespace **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSourceStartEnd )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ __RPC__in_ecount_full(2) ISymUnmanagedDocument *docs[ 2 ], + /* [in] */ __RPC__in_ecount_full(2) ULONG32 lines[ 2 ], + /* [in] */ __RPC__in_ecount_full(2) ULONG32 columns[ 2 ], + /* [out] */ __RPC__out BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSequencePoints )( + __RPC__in ISymUnmanagedMethod * This, + /* [in] */ ULONG32 cPoints, + /* [out] */ __RPC__out ULONG32 *pcPoints, + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ISymUnmanagedDocument *documents[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endColumns[ ]); + + END_INTERFACE + } ISymUnmanagedMethodVtbl; + + interface ISymUnmanagedMethod + { + CONST_VTBL struct ISymUnmanagedMethodVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedMethod_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedMethod_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedMethod_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedMethod_GetToken(This,pToken) \ + ( (This)->lpVtbl -> GetToken(This,pToken) ) + +#define ISymUnmanagedMethod_GetSequencePointCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetSequencePointCount(This,pRetVal) ) + +#define ISymUnmanagedMethod_GetRootScope(This,pRetVal) \ + ( (This)->lpVtbl -> GetRootScope(This,pRetVal) ) + +#define ISymUnmanagedMethod_GetScopeFromOffset(This,offset,pRetVal) \ + ( (This)->lpVtbl -> GetScopeFromOffset(This,offset,pRetVal) ) + +#define ISymUnmanagedMethod_GetOffset(This,document,line,column,pRetVal) \ + ( (This)->lpVtbl -> GetOffset(This,document,line,column,pRetVal) ) + +#define ISymUnmanagedMethod_GetRanges(This,document,line,column,cRanges,pcRanges,ranges) \ + ( (This)->lpVtbl -> GetRanges(This,document,line,column,cRanges,pcRanges,ranges) ) + +#define ISymUnmanagedMethod_GetParameters(This,cParams,pcParams,params) \ + ( (This)->lpVtbl -> GetParameters(This,cParams,pcParams,params) ) + +#define ISymUnmanagedMethod_GetNamespace(This,pRetVal) \ + ( (This)->lpVtbl -> GetNamespace(This,pRetVal) ) + +#define ISymUnmanagedMethod_GetSourceStartEnd(This,docs,lines,columns,pRetVal) \ + ( (This)->lpVtbl -> GetSourceStartEnd(This,docs,lines,columns,pRetVal) ) + +#define ISymUnmanagedMethod_GetSequencePoints(This,cPoints,pcPoints,offsets,documents,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> GetSequencePoints(This,cPoints,pcPoints,offsets,documents,lines,columns,endLines,endColumns) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedMethod_INTERFACE_DEFINED__ */ + + +#ifndef __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ +#define __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ + +/* interface ISymENCUnmanagedMethod */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymENCUnmanagedMethod; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("85E891DA-A631-4c76-ACA2-A44A39C46B8C") + ISymENCUnmanagedMethod : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFileNameFromOffset( + /* [in] */ ULONG32 dwOffset, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLineFromOffset( + /* [in] */ ULONG32 dwOffset, + /* [out] */ __RPC__out ULONG32 *pline, + /* [out] */ __RPC__out ULONG32 *pcolumn, + /* [out] */ __RPC__out ULONG32 *pendLine, + /* [out] */ __RPC__out ULONG32 *pendColumn, + /* [out] */ __RPC__out ULONG32 *pdwStartOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDocumentsForMethodCount( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDocumentsForMethod( + /* [in] */ ULONG32 cDocs, + /* [out] */ __RPC__out ULONG32 *pcDocs, + /* [size_is][in] */ __RPC__in_ecount_full(cDocs) ISymUnmanagedDocument *documents[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSourceExtentInDocument( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [out] */ __RPC__out ULONG32 *pstartLine, + /* [out] */ __RPC__out ULONG32 *pendLine) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymENCUnmanagedMethodVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymENCUnmanagedMethod * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymENCUnmanagedMethod * This); + + HRESULT ( STDMETHODCALLTYPE *GetFileNameFromOffset )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [in] */ ULONG32 dwOffset, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetLineFromOffset )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [in] */ ULONG32 dwOffset, + /* [out] */ __RPC__out ULONG32 *pline, + /* [out] */ __RPC__out ULONG32 *pcolumn, + /* [out] */ __RPC__out ULONG32 *pendLine, + /* [out] */ __RPC__out ULONG32 *pendColumn, + /* [out] */ __RPC__out ULONG32 *pdwStartOffset); + + HRESULT ( STDMETHODCALLTYPE *GetDocumentsForMethodCount )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetDocumentsForMethod )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [in] */ ULONG32 cDocs, + /* [out] */ __RPC__out ULONG32 *pcDocs, + /* [size_is][in] */ __RPC__in_ecount_full(cDocs) ISymUnmanagedDocument *documents[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetSourceExtentInDocument )( + __RPC__in ISymENCUnmanagedMethod * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [out] */ __RPC__out ULONG32 *pstartLine, + /* [out] */ __RPC__out ULONG32 *pendLine); + + END_INTERFACE + } ISymENCUnmanagedMethodVtbl; + + interface ISymENCUnmanagedMethod + { + CONST_VTBL struct ISymENCUnmanagedMethodVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymENCUnmanagedMethod_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymENCUnmanagedMethod_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymENCUnmanagedMethod_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymENCUnmanagedMethod_GetFileNameFromOffset(This,dwOffset,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetFileNameFromOffset(This,dwOffset,cchName,pcchName,szName) ) + +#define ISymENCUnmanagedMethod_GetLineFromOffset(This,dwOffset,pline,pcolumn,pendLine,pendColumn,pdwStartOffset) \ + ( (This)->lpVtbl -> GetLineFromOffset(This,dwOffset,pline,pcolumn,pendLine,pendColumn,pdwStartOffset) ) + +#define ISymENCUnmanagedMethod_GetDocumentsForMethodCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetDocumentsForMethodCount(This,pRetVal) ) + +#define ISymENCUnmanagedMethod_GetDocumentsForMethod(This,cDocs,pcDocs,documents) \ + ( (This)->lpVtbl -> GetDocumentsForMethod(This,cDocs,pcDocs,documents) ) + +#define ISymENCUnmanagedMethod_GetSourceExtentInDocument(This,document,pstartLine,pendLine) \ + ( (This)->lpVtbl -> GetSourceExtentInDocument(This,document,pstartLine,pendLine) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedNamespace_INTERFACE_DEFINED__ +#define __ISymUnmanagedNamespace_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedNamespace */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedNamespace; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0DFF7289-54F8-11d3-BD28-0000F80849BD") + ISymUnmanagedNamespace : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNamespaces( + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVariables( + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedNamespaceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedNamespace * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedNamespace * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedNamespace * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + __RPC__in ISymUnmanagedNamespace * This, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( + __RPC__in ISymUnmanagedNamespace * This, + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetVariables )( + __RPC__in ISymUnmanagedNamespace * This, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); + + END_INTERFACE + } ISymUnmanagedNamespaceVtbl; + + interface ISymUnmanagedNamespace + { + CONST_VTBL struct ISymUnmanagedNamespaceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedNamespace_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedNamespace_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedNamespace_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedNamespace_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ISymUnmanagedNamespace_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ + ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) + +#define ISymUnmanagedNamespace_GetVariables(This,cVars,pcVars,pVars) \ + ( (This)->lpVtbl -> GetVariables(This,cVars,pcVars,pVars) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedNamespace_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedReader_INTERFACE_DEFINED__ +#define __ISymUnmanagedReader_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedReader */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedReader; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5") + ISymUnmanagedReader : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetDocument( + /* [in] */ __RPC__in WCHAR *url, + /* [in] */ GUID language, + /* [in] */ GUID languageVendor, + /* [in] */ GUID documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDocuments( + /* [in] */ ULONG32 cDocs, + /* [out] */ __RPC__out ULONG32 *pcDocs, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUserEntryPoint( + /* [retval][out] */ __RPC__out mdMethodDef *pToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethod( + /* [in] */ mdMethodDef token, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodByVersion( + /* [in] */ mdMethodDef token, + /* [in] */ int version, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVariables( + /* [in] */ mdToken parent, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGlobalVariables( + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodFromDocumentPosition( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSymAttribute( + /* [in] */ mdToken parent, + /* [in] */ __RPC__in WCHAR *name, + /* [in] */ ULONG32 cBuffer, + /* [out] */ __RPC__out ULONG32 *pcBuffer, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNamespaces( + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Initialize( + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ __RPC__in_opt IStream *pIStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE UpdateSymbolStore( + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReplaceSymbolStore( + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSymbolStoreFileName( + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodsFromDocumentPosition( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 cMethod, + /* [out] */ __RPC__out ULONG32 *pcMethod, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDocumentVersion( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, + /* [out] */ __RPC__out int *version, + /* [out] */ __RPC__out BOOL *pbCurrent) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodVersion( + /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, + /* [out] */ __RPC__out int *version) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedReaderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedReader * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedReader * This); + + HRESULT ( STDMETHODCALLTYPE *GetDocument )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in WCHAR *url, + /* [in] */ GUID language, + /* [in] */ GUID languageVendor, + /* [in] */ GUID documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetDocuments )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ ULONG32 cDocs, + /* [out] */ __RPC__out ULONG32 *pcDocs, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetUserEntryPoint )( + __RPC__in ISymUnmanagedReader * This, + /* [retval][out] */ __RPC__out mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetMethod )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ mdMethodDef token, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetMethodByVersion )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ mdMethodDef token, + /* [in] */ int version, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetVariables )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ mdToken parent, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetGlobalVariables )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodFromDocumentPosition )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSymAttribute )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in WCHAR *name, + /* [in] */ ULONG32 cBuffer, + /* [out] */ __RPC__out ULONG32 *pcBuffer, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *ReplaceSymbolStore )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *GetSymbolStoreFileName )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodsFromDocumentPosition )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 cMethod, + /* [out] */ __RPC__out ULONG32 *pcMethod, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetDocumentVersion )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, + /* [out] */ __RPC__out int *version, + /* [out] */ __RPC__out BOOL *pbCurrent); + + HRESULT ( STDMETHODCALLTYPE *GetMethodVersion )( + __RPC__in ISymUnmanagedReader * This, + /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, + /* [out] */ __RPC__out int *version); + + END_INTERFACE + } ISymUnmanagedReaderVtbl; + + interface ISymUnmanagedReader + { + CONST_VTBL struct ISymUnmanagedReaderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedReader_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedReader_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedReader_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedReader_GetDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> GetDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedReader_GetDocuments(This,cDocs,pcDocs,pDocs) \ + ( (This)->lpVtbl -> GetDocuments(This,cDocs,pcDocs,pDocs) ) + +#define ISymUnmanagedReader_GetUserEntryPoint(This,pToken) \ + ( (This)->lpVtbl -> GetUserEntryPoint(This,pToken) ) + +#define ISymUnmanagedReader_GetMethod(This,token,pRetVal) \ + ( (This)->lpVtbl -> GetMethod(This,token,pRetVal) ) + +#define ISymUnmanagedReader_GetMethodByVersion(This,token,version,pRetVal) \ + ( (This)->lpVtbl -> GetMethodByVersion(This,token,version,pRetVal) ) + +#define ISymUnmanagedReader_GetVariables(This,parent,cVars,pcVars,pVars) \ + ( (This)->lpVtbl -> GetVariables(This,parent,cVars,pcVars,pVars) ) + +#define ISymUnmanagedReader_GetGlobalVariables(This,cVars,pcVars,pVars) \ + ( (This)->lpVtbl -> GetGlobalVariables(This,cVars,pcVars,pVars) ) + +#define ISymUnmanagedReader_GetMethodFromDocumentPosition(This,document,line,column,pRetVal) \ + ( (This)->lpVtbl -> GetMethodFromDocumentPosition(This,document,line,column,pRetVal) ) + +#define ISymUnmanagedReader_GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) \ + ( (This)->lpVtbl -> GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) ) + +#define ISymUnmanagedReader_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ + ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) + +#define ISymUnmanagedReader_Initialize(This,importer,filename,searchPath,pIStream) \ + ( (This)->lpVtbl -> Initialize(This,importer,filename,searchPath,pIStream) ) + +#define ISymUnmanagedReader_UpdateSymbolStore(This,filename,pIStream) \ + ( (This)->lpVtbl -> UpdateSymbolStore(This,filename,pIStream) ) + +#define ISymUnmanagedReader_ReplaceSymbolStore(This,filename,pIStream) \ + ( (This)->lpVtbl -> ReplaceSymbolStore(This,filename,pIStream) ) + +#define ISymUnmanagedReader_GetSymbolStoreFileName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetSymbolStoreFileName(This,cchName,pcchName,szName) ) + +#define ISymUnmanagedReader_GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) \ + ( (This)->lpVtbl -> GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) ) + +#define ISymUnmanagedReader_GetDocumentVersion(This,pDoc,version,pbCurrent) \ + ( (This)->lpVtbl -> GetDocumentVersion(This,pDoc,version,pbCurrent) ) + +#define ISymUnmanagedReader_GetMethodVersion(This,pMethod,version) \ + ( (This)->lpVtbl -> GetMethodVersion(This,pMethod,version) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedReader_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ +#define __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedSourceServerModule */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedSourceServerModule; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("997DD0CC-A76F-4c82-8D79-EA87559D27AD") + ISymUnmanagedSourceServerModule : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSourceServerData( + /* [out] */ __RPC__out ULONG *pDataByteCount, + /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*pDataByteCount) BYTE **ppData) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedSourceServerModuleVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedSourceServerModule * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedSourceServerModule * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedSourceServerModule * This); + + HRESULT ( STDMETHODCALLTYPE *GetSourceServerData )( + __RPC__in ISymUnmanagedSourceServerModule * This, + /* [out] */ __RPC__out ULONG *pDataByteCount, + /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*pDataByteCount) BYTE **ppData); + + END_INTERFACE + } ISymUnmanagedSourceServerModuleVtbl; + + interface ISymUnmanagedSourceServerModule + { + CONST_VTBL struct ISymUnmanagedSourceServerModuleVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedSourceServerModule_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedSourceServerModule_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedSourceServerModule_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedSourceServerModule_GetSourceServerData(This,pDataByteCount,ppData) \ + ( (This)->lpVtbl -> GetSourceServerData(This,pDataByteCount,ppData) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ +#define __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedENCUpdate */ +/* [unique][uuid][object] */ + +typedef struct _SYMLINEDELTA + { + mdMethodDef mdMethod; + INT32 delta; + } SYMLINEDELTA; + + +EXTERN_C const IID IID_ISymUnmanagedENCUpdate; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E502D2DD-8671-4338-8F2A-FC08229628C4") + ISymUnmanagedENCUpdate : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE UpdateSymbolStore2( + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ __RPC__in SYMLINEDELTA *pDeltaLines, + /* [in] */ ULONG cDeltaLines) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariableCount( + /* [in] */ mdMethodDef mdMethodToken, + /* [out] */ __RPC__out ULONG *pcLocals) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariables( + /* [in] */ mdMethodDef mdMethodToken, + /* [in] */ ULONG cLocals, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pceltFetched) ISymUnmanagedVariable *rgLocals[ ], + /* [out] */ __RPC__out ULONG *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE InitializeForEnc( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE UpdateMethodLines( + /* [in] */ mdMethodDef mdMethodToken, + /* [size_is][in] */ __RPC__in_ecount_full(cDeltas) INT32 *pDeltas, + /* [in] */ ULONG cDeltas) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedENCUpdateVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedENCUpdate * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedENCUpdate * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedENCUpdate * This); + + HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore2 )( + __RPC__in ISymUnmanagedENCUpdate * This, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ __RPC__in SYMLINEDELTA *pDeltaLines, + /* [in] */ ULONG cDeltaLines); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariableCount )( + __RPC__in ISymUnmanagedENCUpdate * This, + /* [in] */ mdMethodDef mdMethodToken, + /* [out] */ __RPC__out ULONG *pcLocals); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariables )( + __RPC__in ISymUnmanagedENCUpdate * This, + /* [in] */ mdMethodDef mdMethodToken, + /* [in] */ ULONG cLocals, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pceltFetched) ISymUnmanagedVariable *rgLocals[ ], + /* [out] */ __RPC__out ULONG *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE *InitializeForEnc )( + __RPC__in ISymUnmanagedENCUpdate * This); + + HRESULT ( STDMETHODCALLTYPE *UpdateMethodLines )( + __RPC__in ISymUnmanagedENCUpdate * This, + /* [in] */ mdMethodDef mdMethodToken, + /* [size_is][in] */ __RPC__in_ecount_full(cDeltas) INT32 *pDeltas, + /* [in] */ ULONG cDeltas); + + END_INTERFACE + } ISymUnmanagedENCUpdateVtbl; + + interface ISymUnmanagedENCUpdate + { + CONST_VTBL struct ISymUnmanagedENCUpdateVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedENCUpdate_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedENCUpdate_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedENCUpdate_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedENCUpdate_UpdateSymbolStore2(This,pIStream,pDeltaLines,cDeltaLines) \ + ( (This)->lpVtbl -> UpdateSymbolStore2(This,pIStream,pDeltaLines,cDeltaLines) ) + +#define ISymUnmanagedENCUpdate_GetLocalVariableCount(This,mdMethodToken,pcLocals) \ + ( (This)->lpVtbl -> GetLocalVariableCount(This,mdMethodToken,pcLocals) ) + +#define ISymUnmanagedENCUpdate_GetLocalVariables(This,mdMethodToken,cLocals,rgLocals,pceltFetched) \ + ( (This)->lpVtbl -> GetLocalVariables(This,mdMethodToken,cLocals,rgLocals,pceltFetched) ) + +#define ISymUnmanagedENCUpdate_InitializeForEnc(This) \ + ( (This)->lpVtbl -> InitializeForEnc(This) ) + +#define ISymUnmanagedENCUpdate_UpdateMethodLines(This,mdMethodToken,pDeltas,cDeltas) \ + ( (This)->lpVtbl -> UpdateMethodLines(This,mdMethodToken,pDeltas,cDeltas) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ +#define __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedReaderSymbolSearchInfo */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedReaderSymbolSearchInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("20D9645D-03CD-4e34-9C11-9848A5B084F1") + ISymUnmanagedReaderSymbolSearchInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSymbolSearchInfoCount( + /* [out] */ __RPC__out ULONG32 *pcSearchInfo) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSymbolSearchInfo( + /* [in] */ ULONG32 cSearchInfo, + /* [out] */ __RPC__out ULONG32 *pcSearchInfo, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSearchInfo, *pcSearchInfo) ISymUnmanagedSymbolSearchInfo **rgpSearchInfo) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedReaderSymbolSearchInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetSymbolSearchInfoCount )( + __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, + /* [out] */ __RPC__out ULONG32 *pcSearchInfo); + + HRESULT ( STDMETHODCALLTYPE *GetSymbolSearchInfo )( + __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, + /* [in] */ ULONG32 cSearchInfo, + /* [out] */ __RPC__out ULONG32 *pcSearchInfo, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSearchInfo, *pcSearchInfo) ISymUnmanagedSymbolSearchInfo **rgpSearchInfo); + + END_INTERFACE + } ISymUnmanagedReaderSymbolSearchInfoVtbl; + + interface ISymUnmanagedReaderSymbolSearchInfo + { + CONST_VTBL struct ISymUnmanagedReaderSymbolSearchInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedReaderSymbolSearchInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedReaderSymbolSearchInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedReaderSymbolSearchInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedReaderSymbolSearchInfo_GetSymbolSearchInfoCount(This,pcSearchInfo) \ + ( (This)->lpVtbl -> GetSymbolSearchInfoCount(This,pcSearchInfo) ) + +#define ISymUnmanagedReaderSymbolSearchInfo_GetSymbolSearchInfo(This,cSearchInfo,pcSearchInfo,rgpSearchInfo) \ + ( (This)->lpVtbl -> GetSymbolSearchInfo(This,cSearchInfo,pcSearchInfo,rgpSearchInfo) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedScope_INTERFACE_DEFINED__ +#define __ISymUnmanagedScope_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedScope */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedScope; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("68005D0F-B8E0-3B01-84D5-A11A94154942") + ISymUnmanagedScope : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMethod( + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetParent( + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetChildren( + /* [in] */ ULONG32 cChildren, + /* [out] */ __RPC__out ULONG32 *pcChildren, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStartOffset( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEndOffset( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalCount( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocals( + /* [in] */ ULONG32 cLocals, + /* [out] */ __RPC__out ULONG32 *pcLocals, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNamespaces( + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedScopeVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedScope * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedScope * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedScope * This); + + HRESULT ( STDMETHODCALLTYPE *GetMethod )( + __RPC__in ISymUnmanagedScope * This, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetParent )( + __RPC__in ISymUnmanagedScope * This, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetChildren )( + __RPC__in ISymUnmanagedScope * This, + /* [in] */ ULONG32 cChildren, + /* [out] */ __RPC__out ULONG32 *pcChildren, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( + __RPC__in ISymUnmanagedScope * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( + __RPC__in ISymUnmanagedScope * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLocalCount )( + __RPC__in ISymUnmanagedScope * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLocals )( + __RPC__in ISymUnmanagedScope * This, + /* [in] */ ULONG32 cLocals, + /* [out] */ __RPC__out ULONG32 *pcLocals, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( + __RPC__in ISymUnmanagedScope * This, + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); + + END_INTERFACE + } ISymUnmanagedScopeVtbl; + + interface ISymUnmanagedScope + { + CONST_VTBL struct ISymUnmanagedScopeVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedScope_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedScope_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedScope_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedScope_GetMethod(This,pRetVal) \ + ( (This)->lpVtbl -> GetMethod(This,pRetVal) ) + +#define ISymUnmanagedScope_GetParent(This,pRetVal) \ + ( (This)->lpVtbl -> GetParent(This,pRetVal) ) + +#define ISymUnmanagedScope_GetChildren(This,cChildren,pcChildren,children) \ + ( (This)->lpVtbl -> GetChildren(This,cChildren,pcChildren,children) ) + +#define ISymUnmanagedScope_GetStartOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) + +#define ISymUnmanagedScope_GetEndOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) + +#define ISymUnmanagedScope_GetLocalCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetLocalCount(This,pRetVal) ) + +#define ISymUnmanagedScope_GetLocals(This,cLocals,pcLocals,locals) \ + ( (This)->lpVtbl -> GetLocals(This,cLocals,pcLocals,locals) ) + +#define ISymUnmanagedScope_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ + ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedScope_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedConstant_INTERFACE_DEFINED__ +#define __ISymUnmanagedConstant_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedConstant */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedConstant; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9") + ISymUnmanagedConstant : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetValue( + __RPC__in VARIANT *pValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSignature( + /* [in] */ ULONG32 cSig, + /* [out] */ __RPC__out ULONG32 *pcSig, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedConstantVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedConstant * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedConstant * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedConstant * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + __RPC__in ISymUnmanagedConstant * This, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetValue )( + __RPC__in ISymUnmanagedConstant * This, + __RPC__in VARIANT *pValue); + + HRESULT ( STDMETHODCALLTYPE *GetSignature )( + __RPC__in ISymUnmanagedConstant * This, + /* [in] */ ULONG32 cSig, + /* [out] */ __RPC__out ULONG32 *pcSig, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]); + + END_INTERFACE + } ISymUnmanagedConstantVtbl; + + interface ISymUnmanagedConstant + { + CONST_VTBL struct ISymUnmanagedConstantVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedConstant_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedConstant_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedConstant_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedConstant_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ISymUnmanagedConstant_GetValue(This,pValue) \ + ( (This)->lpVtbl -> GetValue(This,pValue) ) + +#define ISymUnmanagedConstant_GetSignature(This,cSig,pcSig,sig) \ + ( (This)->lpVtbl -> GetSignature(This,cSig,pcSig,sig) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedConstant_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedScope2_INTERFACE_DEFINED__ +#define __ISymUnmanagedScope2_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedScope2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedScope2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AE932FBA-3FD8-4dba-8232-30A2309B02DB") + ISymUnmanagedScope2 : public ISymUnmanagedScope + { + public: + virtual HRESULT STDMETHODCALLTYPE GetConstantCount( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetConstants( + /* [in] */ ULONG32 cConstants, + /* [out] */ __RPC__out ULONG32 *pcConstants, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cConstants, *pcConstants) ISymUnmanagedConstant *constants[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedScope2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedScope2 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedScope2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedScope2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetMethod )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetParent )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetChildren )( + __RPC__in ISymUnmanagedScope2 * This, + /* [in] */ ULONG32 cChildren, + /* [out] */ __RPC__out ULONG32 *pcChildren, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLocalCount )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetLocals )( + __RPC__in ISymUnmanagedScope2 * This, + /* [in] */ ULONG32 cLocals, + /* [out] */ __RPC__out ULONG32 *pcLocals, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( + __RPC__in ISymUnmanagedScope2 * This, + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetConstantCount )( + __RPC__in ISymUnmanagedScope2 * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetConstants )( + __RPC__in ISymUnmanagedScope2 * This, + /* [in] */ ULONG32 cConstants, + /* [out] */ __RPC__out ULONG32 *pcConstants, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cConstants, *pcConstants) ISymUnmanagedConstant *constants[ ]); + + END_INTERFACE + } ISymUnmanagedScope2Vtbl; + + interface ISymUnmanagedScope2 + { + CONST_VTBL struct ISymUnmanagedScope2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedScope2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedScope2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedScope2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedScope2_GetMethod(This,pRetVal) \ + ( (This)->lpVtbl -> GetMethod(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetParent(This,pRetVal) \ + ( (This)->lpVtbl -> GetParent(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetChildren(This,cChildren,pcChildren,children) \ + ( (This)->lpVtbl -> GetChildren(This,cChildren,pcChildren,children) ) + +#define ISymUnmanagedScope2_GetStartOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetEndOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetLocalCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetLocalCount(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetLocals(This,cLocals,pcLocals,locals) \ + ( (This)->lpVtbl -> GetLocals(This,cLocals,pcLocals,locals) ) + +#define ISymUnmanagedScope2_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ + ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) + + +#define ISymUnmanagedScope2_GetConstantCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetConstantCount(This,pRetVal) ) + +#define ISymUnmanagedScope2_GetConstants(This,cConstants,pcConstants,constants) \ + ( (This)->lpVtbl -> GetConstants(This,cConstants,pcConstants,constants) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedScope2_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedVariable_INTERFACE_DEFINED__ +#define __ISymUnmanagedVariable_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedVariable */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedVariable; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB") + ISymUnmanagedVariable : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAttributes( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSignature( + /* [in] */ ULONG32 cSig, + /* [out] */ __RPC__out ULONG32 *pcSig, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressKind( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressField1( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressField2( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressField3( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStartOffset( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEndOffset( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedVariableVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedVariable * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedVariable * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedVariable * This); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + __RPC__in ISymUnmanagedVariable * This, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAttributes )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSignature )( + __RPC__in ISymUnmanagedVariable * This, + /* [in] */ ULONG32 cSig, + /* [out] */ __RPC__out ULONG32 *pcSig, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAddressKind )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetAddressField1 )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetAddressField2 )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetAddressField3 )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( + __RPC__in ISymUnmanagedVariable * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + END_INTERFACE + } ISymUnmanagedVariableVtbl; + + interface ISymUnmanagedVariable + { + CONST_VTBL struct ISymUnmanagedVariableVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedVariable_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedVariable_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedVariable_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedVariable_GetName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) + +#define ISymUnmanagedVariable_GetAttributes(This,pRetVal) \ + ( (This)->lpVtbl -> GetAttributes(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetSignature(This,cSig,pcSig,sig) \ + ( (This)->lpVtbl -> GetSignature(This,cSig,pcSig,sig) ) + +#define ISymUnmanagedVariable_GetAddressKind(This,pRetVal) \ + ( (This)->lpVtbl -> GetAddressKind(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetAddressField1(This,pRetVal) \ + ( (This)->lpVtbl -> GetAddressField1(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetAddressField2(This,pRetVal) \ + ( (This)->lpVtbl -> GetAddressField2(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetAddressField3(This,pRetVal) \ + ( (This)->lpVtbl -> GetAddressField3(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetStartOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) + +#define ISymUnmanagedVariable_GetEndOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedVariable_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ +#define __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedSymbolSearchInfo */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedSymbolSearchInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("F8B3534A-A46B-4980-B520-BEC4ACEABA8F") + ISymUnmanagedSymbolSearchInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSearchPathLength( + /* [out] */ __RPC__out ULONG32 *pcchPath) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSearchPath( + /* [in] */ ULONG32 cchPath, + /* [out] */ __RPC__out ULONG32 *pcchPath, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchPath, *pcchPath) WCHAR szPath[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHRESULT( + /* [out] */ __RPC__out HRESULT *phr) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedSymbolSearchInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetSearchPathLength )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This, + /* [out] */ __RPC__out ULONG32 *pcchPath); + + HRESULT ( STDMETHODCALLTYPE *GetSearchPath )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This, + /* [in] */ ULONG32 cchPath, + /* [out] */ __RPC__out ULONG32 *pcchPath, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchPath, *pcchPath) WCHAR szPath[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetHRESULT )( + __RPC__in ISymUnmanagedSymbolSearchInfo * This, + /* [out] */ __RPC__out HRESULT *phr); + + END_INTERFACE + } ISymUnmanagedSymbolSearchInfoVtbl; + + interface ISymUnmanagedSymbolSearchInfo + { + CONST_VTBL struct ISymUnmanagedSymbolSearchInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedSymbolSearchInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedSymbolSearchInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedSymbolSearchInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedSymbolSearchInfo_GetSearchPathLength(This,pcchPath) \ + ( (This)->lpVtbl -> GetSearchPathLength(This,pcchPath) ) + +#define ISymUnmanagedSymbolSearchInfo_GetSearchPath(This,cchPath,pcchPath,szPath) \ + ( (This)->lpVtbl -> GetSearchPath(This,cchPath,pcchPath,szPath) ) + +#define ISymUnmanagedSymbolSearchInfo_GetHRESULT(This,phr) \ + ( (This)->lpVtbl -> GetHRESULT(This,phr) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter_INTERFACE_DEFINED__ +#define __ISymUnmanagedWriter_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedWriter */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedWriter; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ED14AA72-78E2-4884-84E2-334293AE5214") + ISymUnmanagedWriter : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE DefineDocument( + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetUserEntryPoint( + /* [in] */ mdMethodDef entryMethod) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenMethod( + /* [in] */ mdMethodDef method) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseMethod( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenScope( + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseScope( + /* [in] */ ULONG32 endOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetScopeRange( + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineLocalVariable( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineParameter( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineField( + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineGlobalVariable( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3) = 0; + + virtual HRESULT STDMETHODCALLTYPE Close( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSymAttribute( + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE OpenNamespace( + /* [in] */ __RPC__in const WCHAR *name) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseNamespace( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE UsingNamespace( + /* [in] */ __RPC__in const WCHAR *fullName) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetMethodSourceRange( + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn) = 0; + + virtual HRESULT STDMETHODCALLTYPE Initialize( + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDebugInfo( + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineSequencePoints( + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemapToken( + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken) = 0; + + virtual HRESULT STDMETHODCALLTYPE Initialize2( + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineConstant( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedWriterVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedWriter * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedWriter * This); + + HRESULT ( STDMETHODCALLTYPE *DefineDocument )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ mdMethodDef entryMethod); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ mdMethodDef method); + + HRESULT ( STDMETHODCALLTYPE *CloseMethod )( + __RPC__in ISymUnmanagedWriter * This); + + HRESULT ( STDMETHODCALLTYPE *OpenScope )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *CloseScope )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineParameter )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineField )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in ISymUnmanagedWriter * This); + + HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *name); + + HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( + __RPC__in ISymUnmanagedWriter * This); + + HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *fullName); + + HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( + __RPC__in ISymUnmanagedWriter * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); + + HRESULT ( STDMETHODCALLTYPE *RemapToken )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken); + + HRESULT ( STDMETHODCALLTYPE *Initialize2 )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant )( + __RPC__in ISymUnmanagedWriter * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + __RPC__in ISymUnmanagedWriter * This); + + END_INTERFACE + } ISymUnmanagedWriterVtbl; + + interface ISymUnmanagedWriter + { + CONST_VTBL struct ISymUnmanagedWriterVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedWriter_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedWriter_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedWriter_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedWriter_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedWriter_SetUserEntryPoint(This,entryMethod) \ + ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) + +#define ISymUnmanagedWriter_OpenMethod(This,method) \ + ( (This)->lpVtbl -> OpenMethod(This,method) ) + +#define ISymUnmanagedWriter_CloseMethod(This) \ + ( (This)->lpVtbl -> CloseMethod(This) ) + +#define ISymUnmanagedWriter_OpenScope(This,startOffset,pRetVal) \ + ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) + +#define ISymUnmanagedWriter_CloseScope(This,endOffset) \ + ( (This)->lpVtbl -> CloseScope(This,endOffset) ) + +#define ISymUnmanagedWriter_SetScopeRange(This,scopeID,startOffset,endOffset) \ + ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) + +#define ISymUnmanagedWriter_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define ISymUnmanagedWriter_SetSymAttribute(This,parent,name,cData,data) \ + ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) + +#define ISymUnmanagedWriter_OpenNamespace(This,name) \ + ( (This)->lpVtbl -> OpenNamespace(This,name) ) + +#define ISymUnmanagedWriter_CloseNamespace(This) \ + ( (This)->lpVtbl -> CloseNamespace(This) ) + +#define ISymUnmanagedWriter_UsingNamespace(This,fullName) \ + ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) + +#define ISymUnmanagedWriter_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ + ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) + +#define ISymUnmanagedWriter_Initialize(This,emitter,filename,pIStream,fFullBuild) \ + ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) + +#define ISymUnmanagedWriter_GetDebugInfo(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) + +#define ISymUnmanagedWriter_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) + +#define ISymUnmanagedWriter_RemapToken(This,oldToken,newToken) \ + ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) + +#define ISymUnmanagedWriter_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ + ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) + +#define ISymUnmanagedWriter_DefineConstant(This,name,value,cSig,signature) \ + ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) + +#define ISymUnmanagedWriter_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedWriter_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter2_INTERFACE_DEFINED__ +#define __ISymUnmanagedWriter2_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedWriter2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedWriter2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0B97726E-9E6D-4f05-9A26-424022093CAA") + ISymUnmanagedWriter2 : public ISymUnmanagedWriter + { + public: + virtual HRESULT STDMETHODCALLTYPE DefineLocalVariable2( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineGlobalVariable2( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineConstant2( + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ mdSignature sigToken) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedWriter2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedWriter2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineDocument )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ mdMethodDef entryMethod); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ mdMethodDef method); + + HRESULT ( STDMETHODCALLTYPE *CloseMethod )( + __RPC__in ISymUnmanagedWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *OpenScope )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *CloseScope )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineParameter )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineField )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in ISymUnmanagedWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name); + + HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( + __RPC__in ISymUnmanagedWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *fullName); + + HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); + + HRESULT ( STDMETHODCALLTYPE *RemapToken )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken); + + HRESULT ( STDMETHODCALLTYPE *Initialize2 )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + __RPC__in ISymUnmanagedWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( + __RPC__in ISymUnmanagedWriter2 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ mdSignature sigToken); + + END_INTERFACE + } ISymUnmanagedWriter2Vtbl; + + interface ISymUnmanagedWriter2 + { + CONST_VTBL struct ISymUnmanagedWriter2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedWriter2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedWriter2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedWriter2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedWriter2_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedWriter2_SetUserEntryPoint(This,entryMethod) \ + ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) + +#define ISymUnmanagedWriter2_OpenMethod(This,method) \ + ( (This)->lpVtbl -> OpenMethod(This,method) ) + +#define ISymUnmanagedWriter2_CloseMethod(This) \ + ( (This)->lpVtbl -> CloseMethod(This) ) + +#define ISymUnmanagedWriter2_OpenScope(This,startOffset,pRetVal) \ + ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) + +#define ISymUnmanagedWriter2_CloseScope(This,endOffset) \ + ( (This)->lpVtbl -> CloseScope(This,endOffset) ) + +#define ISymUnmanagedWriter2_SetScopeRange(This,scopeID,startOffset,endOffset) \ + ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) + +#define ISymUnmanagedWriter2_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter2_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter2_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter2_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter2_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define ISymUnmanagedWriter2_SetSymAttribute(This,parent,name,cData,data) \ + ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) + +#define ISymUnmanagedWriter2_OpenNamespace(This,name) \ + ( (This)->lpVtbl -> OpenNamespace(This,name) ) + +#define ISymUnmanagedWriter2_CloseNamespace(This) \ + ( (This)->lpVtbl -> CloseNamespace(This) ) + +#define ISymUnmanagedWriter2_UsingNamespace(This,fullName) \ + ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) + +#define ISymUnmanagedWriter2_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ + ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) + +#define ISymUnmanagedWriter2_Initialize(This,emitter,filename,pIStream,fFullBuild) \ + ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) + +#define ISymUnmanagedWriter2_GetDebugInfo(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) + +#define ISymUnmanagedWriter2_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) + +#define ISymUnmanagedWriter2_RemapToken(This,oldToken,newToken) \ + ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) + +#define ISymUnmanagedWriter2_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ + ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) + +#define ISymUnmanagedWriter2_DefineConstant(This,name,value,cSig,signature) \ + ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) + +#define ISymUnmanagedWriter2_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + + +#define ISymUnmanagedWriter2_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter2_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter2_DefineConstant2(This,name,value,sigToken) \ + ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedWriter2_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter3_INTERFACE_DEFINED__ +#define __ISymUnmanagedWriter3_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedWriter3 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedWriter3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("12F1E02C-1E05-4B0E-9468-EBC9D1BB040F") + ISymUnmanagedWriter3 : public ISymUnmanagedWriter2 + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenMethod2( + /* [in] */ mdMethodDef method, + /* [in] */ ULONG32 isect, + /* [in] */ ULONG32 offset) = 0; + + virtual HRESULT STDMETHODCALLTYPE Commit( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedWriter3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedWriter3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedWriter3 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineDocument )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdMethodDef entryMethod); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdMethodDef method); + + HRESULT ( STDMETHODCALLTYPE *CloseMethod )( + __RPC__in ISymUnmanagedWriter3 * This); + + HRESULT ( STDMETHODCALLTYPE *OpenScope )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *CloseScope )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineParameter )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineField )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in ISymUnmanagedWriter3 * This); + + HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name); + + HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( + __RPC__in ISymUnmanagedWriter3 * This); + + HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *fullName); + + HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); + + HRESULT ( STDMETHODCALLTYPE *RemapToken )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken); + + HRESULT ( STDMETHODCALLTYPE *Initialize2 )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + __RPC__in ISymUnmanagedWriter3 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ mdSignature sigToken); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( + __RPC__in ISymUnmanagedWriter3 * This, + /* [in] */ mdMethodDef method, + /* [in] */ ULONG32 isect, + /* [in] */ ULONG32 offset); + + HRESULT ( STDMETHODCALLTYPE *Commit )( + __RPC__in ISymUnmanagedWriter3 * This); + + END_INTERFACE + } ISymUnmanagedWriter3Vtbl; + + interface ISymUnmanagedWriter3 + { + CONST_VTBL struct ISymUnmanagedWriter3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedWriter3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedWriter3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedWriter3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedWriter3_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedWriter3_SetUserEntryPoint(This,entryMethod) \ + ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) + +#define ISymUnmanagedWriter3_OpenMethod(This,method) \ + ( (This)->lpVtbl -> OpenMethod(This,method) ) + +#define ISymUnmanagedWriter3_CloseMethod(This) \ + ( (This)->lpVtbl -> CloseMethod(This) ) + +#define ISymUnmanagedWriter3_OpenScope(This,startOffset,pRetVal) \ + ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) + +#define ISymUnmanagedWriter3_CloseScope(This,endOffset) \ + ( (This)->lpVtbl -> CloseScope(This,endOffset) ) + +#define ISymUnmanagedWriter3_SetScopeRange(This,scopeID,startOffset,endOffset) \ + ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) + +#define ISymUnmanagedWriter3_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter3_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter3_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter3_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter3_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define ISymUnmanagedWriter3_SetSymAttribute(This,parent,name,cData,data) \ + ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) + +#define ISymUnmanagedWriter3_OpenNamespace(This,name) \ + ( (This)->lpVtbl -> OpenNamespace(This,name) ) + +#define ISymUnmanagedWriter3_CloseNamespace(This) \ + ( (This)->lpVtbl -> CloseNamespace(This) ) + +#define ISymUnmanagedWriter3_UsingNamespace(This,fullName) \ + ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) + +#define ISymUnmanagedWriter3_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ + ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) + +#define ISymUnmanagedWriter3_Initialize(This,emitter,filename,pIStream,fFullBuild) \ + ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) + +#define ISymUnmanagedWriter3_GetDebugInfo(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) + +#define ISymUnmanagedWriter3_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) + +#define ISymUnmanagedWriter3_RemapToken(This,oldToken,newToken) \ + ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) + +#define ISymUnmanagedWriter3_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ + ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) + +#define ISymUnmanagedWriter3_DefineConstant(This,name,value,cSig,signature) \ + ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) + +#define ISymUnmanagedWriter3_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + + +#define ISymUnmanagedWriter3_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter3_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter3_DefineConstant2(This,name,value,sigToken) \ + ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) + + +#define ISymUnmanagedWriter3_OpenMethod2(This,method,isect,offset) \ + ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) + +#define ISymUnmanagedWriter3_Commit(This) \ + ( (This)->lpVtbl -> Commit(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedWriter3_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter4_INTERFACE_DEFINED__ +#define __ISymUnmanagedWriter4_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedWriter4 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedWriter4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BC7E3F53-F458-4C23-9DBD-A189E6E96594") + ISymUnmanagedWriter4 : public ISymUnmanagedWriter3 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetDebugInfoWithPadding( + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedWriter4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedWriter4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineDocument )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdMethodDef entryMethod); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdMethodDef method); + + HRESULT ( STDMETHODCALLTYPE *CloseMethod )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *OpenScope )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *CloseScope )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineParameter )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineField )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name); + + HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *fullName); + + HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); + + HRESULT ( STDMETHODCALLTYPE *RemapToken )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken); + + HRESULT ( STDMETHODCALLTYPE *Initialize2 )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ mdSignature sigToken); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [in] */ mdMethodDef method, + /* [in] */ ULONG32 isect, + /* [in] */ ULONG32 offset); + + HRESULT ( STDMETHODCALLTYPE *Commit )( + __RPC__in ISymUnmanagedWriter4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfoWithPadding )( + __RPC__in ISymUnmanagedWriter4 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + END_INTERFACE + } ISymUnmanagedWriter4Vtbl; + + interface ISymUnmanagedWriter4 + { + CONST_VTBL struct ISymUnmanagedWriter4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedWriter4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedWriter4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedWriter4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedWriter4_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedWriter4_SetUserEntryPoint(This,entryMethod) \ + ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) + +#define ISymUnmanagedWriter4_OpenMethod(This,method) \ + ( (This)->lpVtbl -> OpenMethod(This,method) ) + +#define ISymUnmanagedWriter4_CloseMethod(This) \ + ( (This)->lpVtbl -> CloseMethod(This) ) + +#define ISymUnmanagedWriter4_OpenScope(This,startOffset,pRetVal) \ + ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) + +#define ISymUnmanagedWriter4_CloseScope(This,endOffset) \ + ( (This)->lpVtbl -> CloseScope(This,endOffset) ) + +#define ISymUnmanagedWriter4_SetScopeRange(This,scopeID,startOffset,endOffset) \ + ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) + +#define ISymUnmanagedWriter4_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter4_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter4_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter4_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter4_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define ISymUnmanagedWriter4_SetSymAttribute(This,parent,name,cData,data) \ + ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) + +#define ISymUnmanagedWriter4_OpenNamespace(This,name) \ + ( (This)->lpVtbl -> OpenNamespace(This,name) ) + +#define ISymUnmanagedWriter4_CloseNamespace(This) \ + ( (This)->lpVtbl -> CloseNamespace(This) ) + +#define ISymUnmanagedWriter4_UsingNamespace(This,fullName) \ + ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) + +#define ISymUnmanagedWriter4_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ + ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) + +#define ISymUnmanagedWriter4_Initialize(This,emitter,filename,pIStream,fFullBuild) \ + ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) + +#define ISymUnmanagedWriter4_GetDebugInfo(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) + +#define ISymUnmanagedWriter4_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) + +#define ISymUnmanagedWriter4_RemapToken(This,oldToken,newToken) \ + ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) + +#define ISymUnmanagedWriter4_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ + ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) + +#define ISymUnmanagedWriter4_DefineConstant(This,name,value,cSig,signature) \ + ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) + +#define ISymUnmanagedWriter4_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + + +#define ISymUnmanagedWriter4_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter4_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter4_DefineConstant2(This,name,value,sigToken) \ + ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) + + +#define ISymUnmanagedWriter4_OpenMethod2(This,method,isect,offset) \ + ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) + +#define ISymUnmanagedWriter4_Commit(This) \ + ( (This)->lpVtbl -> Commit(This) ) + + +#define ISymUnmanagedWriter4_GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedWriter4_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedWriter5_INTERFACE_DEFINED__ +#define __ISymUnmanagedWriter5_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedWriter5 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedWriter5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("DCF7780D-BDE9-45DF-ACFE-21731A32000C") + ISymUnmanagedWriter5 : public ISymUnmanagedWriter4 + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenMapTokensToSourceSpans( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseMapTokensToSourceSpans( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE MapTokenToSourceSpan( + /* [in] */ mdToken token, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedWriter5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedWriter5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineDocument )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *url, + /* [in] */ __RPC__in const GUID *language, + /* [in] */ __RPC__in const GUID *languageVendor, + /* [in] */ __RPC__in const GUID *documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdMethodDef entryMethod); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdMethodDef method); + + HRESULT ( STDMETHODCALLTYPE *CloseMethod )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *OpenScope )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ ULONG32 startOffset, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *CloseScope )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ ULONG32 scopeID, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineParameter )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 sequence, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineField )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdTypeDef parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 cData, + /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name); + + HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *fullName); + + HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, + /* [in] */ ULONG32 startLine, + /* [in] */ ULONG32 startColumn, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 spCount, + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], + /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); + + HRESULT ( STDMETHODCALLTYPE *RemapToken )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdToken oldToken, + /* [in] */ mdToken newToken); + + HRESULT ( STDMETHODCALLTYPE *Initialize2 )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in_opt IUnknown *emitter, + /* [in] */ __RPC__in const WCHAR *tempfilename, + /* [in] */ __RPC__in_opt IStream *pIStream, + /* [in] */ BOOL fFullBuild, + /* [in] */ __RPC__in const WCHAR *finalfilename); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ ULONG32 cSig, + /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); + + HRESULT ( STDMETHODCALLTYPE *Abort )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3, + /* [in] */ ULONG32 startOffset, + /* [in] */ ULONG32 endOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ ULONG32 attributes, + /* [in] */ mdSignature sigToken, + /* [in] */ ULONG32 addrKind, + /* [in] */ ULONG32 addr1, + /* [in] */ ULONG32 addr2, + /* [in] */ ULONG32 addr3); + + HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ __RPC__in const WCHAR *name, + /* [in] */ VARIANT value, + /* [in] */ mdSignature sigToken); + + HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdMethodDef method, + /* [in] */ ULONG32 isect, + /* [in] */ ULONG32 offset); + + HRESULT ( STDMETHODCALLTYPE *Commit )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *GetDebugInfoWithPadding )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, + /* [in] */ DWORD cData, + /* [out] */ __RPC__out DWORD *pcData, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); + + HRESULT ( STDMETHODCALLTYPE *OpenMapTokensToSourceSpans )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *CloseMapTokensToSourceSpans )( + __RPC__in ISymUnmanagedWriter5 * This); + + HRESULT ( STDMETHODCALLTYPE *MapTokenToSourceSpan )( + __RPC__in ISymUnmanagedWriter5 * This, + /* [in] */ mdToken token, + /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 endLine, + /* [in] */ ULONG32 endColumn); + + END_INTERFACE + } ISymUnmanagedWriter5Vtbl; + + interface ISymUnmanagedWriter5 + { + CONST_VTBL struct ISymUnmanagedWriter5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedWriter5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedWriter5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedWriter5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedWriter5_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedWriter5_SetUserEntryPoint(This,entryMethod) \ + ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) + +#define ISymUnmanagedWriter5_OpenMethod(This,method) \ + ( (This)->lpVtbl -> OpenMethod(This,method) ) + +#define ISymUnmanagedWriter5_CloseMethod(This) \ + ( (This)->lpVtbl -> CloseMethod(This) ) + +#define ISymUnmanagedWriter5_OpenScope(This,startOffset,pRetVal) \ + ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) + +#define ISymUnmanagedWriter5_CloseScope(This,endOffset) \ + ( (This)->lpVtbl -> CloseScope(This,endOffset) ) + +#define ISymUnmanagedWriter5_SetScopeRange(This,scopeID,startOffset,endOffset) \ + ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) + +#define ISymUnmanagedWriter5_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter5_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter5_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter5_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter5_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define ISymUnmanagedWriter5_SetSymAttribute(This,parent,name,cData,data) \ + ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) + +#define ISymUnmanagedWriter5_OpenNamespace(This,name) \ + ( (This)->lpVtbl -> OpenNamespace(This,name) ) + +#define ISymUnmanagedWriter5_CloseNamespace(This) \ + ( (This)->lpVtbl -> CloseNamespace(This) ) + +#define ISymUnmanagedWriter5_UsingNamespace(This,fullName) \ + ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) + +#define ISymUnmanagedWriter5_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ + ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) + +#define ISymUnmanagedWriter5_Initialize(This,emitter,filename,pIStream,fFullBuild) \ + ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) + +#define ISymUnmanagedWriter5_GetDebugInfo(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) + +#define ISymUnmanagedWriter5_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ + ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) + +#define ISymUnmanagedWriter5_RemapToken(This,oldToken,newToken) \ + ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) + +#define ISymUnmanagedWriter5_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ + ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) + +#define ISymUnmanagedWriter5_DefineConstant(This,name,value,cSig,signature) \ + ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) + +#define ISymUnmanagedWriter5_Abort(This) \ + ( (This)->lpVtbl -> Abort(This) ) + + +#define ISymUnmanagedWriter5_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ + ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) + +#define ISymUnmanagedWriter5_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ + ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) + +#define ISymUnmanagedWriter5_DefineConstant2(This,name,value,sigToken) \ + ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) + + +#define ISymUnmanagedWriter5_OpenMethod2(This,method,isect,offset) \ + ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) + +#define ISymUnmanagedWriter5_Commit(This) \ + ( (This)->lpVtbl -> Commit(This) ) + + +#define ISymUnmanagedWriter5_GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) \ + ( (This)->lpVtbl -> GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) ) + + +#define ISymUnmanagedWriter5_OpenMapTokensToSourceSpans(This) \ + ( (This)->lpVtbl -> OpenMapTokensToSourceSpans(This) ) + +#define ISymUnmanagedWriter5_CloseMapTokensToSourceSpans(This) \ + ( (This)->lpVtbl -> CloseMapTokensToSourceSpans(This) ) + +#define ISymUnmanagedWriter5_MapTokenToSourceSpan(This,token,document,line,column,endLine,endColumn) \ + ( (This)->lpVtbl -> MapTokenToSourceSpan(This,token,document,line,column,endLine,endColumn) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedWriter5_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedReader2_INTERFACE_DEFINED__ +#define __ISymUnmanagedReader2_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedReader2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedReader2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A09E53B2-2A57-4cca-8F63-B84F7C35D4AA") + ISymUnmanagedReader2 : public ISymUnmanagedReader + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMethodByVersionPreRemap( + /* [in] */ mdMethodDef token, + /* [in] */ int version, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSymAttributePreRemap( + /* [in] */ mdToken parent, + /* [in] */ __RPC__in WCHAR *name, + /* [in] */ ULONG32 cBuffer, + /* [out] */ __RPC__out ULONG32 *pcBuffer, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodsInDocument( + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 cMethod, + /* [out] */ __RPC__out ULONG32 *pcMethod, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedReader2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedReader2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedReader2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetDocument )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in WCHAR *url, + /* [in] */ GUID language, + /* [in] */ GUID languageVendor, + /* [in] */ GUID documentType, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetDocuments )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ ULONG32 cDocs, + /* [out] */ __RPC__out ULONG32 *pcDocs, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetUserEntryPoint )( + __RPC__in ISymUnmanagedReader2 * This, + /* [retval][out] */ __RPC__out mdMethodDef *pToken); + + HRESULT ( STDMETHODCALLTYPE *GetMethod )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdMethodDef token, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetMethodByVersion )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdMethodDef token, + /* [in] */ int version, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetVariables )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdToken parent, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetGlobalVariables )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ ULONG32 cVars, + /* [out] */ __RPC__out ULONG32 *pcVars, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodFromDocumentPosition )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSymAttribute )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in WCHAR *name, + /* [in] */ ULONG32 cBuffer, + /* [out] */ __RPC__out ULONG32 *pcBuffer, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ ULONG32 cNameSpaces, + /* [out] */ __RPC__out ULONG32 *pcNameSpaces, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); + + HRESULT ( STDMETHODCALLTYPE *Initialize )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt IUnknown *importer, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in const WCHAR *searchPath, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *ReplaceSymbolStore )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in const WCHAR *filename, + /* [in] */ __RPC__in_opt IStream *pIStream); + + HRESULT ( STDMETHODCALLTYPE *GetSymbolStoreFileName )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ ULONG32 cchName, + /* [out] */ __RPC__out ULONG32 *pcchName, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodsFromDocumentPosition )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 line, + /* [in] */ ULONG32 column, + /* [in] */ ULONG32 cMethod, + /* [out] */ __RPC__out ULONG32 *pcMethod, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetDocumentVersion )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, + /* [out] */ __RPC__out int *version, + /* [out] */ __RPC__out BOOL *pbCurrent); + + HRESULT ( STDMETHODCALLTYPE *GetMethodVersion )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, + /* [out] */ __RPC__out int *version); + + HRESULT ( STDMETHODCALLTYPE *GetMethodByVersionPreRemap )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdMethodDef token, + /* [in] */ int version, + /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetSymAttributePreRemap )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ mdToken parent, + /* [in] */ __RPC__in WCHAR *name, + /* [in] */ ULONG32 cBuffer, + /* [out] */ __RPC__out ULONG32 *pcBuffer, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodsInDocument )( + __RPC__in ISymUnmanagedReader2 * This, + /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, + /* [in] */ ULONG32 cMethod, + /* [out] */ __RPC__out ULONG32 *pcMethod, + /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); + + END_INTERFACE + } ISymUnmanagedReader2Vtbl; + + interface ISymUnmanagedReader2 + { + CONST_VTBL struct ISymUnmanagedReader2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedReader2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedReader2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedReader2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedReader2_GetDocument(This,url,language,languageVendor,documentType,pRetVal) \ + ( (This)->lpVtbl -> GetDocument(This,url,language,languageVendor,documentType,pRetVal) ) + +#define ISymUnmanagedReader2_GetDocuments(This,cDocs,pcDocs,pDocs) \ + ( (This)->lpVtbl -> GetDocuments(This,cDocs,pcDocs,pDocs) ) + +#define ISymUnmanagedReader2_GetUserEntryPoint(This,pToken) \ + ( (This)->lpVtbl -> GetUserEntryPoint(This,pToken) ) + +#define ISymUnmanagedReader2_GetMethod(This,token,pRetVal) \ + ( (This)->lpVtbl -> GetMethod(This,token,pRetVal) ) + +#define ISymUnmanagedReader2_GetMethodByVersion(This,token,version,pRetVal) \ + ( (This)->lpVtbl -> GetMethodByVersion(This,token,version,pRetVal) ) + +#define ISymUnmanagedReader2_GetVariables(This,parent,cVars,pcVars,pVars) \ + ( (This)->lpVtbl -> GetVariables(This,parent,cVars,pcVars,pVars) ) + +#define ISymUnmanagedReader2_GetGlobalVariables(This,cVars,pcVars,pVars) \ + ( (This)->lpVtbl -> GetGlobalVariables(This,cVars,pcVars,pVars) ) + +#define ISymUnmanagedReader2_GetMethodFromDocumentPosition(This,document,line,column,pRetVal) \ + ( (This)->lpVtbl -> GetMethodFromDocumentPosition(This,document,line,column,pRetVal) ) + +#define ISymUnmanagedReader2_GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) \ + ( (This)->lpVtbl -> GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) ) + +#define ISymUnmanagedReader2_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ + ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) + +#define ISymUnmanagedReader2_Initialize(This,importer,filename,searchPath,pIStream) \ + ( (This)->lpVtbl -> Initialize(This,importer,filename,searchPath,pIStream) ) + +#define ISymUnmanagedReader2_UpdateSymbolStore(This,filename,pIStream) \ + ( (This)->lpVtbl -> UpdateSymbolStore(This,filename,pIStream) ) + +#define ISymUnmanagedReader2_ReplaceSymbolStore(This,filename,pIStream) \ + ( (This)->lpVtbl -> ReplaceSymbolStore(This,filename,pIStream) ) + +#define ISymUnmanagedReader2_GetSymbolStoreFileName(This,cchName,pcchName,szName) \ + ( (This)->lpVtbl -> GetSymbolStoreFileName(This,cchName,pcchName,szName) ) + +#define ISymUnmanagedReader2_GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) \ + ( (This)->lpVtbl -> GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) ) + +#define ISymUnmanagedReader2_GetDocumentVersion(This,pDoc,version,pbCurrent) \ + ( (This)->lpVtbl -> GetDocumentVersion(This,pDoc,version,pbCurrent) ) + +#define ISymUnmanagedReader2_GetMethodVersion(This,pMethod,version) \ + ( (This)->lpVtbl -> GetMethodVersion(This,pMethod,version) ) + + +#define ISymUnmanagedReader2_GetMethodByVersionPreRemap(This,token,version,pRetVal) \ + ( (This)->lpVtbl -> GetMethodByVersionPreRemap(This,token,version,pRetVal) ) + +#define ISymUnmanagedReader2_GetSymAttributePreRemap(This,parent,name,cBuffer,pcBuffer,buffer) \ + ( (This)->lpVtbl -> GetSymAttributePreRemap(This,parent,name,cBuffer,pcBuffer,buffer) ) + +#define ISymUnmanagedReader2_GetMethodsInDocument(This,document,cMethod,pcMethod,pRetVal) \ + ( (This)->lpVtbl -> GetMethodsInDocument(This,document,cMethod,pcMethod,pRetVal) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedReader2_INTERFACE_DEFINED__ */ + + +#ifndef __ISymNGenWriter_INTERFACE_DEFINED__ +#define __ISymNGenWriter_INTERFACE_DEFINED__ + +/* interface ISymNGenWriter */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymNGenWriter; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d682fd12-43de-411c-811b-be8404cea126") + ISymNGenWriter : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddSymbol( + /* [in] */ __RPC__in BSTR pSymbol, + /* [in] */ USHORT iSection, + /* [in] */ ULONGLONG rva) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddSection( + /* [in] */ USHORT iSection, + /* [in] */ USHORT flags, + /* [in] */ long offset, + /* [in] */ long cb) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymNGenWriterVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymNGenWriter * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymNGenWriter * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymNGenWriter * This); + + HRESULT ( STDMETHODCALLTYPE *AddSymbol )( + __RPC__in ISymNGenWriter * This, + /* [in] */ __RPC__in BSTR pSymbol, + /* [in] */ USHORT iSection, + /* [in] */ ULONGLONG rva); + + HRESULT ( STDMETHODCALLTYPE *AddSection )( + __RPC__in ISymNGenWriter * This, + /* [in] */ USHORT iSection, + /* [in] */ USHORT flags, + /* [in] */ long offset, + /* [in] */ long cb); + + END_INTERFACE + } ISymNGenWriterVtbl; + + interface ISymNGenWriter + { + CONST_VTBL struct ISymNGenWriterVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymNGenWriter_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymNGenWriter_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymNGenWriter_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymNGenWriter_AddSymbol(This,pSymbol,iSection,rva) \ + ( (This)->lpVtbl -> AddSymbol(This,pSymbol,iSection,rva) ) + +#define ISymNGenWriter_AddSection(This,iSection,flags,offset,cb) \ + ( (This)->lpVtbl -> AddSection(This,iSection,flags,offset,cb) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymNGenWriter_INTERFACE_DEFINED__ */ + + +#ifndef __ISymNGenWriter2_INTERFACE_DEFINED__ +#define __ISymNGenWriter2_INTERFACE_DEFINED__ + +/* interface ISymNGenWriter2 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ISymNGenWriter2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4") + ISymNGenWriter2 : public ISymNGenWriter + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenModW( + /* [in] */ const wchar_t *wszModule, + /* [in] */ const wchar_t *wszObjFile, + /* [out] */ BYTE **ppmod) = 0; + + virtual HRESULT STDMETHODCALLTYPE CloseMod( + /* [in] */ BYTE *pmod) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModAddSymbols( + /* [in] */ BYTE *pmod, + /* [in] */ BYTE *pbSym, + /* [in] */ long cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE ModAddSecContribEx( + /* [in] */ BYTE *pmod, + /* [in] */ USHORT isect, + /* [in] */ long off, + /* [in] */ long cb, + /* [in] */ ULONG dwCharacteristics, + /* [in] */ DWORD dwDataCrc, + /* [in] */ DWORD dwRelocCrc) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryPDBNameExW( + /* [size_is][out] */ wchar_t wszPDB[ ], + /* [in] */ SIZE_T cchMax) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymNGenWriter2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISymNGenWriter2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISymNGenWriter2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISymNGenWriter2 * This); + + HRESULT ( STDMETHODCALLTYPE *AddSymbol )( + ISymNGenWriter2 * This, + /* [in] */ BSTR pSymbol, + /* [in] */ USHORT iSection, + /* [in] */ ULONGLONG rva); + + HRESULT ( STDMETHODCALLTYPE *AddSection )( + ISymNGenWriter2 * This, + /* [in] */ USHORT iSection, + /* [in] */ USHORT flags, + /* [in] */ long offset, + /* [in] */ long cb); + + HRESULT ( STDMETHODCALLTYPE *OpenModW )( + ISymNGenWriter2 * This, + /* [in] */ const wchar_t *wszModule, + /* [in] */ const wchar_t *wszObjFile, + /* [out] */ BYTE **ppmod); + + HRESULT ( STDMETHODCALLTYPE *CloseMod )( + ISymNGenWriter2 * This, + /* [in] */ BYTE *pmod); + + HRESULT ( STDMETHODCALLTYPE *ModAddSymbols )( + ISymNGenWriter2 * This, + /* [in] */ BYTE *pmod, + /* [in] */ BYTE *pbSym, + /* [in] */ long cb); + + HRESULT ( STDMETHODCALLTYPE *ModAddSecContribEx )( + ISymNGenWriter2 * This, + /* [in] */ BYTE *pmod, + /* [in] */ USHORT isect, + /* [in] */ long off, + /* [in] */ long cb, + /* [in] */ ULONG dwCharacteristics, + /* [in] */ DWORD dwDataCrc, + /* [in] */ DWORD dwRelocCrc); + + HRESULT ( STDMETHODCALLTYPE *QueryPDBNameExW )( + ISymNGenWriter2 * This, + /* [size_is][out] */ wchar_t wszPDB[ ], + /* [in] */ SIZE_T cchMax); + + END_INTERFACE + } ISymNGenWriter2Vtbl; + + interface ISymNGenWriter2 + { + CONST_VTBL struct ISymNGenWriter2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymNGenWriter2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymNGenWriter2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymNGenWriter2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymNGenWriter2_AddSymbol(This,pSymbol,iSection,rva) \ + ( (This)->lpVtbl -> AddSymbol(This,pSymbol,iSection,rva) ) + +#define ISymNGenWriter2_AddSection(This,iSection,flags,offset,cb) \ + ( (This)->lpVtbl -> AddSection(This,iSection,flags,offset,cb) ) + + +#define ISymNGenWriter2_OpenModW(This,wszModule,wszObjFile,ppmod) \ + ( (This)->lpVtbl -> OpenModW(This,wszModule,wszObjFile,ppmod) ) + +#define ISymNGenWriter2_CloseMod(This,pmod) \ + ( (This)->lpVtbl -> CloseMod(This,pmod) ) + +#define ISymNGenWriter2_ModAddSymbols(This,pmod,pbSym,cb) \ + ( (This)->lpVtbl -> ModAddSymbols(This,pmod,pbSym,cb) ) + +#define ISymNGenWriter2_ModAddSecContribEx(This,pmod,isect,off,cb,dwCharacteristics,dwDataCrc,dwRelocCrc) \ + ( (This)->lpVtbl -> ModAddSecContribEx(This,pmod,isect,off,cb,dwCharacteristics,dwDataCrc,dwRelocCrc) ) + +#define ISymNGenWriter2_QueryPDBNameExW(This,wszPDB,cchMax) \ + ( (This)->lpVtbl -> QueryPDBNameExW(This,wszPDB,cchMax) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymNGenWriter2_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ +#define __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedAsyncMethodPropertiesWriter */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedAsyncMethodPropertiesWriter; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("FC073774-1739-4232-BD56-A027294BEC15") + ISymUnmanagedAsyncMethodPropertiesWriter : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE DefineKickoffMethod( + /* [in] */ mdToken kickoffMethod) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineCatchHandlerILOffset( + /* [in] */ ULONG32 catchHandlerOffset) = 0; + + virtual HRESULT STDMETHODCALLTYPE DefineAsyncStepInfo( + /* [in] */ ULONG32 count, + /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 yieldOffsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 breakpointOffset[ ], + /* [size_is][in] */ __RPC__in_ecount_full(count) mdToken breakpointMethod[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedAsyncMethodPropertiesWriterVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This); + + HRESULT ( STDMETHODCALLTYPE *DefineKickoffMethod )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, + /* [in] */ mdToken kickoffMethod); + + HRESULT ( STDMETHODCALLTYPE *DefineCatchHandlerILOffset )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, + /* [in] */ ULONG32 catchHandlerOffset); + + HRESULT ( STDMETHODCALLTYPE *DefineAsyncStepInfo )( + __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, + /* [in] */ ULONG32 count, + /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 yieldOffsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 breakpointOffset[ ], + /* [size_is][in] */ __RPC__in_ecount_full(count) mdToken breakpointMethod[ ]); + + END_INTERFACE + } ISymUnmanagedAsyncMethodPropertiesWriterVtbl; + + interface ISymUnmanagedAsyncMethodPropertiesWriter + { + CONST_VTBL struct ISymUnmanagedAsyncMethodPropertiesWriterVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedAsyncMethodPropertiesWriter_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedAsyncMethodPropertiesWriter_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedAsyncMethodPropertiesWriter_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedAsyncMethodPropertiesWriter_DefineKickoffMethod(This,kickoffMethod) \ + ( (This)->lpVtbl -> DefineKickoffMethod(This,kickoffMethod) ) + +#define ISymUnmanagedAsyncMethodPropertiesWriter_DefineCatchHandlerILOffset(This,catchHandlerOffset) \ + ( (This)->lpVtbl -> DefineCatchHandlerILOffset(This,catchHandlerOffset) ) + +#define ISymUnmanagedAsyncMethodPropertiesWriter_DefineAsyncStepInfo(This,count,yieldOffsets,breakpointOffset,breakpointMethod) \ + ( (This)->lpVtbl -> DefineAsyncStepInfo(This,count,yieldOffsets,breakpointOffset,breakpointMethod) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ */ + + +#ifndef __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ +#define __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ + +/* interface ISymUnmanagedAsyncMethod */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ISymUnmanagedAsyncMethod; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B20D55B3-532E-4906-87E7-25BD5734ABD2") + ISymUnmanagedAsyncMethod : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE IsAsyncMethod( + /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetKickoffMethod( + /* [retval][out] */ __RPC__out mdToken *kickoffMethod) = 0; + + virtual HRESULT STDMETHODCALLTYPE HasCatchHandlerILOffset( + /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCatchHandlerILOffset( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAsyncStepInfoCount( + /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAsyncStepInfo( + /* [in] */ ULONG32 cStepInfo, + /* [out] */ __RPC__out ULONG32 *pcStepInfo, + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 yieldOffsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 breakpointOffset[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) mdToken breakpointMethod[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISymUnmanagedAsyncMethodVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [in] */ __RPC__in REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in ISymUnmanagedAsyncMethod * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in ISymUnmanagedAsyncMethod * This); + + HRESULT ( STDMETHODCALLTYPE *IsAsyncMethod )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [retval][out] */ __RPC__out BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetKickoffMethod )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [retval][out] */ __RPC__out mdToken *kickoffMethod); + + HRESULT ( STDMETHODCALLTYPE *HasCatchHandlerILOffset )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [retval][out] */ __RPC__out BOOL *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetCatchHandlerILOffset )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetAsyncStepInfoCount )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [retval][out] */ __RPC__out ULONG32 *pRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetAsyncStepInfo )( + __RPC__in ISymUnmanagedAsyncMethod * This, + /* [in] */ ULONG32 cStepInfo, + /* [out] */ __RPC__out ULONG32 *pcStepInfo, + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 yieldOffsets[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 breakpointOffset[ ], + /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) mdToken breakpointMethod[ ]); + + END_INTERFACE + } ISymUnmanagedAsyncMethodVtbl; + + interface ISymUnmanagedAsyncMethod + { + CONST_VTBL struct ISymUnmanagedAsyncMethodVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISymUnmanagedAsyncMethod_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISymUnmanagedAsyncMethod_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISymUnmanagedAsyncMethod_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISymUnmanagedAsyncMethod_IsAsyncMethod(This,pRetVal) \ + ( (This)->lpVtbl -> IsAsyncMethod(This,pRetVal) ) + +#define ISymUnmanagedAsyncMethod_GetKickoffMethod(This,kickoffMethod) \ + ( (This)->lpVtbl -> GetKickoffMethod(This,kickoffMethod) ) + +#define ISymUnmanagedAsyncMethod_HasCatchHandlerILOffset(This,pRetVal) \ + ( (This)->lpVtbl -> HasCatchHandlerILOffset(This,pRetVal) ) + +#define ISymUnmanagedAsyncMethod_GetCatchHandlerILOffset(This,pRetVal) \ + ( (This)->lpVtbl -> GetCatchHandlerILOffset(This,pRetVal) ) + +#define ISymUnmanagedAsyncMethod_GetAsyncStepInfoCount(This,pRetVal) \ + ( (This)->lpVtbl -> GetAsyncStepInfoCount(This,pRetVal) ) + +#define ISymUnmanagedAsyncMethod_GetAsyncStepInfo(This,cStepInfo,pcStepInfo,yieldOffsets,breakpointOffset,breakpointMethod) \ + ( (This)->lpVtbl -> GetAsyncStepInfo(This,cStepInfo,pcStepInfo,yieldOffsets,breakpointOffset,breakpointMethod) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER BSTR_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in BSTR * ); +unsigned char * __RPC_USER BSTR_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in BSTR * ); +unsigned char * __RPC_USER BSTR_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out BSTR * ); +void __RPC_USER BSTR_UserFree( __RPC__in unsigned long *, __RPC__in BSTR * ); + +unsigned long __RPC_USER VARIANT_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in VARIANT * ); +unsigned char * __RPC_USER VARIANT_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out VARIANT * ); +void __RPC_USER VARIANT_UserFree( __RPC__in unsigned long *, __RPC__in VARIANT * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/fusion.h b/lib/coreclr/src/pal/prebuilt/inc/fusion.h new file mode 100644 index 0000000000..b7a577016a --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/fusion.h @@ -0,0 +1,407 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __fusion_h__ +#define __fusion_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IAssemblyName_FWD_DEFINED__ +#define __IAssemblyName_FWD_DEFINED__ +typedef interface IAssemblyName IAssemblyName; + +#endif /* __IAssemblyName_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "objidl.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_fusion_0000_0000 */ +/* [local] */ + + +#ifdef _MSC_VER +#pragma comment(lib,"uuid.lib") +#endif + +//---------------------------------------------------------------------------= +// Fusion Interfaces. + +#ifdef _MSC_VER +#pragma once +#endif + + + + +#ifndef PEKIND_ENUM_DEFINED +#define PEKIND_ENUM_DEFINED +typedef +enum _tagPEKIND + { + peNone = 0, + peMSIL = 0x1, + peI386 = 0x2, + peIA64 = 0x3, + peAMD64 = 0x4, + peARM = 0x5, + peARM64 = 0x6, + peInvalid = 0xffffffff + } PEKIND; + +#endif +typedef +enum _tagAssemblyContentType + { + AssemblyContentType_Default = 0, + AssemblyContentType_WindowsRuntime = 0x1, + AssemblyContentType_Invalid = 0xffffffff + } AssemblyContentType; + +// {CD193BC0-B4BC-11d2-9833-00C04FC31D2E} +EXTERN_GUID(IID_IAssemblyName, 0xCD193BC0, 0xB4BC, 0x11d2, 0x98, 0x33, 0x00, 0xC0, 0x4F, 0xC3, 0x1D, 0x2E); + + +extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0000_v0_0_s_ifspec; + +#ifndef __IAssemblyName_INTERFACE_DEFINED__ +#define __IAssemblyName_INTERFACE_DEFINED__ + +/* interface IAssemblyName */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ IAssemblyName *LPASSEMBLYNAME; + +typedef /* [public] */ +enum __MIDL_IAssemblyName_0001 + { + CANOF_PARSE_DISPLAY_NAME = 0x1, + CANOF_SET_DEFAULT_VALUES = 0x2, + CANOF_VERIFY_FRIEND_ASSEMBLYNAME = 0x4, + CANOF_PARSE_FRIEND_DISPLAY_NAME = ( CANOF_PARSE_DISPLAY_NAME | CANOF_VERIFY_FRIEND_ASSEMBLYNAME ) + } CREATE_ASM_NAME_OBJ_FLAGS; + +typedef /* [public] */ +enum __MIDL_IAssemblyName_0002 + { + ASM_NAME_PUBLIC_KEY = 0, + ASM_NAME_PUBLIC_KEY_TOKEN = ( ASM_NAME_PUBLIC_KEY + 1 ) , + ASM_NAME_HASH_VALUE = ( ASM_NAME_PUBLIC_KEY_TOKEN + 1 ) , + ASM_NAME_NAME = ( ASM_NAME_HASH_VALUE + 1 ) , + ASM_NAME_MAJOR_VERSION = ( ASM_NAME_NAME + 1 ) , + ASM_NAME_MINOR_VERSION = ( ASM_NAME_MAJOR_VERSION + 1 ) , + ASM_NAME_BUILD_NUMBER = ( ASM_NAME_MINOR_VERSION + 1 ) , + ASM_NAME_REVISION_NUMBER = ( ASM_NAME_BUILD_NUMBER + 1 ) , + ASM_NAME_CULTURE = ( ASM_NAME_REVISION_NUMBER + 1 ) , + ASM_NAME_PROCESSOR_ID_ARRAY = ( ASM_NAME_CULTURE + 1 ) , + ASM_NAME_OSINFO_ARRAY = ( ASM_NAME_PROCESSOR_ID_ARRAY + 1 ) , + ASM_NAME_HASH_ALGID = ( ASM_NAME_OSINFO_ARRAY + 1 ) , + ASM_NAME_ALIAS = ( ASM_NAME_HASH_ALGID + 1 ) , + ASM_NAME_CODEBASE_URL = ( ASM_NAME_ALIAS + 1 ) , + ASM_NAME_CODEBASE_LASTMOD = ( ASM_NAME_CODEBASE_URL + 1 ) , + ASM_NAME_NULL_PUBLIC_KEY = ( ASM_NAME_CODEBASE_LASTMOD + 1 ) , + ASM_NAME_NULL_PUBLIC_KEY_TOKEN = ( ASM_NAME_NULL_PUBLIC_KEY + 1 ) , + ASM_NAME_CUSTOM = ( ASM_NAME_NULL_PUBLIC_KEY_TOKEN + 1 ) , + ASM_NAME_NULL_CUSTOM = ( ASM_NAME_CUSTOM + 1 ) , + ASM_NAME_MVID = ( ASM_NAME_NULL_CUSTOM + 1 ) , + ASM_NAME_FILE_MAJOR_VERSION = ( ASM_NAME_MVID + 1 ) , + ASM_NAME_FILE_MINOR_VERSION = ( ASM_NAME_FILE_MAJOR_VERSION + 1 ) , + ASM_NAME_FILE_BUILD_NUMBER = ( ASM_NAME_FILE_MINOR_VERSION + 1 ) , + ASM_NAME_FILE_REVISION_NUMBER = ( ASM_NAME_FILE_BUILD_NUMBER + 1 ) , + ASM_NAME_RETARGET = ( ASM_NAME_FILE_REVISION_NUMBER + 1 ) , + ASM_NAME_SIGNATURE_BLOB = ( ASM_NAME_RETARGET + 1 ) , + ASM_NAME_CONFIG_MASK = ( ASM_NAME_SIGNATURE_BLOB + 1 ) , + ASM_NAME_ARCHITECTURE = ( ASM_NAME_CONFIG_MASK + 1 ) , + ASM_NAME_CONTENT_TYPE = ( ASM_NAME_ARCHITECTURE + 1 ) , + ASM_NAME_MAX_PARAMS = ( ASM_NAME_CONTENT_TYPE + 1 ) + } ASM_NAME; + +typedef /* [public] */ +enum __MIDL_IAssemblyName_0003 + { + ASM_DISPLAYF_VERSION = 0x1, + ASM_DISPLAYF_CULTURE = 0x2, + ASM_DISPLAYF_PUBLIC_KEY_TOKEN = 0x4, + ASM_DISPLAYF_PUBLIC_KEY = 0x8, + ASM_DISPLAYF_CUSTOM = 0x10, + ASM_DISPLAYF_PROCESSORARCHITECTURE = 0x20, + ASM_DISPLAYF_LANGUAGEID = 0x40, + ASM_DISPLAYF_RETARGET = 0x80, + ASM_DISPLAYF_CONFIG_MASK = 0x100, + ASM_DISPLAYF_MVID = 0x200, + ASM_DISPLAYF_CONTENT_TYPE = 0x400, + ASM_DISPLAYF_FULL = ( ( ( ( ( ASM_DISPLAYF_VERSION | ASM_DISPLAYF_CULTURE ) | ASM_DISPLAYF_PUBLIC_KEY_TOKEN ) | ASM_DISPLAYF_RETARGET ) | ASM_DISPLAYF_PROCESSORARCHITECTURE ) | ASM_DISPLAYF_CONTENT_TYPE ) + } ASM_DISPLAY_FLAGS; + +typedef /* [public] */ +enum __MIDL_IAssemblyName_0004 + { + ASM_CMPF_NAME = 0x1, + ASM_CMPF_MAJOR_VERSION = 0x2, + ASM_CMPF_MINOR_VERSION = 0x4, + ASM_CMPF_BUILD_NUMBER = 0x8, + ASM_CMPF_REVISION_NUMBER = 0x10, + ASM_CMPF_VERSION = ( ( ( ASM_CMPF_MAJOR_VERSION | ASM_CMPF_MINOR_VERSION ) | ASM_CMPF_BUILD_NUMBER ) | ASM_CMPF_REVISION_NUMBER ) , + ASM_CMPF_PUBLIC_KEY_TOKEN = 0x20, + ASM_CMPF_CULTURE = 0x40, + ASM_CMPF_CUSTOM = 0x80, + ASM_CMPF_DEFAULT = 0x100, + ASM_CMPF_RETARGET = 0x200, + ASM_CMPF_ARCHITECTURE = 0x400, + ASM_CMPF_CONFIG_MASK = 0x800, + ASM_CMPF_MVID = 0x1000, + ASM_CMPF_SIGNATURE = 0x2000, + ASM_CMPF_CONTENT_TYPE = 0x4000, + ASM_CMPF_IL_ALL = ( ( ( ASM_CMPF_NAME | ASM_CMPF_VERSION ) | ASM_CMPF_PUBLIC_KEY_TOKEN ) | ASM_CMPF_CULTURE ) , + ASM_CMPF_IL_NO_VERSION = ( ( ASM_CMPF_NAME | ASM_CMPF_PUBLIC_KEY_TOKEN ) | ASM_CMPF_CULTURE ) + } ASM_CMP_FLAGS; + + +EXTERN_C const IID IID_IAssemblyName; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("CD193BC0-B4BC-11d2-9833-00C04FC31D2E") + IAssemblyName : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProperty( + /* [in] */ DWORD PropertyId, + /* [in] */ const void *pvProperty, + /* [in] */ DWORD cbProperty) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProperty( + /* [in] */ DWORD PropertyId, + /* [out] */ LPVOID pvProperty, + /* [out][in] */ LPDWORD pcbProperty) = 0; + + virtual HRESULT STDMETHODCALLTYPE Finalize( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDisplayName( + /* [annotation][out] */ + _Out_writes_opt_(*pccDisplayName) LPOLESTR szDisplayName, + /* [out][in] */ LPDWORD pccDisplayName, + /* [in] */ DWORD dwDisplayFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reserved( + /* [in] */ REFIID refIID, + /* [in] */ IUnknown *pUnkReserved1, + /* [in] */ IUnknown *pUnkReserved2, + /* [in] */ LPCOLESTR szReserved, + /* [in] */ LONGLONG llReserved, + /* [in] */ LPVOID pvReserved, + /* [in] */ DWORD cbReserved, + /* [out] */ LPVOID *ppReserved) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [annotation][out][in] */ + _Inout_ LPDWORD lpcwBuffer, + /* [annotation][out] */ + _Out_writes_opt_(*lpcwBuffer) WCHAR *pwzName) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersion( + /* [out] */ LPDWORD pdwVersionHi, + /* [out] */ LPDWORD pdwVersionLow) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsEqual( + /* [in] */ IAssemblyName *pName, + /* [in] */ DWORD dwCmpFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IAssemblyName **pName) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IAssemblyNameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAssemblyName * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAssemblyName * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAssemblyName * This); + + HRESULT ( STDMETHODCALLTYPE *SetProperty )( + IAssemblyName * This, + /* [in] */ DWORD PropertyId, + /* [in] */ const void *pvProperty, + /* [in] */ DWORD cbProperty); + + HRESULT ( STDMETHODCALLTYPE *GetProperty )( + IAssemblyName * This, + /* [in] */ DWORD PropertyId, + /* [out] */ LPVOID pvProperty, + /* [out][in] */ LPDWORD pcbProperty); + + HRESULT ( STDMETHODCALLTYPE *Finalize )( + IAssemblyName * This); + + HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( + IAssemblyName * This, + /* [annotation][out] */ + _Out_writes_opt_(*pccDisplayName) LPOLESTR szDisplayName, + /* [out][in] */ LPDWORD pccDisplayName, + /* [in] */ DWORD dwDisplayFlags); + + HRESULT ( STDMETHODCALLTYPE *Reserved )( + IAssemblyName * This, + /* [in] */ REFIID refIID, + /* [in] */ IUnknown *pUnkReserved1, + /* [in] */ IUnknown *pUnkReserved2, + /* [in] */ LPCOLESTR szReserved, + /* [in] */ LONGLONG llReserved, + /* [in] */ LPVOID pvReserved, + /* [in] */ DWORD cbReserved, + /* [out] */ LPVOID *ppReserved); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IAssemblyName * This, + /* [annotation][out][in] */ + _Inout_ LPDWORD lpcwBuffer, + /* [annotation][out] */ + _Out_writes_opt_(*lpcwBuffer) WCHAR *pwzName); + + HRESULT ( STDMETHODCALLTYPE *GetVersion )( + IAssemblyName * This, + /* [out] */ LPDWORD pdwVersionHi, + /* [out] */ LPDWORD pdwVersionLow); + + HRESULT ( STDMETHODCALLTYPE *IsEqual )( + IAssemblyName * This, + /* [in] */ IAssemblyName *pName, + /* [in] */ DWORD dwCmpFlags); + + HRESULT ( STDMETHODCALLTYPE *Clone )( + IAssemblyName * This, + /* [out] */ IAssemblyName **pName); + + END_INTERFACE + } IAssemblyNameVtbl; + + interface IAssemblyName + { + CONST_VTBL struct IAssemblyNameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAssemblyName_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IAssemblyName_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IAssemblyName_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IAssemblyName_SetProperty(This,PropertyId,pvProperty,cbProperty) \ + ( (This)->lpVtbl -> SetProperty(This,PropertyId,pvProperty,cbProperty) ) + +#define IAssemblyName_GetProperty(This,PropertyId,pvProperty,pcbProperty) \ + ( (This)->lpVtbl -> GetProperty(This,PropertyId,pvProperty,pcbProperty) ) + +#define IAssemblyName_Finalize(This) \ + ( (This)->lpVtbl -> Finalize(This) ) + +#define IAssemblyName_GetDisplayName(This,szDisplayName,pccDisplayName,dwDisplayFlags) \ + ( (This)->lpVtbl -> GetDisplayName(This,szDisplayName,pccDisplayName,dwDisplayFlags) ) + +#define IAssemblyName_Reserved(This,refIID,pUnkReserved1,pUnkReserved2,szReserved,llReserved,pvReserved,cbReserved,ppReserved) \ + ( (This)->lpVtbl -> Reserved(This,refIID,pUnkReserved1,pUnkReserved2,szReserved,llReserved,pvReserved,cbReserved,ppReserved) ) + +#define IAssemblyName_GetName(This,lpcwBuffer,pwzName) \ + ( (This)->lpVtbl -> GetName(This,lpcwBuffer,pwzName) ) + +#define IAssemblyName_GetVersion(This,pdwVersionHi,pdwVersionLow) \ + ( (This)->lpVtbl -> GetVersion(This,pdwVersionHi,pdwVersionLow) ) + +#define IAssemblyName_IsEqual(This,pName,dwCmpFlags) \ + ( (This)->lpVtbl -> IsEqual(This,pName,dwCmpFlags) ) + +#define IAssemblyName_Clone(This,pName) \ + ( (This)->lpVtbl -> Clone(This,pName) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IAssemblyName_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_fusion_0000_0001 */ +/* [local] */ + +STDAPI CreateAssemblyNameObject(LPASSEMBLYNAME *ppAssemblyNameObj, LPCWSTR szAssemblyName, DWORD dwFlags, LPVOID pvReserved); + + +extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_fusion_0000_0001_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/fxver.h b/lib/coreclr/src/pal/prebuilt/inc/fxver.h new file mode 100644 index 0000000000..95ccbc6335 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/fxver.h @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// Insert just the #defines in winver.h, so that the +// C# compiler can include this file after macro preprocessing. +// + +#ifdef __cplusplus +#ifndef FXVER_H_ +#define FXVER_H_ +#define INCLUDE_FXVER_H +#endif +#else +#define RC_INVOKED 1 +#define INCLUDE_FXVER_H +#endif + +#ifdef INCLUDE_FXVER_H +#undef INCLUDE_FXVER_H + +#ifndef RC_INVOKED +#define FXVER_H_RC_INVOKED_ENABLED +#define RC_INVOKED 1 +#endif + +#include + +#ifdef FXVER_H_RC_INVOKED_ENABLED +#undef RC_INVOKED +#undef FXVER_H_RC_INVOKED_ENABLED +#endif + +// +// Include the definitions for rmj, rmm, rup, rpt +// + +#include + +/* + * Product version, name and copyright + */ + +#include "fxverstrings.h" + +/* + * File version, names, description. + */ + +// FX_VER_INTERNALNAME_STR is passed in by the build environment. +#ifndef FX_VER_INTERNALNAME_STR +#define FX_VER_INTERNALNAME_STR UNKNOWN_FILE +#endif + +#define VER_INTERNALNAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) +#define VER_ORIGINALFILENAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) + +// FX_VER_FILEDESCRIPTION_STR is defined in RC files that include fxver.h + +#ifndef FX_VER_FILEDESCRIPTION_STR +#define FX_VER_FILEDESCRIPTION_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) +#endif + +#define VER_FILEDESCRIPTION_STR FX_VER_FILEDESCRIPTION_STR + +#ifndef FX_VER_FILEVERSION_STR +#define FX_VER_FILEVERSION_STR FX_FILEVERSION_STR +#endif + +#define VER_FILEVERSION_STR FX_VER_FILEVERSION_STR +#define VER_FILEVERSION_STR_L VER_PRODUCTVERSION_STR_L + +#ifndef FX_VER_FILEVERSION +#define FX_VER_FILEVERSION VER_DOTFILEVERSION +#endif + +#define VER_FILEVERSION FX_VER_FILEVERSION + +//URT_VFT passed in by the build environment. +#ifndef FX_VFT +#define FX_VFT VFT_UNKNOWN +#endif + +#define VER_FILETYPE FX_VFT +#define VER_FILESUBTYPE VFT2_UNKNOWN + +/* default is nodebug */ +#if DBG +#define VER_DEBUG VS_FF_DEBUG +#else +#define VER_DEBUG 0 +#endif + +#define VER_PRERELEASE 0 + +#define EXPORT_TAG + +// Not setting the private build flag until +// official builds can be detected from native projects +//#if OFFICIAL_BUILD +#define VER_PRIVATE 0 +//#else +//#define VER_PRIVATE VS_FF_PRIVATEBUILD +//#endif + +#define VER_SPECIALBUILD 0 + +#define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#define VER_FILEFLAGS (VER_PRERELEASE|VER_DEBUG|VER_PRIVATE|VER_SPECIALBUILD) +#define VER_FILEOS VOS__WINDOWS32 + +#define VER_COMPANYNAME_STR "Microsoft Corporation" + +#ifdef VER_LANGNEUTRAL +#define VER_VERSION_UNICODE_LANG "000004B0" /* LANG_NEUTRAL/SUBLANG_NEUTRAL, Unicode CP */ +#define VER_VERSION_ANSI_LANG "000004E4" /* LANG_NEUTRAL/SUBLANG_NEUTRAL, Ansi CP */ +#define VER_VERSION_TRANSLATION 0x0000, 0x04B0 +#else +#define VER_VERSION_UNICODE_LANG "040904B0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ +#define VER_VERSION_ANSI_LANG "040904E4" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Ansi CP */ +#define VER_VERSION_TRANSLATION 0x0409, 0x04B0 +#endif + +#if defined(CSC_INVOKED) +#define VER_COMMENTS_STR "Flavor=" + QUOTE_MACRO(URTBLDENV_FRIENDLY) +#else +#define VER_COMMENTS_STR "Flavor=" QUOTE_MACRO(URTBLDENV_FRIENDLY) +#endif + +#if defined(__BUILDMACHINE__) +#if defined(__BUILDDATE__) +#define B2(x,y) " (" #x "." #y ")" +#define B1(x,y) B2(x, y) +#define BUILD_MACHINE_TAG B1(__BUILDMACHINE__, __BUILDDATE__) +#else +#define B2(x) " built by: " #x +#define B1(x) B2(x) +#define BUILD_MACHINE_TAG B1(__BUILDMACHINE__) +#endif +#if defined(__BUILDMACHINE_LEN__) +#if __BUILDMACHINE_LEN__ >= 25 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG +#elif __BUILDMACHINE_LEN__ == 24 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 23 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 22 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 21 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 20 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 19 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 18 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 17 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 16 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 15 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 14 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 13 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 12 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 11 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 10 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 9 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 8 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 7 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 6 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 5 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 4 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 3 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 2 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#elif __BUILDMACHINE_LEN__ == 1 +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG " " +#else +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG +#endif +#else +#define BUILD_MACHINE_TAG_PADDED BUILD_MACHINE_TAG +#endif +#else +#define BUILD_MACHINE_TAG +#define BUILD_MACHINE_TAG_PADDED +#endif + +#endif diff --git a/lib/coreclr/src/pal/prebuilt/inc/fxver.rc b/lib/coreclr/src/pal/prebuilt/inc/fxver.rc new file mode 100644 index 0000000000..ab037e78de --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/fxver.rc @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +/*---------------------------------------------------------------*/ +/* */ +/* The following section actually creates the version structure. */ +/* They are ignored if we are not being invoked by RC. */ +/* */ +/* ntverp.H must be included before including this file */ +/* */ +/* If VER_LEGALCOPYRIGHT_STR is not defined, it will be */ +/* constructed using VER_LEGALCOPYRIGHT_YEARS, so at least one */ +/* these macros must be defined before including this file. */ +/* */ +/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR, and */ +/* VER_INTERNALNAME_STR must be defined before including this */ +/* file. */ +/* */ +/* If VER_FILEVERSION is not defined, VER_PRODUCTVERSION will be */ +/* used instead. If VER_FILEVERSION_STR is not defined, */ +/* VER_PRODUCTVERSION_STR will be used instead. */ +/* */ +/* If VER_ORIGINALFILENAME_STR is not defined, it is set to */ +/* the value in VER_INTERNALNAME_STR. */ +/* */ +/* If INTL is defined, then this is assumed to be an */ +/* an international build; two string blocks will be created, */ +/* (since all version resources must have English), and the */ +/* second one can be localized */ +/* */ +/*---------------------------------------------------------------*/ + +#ifdef _WIN32 +#include <_version.h> +#endif //_WIN32 + +#ifdef RC_INVOKED + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VER_FILEFLAGSMASK +FILEFLAGS VER_FILEFLAGS +FILEOS VER_FILEOS +FILETYPE VER_FILETYPE +FILESUBTYPE VER_FILESUBTYPE +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK VER_VERSION_UNICODE_LANG + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG + VALUE "FileVersion", VER_FILEVERSION_STR BUILD_MACHINE_TAG_PADDED + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_FILEVERSION_STR +#ifdef VER_OLESELFREGISTER + VALUE "OleSelfRegister", "\0" +#endif + VALUE "Comments", VER_COMMENTS_STR +#ifdef VER_EXTRA_VALUES + VER_EXTRA_VALUES +#endif + + END + + +#ifdef VER_ANSICP /* Some apps are hard coded to look for ANSI CP. */ + BLOCK VER_VERSION_ANSI_LANG + BEGIN + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR EXPORT_TAG + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_FILEVERSION_STR +#ifdef VER_OLESELFREGISTER + VALUE "OleSelfRegister", "\0" +#endif + VALUE "Comments", VER_COMMENTS_STR +#ifdef VER_EXTRA_VALUES + VER_EXTRA_VALUES +#endif + END +#endif + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", VER_VERSION_TRANSLATION + END +END + +#endif diff --git a/lib/coreclr/src/pal/prebuilt/inc/fxverstrings.h b/lib/coreclr/src/pal/prebuilt/inc/fxverstrings.h new file mode 100644 index 0000000000..cafcbadf30 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/fxverstrings.h @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#ifndef VER_PRODUCTNAME_STR + #define VER_PRODUCTNAME_STR L"Microsoft\256 .NET Core" +#endif + +#ifndef VER_LEGALCOPYRIGHT_STR + #define VER_LEGALCOPYRIGHT_STR "\251 Microsoft Corporation. All rights reserved." + #define VER_LEGALCOPYRIGHT_STR_L L"\251 Microsoft Corporation. All rights reserved." +#endif + +#ifndef VER_LEGALCOPYRIGHT_LOGO_STR + #define VER_LEGALCOPYRIGHT_LOGO_STR "Copyright (c) Microsoft Corporation. All rights reserved." + #define VER_LEGALCOPYRIGHT_LOGO_STR_L L"Copyright (c) Microsoft Corporation. All rights reserved." +#endif diff --git a/lib/coreclr/src/pal/prebuilt/inc/metahost.h b/lib/coreclr/src/pal/prebuilt/inc/metahost.h new file mode 100644 index 0000000000..aae25d70db --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/metahost.h @@ -0,0 +1,809 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for metahost.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __metahost_h__ +#define __metahost_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICLRMetaHost_FWD_DEFINED__ +#define __ICLRMetaHost_FWD_DEFINED__ +typedef interface ICLRMetaHost ICLRMetaHost; + +#endif /* __ICLRMetaHost_FWD_DEFINED__ */ + + +#ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +#define __ICLRDebuggingLibraryProvider_FWD_DEFINED__ +typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider; + +#endif /* __ICLRDebuggingLibraryProvider_FWD_DEFINED__ */ + + +#ifndef __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ +#define __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ +typedef interface ICLRDebuggingLibraryProvider2 ICLRDebuggingLibraryProvider2; + +#endif /* __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ */ + + +#ifndef __ICLRDebugging_FWD_DEFINED__ +#define __ICLRDebugging_FWD_DEFINED__ +typedef interface ICLRDebugging ICLRDebugging; + +#endif /* __ICLRDebugging_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeInfo_FWD_DEFINED__ +#define __ICLRRuntimeInfo_FWD_DEFINED__ +typedef interface ICLRRuntimeInfo ICLRRuntimeInfo; + +#endif /* __ICLRRuntimeInfo_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "oaidl.h" +#include "ocidl.h" +#include "mscoree.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_metahost_0000_0000 */ +/* [local] */ + +#include +STDAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, /*iid_is(riid)*/ LPVOID *ppInterface); +EXTERN_GUID(IID_ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16); +EXTERN_GUID(CLSID_CLRMetaHost, 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde); +EXTERN_GUID(IID_ICLRDebugging, 0xd28f3c5a, 0x9634, 0x4206, 0xa5, 0x9, 0x47, 0x75, 0x52, 0xee, 0xfb, 0x10); +EXTERN_GUID(CLSID_CLRDebugging, 0xbacc578d, 0xfbdd, 0x48a4, 0x96, 0x9f, 0x2, 0xd9, 0x32, 0xb7, 0x46, 0x34); +EXTERN_GUID(IID_ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91); +EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51); +EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA); + +typedef HRESULT ( __stdcall *CallbackThreadSetFnPtr )( void); + +typedef HRESULT ( __stdcall *CallbackThreadUnsetFnPtr )( void); + +typedef void ( __stdcall *RuntimeLoadedCallbackFnPtr )( + ICLRRuntimeInfo *pRuntimeInfo, + CallbackThreadSetFnPtr pfnCallbackThreadSet, + CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); + + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_s_ifspec; + +#ifndef __ICLRMetaHost_INTERFACE_DEFINED__ +#define __ICLRMetaHost_INTERFACE_DEFINED__ + +/* interface ICLRMetaHost */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRMetaHost; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D332DB9E-B9B3-4125-8207-A14884F53216") + ICLRMetaHost : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRuntime( + /* [in] */ LPCWSTR pwzVersion, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionFromFile( + /* [in] */ LPCWSTR pwzFilePath, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateInstalledRuntimes( + /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateLoadedRuntimes( + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; + + virtual HRESULT STDMETHODCALLTYPE RequestRuntimeLoadedNotification( + /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryLegacyV2RuntimeBinding( + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExitProcess( + /* [in] */ INT32 iExitCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRMetaHostVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRMetaHost * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRMetaHost * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRMetaHost * This); + + HRESULT ( STDMETHODCALLTYPE *GetRuntime )( + ICLRMetaHost * This, + /* [in] */ LPCWSTR pwzVersion, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppRuntime); + + HRESULT ( STDMETHODCALLTYPE *GetVersionFromFile )( + ICLRMetaHost * This, + /* [in] */ LPCWSTR pwzFilePath, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *EnumerateInstalledRuntimes )( + ICLRMetaHost * This, + /* [retval][out] */ IEnumUnknown **ppEnumerator); + + HRESULT ( STDMETHODCALLTYPE *EnumerateLoadedRuntimes )( + ICLRMetaHost * This, + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ IEnumUnknown **ppEnumerator); + + HRESULT ( STDMETHODCALLTYPE *RequestRuntimeLoadedNotification )( + ICLRMetaHost * This, + /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction); + + HRESULT ( STDMETHODCALLTYPE *QueryLegacyV2RuntimeBinding )( + ICLRMetaHost * This, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk); + + HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + ICLRMetaHost * This, + /* [in] */ INT32 iExitCode); + + END_INTERFACE + } ICLRMetaHostVtbl; + + interface ICLRMetaHost + { + CONST_VTBL struct ICLRMetaHostVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRMetaHost_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRMetaHost_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRMetaHost_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRMetaHost_GetRuntime(This,pwzVersion,riid,ppRuntime) \ + ( (This)->lpVtbl -> GetRuntime(This,pwzVersion,riid,ppRuntime) ) + +#define ICLRMetaHost_GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) ) + +#define ICLRMetaHost_EnumerateInstalledRuntimes(This,ppEnumerator) \ + ( (This)->lpVtbl -> EnumerateInstalledRuntimes(This,ppEnumerator) ) + +#define ICLRMetaHost_EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) \ + ( (This)->lpVtbl -> EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) ) + +#define ICLRMetaHost_RequestRuntimeLoadedNotification(This,pCallbackFunction) \ + ( (This)->lpVtbl -> RequestRuntimeLoadedNotification(This,pCallbackFunction) ) + +#define ICLRMetaHost_QueryLegacyV2RuntimeBinding(This,riid,ppUnk) \ + ( (This)->lpVtbl -> QueryLegacyV2RuntimeBinding(This,riid,ppUnk) ) + +#define ICLRMetaHost_ExitProcess(This,iExitCode) \ + ( (This)->lpVtbl -> ExitProcess(This,iExitCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRMetaHost_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_metahost_0000_0001 */ +/* [local] */ + +typedef struct _CLR_DEBUGGING_VERSION + { + WORD wStructVersion; + WORD wMajor; + WORD wMinor; + WORD wBuild; + WORD wRevision; + } CLR_DEBUGGING_VERSION; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_metahost_0000_0001_0001 + { + CLR_DEBUGGING_MANAGED_EVENT_PENDING = 1, + CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH = 2 + } CLR_DEBUGGING_PROCESS_FLAGS; + + + +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_s_ifspec; + +#ifndef __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ +#define __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ + +/* interface ICLRDebuggingLibraryProvider */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebuggingLibraryProvider; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3151C08D-4D09-4f9b-8838-2880BF18FE51") + ICLRDebuggingLibraryProvider : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ProvideLibrary( + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ HMODULE *phModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingLibraryProviderVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebuggingLibraryProvider * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebuggingLibraryProvider * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebuggingLibraryProvider * This); + + HRESULT ( STDMETHODCALLTYPE *ProvideLibrary )( + ICLRDebuggingLibraryProvider * This, + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ HMODULE *phModule); + + END_INTERFACE + } ICLRDebuggingLibraryProviderVtbl; + + interface ICLRDebuggingLibraryProvider + { + CONST_VTBL struct ICLRDebuggingLibraryProviderVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebuggingLibraryProvider_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebuggingLibraryProvider_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebuggingLibraryProvider_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebuggingLibraryProvider_ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) \ + ( (This)->lpVtbl -> ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ +#define __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ + +/* interface ICLRDebuggingLibraryProvider2 */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebuggingLibraryProvider2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA") + ICLRDebuggingLibraryProvider2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ProvideLibrary2( + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ LPWSTR *ppResolvedModulePath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingLibraryProvider2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebuggingLibraryProvider2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebuggingLibraryProvider2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebuggingLibraryProvider2 * This); + + HRESULT ( STDMETHODCALLTYPE *ProvideLibrary2 )( + ICLRDebuggingLibraryProvider2 * This, + /* [in] */ const WCHAR *pwszFileName, + /* [in] */ DWORD dwTimestamp, + /* [in] */ DWORD dwSizeOfImage, + /* [out] */ LPWSTR *ppResolvedModulePath); + + END_INTERFACE + } ICLRDebuggingLibraryProvider2Vtbl; + + interface ICLRDebuggingLibraryProvider2 + { + CONST_VTBL struct ICLRDebuggingLibraryProvider2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebuggingLibraryProvider2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebuggingLibraryProvider2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebuggingLibraryProvider2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebuggingLibraryProvider2_ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) \ + ( (This)->lpVtbl -> ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRDebugging_INTERFACE_DEFINED__ +#define __ICLRDebugging_INTERFACE_DEFINED__ + +/* interface ICLRDebugging */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRDebugging; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("D28F3C5A-9634-4206-A509-477552EEFB10") + ICLRDebugging : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OpenVirtualProcess( + /* [in] */ ULONG64 moduleBaseAddress, + /* [in] */ IUnknown *pDataTarget, + /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, + /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, + /* [in] */ REFIID riidProcess, + /* [iid_is][out] */ IUnknown **ppProcess, + /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, + /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE CanUnloadNow( + HMODULE hModule) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRDebuggingVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRDebugging * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRDebugging * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRDebugging * This); + + HRESULT ( STDMETHODCALLTYPE *OpenVirtualProcess )( + ICLRDebugging * This, + /* [in] */ ULONG64 moduleBaseAddress, + /* [in] */ IUnknown *pDataTarget, + /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, + /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, + /* [in] */ REFIID riidProcess, + /* [iid_is][out] */ IUnknown **ppProcess, + /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, + /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags); + + HRESULT ( STDMETHODCALLTYPE *CanUnloadNow )( + ICLRDebugging * This, + HMODULE hModule); + + END_INTERFACE + } ICLRDebuggingVtbl; + + interface ICLRDebugging + { + CONST_VTBL struct ICLRDebuggingVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRDebugging_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRDebugging_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRDebugging_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRDebugging_OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) \ + ( (This)->lpVtbl -> OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) ) + +#define ICLRDebugging_CanUnloadNow(This,hModule) \ + ( (This)->lpVtbl -> CanUnloadNow(This,hModule) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRDebugging_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRRuntimeInfo_INTERFACE_DEFINED__ +#define __ICLRRuntimeInfo_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeInfo */ +/* [object][local][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRRuntimeInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("BD39D1D2-BA2F-486a-89B0-B4B0CB466891") + ICLRRuntimeInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetVersionString( + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRuntimeDirectory( + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsLoaded( + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ BOOL *pbLoaded) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadErrorString( + /* [in] */ UINT iResourceID, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer, + /* [lcid][in] */ LONG iLocaleID) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadLibrary( + /* [in] */ LPCWSTR pwzDllName, + /* [retval][out] */ HMODULE *phndModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProcAddress( + /* [in] */ LPCSTR pszProcName, + /* [retval][out] */ LPVOID *ppProc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetInterface( + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsLoadable( + /* [retval][out] */ BOOL *pbLoadable) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDefaultStartupFlags( + /* [in] */ DWORD dwStartupFlags, + /* [in] */ LPCWSTR pwzHostConfigFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefaultStartupFlags( + /* [out] */ DWORD *pdwStartupFlags, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, + /* [out][in] */ DWORD *pcchHostConfigFile) = 0; + + virtual HRESULT STDMETHODCALLTYPE BindAsLegacyV2Runtime( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsStarted( + /* [out] */ BOOL *pbStarted, + /* [out] */ DWORD *pdwStartupFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeInfo * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeInfo * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeInfo * This); + + HRESULT ( STDMETHODCALLTYPE *GetVersionString )( + ICLRRuntimeInfo * This, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeDirectory )( + ICLRRuntimeInfo * This, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer); + + HRESULT ( STDMETHODCALLTYPE *IsLoaded )( + ICLRRuntimeInfo * This, + /* [in] */ HANDLE hndProcess, + /* [retval][out] */ BOOL *pbLoaded); + + HRESULT ( STDMETHODCALLTYPE *LoadErrorString )( + ICLRRuntimeInfo * This, + /* [in] */ UINT iResourceID, + /* [annotation][size_is][out] */ + _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, + /* [out][in] */ DWORD *pcchBuffer, + /* [lcid][in] */ LONG iLocaleID); + + HRESULT ( STDMETHODCALLTYPE *LoadLibrary )( + ICLRRuntimeInfo * This, + /* [in] */ LPCWSTR pwzDllName, + /* [retval][out] */ HMODULE *phndModule); + + HRESULT ( STDMETHODCALLTYPE *GetProcAddress )( + ICLRRuntimeInfo * This, + /* [in] */ LPCSTR pszProcName, + /* [retval][out] */ LPVOID *ppProc); + + HRESULT ( STDMETHODCALLTYPE *GetInterface )( + ICLRRuntimeInfo * This, + /* [in] */ REFCLSID rclsid, + /* [in] */ REFIID riid, + /* [retval][iid_is][out] */ LPVOID *ppUnk); + + HRESULT ( STDMETHODCALLTYPE *IsLoadable )( + ICLRRuntimeInfo * This, + /* [retval][out] */ BOOL *pbLoadable); + + HRESULT ( STDMETHODCALLTYPE *SetDefaultStartupFlags )( + ICLRRuntimeInfo * This, + /* [in] */ DWORD dwStartupFlags, + /* [in] */ LPCWSTR pwzHostConfigFile); + + HRESULT ( STDMETHODCALLTYPE *GetDefaultStartupFlags )( + ICLRRuntimeInfo * This, + /* [out] */ DWORD *pdwStartupFlags, + /* [annotation][size_is][out] */ + _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, + /* [out][in] */ DWORD *pcchHostConfigFile); + + HRESULT ( STDMETHODCALLTYPE *BindAsLegacyV2Runtime )( + ICLRRuntimeInfo * This); + + HRESULT ( STDMETHODCALLTYPE *IsStarted )( + ICLRRuntimeInfo * This, + /* [out] */ BOOL *pbStarted, + /* [out] */ DWORD *pdwStartupFlags); + + END_INTERFACE + } ICLRRuntimeInfoVtbl; + + interface ICLRRuntimeInfo + { + CONST_VTBL struct ICLRRuntimeInfoVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeInfo_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeInfo_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeInfo_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeInfo_GetVersionString(This,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetVersionString(This,pwzBuffer,pcchBuffer) ) + +#define ICLRRuntimeInfo_GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) \ + ( (This)->lpVtbl -> GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) ) + +#define ICLRRuntimeInfo_IsLoaded(This,hndProcess,pbLoaded) \ + ( (This)->lpVtbl -> IsLoaded(This,hndProcess,pbLoaded) ) + +#define ICLRRuntimeInfo_LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) \ + ( (This)->lpVtbl -> LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) ) + +#define ICLRRuntimeInfo_LoadLibrary(This,pwzDllName,phndModule) \ + ( (This)->lpVtbl -> LoadLibrary(This,pwzDllName,phndModule) ) + +#define ICLRRuntimeInfo_GetProcAddress(This,pszProcName,ppProc) \ + ( (This)->lpVtbl -> GetProcAddress(This,pszProcName,ppProc) ) + +#define ICLRRuntimeInfo_GetInterface(This,rclsid,riid,ppUnk) \ + ( (This)->lpVtbl -> GetInterface(This,rclsid,riid,ppUnk) ) + +#define ICLRRuntimeInfo_IsLoadable(This,pbLoadable) \ + ( (This)->lpVtbl -> IsLoadable(This,pbLoadable) ) + +#define ICLRRuntimeInfo_SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) \ + ( (This)->lpVtbl -> SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) ) + +#define ICLRRuntimeInfo_GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) \ + ( (This)->lpVtbl -> GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) ) + +#define ICLRRuntimeInfo_BindAsLegacyV2Runtime(This) \ + ( (This)->lpVtbl -> BindAsLegacyV2Runtime(This) ) + +#define ICLRRuntimeInfo_IsStarted(This,pbStarted,pdwStartupFlags) \ + ( (This)->lpVtbl -> IsStarted(This,pbStarted,pdwStartupFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeInfo_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/mscoree.h b/lib/coreclr/src/pal/prebuilt/inc/mscoree.h new file mode 100644 index 0000000000..ab7bbb0d0c --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/mscoree.h @@ -0,0 +1,911 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __mscoree_h__ +#define __mscoree_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICLRRuntimeHost_FWD_DEFINED__ +#define __ICLRRuntimeHost_FWD_DEFINED__ +typedef interface ICLRRuntimeHost ICLRRuntimeHost; + +#endif /* __ICLRRuntimeHost_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost2_FWD_DEFINED__ +#define __ICLRRuntimeHost2_FWD_DEFINED__ +typedef interface ICLRRuntimeHost2 ICLRRuntimeHost2; + +#endif /* __ICLRRuntimeHost2_FWD_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost4_FWD_DEFINED__ +#define __ICLRRuntimeHost4_FWD_DEFINED__ +typedef interface ICLRRuntimeHost4 ICLRRuntimeHost4; + +#endif /* __ICLRRuntimeHost4_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_mscoree_0000_0000 */ +/* [local] */ + +#define DECLARE_DEPRECATED +#define DEPRECATED_CLR_STDAPI STDAPI + +struct IActivationFactory; + +struct IHostControl; + +struct ICLRControl; + +EXTERN_GUID(CLSID_ComCallUnmarshalV4, 0x45fb4600,0xe6e8,0x4928,0xb2,0x5e,0x50,0x47,0x6f,0xf7,0x94,0x25); +EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02); +EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D); +EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF); +typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk); +typedef HRESULT ( __stdcall *FExecuteInAppDomainCallback )( + void *cookie); + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0001 + { + STARTUP_CONCURRENT_GC = 0x1, + STARTUP_LOADER_OPTIMIZATION_MASK = ( 0x3 << 1 ) , + STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = ( 0x1 << 1 ) , + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = ( 0x2 << 1 ) , + STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = ( 0x3 << 1 ) , + STARTUP_LOADER_SAFEMODE = 0x10, + STARTUP_LOADER_SETPREFERENCE = 0x100, + STARTUP_SERVER_GC = 0x1000, + STARTUP_HOARD_GC_VM = 0x2000, + STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, + STARTUP_LEGACY_IMPERSONATION = 0x10000, + STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, + STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, + STARTUP_TRIM_GC_COMMIT = 0x80000, + STARTUP_ETW = 0x100000, + STARTUP_ARM = 0x400000, + STARTUP_SINGLE_APPDOMAIN = 0x800000, + STARTUP_APPX_APP_MODEL = 0x1000000, + STARTUP_DISABLE_RANDOMIZED_STRING_HASHING = 0x2000000 + } STARTUP_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0002 + { + APPDOMAIN_SECURITY_DEFAULT = 0, + APPDOMAIN_SECURITY_SANDBOXED = 0x1, + APPDOMAIN_SECURITY_FORBID_CROSSAD_REVERSE_PINVOKE = 0x2, + APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS = 0x4, + APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS = 0x8, + APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, + APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS = 0x40, + APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE = 0x80, + APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT = 0x100 + } APPDOMAIN_SECURITY_FLAGS; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0003 + { + WAIT_MSGPUMP = 0x1, + WAIT_ALERTABLE = 0x2, + WAIT_NOTINDEADLOCK = 0x4 + } WAIT_OPTION; + +typedef +enum ETaskType + { + TT_DEBUGGERHELPER = 0x1, + TT_GC = 0x2, + TT_FINALIZER = 0x4, + TT_THREADPOOL_TIMER = 0x8, + TT_THREADPOOL_GATE = 0x10, + TT_THREADPOOL_WORKER = 0x20, + TT_THREADPOOL_IOCOMPLETION = 0x40, + TT_ADUNLOAD = 0x80, + TT_USER = 0x100, + TT_THREADPOOL_WAIT = 0x200, + TT_UNKNOWN = 0x80000000 + } ETaskType; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0004 + { + DUMP_FLAVOR_Mini = 0, + DUMP_FLAVOR_CriticalCLRState = 1, + DUMP_FLAVOR_NonHeapCLRState = 2, + DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini + } ECustomDumpFlavor; + +#define BucketParamsCount ( 10 ) + +#define BucketParamLength ( 255 ) + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0005 + { + Parameter1 = 0, + Parameter2 = ( Parameter1 + 1 ) , + Parameter3 = ( Parameter2 + 1 ) , + Parameter4 = ( Parameter3 + 1 ) , + Parameter5 = ( Parameter4 + 1 ) , + Parameter6 = ( Parameter5 + 1 ) , + Parameter7 = ( Parameter6 + 1 ) , + Parameter8 = ( Parameter7 + 1 ) , + Parameter9 = ( Parameter8 + 1 ) , + InvalidBucketParamIndex = ( Parameter9 + 1 ) + } BucketParameterIndex; + +typedef struct _BucketParameters + { + BOOL fInited; + WCHAR pszEventTypeName[ 255 ]; + WCHAR pszParams[ 10 ][ 255 ]; + } BucketParameters; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0006 + { + OPR_ThreadAbort = 0, + OPR_ThreadRudeAbortInNonCriticalRegion = ( OPR_ThreadAbort + 1 ) , + OPR_ThreadRudeAbortInCriticalRegion = ( OPR_ThreadRudeAbortInNonCriticalRegion + 1 ) , + OPR_AppDomainUnload = ( OPR_ThreadRudeAbortInCriticalRegion + 1 ) , + OPR_AppDomainRudeUnload = ( OPR_AppDomainUnload + 1 ) , + OPR_ProcessExit = ( OPR_AppDomainRudeUnload + 1 ) , + OPR_FinalizerRun = ( OPR_ProcessExit + 1 ) , + MaxClrOperation = ( OPR_FinalizerRun + 1 ) + } EClrOperation; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0007 + { + FAIL_NonCriticalResource = 0, + FAIL_CriticalResource = ( FAIL_NonCriticalResource + 1 ) , + FAIL_FatalRuntime = ( FAIL_CriticalResource + 1 ) , + FAIL_OrphanedLock = ( FAIL_FatalRuntime + 1 ) , + FAIL_StackOverflow = ( FAIL_OrphanedLock + 1 ) , + FAIL_AccessViolation = ( FAIL_StackOverflow + 1 ) , + FAIL_CodeContract = ( FAIL_AccessViolation + 1 ) , + MaxClrFailure = ( FAIL_CodeContract + 1 ) + } EClrFailure; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0008 + { + eRuntimeDeterminedPolicy = 0, + eHostDeterminedPolicy = ( eRuntimeDeterminedPolicy + 1 ) + } EClrUnhandledException; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscoree_0000_0000_0009 + { + eNoAction = 0, + eThrowException = ( eNoAction + 1 ) , + eAbortThread = ( eThrowException + 1 ) , + eRudeAbortThread = ( eAbortThread + 1 ) , + eUnloadAppDomain = ( eRudeAbortThread + 1 ) , + eRudeUnloadAppDomain = ( eUnloadAppDomain + 1 ) , + eExitProcess = ( eRudeUnloadAppDomain + 1 ) , + eFastExitProcess = ( eExitProcess + 1 ) , + eRudeExitProcess = ( eFastExitProcess + 1 ) , + MaxPolicyAction = (eRudeExitProcess + 1 ) + } EPolicyAction; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_s_ifspec; + +#ifndef __ICLRRuntimeHost_INTERFACE_DEFINED__ +#define __ICLRRuntimeHost_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeHost */ +/* [object][local][unique][helpstring][version][uuid] */ + + +EXTERN_C const IID IID_ICLRRuntimeHost; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("90F1A06C-7712-4762-86B5-7A5EBA6BDB02") + ICLRRuntimeHost : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetHostControl( + /* [in] */ IHostControl *pHostControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCLRControl( + /* [out] */ ICLRControl **pCLRControl) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnloadAppDomain( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteInAppDomain( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomainId( + /* [out] */ DWORD *pdwAppDomainId) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteApplication( + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteInDefaultAppDomain( + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeHostVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeHost * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeHost * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *Start )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICLRRuntimeHost * This); + + HRESULT ( STDMETHODCALLTYPE *SetHostControl )( + ICLRRuntimeHost * This, + /* [in] */ IHostControl *pHostControl); + + HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( + ICLRRuntimeHost * This, + /* [out] */ ICLRControl **pCLRControl); + + HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( + ICLRRuntimeHost * This, + /* [out] */ DWORD *pdwAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( + ICLRRuntimeHost * This, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue); + + END_INTERFACE + } ICLRRuntimeHostVtbl; + + interface ICLRRuntimeHost + { + CONST_VTBL struct ICLRRuntimeHostVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeHost_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeHost_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeHost_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeHost_Start(This) \ + ( (This)->lpVtbl -> Start(This) ) + +#define ICLRRuntimeHost_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#define ICLRRuntimeHost_SetHostControl(This,pHostControl) \ + ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) + +#define ICLRRuntimeHost_GetCLRControl(This,pCLRControl) \ + ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) + +#define ICLRRuntimeHost_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ + ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) + +#define ICLRRuntimeHost_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ + ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) + +#define ICLRRuntimeHost_GetCurrentAppDomainId(This,pdwAppDomainId) \ + ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) + +#define ICLRRuntimeHost_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) + +#define ICLRRuntimeHost_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeHost_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost2_INTERFACE_DEFINED__ +#define __ICLRRuntimeHost2_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeHost2 */ +/* [local][unique][helpstring][version][uuid][object] */ + + +EXTERN_C const IID IID_ICLRRuntimeHost2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("712AB73F-2C22-4807-AD7E-F501D7B72C2D") + ICLRRuntimeHost2 : public ICLRRuntimeHost + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateAppDomainWithManager( + /* [in] */ LPCWSTR wszFriendlyName, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, + /* [in] */ LPCWSTR wszAppDomainManagerTypeName, + /* [in] */ int nProperties, + /* [in] */ LPCWSTR *pPropertyNames, + /* [in] */ LPCWSTR *pPropertyValues, + /* [out] */ DWORD *pAppDomainID) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateDelegate( + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszAssemblyName, + /* [in] */ LPCWSTR wszClassName, + /* [in] */ LPCWSTR wszMethodName, + /* [out] */ INT_PTR *fnPtr) = 0; + + virtual HRESULT STDMETHODCALLTYPE Authenticate( + /* [in] */ ULONGLONG authKey) = 0; + + virtual HRESULT STDMETHODCALLTYPE RegisterMacEHPort( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetStartupFlags( + /* [in] */ STARTUP_FLAGS dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE DllGetActivationFactory( + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszTypeName, + /* [out] */ IActivationFactory **factory) = 0; + + virtual HRESULT STDMETHODCALLTYPE ExecuteAssembly( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ int argc, + /* [in] */ LPCWSTR *argv, + /* [out] */ DWORD *pReturnValue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeHost2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeHost2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeHost2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeHost2 * This); + + HRESULT ( STDMETHODCALLTYPE *Start )( + ICLRRuntimeHost2 * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICLRRuntimeHost2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetHostControl )( + ICLRRuntimeHost2 * This, + /* [in] */ IHostControl *pHostControl); + + HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( + ICLRRuntimeHost2 * This, + /* [out] */ ICLRControl **pCLRControl); + + HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( + ICLRRuntimeHost2 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( + ICLRRuntimeHost2 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( + ICLRRuntimeHost2 * This, + /* [out] */ DWORD *pdwAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( + ICLRRuntimeHost2 * This, + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( + ICLRRuntimeHost2 * This, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *CreateAppDomainWithManager )( + ICLRRuntimeHost2 * This, + /* [in] */ LPCWSTR wszFriendlyName, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, + /* [in] */ LPCWSTR wszAppDomainManagerTypeName, + /* [in] */ int nProperties, + /* [in] */ LPCWSTR *pPropertyNames, + /* [in] */ LPCWSTR *pPropertyValues, + /* [out] */ DWORD *pAppDomainID); + + HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( + ICLRRuntimeHost2 * This, + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszAssemblyName, + /* [in] */ LPCWSTR wszClassName, + /* [in] */ LPCWSTR wszMethodName, + /* [out] */ INT_PTR *fnPtr); + + HRESULT ( STDMETHODCALLTYPE *Authenticate )( + ICLRRuntimeHost2 * This, + /* [in] */ ULONGLONG authKey); + + HRESULT ( STDMETHODCALLTYPE *RegisterMacEHPort )( + ICLRRuntimeHost2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetStartupFlags )( + ICLRRuntimeHost2 * This, + /* [in] */ STARTUP_FLAGS dwFlags); + + HRESULT ( STDMETHODCALLTYPE *DllGetActivationFactory )( + ICLRRuntimeHost2 * This, + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszTypeName, + /* [out] */ IActivationFactory **factory); + + HRESULT ( STDMETHODCALLTYPE *ExecuteAssembly )( + ICLRRuntimeHost2 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ int argc, + /* [in] */ LPCWSTR *argv, + /* [out] */ DWORD *pReturnValue); + + END_INTERFACE + } ICLRRuntimeHost2Vtbl; + + interface ICLRRuntimeHost2 + { + CONST_VTBL struct ICLRRuntimeHost2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeHost2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeHost2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeHost2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeHost2_Start(This) \ + ( (This)->lpVtbl -> Start(This) ) + +#define ICLRRuntimeHost2_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#define ICLRRuntimeHost2_SetHostControl(This,pHostControl) \ + ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) + +#define ICLRRuntimeHost2_GetCLRControl(This,pCLRControl) \ + ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) + +#define ICLRRuntimeHost2_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ + ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) + +#define ICLRRuntimeHost2_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ + ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) + +#define ICLRRuntimeHost2_GetCurrentAppDomainId(This,pdwAppDomainId) \ + ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) + +#define ICLRRuntimeHost2_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) + +#define ICLRRuntimeHost2_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) + + +#define ICLRRuntimeHost2_CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) \ + ( (This)->lpVtbl -> CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) ) + +#define ICLRRuntimeHost2_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) \ + ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) ) + +#define ICLRRuntimeHost2_Authenticate(This,authKey) \ + ( (This)->lpVtbl -> Authenticate(This,authKey) ) + +#define ICLRRuntimeHost2_RegisterMacEHPort(This) \ + ( (This)->lpVtbl -> RegisterMacEHPort(This) ) + +#define ICLRRuntimeHost2_SetStartupFlags(This,dwFlags) \ + ( (This)->lpVtbl -> SetStartupFlags(This,dwFlags) ) + +#define ICLRRuntimeHost2_DllGetActivationFactory(This,appDomainID,wszTypeName,factory) \ + ( (This)->lpVtbl -> DllGetActivationFactory(This,appDomainID,wszTypeName,factory) ) + +#define ICLRRuntimeHost2_ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeHost2_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRRuntimeHost4_INTERFACE_DEFINED__ +#define __ICLRRuntimeHost4_INTERFACE_DEFINED__ + +/* interface ICLRRuntimeHost4 */ +/* [local][unique][helpstring][version][uuid][object] */ + + +EXTERN_C const IID IID_ICLRRuntimeHost4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF") + ICLRRuntimeHost4 : public ICLRRuntimeHost2 + { + public: + virtual HRESULT STDMETHODCALLTYPE UnloadAppDomain2( + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone, + /* [out] */ int *pLatchedExitCode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRRuntimeHost4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRRuntimeHost4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRRuntimeHost4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRRuntimeHost4 * This); + + HRESULT ( STDMETHODCALLTYPE *Start )( + ICLRRuntimeHost4 * This); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICLRRuntimeHost4 * This); + + HRESULT ( STDMETHODCALLTYPE *SetHostControl )( + ICLRRuntimeHost4 * This, + /* [in] */ IHostControl *pHostControl); + + HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( + ICLRRuntimeHost4 * This, + /* [out] */ ICLRControl **pCLRControl); + + HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ FExecuteInAppDomainCallback pCallback, + /* [in] */ void *cookie); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( + ICLRRuntimeHost4 * This, + /* [out] */ DWORD *pdwAppDomainId); + + HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( + ICLRRuntimeHost4 * This, + /* [in] */ LPCWSTR pwzAppFullName, + /* [in] */ DWORD dwManifestPaths, + /* [in] */ LPCWSTR *ppwzManifestPaths, + /* [in] */ DWORD dwActivationData, + /* [in] */ LPCWSTR *ppwzActivationData, + /* [out] */ int *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( + ICLRRuntimeHost4 * This, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ LPCWSTR pwzTypeName, + /* [in] */ LPCWSTR pwzMethodName, + /* [in] */ LPCWSTR pwzArgument, + /* [out] */ DWORD *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *CreateAppDomainWithManager )( + ICLRRuntimeHost4 * This, + /* [in] */ LPCWSTR wszFriendlyName, + /* [in] */ DWORD dwFlags, + /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, + /* [in] */ LPCWSTR wszAppDomainManagerTypeName, + /* [in] */ int nProperties, + /* [in] */ LPCWSTR *pPropertyNames, + /* [in] */ LPCWSTR *pPropertyValues, + /* [out] */ DWORD *pAppDomainID); + + HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszAssemblyName, + /* [in] */ LPCWSTR wszClassName, + /* [in] */ LPCWSTR wszMethodName, + /* [out] */ INT_PTR *fnPtr); + + HRESULT ( STDMETHODCALLTYPE *Authenticate )( + ICLRRuntimeHost4 * This, + /* [in] */ ULONGLONG authKey); + + HRESULT ( STDMETHODCALLTYPE *RegisterMacEHPort )( + ICLRRuntimeHost4 * This); + + HRESULT ( STDMETHODCALLTYPE *SetStartupFlags )( + ICLRRuntimeHost4 * This, + /* [in] */ STARTUP_FLAGS dwFlags); + + HRESULT ( STDMETHODCALLTYPE *DllGetActivationFactory )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD appDomainID, + /* [in] */ LPCWSTR wszTypeName, + /* [out] */ IActivationFactory **factory); + + HRESULT ( STDMETHODCALLTYPE *ExecuteAssembly )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ LPCWSTR pwzAssemblyPath, + /* [in] */ int argc, + /* [in] */ LPCWSTR *argv, + /* [out] */ DWORD *pReturnValue); + + HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain2 )( + ICLRRuntimeHost4 * This, + /* [in] */ DWORD dwAppDomainId, + /* [in] */ BOOL fWaitUntilDone, + /* [out] */ int *pLatchedExitCode); + + END_INTERFACE + } ICLRRuntimeHost4Vtbl; + + interface ICLRRuntimeHost4 + { + CONST_VTBL struct ICLRRuntimeHost4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRRuntimeHost4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRRuntimeHost4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRRuntimeHost4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRRuntimeHost4_Start(This) \ + ( (This)->lpVtbl -> Start(This) ) + +#define ICLRRuntimeHost4_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#define ICLRRuntimeHost4_SetHostControl(This,pHostControl) \ + ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) + +#define ICLRRuntimeHost4_GetCLRControl(This,pCLRControl) \ + ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) + +#define ICLRRuntimeHost4_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ + ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) + +#define ICLRRuntimeHost4_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ + ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) + +#define ICLRRuntimeHost4_GetCurrentAppDomainId(This,pdwAppDomainId) \ + ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) + +#define ICLRRuntimeHost4_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) + +#define ICLRRuntimeHost4_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) + + +#define ICLRRuntimeHost4_CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) \ + ( (This)->lpVtbl -> CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) ) + +#define ICLRRuntimeHost4_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) \ + ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) ) + +#define ICLRRuntimeHost4_Authenticate(This,authKey) \ + ( (This)->lpVtbl -> Authenticate(This,authKey) ) + +#define ICLRRuntimeHost4_RegisterMacEHPort(This) \ + ( (This)->lpVtbl -> RegisterMacEHPort(This) ) + +#define ICLRRuntimeHost4_SetStartupFlags(This,dwFlags) \ + ( (This)->lpVtbl -> SetStartupFlags(This,dwFlags) ) + +#define ICLRRuntimeHost4_DllGetActivationFactory(This,appDomainID,wszTypeName,factory) \ + ( (This)->lpVtbl -> DllGetActivationFactory(This,appDomainID,wszTypeName,factory) ) + +#define ICLRRuntimeHost4_ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) \ + ( (This)->lpVtbl -> ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) ) + + +#define ICLRRuntimeHost4_UnloadAppDomain2(This,dwAppDomainId,fWaitUntilDone,pLatchedExitCode) \ + ( (This)->lpVtbl -> UnloadAppDomain2(This,dwAppDomainId,fWaitUntilDone,pLatchedExitCode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICLRRuntimeHost4_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscoree_0000_0003 */ +/* [local] */ + +#undef DEPRECATED_CLR_STDAPI +#undef DECLARE_DEPRECATED +#undef DEPRECATED_CLR_API_MESG + + +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/mscorsvc.h b/lib/coreclr/src/pal/prebuilt/inc/mscorsvc.h new file mode 100644 index 0000000000..c51d8bdc9a --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/mscorsvc.h @@ -0,0 +1,2824 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __mscorsvc_h__ +#define __mscorsvc_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICorSvcDependencies_FWD_DEFINED__ +#define __ICorSvcDependencies_FWD_DEFINED__ +typedef interface ICorSvcDependencies ICorSvcDependencies; + +#endif /* __ICorSvcDependencies_FWD_DEFINED__ */ + + +#ifndef __ICorSvcWorker_FWD_DEFINED__ +#define __ICorSvcWorker_FWD_DEFINED__ +typedef interface ICorSvcWorker ICorSvcWorker; + +#endif /* __ICorSvcWorker_FWD_DEFINED__ */ + + +#ifndef __ICorSvcWorker2_FWD_DEFINED__ +#define __ICorSvcWorker2_FWD_DEFINED__ +typedef interface ICorSvcWorker2 ICorSvcWorker2; + +#endif /* __ICorSvcWorker2_FWD_DEFINED__ */ + + +#ifndef __ICorSvcWorker3_FWD_DEFINED__ +#define __ICorSvcWorker3_FWD_DEFINED__ +typedef interface ICorSvcWorker3 ICorSvcWorker3; + +#endif /* __ICorSvcWorker3_FWD_DEFINED__ */ + + +#ifndef __ICorSvcSetPrivateAttributes_FWD_DEFINED__ +#define __ICorSvcSetPrivateAttributes_FWD_DEFINED__ +typedef interface ICorSvcSetPrivateAttributes ICorSvcSetPrivateAttributes; + +#endif /* __ICorSvcSetPrivateAttributes_FWD_DEFINED__ */ + + +#ifndef __ICorSvcRepository_FWD_DEFINED__ +#define __ICorSvcRepository_FWD_DEFINED__ +typedef interface ICorSvcRepository ICorSvcRepository; + +#endif /* __ICorSvcRepository_FWD_DEFINED__ */ + + +#ifndef __ICorSvcAppX_FWD_DEFINED__ +#define __ICorSvcAppX_FWD_DEFINED__ +typedef interface ICorSvcAppX ICorSvcAppX; + +#endif /* __ICorSvcAppX_FWD_DEFINED__ */ + + +#ifndef __ICorSvcLogger_FWD_DEFINED__ +#define __ICorSvcLogger_FWD_DEFINED__ +typedef interface ICorSvcLogger ICorSvcLogger; + +#endif /* __ICorSvcLogger_FWD_DEFINED__ */ + + +#ifndef __ICorSvcPooledWorker_FWD_DEFINED__ +#define __ICorSvcPooledWorker_FWD_DEFINED__ +typedef interface ICorSvcPooledWorker ICorSvcPooledWorker; + +#endif /* __ICorSvcPooledWorker_FWD_DEFINED__ */ + + +#ifndef __ICorSvcBindToWorker_FWD_DEFINED__ +#define __ICorSvcBindToWorker_FWD_DEFINED__ +typedef interface ICorSvcBindToWorker ICorSvcBindToWorker; + +#endif /* __ICorSvcBindToWorker_FWD_DEFINED__ */ + + +#ifndef __ICorSvc_FWD_DEFINED__ +#define __ICorSvc_FWD_DEFINED__ +typedef interface ICorSvc ICorSvc; + +#endif /* __ICorSvc_FWD_DEFINED__ */ + + +#ifndef __ICompileProgressNotification_FWD_DEFINED__ +#define __ICompileProgressNotification_FWD_DEFINED__ +typedef interface ICompileProgressNotification ICompileProgressNotification; + +#endif /* __ICompileProgressNotification_FWD_DEFINED__ */ + + +#ifndef __ICompileProgressNotification2_FWD_DEFINED__ +#define __ICompileProgressNotification2_FWD_DEFINED__ +typedef interface ICompileProgressNotification2 ICompileProgressNotification2; + +#endif /* __ICompileProgressNotification2_FWD_DEFINED__ */ + + +#ifndef __ICorSvcInstaller_FWD_DEFINED__ +#define __ICorSvcInstaller_FWD_DEFINED__ +typedef interface ICorSvcInstaller ICorSvcInstaller; + +#endif /* __ICorSvcInstaller_FWD_DEFINED__ */ + + +#ifndef __ICorSvcAdvancedInstaller_FWD_DEFINED__ +#define __ICorSvcAdvancedInstaller_FWD_DEFINED__ +typedef interface ICorSvcAdvancedInstaller ICorSvcAdvancedInstaller; + +#endif /* __ICorSvcAdvancedInstaller_FWD_DEFINED__ */ + + +#ifndef __ICorSvcOptimizer_FWD_DEFINED__ +#define __ICorSvcOptimizer_FWD_DEFINED__ +typedef interface ICorSvcOptimizer ICorSvcOptimizer; + +#endif /* __ICorSvcOptimizer_FWD_DEFINED__ */ + + +#ifndef __ICorSvcOptimizer2_FWD_DEFINED__ +#define __ICorSvcOptimizer2_FWD_DEFINED__ +typedef interface ICorSvcOptimizer2 ICorSvcOptimizer2; + +#endif /* __ICorSvcOptimizer2_FWD_DEFINED__ */ + + +#ifndef __ICorSvcOptimizer3_FWD_DEFINED__ +#define __ICorSvcOptimizer3_FWD_DEFINED__ +typedef interface ICorSvcOptimizer3 ICorSvcOptimizer3; + +#endif /* __ICorSvcOptimizer3_FWD_DEFINED__ */ + + +#ifndef __ICorSvcManager_FWD_DEFINED__ +#define __ICorSvcManager_FWD_DEFINED__ +typedef interface ICorSvcManager ICorSvcManager; + +#endif /* __ICorSvcManager_FWD_DEFINED__ */ + + +#ifndef __ICorSvcManager2_FWD_DEFINED__ +#define __ICorSvcManager2_FWD_DEFINED__ +typedef interface ICorSvcManager2 ICorSvcManager2; + +#endif /* __ICorSvcManager2_FWD_DEFINED__ */ + + +#ifndef __ICorSvcSetLegacyServiceBehavior_FWD_DEFINED__ +#define __ICorSvcSetLegacyServiceBehavior_FWD_DEFINED__ +typedef interface ICorSvcSetLegacyServiceBehavior ICorSvcSetLegacyServiceBehavior; + +#endif /* __ICorSvcSetLegacyServiceBehavior_FWD_DEFINED__ */ + + +#ifndef __ICorSvcSetTaskBootTriggerState_FWD_DEFINED__ +#define __ICorSvcSetTaskBootTriggerState_FWD_DEFINED__ +typedef interface ICorSvcSetTaskBootTriggerState ICorSvcSetTaskBootTriggerState; + +#endif /* __ICorSvcSetTaskBootTriggerState_FWD_DEFINED__ */ + + +#ifndef __ICorSvcSetTaskDelayStartTriggerState_FWD_DEFINED__ +#define __ICorSvcSetTaskDelayStartTriggerState_FWD_DEFINED__ +typedef interface ICorSvcSetTaskDelayStartTriggerState ICorSvcSetTaskDelayStartTriggerState; + +#endif /* __ICorSvcSetTaskDelayStartTriggerState_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_mscorsvc_0000_0000 */ +/* [local] */ + +#if 0 +#endif +EXTERN_GUID(CLSID_CorSvcWorker, 0x8ed1a844, 0x32a7, 0x4a67, 0xba, 0x62, 0xf8, 0xd5, 0xaf, 0xdf, 0xf4, 0x60); +EXTERN_GUID(CLSID_CorSvcBindToWorker, 0x9f74fb09, 0x4221, 0x40b4, 0xae, 0x21, 0xae, 0xb6, 0xdf, 0xf2, 0x99, 0x4e); +STDAPI CorGetSvc(IUnknown **pIUnknown); + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0000_v0_0_s_ifspec; + + +#ifndef __mscorsvc_LIBRARY_DEFINED__ +#define __mscorsvc_LIBRARY_DEFINED__ + +/* library mscorsvc */ +/* [helpstring][version][uuid] */ + +typedef /* [public][public][public][public][public][public][public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0001_0004_0001 + { + ScenarioDefault = 0, + ScenarioAll = 0x1, + ScenarioDebug = 0x2, + ScenarioProfile = 0x8, + ScenarioTuningDataCollection = 0x10, + ScenarioLegacy = 0x20, + ScenarioNgenLastRetry = 0x10000, + ScenarioAutoNGen = 0x100000, + ScenarioRepositoryOnly = 0x200000 + } OptimizationScenario; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscorsvc_0001_0004_0002 + { + ScenarioEmitFixups = 0x10000, + ScenarioProfileInfo = 0x20000 + } PrivateOptimizationScenario; + +typedef struct _SvcWorkerPriority + { + DWORD dwPriorityClass; + } SvcWorkerPriority; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_mscorsvc_0001_0007_0001 + { + DbgTypePdb = 0x1 + } NGenPrivateAttributesFlags; + +typedef struct _NGenPrivateAttributes + { + DWORD Flags; + DWORD ZapStats; + BSTR DbgDir; + } NGenPrivateAttributes; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0001_0008_0001 + { + RepositoryDefault = 0, + MoveFromRepository = 0x1, + CopyToRepository = 0x2, + IgnoreRepository = 0x4 + } RepositoryFlags; + +typedef +enum CorSvcLogLevel + { + LogLevel_Error = 0, + LogLevel_Warning = ( LogLevel_Error + 1 ) , + LogLevel_Success = ( LogLevel_Warning + 1 ) , + LogLevel_Info = ( LogLevel_Success + 1 ) + } CorSvcLogLevel; + + +EXTERN_C const IID LIBID_mscorsvc; + +#ifndef __ICorSvcDependencies_INTERFACE_DEFINED__ +#define __ICorSvcDependencies_INTERFACE_DEFINED__ + +/* interface ICorSvcDependencies */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcDependencies; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ddb34005-9ba3-4025-9554-f00a2df5dbf5") + ICorSvcDependencies : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAssemblyDependencies( + /* [in] */ BSTR pAssemblyName, + /* [out] */ SAFEARRAY * *pDependencies, + /* [out] */ DWORD *assemblyNGenSetting, + /* [out] */ BSTR *pNativeImageIdentity, + /* [out] */ BSTR *pAssemblyDisplayName, + /* [out] */ SAFEARRAY * *pDependencyLoadSetting, + /* [out] */ SAFEARRAY * *pDependencyNGenSetting) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcDependenciesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcDependencies * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcDependencies * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcDependencies * This); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyDependencies )( + ICorSvcDependencies * This, + /* [in] */ BSTR pAssemblyName, + /* [out] */ SAFEARRAY * *pDependencies, + /* [out] */ DWORD *assemblyNGenSetting, + /* [out] */ BSTR *pNativeImageIdentity, + /* [out] */ BSTR *pAssemblyDisplayName, + /* [out] */ SAFEARRAY * *pDependencyLoadSetting, + /* [out] */ SAFEARRAY * *pDependencyNGenSetting); + + END_INTERFACE + } ICorSvcDependenciesVtbl; + + interface ICorSvcDependencies + { + CONST_VTBL struct ICorSvcDependenciesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcDependencies_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcDependencies_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcDependencies_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcDependencies_GetAssemblyDependencies(This,pAssemblyName,pDependencies,assemblyNGenSetting,pNativeImageIdentity,pAssemblyDisplayName,pDependencyLoadSetting,pDependencyNGenSetting) \ + ( (This)->lpVtbl -> GetAssemblyDependencies(This,pAssemblyName,pDependencies,assemblyNGenSetting,pNativeImageIdentity,pAssemblyDisplayName,pDependencyLoadSetting,pDependencyNGenSetting) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcDependencies_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcWorker_INTERFACE_DEFINED__ +#define __ICorSvcWorker_INTERFACE_DEFINED__ + +/* interface ICorSvcWorker */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcWorker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d1047bc2-67c0-400c-a94c-e64446a67fbe") + ICorSvcWorker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetPriority( + /* [in] */ SvcWorkerPriority priority) = 0; + + virtual HRESULT STDMETHODCALLTYPE OptimizeAssembly( + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [in] */ SAFEARRAY * loadAlwaysList, + /* [in] */ SAFEARRAY * loadSometimesList, + /* [in] */ SAFEARRAY * loadNeverList, + /* [out] */ BSTR *pNativeImageIdentity) = 0; + + virtual HRESULT STDMETHODCALLTYPE DeleteNativeImage( + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pNativeImage) = 0; + + virtual HRESULT STDMETHODCALLTYPE DisplayNativeImages( + /* [in] */ BSTR pAssemblyName) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCorSvcDependencies( + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [out] */ ICorSvcDependencies **pCorSvcDependencies) = 0; + + virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcWorkerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcWorker * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcWorker * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcWorker * This); + + HRESULT ( STDMETHODCALLTYPE *SetPriority )( + ICorSvcWorker * This, + /* [in] */ SvcWorkerPriority priority); + + HRESULT ( STDMETHODCALLTYPE *OptimizeAssembly )( + ICorSvcWorker * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [in] */ SAFEARRAY * loadAlwaysList, + /* [in] */ SAFEARRAY * loadSometimesList, + /* [in] */ SAFEARRAY * loadNeverList, + /* [out] */ BSTR *pNativeImageIdentity); + + HRESULT ( STDMETHODCALLTYPE *DeleteNativeImage )( + ICorSvcWorker * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pNativeImage); + + HRESULT ( STDMETHODCALLTYPE *DisplayNativeImages )( + ICorSvcWorker * This, + /* [in] */ BSTR pAssemblyName); + + HRESULT ( STDMETHODCALLTYPE *GetCorSvcDependencies )( + ICorSvcWorker * This, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [out] */ ICorSvcDependencies **pCorSvcDependencies); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorSvcWorker * This); + + END_INTERFACE + } ICorSvcWorkerVtbl; + + interface ICorSvcWorker + { + CONST_VTBL struct ICorSvcWorkerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcWorker_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcWorker_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcWorker_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcWorker_SetPriority(This,priority) \ + ( (This)->lpVtbl -> SetPriority(This,priority) ) + +#define ICorSvcWorker_OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) \ + ( (This)->lpVtbl -> OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) ) + +#define ICorSvcWorker_DeleteNativeImage(This,pAssemblyName,pNativeImage) \ + ( (This)->lpVtbl -> DeleteNativeImage(This,pAssemblyName,pNativeImage) ) + +#define ICorSvcWorker_DisplayNativeImages(This,pAssemblyName) \ + ( (This)->lpVtbl -> DisplayNativeImages(This,pAssemblyName) ) + +#define ICorSvcWorker_GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) \ + ( (This)->lpVtbl -> GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) ) + +#define ICorSvcWorker_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcWorker_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcWorker2_INTERFACE_DEFINED__ +#define __ICorSvcWorker2_INTERFACE_DEFINED__ + +/* interface ICorSvcWorker2 */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcWorker2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("f3358a7d-0061-4776-880e-a2f21b9ef93e") + ICorSvcWorker2 : public ICorSvcWorker + { + public: + virtual HRESULT STDMETHODCALLTYPE CreatePdb( + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pAppBaseOrConfig, + /* [in] */ OptimizationScenario scenario, + /* [in] */ BSTR pNativeImagePath, + /* [in] */ BSTR pPdbPath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcWorker2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcWorker2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcWorker2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcWorker2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetPriority )( + ICorSvcWorker2 * This, + /* [in] */ SvcWorkerPriority priority); + + HRESULT ( STDMETHODCALLTYPE *OptimizeAssembly )( + ICorSvcWorker2 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [in] */ SAFEARRAY * loadAlwaysList, + /* [in] */ SAFEARRAY * loadSometimesList, + /* [in] */ SAFEARRAY * loadNeverList, + /* [out] */ BSTR *pNativeImageIdentity); + + HRESULT ( STDMETHODCALLTYPE *DeleteNativeImage )( + ICorSvcWorker2 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pNativeImage); + + HRESULT ( STDMETHODCALLTYPE *DisplayNativeImages )( + ICorSvcWorker2 * This, + /* [in] */ BSTR pAssemblyName); + + HRESULT ( STDMETHODCALLTYPE *GetCorSvcDependencies )( + ICorSvcWorker2 * This, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [out] */ ICorSvcDependencies **pCorSvcDependencies); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorSvcWorker2 * This); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb )( + ICorSvcWorker2 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pAppBaseOrConfig, + /* [in] */ OptimizationScenario scenario, + /* [in] */ BSTR pNativeImagePath, + /* [in] */ BSTR pPdbPath); + + END_INTERFACE + } ICorSvcWorker2Vtbl; + + interface ICorSvcWorker2 + { + CONST_VTBL struct ICorSvcWorker2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcWorker2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcWorker2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcWorker2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcWorker2_SetPriority(This,priority) \ + ( (This)->lpVtbl -> SetPriority(This,priority) ) + +#define ICorSvcWorker2_OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) \ + ( (This)->lpVtbl -> OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) ) + +#define ICorSvcWorker2_DeleteNativeImage(This,pAssemblyName,pNativeImage) \ + ( (This)->lpVtbl -> DeleteNativeImage(This,pAssemblyName,pNativeImage) ) + +#define ICorSvcWorker2_DisplayNativeImages(This,pAssemblyName) \ + ( (This)->lpVtbl -> DisplayNativeImages(This,pAssemblyName) ) + +#define ICorSvcWorker2_GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) \ + ( (This)->lpVtbl -> GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) ) + +#define ICorSvcWorker2_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + + +#define ICorSvcWorker2_CreatePdb(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath) \ + ( (This)->lpVtbl -> CreatePdb(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcWorker2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcWorker3_INTERFACE_DEFINED__ +#define __ICorSvcWorker3_INTERFACE_DEFINED__ + +/* interface ICorSvcWorker3 */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcWorker3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("DC516615-47BE-477e-8B55-C5ABE0D76B8F") + ICorSvcWorker3 : public ICorSvcWorker2 + { + public: + virtual HRESULT STDMETHODCALLTYPE CreatePdb2( + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pAppBaseOrConfig, + /* [in] */ OptimizationScenario scenario, + /* [in] */ BSTR pNativeImagePath, + /* [in] */ BSTR pPdbPath, + /* [in] */ BOOL pdbLines, + /* [in] */ BSTR managedPdbSearchPath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcWorker3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcWorker3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcWorker3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcWorker3 * This); + + HRESULT ( STDMETHODCALLTYPE *SetPriority )( + ICorSvcWorker3 * This, + /* [in] */ SvcWorkerPriority priority); + + HRESULT ( STDMETHODCALLTYPE *OptimizeAssembly )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [in] */ SAFEARRAY * loadAlwaysList, + /* [in] */ SAFEARRAY * loadSometimesList, + /* [in] */ SAFEARRAY * loadNeverList, + /* [out] */ BSTR *pNativeImageIdentity); + + HRESULT ( STDMETHODCALLTYPE *DeleteNativeImage )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pNativeImage); + + HRESULT ( STDMETHODCALLTYPE *DisplayNativeImages )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pAssemblyName); + + HRESULT ( STDMETHODCALLTYPE *GetCorSvcDependencies )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pApplicationName, + /* [in] */ OptimizationScenario scenario, + /* [out] */ ICorSvcDependencies **pCorSvcDependencies); + + HRESULT ( STDMETHODCALLTYPE *Stop )( + ICorSvcWorker3 * This); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pAppBaseOrConfig, + /* [in] */ OptimizationScenario scenario, + /* [in] */ BSTR pNativeImagePath, + /* [in] */ BSTR pPdbPath); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb2 )( + ICorSvcWorker3 * This, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BSTR pAppBaseOrConfig, + /* [in] */ OptimizationScenario scenario, + /* [in] */ BSTR pNativeImagePath, + /* [in] */ BSTR pPdbPath, + /* [in] */ BOOL pdbLines, + /* [in] */ BSTR managedPdbSearchPath); + + END_INTERFACE + } ICorSvcWorker3Vtbl; + + interface ICorSvcWorker3 + { + CONST_VTBL struct ICorSvcWorker3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcWorker3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcWorker3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcWorker3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcWorker3_SetPriority(This,priority) \ + ( (This)->lpVtbl -> SetPriority(This,priority) ) + +#define ICorSvcWorker3_OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) \ + ( (This)->lpVtbl -> OptimizeAssembly(This,pAssemblyName,pApplicationName,scenario,loadAlwaysList,loadSometimesList,loadNeverList,pNativeImageIdentity) ) + +#define ICorSvcWorker3_DeleteNativeImage(This,pAssemblyName,pNativeImage) \ + ( (This)->lpVtbl -> DeleteNativeImage(This,pAssemblyName,pNativeImage) ) + +#define ICorSvcWorker3_DisplayNativeImages(This,pAssemblyName) \ + ( (This)->lpVtbl -> DisplayNativeImages(This,pAssemblyName) ) + +#define ICorSvcWorker3_GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) \ + ( (This)->lpVtbl -> GetCorSvcDependencies(This,pApplicationName,scenario,pCorSvcDependencies) ) + +#define ICorSvcWorker3_Stop(This) \ + ( (This)->lpVtbl -> Stop(This) ) + + +#define ICorSvcWorker3_CreatePdb(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath) \ + ( (This)->lpVtbl -> CreatePdb(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath) ) + + +#define ICorSvcWorker3_CreatePdb2(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath,pdbLines,managedPdbSearchPath) \ + ( (This)->lpVtbl -> CreatePdb2(This,pAssemblyName,pAppBaseOrConfig,scenario,pNativeImagePath,pPdbPath,pdbLines,managedPdbSearchPath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcWorker3_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcSetPrivateAttributes_INTERFACE_DEFINED__ +#define __ICorSvcSetPrivateAttributes_INTERFACE_DEFINED__ + +/* interface ICorSvcSetPrivateAttributes */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcSetPrivateAttributes; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("b18e0b40-c089-4350-8328-066c668bccc2") + ICorSvcSetPrivateAttributes : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetNGenPrivateAttributes( + /* [in] */ NGenPrivateAttributes ngenPrivateAttributes) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcSetPrivateAttributesVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcSetPrivateAttributes * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcSetPrivateAttributes * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcSetPrivateAttributes * This); + + HRESULT ( STDMETHODCALLTYPE *SetNGenPrivateAttributes )( + ICorSvcSetPrivateAttributes * This, + /* [in] */ NGenPrivateAttributes ngenPrivateAttributes); + + END_INTERFACE + } ICorSvcSetPrivateAttributesVtbl; + + interface ICorSvcSetPrivateAttributes + { + CONST_VTBL struct ICorSvcSetPrivateAttributesVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcSetPrivateAttributes_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcSetPrivateAttributes_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcSetPrivateAttributes_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcSetPrivateAttributes_SetNGenPrivateAttributes(This,ngenPrivateAttributes) \ + ( (This)->lpVtbl -> SetNGenPrivateAttributes(This,ngenPrivateAttributes) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcSetPrivateAttributes_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcRepository_INTERFACE_DEFINED__ +#define __ICorSvcRepository_INTERFACE_DEFINED__ + +/* interface ICorSvcRepository */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcRepository; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d5346658-b5fd-4353-9647-07ad4783d5a0") + ICorSvcRepository : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetRepository( + /* [in] */ BSTR pRepositoryDir, + /* [in] */ RepositoryFlags repositoryFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcRepositoryVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcRepository * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcRepository * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcRepository * This); + + HRESULT ( STDMETHODCALLTYPE *SetRepository )( + ICorSvcRepository * This, + /* [in] */ BSTR pRepositoryDir, + /* [in] */ RepositoryFlags repositoryFlags); + + END_INTERFACE + } ICorSvcRepositoryVtbl; + + interface ICorSvcRepository + { + CONST_VTBL struct ICorSvcRepositoryVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcRepository_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcRepository_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcRepository_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcRepository_SetRepository(This,pRepositoryDir,repositoryFlags) \ + ( (This)->lpVtbl -> SetRepository(This,pRepositoryDir,repositoryFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcRepository_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcAppX_INTERFACE_DEFINED__ +#define __ICorSvcAppX_INTERFACE_DEFINED__ + +/* interface ICorSvcAppX */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcAppX; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5c814791-559e-4f7f-83ce-184a4ccbae24") + ICorSvcAppX : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetPackage( + /* [in] */ BSTR pPackageFullName) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLocalAppDataDirectory( + /* [in] */ BSTR pLocalAppDataDirectory) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcAppXVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcAppX * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcAppX * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcAppX * This); + + HRESULT ( STDMETHODCALLTYPE *SetPackage )( + ICorSvcAppX * This, + /* [in] */ BSTR pPackageFullName); + + HRESULT ( STDMETHODCALLTYPE *SetLocalAppDataDirectory )( + ICorSvcAppX * This, + /* [in] */ BSTR pLocalAppDataDirectory); + + END_INTERFACE + } ICorSvcAppXVtbl; + + interface ICorSvcAppX + { + CONST_VTBL struct ICorSvcAppXVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcAppX_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcAppX_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcAppX_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcAppX_SetPackage(This,pPackageFullName) \ + ( (This)->lpVtbl -> SetPackage(This,pPackageFullName) ) + +#define ICorSvcAppX_SetLocalAppDataDirectory(This,pLocalAppDataDirectory) \ + ( (This)->lpVtbl -> SetLocalAppDataDirectory(This,pLocalAppDataDirectory) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcAppX_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcLogger_INTERFACE_DEFINED__ +#define __ICorSvcLogger_INTERFACE_DEFINED__ + +/* interface ICorSvcLogger */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcLogger; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("d189ff1a-e266-4f13-9637-4b9522279ffc") + ICorSvcLogger : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Log( + /* [in] */ CorSvcLogLevel logLevel, + /* [in] */ BSTR message) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcLoggerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcLogger * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcLogger * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcLogger * This); + + HRESULT ( STDMETHODCALLTYPE *Log )( + ICorSvcLogger * This, + /* [in] */ CorSvcLogLevel logLevel, + /* [in] */ BSTR message); + + END_INTERFACE + } ICorSvcLoggerVtbl; + + interface ICorSvcLogger + { + CONST_VTBL struct ICorSvcLoggerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcLogger_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcLogger_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcLogger_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcLogger_Log(This,logLevel,message) \ + ( (This)->lpVtbl -> Log(This,logLevel,message) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcLogger_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcPooledWorker_INTERFACE_DEFINED__ +#define __ICorSvcPooledWorker_INTERFACE_DEFINED__ + +/* interface ICorSvcPooledWorker */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcPooledWorker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0631e7e2-6046-4fde-8b6d-a09b64fda6f3") + ICorSvcPooledWorker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CanReuseProcess( + /* [in] */ OptimizationScenario scenario, + /* [in] */ ICorSvcLogger *pCorSvcLogger, + /* [out] */ BOOL *pCanContinue) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcPooledWorkerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcPooledWorker * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcPooledWorker * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcPooledWorker * This); + + HRESULT ( STDMETHODCALLTYPE *CanReuseProcess )( + ICorSvcPooledWorker * This, + /* [in] */ OptimizationScenario scenario, + /* [in] */ ICorSvcLogger *pCorSvcLogger, + /* [out] */ BOOL *pCanContinue); + + END_INTERFACE + } ICorSvcPooledWorkerVtbl; + + interface ICorSvcPooledWorker + { + CONST_VTBL struct ICorSvcPooledWorkerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcPooledWorker_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcPooledWorker_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcPooledWorker_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcPooledWorker_CanReuseProcess(This,scenario,pCorSvcLogger,pCanContinue) \ + ( (This)->lpVtbl -> CanReuseProcess(This,scenario,pCorSvcLogger,pCanContinue) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcPooledWorker_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcBindToWorker_INTERFACE_DEFINED__ +#define __ICorSvcBindToWorker_INTERFACE_DEFINED__ + +/* interface ICorSvcBindToWorker */ +/* [unique][uuid][oleautomation][object] */ + + +EXTERN_C const IID IID_ICorSvcBindToWorker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5c6fb596-4828-4ed5-b9dd-293dad736fb5") + ICorSvcBindToWorker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BindToRuntimeWorker( + /* [in] */ BSTR pRuntimeVersion, + /* [in] */ DWORD ParentProcessID, + /* [in] */ BSTR pInterruptEventName, + /* [in] */ ICorSvcLogger *pCorSvcLogger, + /* [out] */ ICorSvcWorker **pCorSvcWorker) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcBindToWorkerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcBindToWorker * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcBindToWorker * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcBindToWorker * This); + + HRESULT ( STDMETHODCALLTYPE *BindToRuntimeWorker )( + ICorSvcBindToWorker * This, + /* [in] */ BSTR pRuntimeVersion, + /* [in] */ DWORD ParentProcessID, + /* [in] */ BSTR pInterruptEventName, + /* [in] */ ICorSvcLogger *pCorSvcLogger, + /* [out] */ ICorSvcWorker **pCorSvcWorker); + + END_INTERFACE + } ICorSvcBindToWorkerVtbl; + + interface ICorSvcBindToWorker + { + CONST_VTBL struct ICorSvcBindToWorkerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcBindToWorker_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcBindToWorker_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcBindToWorker_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcBindToWorker_BindToRuntimeWorker(This,pRuntimeVersion,ParentProcessID,pInterruptEventName,pCorSvcLogger,pCorSvcWorker) \ + ( (This)->lpVtbl -> BindToRuntimeWorker(This,pRuntimeVersion,ParentProcessID,pInterruptEventName,pCorSvcLogger,pCorSvcWorker) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcBindToWorker_INTERFACE_DEFINED__ */ + +#endif /* __mscorsvc_LIBRARY_DEFINED__ */ + +/* interface __MIDL_itf_mscorsvc_0000_0001 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0001_0001 + { + Service_NoAction = -1, + Service_Start = 0, + Service_Stop = 0x1, + Service_Pause = 0x2, + Service_Continue = 0x3, + Service_Interrogate = 0x4, + Service_StartPaused = 0x5 + } ControlServiceAction; + +typedef struct _COR_SERVICE_STATUS + { + WCHAR sServiceName[ 64 ]; + DWORD dwServiceType; + DWORD dwCurrentState; + DWORD dwControlsAccepted; + DWORD dwWin32ExitCode; + DWORD dwServiceSpecificExitCode; + DWORD dwCheckPoint; + DWORD dwWaitHint; + } COR_SERVICE_STATUS; + +typedef struct _COR_SERVICE_STATUS *LPCOR_SERVICE_STATUS; + +typedef struct _ServiceOptions + { + BOOL RunAsWindowsService; + BOOL RunAsPrivateRuntime; + BOOL StartPaused; + } ServiceOptions; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0001_v0_0_s_ifspec; + +#ifndef __ICorSvc_INTERFACE_DEFINED__ +#define __ICorSvc_INTERFACE_DEFINED__ + +/* interface ICorSvc */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvc; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3eef5ff0-3680-4f20-8a8f-9051aca66b22") + ICorSvc : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetServiceManagerInterface( + /* [in] */ IUnknown **pIUnknown) = 0; + + virtual HRESULT STDMETHODCALLTYPE InstallService( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE UninstallService( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ControlService( + /* [in] */ ControlServiceAction Action, + /* [out] */ LPCOR_SERVICE_STATUS lpServiceStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE RunService( + /* [in] */ ServiceOptions options) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvc * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvc * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvc * This); + + HRESULT ( STDMETHODCALLTYPE *GetServiceManagerInterface )( + ICorSvc * This, + /* [in] */ IUnknown **pIUnknown); + + HRESULT ( STDMETHODCALLTYPE *InstallService )( + ICorSvc * This); + + HRESULT ( STDMETHODCALLTYPE *UninstallService )( + ICorSvc * This); + + HRESULT ( STDMETHODCALLTYPE *ControlService )( + ICorSvc * This, + /* [in] */ ControlServiceAction Action, + /* [out] */ LPCOR_SERVICE_STATUS lpServiceStatus); + + HRESULT ( STDMETHODCALLTYPE *RunService )( + ICorSvc * This, + /* [in] */ ServiceOptions options); + + END_INTERFACE + } ICorSvcVtbl; + + interface ICorSvc + { + CONST_VTBL struct ICorSvcVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvc_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvc_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvc_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvc_GetServiceManagerInterface(This,pIUnknown) \ + ( (This)->lpVtbl -> GetServiceManagerInterface(This,pIUnknown) ) + +#define ICorSvc_InstallService(This) \ + ( (This)->lpVtbl -> InstallService(This) ) + +#define ICorSvc_UninstallService(This) \ + ( (This)->lpVtbl -> UninstallService(This) ) + +#define ICorSvc_ControlService(This,Action,lpServiceStatus) \ + ( (This)->lpVtbl -> ControlService(This,Action,lpServiceStatus) ) + +#define ICorSvc_RunService(This,options) \ + ( (This)->lpVtbl -> RunService(This,options) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvc_INTERFACE_DEFINED__ */ + + +#ifndef __ICompileProgressNotification_INTERFACE_DEFINED__ +#define __ICompileProgressNotification_INTERFACE_DEFINED__ + +/* interface ICompileProgressNotification */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICompileProgressNotification; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("01c10030-6c81-4671-bd51-14b184c673b2") + ICompileProgressNotification : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CompileStarted( + /* [in] */ DWORD cAssembliesToCompile, + /* [in] */ DWORD cTimeEstimate) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProgressNotification( + /* [in] */ DWORD cAssembly, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BOOL isStartNotification, + /* [in] */ HRESULT hrResult, + /* [in] */ BSTR errorExplanation, + /* [in] */ DWORD cTimeRemainingEstimate) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICompileProgressNotificationVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICompileProgressNotification * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICompileProgressNotification * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICompileProgressNotification * This); + + HRESULT ( STDMETHODCALLTYPE *CompileStarted )( + ICompileProgressNotification * This, + /* [in] */ DWORD cAssembliesToCompile, + /* [in] */ DWORD cTimeEstimate); + + HRESULT ( STDMETHODCALLTYPE *ProgressNotification )( + ICompileProgressNotification * This, + /* [in] */ DWORD cAssembly, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BOOL isStartNotification, + /* [in] */ HRESULT hrResult, + /* [in] */ BSTR errorExplanation, + /* [in] */ DWORD cTimeRemainingEstimate); + + END_INTERFACE + } ICompileProgressNotificationVtbl; + + interface ICompileProgressNotification + { + CONST_VTBL struct ICompileProgressNotificationVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICompileProgressNotification_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICompileProgressNotification_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICompileProgressNotification_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICompileProgressNotification_CompileStarted(This,cAssembliesToCompile,cTimeEstimate) \ + ( (This)->lpVtbl -> CompileStarted(This,cAssembliesToCompile,cTimeEstimate) ) + +#define ICompileProgressNotification_ProgressNotification(This,cAssembly,pAssemblyName,isStartNotification,hrResult,errorExplanation,cTimeRemainingEstimate) \ + ( (This)->lpVtbl -> ProgressNotification(This,cAssembly,pAssemblyName,isStartNotification,hrResult,errorExplanation,cTimeRemainingEstimate) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICompileProgressNotification_INTERFACE_DEFINED__ */ + + +#ifndef __ICompileProgressNotification2_INTERFACE_DEFINED__ +#define __ICompileProgressNotification2_INTERFACE_DEFINED__ + +/* interface ICompileProgressNotification2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICompileProgressNotification2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("98E5BDE2-E9A0-4ADE-9CB2-6CD06FDB1A85") + ICompileProgressNotification2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CompileStarted( + /* [in] */ DWORD cAssembliesToCompile, + /* [in] */ DWORD cTimeEstimate, + /* [in] */ DWORD threadID) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProgressNotification( + /* [in] */ DWORD cAssembly, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BOOL isStartNotification, + /* [in] */ HRESULT hrResult, + /* [in] */ BSTR errorExplanation, + /* [in] */ DWORD cTimeRemainingEstimate, + /* [in] */ DWORD threadID) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICompileProgressNotification2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICompileProgressNotification2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICompileProgressNotification2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICompileProgressNotification2 * This); + + HRESULT ( STDMETHODCALLTYPE *CompileStarted )( + ICompileProgressNotification2 * This, + /* [in] */ DWORD cAssembliesToCompile, + /* [in] */ DWORD cTimeEstimate, + /* [in] */ DWORD threadID); + + HRESULT ( STDMETHODCALLTYPE *ProgressNotification )( + ICompileProgressNotification2 * This, + /* [in] */ DWORD cAssembly, + /* [in] */ BSTR pAssemblyName, + /* [in] */ BOOL isStartNotification, + /* [in] */ HRESULT hrResult, + /* [in] */ BSTR errorExplanation, + /* [in] */ DWORD cTimeRemainingEstimate, + /* [in] */ DWORD threadID); + + END_INTERFACE + } ICompileProgressNotification2Vtbl; + + interface ICompileProgressNotification2 + { + CONST_VTBL struct ICompileProgressNotification2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICompileProgressNotification2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICompileProgressNotification2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICompileProgressNotification2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICompileProgressNotification2_CompileStarted(This,cAssembliesToCompile,cTimeEstimate,threadID) \ + ( (This)->lpVtbl -> CompileStarted(This,cAssembliesToCompile,cTimeEstimate,threadID) ) + +#define ICompileProgressNotification2_ProgressNotification(This,cAssembly,pAssemblyName,isStartNotification,hrResult,errorExplanation,cTimeRemainingEstimate,threadID) \ + ( (This)->lpVtbl -> ProgressNotification(This,cAssembly,pAssemblyName,isStartNotification,hrResult,errorExplanation,cTimeRemainingEstimate,threadID) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICompileProgressNotification2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscorsvc_0000_0004 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0004_0001 + { + DefaultOptimizeFlags = 0, + TolerateCompilationFailures = 0x1, + OptimizeNGenQueueOnly = 0x2 + } OptimizeFlags; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0004_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0004_v0_0_s_ifspec; + +#ifndef __ICorSvcInstaller_INTERFACE_DEFINED__ +#define __ICorSvcInstaller_INTERFACE_DEFINED__ + +/* interface ICorSvcInstaller */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcInstaller; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0523feee-eb0e-4857-b2aa-db787521d077") + ICorSvcInstaller : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Install( + /* [in] */ BSTR path) = 0; + + virtual HRESULT STDMETHODCALLTYPE Uninstall( + /* [in] */ BSTR path) = 0; + + virtual HRESULT STDMETHODCALLTYPE Optimize( + /* [in] */ ICompileProgressNotification *pCompileProgressNotification, + /* [in] */ OptimizeFlags optimizeFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLogger( + /* [in] */ ICorSvcLogger *pCorSvcLogger) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcInstallerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcInstaller * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcInstaller * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcInstaller * This); + + HRESULT ( STDMETHODCALLTYPE *Install )( + ICorSvcInstaller * This, + /* [in] */ BSTR path); + + HRESULT ( STDMETHODCALLTYPE *Uninstall )( + ICorSvcInstaller * This, + /* [in] */ BSTR path); + + HRESULT ( STDMETHODCALLTYPE *Optimize )( + ICorSvcInstaller * This, + /* [in] */ ICompileProgressNotification *pCompileProgressNotification, + /* [in] */ OptimizeFlags optimizeFlags); + + HRESULT ( STDMETHODCALLTYPE *SetLogger )( + ICorSvcInstaller * This, + /* [in] */ ICorSvcLogger *pCorSvcLogger); + + END_INTERFACE + } ICorSvcInstallerVtbl; + + interface ICorSvcInstaller + { + CONST_VTBL struct ICorSvcInstallerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcInstaller_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcInstaller_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcInstaller_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcInstaller_Install(This,path) \ + ( (This)->lpVtbl -> Install(This,path) ) + +#define ICorSvcInstaller_Uninstall(This,path) \ + ( (This)->lpVtbl -> Uninstall(This,path) ) + +#define ICorSvcInstaller_Optimize(This,pCompileProgressNotification,optimizeFlags) \ + ( (This)->lpVtbl -> Optimize(This,pCompileProgressNotification,optimizeFlags) ) + +#define ICorSvcInstaller_SetLogger(This,pCorSvcLogger) \ + ( (This)->lpVtbl -> SetLogger(This,pCorSvcLogger) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcInstaller_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscorsvc_0000_0005 */ +/* [local] */ + +typedef /* [public][public][public][public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0005_0001 + { + DefaultFlags = 0, + AllowPartialNames = 0x1, + KeepPriority = 0x2, + NoRoot = 0x4 + } GeneralFlags; + +typedef /* [public][public][public][public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0005_0002 + { + Priority_None = -1, + Priority_0 = 0, + Priority_1 = 0x1, + Priority_2 = 0x2, + Priority_3 = 0x3, + Priority_Default = Priority_3, + Priority_Lowest = Priority_3, + Priority_LowestAggressive = Priority_2, + Priority_Highest = Priority_0, + Priority_Highest_Root = Priority_1, + Priority_Lowest_Root = Priority_3 + } PriorityLevel; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0005_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0005_v0_0_s_ifspec; + +#ifndef __ICorSvcAdvancedInstaller_INTERFACE_DEFINED__ +#define __ICorSvcAdvancedInstaller_INTERFACE_DEFINED__ + +/* interface ICorSvcAdvancedInstaller */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcAdvancedInstaller; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("0871fb80-3ea0-47cc-9b51-d92e2aee75db") + ICorSvcAdvancedInstaller : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Install( + /* [in] */ BSTR path, + /* [in] */ OptimizationScenario optScenario, + /* [in] */ BSTR config, + /* [in] */ GeneralFlags generalFlags, + /* [in] */ PriorityLevel priorityLevel) = 0; + + virtual HRESULT STDMETHODCALLTYPE Uninstall( + /* [in] */ BSTR path, + /* [in] */ OptimizationScenario optScenario, + /* [in] */ BSTR config, + /* [in] */ GeneralFlags generalFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcAdvancedInstallerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcAdvancedInstaller * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcAdvancedInstaller * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcAdvancedInstaller * This); + + HRESULT ( STDMETHODCALLTYPE *Install )( + ICorSvcAdvancedInstaller * This, + /* [in] */ BSTR path, + /* [in] */ OptimizationScenario optScenario, + /* [in] */ BSTR config, + /* [in] */ GeneralFlags generalFlags, + /* [in] */ PriorityLevel priorityLevel); + + HRESULT ( STDMETHODCALLTYPE *Uninstall )( + ICorSvcAdvancedInstaller * This, + /* [in] */ BSTR path, + /* [in] */ OptimizationScenario optScenario, + /* [in] */ BSTR config, + /* [in] */ GeneralFlags generalFlags); + + END_INTERFACE + } ICorSvcAdvancedInstallerVtbl; + + interface ICorSvcAdvancedInstaller + { + CONST_VTBL struct ICorSvcAdvancedInstallerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcAdvancedInstaller_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcAdvancedInstaller_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcAdvancedInstaller_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcAdvancedInstaller_Install(This,path,optScenario,config,generalFlags,priorityLevel) \ + ( (This)->lpVtbl -> Install(This,path,optScenario,config,generalFlags,priorityLevel) ) + +#define ICorSvcAdvancedInstaller_Uninstall(This,path,optScenario,config,generalFlags) \ + ( (This)->lpVtbl -> Uninstall(This,path,optScenario,config,generalFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcAdvancedInstaller_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscorsvc_0000_0006 */ +/* [local] */ + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0006_0001 + { + UpdateDefault = 0, + Force = 0x1, + PostReboot = 0x2 + } UpdateFlags; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0006_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0006_v0_0_s_ifspec; + +#ifndef __ICorSvcOptimizer_INTERFACE_DEFINED__ +#define __ICorSvcOptimizer_INTERFACE_DEFINED__ + +/* interface ICorSvcOptimizer */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcOptimizer; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("94af0ec4-c10d-45d4-a625-d68d1b02a396") + ICorSvcOptimizer : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Update( + /* [in] */ BSTR path, + /* [in] */ UpdateFlags updateFlags, + /* [in] */ GeneralFlags generalFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Display( + /* [in] */ BSTR path, + /* [in] */ GeneralFlags generalFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE ScheduleWork( + /* [in] */ PriorityLevel priorityLevel) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcOptimizerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcOptimizer * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcOptimizer * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcOptimizer * This); + + HRESULT ( STDMETHODCALLTYPE *Update )( + ICorSvcOptimizer * This, + /* [in] */ BSTR path, + /* [in] */ UpdateFlags updateFlags, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *Display )( + ICorSvcOptimizer * This, + /* [in] */ BSTR path, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *ScheduleWork )( + ICorSvcOptimizer * This, + /* [in] */ PriorityLevel priorityLevel); + + END_INTERFACE + } ICorSvcOptimizerVtbl; + + interface ICorSvcOptimizer + { + CONST_VTBL struct ICorSvcOptimizerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcOptimizer_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcOptimizer_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcOptimizer_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcOptimizer_Update(This,path,updateFlags,generalFlags) \ + ( (This)->lpVtbl -> Update(This,path,updateFlags,generalFlags) ) + +#define ICorSvcOptimizer_Display(This,path,generalFlags) \ + ( (This)->lpVtbl -> Display(This,path,generalFlags) ) + +#define ICorSvcOptimizer_ScheduleWork(This,priorityLevel) \ + ( (This)->lpVtbl -> ScheduleWork(This,priorityLevel) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcOptimizer_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcOptimizer2_INTERFACE_DEFINED__ +#define __ICorSvcOptimizer2_INTERFACE_DEFINED__ + +/* interface ICorSvcOptimizer2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcOptimizer2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ee3b09c2-0110-4b6e-a73f-a3d6562f98ab") + ICorSvcOptimizer2 : public ICorSvcOptimizer + { + public: + virtual HRESULT STDMETHODCALLTYPE CreatePdb( + /* [in] */ BSTR nativeImagePath, + /* [in] */ BSTR pdbPath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcOptimizer2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcOptimizer2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcOptimizer2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcOptimizer2 * This); + + HRESULT ( STDMETHODCALLTYPE *Update )( + ICorSvcOptimizer2 * This, + /* [in] */ BSTR path, + /* [in] */ UpdateFlags updateFlags, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *Display )( + ICorSvcOptimizer2 * This, + /* [in] */ BSTR path, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *ScheduleWork )( + ICorSvcOptimizer2 * This, + /* [in] */ PriorityLevel priorityLevel); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb )( + ICorSvcOptimizer2 * This, + /* [in] */ BSTR nativeImagePath, + /* [in] */ BSTR pdbPath); + + END_INTERFACE + } ICorSvcOptimizer2Vtbl; + + interface ICorSvcOptimizer2 + { + CONST_VTBL struct ICorSvcOptimizer2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcOptimizer2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcOptimizer2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcOptimizer2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcOptimizer2_Update(This,path,updateFlags,generalFlags) \ + ( (This)->lpVtbl -> Update(This,path,updateFlags,generalFlags) ) + +#define ICorSvcOptimizer2_Display(This,path,generalFlags) \ + ( (This)->lpVtbl -> Display(This,path,generalFlags) ) + +#define ICorSvcOptimizer2_ScheduleWork(This,priorityLevel) \ + ( (This)->lpVtbl -> ScheduleWork(This,priorityLevel) ) + + +#define ICorSvcOptimizer2_CreatePdb(This,nativeImagePath,pdbPath) \ + ( (This)->lpVtbl -> CreatePdb(This,nativeImagePath,pdbPath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcOptimizer2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcOptimizer3_INTERFACE_DEFINED__ +#define __ICorSvcOptimizer3_INTERFACE_DEFINED__ + +/* interface ICorSvcOptimizer3 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcOptimizer3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6EED164F-61EE-4a07-ABE8-670F92B4B7A9") + ICorSvcOptimizer3 : public ICorSvcOptimizer2 + { + public: + virtual HRESULT STDMETHODCALLTYPE CreatePdb2( + /* [in] */ BSTR nativeImagePath, + /* [in] */ BSTR pdbPath, + /* [in] */ BOOL pdbLines, + /* [in] */ BSTR managedPdbSearchPath) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcOptimizer3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcOptimizer3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcOptimizer3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcOptimizer3 * This); + + HRESULT ( STDMETHODCALLTYPE *Update )( + ICorSvcOptimizer3 * This, + /* [in] */ BSTR path, + /* [in] */ UpdateFlags updateFlags, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *Display )( + ICorSvcOptimizer3 * This, + /* [in] */ BSTR path, + /* [in] */ GeneralFlags generalFlags); + + HRESULT ( STDMETHODCALLTYPE *ScheduleWork )( + ICorSvcOptimizer3 * This, + /* [in] */ PriorityLevel priorityLevel); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb )( + ICorSvcOptimizer3 * This, + /* [in] */ BSTR nativeImagePath, + /* [in] */ BSTR pdbPath); + + HRESULT ( STDMETHODCALLTYPE *CreatePdb2 )( + ICorSvcOptimizer3 * This, + /* [in] */ BSTR nativeImagePath, + /* [in] */ BSTR pdbPath, + /* [in] */ BOOL pdbLines, + /* [in] */ BSTR managedPdbSearchPath); + + END_INTERFACE + } ICorSvcOptimizer3Vtbl; + + interface ICorSvcOptimizer3 + { + CONST_VTBL struct ICorSvcOptimizer3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcOptimizer3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcOptimizer3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcOptimizer3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcOptimizer3_Update(This,path,updateFlags,generalFlags) \ + ( (This)->lpVtbl -> Update(This,path,updateFlags,generalFlags) ) + +#define ICorSvcOptimizer3_Display(This,path,generalFlags) \ + ( (This)->lpVtbl -> Display(This,path,generalFlags) ) + +#define ICorSvcOptimizer3_ScheduleWork(This,priorityLevel) \ + ( (This)->lpVtbl -> ScheduleWork(This,priorityLevel) ) + + +#define ICorSvcOptimizer3_CreatePdb(This,nativeImagePath,pdbPath) \ + ( (This)->lpVtbl -> CreatePdb(This,nativeImagePath,pdbPath) ) + + +#define ICorSvcOptimizer3_CreatePdb2(This,nativeImagePath,pdbPath,pdbLines,managedPdbSearchPath) \ + ( (This)->lpVtbl -> CreatePdb2(This,nativeImagePath,pdbPath,pdbLines,managedPdbSearchPath) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcOptimizer3_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mscorsvc_0000_0009 */ +/* [local] */ + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_mscorsvc_0000_0009_0001 + { + NewWorkAvailable = 0, + ClientWorkStart = 0x1, + ClientWorkDone = 0x2, + UpdatePostReboot = 0x3, + NewWorkAvailableWithDelay = 0x4 + } ServiceNotification; + + + +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mscorsvc_0000_0009_v0_0_s_ifspec; + +#ifndef __ICorSvcManager_INTERFACE_DEFINED__ +#define __ICorSvcManager_INTERFACE_DEFINED__ + +/* interface ICorSvcManager */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcManager; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8f416a48-d663-4a7e-9732-fbca3fc46ea8") + ICorSvcManager : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE ScheduleWorkForSinglePriorityLevel( + /* [in] */ PriorityLevel priorityLevel, + /* [in] */ BSTR pInterruptEventName, + /* [out] */ BOOL *pWorkScheduled) = 0; + + virtual HRESULT STDMETHODCALLTYPE Optimize( + /* [in] */ DWORD dwWorkerPriorityClass, + /* [in] */ ICompileProgressNotification *pCompileProgressNotification, + /* [in] */ BSTR pInterruptEventName) = 0; + + virtual HRESULT STDMETHODCALLTYPE NotifyService( + ServiceNotification notification) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsWorkAvailable( + /* [in] */ PriorityLevel priorityLevel, + /* [out] */ BOOL *pWorkAvailable) = 0; + + virtual HRESULT STDMETHODCALLTYPE Update( + /* [in] */ UpdateFlags updateFlags, + /* [in] */ BSTR pInterruptEventName) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSvcLogger( + /* [in] */ ICorSvcLogger *pCorSvcLogger) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcManagerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcManager * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcManager * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcManager * This); + + HRESULT ( STDMETHODCALLTYPE *ScheduleWorkForSinglePriorityLevel )( + ICorSvcManager * This, + /* [in] */ PriorityLevel priorityLevel, + /* [in] */ BSTR pInterruptEventName, + /* [out] */ BOOL *pWorkScheduled); + + HRESULT ( STDMETHODCALLTYPE *Optimize )( + ICorSvcManager * This, + /* [in] */ DWORD dwWorkerPriorityClass, + /* [in] */ ICompileProgressNotification *pCompileProgressNotification, + /* [in] */ BSTR pInterruptEventName); + + HRESULT ( STDMETHODCALLTYPE *NotifyService )( + ICorSvcManager * This, + ServiceNotification notification); + + HRESULT ( STDMETHODCALLTYPE *IsWorkAvailable )( + ICorSvcManager * This, + /* [in] */ PriorityLevel priorityLevel, + /* [out] */ BOOL *pWorkAvailable); + + HRESULT ( STDMETHODCALLTYPE *Update )( + ICorSvcManager * This, + /* [in] */ UpdateFlags updateFlags, + /* [in] */ BSTR pInterruptEventName); + + HRESULT ( STDMETHODCALLTYPE *SetSvcLogger )( + ICorSvcManager * This, + /* [in] */ ICorSvcLogger *pCorSvcLogger); + + END_INTERFACE + } ICorSvcManagerVtbl; + + interface ICorSvcManager + { + CONST_VTBL struct ICorSvcManagerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcManager_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcManager_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcManager_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcManager_ScheduleWorkForSinglePriorityLevel(This,priorityLevel,pInterruptEventName,pWorkScheduled) \ + ( (This)->lpVtbl -> ScheduleWorkForSinglePriorityLevel(This,priorityLevel,pInterruptEventName,pWorkScheduled) ) + +#define ICorSvcManager_Optimize(This,dwWorkerPriorityClass,pCompileProgressNotification,pInterruptEventName) \ + ( (This)->lpVtbl -> Optimize(This,dwWorkerPriorityClass,pCompileProgressNotification,pInterruptEventName) ) + +#define ICorSvcManager_NotifyService(This,notification) \ + ( (This)->lpVtbl -> NotifyService(This,notification) ) + +#define ICorSvcManager_IsWorkAvailable(This,priorityLevel,pWorkAvailable) \ + ( (This)->lpVtbl -> IsWorkAvailable(This,priorityLevel,pWorkAvailable) ) + +#define ICorSvcManager_Update(This,updateFlags,pInterruptEventName) \ + ( (This)->lpVtbl -> Update(This,updateFlags,pInterruptEventName) ) + +#define ICorSvcManager_SetSvcLogger(This,pCorSvcLogger) \ + ( (This)->lpVtbl -> SetSvcLogger(This,pCorSvcLogger) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcManager_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcManager2_INTERFACE_DEFINED__ +#define __ICorSvcManager2_INTERFACE_DEFINED__ + +/* interface ICorSvcManager2 */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcManager2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("29626056-8031-441b-affa-7a82480058b3") + ICorSvcManager2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetRuntimeVersion( + BSTR version) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetPackageMoniker( + BSTR moniker) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLocalAppData( + BSTR directory) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcManager2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcManager2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcManager2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcManager2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetRuntimeVersion )( + ICorSvcManager2 * This, + BSTR version); + + HRESULT ( STDMETHODCALLTYPE *SetPackageMoniker )( + ICorSvcManager2 * This, + BSTR moniker); + + HRESULT ( STDMETHODCALLTYPE *SetLocalAppData )( + ICorSvcManager2 * This, + BSTR directory); + + END_INTERFACE + } ICorSvcManager2Vtbl; + + interface ICorSvcManager2 + { + CONST_VTBL struct ICorSvcManager2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcManager2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcManager2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcManager2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcManager2_SetRuntimeVersion(This,version) \ + ( (This)->lpVtbl -> SetRuntimeVersion(This,version) ) + +#define ICorSvcManager2_SetPackageMoniker(This,moniker) \ + ( (This)->lpVtbl -> SetPackageMoniker(This,moniker) ) + +#define ICorSvcManager2_SetLocalAppData(This,directory) \ + ( (This)->lpVtbl -> SetLocalAppData(This,directory) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcManager2_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcSetLegacyServiceBehavior_INTERFACE_DEFINED__ +#define __ICorSvcSetLegacyServiceBehavior_INTERFACE_DEFINED__ + +/* interface ICorSvcSetLegacyServiceBehavior */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcSetLegacyServiceBehavior; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("35e5d609-ec3d-4fc2-9ba2-5f99e42ff42f") + ICorSvcSetLegacyServiceBehavior : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetLegacyServiceBehavior( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcSetLegacyServiceBehaviorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcSetLegacyServiceBehavior * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcSetLegacyServiceBehavior * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcSetLegacyServiceBehavior * This); + + HRESULT ( STDMETHODCALLTYPE *SetLegacyServiceBehavior )( + ICorSvcSetLegacyServiceBehavior * This); + + END_INTERFACE + } ICorSvcSetLegacyServiceBehaviorVtbl; + + interface ICorSvcSetLegacyServiceBehavior + { + CONST_VTBL struct ICorSvcSetLegacyServiceBehaviorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcSetLegacyServiceBehavior_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcSetLegacyServiceBehavior_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcSetLegacyServiceBehavior_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcSetLegacyServiceBehavior_SetLegacyServiceBehavior(This) \ + ( (This)->lpVtbl -> SetLegacyServiceBehavior(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcSetLegacyServiceBehavior_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcSetTaskBootTriggerState_INTERFACE_DEFINED__ +#define __ICorSvcSetTaskBootTriggerState_INTERFACE_DEFINED__ + +/* interface ICorSvcSetTaskBootTriggerState */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcSetTaskBootTriggerState; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("115466A4-7005-4CA3-971F-01F0A2C8EF09") + ICorSvcSetTaskBootTriggerState : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetTaskBootTriggerState( + BOOL bEnabled) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcSetTaskBootTriggerStateVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcSetTaskBootTriggerState * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcSetTaskBootTriggerState * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcSetTaskBootTriggerState * This); + + HRESULT ( STDMETHODCALLTYPE *SetTaskBootTriggerState )( + ICorSvcSetTaskBootTriggerState * This, + BOOL bEnabled); + + END_INTERFACE + } ICorSvcSetTaskBootTriggerStateVtbl; + + interface ICorSvcSetTaskBootTriggerState + { + CONST_VTBL struct ICorSvcSetTaskBootTriggerStateVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcSetTaskBootTriggerState_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcSetTaskBootTriggerState_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcSetTaskBootTriggerState_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcSetTaskBootTriggerState_SetTaskBootTriggerState(This,bEnabled) \ + ( (This)->lpVtbl -> SetTaskBootTriggerState(This,bEnabled) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcSetTaskBootTriggerState_INTERFACE_DEFINED__ */ + + +#ifndef __ICorSvcSetTaskDelayStartTriggerState_INTERFACE_DEFINED__ +#define __ICorSvcSetTaskDelayStartTriggerState_INTERFACE_DEFINED__ + +/* interface ICorSvcSetTaskDelayStartTriggerState */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_ICorSvcSetTaskDelayStartTriggerState; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("261DD1E3-F07E-4B8D-B54E-F26889413626") + ICorSvcSetTaskDelayStartTriggerState : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetTaskDelayStartTriggerState( + BOOL bEnabled) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorSvcSetTaskDelayStartTriggerStateVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorSvcSetTaskDelayStartTriggerState * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorSvcSetTaskDelayStartTriggerState * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorSvcSetTaskDelayStartTriggerState * This); + + HRESULT ( STDMETHODCALLTYPE *SetTaskDelayStartTriggerState )( + ICorSvcSetTaskDelayStartTriggerState * This, + BOOL bEnabled); + + END_INTERFACE + } ICorSvcSetTaskDelayStartTriggerStateVtbl; + + interface ICorSvcSetTaskDelayStartTriggerState + { + CONST_VTBL struct ICorSvcSetTaskDelayStartTriggerStateVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorSvcSetTaskDelayStartTriggerState_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorSvcSetTaskDelayStartTriggerState_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorSvcSetTaskDelayStartTriggerState_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorSvcSetTaskDelayStartTriggerState_SetTaskDelayStartTriggerState(This,bEnabled) \ + ( (This)->lpVtbl -> SetTaskDelayStartTriggerState(This,bEnabled) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorSvcSetTaskDelayStartTriggerState_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); +unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); +unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); +void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/ndpversion.h b/lib/coreclr/src/pal/prebuilt/inc/ndpversion.h new file mode 100644 index 0000000000..ba6d018266 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/ndpversion.h @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#include diff --git a/lib/coreclr/src/pal/prebuilt/inc/ndpversion_generated.h b/lib/coreclr/src/pal/prebuilt/inc/ndpversion_generated.h new file mode 100644 index 0000000000..563e316971 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/ndpversion_generated.h @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if 0 +/**** Generated Based on d:\ProjectK\src\InternalApis\Version\buildnumber.settings.targets +One can't put comments in this file (without the #if) +because this header is preprocessed in non-C++ context (xml, perl, etc.). *****/ +#endif +#define NDPVersionNumberMajor 4 +#define NDPVersionNumberMinor 0 +#define NDPVersionNumberMajor_A "4" +#define NDPVersionNumberMinor_A "00" +#define NDPVersionNumbers_A "4.00" +#include "buildnumber.h" diff --git a/lib/coreclr/src/pal/prebuilt/inc/product_version.h b/lib/coreclr/src/pal/prebuilt/inc/product_version.h new file mode 100644 index 0000000000..a21ee68741 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/product_version.h @@ -0,0 +1,113 @@ + +#if 0 + Version strings for product keys... no comments can be allowed in this + file due to some usage of this in the build process. + // Licensed to the .NET Foundation under one or more agreements. + // The .NET Foundation licenses this file to you under the MIT license. + // See the LICENSE file in the project root for more information. +#endif + +#include +#ifdef USE_CLR20_VERSION +#include +#else +#include +#endif + +#ifdef CLR_MAJOR_VERSION +#undef CLR_MAJOR_VERSION +#endif + +#ifdef CLR_MINOR_VERSION +#undef CLR_MINOR_VERSION +#endif + +#ifdef CLR_BUILD_VERSION +#undef CLR_BUILD_VERSION +#endif + +#ifdef CLR_BUILD_VERSION_QFE +#undef CLR_BUILD_VERSION_QFE +#endif + +#ifdef VER_FILEVERSIONMINOR +#undef VER_FILEVERSIONMINOR +#endif + +#ifdef VER_FILEVERSIONBUILD +#undef VER_FILEVERSIONBUILD +#endif + +#ifdef VER_FILEVERSIONREVISION +#undef VER_FILEVERSIONREVISION +#endif + +#define CLR_MAJOR_VERSION rmj +#define CLR_MINOR_VERSION rmm +#define CLR_BUILD_VERSION rup +#define CLR_BUILD_VERSION_QFE rpt + +#define VER_FILEVERSIONMINOR fvn +#define VER_FILEVERSIONBUILD fvb +#define VER_FILEVERSIONREVISION fvr + +#define VER_ASSEMBLYMAJORVERSION asm_rmj +#define VER_ASSEMBLYMINORVERSION asm_rmm +#define VER_ASSEMBLYBUILD asm_rup +#define VER_ASSEMBLYBUILD_QFE asm_rpt + +#define QUOTE_MACRO_HELPER(x) #x +#define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) + +#ifndef QUOTE_MACRO_L +#define QUOTE_MACRO_L_HELPER(x) L###x +#define QUOTE_MACRO_L(x) QUOTE_MACRO_L_HELPER(x) +#endif + +#define CONCAT_MACRO_HELPER(x, y) x ## y +#define CONCAT_MACRO(x, y) CONCAT_MACRO_HELPER(x, y) + +#define VER_PRODUCTVERSION CLR_MAJOR_VERSION,CLR_MINOR_VERSION,CLR_BUILD_VERSION,CLR_BUILD_VERSION_QFE +#define VER_DOTFILEVERSION CLR_MAJOR_VERSION,VER_FILEVERSIONMINOR,VER_FILEVERSIONBUILD,VER_FILEVERSIONREVISION +#define VER_MANAGED_DOTFILEVERSION CLR_MAJOR_VERSION.VER_FILEVERSIONMINOR.VER_FILEVERSIONBUILD.VER_FILEVERSIONREVISION + +#define VER_DOTPRODUCTVERSION CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION.CLR_BUILD_VERSION_QFE +#define VER_DOTPRODUCTMAJORMINOR CLR_MAJOR_VERSION.CLR_MINOR_VERSION +#define VER_DOTPRODUCTVERSIONNOQFE CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION +#define VER_DOTPRODUCTVERSIONZEROQFE CLR_MAJOR_VERSION.CLR_MINOR_VERSION.CLR_BUILD_VERSION.0 +#define VER_DOTASSEMBLYVERSION VER_ASSEMBLYMAJORVERSION.VER_ASSEMBLYMINORVERSION.VER_ASSEMBLYBUILD.VER_ASSEMBLYBUILD_QFE +#define VER_DOTASSEMBLYVERSION3PART VER_ASSEMBLYMAJORVERSION.VER_ASSEMBLYMINORVERSION.VER_ASSEMBLYBUILD + +#define VER_UNDERSCORE_PRODUCTVERSION_STR3 CONCAT_MACRO(_, CLR_BUILD_VERSION) +#define VER_UNDERSCORE_PRODUCTVERSION_STR2 CONCAT_MACRO(CLR_MINOR_VERSION, VER_UNDERSCORE_PRODUCTVERSION_STR3) +#define VER_UNDERSCORE_PRODUCTVERSION_STR1 CONCAT_MACRO(_, VER_UNDERSCORE_PRODUCTVERSION_STR2) +#define VER_UNDERSCORE_PRODUCTVERSION CONCAT_MACRO(CLR_MAJOR_VERSION, VER_UNDERSCORE_PRODUCTVERSION_STR1) + +#define VER_UNDERSCORE_PRODUCTVERSION_STR QUOTE_MACRO(VER_UNDERSCORE_PRODUCTVERSION) +#define VER_UNDERSCORE_PRODUCTVERSION_STR_L QUOTE_MACRO_L(VER_UNDERSCORE_PRODUCTVERSION) + +#define FX_FILEVERSION_STR QUOTE_MACRO(VER_MANAGED_DOTFILEVERSION) +#define VER_PRODUCTVERSION_STR QUOTE_MACRO(VER_DOTPRODUCTVERSION) +#define VER_PRODUCTVERSION_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSION) + +#define VER_PRODUCTMAJORMINOR_STR QUOTE_MACRO(VER_DOTPRODUCTMAJORMINOR) +#define VER_PRODUCTMAJORMINOR_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTMAJORMINOR) + +#define VER_PRODUCTVERSION_NO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONNOQFE) +#define VER_PRODUCTVERSION_NO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONNOQFE) + +#define VER_PRODUCTVERSION_ZERO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONZEROQFE) +#define VER_PRODUCTVERSION_ZERO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONZEROQFE) + +#define VER_PRODUCTVERSION_NO_QFE_STR QUOTE_MACRO(VER_DOTPRODUCTVERSIONNOQFE) +#define VER_PRODUCTVERSION_NO_QFE_STR_L QUOTE_MACRO_L(VER_DOTPRODUCTVERSIONNOQFE) + +#define VER_ASSEMBLYVERSION_STR QUOTE_MACRO(VER_DOTASSEMBLYVERSION) +#define VER_ASSEMBLYVERSION_STR_L QUOTE_MACRO_L(VER_DOTASSEMBLYVERSION) + +#define VER_ASSEMBLYVERSION3PART_STR QUOTE_MACRO(VER_DOTASSEMBLYVERSION3PART) +#define VER_ASSEMBLYVERSION3PART_STR_L QUOTE_MACRO_L(VER_DOTASSEMBLYVERSION3PART) + +#define VER_ECMA_PUBLICKEY b77a5c561934e089 +#define ECMA_PUBLICKEY_STR QUOTE_MACRO(VER_ECMA_PUBLICKEY) +#define ECMA_PUBLICKEY_STR_L QUOTE_MACRO_L(VER_ECMA_PUBLICKEY) diff --git a/lib/coreclr/src/pal/prebuilt/inc/readme.txt b/lib/coreclr/src/pal/prebuilt/inc/readme.txt new file mode 100644 index 0000000000..3b453d2d9d --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/readme.txt @@ -0,0 +1 @@ +This folder contains include files generated from idl sources. Since we cannot run MIDL on non-Windows platforms, we have to have them checked in. diff --git a/lib/coreclr/src/pal/prebuilt/inc/sospriv.h b/lib/coreclr/src/pal/prebuilt/inc/sospriv.h new file mode 100644 index 0000000000..8896720792 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/sospriv.h @@ -0,0 +1,2365 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0613 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for C:/ssd/coreclr/src/inc/sospriv.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.00.0613 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __sospriv_h__ +#define __sospriv_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ISOSEnum_FWD_DEFINED__ +#define __ISOSEnum_FWD_DEFINED__ +typedef interface ISOSEnum ISOSEnum; + +#endif /* __ISOSEnum_FWD_DEFINED__ */ + + +#ifndef __ISOSHandleEnum_FWD_DEFINED__ +#define __ISOSHandleEnum_FWD_DEFINED__ +typedef interface ISOSHandleEnum ISOSHandleEnum; + +#endif /* __ISOSHandleEnum_FWD_DEFINED__ */ + + +#ifndef __ISOSStackRefErrorEnum_FWD_DEFINED__ +#define __ISOSStackRefErrorEnum_FWD_DEFINED__ +typedef interface ISOSStackRefErrorEnum ISOSStackRefErrorEnum; + +#endif /* __ISOSStackRefErrorEnum_FWD_DEFINED__ */ + + +#ifndef __ISOSStackRefEnum_FWD_DEFINED__ +#define __ISOSStackRefEnum_FWD_DEFINED__ +typedef interface ISOSStackRefEnum ISOSStackRefEnum; + +#endif /* __ISOSStackRefEnum_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface_FWD_DEFINED__ +#define __ISOSDacInterface_FWD_DEFINED__ +typedef interface ISOSDacInterface ISOSDacInterface; + +#endif /* __ISOSDacInterface_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface2_FWD_DEFINED__ +#define __ISOSDacInterface2_FWD_DEFINED__ +typedef interface ISOSDacInterface2 ISOSDacInterface2; + +#endif /* __ISOSDacInterface2_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface3_FWD_DEFINED__ +#define __ISOSDacInterface3_FWD_DEFINED__ +typedef interface ISOSDacInterface3 ISOSDacInterface3; + +#endif /* __ISOSDacInterface3_FWD_DEFINED__ */ + + +#ifndef __ISOSDacInterface4_FWD_DEFINED__ +#define __ISOSDacInterface4_FWD_DEFINED__ +typedef interface ISOSDacInterface4 ISOSDacInterface4; + +#endif /* __ISOSDacInterface4_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "xclrdata.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_sospriv_0000_0000 */ +/* [local] */ + + + + + + + + + + + + + + + + + + + + + + + + + +#if 0 +typedef ULONG64 CLRDATA_ADDRESS; + +typedef int CONTEXT; + +typedef int T_CONTEXT; + +typedef int mdToken; + +typedef unsigned int size_t; + +typedef int ModuleMapType; + +typedef int VCSHeapType; + +#endif +enum ModuleMapType { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE }; +enum VCSHeapType {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap}; +typedef void ( *MODULEMAPTRAVERSE )( + UINT index, + CLRDATA_ADDRESS methodTable, + LPVOID token); + +typedef void ( *VISITHEAP )( + CLRDATA_ADDRESS blockData, + size_t blockSize, + BOOL blockIsCurrentBlock); + +typedef BOOL ( *VISITRCWFORCLEANUP )( + CLRDATA_ADDRESS RCW, + CLRDATA_ADDRESS Context, + CLRDATA_ADDRESS Thread, + BOOL bIsFreeThreaded, + LPVOID token); + +typedef BOOL ( *DUMPEHINFO )( + UINT clauseIndex, + UINT totalClauses, + struct DACEHInfo *pEHInfo, + LPVOID token); + +#ifndef _SOS_HandleData +#define _SOS_HandleData +typedef struct _SOSHandleData + { + CLRDATA_ADDRESS AppDomain; + CLRDATA_ADDRESS Handle; + CLRDATA_ADDRESS Secondary; + unsigned int Type; + BOOL StrongReference; + unsigned int RefCount; + unsigned int JupiterRefCount; + BOOL IsPegged; + } SOSHandleData; + +#endif //HandleData + + +extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0000_v0_0_s_ifspec; + +#ifndef __ISOSEnum_INTERFACE_DEFINED__ +#define __ISOSEnum_INTERFACE_DEFINED__ + +/* interface ISOSEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("286CA186-E763-4F61-9760-487D43AE4341") + ISOSEnum : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ unsigned int count) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCount( + /* [out] */ unsigned int *pCount) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSEnum * This, + /* [in] */ unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSEnum * This, + /* [out] */ unsigned int *pCount); + + END_INTERFACE + } ISOSEnumVtbl; + + interface ISOSEnum + { + CONST_VTBL struct ISOSEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSEnum_Skip(This,count) \ + ( (This)->lpVtbl -> Skip(This,count) ) + +#define ISOSEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ISOSEnum_GetCount(This,pCount) \ + ( (This)->lpVtbl -> GetCount(This,pCount) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSHandleEnum_INTERFACE_DEFINED__ +#define __ISOSHandleEnum_INTERFACE_DEFINED__ + +/* interface ISOSHandleEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSHandleEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3E269830-4A2B-4301-8EE2-D6805B29B2FA") + ISOSHandleEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSHandleData handles[ ], + /* [out] */ unsigned int *pNeeded) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSHandleEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSHandleEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSHandleEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSHandleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSHandleEnum * This, + /* [in] */ unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSHandleEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSHandleEnum * This, + /* [out] */ unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSHandleEnum * This, + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSHandleData handles[ ], + /* [out] */ unsigned int *pNeeded); + + END_INTERFACE + } ISOSHandleEnumVtbl; + + interface ISOSHandleEnum + { + CONST_VTBL struct ISOSHandleEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSHandleEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSHandleEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSHandleEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSHandleEnum_Skip(This,count) \ + ( (This)->lpVtbl -> Skip(This,count) ) + +#define ISOSHandleEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ISOSHandleEnum_GetCount(This,pCount) \ + ( (This)->lpVtbl -> GetCount(This,pCount) ) + + +#define ISOSHandleEnum_Next(This,count,handles,pNeeded) \ + ( (This)->lpVtbl -> Next(This,count,handles,pNeeded) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSHandleEnum_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_sospriv_0000_0002 */ +/* [local] */ + +#ifndef _SOS_StackReference_ +#define _SOS_StackReference_ +typedef +enum SOSStackSourceType + { + SOS_StackSourceIP = 0, + SOS_StackSourceFrame = ( SOS_StackSourceIP + 1 ) + } SOSStackSourceType; + +typedef +enum SOSRefFlags + { + SOSRefInterior = 1, + SOSRefPinned = 2 + } SOSRefFlags; + +typedef struct _SOS_StackRefData + { + BOOL HasRegisterInformation; + int Register; + int Offset; + CLRDATA_ADDRESS Address; + CLRDATA_ADDRESS Object; + unsigned int Flags; + SOSStackSourceType SourceType; + CLRDATA_ADDRESS Source; + CLRDATA_ADDRESS StackPointer; + } SOSStackRefData; + +typedef struct _SOS_StackRefError + { + SOSStackSourceType SourceType; + CLRDATA_ADDRESS Source; + CLRDATA_ADDRESS StackPointer; + } SOSStackRefError; + +#endif // _SOS_StackReference_ + + +extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_s_ifspec; + +#ifndef __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ +#define __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ + +/* interface ISOSStackRefErrorEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSStackRefErrorEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("774F4E1B-FB7B-491B-976D-A8130FE355E9") + ISOSStackRefErrorEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSStackRefError ref[ ], + /* [out] */ unsigned int *pFetched) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSStackRefErrorEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSStackRefErrorEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSStackRefErrorEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSStackRefErrorEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSStackRefErrorEnum * This, + /* [in] */ unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSStackRefErrorEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSStackRefErrorEnum * This, + /* [out] */ unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSStackRefErrorEnum * This, + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSStackRefError ref[ ], + /* [out] */ unsigned int *pFetched); + + END_INTERFACE + } ISOSStackRefErrorEnumVtbl; + + interface ISOSStackRefErrorEnum + { + CONST_VTBL struct ISOSStackRefErrorEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSStackRefErrorEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSStackRefErrorEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSStackRefErrorEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSStackRefErrorEnum_Skip(This,count) \ + ( (This)->lpVtbl -> Skip(This,count) ) + +#define ISOSStackRefErrorEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ISOSStackRefErrorEnum_GetCount(This,pCount) \ + ( (This)->lpVtbl -> GetCount(This,pCount) ) + + +#define ISOSStackRefErrorEnum_Next(This,count,ref,pFetched) \ + ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSStackRefEnum_INTERFACE_DEFINED__ +#define __ISOSStackRefEnum_INTERFACE_DEFINED__ + +/* interface ISOSStackRefEnum */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSStackRefEnum; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("8FA642BD-9F10-4799-9AA3-512AE78C77EE") + ISOSStackRefEnum : public ISOSEnum + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSStackRefData ref[ ], + /* [out] */ unsigned int *pFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumerateErrors( + /* [out] */ ISOSStackRefErrorEnum **ppEnum) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSStackRefEnumVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSStackRefEnum * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSStackRefEnum * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSStackRefEnum * This); + + HRESULT ( STDMETHODCALLTYPE *Skip )( + ISOSStackRefEnum * This, + /* [in] */ unsigned int count); + + HRESULT ( STDMETHODCALLTYPE *Reset )( + ISOSStackRefEnum * This); + + HRESULT ( STDMETHODCALLTYPE *GetCount )( + ISOSStackRefEnum * This, + /* [out] */ unsigned int *pCount); + + HRESULT ( STDMETHODCALLTYPE *Next )( + ISOSStackRefEnum * This, + /* [in] */ unsigned int count, + /* [length_is][size_is][out] */ SOSStackRefData ref[ ], + /* [out] */ unsigned int *pFetched); + + HRESULT ( STDMETHODCALLTYPE *EnumerateErrors )( + ISOSStackRefEnum * This, + /* [out] */ ISOSStackRefErrorEnum **ppEnum); + + END_INTERFACE + } ISOSStackRefEnumVtbl; + + interface ISOSStackRefEnum + { + CONST_VTBL struct ISOSStackRefEnumVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSStackRefEnum_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSStackRefEnum_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSStackRefEnum_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSStackRefEnum_Skip(This,count) \ + ( (This)->lpVtbl -> Skip(This,count) ) + +#define ISOSStackRefEnum_Reset(This) \ + ( (This)->lpVtbl -> Reset(This) ) + +#define ISOSStackRefEnum_GetCount(This,pCount) \ + ( (This)->lpVtbl -> GetCount(This,pCount) ) + + +#define ISOSStackRefEnum_Next(This,count,ref,pFetched) \ + ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) + +#define ISOSStackRefEnum_EnumerateErrors(This,ppEnum) \ + ( (This)->lpVtbl -> EnumerateErrors(This,ppEnum) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSStackRefEnum_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface_INTERFACE_DEFINED__ +#define __ISOSDacInterface_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("436f00f2-b42a-4b9f-870c-e73db66ae930") + ISOSDacInterface : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetThreadStoreData( + struct DacpThreadStoreData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainStoreData( + struct DacpAppDomainStoreData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainList( + unsigned int count, + CLRDATA_ADDRESS values[ ], + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainData( + CLRDATA_ADDRESS addr, + struct DacpAppDomainData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainName( + CLRDATA_ADDRESS addr, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDomainFromContext( + CLRDATA_ADDRESS context, + CLRDATA_ADDRESS *domain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyList( + CLRDATA_ADDRESS appDomain, + int count, + CLRDATA_ADDRESS values[ ], + int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyData( + CLRDATA_ADDRESS baseDomainPtr, + CLRDATA_ADDRESS assembly, + struct DacpAssemblyData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyName( + CLRDATA_ADDRESS assembly, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModule( + CLRDATA_ADDRESS addr, + IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleData( + CLRDATA_ADDRESS moduleAddr, + struct DacpModuleData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE TraverseModuleMap( + ModuleMapType mmt, + CLRDATA_ADDRESS moduleAddr, + MODULEMAPTRAVERSE pCallback, + LPVOID token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyModuleList( + CLRDATA_ADDRESS assembly, + unsigned int count, + CLRDATA_ADDRESS modules[ ], + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILForModule( + CLRDATA_ADDRESS moduleAddr, + DWORD rva, + CLRDATA_ADDRESS *il) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadData( + CLRDATA_ADDRESS thread, + struct DacpThreadData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadFromThinlockID( + UINT thinLockId, + CLRDATA_ADDRESS *pThread) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackLimits( + CLRDATA_ADDRESS threadPtr, + CLRDATA_ADDRESS *lower, + CLRDATA_ADDRESS *upper, + CLRDATA_ADDRESS *fp) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescData( + CLRDATA_ADDRESS methodDesc, + CLRDATA_ADDRESS ip, + struct DacpMethodDescData *data, + ULONG cRevertedRejitVersions, + struct DacpReJitData *rgRevertedRejitData, + ULONG *pcNeededRevertedRejitData) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromIP( + CLRDATA_ADDRESS ip, + CLRDATA_ADDRESS *ppMD) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescName( + CLRDATA_ADDRESS methodDesc, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromFrame( + CLRDATA_ADDRESS frameAddr, + CLRDATA_ADDRESS *ppMD) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescFromToken( + CLRDATA_ADDRESS moduleAddr, + mdToken token, + CLRDATA_ADDRESS *methodDesc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDescTransparencyData( + CLRDATA_ADDRESS methodDesc, + struct DacpMethodDescTransparencyData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeHeaderData( + CLRDATA_ADDRESS ip, + struct DacpCodeHeaderData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetJitManagerList( + unsigned int count, + struct DacpJitManagerInfo *managers, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetJitHelperFunctionName( + CLRDATA_ADDRESS ip, + unsigned int count, + char *name, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetJumpThunkTarget( + T_CONTEXT *ctx, + CLRDATA_ADDRESS *targetIP, + CLRDATA_ADDRESS *targetMD) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadpoolData( + struct DacpThreadpoolData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetWorkRequestData( + CLRDATA_ADDRESS addrWorkRequest, + struct DacpWorkRequestData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHillClimbingLogEntry( + CLRDATA_ADDRESS addr, + struct DacpHillClimbingLogEntry *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectData( + CLRDATA_ADDRESS objAddr, + struct DacpObjectData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectStringData( + CLRDATA_ADDRESS obj, + unsigned int count, + WCHAR *stringData, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetObjectClassName( + CLRDATA_ADDRESS obj, + unsigned int count, + WCHAR *className, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableName( + CLRDATA_ADDRESS mt, + unsigned int count, + WCHAR *mtName, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableData( + CLRDATA_ADDRESS mt, + struct DacpMethodTableData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlot( + CLRDATA_ADDRESS mt, + unsigned int slot, + CLRDATA_ADDRESS *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableFieldData( + CLRDATA_ADDRESS mt, + struct DacpMethodTableFieldData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableTransparencyData( + CLRDATA_ADDRESS mt, + struct DacpMethodTableTransparencyData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodTableForEEClass( + CLRDATA_ADDRESS eeClass, + CLRDATA_ADDRESS *value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldDescData( + CLRDATA_ADDRESS fieldDesc, + struct DacpFieldDescData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFrameName( + CLRDATA_ADDRESS vtable, + unsigned int count, + WCHAR *frameName, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPEFileBase( + CLRDATA_ADDRESS addr, + CLRDATA_ADDRESS *base) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPEFileName( + CLRDATA_ADDRESS addr, + unsigned int count, + WCHAR *fileName, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCHeapData( + struct DacpGcHeapData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCHeapList( + unsigned int count, + CLRDATA_ADDRESS heaps[ ], + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCHeapDetails( + CLRDATA_ADDRESS heap, + struct DacpGcHeapDetails *details) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCHeapStaticData( + struct DacpGcHeapDetails *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHeapSegmentData( + CLRDATA_ADDRESS seg, + struct DacpHeapSegmentData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOOMData( + CLRDATA_ADDRESS oomAddr, + struct DacpOomData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOOMStaticData( + struct DacpOomData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeData( + CLRDATA_ADDRESS addr, + struct DacpGcHeapAnalyzeData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeStaticData( + struct DacpGcHeapAnalyzeData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleData( + CLRDATA_ADDRESS addr, + struct DacpDomainLocalModuleData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromAppDomain( + CLRDATA_ADDRESS appDomainAddr, + int moduleID, + struct DacpDomainLocalModuleData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromModule( + CLRDATA_ADDRESS moduleAddr, + struct DacpDomainLocalModuleData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadLocalModuleData( + CLRDATA_ADDRESS thread, + unsigned int index, + struct DacpThreadLocalModuleData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSyncBlockData( + unsigned int number, + struct DacpSyncBlockData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSyncBlockCleanupData( + CLRDATA_ADDRESS addr, + struct DacpSyncBlockCleanupData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandleEnum( + ISOSHandleEnum **ppHandleEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForTypes( + unsigned int types[ ], + unsigned int count, + ISOSHandleEnum **ppHandleEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForGC( + unsigned int gen, + ISOSHandleEnum **ppHandleEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE TraverseEHInfo( + CLRDATA_ADDRESS ip, + DUMPEHINFO pCallback, + LPVOID token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNestedExceptionData( + CLRDATA_ADDRESS exception, + CLRDATA_ADDRESS *exceptionObject, + CLRDATA_ADDRESS *nextNestedException) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStressLogAddress( + CLRDATA_ADDRESS *stressLog) = 0; + + virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap( + CLRDATA_ADDRESS loaderHeapAddr, + VISITHEAP pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeHeapList( + CLRDATA_ADDRESS jitManager, + unsigned int count, + struct DacpJitCodeHeapInfo *codeHeaps, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE TraverseVirtCallStubHeap( + CLRDATA_ADDRESS pAppDomain, + VCSHeapType heaptype, + VISITHEAP pCallback) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUsefulGlobals( + struct DacpUsefulGlobalsData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetClrWatsonBuckets( + CLRDATA_ADDRESS thread, + void *pGenericModeBlock) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTLSIndex( + ULONG *pIndex) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDacModuleHandle( + HMODULE *phModule) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRCWData( + CLRDATA_ADDRESS addr, + struct DacpRCWData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRCWInterfaces( + CLRDATA_ADDRESS rcw, + unsigned int count, + struct DacpCOMInterfacePointerData *interfaces, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCCWData( + CLRDATA_ADDRESS ccw, + struct DacpCCWData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCCWInterfaces( + CLRDATA_ADDRESS ccw, + unsigned int count, + struct DacpCOMInterfacePointerData *interfaces, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE TraverseRCWCleanupList( + CLRDATA_ADDRESS cleanupListPtr, + VISITRCWFORCLEANUP pCallback, + LPVOID token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackReferences( + /* [in] */ DWORD osThreadID, + /* [out] */ ISOSStackRefEnum **ppEnum) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRegisterName( + /* [in] */ int regName, + /* [in] */ unsigned int count, + /* [out] */ WCHAR *buffer, + /* [out] */ unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetThreadAllocData( + CLRDATA_ADDRESS thread, + struct DacpAllocData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHeapAllocData( + unsigned int count, + struct DacpGenerationAllocData *data, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyList( + CLRDATA_ADDRESS appDomain, + int count, + CLRDATA_ADDRESS values[ ], + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPrivateBinPaths( + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *paths, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssemblyLocation( + CLRDATA_ADDRESS assembly, + int count, + WCHAR *location, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainConfigFile( + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *configFile, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetApplicationBase( + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *base, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyData( + CLRDATA_ADDRESS assembly, + unsigned int *pContext, + HRESULT *pResult) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyLocation( + CLRDATA_ADDRESS assesmbly, + unsigned int count, + WCHAR *location, + unsigned int *pNeeded) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyDisplayName( + CLRDATA_ADDRESS assembly, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterfaceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface * This); + + HRESULT ( STDMETHODCALLTYPE *GetThreadStoreData )( + ISOSDacInterface * This, + struct DacpThreadStoreData *data); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainStoreData )( + ISOSDacInterface * This, + struct DacpAppDomainStoreData *data); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainList )( + ISOSDacInterface * This, + unsigned int count, + CLRDATA_ADDRESS values[ ], + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpAppDomainData *data); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetDomainFromContext )( + ISOSDacInterface * This, + CLRDATA_ADDRESS context, + CLRDATA_ADDRESS *domain); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyList )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomain, + int count, + CLRDATA_ADDRESS values[ ], + int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS baseDomainPtr, + CLRDATA_ADDRESS assembly, + struct DacpAssemblyData *data); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assembly, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *GetModuleData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS moduleAddr, + struct DacpModuleData *data); + + HRESULT ( STDMETHODCALLTYPE *TraverseModuleMap )( + ISOSDacInterface * This, + ModuleMapType mmt, + CLRDATA_ADDRESS moduleAddr, + MODULEMAPTRAVERSE pCallback, + LPVOID token); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyModuleList )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assembly, + unsigned int count, + CLRDATA_ADDRESS modules[ ], + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetILForModule )( + ISOSDacInterface * This, + CLRDATA_ADDRESS moduleAddr, + DWORD rva, + CLRDATA_ADDRESS *il); + + HRESULT ( STDMETHODCALLTYPE *GetThreadData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS thread, + struct DacpThreadData *data); + + HRESULT ( STDMETHODCALLTYPE *GetThreadFromThinlockID )( + ISOSDacInterface * This, + UINT thinLockId, + CLRDATA_ADDRESS *pThread); + + HRESULT ( STDMETHODCALLTYPE *GetStackLimits )( + ISOSDacInterface * This, + CLRDATA_ADDRESS threadPtr, + CLRDATA_ADDRESS *lower, + CLRDATA_ADDRESS *upper, + CLRDATA_ADDRESS *fp); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS methodDesc, + CLRDATA_ADDRESS ip, + struct DacpMethodDescData *data, + ULONG cRevertedRejitVersions, + struct DacpReJitData *rgRevertedRejitData, + ULONG *pcNeededRevertedRejitData); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescPtrFromIP )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ip, + CLRDATA_ADDRESS *ppMD); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS methodDesc, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescPtrFromFrame )( + ISOSDacInterface * This, + CLRDATA_ADDRESS frameAddr, + CLRDATA_ADDRESS *ppMD); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescFromToken )( + ISOSDacInterface * This, + CLRDATA_ADDRESS moduleAddr, + mdToken token, + CLRDATA_ADDRESS *methodDesc); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDescTransparencyData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS methodDesc, + struct DacpMethodDescTransparencyData *data); + + HRESULT ( STDMETHODCALLTYPE *GetCodeHeaderData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ip, + struct DacpCodeHeaderData *data); + + HRESULT ( STDMETHODCALLTYPE *GetJitManagerList )( + ISOSDacInterface * This, + unsigned int count, + struct DacpJitManagerInfo *managers, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetJitHelperFunctionName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ip, + unsigned int count, + char *name, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetJumpThunkTarget )( + ISOSDacInterface * This, + T_CONTEXT *ctx, + CLRDATA_ADDRESS *targetIP, + CLRDATA_ADDRESS *targetMD); + + HRESULT ( STDMETHODCALLTYPE *GetThreadpoolData )( + ISOSDacInterface * This, + struct DacpThreadpoolData *data); + + HRESULT ( STDMETHODCALLTYPE *GetWorkRequestData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addrWorkRequest, + struct DacpWorkRequestData *data); + + HRESULT ( STDMETHODCALLTYPE *GetHillClimbingLogEntry )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpHillClimbingLogEntry *data); + + HRESULT ( STDMETHODCALLTYPE *GetObjectData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS objAddr, + struct DacpObjectData *data); + + HRESULT ( STDMETHODCALLTYPE *GetObjectStringData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS obj, + unsigned int count, + WCHAR *stringData, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetObjectClassName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS obj, + unsigned int count, + WCHAR *className, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS mt, + unsigned int count, + WCHAR *mtName, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS mt, + struct DacpMethodTableData *data); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableSlot )( + ISOSDacInterface * This, + CLRDATA_ADDRESS mt, + unsigned int slot, + CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableFieldData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS mt, + struct DacpMethodTableFieldData *data); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableTransparencyData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS mt, + struct DacpMethodTableTransparencyData *data); + + HRESULT ( STDMETHODCALLTYPE *GetMethodTableForEEClass )( + ISOSDacInterface * This, + CLRDATA_ADDRESS eeClass, + CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *GetFieldDescData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS fieldDesc, + struct DacpFieldDescData *data); + + HRESULT ( STDMETHODCALLTYPE *GetFrameName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS vtable, + unsigned int count, + WCHAR *frameName, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetPEFileBase )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + CLRDATA_ADDRESS *base); + + HRESULT ( STDMETHODCALLTYPE *GetPEFileName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + unsigned int count, + WCHAR *fileName, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapData )( + ISOSDacInterface * This, + struct DacpGcHeapData *data); + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapList )( + ISOSDacInterface * This, + unsigned int count, + CLRDATA_ADDRESS heaps[ ], + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapDetails )( + ISOSDacInterface * This, + CLRDATA_ADDRESS heap, + struct DacpGcHeapDetails *details); + + HRESULT ( STDMETHODCALLTYPE *GetGCHeapStaticData )( + ISOSDacInterface * This, + struct DacpGcHeapDetails *data); + + HRESULT ( STDMETHODCALLTYPE *GetHeapSegmentData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS seg, + struct DacpHeapSegmentData *data); + + HRESULT ( STDMETHODCALLTYPE *GetOOMData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS oomAddr, + struct DacpOomData *data); + + HRESULT ( STDMETHODCALLTYPE *GetOOMStaticData )( + ISOSDacInterface * This, + struct DacpOomData *data); + + HRESULT ( STDMETHODCALLTYPE *GetHeapAnalyzeData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpGcHeapAnalyzeData *data); + + HRESULT ( STDMETHODCALLTYPE *GetHeapAnalyzeStaticData )( + ISOSDacInterface * This, + struct DacpGcHeapAnalyzeData *data); + + HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpDomainLocalModuleData *data); + + HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleDataFromAppDomain )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomainAddr, + int moduleID, + struct DacpDomainLocalModuleData *data); + + HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleDataFromModule )( + ISOSDacInterface * This, + CLRDATA_ADDRESS moduleAddr, + struct DacpDomainLocalModuleData *data); + + HRESULT ( STDMETHODCALLTYPE *GetThreadLocalModuleData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS thread, + unsigned int index, + struct DacpThreadLocalModuleData *data); + + HRESULT ( STDMETHODCALLTYPE *GetSyncBlockData )( + ISOSDacInterface * This, + unsigned int number, + struct DacpSyncBlockData *data); + + HRESULT ( STDMETHODCALLTYPE *GetSyncBlockCleanupData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpSyncBlockCleanupData *data); + + HRESULT ( STDMETHODCALLTYPE *GetHandleEnum )( + ISOSDacInterface * This, + ISOSHandleEnum **ppHandleEnum); + + HRESULT ( STDMETHODCALLTYPE *GetHandleEnumForTypes )( + ISOSDacInterface * This, + unsigned int types[ ], + unsigned int count, + ISOSHandleEnum **ppHandleEnum); + + HRESULT ( STDMETHODCALLTYPE *GetHandleEnumForGC )( + ISOSDacInterface * This, + unsigned int gen, + ISOSHandleEnum **ppHandleEnum); + + HRESULT ( STDMETHODCALLTYPE *TraverseEHInfo )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ip, + DUMPEHINFO pCallback, + LPVOID token); + + HRESULT ( STDMETHODCALLTYPE *GetNestedExceptionData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS exception, + CLRDATA_ADDRESS *exceptionObject, + CLRDATA_ADDRESS *nextNestedException); + + HRESULT ( STDMETHODCALLTYPE *GetStressLogAddress )( + ISOSDacInterface * This, + CLRDATA_ADDRESS *stressLog); + + HRESULT ( STDMETHODCALLTYPE *TraverseLoaderHeap )( + ISOSDacInterface * This, + CLRDATA_ADDRESS loaderHeapAddr, + VISITHEAP pCallback); + + HRESULT ( STDMETHODCALLTYPE *GetCodeHeapList )( + ISOSDacInterface * This, + CLRDATA_ADDRESS jitManager, + unsigned int count, + struct DacpJitCodeHeapInfo *codeHeaps, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *TraverseVirtCallStubHeap )( + ISOSDacInterface * This, + CLRDATA_ADDRESS pAppDomain, + VCSHeapType heaptype, + VISITHEAP pCallback); + + HRESULT ( STDMETHODCALLTYPE *GetUsefulGlobals )( + ISOSDacInterface * This, + struct DacpUsefulGlobalsData *data); + + HRESULT ( STDMETHODCALLTYPE *GetClrWatsonBuckets )( + ISOSDacInterface * This, + CLRDATA_ADDRESS thread, + void *pGenericModeBlock); + + HRESULT ( STDMETHODCALLTYPE *GetTLSIndex )( + ISOSDacInterface * This, + ULONG *pIndex); + + HRESULT ( STDMETHODCALLTYPE *GetDacModuleHandle )( + ISOSDacInterface * This, + HMODULE *phModule); + + HRESULT ( STDMETHODCALLTYPE *GetRCWData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS addr, + struct DacpRCWData *data); + + HRESULT ( STDMETHODCALLTYPE *GetRCWInterfaces )( + ISOSDacInterface * This, + CLRDATA_ADDRESS rcw, + unsigned int count, + struct DacpCOMInterfacePointerData *interfaces, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetCCWData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ccw, + struct DacpCCWData *data); + + HRESULT ( STDMETHODCALLTYPE *GetCCWInterfaces )( + ISOSDacInterface * This, + CLRDATA_ADDRESS ccw, + unsigned int count, + struct DacpCOMInterfacePointerData *interfaces, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *TraverseRCWCleanupList )( + ISOSDacInterface * This, + CLRDATA_ADDRESS cleanupListPtr, + VISITRCWFORCLEANUP pCallback, + LPVOID token); + + HRESULT ( STDMETHODCALLTYPE *GetStackReferences )( + ISOSDacInterface * This, + /* [in] */ DWORD osThreadID, + /* [out] */ ISOSStackRefEnum **ppEnum); + + HRESULT ( STDMETHODCALLTYPE *GetRegisterName )( + ISOSDacInterface * This, + /* [in] */ int regName, + /* [in] */ unsigned int count, + /* [out] */ WCHAR *buffer, + /* [out] */ unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetThreadAllocData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS thread, + struct DacpAllocData *data); + + HRESULT ( STDMETHODCALLTYPE *GetHeapAllocData )( + ISOSDacInterface * This, + unsigned int count, + struct DacpGenerationAllocData *data, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyList )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomain, + int count, + CLRDATA_ADDRESS values[ ], + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetPrivateBinPaths )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *paths, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetAssemblyLocation )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assembly, + int count, + WCHAR *location, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainConfigFile )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *configFile, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetApplicationBase )( + ISOSDacInterface * This, + CLRDATA_ADDRESS appDomain, + int count, + WCHAR *base, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyData )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assembly, + unsigned int *pContext, + HRESULT *pResult); + + HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyLocation )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assesmbly, + unsigned int count, + WCHAR *location, + unsigned int *pNeeded); + + HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyDisplayName )( + ISOSDacInterface * This, + CLRDATA_ADDRESS assembly, + unsigned int count, + WCHAR *name, + unsigned int *pNeeded); + + END_INTERFACE + } ISOSDacInterfaceVtbl; + + interface ISOSDacInterface + { + CONST_VTBL struct ISOSDacInterfaceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface_GetThreadStoreData(This,data) \ + ( (This)->lpVtbl -> GetThreadStoreData(This,data) ) + +#define ISOSDacInterface_GetAppDomainStoreData(This,data) \ + ( (This)->lpVtbl -> GetAppDomainStoreData(This,data) ) + +#define ISOSDacInterface_GetAppDomainList(This,count,values,pNeeded) \ + ( (This)->lpVtbl -> GetAppDomainList(This,count,values,pNeeded) ) + +#define ISOSDacInterface_GetAppDomainData(This,addr,data) \ + ( (This)->lpVtbl -> GetAppDomainData(This,addr,data) ) + +#define ISOSDacInterface_GetAppDomainName(This,addr,count,name,pNeeded) \ + ( (This)->lpVtbl -> GetAppDomainName(This,addr,count,name,pNeeded) ) + +#define ISOSDacInterface_GetDomainFromContext(This,context,domain) \ + ( (This)->lpVtbl -> GetDomainFromContext(This,context,domain) ) + +#define ISOSDacInterface_GetAssemblyList(This,appDomain,count,values,pNeeded) \ + ( (This)->lpVtbl -> GetAssemblyList(This,appDomain,count,values,pNeeded) ) + +#define ISOSDacInterface_GetAssemblyData(This,baseDomainPtr,assembly,data) \ + ( (This)->lpVtbl -> GetAssemblyData(This,baseDomainPtr,assembly,data) ) + +#define ISOSDacInterface_GetAssemblyName(This,assembly,count,name,pNeeded) \ + ( (This)->lpVtbl -> GetAssemblyName(This,assembly,count,name,pNeeded) ) + +#define ISOSDacInterface_GetModule(This,addr,mod) \ + ( (This)->lpVtbl -> GetModule(This,addr,mod) ) + +#define ISOSDacInterface_GetModuleData(This,moduleAddr,data) \ + ( (This)->lpVtbl -> GetModuleData(This,moduleAddr,data) ) + +#define ISOSDacInterface_TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) \ + ( (This)->lpVtbl -> TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) ) + +#define ISOSDacInterface_GetAssemblyModuleList(This,assembly,count,modules,pNeeded) \ + ( (This)->lpVtbl -> GetAssemblyModuleList(This,assembly,count,modules,pNeeded) ) + +#define ISOSDacInterface_GetILForModule(This,moduleAddr,rva,il) \ + ( (This)->lpVtbl -> GetILForModule(This,moduleAddr,rva,il) ) + +#define ISOSDacInterface_GetThreadData(This,thread,data) \ + ( (This)->lpVtbl -> GetThreadData(This,thread,data) ) + +#define ISOSDacInterface_GetThreadFromThinlockID(This,thinLockId,pThread) \ + ( (This)->lpVtbl -> GetThreadFromThinlockID(This,thinLockId,pThread) ) + +#define ISOSDacInterface_GetStackLimits(This,threadPtr,lower,upper,fp) \ + ( (This)->lpVtbl -> GetStackLimits(This,threadPtr,lower,upper,fp) ) + +#define ISOSDacInterface_GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) \ + ( (This)->lpVtbl -> GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) ) + +#define ISOSDacInterface_GetMethodDescPtrFromIP(This,ip,ppMD) \ + ( (This)->lpVtbl -> GetMethodDescPtrFromIP(This,ip,ppMD) ) + +#define ISOSDacInterface_GetMethodDescName(This,methodDesc,count,name,pNeeded) \ + ( (This)->lpVtbl -> GetMethodDescName(This,methodDesc,count,name,pNeeded) ) + +#define ISOSDacInterface_GetMethodDescPtrFromFrame(This,frameAddr,ppMD) \ + ( (This)->lpVtbl -> GetMethodDescPtrFromFrame(This,frameAddr,ppMD) ) + +#define ISOSDacInterface_GetMethodDescFromToken(This,moduleAddr,token,methodDesc) \ + ( (This)->lpVtbl -> GetMethodDescFromToken(This,moduleAddr,token,methodDesc) ) + +#define ISOSDacInterface_GetMethodDescTransparencyData(This,methodDesc,data) \ + ( (This)->lpVtbl -> GetMethodDescTransparencyData(This,methodDesc,data) ) + +#define ISOSDacInterface_GetCodeHeaderData(This,ip,data) \ + ( (This)->lpVtbl -> GetCodeHeaderData(This,ip,data) ) + +#define ISOSDacInterface_GetJitManagerList(This,count,managers,pNeeded) \ + ( (This)->lpVtbl -> GetJitManagerList(This,count,managers,pNeeded) ) + +#define ISOSDacInterface_GetJitHelperFunctionName(This,ip,count,name,pNeeded) \ + ( (This)->lpVtbl -> GetJitHelperFunctionName(This,ip,count,name,pNeeded) ) + +#define ISOSDacInterface_GetJumpThunkTarget(This,ctx,targetIP,targetMD) \ + ( (This)->lpVtbl -> GetJumpThunkTarget(This,ctx,targetIP,targetMD) ) + +#define ISOSDacInterface_GetThreadpoolData(This,data) \ + ( (This)->lpVtbl -> GetThreadpoolData(This,data) ) + +#define ISOSDacInterface_GetWorkRequestData(This,addrWorkRequest,data) \ + ( (This)->lpVtbl -> GetWorkRequestData(This,addrWorkRequest,data) ) + +#define ISOSDacInterface_GetHillClimbingLogEntry(This,addr,data) \ + ( (This)->lpVtbl -> GetHillClimbingLogEntry(This,addr,data) ) + +#define ISOSDacInterface_GetObjectData(This,objAddr,data) \ + ( (This)->lpVtbl -> GetObjectData(This,objAddr,data) ) + +#define ISOSDacInterface_GetObjectStringData(This,obj,count,stringData,pNeeded) \ + ( (This)->lpVtbl -> GetObjectStringData(This,obj,count,stringData,pNeeded) ) + +#define ISOSDacInterface_GetObjectClassName(This,obj,count,className,pNeeded) \ + ( (This)->lpVtbl -> GetObjectClassName(This,obj,count,className,pNeeded) ) + +#define ISOSDacInterface_GetMethodTableName(This,mt,count,mtName,pNeeded) \ + ( (This)->lpVtbl -> GetMethodTableName(This,mt,count,mtName,pNeeded) ) + +#define ISOSDacInterface_GetMethodTableData(This,mt,data) \ + ( (This)->lpVtbl -> GetMethodTableData(This,mt,data) ) + +#define ISOSDacInterface_GetMethodTableSlot(This,mt,slot,value) \ + ( (This)->lpVtbl -> GetMethodTableSlot(This,mt,slot,value) ) + +#define ISOSDacInterface_GetMethodTableFieldData(This,mt,data) \ + ( (This)->lpVtbl -> GetMethodTableFieldData(This,mt,data) ) + +#define ISOSDacInterface_GetMethodTableTransparencyData(This,mt,data) \ + ( (This)->lpVtbl -> GetMethodTableTransparencyData(This,mt,data) ) + +#define ISOSDacInterface_GetMethodTableForEEClass(This,eeClass,value) \ + ( (This)->lpVtbl -> GetMethodTableForEEClass(This,eeClass,value) ) + +#define ISOSDacInterface_GetFieldDescData(This,fieldDesc,data) \ + ( (This)->lpVtbl -> GetFieldDescData(This,fieldDesc,data) ) + +#define ISOSDacInterface_GetFrameName(This,vtable,count,frameName,pNeeded) \ + ( (This)->lpVtbl -> GetFrameName(This,vtable,count,frameName,pNeeded) ) + +#define ISOSDacInterface_GetPEFileBase(This,addr,base) \ + ( (This)->lpVtbl -> GetPEFileBase(This,addr,base) ) + +#define ISOSDacInterface_GetPEFileName(This,addr,count,fileName,pNeeded) \ + ( (This)->lpVtbl -> GetPEFileName(This,addr,count,fileName,pNeeded) ) + +#define ISOSDacInterface_GetGCHeapData(This,data) \ + ( (This)->lpVtbl -> GetGCHeapData(This,data) ) + +#define ISOSDacInterface_GetGCHeapList(This,count,heaps,pNeeded) \ + ( (This)->lpVtbl -> GetGCHeapList(This,count,heaps,pNeeded) ) + +#define ISOSDacInterface_GetGCHeapDetails(This,heap,details) \ + ( (This)->lpVtbl -> GetGCHeapDetails(This,heap,details) ) + +#define ISOSDacInterface_GetGCHeapStaticData(This,data) \ + ( (This)->lpVtbl -> GetGCHeapStaticData(This,data) ) + +#define ISOSDacInterface_GetHeapSegmentData(This,seg,data) \ + ( (This)->lpVtbl -> GetHeapSegmentData(This,seg,data) ) + +#define ISOSDacInterface_GetOOMData(This,oomAddr,data) \ + ( (This)->lpVtbl -> GetOOMData(This,oomAddr,data) ) + +#define ISOSDacInterface_GetOOMStaticData(This,data) \ + ( (This)->lpVtbl -> GetOOMStaticData(This,data) ) + +#define ISOSDacInterface_GetHeapAnalyzeData(This,addr,data) \ + ( (This)->lpVtbl -> GetHeapAnalyzeData(This,addr,data) ) + +#define ISOSDacInterface_GetHeapAnalyzeStaticData(This,data) \ + ( (This)->lpVtbl -> GetHeapAnalyzeStaticData(This,data) ) + +#define ISOSDacInterface_GetDomainLocalModuleData(This,addr,data) \ + ( (This)->lpVtbl -> GetDomainLocalModuleData(This,addr,data) ) + +#define ISOSDacInterface_GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) \ + ( (This)->lpVtbl -> GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) ) + +#define ISOSDacInterface_GetDomainLocalModuleDataFromModule(This,moduleAddr,data) \ + ( (This)->lpVtbl -> GetDomainLocalModuleDataFromModule(This,moduleAddr,data) ) + +#define ISOSDacInterface_GetThreadLocalModuleData(This,thread,index,data) \ + ( (This)->lpVtbl -> GetThreadLocalModuleData(This,thread,index,data) ) + +#define ISOSDacInterface_GetSyncBlockData(This,number,data) \ + ( (This)->lpVtbl -> GetSyncBlockData(This,number,data) ) + +#define ISOSDacInterface_GetSyncBlockCleanupData(This,addr,data) \ + ( (This)->lpVtbl -> GetSyncBlockCleanupData(This,addr,data) ) + +#define ISOSDacInterface_GetHandleEnum(This,ppHandleEnum) \ + ( (This)->lpVtbl -> GetHandleEnum(This,ppHandleEnum) ) + +#define ISOSDacInterface_GetHandleEnumForTypes(This,types,count,ppHandleEnum) \ + ( (This)->lpVtbl -> GetHandleEnumForTypes(This,types,count,ppHandleEnum) ) + +#define ISOSDacInterface_GetHandleEnumForGC(This,gen,ppHandleEnum) \ + ( (This)->lpVtbl -> GetHandleEnumForGC(This,gen,ppHandleEnum) ) + +#define ISOSDacInterface_TraverseEHInfo(This,ip,pCallback,token) \ + ( (This)->lpVtbl -> TraverseEHInfo(This,ip,pCallback,token) ) + +#define ISOSDacInterface_GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) \ + ( (This)->lpVtbl -> GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) ) + +#define ISOSDacInterface_GetStressLogAddress(This,stressLog) \ + ( (This)->lpVtbl -> GetStressLogAddress(This,stressLog) ) + +#define ISOSDacInterface_TraverseLoaderHeap(This,loaderHeapAddr,pCallback) \ + ( (This)->lpVtbl -> TraverseLoaderHeap(This,loaderHeapAddr,pCallback) ) + +#define ISOSDacInterface_GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) \ + ( (This)->lpVtbl -> GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) ) + +#define ISOSDacInterface_TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) \ + ( (This)->lpVtbl -> TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) ) + +#define ISOSDacInterface_GetUsefulGlobals(This,data) \ + ( (This)->lpVtbl -> GetUsefulGlobals(This,data) ) + +#define ISOSDacInterface_GetClrWatsonBuckets(This,thread,pGenericModeBlock) \ + ( (This)->lpVtbl -> GetClrWatsonBuckets(This,thread,pGenericModeBlock) ) + +#define ISOSDacInterface_GetTLSIndex(This,pIndex) \ + ( (This)->lpVtbl -> GetTLSIndex(This,pIndex) ) + +#define ISOSDacInterface_GetDacModuleHandle(This,phModule) \ + ( (This)->lpVtbl -> GetDacModuleHandle(This,phModule) ) + +#define ISOSDacInterface_GetRCWData(This,addr,data) \ + ( (This)->lpVtbl -> GetRCWData(This,addr,data) ) + +#define ISOSDacInterface_GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) \ + ( (This)->lpVtbl -> GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) ) + +#define ISOSDacInterface_GetCCWData(This,ccw,data) \ + ( (This)->lpVtbl -> GetCCWData(This,ccw,data) ) + +#define ISOSDacInterface_GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) \ + ( (This)->lpVtbl -> GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) ) + +#define ISOSDacInterface_TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) \ + ( (This)->lpVtbl -> TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) ) + +#define ISOSDacInterface_GetStackReferences(This,osThreadID,ppEnum) \ + ( (This)->lpVtbl -> GetStackReferences(This,osThreadID,ppEnum) ) + +#define ISOSDacInterface_GetRegisterName(This,regName,count,buffer,pNeeded) \ + ( (This)->lpVtbl -> GetRegisterName(This,regName,count,buffer,pNeeded) ) + +#define ISOSDacInterface_GetThreadAllocData(This,thread,data) \ + ( (This)->lpVtbl -> GetThreadAllocData(This,thread,data) ) + +#define ISOSDacInterface_GetHeapAllocData(This,count,data,pNeeded) \ + ( (This)->lpVtbl -> GetHeapAllocData(This,count,data,pNeeded) ) + +#define ISOSDacInterface_GetFailedAssemblyList(This,appDomain,count,values,pNeeded) \ + ( (This)->lpVtbl -> GetFailedAssemblyList(This,appDomain,count,values,pNeeded) ) + +#define ISOSDacInterface_GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) \ + ( (This)->lpVtbl -> GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) ) + +#define ISOSDacInterface_GetAssemblyLocation(This,assembly,count,location,pNeeded) \ + ( (This)->lpVtbl -> GetAssemblyLocation(This,assembly,count,location,pNeeded) ) + +#define ISOSDacInterface_GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) \ + ( (This)->lpVtbl -> GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) ) + +#define ISOSDacInterface_GetApplicationBase(This,appDomain,count,base,pNeeded) \ + ( (This)->lpVtbl -> GetApplicationBase(This,appDomain,count,base,pNeeded) ) + +#define ISOSDacInterface_GetFailedAssemblyData(This,assembly,pContext,pResult) \ + ( (This)->lpVtbl -> GetFailedAssemblyData(This,assembly,pContext,pResult) ) + +#define ISOSDacInterface_GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) \ + ( (This)->lpVtbl -> GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) ) + +#define ISOSDacInterface_GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) \ + ( (This)->lpVtbl -> GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface2_INTERFACE_DEFINED__ +#define __ISOSDacInterface2_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A16026EC-96F4-40BA-87FB-5575986FB7AF") + ISOSDacInterface2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetObjectExceptionData( + CLRDATA_ADDRESS objAddr, + struct DacpExceptionObjectData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsRCWDCOMProxy( + CLRDATA_ADDRESS rcwAddr, + BOOL *isDCOMProxy) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetObjectExceptionData )( + ISOSDacInterface2 * This, + CLRDATA_ADDRESS objAddr, + struct DacpExceptionObjectData *data); + + HRESULT ( STDMETHODCALLTYPE *IsRCWDCOMProxy )( + ISOSDacInterface2 * This, + CLRDATA_ADDRESS rcwAddr, + BOOL *isDCOMProxy); + + END_INTERFACE + } ISOSDacInterface2Vtbl; + + interface ISOSDacInterface2 + { + CONST_VTBL struct ISOSDacInterface2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface2_GetObjectExceptionData(This,objAddr,data) \ + ( (This)->lpVtbl -> GetObjectExceptionData(This,objAddr,data) ) + +#define ISOSDacInterface2_IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) \ + ( (This)->lpVtbl -> IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface2_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface3_INTERFACE_DEFINED__ +#define __ISOSDacInterface3_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface3 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4") + ISOSDacInterface3 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoData( + CLRDATA_ADDRESS interestingInfoAddr, + struct DacpGCInterestingInfoData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoStaticData( + struct DacpGCInterestingInfoData *data) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetGCGlobalMechanisms( + size_t *globalMechanisms) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetGCInterestingInfoData )( + ISOSDacInterface3 * This, + CLRDATA_ADDRESS interestingInfoAddr, + struct DacpGCInterestingInfoData *data); + + HRESULT ( STDMETHODCALLTYPE *GetGCInterestingInfoStaticData )( + ISOSDacInterface3 * This, + struct DacpGCInterestingInfoData *data); + + HRESULT ( STDMETHODCALLTYPE *GetGCGlobalMechanisms )( + ISOSDacInterface3 * This, + size_t *globalMechanisms); + + END_INTERFACE + } ISOSDacInterface3Vtbl; + + interface ISOSDacInterface3 + { + CONST_VTBL struct ISOSDacInterface3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface3_GetGCInterestingInfoData(This,interestingInfoAddr,data) \ + ( (This)->lpVtbl -> GetGCInterestingInfoData(This,interestingInfoAddr,data) ) + +#define ISOSDacInterface3_GetGCInterestingInfoStaticData(This,data) \ + ( (This)->lpVtbl -> GetGCInterestingInfoStaticData(This,data) ) + +#define ISOSDacInterface3_GetGCGlobalMechanisms(This,globalMechanisms) \ + ( (This)->lpVtbl -> GetGCGlobalMechanisms(This,globalMechanisms) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface3_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface4_INTERFACE_DEFINED__ +#define __ISOSDacInterface4_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface4 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("74B9D34C-A612-4B07-93DD-5462178FCE11") + ISOSDacInterface4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetClrNotification( + CLRDATA_ADDRESS arguments[ ], + int count, + int *pNeeded) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface4 * This); + + HRESULT ( STDMETHODCALLTYPE *GetClrNotification )( + ISOSDacInterface4 * This, + CLRDATA_ADDRESS arguments[ ], + int count, + int *pNeeded); + + END_INTERFACE + } ISOSDacInterface4Vtbl; + + interface ISOSDacInterface4 + { + CONST_VTBL struct ISOSDacInterface4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface4_GetClrNotification(This,arguments,count,pNeeded) \ + ( (This)->lpVtbl -> GetClrNotification(This,arguments,count,pNeeded) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface4_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface5_INTERFACE_DEFINED__ +#define __ISOSDacInterface5_INTERFACE_DEFINED__ + +/* interface ISOSDacInterface5 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_ISOSDacInterface5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("127d6abe-6c86-4e48-8e7b-220781c58101") + ISOSDacInterface5 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTieredVersions( + CLRDATA_ADDRESS methodDesc, + int rejitId, + struct DacpTieredVersionData *nativeCodeAddrs, + int cNativeCodeAddrs, + int *pcNativeCodeAddrs) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ISOSDacInterface5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ISOSDacInterface5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ISOSDacInterface5 * This); + + HRESULT ( STDMETHODCALLTYPE *GetTieredVersions )( + ISOSDacInterface5 * This, + CLRDATA_ADDRESS methodDesc, + int rejitId, + CLRDATA_ADDRESS *nativeCodeAddrs, + int cNativeCodeAddrs); + + END_INTERFACE + } ISOSDacInterface5Vtbl; + + interface ISOSDacInterface5 + { + CONST_VTBL struct ISOSDacInterface5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface5_GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs) \ + ( (This)->lpVtbl -> GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */ + + +#ifndef __ISOSDacInterface6_INTERFACE_DEFINED__ +#define __ISOSDacInterface6_INTERFACE_DEFINED__ + + /* interface ISOSDacInterface6 */ + /* [uuid][local][object] */ + + + EXTERN_C const IID IID_ISOSDacInterface6; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("11206399-4B66-4EDB-98EA-85654E59AD45") + ISOSDacInterface6 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData( + CLRDATA_ADDRESS mt, + struct DacpMethodTableCollectibleData *data) = 0; + }; + + +#else /* C style interface */ + + typedef struct ISOSDacInterface6Vtbl + { + BEGIN_INTERFACE + + HRESULT(STDMETHODCALLTYPE *QueryInterface)( + ISOSDacInterface5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG(STDMETHODCALLTYPE *AddRef)( + ISOSDacInterface5 * This); + + ULONG(STDMETHODCALLTYPE *Release)( + ISOSDacInterface5 * This); + + HRESULT(STDMETHODCALLTYPE *GetMethodTableCollectibleData)( + CLRDATA_ADDRESS mt, + struct DacpMethodTableCollectibleData *data); + + END_INTERFACE + } ISOSDacInterface6Vtbl; + + interface ISOSDacInterface6 + { + CONST_VTBL struct ISOSDacInterface6Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ISOSDacInterface6_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ISOSDacInterface6_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \ + ( (This)->lpVtbl -> GetMethodTableCollectibleData(This,mt,data) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/version.h b/lib/coreclr/src/pal/prebuilt/inc/version.h new file mode 100644 index 0000000000..a6de92ca95 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/version.h @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include + +#define rmj NDPVersionNumberMajor +#define rmm NDPVersionNumberMinor +#define rup NDPBuildNumberMajor +#define rpt NDPBuildNumberMinor + +#define fvn NDPFileVersionMinor +#define fvb NDPFileVersionBuild +#define fvr NDPFileVersionRevision + +#define szVerName "" +#define szVerUser "" diff --git a/lib/coreclr/src/pal/prebuilt/inc/xclrdata.h b/lib/coreclr/src/pal/prebuilt/inc/xclrdata.h new file mode 100644 index 0000000000..3ce477ec82 --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/xclrdata.h @@ -0,0 +1,7909 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.00.0603 */ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __xclrdata_h__ +#define __xclrdata_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IXCLRDataTarget3_FWD_DEFINED__ +#define __IXCLRDataTarget3_FWD_DEFINED__ +typedef interface IXCLRDataTarget3 IXCLRDataTarget3; + +#endif /* __IXCLRDataTarget3_FWD_DEFINED__ */ + + +#ifndef __IXCLRLibrarySupport_FWD_DEFINED__ +#define __IXCLRLibrarySupport_FWD_DEFINED__ +typedef interface IXCLRLibrarySupport IXCLRLibrarySupport; + +#endif /* __IXCLRLibrarySupport_FWD_DEFINED__ */ + + +#ifndef __IXCLRDisassemblySupport_FWD_DEFINED__ +#define __IXCLRDisassemblySupport_FWD_DEFINED__ +typedef interface IXCLRDisassemblySupport IXCLRDisassemblySupport; + +#endif /* __IXCLRDisassemblySupport_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataDisplay_FWD_DEFINED__ +#define __IXCLRDataDisplay_FWD_DEFINED__ +typedef interface IXCLRDataDisplay IXCLRDataDisplay; + +#endif /* __IXCLRDataDisplay_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataProcess_FWD_DEFINED__ +#define __IXCLRDataProcess_FWD_DEFINED__ +typedef interface IXCLRDataProcess IXCLRDataProcess; + +#endif /* __IXCLRDataProcess_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataProcess2_FWD_DEFINED__ +#define __IXCLRDataProcess2_FWD_DEFINED__ +typedef interface IXCLRDataProcess2 IXCLRDataProcess2; + +#endif /* __IXCLRDataProcess2_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataAppDomain_FWD_DEFINED__ +#define __IXCLRDataAppDomain_FWD_DEFINED__ +typedef interface IXCLRDataAppDomain IXCLRDataAppDomain; + +#endif /* __IXCLRDataAppDomain_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataAssembly_FWD_DEFINED__ +#define __IXCLRDataAssembly_FWD_DEFINED__ +typedef interface IXCLRDataAssembly IXCLRDataAssembly; + +#endif /* __IXCLRDataAssembly_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataModule_FWD_DEFINED__ +#define __IXCLRDataModule_FWD_DEFINED__ +typedef interface IXCLRDataModule IXCLRDataModule; + +#endif /* __IXCLRDataModule_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataModule2_FWD_DEFINED__ +#define __IXCLRDataModule2_FWD_DEFINED__ +typedef interface IXCLRDataModule2 IXCLRDataModule2; + +#endif /* __IXCLRDataModule2_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataTypeDefinition_FWD_DEFINED__ +#define __IXCLRDataTypeDefinition_FWD_DEFINED__ +typedef interface IXCLRDataTypeDefinition IXCLRDataTypeDefinition; + +#endif /* __IXCLRDataTypeDefinition_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataTypeInstance_FWD_DEFINED__ +#define __IXCLRDataTypeInstance_FWD_DEFINED__ +typedef interface IXCLRDataTypeInstance IXCLRDataTypeInstance; + +#endif /* __IXCLRDataTypeInstance_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataMethodDefinition_FWD_DEFINED__ +#define __IXCLRDataMethodDefinition_FWD_DEFINED__ +typedef interface IXCLRDataMethodDefinition IXCLRDataMethodDefinition; + +#endif /* __IXCLRDataMethodDefinition_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataMethodInstance_FWD_DEFINED__ +#define __IXCLRDataMethodInstance_FWD_DEFINED__ +typedef interface IXCLRDataMethodInstance IXCLRDataMethodInstance; + +#endif /* __IXCLRDataMethodInstance_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataTask_FWD_DEFINED__ +#define __IXCLRDataTask_FWD_DEFINED__ +typedef interface IXCLRDataTask IXCLRDataTask; + +#endif /* __IXCLRDataTask_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataStackWalk_FWD_DEFINED__ +#define __IXCLRDataStackWalk_FWD_DEFINED__ +typedef interface IXCLRDataStackWalk IXCLRDataStackWalk; + +#endif /* __IXCLRDataStackWalk_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataFrame_FWD_DEFINED__ +#define __IXCLRDataFrame_FWD_DEFINED__ +typedef interface IXCLRDataFrame IXCLRDataFrame; + +#endif /* __IXCLRDataFrame_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataFrame2_FWD_DEFINED__ +#define __IXCLRDataFrame2_FWD_DEFINED__ +typedef interface IXCLRDataFrame2 IXCLRDataFrame2; + +#endif /* __IXCLRDataFrame2_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionState_FWD_DEFINED__ +#define __IXCLRDataExceptionState_FWD_DEFINED__ +typedef interface IXCLRDataExceptionState IXCLRDataExceptionState; + +#endif /* __IXCLRDataExceptionState_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataValue_FWD_DEFINED__ +#define __IXCLRDataValue_FWD_DEFINED__ +typedef interface IXCLRDataValue IXCLRDataValue; + +#endif /* __IXCLRDataValue_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification_FWD_DEFINED__ +#define __IXCLRDataExceptionNotification_FWD_DEFINED__ +typedef interface IXCLRDataExceptionNotification IXCLRDataExceptionNotification; + +#endif /* __IXCLRDataExceptionNotification_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification2_FWD_DEFINED__ +#define __IXCLRDataExceptionNotification2_FWD_DEFINED__ +typedef interface IXCLRDataExceptionNotification2 IXCLRDataExceptionNotification2; + +#endif /* __IXCLRDataExceptionNotification2_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification3_FWD_DEFINED__ +#define __IXCLRDataExceptionNotification3_FWD_DEFINED__ +typedef interface IXCLRDataExceptionNotification3 IXCLRDataExceptionNotification3; + +#endif /* __IXCLRDataExceptionNotification3_FWD_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification4_FWD_DEFINED__ +#define __IXCLRDataExceptionNotification4_FWD_DEFINED__ +typedef interface IXCLRDataExceptionNotification4 IXCLRDataExceptionNotification4; + +#endif /* __IXCLRDataExceptionNotification4_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "clrdata.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_xclrdata_0000_0000 */ +/* [local] */ + +#if 0 +typedef UINT32 mdToken; + +typedef mdToken mdTypeDef; + +typedef mdToken mdMethodDef; + +typedef mdToken mdFieldDef; + +typedef ULONG CorElementType; + +typedef struct _EXCEPTION_RECORD64 + { + DWORD ExceptionCode; + DWORD ExceptionFlags; + DWORD64 ExceptionRecord; + DWORD64 ExceptionAddress; + DWORD NumberParameters; + DWORD __unusedAlignment; + DWORD64 ExceptionInformation[ 15 ]; + } EXCEPTION_RECORD64; + +typedef struct _EXCEPTION_RECORD64 *PEXCEPTION_RECORD64; + +#endif +#pragma warning(push) +#pragma warning(disable:28718) + + + + + + + + + + + + + + + + + + +#pragma warning(pop) +typedef /* [public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0000_0001 + { + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; + } CLRDATA_ADDRESS_RANGE; + +typedef ULONG64 CLRDATA_ENUM; + +#define CLRDATA_NOTIFY_EXCEPTION 0xe0444143 +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0000_0002 + { + CLRDATA_REQUEST_REVISION = 0xe0000000 + } CLRDataGeneralRequest; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0000_0003 + { + CLRDATA_TYPE_DEFAULT = 0, + CLRDATA_TYPE_IS_PRIMITIVE = 0x1, + CLRDATA_TYPE_IS_VALUE_TYPE = 0x2, + CLRDATA_TYPE_IS_STRING = 0x4, + CLRDATA_TYPE_IS_ARRAY = 0x8, + CLRDATA_TYPE_IS_REFERENCE = 0x10, + CLRDATA_TYPE_IS_POINTER = 0x20, + CLRDATA_TYPE_IS_ENUM = 0x40, + CLRDATA_TYPE_ALL_KINDS = 0x7f + } CLRDataTypeFlag; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0000_0004 + { + CLRDATA_FIELD_DEFAULT = 0, + CLRDATA_FIELD_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, + CLRDATA_FIELD_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, + CLRDATA_FIELD_IS_STRING = CLRDATA_TYPE_IS_STRING, + CLRDATA_FIELD_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, + CLRDATA_FIELD_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, + CLRDATA_FIELD_IS_POINTER = CLRDATA_TYPE_IS_POINTER, + CLRDATA_FIELD_IS_ENUM = CLRDATA_TYPE_IS_ENUM, + CLRDATA_FIELD_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, + CLRDATA_FIELD_IS_INHERITED = 0x80, + CLRDATA_FIELD_IS_LITERAL = 0x100, + CLRDATA_FIELD_FROM_INSTANCE = 0x200, + CLRDATA_FIELD_FROM_TASK_LOCAL = 0x400, + CLRDATA_FIELD_FROM_STATIC = 0x800, + CLRDATA_FIELD_ALL_LOCATIONS = 0xe00, + CLRDATA_FIELD_ALL_FIELDS = 0xeff + } CLRDataFieldFlag; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0000_0005 + { + CLRDATA_VALUE_DEFAULT = 0, + CLRDATA_VALUE_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, + CLRDATA_VALUE_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, + CLRDATA_VALUE_IS_STRING = CLRDATA_TYPE_IS_STRING, + CLRDATA_VALUE_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, + CLRDATA_VALUE_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, + CLRDATA_VALUE_IS_POINTER = CLRDATA_TYPE_IS_POINTER, + CLRDATA_VALUE_IS_ENUM = CLRDATA_TYPE_IS_ENUM, + CLRDATA_VALUE_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, + CLRDATA_VALUE_IS_INHERITED = CLRDATA_FIELD_IS_INHERITED, + CLRDATA_VALUE_IS_LITERAL = CLRDATA_FIELD_IS_LITERAL, + CLRDATA_VALUE_FROM_INSTANCE = CLRDATA_FIELD_FROM_INSTANCE, + CLRDATA_VALUE_FROM_TASK_LOCAL = CLRDATA_FIELD_FROM_TASK_LOCAL, + CLRDATA_VALUE_FROM_STATIC = CLRDATA_FIELD_FROM_STATIC, + CLRDATA_VALUE_ALL_LOCATIONS = CLRDATA_FIELD_ALL_LOCATIONS, + CLRDATA_VALUE_ALL_FIELDS = CLRDATA_FIELD_ALL_FIELDS, + CLRDATA_VALUE_IS_BOXED = 0x1000 + } CLRDataValueFlag; + + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0000_v0_0_s_ifspec; + +#ifndef __IXCLRDataTarget3_INTERFACE_DEFINED__ +#define __IXCLRDataTarget3_INTERFACE_DEFINED__ + +/* interface IXCLRDataTarget3 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataTarget3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("59d9b5e1-4a6f-4531-84c3-51d12da22fd4") + IXCLRDataTarget3 : public ICLRDataTarget2 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMetaData( + /* [in] */ LPCWSTR imagePath, + /* [in] */ ULONG32 imageTimestamp, + /* [in] */ ULONG32 imageSize, + /* [in] */ GUID *mvid, + /* [in] */ ULONG32 mdRva, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufferSize, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *dataSize) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataTarget3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataTarget3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataTarget3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataTarget3 * This); + + HRESULT ( STDMETHODCALLTYPE *GetMachineType )( + IXCLRDataTarget3 * This, + /* [out] */ ULONG32 *machineType); + + HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( + IXCLRDataTarget3 * This, + /* [out] */ ULONG32 *pointerSize); + + HRESULT ( STDMETHODCALLTYPE *GetImageBase )( + IXCLRDataTarget3 * This, + /* [string][in] */ LPCWSTR imagePath, + /* [out] */ CLRDATA_ADDRESS *baseAddress); + + HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( + IXCLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesRead); + + HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( + IXCLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [size_is][in] */ BYTE *buffer, + /* [in] */ ULONG32 bytesRequested, + /* [out] */ ULONG32 *bytesWritten); + + HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( + IXCLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [out] */ CLRDATA_ADDRESS *value); + + HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( + IXCLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 index, + /* [in] */ CLRDATA_ADDRESS value); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( + IXCLRDataTarget3 * This, + /* [out] */ ULONG32 *threadID); + + HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( + IXCLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextSize, + /* [size_is][out] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( + IXCLRDataTarget3 * This, + /* [in] */ ULONG32 threadID, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE *context); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataTarget3 * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( + IXCLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags, + /* [in] */ ULONG32 protectFlags, + /* [out] */ CLRDATA_ADDRESS *virt); + + HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( + IXCLRDataTarget3 * This, + /* [in] */ CLRDATA_ADDRESS addr, + /* [in] */ ULONG32 size, + /* [in] */ ULONG32 typeFlags); + + HRESULT ( STDMETHODCALLTYPE *GetMetaData )( + IXCLRDataTarget3 * This, + /* [in] */ LPCWSTR imagePath, + /* [in] */ ULONG32 imageTimestamp, + /* [in] */ ULONG32 imageSize, + /* [in] */ GUID *mvid, + /* [in] */ ULONG32 mdRva, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufferSize, + /* [length_is][size_is][out] */ BYTE *buffer, + /* [out] */ ULONG32 *dataSize); + + END_INTERFACE + } IXCLRDataTarget3Vtbl; + + interface IXCLRDataTarget3 + { + CONST_VTBL struct IXCLRDataTarget3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataTarget3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataTarget3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataTarget3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataTarget3_GetMachineType(This,machineType) \ + ( (This)->lpVtbl -> GetMachineType(This,machineType) ) + +#define IXCLRDataTarget3_GetPointerSize(This,pointerSize) \ + ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) + +#define IXCLRDataTarget3_GetImageBase(This,imagePath,baseAddress) \ + ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) + +#define IXCLRDataTarget3_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ + ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) + +#define IXCLRDataTarget3_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ + ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) + +#define IXCLRDataTarget3_GetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) + +#define IXCLRDataTarget3_SetTLSValue(This,threadID,index,value) \ + ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) + +#define IXCLRDataTarget3_GetCurrentThreadID(This,threadID) \ + ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) + +#define IXCLRDataTarget3_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ + ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) + +#define IXCLRDataTarget3_SetThreadContext(This,threadID,contextSize,context) \ + ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) + +#define IXCLRDataTarget3_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + + +#define IXCLRDataTarget3_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ + ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) + +#define IXCLRDataTarget3_FreeVirtual(This,addr,size,typeFlags) \ + ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) + + +#define IXCLRDataTarget3_GetMetaData(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) \ + ( (This)->lpVtbl -> GetMetaData(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataTarget3_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0001 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0001 + { + CLRDATA_BYNAME_CASE_SENSITIVE = 0, + CLRDATA_BYNAME_CASE_INSENSITIVE = 0x1 + } CLRDataByNameFlag; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0002 + { + CLRDATA_GETNAME_DEFAULT = 0, + CLRDATA_GETNAME_NO_NAMESPACES = 0x1, + CLRDATA_GETNAME_NO_PARAMETERS = 0x2 + } CLRDataGetNameFlag; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0003 + { + CLRDATA_PROCESS_DEFAULT = 0, + CLRDATA_PROCESS_IN_GC = 0x1 + } CLRDataProcessFlag; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0004 + { + CLRDATA_ADDRESS_UNRECOGNIZED = 0, + CLRDATA_ADDRESS_MANAGED_METHOD = ( CLRDATA_ADDRESS_UNRECOGNIZED + 1 ) , + CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE = ( CLRDATA_ADDRESS_MANAGED_METHOD + 1 ) , + CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE = ( CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE + 1 ) , + CLRDATA_ADDRESS_GC_DATA = ( CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE + 1 ) , + CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB = ( CLRDATA_ADDRESS_GC_DATA + 1 ) , + CLRDATA_ADDRESS_RUNTIME_UNMANAGED_STUB = ( CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB + 1 ) + } CLRDataAddressType; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0005 + { + CLRDATA_NOTIFY_ON_MODULE_LOAD = 0x1, + CLRDATA_NOTIFY_ON_MODULE_UNLOAD = 0x2, + CLRDATA_NOTIFY_ON_EXCEPTION = 0x4, + CLRDATA_NOTIFY_ON_EXCEPTION_CATCH_ENTER = 0x8 + } CLRDataOtherNotifyFlag; + +typedef /* [public][public][public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0001_0006 + { + ULONG64 Data[ 8 ]; + } CLRDATA_FOLLOW_STUB_BUFFER; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0007 + { + CLRDATA_FOLLOW_STUB_DEFAULT = 0 + } CLRDataFollowStubInFlag; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0008 + { + CLRDATA_FOLLOW_STUB_INTERMEDIATE = 0, + CLRDATA_FOLLOW_STUB_EXIT = 0x1 + } CLRDataFollowStubOutFlag; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0009 + { + CLRNATIVEIMAGE_PE_INFO = 0x1, + CLRNATIVEIMAGE_COR_INFO = 0x2, + CLRNATIVEIMAGE_FIXUP_TABLES = 0x4, + CLRNATIVEIMAGE_FIXUP_HISTOGRAM = 0x8, + CLRNATIVEIMAGE_MODULE = 0x10, + CLRNATIVEIMAGE_METHODS = 0x20, + CLRNATIVEIMAGE_DISASSEMBLE_CODE = 0x40, + CLRNATIVEIMAGE_IL = 0x80, + CLRNATIVEIMAGE_METHODTABLES = 0x100, + CLRNATIVEIMAGE_NATIVE_INFO = 0x200, + CLRNATIVEIMAGE_MODULE_TABLES = 0x400, + CLRNATIVEIMAGE_FROZEN_SEGMENT = 0x800, + CLRNATIVEIMAGE_PE_FILE = 0x1000, + CLRNATIVEIMAGE_GC_INFO = 0x2000, + CLRNATIVEIMAGE_EECLASSES = 0x4000, + CLRNATIVEIMAGE_NATIVE_TABLES = 0x8000, + CLRNATIVEIMAGE_PRECODES = 0x10000, + CLRNATIVEIMAGE_TYPEDESCS = 0x20000, + CLRNATIVEIMAGE_VERBOSE_TYPES = 0x40000, + CLRNATIVEIMAGE_METHODDESCS = 0x80000, + CLRNATIVEIMAGE_METADATA = 0x100000, + CLRNATIVEIMAGE_DISABLE_NAMES = 0x200000, + CLRNATIVEIMAGE_DISABLE_REBASING = 0x400000, + CLRNATIVEIMAGE_SLIM_MODULE_TBLS = 0x800000, + CLRNATIVEIMAGE_RESOURCES = 0x1000000, + CLRNATIVEIMAGE_FILE_OFFSET = 0x2000000, + CLRNATIVEIMAGE_DEBUG_TRACE = 0x4000000, + CLRNATIVEIMAGE_RELOCATIONS = 0x8000000, + CLRNATIVEIMAGE_FIXUP_THUNKS = 0x10000000, + CLRNATIVEIMAGE_DEBUG_COVERAGE = 0x80000000 + } CLRNativeImageDumpOptions; + +#ifdef __cplusplus +inline CLRNativeImageDumpOptions operator|=(CLRNativeImageDumpOptions& lhs, CLRNativeImageDumpOptions rhs) { return (lhs = (CLRNativeImageDumpOptions)( ((unsigned)lhs) | ((unsigned)rhs) )); } +#endif +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0001_0010 + { + CLRDATAHINT_DISPLAY_HINTS_NONE = 0, + CLRDATAHINT_DISPLAY_ARRAY_AS_TABLE = 0x1, + CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY = 0x2, + CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY_IDX = 0x3, + CLRDATAHINT_DISPLAY_ARRAY_AS_MAP = 0x4, + CLRDATAHINT_DISPLAY_ARRAY_HINT_MASK = 0xff, + CLRDATAHINT_DISPLAY_STRUCT_AS_TABLE = 0x100, + CLRDATAHINT_DISPLAY_STRUCT_HINT_MASK = 0xff00, + CLRDATAHINT_DISPLAY_SEP_TAB = 0, + CLRDATAHINT_DISPLAY_SEP_SPACE = 0x1000000, + CLRDATAHINT_DISPLAY_SEP_TAB_SPACE = 0x2000000, + CLRDATAHINT_DISPLAY_SEP_MASK = 0xff000000 + } CLRDataDisplayHints; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0001_v0_0_s_ifspec; + +#ifndef __IXCLRLibrarySupport_INTERFACE_DEFINED__ +#define __IXCLRLibrarySupport_INTERFACE_DEFINED__ + +/* interface IXCLRLibrarySupport */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRLibrarySupport; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E5F3039D-2C0C-4230-A69E-12AF1C3E563C") + IXCLRLibrarySupport : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE LoadHardboundDependency( + const WCHAR *name, + REFGUID mvid, + /* [out] */ SIZE_T *loadedBase) = 0; + + virtual HRESULT STDMETHODCALLTYPE LoadSoftboundDependency( + const WCHAR *name, + const BYTE *assemblymetadataBinding, + const BYTE *hash, + ULONG hashLength, + /* [out] */ SIZE_T *loadedBase) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRLibrarySupportVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRLibrarySupport * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRLibrarySupport * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRLibrarySupport * This); + + HRESULT ( STDMETHODCALLTYPE *LoadHardboundDependency )( + IXCLRLibrarySupport * This, + const WCHAR *name, + REFGUID mvid, + /* [out] */ SIZE_T *loadedBase); + + HRESULT ( STDMETHODCALLTYPE *LoadSoftboundDependency )( + IXCLRLibrarySupport * This, + const WCHAR *name, + const BYTE *assemblymetadataBinding, + const BYTE *hash, + ULONG hashLength, + /* [out] */ SIZE_T *loadedBase); + + END_INTERFACE + } IXCLRLibrarySupportVtbl; + + interface IXCLRLibrarySupport + { + CONST_VTBL struct IXCLRLibrarySupportVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRLibrarySupport_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRLibrarySupport_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRLibrarySupport_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRLibrarySupport_LoadHardboundDependency(This,name,mvid,loadedBase) \ + ( (This)->lpVtbl -> LoadHardboundDependency(This,name,mvid,loadedBase) ) + +#define IXCLRLibrarySupport_LoadSoftboundDependency(This,name,assemblymetadataBinding,hash,hashLength,loadedBase) \ + ( (This)->lpVtbl -> LoadSoftboundDependency(This,name,assemblymetadataBinding,hash,hashLength,loadedBase) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRLibrarySupport_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0002 */ +/* [local] */ + + +typedef SIZE_T ( __stdcall *CDSTranslateAddrCB )( + IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020000, + CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020001, + wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020002, + SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020003, + DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020004); + +typedef SIZE_T ( __stdcall *CDSTranslateFixupCB )( + IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020006, + CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020007, + SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020008, + wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020009, + SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020010, + DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020011); + +typedef SIZE_T ( __stdcall *CDSTranslateConstCB )( + IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020013, + DWORD __MIDL____MIDL_itf_xclrdata_0000_00020014, + wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020015, + SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020016); + +typedef SIZE_T ( __stdcall *CDSTranslateRegrelCB )( + IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020018, + unsigned int rega, + CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020019, + wchar_t *__MIDL____MIDL_itf_xclrdata_0000_00020020, + SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020021, + DWORD *__MIDL____MIDL_itf_xclrdata_0000_00020022); + + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0002_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0002_v0_0_s_ifspec; + +#ifndef __IXCLRDisassemblySupport_INTERFACE_DEFINED__ +#define __IXCLRDisassemblySupport_INTERFACE_DEFINED__ + +/* interface IXCLRDisassemblySupport */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDisassemblySupport; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1F0F7134-D3F3-47DE-8E9B-C2FD358A2936") + IXCLRDisassemblySupport : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetTranslateAddrCallback( + /* [in] */ CDSTranslateAddrCB cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE PvClientSet( + /* [in] */ void *pv) = 0; + + virtual SIZE_T STDMETHODCALLTYPE CbDisassemble( + CLRDATA_ADDRESS __MIDL__IXCLRDisassemblySupport0000, + const void *__MIDL__IXCLRDisassemblySupport0001, + SIZE_T __MIDL__IXCLRDisassemblySupport0002) = 0; + + virtual SIZE_T STDMETHODCALLTYPE Cinstruction( void) = 0; + + virtual BOOL STDMETHODCALLTYPE FSelectInstruction( + SIZE_T __MIDL__IXCLRDisassemblySupport0003) = 0; + + virtual SIZE_T STDMETHODCALLTYPE CchFormatInstr( + wchar_t *__MIDL__IXCLRDisassemblySupport0004, + SIZE_T __MIDL__IXCLRDisassemblySupport0005) = 0; + + virtual void *STDMETHODCALLTYPE PvClient( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTranslateFixupCallback( + /* [in] */ CDSTranslateFixupCB cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTranslateConstCallback( + /* [in] */ CDSTranslateConstCB cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTranslateRegrelCallback( + /* [in] */ CDSTranslateRegrelCB cb) = 0; + + virtual BOOL STDMETHODCALLTYPE TargetIsAddress( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDisassemblySupportVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDisassemblySupport * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDisassemblySupport * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDisassemblySupport * This); + + HRESULT ( STDMETHODCALLTYPE *SetTranslateAddrCallback )( + IXCLRDisassemblySupport * This, + /* [in] */ CDSTranslateAddrCB cb); + + HRESULT ( STDMETHODCALLTYPE *PvClientSet )( + IXCLRDisassemblySupport * This, + /* [in] */ void *pv); + + SIZE_T ( STDMETHODCALLTYPE *CbDisassemble )( + IXCLRDisassemblySupport * This, + CLRDATA_ADDRESS __MIDL__IXCLRDisassemblySupport0000, + const void *__MIDL__IXCLRDisassemblySupport0001, + SIZE_T __MIDL__IXCLRDisassemblySupport0002); + + SIZE_T ( STDMETHODCALLTYPE *Cinstruction )( + IXCLRDisassemblySupport * This); + + BOOL ( STDMETHODCALLTYPE *FSelectInstruction )( + IXCLRDisassemblySupport * This, + SIZE_T __MIDL__IXCLRDisassemblySupport0003); + + SIZE_T ( STDMETHODCALLTYPE *CchFormatInstr )( + IXCLRDisassemblySupport * This, + wchar_t *__MIDL__IXCLRDisassemblySupport0004, + SIZE_T __MIDL__IXCLRDisassemblySupport0005); + + void *( STDMETHODCALLTYPE *PvClient )( + IXCLRDisassemblySupport * This); + + HRESULT ( STDMETHODCALLTYPE *SetTranslateFixupCallback )( + IXCLRDisassemblySupport * This, + /* [in] */ CDSTranslateFixupCB cb); + + HRESULT ( STDMETHODCALLTYPE *SetTranslateConstCallback )( + IXCLRDisassemblySupport * This, + /* [in] */ CDSTranslateConstCB cb); + + HRESULT ( STDMETHODCALLTYPE *SetTranslateRegrelCallback )( + IXCLRDisassemblySupport * This, + /* [in] */ CDSTranslateRegrelCB cb); + + BOOL ( STDMETHODCALLTYPE *TargetIsAddress )( + IXCLRDisassemblySupport * This); + + END_INTERFACE + } IXCLRDisassemblySupportVtbl; + + interface IXCLRDisassemblySupport + { + CONST_VTBL struct IXCLRDisassemblySupportVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDisassemblySupport_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDisassemblySupport_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDisassemblySupport_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDisassemblySupport_SetTranslateAddrCallback(This,cb) \ + ( (This)->lpVtbl -> SetTranslateAddrCallback(This,cb) ) + +#define IXCLRDisassemblySupport_PvClientSet(This,pv) \ + ( (This)->lpVtbl -> PvClientSet(This,pv) ) + +#define IXCLRDisassemblySupport_CbDisassemble(This,__MIDL__IXCLRDisassemblySupport0000,__MIDL__IXCLRDisassemblySupport0001,__MIDL__IXCLRDisassemblySupport0002) \ + ( (This)->lpVtbl -> CbDisassemble(This,__MIDL__IXCLRDisassemblySupport0000,__MIDL__IXCLRDisassemblySupport0001,__MIDL__IXCLRDisassemblySupport0002) ) + +#define IXCLRDisassemblySupport_Cinstruction(This) \ + ( (This)->lpVtbl -> Cinstruction(This) ) + +#define IXCLRDisassemblySupport_FSelectInstruction(This,__MIDL__IXCLRDisassemblySupport0003) \ + ( (This)->lpVtbl -> FSelectInstruction(This,__MIDL__IXCLRDisassemblySupport0003) ) + +#define IXCLRDisassemblySupport_CchFormatInstr(This,__MIDL__IXCLRDisassemblySupport0004,__MIDL__IXCLRDisassemblySupport0005) \ + ( (This)->lpVtbl -> CchFormatInstr(This,__MIDL__IXCLRDisassemblySupport0004,__MIDL__IXCLRDisassemblySupport0005) ) + +#define IXCLRDisassemblySupport_PvClient(This) \ + ( (This)->lpVtbl -> PvClient(This) ) + +#define IXCLRDisassemblySupport_SetTranslateFixupCallback(This,cb) \ + ( (This)->lpVtbl -> SetTranslateFixupCallback(This,cb) ) + +#define IXCLRDisassemblySupport_SetTranslateConstCallback(This,cb) \ + ( (This)->lpVtbl -> SetTranslateConstCallback(This,cb) ) + +#define IXCLRDisassemblySupport_SetTranslateRegrelCallback(This,cb) \ + ( (This)->lpVtbl -> SetTranslateRegrelCallback(This,cb) ) + +#define IXCLRDisassemblySupport_TargetIsAddress(This) \ + ( (This)->lpVtbl -> TargetIsAddress(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDisassemblySupport_INTERFACE_DEFINED__ */ + + +#ifndef __IXCLRDataDisplay_INTERFACE_DEFINED__ +#define __IXCLRDataDisplay_INTERFACE_DEFINED__ + +/* interface IXCLRDataDisplay */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataDisplay; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A3C1704A-4559-4a67-8D28-E8F4FE3B3F62") + IXCLRDataDisplay : public IUnknown + { + public: + virtual HRESULT STDMETHODVCALLTYPE ErrorPrintF( + const char *const fmt, + ...) = 0; + + virtual HRESULT STDMETHODCALLTYPE NativeImageDimensions( + SIZE_T base, + SIZE_T size, + DWORD sectionAlign) = 0; + + virtual HRESULT STDMETHODCALLTYPE Section( + const char *const name, + SIZE_T rva, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDumpOptions( + /* [out] */ CLRNativeImageDumpOptions *pOptions) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartDocument( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndDocument( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartCategory( + const char *const name) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndCategory( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartElement( + const char *const name) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndElement( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartVStructure( + const char *const name) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartVStructureWithOffset( + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndVStructure( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartTextElement( + const char *const name) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndTextElement( void) = 0; + + virtual HRESULT STDMETHODVCALLTYPE WriteXmlText( + const char *const fmt, + ...) = 0; + + virtual HRESULT STDMETHODVCALLTYPE WriteXmlTextBlock( + const char *const fmt, + ...) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteEmptyElement( + const char *const element) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementPointer( + const char *const element, + SIZE_T ptr) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementPointerAnnotated( + const char *const element, + SIZE_T ptr, + const WCHAR *const annotation) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementAddress( + const char *const element, + SIZE_T base, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementAddressNamed( + const char *const element, + const char *const name, + SIZE_T base, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementAddressNamedW( + const char *const element, + const WCHAR *const name, + SIZE_T base, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementString( + const char *const element, + const char *const data) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementStringW( + const char *const element, + const WCHAR *const data) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementInt( + const char *const element, + int value) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementUInt( + const char *const element, + DWORD value) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementEnumerated( + const char *const element, + DWORD value, + const WCHAR *const mnemonic) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementIntWithSuppress( + const char *const element, + int value, + int suppressIfEqual) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteElementFlag( + const char *const element, + BOOL flag) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartArray( + const char *const name, + const WCHAR *const fmt) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndArray( + const char *const countPrefix) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartList( + const WCHAR *const fmt) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndList( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartArrayWithOffset( + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize, + const WCHAR *const fmt) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldString( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + const char *const data) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldStringW( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + const WCHAR *const data) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldPointer( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldPointerWithSize( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldInt( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + int value) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldUInt( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + DWORD value) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldEnumerated( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + DWORD value, + const WCHAR *const mnemonic) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldEmpty( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldFlag( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + BOOL flag) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldPointerAnnotated( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + const WCHAR *const annotation) = 0; + + virtual HRESULT STDMETHODCALLTYPE WriteFieldAddress( + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T base, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartStructure( + const char *const name, + SIZE_T ptr, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartStructureWithNegSpace( + const char *const name, + SIZE_T ptr, + SIZE_T startPtr, + SIZE_T totalSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartStructureWithOffset( + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + SIZE_T size) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndStructure( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataDisplayVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataDisplay * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataDisplay * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODVCALLTYPE *ErrorPrintF )( + IXCLRDataDisplay * This, + const char *const fmt, + ...); + + HRESULT ( STDMETHODCALLTYPE *NativeImageDimensions )( + IXCLRDataDisplay * This, + SIZE_T base, + SIZE_T size, + DWORD sectionAlign); + + HRESULT ( STDMETHODCALLTYPE *Section )( + IXCLRDataDisplay * This, + const char *const name, + SIZE_T rva, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *GetDumpOptions )( + IXCLRDataDisplay * This, + /* [out] */ CLRNativeImageDumpOptions *pOptions); + + HRESULT ( STDMETHODCALLTYPE *StartDocument )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *EndDocument )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *StartCategory )( + IXCLRDataDisplay * This, + const char *const name); + + HRESULT ( STDMETHODCALLTYPE *EndCategory )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *StartElement )( + IXCLRDataDisplay * This, + const char *const name); + + HRESULT ( STDMETHODCALLTYPE *EndElement )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *StartVStructure )( + IXCLRDataDisplay * This, + const char *const name); + + HRESULT ( STDMETHODCALLTYPE *StartVStructureWithOffset )( + IXCLRDataDisplay * This, + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize); + + HRESULT ( STDMETHODCALLTYPE *EndVStructure )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *StartTextElement )( + IXCLRDataDisplay * This, + const char *const name); + + HRESULT ( STDMETHODCALLTYPE *EndTextElement )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODVCALLTYPE *WriteXmlText )( + IXCLRDataDisplay * This, + const char *const fmt, + ...); + + HRESULT ( STDMETHODVCALLTYPE *WriteXmlTextBlock )( + IXCLRDataDisplay * This, + const char *const fmt, + ...); + + HRESULT ( STDMETHODCALLTYPE *WriteEmptyElement )( + IXCLRDataDisplay * This, + const char *const element); + + HRESULT ( STDMETHODCALLTYPE *WriteElementPointer )( + IXCLRDataDisplay * This, + const char *const element, + SIZE_T ptr); + + HRESULT ( STDMETHODCALLTYPE *WriteElementPointerAnnotated )( + IXCLRDataDisplay * This, + const char *const element, + SIZE_T ptr, + const WCHAR *const annotation); + + HRESULT ( STDMETHODCALLTYPE *WriteElementAddress )( + IXCLRDataDisplay * This, + const char *const element, + SIZE_T base, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *WriteElementAddressNamed )( + IXCLRDataDisplay * This, + const char *const element, + const char *const name, + SIZE_T base, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *WriteElementAddressNamedW )( + IXCLRDataDisplay * This, + const char *const element, + const WCHAR *const name, + SIZE_T base, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *WriteElementString )( + IXCLRDataDisplay * This, + const char *const element, + const char *const data); + + HRESULT ( STDMETHODCALLTYPE *WriteElementStringW )( + IXCLRDataDisplay * This, + const char *const element, + const WCHAR *const data); + + HRESULT ( STDMETHODCALLTYPE *WriteElementInt )( + IXCLRDataDisplay * This, + const char *const element, + int value); + + HRESULT ( STDMETHODCALLTYPE *WriteElementUInt )( + IXCLRDataDisplay * This, + const char *const element, + DWORD value); + + HRESULT ( STDMETHODCALLTYPE *WriteElementEnumerated )( + IXCLRDataDisplay * This, + const char *const element, + DWORD value, + const WCHAR *const mnemonic); + + HRESULT ( STDMETHODCALLTYPE *WriteElementIntWithSuppress )( + IXCLRDataDisplay * This, + const char *const element, + int value, + int suppressIfEqual); + + HRESULT ( STDMETHODCALLTYPE *WriteElementFlag )( + IXCLRDataDisplay * This, + const char *const element, + BOOL flag); + + HRESULT ( STDMETHODCALLTYPE *StartArray )( + IXCLRDataDisplay * This, + const char *const name, + const WCHAR *const fmt); + + HRESULT ( STDMETHODCALLTYPE *EndArray )( + IXCLRDataDisplay * This, + const char *const countPrefix); + + HRESULT ( STDMETHODCALLTYPE *StartList )( + IXCLRDataDisplay * This, + const WCHAR *const fmt); + + HRESULT ( STDMETHODCALLTYPE *EndList )( + IXCLRDataDisplay * This); + + HRESULT ( STDMETHODCALLTYPE *StartArrayWithOffset )( + IXCLRDataDisplay * This, + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize, + const WCHAR *const fmt); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldString )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + const char *const data); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldStringW )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + const WCHAR *const data); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldPointer )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldPointerWithSize )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldInt )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + int value); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldUInt )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + DWORD value); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldEnumerated )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + DWORD value, + const WCHAR *const mnemonic); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldEmpty )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldFlag )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + BOOL flag); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldPointerAnnotated )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + const WCHAR *const annotation); + + HRESULT ( STDMETHODCALLTYPE *WriteFieldAddress )( + IXCLRDataDisplay * This, + const char *const element, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T base, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *StartStructure )( + IXCLRDataDisplay * This, + const char *const name, + SIZE_T ptr, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *StartStructureWithNegSpace )( + IXCLRDataDisplay * This, + const char *const name, + SIZE_T ptr, + SIZE_T startPtr, + SIZE_T totalSize); + + HRESULT ( STDMETHODCALLTYPE *StartStructureWithOffset )( + IXCLRDataDisplay * This, + const char *const name, + unsigned int fieldOffset, + unsigned int fieldSize, + SIZE_T ptr, + SIZE_T size); + + HRESULT ( STDMETHODCALLTYPE *EndStructure )( + IXCLRDataDisplay * This); + + END_INTERFACE + } IXCLRDataDisplayVtbl; + + interface IXCLRDataDisplay + { + CONST_VTBL struct IXCLRDataDisplayVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataDisplay_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataDisplay_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataDisplay_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataDisplay_ErrorPrintF(This,fmt,...) \ + ( (This)->lpVtbl -> ErrorPrintF(This,fmt,...) ) + +#define IXCLRDataDisplay_NativeImageDimensions(This,base,size,sectionAlign) \ + ( (This)->lpVtbl -> NativeImageDimensions(This,base,size,sectionAlign) ) + +#define IXCLRDataDisplay_Section(This,name,rva,size) \ + ( (This)->lpVtbl -> Section(This,name,rva,size) ) + +#define IXCLRDataDisplay_GetDumpOptions(This,pOptions) \ + ( (This)->lpVtbl -> GetDumpOptions(This,pOptions) ) + +#define IXCLRDataDisplay_StartDocument(This) \ + ( (This)->lpVtbl -> StartDocument(This) ) + +#define IXCLRDataDisplay_EndDocument(This) \ + ( (This)->lpVtbl -> EndDocument(This) ) + +#define IXCLRDataDisplay_StartCategory(This,name) \ + ( (This)->lpVtbl -> StartCategory(This,name) ) + +#define IXCLRDataDisplay_EndCategory(This) \ + ( (This)->lpVtbl -> EndCategory(This) ) + +#define IXCLRDataDisplay_StartElement(This,name) \ + ( (This)->lpVtbl -> StartElement(This,name) ) + +#define IXCLRDataDisplay_EndElement(This) \ + ( (This)->lpVtbl -> EndElement(This) ) + +#define IXCLRDataDisplay_StartVStructure(This,name) \ + ( (This)->lpVtbl -> StartVStructure(This,name) ) + +#define IXCLRDataDisplay_StartVStructureWithOffset(This,name,fieldOffset,fieldSize) \ + ( (This)->lpVtbl -> StartVStructureWithOffset(This,name,fieldOffset,fieldSize) ) + +#define IXCLRDataDisplay_EndVStructure(This) \ + ( (This)->lpVtbl -> EndVStructure(This) ) + +#define IXCLRDataDisplay_StartTextElement(This,name) \ + ( (This)->lpVtbl -> StartTextElement(This,name) ) + +#define IXCLRDataDisplay_EndTextElement(This) \ + ( (This)->lpVtbl -> EndTextElement(This) ) + +#define IXCLRDataDisplay_WriteXmlText(This,fmt,...) \ + ( (This)->lpVtbl -> WriteXmlText(This,fmt,...) ) + +#define IXCLRDataDisplay_WriteXmlTextBlock(This,fmt,...) \ + ( (This)->lpVtbl -> WriteXmlTextBlock(This,fmt,...) ) + +#define IXCLRDataDisplay_WriteEmptyElement(This,element) \ + ( (This)->lpVtbl -> WriteEmptyElement(This,element) ) + +#define IXCLRDataDisplay_WriteElementPointer(This,element,ptr) \ + ( (This)->lpVtbl -> WriteElementPointer(This,element,ptr) ) + +#define IXCLRDataDisplay_WriteElementPointerAnnotated(This,element,ptr,annotation) \ + ( (This)->lpVtbl -> WriteElementPointerAnnotated(This,element,ptr,annotation) ) + +#define IXCLRDataDisplay_WriteElementAddress(This,element,base,size) \ + ( (This)->lpVtbl -> WriteElementAddress(This,element,base,size) ) + +#define IXCLRDataDisplay_WriteElementAddressNamed(This,element,name,base,size) \ + ( (This)->lpVtbl -> WriteElementAddressNamed(This,element,name,base,size) ) + +#define IXCLRDataDisplay_WriteElementAddressNamedW(This,element,name,base,size) \ + ( (This)->lpVtbl -> WriteElementAddressNamedW(This,element,name,base,size) ) + +#define IXCLRDataDisplay_WriteElementString(This,element,data) \ + ( (This)->lpVtbl -> WriteElementString(This,element,data) ) + +#define IXCLRDataDisplay_WriteElementStringW(This,element,data) \ + ( (This)->lpVtbl -> WriteElementStringW(This,element,data) ) + +#define IXCLRDataDisplay_WriteElementInt(This,element,value) \ + ( (This)->lpVtbl -> WriteElementInt(This,element,value) ) + +#define IXCLRDataDisplay_WriteElementUInt(This,element,value) \ + ( (This)->lpVtbl -> WriteElementUInt(This,element,value) ) + +#define IXCLRDataDisplay_WriteElementEnumerated(This,element,value,mnemonic) \ + ( (This)->lpVtbl -> WriteElementEnumerated(This,element,value,mnemonic) ) + +#define IXCLRDataDisplay_WriteElementIntWithSuppress(This,element,value,suppressIfEqual) \ + ( (This)->lpVtbl -> WriteElementIntWithSuppress(This,element,value,suppressIfEqual) ) + +#define IXCLRDataDisplay_WriteElementFlag(This,element,flag) \ + ( (This)->lpVtbl -> WriteElementFlag(This,element,flag) ) + +#define IXCLRDataDisplay_StartArray(This,name,fmt) \ + ( (This)->lpVtbl -> StartArray(This,name,fmt) ) + +#define IXCLRDataDisplay_EndArray(This,countPrefix) \ + ( (This)->lpVtbl -> EndArray(This,countPrefix) ) + +#define IXCLRDataDisplay_StartList(This,fmt) \ + ( (This)->lpVtbl -> StartList(This,fmt) ) + +#define IXCLRDataDisplay_EndList(This) \ + ( (This)->lpVtbl -> EndList(This) ) + +#define IXCLRDataDisplay_StartArrayWithOffset(This,name,fieldOffset,fieldSize,fmt) \ + ( (This)->lpVtbl -> StartArrayWithOffset(This,name,fieldOffset,fieldSize,fmt) ) + +#define IXCLRDataDisplay_WriteFieldString(This,element,fieldOffset,fieldSize,data) \ + ( (This)->lpVtbl -> WriteFieldString(This,element,fieldOffset,fieldSize,data) ) + +#define IXCLRDataDisplay_WriteFieldStringW(This,element,fieldOffset,fieldSize,data) \ + ( (This)->lpVtbl -> WriteFieldStringW(This,element,fieldOffset,fieldSize,data) ) + +#define IXCLRDataDisplay_WriteFieldPointer(This,element,fieldOffset,fieldSize,ptr) \ + ( (This)->lpVtbl -> WriteFieldPointer(This,element,fieldOffset,fieldSize,ptr) ) + +#define IXCLRDataDisplay_WriteFieldPointerWithSize(This,element,fieldOffset,fieldSize,ptr,size) \ + ( (This)->lpVtbl -> WriteFieldPointerWithSize(This,element,fieldOffset,fieldSize,ptr,size) ) + +#define IXCLRDataDisplay_WriteFieldInt(This,element,fieldOffset,fieldSize,value) \ + ( (This)->lpVtbl -> WriteFieldInt(This,element,fieldOffset,fieldSize,value) ) + +#define IXCLRDataDisplay_WriteFieldUInt(This,element,fieldOffset,fieldSize,value) \ + ( (This)->lpVtbl -> WriteFieldUInt(This,element,fieldOffset,fieldSize,value) ) + +#define IXCLRDataDisplay_WriteFieldEnumerated(This,element,fieldOffset,fieldSize,value,mnemonic) \ + ( (This)->lpVtbl -> WriteFieldEnumerated(This,element,fieldOffset,fieldSize,value,mnemonic) ) + +#define IXCLRDataDisplay_WriteFieldEmpty(This,element,fieldOffset,fieldSize) \ + ( (This)->lpVtbl -> WriteFieldEmpty(This,element,fieldOffset,fieldSize) ) + +#define IXCLRDataDisplay_WriteFieldFlag(This,element,fieldOffset,fieldSize,flag) \ + ( (This)->lpVtbl -> WriteFieldFlag(This,element,fieldOffset,fieldSize,flag) ) + +#define IXCLRDataDisplay_WriteFieldPointerAnnotated(This,element,fieldOffset,fieldSize,ptr,annotation) \ + ( (This)->lpVtbl -> WriteFieldPointerAnnotated(This,element,fieldOffset,fieldSize,ptr,annotation) ) + +#define IXCLRDataDisplay_WriteFieldAddress(This,element,fieldOffset,fieldSize,base,size) \ + ( (This)->lpVtbl -> WriteFieldAddress(This,element,fieldOffset,fieldSize,base,size) ) + +#define IXCLRDataDisplay_StartStructure(This,name,ptr,size) \ + ( (This)->lpVtbl -> StartStructure(This,name,ptr,size) ) + +#define IXCLRDataDisplay_StartStructureWithNegSpace(This,name,ptr,startPtr,totalSize) \ + ( (This)->lpVtbl -> StartStructureWithNegSpace(This,name,ptr,startPtr,totalSize) ) + +#define IXCLRDataDisplay_StartStructureWithOffset(This,name,fieldOffset,fieldSize,ptr,size) \ + ( (This)->lpVtbl -> StartStructureWithOffset(This,name,fieldOffset,fieldSize,ptr,size) ) + +#define IXCLRDataDisplay_EndStructure(This) \ + ( (This)->lpVtbl -> EndStructure(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataDisplay_INTERFACE_DEFINED__ */ + + +#ifndef __IXCLRDataProcess_INTERFACE_DEFINED__ +#define __IXCLRDataProcess_INTERFACE_DEFINED__ + +/* interface IXCLRDataProcess */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataProcess; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b7") + IXCLRDataProcess : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Flush( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumTasks( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumTask( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTask **task) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumTasks( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTaskByOSThreadID( + /* [in] */ ULONG32 osThreadID, + /* [out] */ IXCLRDataTask **task) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTaskByUniqueID( + /* [in] */ ULONG64 taskID, + /* [out] */ IXCLRDataTask **task) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataProcess *process) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetManagedObject( + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState( + /* [out] */ ULONG32 *state) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState( + /* [in] */ ULONG32 state) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressType( + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDataAddressType *type) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRuntimeNameByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ CLRDATA_ADDRESS *displacement) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomainByUniqueID( + /* [in] */ ULONG64 id, + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAssembly( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumModules( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumModule( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumModules( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModuleByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByAddress( + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByAddress( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDataByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataValue **value, + /* [out] */ CLRDATA_ADDRESS *displacement) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetExceptionStateByExceptionRecord( + /* [in] */ EXCEPTION_RECORD64 *record, + /* [out] */ IXCLRDataExceptionState **exState) = 0; + + virtual HRESULT STDMETHODCALLTYPE TranslateExceptionRecordToNotification( + /* [in] */ EXCEPTION_RECORD64 *record, + /* [in] */ IXCLRDataExceptionNotification *notify) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateMemoryValue( + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ IXCLRDataTypeInstance *type, + /* [in] */ CLRDATA_ADDRESS addr, + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAllTypeNotifications( + IXCLRDataModule *mod, + ULONG32 flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetAllCodeNotifications( + IXCLRDataModule *mod, + ULONG32 flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeNotifications( + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTypeNotifications( + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeNotifications( + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCodeNotifications( + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOtherNotificationFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetOtherNotificationFlags( + /* [in] */ ULONG32 flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByAddress( + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByAddress( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE FollowStub( + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE FollowStub2( + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE DumpNativeImage( + /* [in] */ CLRDATA_ADDRESS loadedBase, + /* [in] */ LPCWSTR name, + /* [in] */ IXCLRDataDisplay *display, + /* [in] */ IXCLRLibrarySupport *libSupport, + /* [in] */ IXCLRDisassemblySupport *dis) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataProcessVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataProcess * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataProcess * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataProcess * This); + + HRESULT ( STDMETHODCALLTYPE *Flush )( + IXCLRDataProcess * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTasks )( + IXCLRDataProcess * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTask )( + IXCLRDataProcess * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTasks )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByOSThreadID )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 osThreadID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByUniqueID )( + IXCLRDataProcess * This, + /* [in] */ ULONG64 taskID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataProcess * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataProcess * This, + /* [in] */ IXCLRDataProcess *process); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataProcess * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( + IXCLRDataProcess * This, + /* [out] */ ULONG32 *state); + + HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *GetAddressType )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDataAddressType *type); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeNameByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( + IXCLRDataProcess * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( + IXCLRDataProcess * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainByUniqueID )( + IXCLRDataProcess * This, + /* [in] */ ULONG64 id, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( + IXCLRDataProcess * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( + IXCLRDataProcess * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( + IXCLRDataProcess * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumModule )( + IXCLRDataProcess * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetModuleByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetDataByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataValue **value, + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionStateByExceptionRecord )( + IXCLRDataProcess * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [out] */ IXCLRDataExceptionState **exState); + + HRESULT ( STDMETHODCALLTYPE *TranslateExceptionRecordToNotification )( + IXCLRDataProcess * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [in] */ IXCLRDataExceptionNotification *notify); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *CreateMemoryValue )( + IXCLRDataProcess * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ IXCLRDataTypeInstance *type, + /* [in] */ CLRDATA_ADDRESS addr, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *SetAllTypeNotifications )( + IXCLRDataProcess * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *SetAllCodeNotifications )( + IXCLRDataProcess * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *GetTypeNotifications )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetTypeNotifications )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetCodeNotifications )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetCodeNotifications )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetOtherNotificationFlags )( + IXCLRDataProcess * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *SetOtherNotificationFlags )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByAddress )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *FollowStub )( + IXCLRDataProcess * This, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *FollowStub2 )( + IXCLRDataProcess * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *DumpNativeImage )( + IXCLRDataProcess * This, + /* [in] */ CLRDATA_ADDRESS loadedBase, + /* [in] */ LPCWSTR name, + /* [in] */ IXCLRDataDisplay *display, + /* [in] */ IXCLRLibrarySupport *libSupport, + /* [in] */ IXCLRDisassemblySupport *dis); + + END_INTERFACE + } IXCLRDataProcessVtbl; + + interface IXCLRDataProcess + { + CONST_VTBL struct IXCLRDataProcessVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataProcess_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataProcess_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataProcess_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataProcess_Flush(This) \ + ( (This)->lpVtbl -> Flush(This) ) + +#define IXCLRDataProcess_StartEnumTasks(This,handle) \ + ( (This)->lpVtbl -> StartEnumTasks(This,handle) ) + +#define IXCLRDataProcess_EnumTask(This,handle,task) \ + ( (This)->lpVtbl -> EnumTask(This,handle,task) ) + +#define IXCLRDataProcess_EndEnumTasks(This,handle) \ + ( (This)->lpVtbl -> EndEnumTasks(This,handle) ) + +#define IXCLRDataProcess_GetTaskByOSThreadID(This,osThreadID,task) \ + ( (This)->lpVtbl -> GetTaskByOSThreadID(This,osThreadID,task) ) + +#define IXCLRDataProcess_GetTaskByUniqueID(This,taskID,task) \ + ( (This)->lpVtbl -> GetTaskByUniqueID(This,taskID,task) ) + +#define IXCLRDataProcess_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataProcess_IsSameObject(This,process) \ + ( (This)->lpVtbl -> IsSameObject(This,process) ) + +#define IXCLRDataProcess_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataProcess_GetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess_SetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess_GetAddressType(This,address,type) \ + ( (This)->lpVtbl -> GetAddressType(This,address,type) ) + +#define IXCLRDataProcess_GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) \ + ( (This)->lpVtbl -> GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) ) + +#define IXCLRDataProcess_StartEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess_EnumAppDomain(This,handle,appDomain) \ + ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) + +#define IXCLRDataProcess_EndEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess_GetAppDomainByUniqueID(This,id,appDomain) \ + ( (This)->lpVtbl -> GetAppDomainByUniqueID(This,id,appDomain) ) + +#define IXCLRDataProcess_StartEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess_EnumAssembly(This,handle,assembly) \ + ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) + +#define IXCLRDataProcess_EndEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess_StartEnumModules(This,handle) \ + ( (This)->lpVtbl -> StartEnumModules(This,handle) ) + +#define IXCLRDataProcess_EnumModule(This,handle,mod) \ + ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) + +#define IXCLRDataProcess_EndEnumModules(This,handle) \ + ( (This)->lpVtbl -> EndEnumModules(This,handle) ) + +#define IXCLRDataProcess_GetModuleByAddress(This,address,mod) \ + ( (This)->lpVtbl -> GetModuleByAddress(This,address,mod) ) + +#define IXCLRDataProcess_StartEnumMethodInstancesByAddress(This,address,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstancesByAddress(This,address,appDomain,handle) ) + +#define IXCLRDataProcess_EnumMethodInstanceByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodInstanceByAddress(This,handle,method) ) + +#define IXCLRDataProcess_EndEnumMethodInstancesByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstancesByAddress(This,handle) ) + +#define IXCLRDataProcess_GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) \ + ( (This)->lpVtbl -> GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) ) + +#define IXCLRDataProcess_GetExceptionStateByExceptionRecord(This,record,exState) \ + ( (This)->lpVtbl -> GetExceptionStateByExceptionRecord(This,record,exState) ) + +#define IXCLRDataProcess_TranslateExceptionRecordToNotification(This,record,notify) \ + ( (This)->lpVtbl -> TranslateExceptionRecordToNotification(This,record,notify) ) + +#define IXCLRDataProcess_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataProcess_CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) \ + ( (This)->lpVtbl -> CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) ) + +#define IXCLRDataProcess_SetAllTypeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllTypeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess_SetAllCodeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllCodeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess_GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess_SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess_GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess_SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess_GetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> GetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess_SetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> SetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess_StartEnumMethodDefinitionsByAddress(This,address,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitionsByAddress(This,address,handle) ) + +#define IXCLRDataProcess_EnumMethodDefinitionByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodDefinitionByAddress(This,handle,method) ) + +#define IXCLRDataProcess_EndEnumMethodDefinitionsByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitionsByAddress(This,handle) ) + +#define IXCLRDataProcess_FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess_FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess_DumpNativeImage(This,loadedBase,name,display,libSupport,dis) \ + ( (This)->lpVtbl -> DumpNativeImage(This,loadedBase,name,display,libSupport,dis) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataProcess_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0005 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public][public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0005_0001 + { + GC_MARK_END = 1, + GC_EVENT_TYPE_MAX = ( GC_MARK_END + 1 ) + } GcEvt_t; + +typedef /* [public][public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0005_0002 + { + GcEvt_t typ; + /* [switch_is] */ /* [switch_type] */ union + { + /* [case()] */ int condemnedGeneration; + } ; + } GcEvtArgs; + + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0005_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0005_v0_0_s_ifspec; + +#ifndef __IXCLRDataProcess2_INTERFACE_DEFINED__ +#define __IXCLRDataProcess2_INTERFACE_DEFINED__ + +/* interface IXCLRDataProcess2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataProcess2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b8") + IXCLRDataProcess2 : public IXCLRDataProcess + { + public: + virtual HRESULT STDMETHODCALLTYPE GetGcNotification( + /* [out][in] */ GcEvtArgs *gcEvtArgs) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetGcNotification( + /* [in] */ GcEvtArgs gcEvtArgs) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataProcess2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataProcess2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataProcess2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataProcess2 * This); + + HRESULT ( STDMETHODCALLTYPE *Flush )( + IXCLRDataProcess2 * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTasks )( + IXCLRDataProcess2 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTask )( + IXCLRDataProcess2 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTasks )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByOSThreadID )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 osThreadID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetTaskByUniqueID )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG64 taskID, + /* [out] */ IXCLRDataTask **task); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataProcess2 * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataProcess2 * This, + /* [in] */ IXCLRDataProcess *process); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataProcess2 * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( + IXCLRDataProcess2 * This, + /* [out] */ ULONG32 *state); + + HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *GetAddressType )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDataAddressType *type); + + HRESULT ( STDMETHODCALLTYPE *GetRuntimeNameByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( + IXCLRDataProcess2 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( + IXCLRDataProcess2 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomainByUniqueID )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG64 id, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( + IXCLRDataProcess2 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( + IXCLRDataProcess2 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( + IXCLRDataProcess2 * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumModule )( + IXCLRDataProcess2 * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetModuleByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetDataByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataValue **value, + /* [out] */ CLRDATA_ADDRESS *displacement); + + HRESULT ( STDMETHODCALLTYPE *GetExceptionStateByExceptionRecord )( + IXCLRDataProcess2 * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [out] */ IXCLRDataExceptionState **exState); + + HRESULT ( STDMETHODCALLTYPE *TranslateExceptionRecordToNotification )( + IXCLRDataProcess2 * This, + /* [in] */ EXCEPTION_RECORD64 *record, + /* [in] */ IXCLRDataExceptionNotification *notify); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *CreateMemoryValue )( + IXCLRDataProcess2 * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [in] */ IXCLRDataTypeInstance *type, + /* [in] */ CLRDATA_ADDRESS addr, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *SetAllTypeNotifications )( + IXCLRDataProcess2 * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *SetAllCodeNotifications )( + IXCLRDataProcess2 * This, + IXCLRDataModule *mod, + ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *GetTypeNotifications )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetTypeNotifications )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdTypeDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetCodeNotifications )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][out] */ ULONG32 flags[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetCodeNotifications )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 numTokens, + /* [size_is][in] */ IXCLRDataModule *mods[ ], + /* [in] */ IXCLRDataModule *singleMod, + /* [size_is][in] */ mdMethodDef tokens[ ], + /* [size_is][in] */ ULONG32 flags[ ], + /* [in] */ ULONG32 singleFlags); + + HRESULT ( STDMETHODCALLTYPE *GetOtherNotificationFlags )( + IXCLRDataProcess2 * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *SetOtherNotificationFlags )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByAddress )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *FollowStub )( + IXCLRDataProcess2 * This, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *FollowStub2 )( + IXCLRDataProcess2 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 inFlags, + /* [in] */ CLRDATA_ADDRESS inAddr, + /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, + /* [out] */ CLRDATA_ADDRESS *outAddr, + /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, + /* [out] */ ULONG32 *outFlags); + + HRESULT ( STDMETHODCALLTYPE *DumpNativeImage )( + IXCLRDataProcess2 * This, + /* [in] */ CLRDATA_ADDRESS loadedBase, + /* [in] */ LPCWSTR name, + /* [in] */ IXCLRDataDisplay *display, + /* [in] */ IXCLRLibrarySupport *libSupport, + /* [in] */ IXCLRDisassemblySupport *dis); + + HRESULT ( STDMETHODCALLTYPE *GetGcNotification )( + IXCLRDataProcess2 * This, + /* [out][in] */ GcEvtArgs *gcEvtArgs); + + HRESULT ( STDMETHODCALLTYPE *SetGcNotification )( + IXCLRDataProcess2 * This, + /* [in] */ GcEvtArgs gcEvtArgs); + + END_INTERFACE + } IXCLRDataProcess2Vtbl; + + interface IXCLRDataProcess2 + { + CONST_VTBL struct IXCLRDataProcess2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataProcess2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataProcess2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataProcess2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataProcess2_Flush(This) \ + ( (This)->lpVtbl -> Flush(This) ) + +#define IXCLRDataProcess2_StartEnumTasks(This,handle) \ + ( (This)->lpVtbl -> StartEnumTasks(This,handle) ) + +#define IXCLRDataProcess2_EnumTask(This,handle,task) \ + ( (This)->lpVtbl -> EnumTask(This,handle,task) ) + +#define IXCLRDataProcess2_EndEnumTasks(This,handle) \ + ( (This)->lpVtbl -> EndEnumTasks(This,handle) ) + +#define IXCLRDataProcess2_GetTaskByOSThreadID(This,osThreadID,task) \ + ( (This)->lpVtbl -> GetTaskByOSThreadID(This,osThreadID,task) ) + +#define IXCLRDataProcess2_GetTaskByUniqueID(This,taskID,task) \ + ( (This)->lpVtbl -> GetTaskByUniqueID(This,taskID,task) ) + +#define IXCLRDataProcess2_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataProcess2_IsSameObject(This,process) \ + ( (This)->lpVtbl -> IsSameObject(This,process) ) + +#define IXCLRDataProcess2_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataProcess2_GetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess2_SetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) + +#define IXCLRDataProcess2_GetAddressType(This,address,type) \ + ( (This)->lpVtbl -> GetAddressType(This,address,type) ) + +#define IXCLRDataProcess2_GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) \ + ( (This)->lpVtbl -> GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) ) + +#define IXCLRDataProcess2_StartEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess2_EnumAppDomain(This,handle,appDomain) \ + ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) + +#define IXCLRDataProcess2_EndEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) + +#define IXCLRDataProcess2_GetAppDomainByUniqueID(This,id,appDomain) \ + ( (This)->lpVtbl -> GetAppDomainByUniqueID(This,id,appDomain) ) + +#define IXCLRDataProcess2_StartEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess2_EnumAssembly(This,handle,assembly) \ + ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) + +#define IXCLRDataProcess2_EndEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) + +#define IXCLRDataProcess2_StartEnumModules(This,handle) \ + ( (This)->lpVtbl -> StartEnumModules(This,handle) ) + +#define IXCLRDataProcess2_EnumModule(This,handle,mod) \ + ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) + +#define IXCLRDataProcess2_EndEnumModules(This,handle) \ + ( (This)->lpVtbl -> EndEnumModules(This,handle) ) + +#define IXCLRDataProcess2_GetModuleByAddress(This,address,mod) \ + ( (This)->lpVtbl -> GetModuleByAddress(This,address,mod) ) + +#define IXCLRDataProcess2_StartEnumMethodInstancesByAddress(This,address,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstancesByAddress(This,address,appDomain,handle) ) + +#define IXCLRDataProcess2_EnumMethodInstanceByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodInstanceByAddress(This,handle,method) ) + +#define IXCLRDataProcess2_EndEnumMethodInstancesByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstancesByAddress(This,handle) ) + +#define IXCLRDataProcess2_GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) \ + ( (This)->lpVtbl -> GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) ) + +#define IXCLRDataProcess2_GetExceptionStateByExceptionRecord(This,record,exState) \ + ( (This)->lpVtbl -> GetExceptionStateByExceptionRecord(This,record,exState) ) + +#define IXCLRDataProcess2_TranslateExceptionRecordToNotification(This,record,notify) \ + ( (This)->lpVtbl -> TranslateExceptionRecordToNotification(This,record,notify) ) + +#define IXCLRDataProcess2_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataProcess2_CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) \ + ( (This)->lpVtbl -> CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) ) + +#define IXCLRDataProcess2_SetAllTypeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllTypeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess2_SetAllCodeNotifications(This,mod,flags) \ + ( (This)->lpVtbl -> SetAllCodeNotifications(This,mod,flags) ) + +#define IXCLRDataProcess2_GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess2_SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess2_GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ + ( (This)->lpVtbl -> GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) + +#define IXCLRDataProcess2_SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ + ( (This)->lpVtbl -> SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) + +#define IXCLRDataProcess2_GetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> GetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess2_SetOtherNotificationFlags(This,flags) \ + ( (This)->lpVtbl -> SetOtherNotificationFlags(This,flags) ) + +#define IXCLRDataProcess2_StartEnumMethodDefinitionsByAddress(This,address,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitionsByAddress(This,address,handle) ) + +#define IXCLRDataProcess2_EnumMethodDefinitionByAddress(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodDefinitionByAddress(This,handle,method) ) + +#define IXCLRDataProcess2_EndEnumMethodDefinitionsByAddress(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitionsByAddress(This,handle) ) + +#define IXCLRDataProcess2_FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess2_FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ + ( (This)->lpVtbl -> FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) + +#define IXCLRDataProcess2_DumpNativeImage(This,loadedBase,name,display,libSupport,dis) \ + ( (This)->lpVtbl -> DumpNativeImage(This,loadedBase,name,display,libSupport,dis) ) + + +#define IXCLRDataProcess2_GetGcNotification(This,gcEvtArgs) \ + ( (This)->lpVtbl -> GetGcNotification(This,gcEvtArgs) ) + +#define IXCLRDataProcess2_SetGcNotification(This,gcEvtArgs) \ + ( (This)->lpVtbl -> SetGcNotification(This,gcEvtArgs) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataProcess2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0006 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0006_0001 + { + CLRDATA_DOMAIN_DEFAULT = 0 + } CLRDataAppDomainFlag; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0006_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0006_v0_0_s_ifspec; + +#ifndef __IXCLRDataAppDomain_INTERFACE_DEFINED__ +#define __IXCLRDataAppDomain_INTERFACE_DEFINED__ + +/* interface IXCLRDataAppDomain */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataAppDomain; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7CA04601-C702-4670-A63C-FA44F7DA7BD5") + IXCLRDataAppDomain : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ IXCLRDataProcess **process) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUniqueID( + /* [out] */ ULONG64 *id) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataAppDomain *appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetManagedObject( + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataAppDomainVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataAppDomain * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataAppDomain * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataAppDomain * This); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + IXCLRDataAppDomain * This, + /* [out] */ IXCLRDataProcess **process); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataAppDomain * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetUniqueID )( + IXCLRDataAppDomain * This, + /* [out] */ ULONG64 *id); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataAppDomain * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataAppDomain * This, + /* [in] */ IXCLRDataAppDomain *appDomain); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataAppDomain * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataAppDomain * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + END_INTERFACE + } IXCLRDataAppDomainVtbl; + + interface IXCLRDataAppDomain + { + CONST_VTBL struct IXCLRDataAppDomainVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataAppDomain_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataAppDomain_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataAppDomain_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataAppDomain_GetProcess(This,process) \ + ( (This)->lpVtbl -> GetProcess(This,process) ) + +#define IXCLRDataAppDomain_GetName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) + +#define IXCLRDataAppDomain_GetUniqueID(This,id) \ + ( (This)->lpVtbl -> GetUniqueID(This,id) ) + +#define IXCLRDataAppDomain_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataAppDomain_IsSameObject(This,appDomain) \ + ( (This)->lpVtbl -> IsSameObject(This,appDomain) ) + +#define IXCLRDataAppDomain_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataAppDomain_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataAppDomain_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0007 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0007_0001 + { + CLRDATA_ASSEMBLY_DEFAULT = 0 + } CLRDataAssemblyFlag; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0007_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0007_v0_0_s_ifspec; + +#ifndef __IXCLRDataAssembly_INTERFACE_DEFINED__ +#define __IXCLRDataAssembly_INTERFACE_DEFINED__ + +/* interface IXCLRDataAssembly */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataAssembly; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2FA17588-43C2-46ab-9B51-C8F01E39C9AC") + IXCLRDataAssembly : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE StartEnumModules( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumModule( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumModules( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFileName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataAssembly *assembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDisplayName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataAssemblyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataAssembly * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataAssembly * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataAssembly * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( + IXCLRDataAssembly * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumModule )( + IXCLRDataAssembly * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( + IXCLRDataAssembly * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataAssembly * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFileName )( + IXCLRDataAssembly * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataAssembly * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataAssembly * This, + /* [in] */ IXCLRDataAssembly *assembly); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataAssembly * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( + IXCLRDataAssembly * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( + IXCLRDataAssembly * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( + IXCLRDataAssembly * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( + IXCLRDataAssembly * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + END_INTERFACE + } IXCLRDataAssemblyVtbl; + + interface IXCLRDataAssembly + { + CONST_VTBL struct IXCLRDataAssemblyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataAssembly_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataAssembly_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataAssembly_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataAssembly_StartEnumModules(This,handle) \ + ( (This)->lpVtbl -> StartEnumModules(This,handle) ) + +#define IXCLRDataAssembly_EnumModule(This,handle,mod) \ + ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) + +#define IXCLRDataAssembly_EndEnumModules(This,handle) \ + ( (This)->lpVtbl -> EndEnumModules(This,handle) ) + +#define IXCLRDataAssembly_GetName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) + +#define IXCLRDataAssembly_GetFileName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetFileName(This,bufLen,nameLen,name) ) + +#define IXCLRDataAssembly_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataAssembly_IsSameObject(This,assembly) \ + ( (This)->lpVtbl -> IsSameObject(This,assembly) ) + +#define IXCLRDataAssembly_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataAssembly_StartEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) + +#define IXCLRDataAssembly_EnumAppDomain(This,handle,appDomain) \ + ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) + +#define IXCLRDataAssembly_EndEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) + +#define IXCLRDataAssembly_GetDisplayName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetDisplayName(This,bufLen,nameLen,name) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataAssembly_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0008 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0008_0001 + { + CLRDATA_MODULE_DEFAULT = 0, + CLRDATA_MODULE_IS_DYNAMIC = 0x1, + CLRDATA_MODULE_IS_MEMORY_STREAM = 0x2 + } CLRDataModuleFlag; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0008_0002 + { + CLRDATA_MODULE_PE_FILE = 0, + CLRDATA_MODULE_PREJIT_FILE = ( CLRDATA_MODULE_PE_FILE + 1 ) , + CLRDATA_MODULE_MEMORY_STREAM = ( CLRDATA_MODULE_PREJIT_FILE + 1 ) , + CLRDATA_MODULE_OTHER = ( CLRDATA_MODULE_MEMORY_STREAM + 1 ) + } CLRDataModuleExtentType; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0008_0003 + { + CLRDATA_ADDRESS base; + ULONG32 length; + CLRDataModuleExtentType type; + } CLRDATA_MODULE_EXTENT; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0008_0004 + { + CLRDATA_TYPENOTIFY_NONE = 0, + CLRDATA_TYPENOTIFY_LOADED = 0x1, + CLRDATA_TYPENOTIFY_UNLOADED = 0x2 + } CLRDataTypeNotification; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0008_0005 + { + CLRDATA_METHNOTIFY_NONE = 0, + CLRDATA_METHNOTIFY_GENERATED = 0x1, + CLRDATA_METHNOTIFY_DISCARDED = 0x2 + } CLRDataMethodCodeNotification; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0008_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0008_v0_0_s_ifspec; + +#ifndef __IXCLRDataModule_INTERFACE_DEFINED__ +#define __IXCLRDataModule_INTERFACE_DEFINED__ + +/* interface IXCLRDataModule */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataModule; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("88E32849-0A0A-4cb0-9022-7CD2E9E139E2") + IXCLRDataModule : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAssembly( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitions( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinition( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitions( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstances( + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumTypeInstance( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstances( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitionsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinitionByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitionsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstancesByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumTypeInstanceByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **type) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstancesByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeDefinitionByToken( + /* [in] */ mdTypeDef token, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken( + /* [in] */ mdMethodDef token, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumDataByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumDataByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumDataByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFileName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataModule *mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumExtent( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_MODULE_EXTENT *extent) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetVersionId( + /* [out] */ GUID *vid) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataModuleVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataModule * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataModule * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataModule * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( + IXCLRDataModule * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAssembly **assembly); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTypeDefinitions )( + IXCLRDataModule * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTypeDefinition )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTypeDefinitions )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTypeInstances )( + IXCLRDataModule * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTypeInstance )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **typeInstance); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTypeInstances )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTypeDefinitionsByName )( + IXCLRDataModule * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTypeDefinitionByName )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTypeDefinitionsByName )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumTypeInstancesByName )( + IXCLRDataModule * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumTypeInstanceByName )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **type); + + HRESULT ( STDMETHODCALLTYPE *EndEnumTypeInstancesByName )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetTypeDefinitionByToken )( + IXCLRDataModule * This, + /* [in] */ mdTypeDef token, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByName )( + IXCLRDataModule * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByName )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByName )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByName )( + IXCLRDataModule * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByName )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByName )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDefinitionByToken )( + IXCLRDataModule * This, + /* [in] */ mdMethodDef token, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition); + + HRESULT ( STDMETHODCALLTYPE *StartEnumDataByName )( + IXCLRDataModule * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumDataByName )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *EndEnumDataByName )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataModule * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFileName )( + IXCLRDataModule * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataModule * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataModule * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( + IXCLRDataModule * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumExtent )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_MODULE_EXTENT *extent); + + HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataModule * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( + IXCLRDataModule * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( + IXCLRDataModule * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( + IXCLRDataModule * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetVersionId )( + IXCLRDataModule * This, + /* [out] */ GUID *vid); + + END_INTERFACE + } IXCLRDataModuleVtbl; + + interface IXCLRDataModule + { + CONST_VTBL struct IXCLRDataModuleVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataModule_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataModule_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataModule_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataModule_StartEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) + +#define IXCLRDataModule_EnumAssembly(This,handle,assembly) \ + ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) + +#define IXCLRDataModule_EndEnumAssemblies(This,handle) \ + ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) + +#define IXCLRDataModule_StartEnumTypeDefinitions(This,handle) \ + ( (This)->lpVtbl -> StartEnumTypeDefinitions(This,handle) ) + +#define IXCLRDataModule_EnumTypeDefinition(This,handle,typeDefinition) \ + ( (This)->lpVtbl -> EnumTypeDefinition(This,handle,typeDefinition) ) + +#define IXCLRDataModule_EndEnumTypeDefinitions(This,handle) \ + ( (This)->lpVtbl -> EndEnumTypeDefinitions(This,handle) ) + +#define IXCLRDataModule_StartEnumTypeInstances(This,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumTypeInstances(This,appDomain,handle) ) + +#define IXCLRDataModule_EnumTypeInstance(This,handle,typeInstance) \ + ( (This)->lpVtbl -> EnumTypeInstance(This,handle,typeInstance) ) + +#define IXCLRDataModule_EndEnumTypeInstances(This,handle) \ + ( (This)->lpVtbl -> EndEnumTypeInstances(This,handle) ) + +#define IXCLRDataModule_StartEnumTypeDefinitionsByName(This,name,flags,handle) \ + ( (This)->lpVtbl -> StartEnumTypeDefinitionsByName(This,name,flags,handle) ) + +#define IXCLRDataModule_EnumTypeDefinitionByName(This,handle,type) \ + ( (This)->lpVtbl -> EnumTypeDefinitionByName(This,handle,type) ) + +#define IXCLRDataModule_EndEnumTypeDefinitionsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumTypeDefinitionsByName(This,handle) ) + +#define IXCLRDataModule_StartEnumTypeInstancesByName(This,name,flags,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumTypeInstancesByName(This,name,flags,appDomain,handle) ) + +#define IXCLRDataModule_EnumTypeInstanceByName(This,handle,type) \ + ( (This)->lpVtbl -> EnumTypeInstanceByName(This,handle,type) ) + +#define IXCLRDataModule_EndEnumTypeInstancesByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumTypeInstancesByName(This,handle) ) + +#define IXCLRDataModule_GetTypeDefinitionByToken(This,token,typeDefinition) \ + ( (This)->lpVtbl -> GetTypeDefinitionByToken(This,token,typeDefinition) ) + +#define IXCLRDataModule_StartEnumMethodDefinitionsByName(This,name,flags,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitionsByName(This,name,flags,handle) ) + +#define IXCLRDataModule_EnumMethodDefinitionByName(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodDefinitionByName(This,handle,method) ) + +#define IXCLRDataModule_EndEnumMethodDefinitionsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitionsByName(This,handle) ) + +#define IXCLRDataModule_StartEnumMethodInstancesByName(This,name,flags,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstancesByName(This,name,flags,appDomain,handle) ) + +#define IXCLRDataModule_EnumMethodInstanceByName(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodInstanceByName(This,handle,method) ) + +#define IXCLRDataModule_EndEnumMethodInstancesByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstancesByName(This,handle) ) + +#define IXCLRDataModule_GetMethodDefinitionByToken(This,token,methodDefinition) \ + ( (This)->lpVtbl -> GetMethodDefinitionByToken(This,token,methodDefinition) ) + +#define IXCLRDataModule_StartEnumDataByName(This,name,flags,appDomain,tlsTask,handle) \ + ( (This)->lpVtbl -> StartEnumDataByName(This,name,flags,appDomain,tlsTask,handle) ) + +#define IXCLRDataModule_EnumDataByName(This,handle,value) \ + ( (This)->lpVtbl -> EnumDataByName(This,handle,value) ) + +#define IXCLRDataModule_EndEnumDataByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumDataByName(This,handle) ) + +#define IXCLRDataModule_GetName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) + +#define IXCLRDataModule_GetFileName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetFileName(This,bufLen,nameLen,name) ) + +#define IXCLRDataModule_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataModule_IsSameObject(This,mod) \ + ( (This)->lpVtbl -> IsSameObject(This,mod) ) + +#define IXCLRDataModule_StartEnumExtents(This,handle) \ + ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) + +#define IXCLRDataModule_EnumExtent(This,handle,extent) \ + ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) + +#define IXCLRDataModule_EndEnumExtents(This,handle) \ + ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) + +#define IXCLRDataModule_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataModule_StartEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) + +#define IXCLRDataModule_EnumAppDomain(This,handle,appDomain) \ + ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) + +#define IXCLRDataModule_EndEnumAppDomains(This,handle) \ + ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) + +#define IXCLRDataModule_GetVersionId(This,vid) \ + ( (This)->lpVtbl -> GetVersionId(This,vid) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataModule_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0009 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0009_v0_0_s_ifspec; + +#ifndef __IXCLRDataModule2_INTERFACE_DEFINED__ +#define __IXCLRDataModule2_INTERFACE_DEFINED__ + +/* interface IXCLRDataModule2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataModule2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("34625881-7EB3-4524-817B-8DB9D064C760") + IXCLRDataModule2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( + /* [in] */ DWORD dwFlags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataModule2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataModule2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataModule2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataModule2 * This); + + HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( + IXCLRDataModule2 * This, + /* [in] */ DWORD dwFlags); + + END_INTERFACE + } IXCLRDataModule2Vtbl; + + interface IXCLRDataModule2 + { + CONST_VTBL struct IXCLRDataModule2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataModule2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataModule2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataModule2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataModule2_SetJITCompilerFlags(This,dwFlags) \ + ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataModule2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0010 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0010_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0010_v0_0_s_ifspec; + +#ifndef __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ +#define __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ + +/* interface IXCLRDataTypeDefinition */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataTypeDefinition; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4675666C-C275-45b8-9F6C-AB165D5C1E09") + IXCLRDataTypeDefinition : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitions( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinition( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitions( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken( + /* [in] */ mdMethodDef token, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumInstances( + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumInstance( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **instance) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumInstances( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( + /* [out] */ mdTypeDef *token, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCorElementType( + /* [out] */ CorElementType *type) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataTypeDefinition *type) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArrayRank( + /* [out] */ ULONG32 *rank) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBase( + /* [out] */ IXCLRDataTypeDefinition **base) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumFields( + /* [in] */ ULONG32 flags, + /* [out] */ ULONG32 *numFields) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumFields( + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumField( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumFields( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumFieldByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldByToken( + /* [in] */ mdFieldDef token, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeNotification( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetTypeNotification( + /* [in] */ ULONG32 flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumField2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2( + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataTypeDefinitionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataTypeDefinition * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataTypeDefinition * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataTypeDefinition * This); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + IXCLRDataTypeDefinition * This, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitions )( + IXCLRDataTypeDefinition * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinition )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitions )( + IXCLRDataTypeDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByName )( + IXCLRDataTypeDefinition * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByName )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodDefinition **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByName )( + IXCLRDataTypeDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetMethodDefinitionByToken )( + IXCLRDataTypeDefinition * This, + /* [in] */ mdMethodDef token, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition); + + HRESULT ( STDMETHODCALLTYPE *StartEnumInstances )( + IXCLRDataTypeDefinition * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumInstance )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeInstance **instance); + + HRESULT ( STDMETHODCALLTYPE *EndEnumInstances )( + IXCLRDataTypeDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataTypeDefinition * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( + IXCLRDataTypeDefinition * This, + /* [out] */ mdTypeDef *token, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *GetCorElementType )( + IXCLRDataTypeDefinition * This, + /* [out] */ CorElementType *type); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataTypeDefinition * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataTypeDefinition * This, + /* [in] */ IXCLRDataTypeDefinition *type); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataTypeDefinition * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetArrayRank )( + IXCLRDataTypeDefinition * This, + /* [out] */ ULONG32 *rank); + + HRESULT ( STDMETHODCALLTYPE *GetBase )( + IXCLRDataTypeDefinition * This, + /* [out] */ IXCLRDataTypeDefinition **base); + + HRESULT ( STDMETHODCALLTYPE *GetNumFields )( + IXCLRDataTypeDefinition * This, + /* [in] */ ULONG32 flags, + /* [out] */ ULONG32 *numFields); + + HRESULT ( STDMETHODCALLTYPE *StartEnumFields )( + IXCLRDataTypeDefinition * This, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumField )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EndEnumFields )( + IXCLRDataTypeDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumFieldsByName )( + IXCLRDataTypeDefinition * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumFieldByName )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EndEnumFieldsByName )( + IXCLRDataTypeDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetFieldByToken )( + IXCLRDataTypeDefinition * This, + /* [in] */ mdFieldDef token, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *GetTypeNotification )( + IXCLRDataTypeDefinition * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *SetTypeNotification )( + IXCLRDataTypeDefinition * This, + /* [in] */ ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *EnumField2 )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EnumFieldByName2 )( + IXCLRDataTypeDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *GetFieldByToken2 )( + IXCLRDataTypeDefinition * This, + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataTypeDefinition **type, + /* [out] */ ULONG32 *flags); + + END_INTERFACE + } IXCLRDataTypeDefinitionVtbl; + + interface IXCLRDataTypeDefinition + { + CONST_VTBL struct IXCLRDataTypeDefinitionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataTypeDefinition_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataTypeDefinition_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataTypeDefinition_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataTypeDefinition_GetModule(This,mod) \ + ( (This)->lpVtbl -> GetModule(This,mod) ) + +#define IXCLRDataTypeDefinition_StartEnumMethodDefinitions(This,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitions(This,handle) ) + +#define IXCLRDataTypeDefinition_EnumMethodDefinition(This,handle,methodDefinition) \ + ( (This)->lpVtbl -> EnumMethodDefinition(This,handle,methodDefinition) ) + +#define IXCLRDataTypeDefinition_EndEnumMethodDefinitions(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitions(This,handle) ) + +#define IXCLRDataTypeDefinition_StartEnumMethodDefinitionsByName(This,name,flags,handle) \ + ( (This)->lpVtbl -> StartEnumMethodDefinitionsByName(This,name,flags,handle) ) + +#define IXCLRDataTypeDefinition_EnumMethodDefinitionByName(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodDefinitionByName(This,handle,method) ) + +#define IXCLRDataTypeDefinition_EndEnumMethodDefinitionsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodDefinitionsByName(This,handle) ) + +#define IXCLRDataTypeDefinition_GetMethodDefinitionByToken(This,token,methodDefinition) \ + ( (This)->lpVtbl -> GetMethodDefinitionByToken(This,token,methodDefinition) ) + +#define IXCLRDataTypeDefinition_StartEnumInstances(This,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumInstances(This,appDomain,handle) ) + +#define IXCLRDataTypeDefinition_EnumInstance(This,handle,instance) \ + ( (This)->lpVtbl -> EnumInstance(This,handle,instance) ) + +#define IXCLRDataTypeDefinition_EndEnumInstances(This,handle) \ + ( (This)->lpVtbl -> EndEnumInstances(This,handle) ) + +#define IXCLRDataTypeDefinition_GetName(This,flags,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataTypeDefinition_GetTokenAndScope(This,token,mod) \ + ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) + +#define IXCLRDataTypeDefinition_GetCorElementType(This,type) \ + ( (This)->lpVtbl -> GetCorElementType(This,type) ) + +#define IXCLRDataTypeDefinition_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataTypeDefinition_IsSameObject(This,type) \ + ( (This)->lpVtbl -> IsSameObject(This,type) ) + +#define IXCLRDataTypeDefinition_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataTypeDefinition_GetArrayRank(This,rank) \ + ( (This)->lpVtbl -> GetArrayRank(This,rank) ) + +#define IXCLRDataTypeDefinition_GetBase(This,base) \ + ( (This)->lpVtbl -> GetBase(This,base) ) + +#define IXCLRDataTypeDefinition_GetNumFields(This,flags,numFields) \ + ( (This)->lpVtbl -> GetNumFields(This,flags,numFields) ) + +#define IXCLRDataTypeDefinition_StartEnumFields(This,flags,handle) \ + ( (This)->lpVtbl -> StartEnumFields(This,flags,handle) ) + +#define IXCLRDataTypeDefinition_EnumField(This,handle,nameBufLen,nameLen,nameBuf,type,flags,token) \ + ( (This)->lpVtbl -> EnumField(This,handle,nameBufLen,nameLen,nameBuf,type,flags,token) ) + +#define IXCLRDataTypeDefinition_EndEnumFields(This,handle) \ + ( (This)->lpVtbl -> EndEnumFields(This,handle) ) + +#define IXCLRDataTypeDefinition_StartEnumFieldsByName(This,name,nameFlags,fieldFlags,handle) \ + ( (This)->lpVtbl -> StartEnumFieldsByName(This,name,nameFlags,fieldFlags,handle) ) + +#define IXCLRDataTypeDefinition_EnumFieldByName(This,handle,type,flags,token) \ + ( (This)->lpVtbl -> EnumFieldByName(This,handle,type,flags,token) ) + +#define IXCLRDataTypeDefinition_EndEnumFieldsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumFieldsByName(This,handle) ) + +#define IXCLRDataTypeDefinition_GetFieldByToken(This,token,nameBufLen,nameLen,nameBuf,type,flags) \ + ( (This)->lpVtbl -> GetFieldByToken(This,token,nameBufLen,nameLen,nameBuf,type,flags) ) + +#define IXCLRDataTypeDefinition_GetTypeNotification(This,flags) \ + ( (This)->lpVtbl -> GetTypeNotification(This,flags) ) + +#define IXCLRDataTypeDefinition_SetTypeNotification(This,flags) \ + ( (This)->lpVtbl -> SetTypeNotification(This,flags) ) + +#define IXCLRDataTypeDefinition_EnumField2(This,handle,nameBufLen,nameLen,nameBuf,type,flags,tokenScope,token) \ + ( (This)->lpVtbl -> EnumField2(This,handle,nameBufLen,nameLen,nameBuf,type,flags,tokenScope,token) ) + +#define IXCLRDataTypeDefinition_EnumFieldByName2(This,handle,type,flags,tokenScope,token) \ + ( (This)->lpVtbl -> EnumFieldByName2(This,handle,type,flags,tokenScope,token) ) + +#define IXCLRDataTypeDefinition_GetFieldByToken2(This,tokenScope,token,nameBufLen,nameLen,nameBuf,type,flags) \ + ( (This)->lpVtbl -> GetFieldByToken2(This,tokenScope,token,nameBufLen,nameLen,nameBuf,type,flags) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0011 */ +/* [local] */ + +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0011_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0011_v0_0_s_ifspec; + +#ifndef __IXCLRDataTypeInstance_INTERFACE_DEFINED__ +#define __IXCLRDataTypeInstance_INTERFACE_DEFINED__ + +/* interface IXCLRDataTypeInstance */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataTypeInstance; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("4D078D91-9CB3-4b0d-97AC-28C8A5A82597") + IXCLRDataTypeInstance : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstances( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodInstance( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **methodInstance) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstances( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields( + /* [out] */ ULONG32 *numFields) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByIndex( + /* [in] */ ULONG32 index, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( + /* [out] */ ULONG32 *numTypeArgs) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetModule( + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefinition( + /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataTypeInstance *type) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields2( + /* [in] */ ULONG32 flags, + /* [out] */ ULONG32 *numFields) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFields( + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumStaticField( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFields( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName2( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName2( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken( + /* [in] */ mdFieldDef token, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBase( + /* [out] */ IXCLRDataTypeInstance **base) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumStaticField2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName3( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken2( + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataTypeInstanceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataTypeInstance * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataTypeInstance * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataTypeInstance * This); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstances )( + IXCLRDataTypeInstance * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstance )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **methodInstance); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstances )( + IXCLRDataTypeInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByName )( + IXCLRDataTypeInstance * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByName )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByName )( + IXCLRDataTypeInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetNumStaticFields )( + IXCLRDataTypeInstance * This, + /* [out] */ ULONG32 *numFields); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByIndex )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 index, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFieldsByName )( + IXCLRDataTypeInstance * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFieldsByName )( + IXCLRDataTypeInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( + IXCLRDataTypeInstance * This, + /* [out] */ ULONG32 *numTypeArgs); + + HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetModule )( + IXCLRDataTypeInstance * This, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *GetDefinition )( + IXCLRDataTypeInstance * This, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataTypeInstance * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataTypeInstance * This, + /* [in] */ IXCLRDataTypeInstance *type); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetNumStaticFields2 )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 flags, + /* [out] */ ULONG32 *numFields); + + HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFields )( + IXCLRDataTypeInstance * This, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumStaticField )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFields )( + IXCLRDataTypeInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFieldsByName2 )( + IXCLRDataTypeInstance * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName2 )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFieldsByName2 )( + IXCLRDataTypeInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByToken )( + IXCLRDataTypeInstance * This, + /* [in] */ mdFieldDef token, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetBase )( + IXCLRDataTypeInstance * This, + /* [out] */ IXCLRDataTypeInstance **base); + + HRESULT ( STDMETHODCALLTYPE *EnumStaticField2 )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName3 )( + IXCLRDataTypeInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **value, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByToken2 )( + IXCLRDataTypeInstance * This, + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [in] */ IXCLRDataTask *tlsTask, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + END_INTERFACE + } IXCLRDataTypeInstanceVtbl; + + interface IXCLRDataTypeInstance + { + CONST_VTBL struct IXCLRDataTypeInstanceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataTypeInstance_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataTypeInstance_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataTypeInstance_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataTypeInstance_StartEnumMethodInstances(This,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstances(This,handle) ) + +#define IXCLRDataTypeInstance_EnumMethodInstance(This,handle,methodInstance) \ + ( (This)->lpVtbl -> EnumMethodInstance(This,handle,methodInstance) ) + +#define IXCLRDataTypeInstance_EndEnumMethodInstances(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstances(This,handle) ) + +#define IXCLRDataTypeInstance_StartEnumMethodInstancesByName(This,name,flags,handle) \ + ( (This)->lpVtbl -> StartEnumMethodInstancesByName(This,name,flags,handle) ) + +#define IXCLRDataTypeInstance_EnumMethodInstanceByName(This,handle,method) \ + ( (This)->lpVtbl -> EnumMethodInstanceByName(This,handle,method) ) + +#define IXCLRDataTypeInstance_EndEnumMethodInstancesByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumMethodInstancesByName(This,handle) ) + +#define IXCLRDataTypeInstance_GetNumStaticFields(This,numFields) \ + ( (This)->lpVtbl -> GetNumStaticFields(This,numFields) ) + +#define IXCLRDataTypeInstance_GetStaticFieldByIndex(This,index,tlsTask,field,bufLen,nameLen,nameBuf,token) \ + ( (This)->lpVtbl -> GetStaticFieldByIndex(This,index,tlsTask,field,bufLen,nameLen,nameBuf,token) ) + +#define IXCLRDataTypeInstance_StartEnumStaticFieldsByName(This,name,flags,tlsTask,handle) \ + ( (This)->lpVtbl -> StartEnumStaticFieldsByName(This,name,flags,tlsTask,handle) ) + +#define IXCLRDataTypeInstance_EnumStaticFieldByName(This,handle,value) \ + ( (This)->lpVtbl -> EnumStaticFieldByName(This,handle,value) ) + +#define IXCLRDataTypeInstance_EndEnumStaticFieldsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumStaticFieldsByName(This,handle) ) + +#define IXCLRDataTypeInstance_GetNumTypeArguments(This,numTypeArgs) \ + ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) + +#define IXCLRDataTypeInstance_GetTypeArgumentByIndex(This,index,typeArg) \ + ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) + +#define IXCLRDataTypeInstance_GetName(This,flags,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataTypeInstance_GetModule(This,mod) \ + ( (This)->lpVtbl -> GetModule(This,mod) ) + +#define IXCLRDataTypeInstance_GetDefinition(This,typeDefinition) \ + ( (This)->lpVtbl -> GetDefinition(This,typeDefinition) ) + +#define IXCLRDataTypeInstance_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataTypeInstance_IsSameObject(This,type) \ + ( (This)->lpVtbl -> IsSameObject(This,type) ) + +#define IXCLRDataTypeInstance_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataTypeInstance_GetNumStaticFields2(This,flags,numFields) \ + ( (This)->lpVtbl -> GetNumStaticFields2(This,flags,numFields) ) + +#define IXCLRDataTypeInstance_StartEnumStaticFields(This,flags,tlsTask,handle) \ + ( (This)->lpVtbl -> StartEnumStaticFields(This,flags,tlsTask,handle) ) + +#define IXCLRDataTypeInstance_EnumStaticField(This,handle,value) \ + ( (This)->lpVtbl -> EnumStaticField(This,handle,value) ) + +#define IXCLRDataTypeInstance_EndEnumStaticFields(This,handle) \ + ( (This)->lpVtbl -> EndEnumStaticFields(This,handle) ) + +#define IXCLRDataTypeInstance_StartEnumStaticFieldsByName2(This,name,nameFlags,fieldFlags,tlsTask,handle) \ + ( (This)->lpVtbl -> StartEnumStaticFieldsByName2(This,name,nameFlags,fieldFlags,tlsTask,handle) ) + +#define IXCLRDataTypeInstance_EnumStaticFieldByName2(This,handle,value) \ + ( (This)->lpVtbl -> EnumStaticFieldByName2(This,handle,value) ) + +#define IXCLRDataTypeInstance_EndEnumStaticFieldsByName2(This,handle) \ + ( (This)->lpVtbl -> EndEnumStaticFieldsByName2(This,handle) ) + +#define IXCLRDataTypeInstance_GetStaticFieldByToken(This,token,tlsTask,field,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetStaticFieldByToken(This,token,tlsTask,field,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataTypeInstance_GetBase(This,base) \ + ( (This)->lpVtbl -> GetBase(This,base) ) + +#define IXCLRDataTypeInstance_EnumStaticField2(This,handle,value,bufLen,nameLen,nameBuf,tokenScope,token) \ + ( (This)->lpVtbl -> EnumStaticField2(This,handle,value,bufLen,nameLen,nameBuf,tokenScope,token) ) + +#define IXCLRDataTypeInstance_EnumStaticFieldByName3(This,handle,value,tokenScope,token) \ + ( (This)->lpVtbl -> EnumStaticFieldByName3(This,handle,value,tokenScope,token) ) + +#define IXCLRDataTypeInstance_GetStaticFieldByToken2(This,tokenScope,token,tlsTask,field,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetStaticFieldByToken2(This,tokenScope,token,tlsTask,field,bufLen,nameLen,nameBuf) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataTypeInstance_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0012 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0012_0001 + { + CLRDATA_SOURCE_TYPE_INVALID = 0 + } CLRDataSourceType; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0012_0002 + { + CLRDATA_IL_OFFSET_NO_MAPPING = -1, + CLRDATA_IL_OFFSET_PROLOG = -2, + CLRDATA_IL_OFFSET_EPILOG = -3 + } CLRDATA_IL_OFFSET_MARKER; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0012_0003 + { + ULONG32 ilOffset; + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; + CLRDataSourceType type; + } CLRDATA_IL_ADDRESS_MAP; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0012_0004 + { + CLRDATA_METHOD_DEFAULT = 0, + CLRDATA_METHOD_HAS_THIS = 0x1 + } CLRDataMethodFlag; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0012_0005 + { + CLRDATA_METHDEF_IL = 0 + } CLRDataMethodDefinitionExtentType; + +typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0012_0006 + { + CLRDATA_ADDRESS startAddress; + CLRDATA_ADDRESS endAddress; + ULONG32 enCVersion; + CLRDataMethodDefinitionExtentType type; + } CLRDATA_METHDEF_EXTENT; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0012_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0012_v0_0_s_ifspec; + +#ifndef __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ +#define __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ + +/* interface IXCLRDataMethodDefinition */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataMethodDefinition; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("AAF60008-FB2C-420b-8FB1-42D244A54A97") + IXCLRDataMethodDefinition : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTypeDefinition( + /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumInstances( + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumInstance( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **instance) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumInstances( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( + /* [out] */ mdMethodDef *token, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataMethodDefinition *method) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLatestEnCVersion( + /* [out] */ ULONG32 *version) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumExtent( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_METHDEF_EXTENT *extent) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeNotification( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCodeNotification( + /* [in] */ ULONG32 flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress( + /* [out] */ CLRDATA_ADDRESS *addr) = 0; + + virtual HRESULT STDMETHODCALLTYPE HasClassOrMethodInstantiation( + /* [out] */ BOOL *bGeneric) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataMethodDefinitionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataMethodDefinition * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataMethodDefinition * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataMethodDefinition * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeDefinition )( + IXCLRDataMethodDefinition * This, + /* [out] */ IXCLRDataTypeDefinition **typeDefinition); + + HRESULT ( STDMETHODCALLTYPE *StartEnumInstances )( + IXCLRDataMethodDefinition * This, + /* [in] */ IXCLRDataAppDomain *appDomain, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumInstance )( + IXCLRDataMethodDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataMethodInstance **instance); + + HRESULT ( STDMETHODCALLTYPE *EndEnumInstances )( + IXCLRDataMethodDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataMethodDefinition * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( + IXCLRDataMethodDefinition * This, + /* [out] */ mdMethodDef *token, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataMethodDefinition * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataMethodDefinition * This, + /* [in] */ IXCLRDataMethodDefinition *method); + + HRESULT ( STDMETHODCALLTYPE *GetLatestEnCVersion )( + IXCLRDataMethodDefinition * This, + /* [out] */ ULONG32 *version); + + HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( + IXCLRDataMethodDefinition * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumExtent )( + IXCLRDataMethodDefinition * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_METHDEF_EXTENT *extent); + + HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( + IXCLRDataMethodDefinition * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetCodeNotification )( + IXCLRDataMethodDefinition * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *SetCodeNotification )( + IXCLRDataMethodDefinition * This, + /* [in] */ ULONG32 flags); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataMethodDefinition * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetRepresentativeEntryAddress )( + IXCLRDataMethodDefinition * This, + /* [out] */ CLRDATA_ADDRESS *addr); + + HRESULT ( STDMETHODCALLTYPE *HasClassOrMethodInstantiation )( + IXCLRDataMethodDefinition * This, + /* [out] */ BOOL *bGeneric); + + END_INTERFACE + } IXCLRDataMethodDefinitionVtbl; + + interface IXCLRDataMethodDefinition + { + CONST_VTBL struct IXCLRDataMethodDefinitionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataMethodDefinition_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataMethodDefinition_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataMethodDefinition_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataMethodDefinition_GetTypeDefinition(This,typeDefinition) \ + ( (This)->lpVtbl -> GetTypeDefinition(This,typeDefinition) ) + +#define IXCLRDataMethodDefinition_StartEnumInstances(This,appDomain,handle) \ + ( (This)->lpVtbl -> StartEnumInstances(This,appDomain,handle) ) + +#define IXCLRDataMethodDefinition_EnumInstance(This,handle,instance) \ + ( (This)->lpVtbl -> EnumInstance(This,handle,instance) ) + +#define IXCLRDataMethodDefinition_EndEnumInstances(This,handle) \ + ( (This)->lpVtbl -> EndEnumInstances(This,handle) ) + +#define IXCLRDataMethodDefinition_GetName(This,flags,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,name) ) + +#define IXCLRDataMethodDefinition_GetTokenAndScope(This,token,mod) \ + ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) + +#define IXCLRDataMethodDefinition_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataMethodDefinition_IsSameObject(This,method) \ + ( (This)->lpVtbl -> IsSameObject(This,method) ) + +#define IXCLRDataMethodDefinition_GetLatestEnCVersion(This,version) \ + ( (This)->lpVtbl -> GetLatestEnCVersion(This,version) ) + +#define IXCLRDataMethodDefinition_StartEnumExtents(This,handle) \ + ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) + +#define IXCLRDataMethodDefinition_EnumExtent(This,handle,extent) \ + ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) + +#define IXCLRDataMethodDefinition_EndEnumExtents(This,handle) \ + ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) + +#define IXCLRDataMethodDefinition_GetCodeNotification(This,flags) \ + ( (This)->lpVtbl -> GetCodeNotification(This,flags) ) + +#define IXCLRDataMethodDefinition_SetCodeNotification(This,flags) \ + ( (This)->lpVtbl -> SetCodeNotification(This,flags) ) + +#define IXCLRDataMethodDefinition_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataMethodDefinition_GetRepresentativeEntryAddress(This,addr) \ + ( (This)->lpVtbl -> GetRepresentativeEntryAddress(This,addr) ) + +#define IXCLRDataMethodDefinition_HasClassOrMethodInstantiation(This,bGeneric) \ + ( (This)->lpVtbl -> HasClassOrMethodInstantiation(This,bGeneric) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0013 */ +/* [local] */ + +#pragma warning(pop) +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0013_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0013_v0_0_s_ifspec; + +#ifndef __IXCLRDataMethodInstance_INTERFACE_DEFINED__ +#define __IXCLRDataMethodInstance_INTERFACE_DEFINED__ + +/* interface IXCLRDataMethodInstance */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataMethodInstance; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("ECD73800-22CA-4b0d-AB55-E9BA7E6318A5") + IXCLRDataMethodInstance : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetTypeInstance( + /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDefinition( + /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( + /* [out] */ mdMethodDef *token, + /* [out] */ IXCLRDataModule **mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataMethodInstance *method) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEnCVersion( + /* [out] */ ULONG32 *version) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( + /* [out] */ ULONG32 *numTypeArgs) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILOffsetsByAddress( + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 offsetsLen, + /* [out] */ ULONG32 *offsetsNeeded, + /* [size_is][out] */ ULONG32 ilOffsets[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddressRangesByILOffset( + /* [in] */ ULONG32 ilOffset, + /* [in] */ ULONG32 rangesLen, + /* [out] */ ULONG32 *rangesNeeded, + /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetILAddressMap( + /* [in] */ ULONG32 mapLen, + /* [out] */ ULONG32 *mapNeeded, + /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumExtent( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_ADDRESS_RANGE *extent) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress( + /* [out] */ CLRDATA_ADDRESS *addr) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataMethodInstanceVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataMethodInstance * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataMethodInstance * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataMethodInstance * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInstance )( + IXCLRDataMethodInstance * This, + /* [out] */ IXCLRDataTypeInstance **typeInstance); + + HRESULT ( STDMETHODCALLTYPE *GetDefinition )( + IXCLRDataMethodInstance * This, + /* [out] */ IXCLRDataMethodDefinition **methodDefinition); + + HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( + IXCLRDataMethodInstance * This, + /* [out] */ mdMethodDef *token, + /* [out] */ IXCLRDataModule **mod); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataMethodInstance * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataMethodInstance * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataMethodInstance * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *GetEnCVersion )( + IXCLRDataMethodInstance * This, + /* [out] */ ULONG32 *version); + + HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( + IXCLRDataMethodInstance * This, + /* [out] */ ULONG32 *numTypeArgs); + + HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( + IXCLRDataMethodInstance * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg); + + HRESULT ( STDMETHODCALLTYPE *GetILOffsetsByAddress )( + IXCLRDataMethodInstance * This, + /* [in] */ CLRDATA_ADDRESS address, + /* [in] */ ULONG32 offsetsLen, + /* [out] */ ULONG32 *offsetsNeeded, + /* [size_is][out] */ ULONG32 ilOffsets[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAddressRangesByILOffset )( + IXCLRDataMethodInstance * This, + /* [in] */ ULONG32 ilOffset, + /* [in] */ ULONG32 rangesLen, + /* [out] */ ULONG32 *rangesNeeded, + /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetILAddressMap )( + IXCLRDataMethodInstance * This, + /* [in] */ ULONG32 mapLen, + /* [out] */ ULONG32 *mapNeeded, + /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]); + + HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( + IXCLRDataMethodInstance * This, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumExtent )( + IXCLRDataMethodInstance * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ CLRDATA_ADDRESS_RANGE *extent); + + HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( + IXCLRDataMethodInstance * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataMethodInstance * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetRepresentativeEntryAddress )( + IXCLRDataMethodInstance * This, + /* [out] */ CLRDATA_ADDRESS *addr); + + END_INTERFACE + } IXCLRDataMethodInstanceVtbl; + + interface IXCLRDataMethodInstance + { + CONST_VTBL struct IXCLRDataMethodInstanceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataMethodInstance_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataMethodInstance_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataMethodInstance_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataMethodInstance_GetTypeInstance(This,typeInstance) \ + ( (This)->lpVtbl -> GetTypeInstance(This,typeInstance) ) + +#define IXCLRDataMethodInstance_GetDefinition(This,methodDefinition) \ + ( (This)->lpVtbl -> GetDefinition(This,methodDefinition) ) + +#define IXCLRDataMethodInstance_GetTokenAndScope(This,token,mod) \ + ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) + +#define IXCLRDataMethodInstance_GetName(This,flags,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataMethodInstance_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataMethodInstance_IsSameObject(This,method) \ + ( (This)->lpVtbl -> IsSameObject(This,method) ) + +#define IXCLRDataMethodInstance_GetEnCVersion(This,version) \ + ( (This)->lpVtbl -> GetEnCVersion(This,version) ) + +#define IXCLRDataMethodInstance_GetNumTypeArguments(This,numTypeArgs) \ + ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) + +#define IXCLRDataMethodInstance_GetTypeArgumentByIndex(This,index,typeArg) \ + ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) + +#define IXCLRDataMethodInstance_GetILOffsetsByAddress(This,address,offsetsLen,offsetsNeeded,ilOffsets) \ + ( (This)->lpVtbl -> GetILOffsetsByAddress(This,address,offsetsLen,offsetsNeeded,ilOffsets) ) + +#define IXCLRDataMethodInstance_GetAddressRangesByILOffset(This,ilOffset,rangesLen,rangesNeeded,addressRanges) \ + ( (This)->lpVtbl -> GetAddressRangesByILOffset(This,ilOffset,rangesLen,rangesNeeded,addressRanges) ) + +#define IXCLRDataMethodInstance_GetILAddressMap(This,mapLen,mapNeeded,maps) \ + ( (This)->lpVtbl -> GetILAddressMap(This,mapLen,mapNeeded,maps) ) + +#define IXCLRDataMethodInstance_StartEnumExtents(This,handle) \ + ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) + +#define IXCLRDataMethodInstance_EnumExtent(This,handle,extent) \ + ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) + +#define IXCLRDataMethodInstance_EndEnumExtents(This,handle) \ + ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) + +#define IXCLRDataMethodInstance_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataMethodInstance_GetRepresentativeEntryAddress(This,addr) \ + ( (This)->lpVtbl -> GetRepresentativeEntryAddress(This,addr) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataMethodInstance_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0014 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0014_0001 + { + CLRDATA_TASK_DEFAULT = 0, + CLRDATA_TASK_WAITING_FOR_GC = 0x1 + } CLRDataTaskFlag; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0014_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0014_v0_0_s_ifspec; + +#ifndef __IXCLRDataTask_INTERFACE_DEFINED__ +#define __IXCLRDataTask_INTERFACE_DEFINED__ + +/* interface IXCLRDataTask */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataTask; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("A5B0BEEA-EC62-4618-8012-A24FFC23934C") + IXCLRDataTask : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetProcess( + /* [out] */ IXCLRDataProcess **process) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomain( + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetUniqueID( + /* [out] */ ULONG64 *id) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameObject( + /* [in] */ IXCLRDataTask *task) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetManagedObject( + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState( + /* [out] */ ULONG32 *state) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState( + /* [in] */ ULONG32 state) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( + /* [in] */ ULONG32 flags, + /* [out] */ IXCLRDataStackWalk **stackWalk) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOSThreadID( + /* [out] */ ULONG32 *id) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContext( + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentExceptionState( + /* [out] */ IXCLRDataExceptionState **exception) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetName( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLastExceptionState( + /* [out] */ IXCLRDataExceptionState **exception) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataTaskVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataTask * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataTask * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataTask * This); + + HRESULT ( STDMETHODCALLTYPE *GetProcess )( + IXCLRDataTask * This, + /* [out] */ IXCLRDataProcess **process); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomain )( + IXCLRDataTask * This, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *GetUniqueID )( + IXCLRDataTask * This, + /* [out] */ ULONG64 *id); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataTask * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *IsSameObject )( + IXCLRDataTask * This, + /* [in] */ IXCLRDataTask *task); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataTask * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( + IXCLRDataTask * This, + /* [out] */ ULONG32 *state); + + HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( + IXCLRDataTask * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( + IXCLRDataTask * This, + /* [in] */ ULONG32 flags, + /* [out] */ IXCLRDataStackWalk **stackWalk); + + HRESULT ( STDMETHODCALLTYPE *GetOSThreadID )( + IXCLRDataTask * This, + /* [out] */ ULONG32 *id); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + IXCLRDataTask * This, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetContext )( + IXCLRDataTask * This, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCurrentExceptionState )( + IXCLRDataTask * This, + /* [out] */ IXCLRDataExceptionState **exception); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataTask * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetName )( + IXCLRDataTask * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetLastExceptionState )( + IXCLRDataTask * This, + /* [out] */ IXCLRDataExceptionState **exception); + + END_INTERFACE + } IXCLRDataTaskVtbl; + + interface IXCLRDataTask + { + CONST_VTBL struct IXCLRDataTaskVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataTask_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataTask_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataTask_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataTask_GetProcess(This,process) \ + ( (This)->lpVtbl -> GetProcess(This,process) ) + +#define IXCLRDataTask_GetCurrentAppDomain(This,appDomain) \ + ( (This)->lpVtbl -> GetCurrentAppDomain(This,appDomain) ) + +#define IXCLRDataTask_GetUniqueID(This,id) \ + ( (This)->lpVtbl -> GetUniqueID(This,id) ) + +#define IXCLRDataTask_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataTask_IsSameObject(This,task) \ + ( (This)->lpVtbl -> IsSameObject(This,task) ) + +#define IXCLRDataTask_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataTask_GetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) + +#define IXCLRDataTask_SetDesiredExecutionState(This,state) \ + ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) + +#define IXCLRDataTask_CreateStackWalk(This,flags,stackWalk) \ + ( (This)->lpVtbl -> CreateStackWalk(This,flags,stackWalk) ) + +#define IXCLRDataTask_GetOSThreadID(This,id) \ + ( (This)->lpVtbl -> GetOSThreadID(This,id) ) + +#define IXCLRDataTask_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + +#define IXCLRDataTask_SetContext(This,contextSize,context) \ + ( (This)->lpVtbl -> SetContext(This,contextSize,context) ) + +#define IXCLRDataTask_GetCurrentExceptionState(This,exception) \ + ( (This)->lpVtbl -> GetCurrentExceptionState(This,exception) ) + +#define IXCLRDataTask_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataTask_GetName(This,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) + +#define IXCLRDataTask_GetLastExceptionState(This,exception) \ + ( (This)->lpVtbl -> GetLastExceptionState(This,exception) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataTask_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0015 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0015_0001 + { + CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, + CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, + CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, + CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE = 0x8 + } CLRDataSimpleFrameType; + +typedef /* [public][public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0015_0002 + { + CLRDATA_DETFRAME_UNRECOGNIZED = 0, + CLRDATA_DETFRAME_UNKNOWN_STUB = ( CLRDATA_DETFRAME_UNRECOGNIZED + 1 ) , + CLRDATA_DETFRAME_CLASS_INIT = ( CLRDATA_DETFRAME_UNKNOWN_STUB + 1 ) , + CLRDATA_DETFRAME_EXCEPTION_FILTER = ( CLRDATA_DETFRAME_CLASS_INIT + 1 ) , + CLRDATA_DETFRAME_SECURITY = ( CLRDATA_DETFRAME_EXCEPTION_FILTER + 1 ) , + CLRDATA_DETFRAME_CONTEXT_POLICY = ( CLRDATA_DETFRAME_SECURITY + 1 ) , + CLRDATA_DETFRAME_INTERCEPTION = ( CLRDATA_DETFRAME_CONTEXT_POLICY + 1 ) , + CLRDATA_DETFRAME_PROCESS_START = ( CLRDATA_DETFRAME_INTERCEPTION + 1 ) , + CLRDATA_DETFRAME_THREAD_START = ( CLRDATA_DETFRAME_PROCESS_START + 1 ) , + CLRDATA_DETFRAME_TRANSITION_TO_MANAGED = ( CLRDATA_DETFRAME_THREAD_START + 1 ) , + CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED = ( CLRDATA_DETFRAME_TRANSITION_TO_MANAGED + 1 ) , + CLRDATA_DETFRAME_COM_INTEROP_STUB = ( CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED + 1 ) , + CLRDATA_DETFRAME_DEBUGGER_EVAL = ( CLRDATA_DETFRAME_COM_INTEROP_STUB + 1 ) , + CLRDATA_DETFRAME_CONTEXT_SWITCH = ( CLRDATA_DETFRAME_DEBUGGER_EVAL + 1 ) , + CLRDATA_DETFRAME_FUNC_EVAL = ( CLRDATA_DETFRAME_CONTEXT_SWITCH + 1 ) , + CLRDATA_DETFRAME_FINALLY = ( CLRDATA_DETFRAME_FUNC_EVAL + 1 ) + } CLRDataDetailedFrameType; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0015_0003 + { + CLRDATA_STACK_WALK_REQUEST_SET_FIRST_FRAME = 0xe1000000 + } CLRDataStackWalkRequest; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0015_0004 + { + CLRDATA_STACK_SET_UNWIND_CONTEXT = 0, + CLRDATA_STACK_SET_CURRENT_CONTEXT = 0x1 + } CLRDataStackSetContextFlag; + + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0015_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0015_v0_0_s_ifspec; + +#ifndef __IXCLRDataStackWalk_INTERFACE_DEFINED__ +#define __IXCLRDataStackWalk_INTERFACE_DEFINED__ + +/* interface IXCLRDataStackWalk */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataStackWalk; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E59D8D22-ADA7-49a2-89B5-A415AFCFC95F") + IXCLRDataStackWalk : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContext( + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetStackSizeSkipped( + /* [out] */ ULONG64 *stackSizeSkipped) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFrameType( + /* [out] */ CLRDataSimpleFrameType *simpleType, + /* [out] */ CLRDataDetailedFrameType *detailedType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFrame( + /* [out] */ IXCLRDataFrame **frame) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContext2( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataStackWalkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataStackWalk * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataStackWalk * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataStackWalk * This); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + IXCLRDataStackWalk * This, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetContext )( + IXCLRDataStackWalk * This, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]); + + HRESULT ( STDMETHODCALLTYPE *Next )( + IXCLRDataStackWalk * This); + + HRESULT ( STDMETHODCALLTYPE *GetStackSizeSkipped )( + IXCLRDataStackWalk * This, + /* [out] */ ULONG64 *stackSizeSkipped); + + HRESULT ( STDMETHODCALLTYPE *GetFrameType )( + IXCLRDataStackWalk * This, + /* [out] */ CLRDataSimpleFrameType *simpleType, + /* [out] */ CLRDataDetailedFrameType *detailedType); + + HRESULT ( STDMETHODCALLTYPE *GetFrame )( + IXCLRDataStackWalk * This, + /* [out] */ IXCLRDataFrame **frame); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataStackWalk * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *SetContext2 )( + IXCLRDataStackWalk * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE context[ ]); + + END_INTERFACE + } IXCLRDataStackWalkVtbl; + + interface IXCLRDataStackWalk + { + CONST_VTBL struct IXCLRDataStackWalkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataStackWalk_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataStackWalk_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataStackWalk_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + +#define IXCLRDataStackWalk_SetContext(This,contextSize,context) \ + ( (This)->lpVtbl -> SetContext(This,contextSize,context) ) + +#define IXCLRDataStackWalk_Next(This) \ + ( (This)->lpVtbl -> Next(This) ) + +#define IXCLRDataStackWalk_GetStackSizeSkipped(This,stackSizeSkipped) \ + ( (This)->lpVtbl -> GetStackSizeSkipped(This,stackSizeSkipped) ) + +#define IXCLRDataStackWalk_GetFrameType(This,simpleType,detailedType) \ + ( (This)->lpVtbl -> GetFrameType(This,simpleType,detailedType) ) + +#define IXCLRDataStackWalk_GetFrame(This,frame) \ + ( (This)->lpVtbl -> GetFrame(This,frame) ) + +#define IXCLRDataStackWalk_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataStackWalk_SetContext2(This,flags,contextSize,context) \ + ( (This)->lpVtbl -> SetContext2(This,flags,contextSize,context) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataStackWalk_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0016 */ +/* [local] */ + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0016_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0016_v0_0_s_ifspec; + +#ifndef __IXCLRDataFrame_INTERFACE_DEFINED__ +#define __IXCLRDataFrame_INTERFACE_DEFINED__ + +/* interface IXCLRDataFrame */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataFrame; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("271498C2-4085-4766-BC3A-7F8ED188A173") + IXCLRDataFrame : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFrameType( + /* [out] */ CLRDataSimpleFrameType *simpleType, + /* [out] */ CLRDataDetailedFrameType *detailedType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContext( + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAppDomain( + /* [out] */ IXCLRDataAppDomain **appDomain) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumArguments( + /* [out] */ ULONG32 *numArgs) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArgumentByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **arg, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumLocalVariables( + /* [out] */ ULONG32 *numLocals) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocalVariableByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **localVariable, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCodeName( + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetMethodInstance( + /* [out] */ IXCLRDataMethodInstance **method) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( + /* [out] */ ULONG32 *numTypeArgs) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataFrameVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataFrame * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataFrame * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataFrame * This); + + HRESULT ( STDMETHODCALLTYPE *GetFrameType )( + IXCLRDataFrame * This, + /* [out] */ CLRDataSimpleFrameType *simpleType, + /* [out] */ CLRDataDetailedFrameType *detailedType); + + HRESULT ( STDMETHODCALLTYPE *GetContext )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 contextFlags, + /* [in] */ ULONG32 contextBufSize, + /* [out] */ ULONG32 *contextSize, + /* [size_is][out] */ BYTE contextBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( + IXCLRDataFrame * This, + /* [out] */ IXCLRDataAppDomain **appDomain); + + HRESULT ( STDMETHODCALLTYPE *GetNumArguments )( + IXCLRDataFrame * This, + /* [out] */ ULONG32 *numArgs); + + HRESULT ( STDMETHODCALLTYPE *GetArgumentByIndex )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **arg, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNumLocalVariables )( + IXCLRDataFrame * This, + /* [out] */ ULONG32 *numLocals); + + HRESULT ( STDMETHODCALLTYPE *GetLocalVariableByIndex )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **localVariable, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR name[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetCodeName )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 flags, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetMethodInstance )( + IXCLRDataFrame * This, + /* [out] */ IXCLRDataMethodInstance **method); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( + IXCLRDataFrame * This, + /* [out] */ ULONG32 *numTypeArgs); + + HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( + IXCLRDataFrame * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataTypeInstance **typeArg); + + END_INTERFACE + } IXCLRDataFrameVtbl; + + interface IXCLRDataFrame + { + CONST_VTBL struct IXCLRDataFrameVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataFrame_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataFrame_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataFrame_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataFrame_GetFrameType(This,simpleType,detailedType) \ + ( (This)->lpVtbl -> GetFrameType(This,simpleType,detailedType) ) + +#define IXCLRDataFrame_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ + ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) + +#define IXCLRDataFrame_GetAppDomain(This,appDomain) \ + ( (This)->lpVtbl -> GetAppDomain(This,appDomain) ) + +#define IXCLRDataFrame_GetNumArguments(This,numArgs) \ + ( (This)->lpVtbl -> GetNumArguments(This,numArgs) ) + +#define IXCLRDataFrame_GetArgumentByIndex(This,index,arg,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetArgumentByIndex(This,index,arg,bufLen,nameLen,name) ) + +#define IXCLRDataFrame_GetNumLocalVariables(This,numLocals) \ + ( (This)->lpVtbl -> GetNumLocalVariables(This,numLocals) ) + +#define IXCLRDataFrame_GetLocalVariableByIndex(This,index,localVariable,bufLen,nameLen,name) \ + ( (This)->lpVtbl -> GetLocalVariableByIndex(This,index,localVariable,bufLen,nameLen,name) ) + +#define IXCLRDataFrame_GetCodeName(This,flags,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetCodeName(This,flags,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataFrame_GetMethodInstance(This,method) \ + ( (This)->lpVtbl -> GetMethodInstance(This,method) ) + +#define IXCLRDataFrame_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataFrame_GetNumTypeArguments(This,numTypeArgs) \ + ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) + +#define IXCLRDataFrame_GetTypeArgumentByIndex(This,index,typeArg) \ + ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataFrame_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0017 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0017_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0017_v0_0_s_ifspec; + +#ifndef __IXCLRDataFrame2_INTERFACE_DEFINED__ +#define __IXCLRDataFrame2_INTERFACE_DEFINED__ + +/* interface IXCLRDataFrame2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataFrame2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("1C4D9A4B-702D-4CF6-B290-1DB6F43050D0") + IXCLRDataFrame2 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetExactGenericArgsToken( + /* [out] */ IXCLRDataValue **genericToken) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataFrame2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataFrame2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataFrame2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataFrame2 * This); + + HRESULT ( STDMETHODCALLTYPE *GetExactGenericArgsToken )( + IXCLRDataFrame2 * This, + /* [out] */ IXCLRDataValue **genericToken); + + END_INTERFACE + } IXCLRDataFrame2Vtbl; + + interface IXCLRDataFrame2 + { + CONST_VTBL struct IXCLRDataFrame2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataFrame2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataFrame2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataFrame2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataFrame2_GetExactGenericArgsToken(This,genericToken) \ + ( (This)->lpVtbl -> GetExactGenericArgsToken(This,genericToken) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataFrame2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0018 */ +/* [local] */ + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0018_0001 + { + CLRDATA_EXCEPTION_DEFAULT = 0, + CLRDATA_EXCEPTION_NESTED = 0x1, + CLRDATA_EXCEPTION_PARTIAL = 0x2 + } CLRDataExceptionStateFlag; + +typedef /* [public][public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0018_0002 + { + CLRDATA_EXBASE_EXCEPTION = 0, + CLRDATA_EXBASE_OUT_OF_MEMORY = ( CLRDATA_EXBASE_EXCEPTION + 1 ) , + CLRDATA_EXBASE_INVALID_ARGUMENT = ( CLRDATA_EXBASE_OUT_OF_MEMORY + 1 ) + } CLRDataBaseExceptionType; + +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0018_0003 + { + CLRDATA_EXSAME_SECOND_CHANCE = 0, + CLRDATA_EXSAME_FIRST_CHANCE = 0x1 + } CLRDataExceptionSameFlag; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0018_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0018_v0_0_s_ifspec; + +#ifndef __IXCLRDataExceptionState_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionState_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionState */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionState; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("75DA9E4C-BD33-43C8-8F5C-96E8A5241F57") + IXCLRDataExceptionState : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetPrevious( + /* [out] */ IXCLRDataExceptionState **exState) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetManagedObject( + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBaseType( + /* [out] */ CLRDataBaseExceptionType *type) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCode( + /* [out] */ ULONG32 *code) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetString( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *strLen, + /* [size_is][out] */ WCHAR str[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameState( + /* [in] */ EXCEPTION_RECORD64 *exRecord, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE cxRecord[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE IsSameState2( + /* [in] */ ULONG32 flags, + /* [in] */ EXCEPTION_RECORD64 *exRecord, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE cxRecord[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetTask( + /* [out] */ IXCLRDataTask **task) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionStateVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionState * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionState * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionState * This); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataExceptionState * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *GetPrevious )( + IXCLRDataExceptionState * This, + /* [out] */ IXCLRDataExceptionState **exState); + + HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( + IXCLRDataExceptionState * This, + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *GetBaseType )( + IXCLRDataExceptionState * This, + /* [out] */ CLRDataBaseExceptionType *type); + + HRESULT ( STDMETHODCALLTYPE *GetCode )( + IXCLRDataExceptionState * This, + /* [out] */ ULONG32 *code); + + HRESULT ( STDMETHODCALLTYPE *GetString )( + IXCLRDataExceptionState * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *strLen, + /* [size_is][out] */ WCHAR str[ ]); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataExceptionState * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *IsSameState )( + IXCLRDataExceptionState * This, + /* [in] */ EXCEPTION_RECORD64 *exRecord, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE cxRecord[ ]); + + HRESULT ( STDMETHODCALLTYPE *IsSameState2 )( + IXCLRDataExceptionState * This, + /* [in] */ ULONG32 flags, + /* [in] */ EXCEPTION_RECORD64 *exRecord, + /* [in] */ ULONG32 contextSize, + /* [size_is][in] */ BYTE cxRecord[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetTask )( + IXCLRDataExceptionState * This, + /* [out] */ IXCLRDataTask **task); + + END_INTERFACE + } IXCLRDataExceptionStateVtbl; + + interface IXCLRDataExceptionState + { + CONST_VTBL struct IXCLRDataExceptionStateVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionState_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionState_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionState_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionState_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataExceptionState_GetPrevious(This,exState) \ + ( (This)->lpVtbl -> GetPrevious(This,exState) ) + +#define IXCLRDataExceptionState_GetManagedObject(This,value) \ + ( (This)->lpVtbl -> GetManagedObject(This,value) ) + +#define IXCLRDataExceptionState_GetBaseType(This,type) \ + ( (This)->lpVtbl -> GetBaseType(This,type) ) + +#define IXCLRDataExceptionState_GetCode(This,code) \ + ( (This)->lpVtbl -> GetCode(This,code) ) + +#define IXCLRDataExceptionState_GetString(This,bufLen,strLen,str) \ + ( (This)->lpVtbl -> GetString(This,bufLen,strLen,str) ) + +#define IXCLRDataExceptionState_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataExceptionState_IsSameState(This,exRecord,contextSize,cxRecord) \ + ( (This)->lpVtbl -> IsSameState(This,exRecord,contextSize,cxRecord) ) + +#define IXCLRDataExceptionState_IsSameState2(This,flags,exRecord,contextSize,cxRecord) \ + ( (This)->lpVtbl -> IsSameState2(This,flags,exRecord,contextSize,cxRecord) ) + +#define IXCLRDataExceptionState_GetTask(This,task) \ + ( (This)->lpVtbl -> GetTask(This,task) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataExceptionState_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0019 */ +/* [local] */ + +#pragma warning(pop) +typedef /* [public] */ +enum __MIDL___MIDL_itf_xclrdata_0000_0019_0001 + { + CLRDATA_VLOC_MEMORY = 0, + CLRDATA_VLOC_REGISTER = 0x1 + } ClrDataValueLocationFlag; + +#pragma warning(push) +#pragma warning(disable:28718) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0019_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0019_v0_0_s_ifspec; + +#ifndef __IXCLRDataValue_INTERFACE_DEFINED__ +#define __IXCLRDataValue_INTERFACE_DEFINED__ + +/* interface IXCLRDataValue */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataValue; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("96EC93C7-1000-4e93-8991-98D8766E6666") + IXCLRDataValue : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetFlags( + /* [out] */ ULONG32 *flags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAddress( + /* [out] */ CLRDATA_ADDRESS *address) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSize( + /* [out] */ ULONG64 *size) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetBytes( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *dataSize, + /* [size_is][out] */ BYTE buffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetBytes( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *dataSize, + /* [size_is][in] */ BYTE buffer[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetType( + /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumFields( + /* [out] */ ULONG32 *numFields) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldByIndex( + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE Request( + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumFields2( + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ ULONG32 *numFields) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumFields( + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumField( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumFields( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName( + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ CLRDATA_ENUM *handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumFieldByName( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName( + /* [in] */ CLRDATA_ENUM handle) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldByToken( + /* [in] */ mdFieldDef token, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssociatedValue( + /* [out] */ IXCLRDataValue **assocValue) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetAssociatedType( + /* [out] */ IXCLRDataTypeInstance **assocType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetString( + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *strLen, + /* [size_is][out] */ WCHAR str[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArrayProperties( + /* [out] */ ULONG32 *rank, + /* [out] */ ULONG32 *totalElements, + /* [in] */ ULONG32 numDim, + /* [size_is][out] */ ULONG32 dims[ ], + /* [in] */ ULONG32 numBases, + /* [size_is][out] */ LONG32 bases[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetArrayElement( + /* [in] */ ULONG32 numInd, + /* [size_is][in] */ LONG32 indices[ ], + /* [out] */ IXCLRDataValue **value) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumField2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2( + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2( + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetNumLocations( + /* [out] */ ULONG32 *numLocs) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetLocationByIndex( + /* [in] */ ULONG32 loc, + /* [out] */ ULONG32 *flags, + /* [out] */ CLRDATA_ADDRESS *arg) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataValueVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataValue * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataValue * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataValue * This); + + HRESULT ( STDMETHODCALLTYPE *GetFlags )( + IXCLRDataValue * This, + /* [out] */ ULONG32 *flags); + + HRESULT ( STDMETHODCALLTYPE *GetAddress )( + IXCLRDataValue * This, + /* [out] */ CLRDATA_ADDRESS *address); + + HRESULT ( STDMETHODCALLTYPE *GetSize )( + IXCLRDataValue * This, + /* [out] */ ULONG64 *size); + + HRESULT ( STDMETHODCALLTYPE *GetBytes )( + IXCLRDataValue * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *dataSize, + /* [size_is][out] */ BYTE buffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *SetBytes )( + IXCLRDataValue * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *dataSize, + /* [size_is][in] */ BYTE buffer[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetType )( + IXCLRDataValue * This, + /* [out] */ IXCLRDataTypeInstance **typeInstance); + + HRESULT ( STDMETHODCALLTYPE *GetNumFields )( + IXCLRDataValue * This, + /* [out] */ ULONG32 *numFields); + + HRESULT ( STDMETHODCALLTYPE *GetFieldByIndex )( + IXCLRDataValue * This, + /* [in] */ ULONG32 index, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *Request )( + IXCLRDataValue * This, + /* [in] */ ULONG32 reqCode, + /* [in] */ ULONG32 inBufferSize, + /* [size_is][in] */ BYTE *inBuffer, + /* [in] */ ULONG32 outBufferSize, + /* [size_is][out] */ BYTE *outBuffer); + + HRESULT ( STDMETHODCALLTYPE *GetNumFields2 )( + IXCLRDataValue * This, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ ULONG32 *numFields); + + HRESULT ( STDMETHODCALLTYPE *StartEnumFields )( + IXCLRDataValue * This, + /* [in] */ ULONG32 flags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumField )( + IXCLRDataValue * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EndEnumFields )( + IXCLRDataValue * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *StartEnumFieldsByName )( + IXCLRDataValue * This, + /* [in] */ LPCWSTR name, + /* [in] */ ULONG32 nameFlags, + /* [in] */ ULONG32 fieldFlags, + /* [in] */ IXCLRDataTypeInstance *fromType, + /* [out] */ CLRDATA_ENUM *handle); + + HRESULT ( STDMETHODCALLTYPE *EnumFieldByName )( + IXCLRDataValue * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EndEnumFieldsByName )( + IXCLRDataValue * This, + /* [in] */ CLRDATA_ENUM handle); + + HRESULT ( STDMETHODCALLTYPE *GetFieldByToken )( + IXCLRDataValue * This, + /* [in] */ mdFieldDef token, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetAssociatedValue )( + IXCLRDataValue * This, + /* [out] */ IXCLRDataValue **assocValue); + + HRESULT ( STDMETHODCALLTYPE *GetAssociatedType )( + IXCLRDataValue * This, + /* [out] */ IXCLRDataTypeInstance **assocType); + + HRESULT ( STDMETHODCALLTYPE *GetString )( + IXCLRDataValue * This, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *strLen, + /* [size_is][out] */ WCHAR str[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetArrayProperties )( + IXCLRDataValue * This, + /* [out] */ ULONG32 *rank, + /* [out] */ ULONG32 *totalElements, + /* [in] */ ULONG32 numDim, + /* [size_is][out] */ ULONG32 dims[ ], + /* [in] */ ULONG32 numBases, + /* [size_is][out] */ LONG32 bases[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetArrayElement )( + IXCLRDataValue * This, + /* [in] */ ULONG32 numInd, + /* [size_is][in] */ LONG32 indices[ ], + /* [out] */ IXCLRDataValue **value); + + HRESULT ( STDMETHODCALLTYPE *EnumField2 )( + IXCLRDataValue * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 nameBufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ], + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *EnumFieldByName2 )( + IXCLRDataValue * This, + /* [out][in] */ CLRDATA_ENUM *handle, + /* [out] */ IXCLRDataValue **field, + /* [out] */ IXCLRDataModule **tokenScope, + /* [out] */ mdFieldDef *token); + + HRESULT ( STDMETHODCALLTYPE *GetFieldByToken2 )( + IXCLRDataValue * This, + /* [in] */ IXCLRDataModule *tokenScope, + /* [in] */ mdFieldDef token, + /* [out] */ IXCLRDataValue **field, + /* [in] */ ULONG32 bufLen, + /* [out] */ ULONG32 *nameLen, + /* [size_is][out] */ WCHAR nameBuf[ ]); + + HRESULT ( STDMETHODCALLTYPE *GetNumLocations )( + IXCLRDataValue * This, + /* [out] */ ULONG32 *numLocs); + + HRESULT ( STDMETHODCALLTYPE *GetLocationByIndex )( + IXCLRDataValue * This, + /* [in] */ ULONG32 loc, + /* [out] */ ULONG32 *flags, + /* [out] */ CLRDATA_ADDRESS *arg); + + END_INTERFACE + } IXCLRDataValueVtbl; + + interface IXCLRDataValue + { + CONST_VTBL struct IXCLRDataValueVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataValue_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataValue_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataValue_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataValue_GetFlags(This,flags) \ + ( (This)->lpVtbl -> GetFlags(This,flags) ) + +#define IXCLRDataValue_GetAddress(This,address) \ + ( (This)->lpVtbl -> GetAddress(This,address) ) + +#define IXCLRDataValue_GetSize(This,size) \ + ( (This)->lpVtbl -> GetSize(This,size) ) + +#define IXCLRDataValue_GetBytes(This,bufLen,dataSize,buffer) \ + ( (This)->lpVtbl -> GetBytes(This,bufLen,dataSize,buffer) ) + +#define IXCLRDataValue_SetBytes(This,bufLen,dataSize,buffer) \ + ( (This)->lpVtbl -> SetBytes(This,bufLen,dataSize,buffer) ) + +#define IXCLRDataValue_GetType(This,typeInstance) \ + ( (This)->lpVtbl -> GetType(This,typeInstance) ) + +#define IXCLRDataValue_GetNumFields(This,numFields) \ + ( (This)->lpVtbl -> GetNumFields(This,numFields) ) + +#define IXCLRDataValue_GetFieldByIndex(This,index,field,bufLen,nameLen,nameBuf,token) \ + ( (This)->lpVtbl -> GetFieldByIndex(This,index,field,bufLen,nameLen,nameBuf,token) ) + +#define IXCLRDataValue_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ + ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) + +#define IXCLRDataValue_GetNumFields2(This,flags,fromType,numFields) \ + ( (This)->lpVtbl -> GetNumFields2(This,flags,fromType,numFields) ) + +#define IXCLRDataValue_StartEnumFields(This,flags,fromType,handle) \ + ( (This)->lpVtbl -> StartEnumFields(This,flags,fromType,handle) ) + +#define IXCLRDataValue_EnumField(This,handle,field,nameBufLen,nameLen,nameBuf,token) \ + ( (This)->lpVtbl -> EnumField(This,handle,field,nameBufLen,nameLen,nameBuf,token) ) + +#define IXCLRDataValue_EndEnumFields(This,handle) \ + ( (This)->lpVtbl -> EndEnumFields(This,handle) ) + +#define IXCLRDataValue_StartEnumFieldsByName(This,name,nameFlags,fieldFlags,fromType,handle) \ + ( (This)->lpVtbl -> StartEnumFieldsByName(This,name,nameFlags,fieldFlags,fromType,handle) ) + +#define IXCLRDataValue_EnumFieldByName(This,handle,field,token) \ + ( (This)->lpVtbl -> EnumFieldByName(This,handle,field,token) ) + +#define IXCLRDataValue_EndEnumFieldsByName(This,handle) \ + ( (This)->lpVtbl -> EndEnumFieldsByName(This,handle) ) + +#define IXCLRDataValue_GetFieldByToken(This,token,field,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetFieldByToken(This,token,field,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataValue_GetAssociatedValue(This,assocValue) \ + ( (This)->lpVtbl -> GetAssociatedValue(This,assocValue) ) + +#define IXCLRDataValue_GetAssociatedType(This,assocType) \ + ( (This)->lpVtbl -> GetAssociatedType(This,assocType) ) + +#define IXCLRDataValue_GetString(This,bufLen,strLen,str) \ + ( (This)->lpVtbl -> GetString(This,bufLen,strLen,str) ) + +#define IXCLRDataValue_GetArrayProperties(This,rank,totalElements,numDim,dims,numBases,bases) \ + ( (This)->lpVtbl -> GetArrayProperties(This,rank,totalElements,numDim,dims,numBases,bases) ) + +#define IXCLRDataValue_GetArrayElement(This,numInd,indices,value) \ + ( (This)->lpVtbl -> GetArrayElement(This,numInd,indices,value) ) + +#define IXCLRDataValue_EnumField2(This,handle,field,nameBufLen,nameLen,nameBuf,tokenScope,token) \ + ( (This)->lpVtbl -> EnumField2(This,handle,field,nameBufLen,nameLen,nameBuf,tokenScope,token) ) + +#define IXCLRDataValue_EnumFieldByName2(This,handle,field,tokenScope,token) \ + ( (This)->lpVtbl -> EnumFieldByName2(This,handle,field,tokenScope,token) ) + +#define IXCLRDataValue_GetFieldByToken2(This,tokenScope,token,field,bufLen,nameLen,nameBuf) \ + ( (This)->lpVtbl -> GetFieldByToken2(This,tokenScope,token,field,bufLen,nameLen,nameBuf) ) + +#define IXCLRDataValue_GetNumLocations(This,numLocs) \ + ( (This)->lpVtbl -> GetNumLocations(This,numLocs) ) + +#define IXCLRDataValue_GetLocationByIndex(This,loc,flags,arg) \ + ( (This)->lpVtbl -> GetLocationByIndex(This,loc,flags,arg) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataValue_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_xclrdata_0000_0020 */ +/* [local] */ + +#pragma warning(pop) + + +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0020_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0020_v0_0_s_ifspec; + +#ifndef __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionNotification */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionNotification; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2D95A079-42A1-4837-818F-0B97D7048E0E") + IXCLRDataExceptionNotification : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE OnCodeGenerated( + /* [in] */ IXCLRDataMethodInstance *method) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnCodeDiscarded( + /* [in] */ IXCLRDataMethodInstance *method) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnProcessExecution( + /* [in] */ ULONG32 state) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnTaskExecution( + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded( + /* [in] */ IXCLRDataModule *mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded( + /* [in] */ IXCLRDataModule *mod) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnTypeLoaded( + /* [in] */ IXCLRDataTypeInstance *typeInst) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnTypeUnloaded( + /* [in] */ IXCLRDataTypeInstance *typeInst) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionNotificationVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionNotification * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionNotification * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionNotification * This); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( + IXCLRDataExceptionNotification * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( + IXCLRDataExceptionNotification * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + END_INTERFACE + } IXCLRDataExceptionNotificationVtbl; + + interface IXCLRDataExceptionNotification + { + CONST_VTBL struct IXCLRDataExceptionNotificationVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionNotification_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionNotification_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionNotification_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionNotification_OnCodeGenerated(This,method) \ + ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) + +#define IXCLRDataExceptionNotification_OnCodeDiscarded(This,method) \ + ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) + +#define IXCLRDataExceptionNotification_OnProcessExecution(This,state) \ + ( (This)->lpVtbl -> OnProcessExecution(This,state) ) + +#define IXCLRDataExceptionNotification_OnTaskExecution(This,task,state) \ + ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) + +#define IXCLRDataExceptionNotification_OnModuleLoaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) + +#define IXCLRDataExceptionNotification_OnModuleUnloaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) + +#define IXCLRDataExceptionNotification_OnTypeLoaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) + +#define IXCLRDataExceptionNotification_OnTypeUnloaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionNotification2 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionNotification2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("31201a94-4337-49b7-aef7-0c755054091f") + IXCLRDataExceptionNotification2 : public IXCLRDataExceptionNotification + { + public: + virtual HRESULT STDMETHODCALLTYPE OnAppDomainLoaded( + /* [in] */ IXCLRDataAppDomain *domain) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainUnloaded( + /* [in] */ IXCLRDataAppDomain *domain) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnException( + /* [in] */ IXCLRDataExceptionState *exception) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionNotification2Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionNotification2 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionNotification2 * This); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnException )( + IXCLRDataExceptionNotification2 * This, + /* [in] */ IXCLRDataExceptionState *exception); + + END_INTERFACE + } IXCLRDataExceptionNotification2Vtbl; + + interface IXCLRDataExceptionNotification2 + { + CONST_VTBL struct IXCLRDataExceptionNotification2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionNotification2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionNotification2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionNotification2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionNotification2_OnCodeGenerated(This,method) \ + ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) + +#define IXCLRDataExceptionNotification2_OnCodeDiscarded(This,method) \ + ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) + +#define IXCLRDataExceptionNotification2_OnProcessExecution(This,state) \ + ( (This)->lpVtbl -> OnProcessExecution(This,state) ) + +#define IXCLRDataExceptionNotification2_OnTaskExecution(This,task,state) \ + ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) + +#define IXCLRDataExceptionNotification2_OnModuleLoaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) + +#define IXCLRDataExceptionNotification2_OnModuleUnloaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) + +#define IXCLRDataExceptionNotification2_OnTypeLoaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) + +#define IXCLRDataExceptionNotification2_OnTypeUnloaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) + + +#define IXCLRDataExceptionNotification2_OnAppDomainLoaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) + +#define IXCLRDataExceptionNotification2_OnAppDomainUnloaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) + +#define IXCLRDataExceptionNotification2_OnException(This,exception) \ + ( (This)->lpVtbl -> OnException(This,exception) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionNotification3 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionNotification3; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("31201a94-4337-49b7-aef7-0c7550540920") + IXCLRDataExceptionNotification3 : public IXCLRDataExceptionNotification2 + { + public: + virtual HRESULT STDMETHODCALLTYPE OnGcEvent( + /* [in] */ GcEvtArgs gcEvtArgs) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionNotification3Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionNotification3 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionNotification3 * This); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnException )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ IXCLRDataExceptionState *exception); + + HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( + IXCLRDataExceptionNotification3 * This, + /* [in] */ GcEvtArgs gcEvtArgs); + + END_INTERFACE + } IXCLRDataExceptionNotification3Vtbl; + + interface IXCLRDataExceptionNotification3 + { + CONST_VTBL struct IXCLRDataExceptionNotification3Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionNotification3_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionNotification3_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionNotification3_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionNotification3_OnCodeGenerated(This,method) \ + ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) + +#define IXCLRDataExceptionNotification3_OnCodeDiscarded(This,method) \ + ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) + +#define IXCLRDataExceptionNotification3_OnProcessExecution(This,state) \ + ( (This)->lpVtbl -> OnProcessExecution(This,state) ) + +#define IXCLRDataExceptionNotification3_OnTaskExecution(This,task,state) \ + ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) + +#define IXCLRDataExceptionNotification3_OnModuleLoaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) + +#define IXCLRDataExceptionNotification3_OnModuleUnloaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) + +#define IXCLRDataExceptionNotification3_OnTypeLoaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) + +#define IXCLRDataExceptionNotification3_OnTypeUnloaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) + + +#define IXCLRDataExceptionNotification3_OnAppDomainLoaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) + +#define IXCLRDataExceptionNotification3_OnAppDomainUnloaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) + +#define IXCLRDataExceptionNotification3_OnException(This,exception) \ + ( (This)->lpVtbl -> OnException(This,exception) ) + + +#define IXCLRDataExceptionNotification3_OnGcEvent(This,gcEvtArgs) \ + ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ */ + + +#ifndef __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionNotification4 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionNotification4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("C25E926E-5F09-4AA2-BBAD-B7FC7F10CFD7") + IXCLRDataExceptionNotification4 : public IXCLRDataExceptionNotification3 + { + public: + virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter( + /* [in] */ IXCLRDataMethodInstance *catchingMethod, + DWORD catcherNativeOffset) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionNotification4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionNotification4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionNotification4 * This); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnException )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataExceptionState *exception); + + HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ GcEvtArgs gcEvtArgs); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + IXCLRDataExceptionNotification4 * This, + /* [in] */ IXCLRDataMethodInstance *catchingMethod, + DWORD catcherNativeOffset); + + END_INTERFACE + } IXCLRDataExceptionNotification4Vtbl; + + interface IXCLRDataExceptionNotification4 + { + CONST_VTBL struct IXCLRDataExceptionNotification4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionNotification4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionNotification4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionNotification4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionNotification4_OnCodeGenerated(This,method) \ + ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) + +#define IXCLRDataExceptionNotification4_OnCodeDiscarded(This,method) \ + ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) + +#define IXCLRDataExceptionNotification4_OnProcessExecution(This,state) \ + ( (This)->lpVtbl -> OnProcessExecution(This,state) ) + +#define IXCLRDataExceptionNotification4_OnTaskExecution(This,task,state) \ + ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) + +#define IXCLRDataExceptionNotification4_OnModuleLoaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) + +#define IXCLRDataExceptionNotification4_OnModuleUnloaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) + +#define IXCLRDataExceptionNotification4_OnTypeLoaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) + +#define IXCLRDataExceptionNotification4_OnTypeUnloaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) + + +#define IXCLRDataExceptionNotification4_OnAppDomainLoaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) + +#define IXCLRDataExceptionNotification4_OnAppDomainUnloaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) + +#define IXCLRDataExceptionNotification4_OnException(This,exception) \ + ( (This)->lpVtbl -> OnException(This,exception) ) + + +#define IXCLRDataExceptionNotification4_OnGcEvent(This,gcEvtArgs) \ + ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) + + +#define IXCLRDataExceptionNotification4_ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#ifndef __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ +#define __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ + +/* interface IXCLRDataExceptionNotification5 */ +/* [uuid][local][object] */ + + +EXTERN_C const IID IID_IXCLRDataExceptionNotification5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e77a39ea-3548-44d9-b171-8569ed1a9423") + IXCLRDataExceptionNotification5 : public IXCLRDataExceptionNotification4 + { + public: + virtual HRESULT STDMETHODCALLTYPE OnCodeGenerated2( + /* [in] */ IXCLRDataMethodInstance *method, + /* [in] */ CLRDATA_ADDRESS nativeCodeLocation) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IXCLRDataExceptionNotification5Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IXCLRDataExceptionNotification5 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IXCLRDataExceptionNotification5 * This); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataMethodInstance *method); + + HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataTask *task, + /* [in] */ ULONG32 state); + + HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataModule *mod); + + HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataTypeInstance *typeInst); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataAppDomain *domain); + + HRESULT ( STDMETHODCALLTYPE *OnException )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataExceptionState *exception); + + HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ GcEvtArgs gcEvtArgs); + + HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataMethodInstance *catchingMethod, + DWORD catcherNativeOffset); + + HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated2 )( + IXCLRDataExceptionNotification5 * This, + /* [in] */ IXCLRDataMethodInstance *method, + /* [in] */ CLRDATA_ADDRESS nativeCodeLocation); + + END_INTERFACE + } IXCLRDataExceptionNotification5Vtbl; + + interface IXCLRDataExceptionNotification5 + { + CONST_VTBL struct IXCLRDataExceptionNotification5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IXCLRDataExceptionNotification5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IXCLRDataExceptionNotification5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IXCLRDataExceptionNotification5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IXCLRDataExceptionNotification5_OnCodeGenerated(This,method) \ + ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) + +#define IXCLRDataExceptionNotification5_OnCodeDiscarded(This,method) \ + ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) + +#define IXCLRDataExceptionNotification5_OnProcessExecution(This,state) \ + ( (This)->lpVtbl -> OnProcessExecution(This,state) ) + +#define IXCLRDataExceptionNotification5_OnTaskExecution(This,task,state) \ + ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) + +#define IXCLRDataExceptionNotification5_OnModuleLoaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) + +#define IXCLRDataExceptionNotification5_OnModuleUnloaded(This,mod) \ + ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) + +#define IXCLRDataExceptionNotification5_OnTypeLoaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) + +#define IXCLRDataExceptionNotification5_OnTypeUnloaded(This,typeInst) \ + ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) + + +#define IXCLRDataExceptionNotification5_OnAppDomainLoaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) + +#define IXCLRDataExceptionNotification5_OnAppDomainUnloaded(This,domain) \ + ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) + +#define IXCLRDataExceptionNotification5_OnException(This,exception) \ + ( (This)->lpVtbl -> OnException(This,exception) ) + + +#define IXCLRDataExceptionNotification5_OnGcEvent(This,gcEvtArgs) \ + ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) + + +#define IXCLRDataExceptionNotification5_ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) \ + ( (This)->lpVtbl -> ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) ) + + +#define IXCLRDataExceptionNotification5_OnCodeGenerated2(This,method,nativeCodeLocation) \ + ( (This)->lpVtbl -> OnCodeGenerated2(This,method,nativeCodeLocation) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ */ + + + + +#endif /* __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/lib/coreclr/src/pal/prebuilt/inc/xcordebug.h b/lib/coreclr/src/pal/prebuilt/inc/xcordebug.h new file mode 100644 index 0000000000..4160fe5e3c --- /dev/null +++ b/lib/coreclr/src/pal/prebuilt/inc/xcordebug.h @@ -0,0 +1,268 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0622 */ +/* at Mon Jan 18 19:14:07 2038 + */ +/* Compiler settings for F:/Dev/coreclr/src/inc/xcordebug.idl: + Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +/* @@MIDL_FILE_HEADING( ) */ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __xcordebug_h__ +#define __xcordebug_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __ICorDebugProcess4_FWD_DEFINED__ +#define __ICorDebugProcess4_FWD_DEFINED__ +typedef interface ICorDebugProcess4 ICorDebugProcess4; + +#endif /* __ICorDebugProcess4_FWD_DEFINED__ */ + + +#ifndef __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ +#define __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ +typedef interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly; + +#endif /* __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "cordebug.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +#ifndef __ICorDebugProcess4_INTERFACE_DEFINED__ +#define __ICorDebugProcess4_INTERFACE_DEFINED__ + +/* interface ICorDebugProcess4 */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugProcess4; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E930C679-78AF-4953-8AB7-B0AABF0F9F80") + ICorDebugProcess4 : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Filter( + /* [size_is][length_is][in] */ const BYTE pRecord[ ], + /* [in] */ DWORD countBytes, + /* [in] */ CorDebugRecordFormat format, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwThreadId, + /* [in] */ ICorDebugManagedCallback *pCallback, + /* [out][in] */ CORDB_CONTINUE_STATUS *pContinueStatus) = 0; + + virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( + /* [in] */ CorDebugStateChange eChange) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugProcess4Vtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugProcess4 * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugProcess4 * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugProcess4 * This); + + HRESULT ( STDMETHODCALLTYPE *Filter )( + ICorDebugProcess4 * This, + /* [size_is][length_is][in] */ const BYTE pRecord[ ], + /* [in] */ DWORD countBytes, + /* [in] */ CorDebugRecordFormat format, + /* [in] */ DWORD dwFlags, + /* [in] */ DWORD dwThreadId, + /* [in] */ ICorDebugManagedCallback *pCallback, + /* [out][in] */ CORDB_CONTINUE_STATUS *pContinueStatus); + + HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( + ICorDebugProcess4 * This, + /* [in] */ CorDebugStateChange eChange); + + END_INTERFACE + } ICorDebugProcess4Vtbl; + + interface ICorDebugProcess4 + { + CONST_VTBL struct ICorDebugProcess4Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugProcess4_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugProcess4_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugProcess4_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugProcess4_Filter(This,pRecord,countBytes,format,dwFlags,dwThreadId,pCallback,pContinueStatus) \ + ( (This)->lpVtbl -> Filter(This,pRecord,countBytes,format,dwFlags,dwThreadId,pCallback,pContinueStatus) ) + +#define ICorDebugProcess4_ProcessStateChanged(This,eChange) \ + ( (This)->lpVtbl -> ProcessStateChanged(This,eChange) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugProcess4_INTERFACE_DEFINED__ */ + + +#ifndef __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ +#define __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ + +/* interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("34B27FB0-A318-450D-A0DD-11B70B21F41D") + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE InvokePauseCallback( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE InvokeResumeCallback( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); + + HRESULT ( STDMETHODCALLTYPE *InvokePauseCallback )( + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); + + HRESULT ( STDMETHODCALLTYPE *InvokeResumeCallback )( + ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly * This); + + END_INTERFACE + } ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl; + + interface ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly + { + CONST_VTBL struct ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnlyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_InvokePauseCallback(This) \ + ( (This)->lpVtbl -> InvokePauseCallback(This) ) + +#define ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_InvokeResumeCallback(This) \ + ( (This)->lpVtbl -> InvokeResumeCallback(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __ICorDebugLegacyNetCFHostCallbackInvoker_PrivateWindowsPhoneOnly_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/pre-build-events-cpp.bat b/pre-build-events-cpp.bat new file mode 100644 index 0000000000..4c80e1232b --- /dev/null +++ b/pre-build-events-cpp.bat @@ -0,0 +1,21 @@ +REM This batch file moves locked outputs (dll/pdb/xml) so as not to block the local build process. +REM The corprofiler dlls get locked up when running the samples against iisexpress.exe for example +REM This is to fix the need to close Visual Studio, manually kill a VBCSCompiler.exe process, delete a dll, then restart Visual Studio + +echo PreBuildEvents +echo $(TargetPath) is %1 +echo $(TargetFileName) is %2 +echo $(TargetDir) is %3 +echo $(TargetName) is %4 + +set dir=%3%LockedAssemblies + +if not exist %dir% (mkdir %dir%) + +REM delete all assemblies not really locked by a process +del "%dir%\*" /q + +REM assembly file (.exe / .dll) - .pdb file - eventually .xml file (documentation) are concerned +if exist "%1" move "%1" "%dir%\%2.locked.%random%" +if exist "%3%4.pdb" move "%3%4.pdb" "%dir%\%4.pdb.locked%random%" +if exist "%3%4.xml.locked" del "%dir%\%4.xml.locked%random%" \ No newline at end of file diff --git a/sample-libs/Directory.Build.props b/sample-libs/Directory.Build.props new file mode 100644 index 0000000000..7fb48af8c9 --- /dev/null +++ b/sample-libs/Directory.Build.props @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/sample-libs/Samples.ExampleLibrary/Class1.cs b/sample-libs/Samples.ExampleLibrary/Class1.cs new file mode 100644 index 0000000000..c8121bd510 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/Class1.cs @@ -0,0 +1,136 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Samples.ExampleLibrary +{ + public class Class1 + { + public int Add(int x, int y) + { + return x + y; + } + + public virtual int Multiply(int x, int y) + { + return x * y; + } + + public Func Divide = (int x, int y) => x / y; + + public string ToCustomString() + { + return "Custom"; + } + + public object ToObject() + { + return this; + } + + public Class1[] ToArray() + { + return new Class1[] { this }; + } + + public Array ToCustomArray() + { + var lengthsArray = new int[2] { 5, 10 }; + var lowerBoundsArray = new int[2] { 20, 15 }; + return Array.CreateInstance(typeof(Class1), lengthsArray, lowerBoundsArray); + } + + public Class1[, ,] ToMdArray() + { + return new Class1[4, 2, 3]; + } + + public Class1[][] ToJaggedArray() + { + return new Class1[][] + { + new Class1[] { this }, + new Class1[] { null, null } + }; + } + + public List ToList() + { + return new List() { this }; + } + + public List.Enumerator ToEnumerator() + { + return ToList().GetEnumerator(); + } + + public DictionaryEntry ToDictionaryEntry() + { + return new DictionaryEntry("Class1", this); + } + + public bool ToBool() + { + return false; + } + + public char ToChar() + { + return 'b'; + } + + public sbyte ToSByte() + { + return 0x1; + } + + public byte ToByte() + { + return 0x1; + } + + public Int16 ToInt16() + { + return 16; + } + + public UInt16 ToUInt16() + { + return 16; + } + + public Int32 ToInt32() + { + return 32; + } + + public UInt32 ToUInt32() + { + return 32; + } + + public Int64 ToInt64() + { + return 64; + } + + public UInt64 ToUInt64() + { + return 64; + } + + public float ToSingle() + { + return 0.1f; + } + + public double ToDouble() + { + return 0.1; + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/Directory.Build.props b/sample-libs/Samples.ExampleLibrary/Directory.Build.props new file mode 100644 index 0000000000..7fb48af8c9 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/Directory.Build.props @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/sample-libs/Samples.ExampleLibrary/FakeClient/Biscuit.cs b/sample-libs/Samples.ExampleLibrary/FakeClient/Biscuit.cs new file mode 100644 index 0000000000..0d11a75dfc --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/FakeClient/Biscuit.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace Samples.ExampleLibrary.FakeClient +{ + public class Biscuit : Biscuit + { + public T Reward { get; set; } + } + + public class Biscuit + { + public Guid Id { get; set; } + public string Message { get; set; } + public List Treats { get; set; } = new List(); + + public class Cookie + { + public bool IsYummy { get; set; } + + public class Raisin + { + public bool IsPurple { get; set; } + } + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/FakeClient/DogClient.cs b/sample-libs/Samples.ExampleLibrary/FakeClient/DogClient.cs new file mode 100644 index 0000000000..3f8f00f3e5 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/FakeClient/DogClient.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Samples.ExampleLibrary.FakeClient +{ + public class DogClient + { + public void Silence() + { + Task.Delay(1).Wait(); + } + + public string TellMeIfTheCookieIsYummy(Biscuit.Cookie cookie, Biscuit.Cookie.Raisin raisin) + { + if (cookie.IsYummy) + { + if (raisin.IsPurple) + { + return "Yes, it is yummy, with purple raisins."; + } + + return "Yes, it is yummy, with white raisins."; + } + + return "No, it is not yummy"; + } + + public void Sit( + string message, + int howManyTimes, + byte[] whatEvenIs = null, + Guid[][] whatEvenIsThis = null, + T1[][][] whatEvenIsThisT = null, + List evenMoreWhatIsThis = null, + List> previousTricks = null, + Tuple, long>, Task, Guid> tuple = null, + Dictionary>>> whatAmIDoing = null) + { + for (var i = 0; i < howManyTimes; i++) + { + message += + message + + whatEvenIs?.ToString() + + whatEvenIsThis?.ToString() + + whatEvenIsThisT?.ToString() + + evenMoreWhatIsThis?.GetType() + + previousTricks?.GetType() + + tuple?.GetType() + + whatAmIDoing?.GetType(); + } + } + + public Biscuit Rollover(Guid clientId, short timesToRun, DogTrick trick) + { + var biscuit = new Biscuit + { + Id = clientId, + Message = trick.Message + }; + + Sit("Sit!", timesToRun); + + return biscuit; + } + + public async Task> StayAndLayDown(Guid clientId, short timesToRun, DogTrick trick, TM1 extraTreat, TM2 extraExtraTreat) + { + await Task.Delay(5); + var biscuit = new Biscuit(); + biscuit.Treats.Add(extraTreat); + biscuit.Treats.Add(extraExtraTreat); + return await Task.FromResult(biscuit); + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/FakeClient/DogTrick.cs b/sample-libs/Samples.ExampleLibrary/FakeClient/DogTrick.cs new file mode 100644 index 0000000000..2898986909 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/FakeClient/DogTrick.cs @@ -0,0 +1,13 @@ +namespace Samples.ExampleLibrary.FakeClient +{ + public class DogTrick + { + public string Message { get; set; } + public T Reward { get; set; } + } + + public class DogTrick + { + public string Message { get; set; } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/GenericTests/ComprehensiveCaller.cs b/sample-libs/Samples.ExampleLibrary/GenericTests/ComprehensiveCaller.cs new file mode 100644 index 0000000000..974fa8b6e7 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/GenericTests/ComprehensiveCaller.cs @@ -0,0 +1,136 @@ +using System; +using System.Threading.Tasks; + +namespace Samples.ExampleLibrary.GenericTests +{ + public class ComprehensiveCaller + { + #region CallReturnM1 + public void CallReturnM1WithCallerTypeArgs(GenericTarget target, CallerT1 input1, CallerT2 input2) + { + target.ReturnM1(input1, input2); + } + + public void CallReturnM1WithCallerTypeArgsReversed(GenericTarget target, CallerT1 input1, CallerT2 input2) + { + target.ReturnM1(input2, input1); + } + + public void CallReturnM1WithClass(GenericTarget target, Exception input1, CallerT2 input2) + { + target.ReturnM1(input1, input2); + } + + public void CallReturnM1WithStruct(GenericTarget target, PointStruct input1, CallerT2 input2) + { + target.ReturnM1(input1, input2); + } + + public void CallReturnM1WithReferenceTypeGenericInstantiation(GenericTarget target, Task input1, CallerT2 input2) + { + target.ReturnM1, CallerT2>(input1, input2); + } + + public void CallReturnM1WithValueTypeGenericInstantiation(GenericTarget target, StructContainer input1, CallerT2 input2) + { + target.ReturnM1, CallerT2>(input1, input2); + } + #endregion + + #region CallReturnM2 + public void CallReturnM2WithCallerTypeArgs(GenericTarget target, CallerT1 input1, CallerT2 input2) + { + target.ReturnM2(input1, input2); + } + + public void CallReturnM2WithCallerTypeArgsReversed(GenericTarget target, CallerT1 input1, CallerT2 input2) + { + target.ReturnM2(input2, input1); + } + + public void CallReturnM2WithClass(GenericTarget target, CallerT1 input1, Exception input2) + { + target.ReturnM2(input1, input2); + } + + public void CallReturnM2WithStruct(GenericTarget target, CallerT1 input1, PointStruct input2) + { + target.ReturnM2(input1, input2); + } + + public void CallReturnM2WithReferenceTypeGenericInstantiation(GenericTarget target, CallerT1 input1, Task input2) + { + target.ReturnM2>(input1, input2); + } + + public void CallReturnM2WithValueTypeGenericInstantiation(GenericTarget target, CallerT1 input1, StructContainer input2) + { + target.ReturnM2>(input1, input2); + } + #endregion + + #region CallReturnT1 + public void CallReturnT1WithCallerTypeArgs(GenericTarget target, object input) + { + target.ReturnT1(input); + } + + public void CallReturnT1WithCallerTypeArgsReversed(GenericTarget target, object input) + { + target.ReturnT1(input); + } + + public void CallReturnT1WithClass(GenericTarget target, object input) + { + target.ReturnT1(input); + } + + public void CallReturnT1WithStruct(GenericTarget target, object input) + { + target.ReturnT1(input); + } + + public void CallReturnT1WithReferenceTypeGenericInstantiation(GenericTarget, CallerT2> target, object input) + { + target.ReturnT1(input); + } + + public void CallReturnT1WithValueTypeGenericInstantiation(GenericTarget, CallerT2> target, object input) + { + target.ReturnT1(input); + } + #endregion + + #region CallReturnT2 + public void CallReturnT2WithCallerTypeArgs(GenericTarget target, object input) + { + target.ReturnT2(input); + } + + public void CallReturnT2WithCallerTypeArgsReversed(GenericTarget target, object input) + { + target.ReturnT2(input); + } + + public void CallReturnT2WithClass(GenericTarget target, object input) + { + target.ReturnT2(input); + } + + public void CallReturnT2WithStruct(GenericTarget, PointStruct> target, object input) + { + target.ReturnT2(input); + } + + public void CallReturnT2WithReferenceTypeGenericInstantiation(GenericTarget>>, Task> target, object input) + { + target.ReturnT2(input); + } + + public void CallReturnT2WithValueTypeGenericInstantiation(GenericTarget> target, object input) + { + target.ReturnT2(input); + } + #endregion + } +} diff --git a/sample-libs/Samples.ExampleLibrary/GenericTests/GenericTarget.cs b/sample-libs/Samples.ExampleLibrary/GenericTests/GenericTarget.cs new file mode 100644 index 0000000000..9807e5c9df --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/GenericTests/GenericTarget.cs @@ -0,0 +1,25 @@ +namespace Samples.ExampleLibrary.GenericTests +{ + public class GenericTarget + { + public M1 ReturnM1(M1 input1, M2 input2) + { + return input1; + } + + public M2 ReturnM2(M1 input1, M2 input2) + { + return input2; + } + + public T1 ReturnT1(object input) + { + return (T1)input; + } + + public T2 ReturnT2(object input) + { + return (T2)input; + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/GenericTests/PointStruct.cs b/sample-libs/Samples.ExampleLibrary/GenericTests/PointStruct.cs new file mode 100644 index 0000000000..f8a81c5fab --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/GenericTests/PointStruct.cs @@ -0,0 +1,13 @@ +namespace Samples.ExampleLibrary.GenericTests +{ + public struct PointStruct + { + public int x, y; + + public PointStruct(int x, int y) + { + this.x = x; + this.y = y; + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/GenericTests/StructContainer.cs b/sample-libs/Samples.ExampleLibrary/GenericTests/StructContainer.cs new file mode 100644 index 0000000000..fd1e62f23b --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/GenericTests/StructContainer.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Samples.ExampleLibrary.GenericTests +{ + public struct StructContainer + { + public List Items { get; } + + public long Id { get; } + + public StructContainer(long id, List items) + { + Id = id; + Items = items; + } + } +} diff --git a/sample-libs/Samples.ExampleLibrary/Samples.ExampleLibrary.csproj b/sample-libs/Samples.ExampleLibrary/Samples.ExampleLibrary.csproj new file mode 100644 index 0000000000..6a3e57d200 --- /dev/null +++ b/sample-libs/Samples.ExampleLibrary/Samples.ExampleLibrary.csproj @@ -0,0 +1,7 @@ + + + + netstandard1.0 + + + diff --git a/sample-libs/Samples.ExampleLibraryTracer/Class1.cs b/sample-libs/Samples.ExampleLibraryTracer/Class1.cs new file mode 100644 index 0000000000..b9df0afdd9 --- /dev/null +++ b/sample-libs/Samples.ExampleLibraryTracer/Class1.cs @@ -0,0 +1,17 @@ +using System; + +namespace Samples.ExampleLibraryTracer +{ + public class Class1 + { + public int Add(int x, int y) + { + return 2 * (x + y); + } + + public virtual int Multiply(int x, int y) + { + return 2 * (x * y); + } + } +} diff --git a/sample-libs/Samples.ExampleLibraryTracer/Directory.Build.props b/sample-libs/Samples.ExampleLibraryTracer/Directory.Build.props new file mode 100644 index 0000000000..7fb48af8c9 --- /dev/null +++ b/sample-libs/Samples.ExampleLibraryTracer/Directory.Build.props @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/sample-libs/Samples.ExampleLibraryTracer/Samples.ExampleLibraryTracer.csproj b/sample-libs/Samples.ExampleLibraryTracer/Samples.ExampleLibraryTracer.csproj new file mode 100644 index 0000000000..6a3e57d200 --- /dev/null +++ b/sample-libs/Samples.ExampleLibraryTracer/Samples.ExampleLibraryTracer.csproj @@ -0,0 +1,7 @@ + + + + netstandard1.0 + + + diff --git a/sample-libs/Samples.Shared/Samples.Shared.csproj b/sample-libs/Samples.Shared/Samples.Shared.csproj new file mode 100644 index 0000000000..f77900360a --- /dev/null +++ b/sample-libs/Samples.Shared/Samples.Shared.csproj @@ -0,0 +1,13 @@ + + + netstandard2.0;net45 + netstandard2.0;netstandard2.1 + Library + true + + + + + + + \ No newline at end of file diff --git a/sample-libs/Samples.Shared/Web/DistributedTracingModel.cs b/sample-libs/Samples.Shared/Web/DistributedTracingModel.cs new file mode 100644 index 0000000000..dc6ad79278 --- /dev/null +++ b/sample-libs/Samples.Shared/Web/DistributedTracingModel.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace Samples.Shared.Web +{ + public class DistributedTracingModel + { + public List Spans { get; set; } + + public void AddSpan( + string method, + string serviceName, + string operationName, + string resourceName, + ulong? traceId, + ulong? spanId) + { + if (Spans == null) + { + Spans = new List(); + } + + Spans.Insert( + 0, + new SpanIdsModel + { + Method = method, + ServiceName = serviceName, + OperationName = operationName, + ResourceName = resourceName, + TraceId = traceId, + SpanId = spanId + }); + } + } + + public class SpanIdsModel + { + public string Method { get; set; } + public string ServiceName { get; set; } + public string OperationName { get; set; } + public string ResourceName { get; set; } + public ulong? TraceId { get; set; } + public ulong? SpanId { get; set; } + } +} diff --git a/sample-libs/Samples.Shared/Web/HttpClientExtensions.cs b/sample-libs/Samples.Shared/Web/HttpClientExtensions.cs new file mode 100644 index 0000000000..9fb033aef5 --- /dev/null +++ b/sample-libs/Samples.Shared/Web/HttpClientExtensions.cs @@ -0,0 +1,25 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Samples.Shared.Web +{ + public static class HttpClientExtensions + { + public static async Task GetAsync(this HttpClient client, string url) + { + if (client == null) + { + throw new ArgumentNullException(nameof(client)); + } + + if (url == null) + { + throw new ArgumentNullException(nameof(url)); + } + + var response = await client.GetAsync(url); + return await response.Content.ReadAsAsync(); + } + } +} diff --git a/src/Datadog.Trace.AspNet/AspNetScopeManager.cs b/src/Datadog.Trace.AspNet/AspNetScopeManager.cs new file mode 100644 index 0000000000..84359c82fb --- /dev/null +++ b/src/Datadog.Trace.AspNet/AspNetScopeManager.cs @@ -0,0 +1,37 @@ +using System; +using System.Web; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.AspNet +{ + internal class AspNetScopeManager : ScopeManagerBase + { + private readonly string _name = "__Datadog_Scope_Current__" + Guid.NewGuid(); + private readonly AsyncLocalCompat _activeScopeFallback = new AsyncLocalCompat(); + + public override Scope Active + { + get + { + var activeScope = _activeScopeFallback.Get(); + if (activeScope != null) + { + return activeScope; + } + + return HttpContext.Current?.Items[_name] as Scope; + } + + protected set + { + _activeScopeFallback.Set(value); + + var httpContext = HttpContext.Current; + if (httpContext != null) + { + httpContext.Items[_name] = value; + } + } + } + } +} diff --git a/src/Datadog.Trace.AspNet/AssemblyInfo.cs b/src/Datadog.Trace.AspNet/AssemblyInfo.cs new file mode 100644 index 0000000000..00c9057657 --- /dev/null +++ b/src/Datadog.Trace.AspNet/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/src/Datadog.Trace.AspNet/Datadog.Trace.AspNet.csproj b/src/Datadog.Trace.AspNet/Datadog.Trace.AspNet.csproj new file mode 100644 index 0000000000..9196af9e81 --- /dev/null +++ b/src/Datadog.Trace.AspNet/Datadog.Trace.AspNet.csproj @@ -0,0 +1,35 @@ + + + + net45 + + + 1.19.1 + Datadog APM Tracing for ASP.NET + +DEPRECATED. This package exists only for backwards compatibility. If your project references this package ("Datadog.Trace.AspNet") or "Datadog.Trace.ClrProfiler.Managed", you can remove them both. + +.NET Core applications no longer require any NuGet package to enable automatic instrumentation. + +Automatic instrumentation for both ASP.NET and ASP.NET Core is now automatically enabled. + +Users who need manual instrumentation should reference the "Datadog.Trace" package. + + + false + + + false + $(NoWarn);NU5128 + + + + + + + + + + \ No newline at end of file diff --git a/src/Datadog.Trace.AspNet/HttpApplicationStartup.cs b/src/Datadog.Trace.AspNet/HttpApplicationStartup.cs new file mode 100644 index 0000000000..914560948a --- /dev/null +++ b/src/Datadog.Trace.AspNet/HttpApplicationStartup.cs @@ -0,0 +1,35 @@ +using System.Web; +using Datadog.Trace.AspNet; + +[assembly: PreApplicationStartMethod(typeof(HttpApplicationStartup), "Register")] + +namespace Datadog.Trace.AspNet +{ + /// + /// Helper class use to register the into the ASP.NET pipeline. + /// + public static class HttpApplicationStartup + { + /// + /// Registers the into the ASP.NET pipeline. + /// + /// This method replaces with a new instance. + public static void Register() + { + // in ASP.NET, we always want to try to use AspNetScopeManager, + // even if the "AspNet" integration is disabled + Tracer.Instance = new Tracer( + settings: null, + agentWriter: null, + sampler: null, + scopeManager: new AspNetScopeManager(), + statsd: null); + + if (Tracer.Instance.Settings.IsIntegrationEnabled(TracingHttpModule.IntegrationName)) + { + // only register http module if integration is enabled + HttpApplication.RegisterModule(typeof(TracingHttpModule)); + } + } + } +} diff --git a/src/Datadog.Trace.AspNet/TracingHttpModule.cs b/src/Datadog.Trace.AspNet/TracingHttpModule.cs new file mode 100644 index 0000000000..6d62b847d5 --- /dev/null +++ b/src/Datadog.Trace.AspNet/TracingHttpModule.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace.AspNet +{ + /// + /// IHttpModule used to trace within an ASP.NET HttpApplication request + /// + public class TracingHttpModule : IHttpModule + { + /// + /// Name of the Integration + /// + public const string IntegrationName = "AspNet"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(TracingHttpModule)); + + // there is no ConcurrentHashSet, so use a ConcurrentDictionary + // where we only care about the key, not the value + private static ConcurrentDictionary registeredEventHandlers = new ConcurrentDictionary(); + + private readonly string _httpContextScopeKey; + private readonly string _requestOperationName; + private HttpApplication _httpApplication; + + /// + /// Initializes a new instance of the class. + /// + public TracingHttpModule() + : this("aspnet.request") + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The operation name to be used for the trace/span data generated + public TracingHttpModule(string operationName) + { + _requestOperationName = operationName ?? throw new ArgumentNullException(nameof(operationName)); + + _httpContextScopeKey = string.Concat("__Datadog.Trace.AspNet.TracingHttpModule-", _requestOperationName); + } + + /// + public void Init(HttpApplication httpApplication) + { + // Intent: The first HttpModule to run Init for this HttpApplication will register for events + // Actual: Each HttpApplication that comes through here is potentially a new .NET object, even + // if it refers to the same web application. Based on my reading, it appears that initialization + // is done for several types of resources. Read more in this SO article -- look at Sunday Ironfoot's + // (yes, reliable sounding name of course) response toward the end of this article: + // https://stackoverflow.com/a/2416546/24231. + // I've discovered that not letting each of these unique application objects be added, and thus + // the event handlers be registered within each HttpApplication object, leads to the runtime + // weirdness: at one point it crashed consistently for me, and later, I saw no spans at all. + if (registeredEventHandlers.TryAdd(httpApplication, 1)) + { + _httpApplication = httpApplication; + httpApplication.BeginRequest += OnBeginRequest; + httpApplication.EndRequest += OnEndRequest; + httpApplication.Error += OnError; + } + } + + /// + public void Dispose() + { + // defend against multiple calls to Dispose() + if (_httpApplication != null) + { + // Remove the HttpApplication mapping so we don't keep the object alive + registeredEventHandlers.TryRemove(_httpApplication, out var _); + _httpApplication = null; + } + } + + private void OnBeginRequest(object sender, EventArgs eventArgs) + { + Scope scope = null; + + try + { + var tracer = Tracer.Instance; + + if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled + return; + } + + var httpContext = (sender as HttpApplication)?.Context; + + if (httpContext == null) + { + return; + } + + HttpRequest httpRequest = httpContext.Request; + SpanContext propagatedContext = null; + var tagsFromHeaders = Enumerable.Empty>(); + + if (tracer.ActiveScope == null) + { + try + { + // extract propagated http headers + var headers = httpRequest.Headers.Wrap(); + propagatedContext = SpanContextPropagator.Instance.Extract(headers); + tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headers, tracer.Settings.HeaderTags); + } + catch (Exception ex) + { + Log.Error(ex, "Error extracting propagated HTTP headers."); + } + } + + string host = httpRequest.Headers.Get("Host"); + string httpMethod = httpRequest.HttpMethod.ToUpperInvariant(); + string url = httpRequest.RawUrl.ToLowerInvariant(); + string path = UriHelpers.GetRelativeUrl(httpRequest.Url, tryRemoveIds: true); + string resourceName = $"{httpMethod} {path.ToLowerInvariant()}"; + + scope = tracer.StartActive(_requestOperationName, propagatedContext); + scope.Span.DecorateWebServerSpan(resourceName, httpMethod, host, url, tagsFromHeaders); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); + scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); + + httpContext.Items[_httpContextScopeKey] = scope; + } + catch (Exception ex) + { + // Dispose here, as the scope won't be in context items and won't get disposed on request end in that case... + scope?.Dispose(); + Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); + } + } + + private void OnEndRequest(object sender, EventArgs eventArgs) + { + try + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled + return; + } + + if (sender is HttpApplication app && + app.Context.Items[_httpContextScopeKey] is Scope scope) + { + scope.Span.SetServerStatusCode(app.Context.Response.StatusCode); + scope.Dispose(); + } + } + catch (Exception ex) + { + Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); + } + } + + private void OnError(object sender, EventArgs eventArgs) + { + try + { + var httpContext = (sender as HttpApplication)?.Context; + var exception = httpContext?.Error; + + // We want to ignore 404 exceptions here, as they are not errors + var httpException = exception as HttpException; + var is404 = httpException?.GetHttpCode() == 404; + + if (exception != null && !is404 && httpContext.Items[_httpContextScopeKey] is Scope scope) + { + scope.Span.SetException(exception); + } + } + catch (Exception ex) + { + Log.Error(ex, "Datadog ASP.NET HttpModule instrumentation error"); + } + } + } +} diff --git a/src/Datadog.Trace.Ci.Shared/BuildTags.cs b/src/Datadog.Trace.Ci.Shared/BuildTags.cs new file mode 100644 index 0000000000..c7fdcfc18d --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/BuildTags.cs @@ -0,0 +1,138 @@ +namespace Datadog.Trace.Ci +{ + /// + /// Span tags for build data model + /// + internal static class BuildTags + { + /// + /// Build operation name + /// + public const string BuildOperationName = "msbuild.build"; + + /// + /// Build name + /// + public const string BuildName = "build.name"; + + /// + /// Build command + /// + public const string BuildCommand = "build.command"; + + /// + /// Build working folder + /// + public const string BuildWorkingFolder = "build.working_folder"; + + /// + /// Build environment + /// + public const string BuildEnvironment = "build.environment"; + + /// + /// Build start message + /// + public const string BuildStartMessage = "build.start_message"; + + /// + /// Build start message + /// + public const string BuildEndMessage = "build.end_message"; + + /// + /// Build status + /// + public const string BuildStatus = "build.status"; + + /// + /// Build succeeded status + /// + public const string BuildSucceededStatus = "SUCCEEDED"; + + /// + /// Build failed status + /// + public const string BuildFailedStatus = "FAILED"; + + /// + /// Project properties + /// + public const string ProjectProperties = "project.properties"; + + /// + /// Project filename + /// + public const string ProjectFile = "project.file"; + + /// + /// Project sender entity + /// + public const string ProjectSenderName = "project.sender_name"; + + /// + /// Project target names + /// + public const string ProjectTargetNames = "project.target_names"; + + /// + /// Project tools version + /// + public const string ProjectToolsVersion = "project.tools_version"; + + /// + /// Error message + /// + public const string ErrorMessage = "error.msg"; + + /// + /// Error type + /// + public const string ErrorType = "error.type"; + + /// + /// Error code + /// + public const string ErrorCode = "error.code"; + + /// + /// Error file + /// + public const string ErrorFile = "error.file"; + + /// + /// Error start line + /// + public const string ErrorStartLine = "error.start_location.line"; + + /// + /// Error start column + /// + public const string ErrorStartColumn = "error.start_location.column"; + + /// + /// Error end line + /// + public const string ErrorEndLine = "error.end_location.line"; + + /// + /// Error end column + /// + public const string ErrorEndColumn = "error.end_location.column"; + + /// + /// Error project file + /// + public const string ErrorProjectFile = "error.project_file"; + + /// + /// Error sub category + /// + public const string ErrorSubCategory = "error.sub_category"; + + /// + /// Error stack + /// + public const string ErrorStack = "error.stack"; + } +} diff --git a/src/Datadog.Trace.Ci.Shared/CIEnvironmentValues.cs b/src/Datadog.Trace.Ci.Shared/CIEnvironmentValues.cs new file mode 100644 index 0000000000..2cf0e99c5d --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/CIEnvironmentValues.cs @@ -0,0 +1,279 @@ +using System; +using System.Text.RegularExpressions; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; +using Datadog.Trace.Vendors.Serilog; + +namespace Datadog.Trace.Ci +{ + internal static class CIEnvironmentValues + { + private static readonly ILogger Logger = DatadogLogging.GetLogger(typeof(CIEnvironmentValues)); + + static CIEnvironmentValues() + { + if (EnvironmentHelpers.GetEnvironmentVariable("TRAVIS") != null) + { + SetupTravisEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("CIRCLECI") != null) + { + SetupCircleCiEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("JENKINS_URL") != null) + { + SetupJenkinsEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("GITLAB_CI") != null) + { + SetupGitlabEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR") != null) + { + SetupAppveyorEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("TF_BUILD") != null) + { + SetupAzurePipelinesEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_COMMIT") != null) + { + SetupBitbucketEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("GITHUB_SHA") != null) + { + SetupGithubActionsEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("TEAMCITY_VERSION") != null) + { + SetupTeamcityEnvironment(); + } + else if (EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE") != null) + { + SetupBuildkiteEnvironment(); + } + + try + { + // Clean branch name + if (!string.IsNullOrEmpty(Branch)) + { + var regex = new Regex(@"^refs\/heads\/(.*)|refs\/(.*)$", RegexOptions.Compiled); + var match = regex.Match(Branch); + if (match.Success && match.Groups.Count == 3) + { + Branch = !string.IsNullOrWhiteSpace(match.Groups[1].Value) ? match.Groups[1].Value : match.Groups[2].Value; + } + } + } + catch (Exception ex) + { + Logger.Warning(ex, "Error fixing branch name: {0}", Branch); + } + } + + public static bool IsCI { get; private set; } + + public static string Provider { get; private set; } + + public static string Repository { get; private set; } + + public static string Commit { get; private set; } + + public static string Branch { get; private set; } + + public static string SourceRoot { get; private set; } + + public static string PipelineId { get; private set; } + + public static string PipelineNumber { get; private set; } + + public static string PipelineUrl { get; private set; } + + public static string JobUrl { get; private set; } + + public static void DecorateSpan(Span span) + { + if (span == null || !IsCI) + { + return; + } + + span.SetTag(CommonTags.CIProvider, Provider); + span.SetTag(CommonTags.CIPipelineId, PipelineId); + span.SetTag(CommonTags.CIPipelineNumber, PipelineNumber); + span.SetTag(CommonTags.CIPipelineUrl, PipelineUrl); + span.SetTag(CommonTags.CIJobUrl, JobUrl); + + span.SetTag(CommonTags.GitRepository, Repository); + span.SetTag(CommonTags.GitCommit, Commit); + span.SetTag(CommonTags.GitBranch, Branch); + + span.SetTag(CommonTags.BuildSourceRoot, SourceRoot); + } + + private static void SetupTravisEnvironment() + { + IsCI = true; + Provider = "travis"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_REPO_SLUG"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_COMMIT"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_BUILD_DIR"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_BUILD_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_BUILD_NUMBER"); + PipelineUrl = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_BUILD_WEB_URL"); + JobUrl = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_JOB_WEB_URL"); + Branch = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_PULL_REQUEST_BRANCH"); + if (string.IsNullOrWhiteSpace(Branch)) + { + Branch = EnvironmentHelpers.GetEnvironmentVariable("TRAVIS_BRANCH"); + } + } + + private static void SetupCircleCiEnvironment() + { + IsCI = true; + Provider = "circleci"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_REPOSITORY_URL"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_SHA1"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_WORKING_DIRECTORY"); + PipelineId = null; + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_BUILD_NUM"); + PipelineUrl = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_BUILD_URL"); + Branch = EnvironmentHelpers.GetEnvironmentVariable("CIRCLE_BRANCH"); + } + + private static void SetupJenkinsEnvironment() + { + IsCI = true; + Provider = "jenkins"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("GIT_URL"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("GIT_COMMIT"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("WORKSPACE"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("BUILD_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("BUILD_NUMBER"); + PipelineUrl = EnvironmentHelpers.GetEnvironmentVariable("BUILD_URL"); + JobUrl = EnvironmentHelpers.GetEnvironmentVariable("JOB_URL"); + Branch = EnvironmentHelpers.GetEnvironmentVariable("GIT_BRANCH"); + if (Branch?.IndexOf("origin/", StringComparison.Ordinal) == 0) + { + Branch = Branch.Substring(7); + } + } + + private static void SetupGitlabEnvironment() + { + IsCI = true; + Provider = "gitlab"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("CI_REPOSITORY_URL"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("CI_COMMIT_SHA"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("CI_PROJECT_DIR"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("CI_PIPELINE_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("CI_PIPELINE_IID"); + PipelineUrl = EnvironmentHelpers.GetEnvironmentVariable("CI_PIPELINE_URL"); + JobUrl = EnvironmentHelpers.GetEnvironmentVariable("CI_JOB_URL"); + Branch = EnvironmentHelpers.GetEnvironmentVariable("CI_COMMIT_BRANCH"); + if (string.IsNullOrWhiteSpace(Branch)) + { + Branch = EnvironmentHelpers.GetEnvironmentVariable("CI_COMMIT_REF_NAME"); + } + } + + private static void SetupAppveyorEnvironment() + { + IsCI = true; + Provider = "appveyor"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_REPO_NAME"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_REPO_COMMIT"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_BUILD_FOLDER"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_BUILD_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_BUILD_NUMBER"); + PipelineUrl = string.Format("https://ci.appveyor.com/project/{0}/builds/{1}", EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_PROJECT_SLUG"), EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_BUILD_ID")); + Branch = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH"); + if (string.IsNullOrWhiteSpace(Branch)) + { + Branch = EnvironmentHelpers.GetEnvironmentVariable("APPVEYOR_REPO_BRANCH"); + } + } + + private static void SetupAzurePipelinesEnvironment() + { + IsCI = true; + Provider = "azurepipelines"; + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("BUILD_SOURCESDIRECTORY"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("BUILD_BUILDID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("BUILD_BUILDNUMBER"); + PipelineUrl = string.Format("{0}{1}/_build/results?buildId={2}&_a=summary", EnvironmentHelpers.GetEnvironmentVariable("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"), EnvironmentHelpers.GetEnvironmentVariable("SYSTEM_TEAMPROJECT"), EnvironmentHelpers.GetEnvironmentVariable("BUILD_BUILDID")); + Repository = EnvironmentHelpers.GetEnvironmentVariable("BUILD_REPOSITORY_URI"); + + string prCommit = EnvironmentHelpers.GetEnvironmentVariable("SYSTEM_PULLREQUEST_SOURCECOMMITID"); + Commit = !string.IsNullOrWhiteSpace(prCommit) ? prCommit : EnvironmentHelpers.GetEnvironmentVariable("BUILD_SOURCEVERSION"); + + string prBranch = EnvironmentHelpers.GetEnvironmentVariable("SYSTEM_PULLREQUEST_SOURCEBRANCH"); + Branch = !string.IsNullOrWhiteSpace(prBranch) ? prBranch : EnvironmentHelpers.GetEnvironmentVariable("BUILD_SOURCEBRANCHNAME"); + + if (string.IsNullOrWhiteSpace(Branch)) + { + Branch = EnvironmentHelpers.GetEnvironmentVariable("BUILD_SOURCEBRANCH"); + } + } + + private static void SetupBitbucketEnvironment() + { + IsCI = true; + Provider = "bitbucketpipelines"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_GIT_SSH_ORIGIN"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_COMMIT"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_CLONE_DIR"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_PIPELINE_UUID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("BITBUCKET_BUILD_NUMBER"); + PipelineUrl = null; + } + + private static void SetupGithubActionsEnvironment() + { + IsCI = true; + Provider = "github"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_REPOSITORY"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_SHA"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_WORKSPACE"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_RUN_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_RUN_NUMBER"); + PipelineUrl = $"{Repository}/commit/{Commit}/checks"; + Branch = EnvironmentHelpers.GetEnvironmentVariable("GITHUB_REF"); + } + + private static void SetupTeamcityEnvironment() + { + IsCI = true; + Provider = "teamcity"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("BUILD_VCS_URL"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("BUILD_VCS_NUMBER"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("BUILD_CHECKOUTDIR"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("BUILD_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("BUILD_NUMBER"); + string serverUrl = EnvironmentHelpers.GetEnvironmentVariable("SERVER_URL"); + if (PipelineId != null && serverUrl != null) + { + PipelineUrl = $"{serverUrl}/viewLog.html?buildId={PipelineId}"; + } + else + { + PipelineUrl = null; + } + } + + private static void SetupBuildkiteEnvironment() + { + IsCI = true; + Provider = "buildkite"; + Repository = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_REPO"); + Commit = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_COMMIT"); + SourceRoot = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_BUILD_CHECKOUT_PATH"); + PipelineId = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_BUILD_ID"); + PipelineNumber = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_BUILD_NUMBER"); + PipelineUrl = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_BUILD_URL"); + Branch = EnvironmentHelpers.GetEnvironmentVariable("BUILDKITE_BRANCH"); + } + } +} diff --git a/src/Datadog.Trace.Ci.Shared/CommonTags.cs b/src/Datadog.Trace.Ci.Shared/CommonTags.cs new file mode 100644 index 0000000000..ba1c3b5dde --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/CommonTags.cs @@ -0,0 +1,78 @@ +namespace Datadog.Trace.Ci +{ + /// + /// Common Span tags for test/build data model + /// + internal static class CommonTags + { + /// + /// GIT Repository + /// + public const string GitRepository = "git.repository_url"; + + /// + /// GIT Commit hash + /// + public const string GitCommit = "git.commit_sha"; + + /// + /// GIT Branch name + /// + public const string GitBranch = "git.branch"; + + /// + /// Build Source root + /// + public const string BuildSourceRoot = "build.source_root"; + + /// + /// CI Provider + /// + public const string CIProvider = "ci.provider.name"; + + /// + /// CI Pipeline id + /// + public const string CIPipelineId = "ci.pipeline.id"; + + /// + /// CI Pipeline number + /// + public const string CIPipelineNumber = "ci.pipeline.number"; + + /// + /// CI Pipeline url + /// + public const string CIPipelineUrl = "ci.pipeline.url"; + + /// + /// CI Job url + /// + public const string CIJobUrl = "ci.job.url"; + + /// + /// Runtime name + /// + public const string RuntimeName = "runtime.name"; + + /// + /// Runtime os architecture + /// + public const string RuntimeOSArchitecture = "runtime.os_architecture"; + + /// + /// Runtime os platform + /// + public const string RuntimeOSPlatform = "runtime.os_platform"; + + /// + /// Runtime process architecture + /// + public const string RuntimeProcessArchitecture = "runtime.process_architecture"; + + /// + /// Runtime version + /// + public const string RuntimeVersion = "runtime.version"; + } +} diff --git a/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.projitems b/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.projitems new file mode 100644 index 0000000000..29f4ae868b --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.projitems @@ -0,0 +1,17 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + a1d7653a-c409-414a-b9b0-7879953ebcdd + + + Datadog.Trace.Ci + + + + + + + + \ No newline at end of file diff --git a/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.shproj b/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.shproj new file mode 100644 index 0000000000..c6cef39c6c --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/Datadog.Trace.Ci.Shared.shproj @@ -0,0 +1,13 @@ + + + + a1d7653a-c409-414a-b9b0-7879953ebcdd + 14.0 + + + + + + + + diff --git a/src/Datadog.Trace.Ci.Shared/TestTags.cs b/src/Datadog.Trace.Ci.Shared/TestTags.cs new file mode 100644 index 0000000000..77e33db8de --- /dev/null +++ b/src/Datadog.Trace.Ci.Shared/TestTags.cs @@ -0,0 +1,73 @@ +namespace Datadog.Trace.Ci +{ + /// + /// Span tags for test data model + /// + internal static class TestTags + { + /// + /// Test suite name + /// + public const string Suite = "test.suite"; + + /// + /// Test name + /// + public const string Name = "test.name"; + + /// + /// Test type + /// + public const string Type = "test.type"; + + /// + /// Test type test + /// + public const string TypeTest = "test"; + + /// + /// Test type benchmark + /// + public const string TypeBenchmark = "benchmark"; + + /// + /// Test framework + /// + public const string Framework = "test.framework"; + + /// + /// Test parameters + /// + public const string Arguments = "test.arguments"; + + /// + /// Test traits + /// + public const string Traits = "test.traits"; + + /// + /// Test status + /// + public const string Status = "test.status"; + + /// + /// Test Pass status + /// + public const string StatusPass = "pass"; + + /// + /// Test Fail status + /// + public const string StatusFail = "fail"; + + /// + /// Test Skip status + /// + public const string StatusSkip = "skip"; + + /// + /// Test skip reason + /// + public const string SkipReason = "test.skip_reason"; + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/AssemblyInfo.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/AssemblyInfo.cs new file mode 100644 index 0000000000..16b2a2813c --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Runtime.CompilerServices; + +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.Managed, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.Managed.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/ClrNames.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/ClrNames.cs new file mode 100644 index 0000000000..fe7161d080 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/ClrNames.cs @@ -0,0 +1,35 @@ +namespace Datadog.Trace.ClrProfiler +{ + internal static class ClrNames + { + public const string Ignore = "_"; + + public const string Void = "System.Void"; + public const string Object = "System.Object"; + public const string Bool = "System.Boolean"; + public const string String = "System.String"; + + public const string SByte = "System.SByte"; + public const string Byte = "System.Byte"; + + public const string Int16 = "System.Int16"; + public const string Int32 = "System.Int32"; + public const string Int64 = "System.Int64"; + + public const string UInt16 = "System.UInt16"; + public const string UInt32 = "System.UInt32"; + public const string UInt64 = "System.UInt64"; + + public const string Task = "System.Threading.Tasks.Task"; + public const string CancellationToken = "System.Threading.CancellationToken"; + + // ReSharper disable once InconsistentNaming + public const string IAsyncResult = "System.IAsyncResult"; + public const string AsyncCallback = "System.AsyncCallback"; + + public const string HttpRequestMessage = "System.Net.Http.HttpRequestMessage"; + public const string HttpResponseMessageTask = "System.Threading.Tasks.Task`1"; + + public const string GenericTask = "System.Threading.Tasks.Task`1"; + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj b/src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj new file mode 100644 index 0000000000..474e861c44 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj @@ -0,0 +1,16 @@ + + + + Datadog.Trace.ClrProfiler + + + 1.19.1 + false + + + false + + + \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/IntegrationVersionRange.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/IntegrationVersionRange.cs new file mode 100644 index 0000000000..13e57ee728 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/IntegrationVersionRange.cs @@ -0,0 +1,94 @@ +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Specifies a safe version range for an integration. + /// + public class IntegrationVersionRange + { + /// + /// Gets the minimum major version. + /// + public ushort MinimumMajor { get; private set; } = ushort.MinValue; + + /// + /// Gets the minimum minor version. + /// + public ushort MinimumMinor { get; private set; } = ushort.MinValue; + + /// + /// Gets the minimum patch version. + /// + public ushort MinimumPatch { get; private set; } = ushort.MinValue; + + /// + /// Gets the maximum major version. + /// + public ushort MaximumMajor { get; private set; } = ushort.MaxValue; + + /// + /// Gets the maximum minor version. + /// + public ushort MaximumMinor { get; private set; } = ushort.MaxValue; + + /// + /// Gets the maximum patch version. + /// + public ushort MaximumPatch { get; private set; } = ushort.MaxValue; + + /// + /// Gets the MinimumMajor, MinimumMinor, and MinimumPatch properties. + /// Convenience property for setting target minimum version. + /// + public string MinimumVersion + { + get => $"{MinimumMajor}.{MinimumMinor}.{MinimumPatch}"; + internal set + { + MinimumMajor = MinimumMinor = MinimumPatch = ushort.MinValue; + var parts = value.Split('.'); + if (parts.Length > 0) + { + MinimumMajor = ushort.Parse(parts[0]); + } + + if (parts.Length > 1) + { + MinimumMinor = ushort.Parse(parts[1]); + } + + if (parts.Length > 2) + { + MinimumPatch = ushort.Parse(parts[2]); + } + } + } + + /// + /// Gets the MaximumMajor, MaximumMinor, and MaximumPatch properties. + /// Convenience property for setting target minimum version. + /// + public string MaximumVersion + { + get => $"{MaximumMajor}.{MaximumMinor}.{MaximumPatch}"; + internal set + { + MaximumMajor = MaximumMinor = MaximumPatch = ushort.MaxValue; + var parts = value.Split('.'); + if (parts.Length > 0) + { + MaximumMajor = ushort.Parse(parts[0]); + } + + if (parts.Length > 1) + { + MaximumMinor = ushort.Parse(parts[1]); + } + + if (parts.Length > 2) + { + MaximumPatch = ushort.Parse(parts[2]); + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/InterceptMethodAttribute.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/InterceptMethodAttribute.cs new file mode 100644 index 0000000000..36acff706b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/InterceptMethodAttribute.cs @@ -0,0 +1,112 @@ +using System; +using System.Linq; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Attribute that indicates that the decorated method is meant to intercept calls + /// to another method. Used to generate the integration definitions file. + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] + public class InterceptMethodAttribute : Attribute + { + /// + /// Gets or sets the name of the integration. + /// + /// + /// Multiple method replacements with the same integration name are grouped together. + /// + public string Integration { get; set; } + + /// + /// Gets or sets the name of the assembly where calls to the target method are searched. + /// If null, search in all loaded assemblies. + /// + public string CallerAssembly { get; set; } + + /// + /// Gets or sets the name of the type where calls to the target method are searched. + /// If null, search in all types defined in loaded assemblies. + /// + public string CallerType { get; set; } + + /// + /// Gets or sets the name of the method where calls to the target method are searched. + /// If null, search in all loaded types. + /// + public string CallerMethod { get; set; } + + /// + /// Gets or sets the name of the assembly that contains the target method to be intercepted. + /// Required if is not set. + /// + public string TargetAssembly + { + get => string.Empty; + set => TargetAssemblies = new[] { value }; + } + + /// + /// Gets or sets the name of the assemblies that contain the target method to be intercepted. + /// Required if is not set. + /// + public string[] TargetAssemblies { get; set; } + + /// + /// Gets or sets the name of the type that contains the target method to be intercepted. + /// Required. + /// + public string TargetType { get; set; } + + /// + /// Gets or sets the name of the target method to be intercepted. + /// If null, default to the name of the decorated method. + /// + public string TargetMethod { get; set; } + + /// + /// Gets or sets the method signature that is matched to the target method to be intercepted. + /// If null, signature check is not done. + /// + public string TargetSignature { get; set; } + + /// + /// Gets or sets the explicit type array for the target method to be intercepted. + /// This is a required field. + /// Follows format: + /// new[] { return_type, param_1_type, param_2_type, ..., param_n_type } + /// Must match the wrapper method in count: + /// n (parameters) + 1 (return type) - (is_instance_method : 1 : 0) - 1 (opcode) + /// Indexes with "_" are ignored for comparison purposes. + /// + public string[] TargetSignatureTypes { get; set; } + + /// + /// Gets the target version range for . + /// + public IntegrationVersionRange TargetVersionRange { get; } = new IntegrationVersionRange(); + + /// + /// Gets or sets the target minimum version. + /// + public string TargetMinimumVersion + { + get => TargetVersionRange.MinimumVersion; + set => TargetVersionRange.MinimumVersion = value; + } + + /// + /// Gets or sets the target maximum version. + /// + public string TargetMaximumVersion + { + get => TargetVersionRange.MaximumVersion; + set => TargetVersionRange.MaximumVersion = value; + } + + /// + /// Gets or sets the MethodReplacementActionType for this method. + /// + public MethodReplacementActionType MethodReplacementAction { get; set; } = MethodReplacementActionType.ReplaceTargetMethod; + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/MethodReplacementActionType.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/MethodReplacementActionType.cs new file mode 100644 index 0000000000..775530d193 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/MethodReplacementActionType.cs @@ -0,0 +1,27 @@ +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Enum that instructs the CLR profiler, during JIT compilation of a method, + /// where to insert a method call to the intercept method. + /// + public enum MethodReplacementActionType + { + /// + /// All method calls to the target method should be replaced with method + /// calls to the intercept method. + /// This is the historical behavior of the CLR profiler and it requires + /// that the method body of the intercept method invokes the original + /// target method. + /// + ReplaceTargetMethod, + + /// + /// The method call to the intercept method should be inserted at the + /// beginning of the caller's method body. + /// This action is not intended for generating spans. This should only + /// be used for inserting profiler-initialization logic such as + /// adding ASP.NET middleware. + /// + InsertFirst, + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Core/TypeExtensions.cs b/src/Datadog.Trace.ClrProfiler.Managed.Core/TypeExtensions.cs new file mode 100644 index 0000000000..e9662a18d6 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Core/TypeExtensions.cs @@ -0,0 +1,77 @@ +namespace Datadog.Trace.ClrProfiler +{ + internal static class TypeExtensions + { + public static System.Type GetInstrumentedType( + this object runtimeObject, + string instrumentedTypeName) + { + if (runtimeObject == null) + { + return null; + } + + var currentType = runtimeObject.GetType(); + + while (currentType != null) + { + if ($"{currentType.Namespace}.{currentType.Name}" == instrumentedTypeName) + { + return currentType; + } + + currentType = currentType.BaseType; + } + + return null; + } + + public static System.Type GetInstrumentedType( + this object runtimeObject, + string instrumentedNamespace, + string instrumentedTypeName) + { + if (runtimeObject == null) + { + return null; + } + + var currentType = runtimeObject.GetType(); + + while (currentType != null) + { + if (currentType.Name == instrumentedTypeName && currentType.Namespace == instrumentedNamespace) + { + return currentType; + } + + currentType = currentType.BaseType; + } + + return null; + } + + public static System.Type GetInstrumentedInterface( + this object runtimeObject, + string instrumentedInterfaceName) + { + if (runtimeObject == null) + { + return null; + } + + var currentType = runtimeObject.GetType(); + var interfaces = currentType.GetInterfaces(); + + foreach (var interfaceType in interfaces) + { + if ($"{interfaceType.Namespace}.{interfaceType.Name}" == instrumentedInterfaceName) + { + return interfaceType; + } + } + + return null; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj new file mode 100644 index 0000000000..a8cc1ab9ed --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj @@ -0,0 +1,13 @@ + + + + Datadog.Trace.ClrProfiler.Managed.Loader + net45;netcoreapp2.0 + netcoreapp2.0 + ..\bin\ProfilerResources\ + + + 1.19.1 + + + \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/FileSink.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/FileSink.cs new file mode 100644 index 0000000000..552b7431dd --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/FileSink.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// +// This comment is here to prevent StyleCop from analyzing a file originally from Serilog. +//------------------------------------------------------------------------------ + +using System; +using System.IO; +using System.Text; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + internal sealed class FileSink : IDisposable + { + readonly TextWriter _output; + readonly FileStream _underlyingStream; + readonly object _syncRoot = new object(); + + public FileSink(string path, Encoding encoding = null) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + + var directory = Path.GetDirectoryName(path); + if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read); + + _output = new StreamWriter(outputStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + public void Info(string message, params object[] args) + { + _output.Write(message, args); + FlushToDisk(); + } + + public void Dispose() + { + lock (_syncRoot) + { + _output.Dispose(); + } + } + + private void FlushToDisk() + { + lock (_syncRoot) + { + _output.Flush(); + _underlyingStream.Flush(true); + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/ManagedProfilerAssemblyLoadContext.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/ManagedProfilerAssemblyLoadContext.cs new file mode 100644 index 0000000000..9ddedbd94b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/ManagedProfilerAssemblyLoadContext.cs @@ -0,0 +1,15 @@ +#if NETCOREAPP +using System.Reflection; +using System.Runtime.Loader; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + internal class ManagedProfilerAssemblyLoadContext : AssemblyLoadContext + { + protected override Assembly Load(AssemblyName assemblyName) + { + return null; + } + } +} +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetCore.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetCore.cs new file mode 100644 index 0000000000..bf7e92be6b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetCore.cs @@ -0,0 +1,58 @@ +#if NETCOREAPP +using System; +using System.IO; +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + /// + /// A class that attempts to load the Datadog.Trace.ClrProfiler.Managed .NET assembly. + /// + public partial class Startup + { + internal static System.Runtime.Loader.AssemblyLoadContext DependencyLoadContext { get; } = new ManagedProfilerAssemblyLoadContext(); + + private static string ResolveManagedProfilerDirectory() + { + string tracerFrameworkDirectory = "netstandard2.0"; + var tracerHomeDirectory = ReadEnvironmentVariable("DD_DOTNET_TRACER_HOME") ?? string.Empty; + return Path.Combine(tracerHomeDirectory, tracerFrameworkDirectory); + } + + private static Assembly AssemblyResolve_ManagedProfilerDependencies(object sender, ResolveEventArgs args) + { + var assemblyName = new AssemblyName(args.Name); + + // On .NET Framework, having a non-US locale can cause mscorlib + // to enter the AssemblyResolve event when searching for resources + // in its satellite assemblies. This seems to have been fixed in + // .NET Core in the 2.0 servicing branch, so we should not see this + // occur, but guard against it anyways. If we do see it, exit early + // so we don't cause infinite recursion. + if (string.Equals(assemblyName.Name, "System.Private.CoreLib.resources", StringComparison.OrdinalIgnoreCase) || + string.Equals(assemblyName.Name, "System.Net.Http", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + var path = Path.Combine(ManagedProfilerDirectory, $"{assemblyName.Name}.dll"); + + if (assemblyName.Name.StartsWith("Datadog.Trace", StringComparison.OrdinalIgnoreCase) + && assemblyName.FullName.IndexOf("PublicKeyToken=def86d061d0d2eeb", StringComparison.OrdinalIgnoreCase) >= 0 + && File.Exists(path)) + { + StartupLogger.Debug("Loading {0} with Assembly.LoadFrom", path); + return Assembly.LoadFrom(path); // Load the main profiler and tracer into the default Assembly Load Context + } + else if (File.Exists(path)) + { + StartupLogger.Debug("Loading {0} with DependencyLoadContext.LoadFromAssemblyPath", path); + return DependencyLoadContext.LoadFromAssemblyPath(path); // Load unresolved framework and third-party dependencies into a custom Assembly Load Context + } + + return null; + } + } +} + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetFramework.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetFramework.cs new file mode 100644 index 0000000000..b68c03e89a --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.NetFramework.cs @@ -0,0 +1,57 @@ +#if NETFRAMEWORK + +using System; +using System.IO; +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + /// + /// A class that attempts to load the Datadog.Trace.ClrProfiler.Managed .NET assembly. + /// + public partial class Startup + { + private static string ResolveManagedProfilerDirectory() + { + // We currently build two assemblies targeting .NET Framework. + // If we're running on the .NET Framework, load the highest-compatible assembly + string corlibFileVersionString = ((AssemblyFileVersionAttribute)typeof(object).Assembly.GetCustomAttribute(typeof(AssemblyFileVersionAttribute))).Version; + string corlib461FileVersionString = "4.6.1055.0"; + + // This will throw an exception if the version number does not match the expected 2-4 part version number of non-negative int32 numbers, + // but mscorlib should be versioned correctly + var corlibVersion = new Version(corlibFileVersionString); + var corlib461Version = new Version(corlib461FileVersionString); + var tracerFrameworkDirectory = corlibVersion < corlib461Version ? "net45" : "net461"; + + var tracerHomeDirectory = ReadEnvironmentVariable("DD_DOTNET_TRACER_HOME") ?? string.Empty; + return Path.Combine(tracerHomeDirectory, tracerFrameworkDirectory); + } + + private static Assembly AssemblyResolve_ManagedProfilerDependencies(object sender, ResolveEventArgs args) + { + var assemblyName = new AssemblyName(args.Name).Name; + + // On .NET Framework, having a non-US locale can cause mscorlib + // to enter the AssemblyResolve event when searching for resources + // in its satellite assemblies. Exit early so we don't cause + // infinite recursion. + if (string.Equals(assemblyName, "mscorlib.resources", StringComparison.OrdinalIgnoreCase) || + string.Equals(assemblyName, "System.Net.Http", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + var path = Path.Combine(ManagedProfilerDirectory, $"{assemblyName}.dll"); + if (File.Exists(path)) + { + StartupLogger.Debug("Loading {0}", path); + return Assembly.LoadFrom(path); + } + + return null; + } + } +} + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs new file mode 100644 index 0000000000..0aa4c14bc4 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs @@ -0,0 +1,58 @@ +using System; +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + /// + /// A class that attempts to load the Datadog.Trace.ClrProfiler.Managed .NET assembly. + /// + public partial class Startup + { + /// + /// Initializes static members of the class. + /// This method also attempts to load the Datadog.Trace.ClrProfiler.Managed .NET assembly. + /// + static Startup() + { + ManagedProfilerDirectory = ResolveManagedProfilerDirectory(); + AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve_ManagedProfilerDependencies; + TryLoadManagedAssembly(); + } + + internal static string ManagedProfilerDirectory { get; } + + private static void TryLoadManagedAssembly() + { + try + { + var assembly = Assembly.Load("Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"); + + if (assembly != null) + { + // call method Datadog.Trace.ClrProfiler.Instrumentation.Initialize() + var type = assembly.GetType("Datadog.Trace.ClrProfiler.Instrumentation", throwOnError: false); + var method = type?.GetRuntimeMethod("Initialize", parameters: new Type[0]); + method?.Invoke(obj: null, parameters: null); + } + } + catch (Exception ex) + { + StartupLogger.Log(ex, "Error when loading managed assemblies."); + } + } + + private static string ReadEnvironmentVariable(string key) + { + try + { + return Environment.GetEnvironmentVariable(key); + } + catch (Exception ex) + { + StartupLogger.Log(ex, "Error while loading environment variable " + key); + } + + return null; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed.Loader/StartupLogger.cs b/src/Datadog.Trace.ClrProfiler.Managed.Loader/StartupLogger.cs new file mode 100644 index 0000000000..a4c06c4f7c --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed.Loader/StartupLogger.cs @@ -0,0 +1,167 @@ +using System; +using System.Diagnostics; +using System.IO; + +namespace Datadog.Trace.ClrProfiler.Managed.Loader +{ + internal static class StartupLogger + { + private const string NixDefaultDirectory = "/var/log/datadog/dotnet"; + + private static readonly bool DebugEnabled = IsDebugEnabled(); + private static readonly string LogDirectory = GetLogDirectory(); + private static readonly string StartupLogFilePath = SetStartupLogFilePath(); + + public static void Log(string message, params object[] args) + { + try + { + if (StartupLogFilePath != null) + { + try + { + using (var fileSink = new FileSink(StartupLogFilePath)) + { + fileSink.Info($"[{DateTime.UtcNow}] {message}{Environment.NewLine}", args); + } + + return; + } + catch + { + // ignore + } + } + + Console.Error.WriteLine(message, args); + } + catch + { + // ignore + } + } + + public static void Log(Exception ex, string message, params object[] args) + { + message = $"{message}{Environment.NewLine}{ex}"; + Log(message, args); + } + + public static void Debug(string message, params object[] args) + { + if (DebugEnabled) + { + Log(message, args); + } + } + + private static string GetLogDirectory() + { + string logDirectory = null; + + try + { + var nativeLogFile = Environment.GetEnvironmentVariable("DD_TRACE_LOG_PATH"); + + if (!string.IsNullOrEmpty(nativeLogFile)) + { + logDirectory = Path.GetDirectoryName(nativeLogFile); + } + + if (logDirectory == null) + { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + var windowsDefaultDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Datadog .NET Tracer", "logs"); + logDirectory = windowsDefaultDirectory; + } + else + { + // Linux + logDirectory = NixDefaultDirectory; + } + } + + logDirectory = CreateDirectoryIfMissing(logDirectory) ?? Path.GetTempPath(); + } + catch + { + // The try block may throw a SecurityException if not granted the System.Security.Permissions.FileIOPermission + // because of the following API calls + // - Directory.Exists + // - Environment.GetFolderPath + // - Path.GetTempPath + + // Unsafe to log + logDirectory = null; + } + + return logDirectory; + } + + private static string CreateDirectoryIfMissing(string pathToCreate) + { + try + { + Directory.CreateDirectory(pathToCreate); + return pathToCreate; + } + catch + { + // Unable to create the directory meaning that the user will have to create it on their own. + // It is unsafe to log here, so return null to defer deciding what the path is + return null; + } + } + + private static string SetStartupLogFilePath() + { + if (LogDirectory == null) + { + return null; + } + + try + { + var process = Process.GetCurrentProcess(); + // Do our best to not block other processes on write + return Path.Combine(LogDirectory, $"dotnet-tracer-loader-{process.ProcessName}-{process.Id}.log"); + } + catch + { + // We can't get the process info + return Path.Combine(LogDirectory, "dotnet-tracer-loader.log"); + } + } + + private static bool IsDebugEnabled() + { + try + { + var ddTraceDebugValue = Environment.GetEnvironmentVariable("DD_TRACE_DEBUG"); + + if (ddTraceDebugValue == null) + { + return false; + } + + switch (ddTraceDebugValue.ToUpperInvariant()) + { + case "TRUE": + case "YES": + case "Y": + case "T": + case "1": + return true; + default: + return false; + } + } + catch + { + // Default to not enabled + return false; + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/AssemblyInfo.cs b/src/Datadog.Trace.ClrProfiler.Managed/AssemblyInfo.cs new file mode 100644 index 0000000000..3409cbf525 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("System.Web.Mvc, PublicKey=0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.Managed.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj b/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj new file mode 100644 index 0000000000..244ca95c30 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj @@ -0,0 +1,52 @@ + + + + Datadog.Trace.ClrProfiler + + + 1.19.1 + Datadog APM - ClrProfiler + +DEPRECATED. This package exists only for backwards compatibility. If your project references this package ("Datadog.Trace.ClrProfiler.Managed") or "Datadog.Trace.AspNet", you can remove them both. + +.NET Core applications no longer require any NuGet package to enable automatic instrumentation. + +Automatic instrumentation for both ASP.NET and ASP.NET Core is now automatically enabled. + +Users who need manual instrumentation should reference the "Datadog.Trace" package. + + + + false + $(NoWarn);NU5128 + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj.DotSettings b/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj.DotSettings new file mode 100644 index 0000000000..4fb6a5c6ea --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj.DotSettings @@ -0,0 +1,5 @@ + + False + True + True + True \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Managed/DynamicMethodBuilder.cs b/src/Datadog.Trace.ClrProfiler.Managed/DynamicMethodBuilder.cs new file mode 100644 index 0000000000..aa69971c79 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/DynamicMethodBuilder.cs @@ -0,0 +1,63 @@ +using System; +using System.Reflection.Emit; +using Datadog.Trace.ClrProfiler.Emit; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Helper class to instances of using . + /// + /// The type of delegate + [Obsolete("This type will be removed in a future version of this library.")] + public static class DynamicMethodBuilder + where TDelegate : Delegate + { + /// + /// Memoizes CreateMethodCallDelegate + /// + /// The that contains the method. + /// The name of the method. + /// The method's return type. + /// optional types for the method parameters + /// optional generic type arguments for a generic method + /// A that can be used to execute the dynamic method. + public static TDelegate GetOrCreateMethodCallDelegate( + Type type, + string methodName, + Type returnType = null, + Type[] methodParameterTypes = null, + Type[] methodGenericArguments = null) + { + return Emit.DynamicMethodBuilder.GetOrCreateMethodCallDelegate( + type, + methodName, + OpCodeValue.Callvirt, + returnType, + methodParameterTypes, + methodGenericArguments); + } + + /// + /// Creates a simple using that + /// calls a method with the specified name and parameter types. + /// + /// The that contains the method to call when the returned delegate is executed.. + /// The name of the method to call when the returned delegate is executed. + /// If not null, use method overload that matches the specified parameters. + /// If not null, use method overload that has the same number of generic arguments. + /// A that can be used to execute the dynamic method. + public static TDelegate CreateMethodCallDelegate( + Type type, + string methodName, + Type[] methodParameterTypes = null, + Type[] methodGenericArguments = null) + { + return Emit.DynamicMethodBuilder.CreateMethodCallDelegate( + type, + methodName, + OpCodeValue.Callvirt, + methodParameterTypes, + methodGenericArguments); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/DelegateMetadata.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/DelegateMetadata.cs new file mode 100644 index 0000000000..f0cc87d035 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/DelegateMetadata.cs @@ -0,0 +1,52 @@ +using System; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + internal class DelegateMetadata + { + public Type Type { get; set; } + + public Type ReturnType { get; set; } + + public Type[] Generics { get; set; } + + public Type[] Parameters { get; set; } + + public static DelegateMetadata Create() + where TDelegate : System.Delegate + { + Type delegateType = typeof(TDelegate); + Type[] genericTypeArguments = delegateType.GenericTypeArguments; + + Type[] parameterTypes; + Type returnType; + + if (delegateType.Name.StartsWith("Func`")) + { + // last generic type argument is the return type + int parameterCount = genericTypeArguments.Length - 1; + parameterTypes = new Type[parameterCount]; + Array.Copy(genericTypeArguments, parameterTypes, parameterCount); + + returnType = genericTypeArguments[parameterCount]; + } + else if (delegateType.Name.StartsWith("Action`")) + { + parameterTypes = genericTypeArguments; + returnType = typeof(void); + } + else + { + throw new Exception($"Only Func<> or Action<> are supported in {nameof(DelegateMetadata)}."); + } + + return new DelegateMetadata() + { + Generics = genericTypeArguments, + Parameters = parameterTypes, + ReturnType = returnType, + Type = delegateType + }; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/DynamicMethodBuilder.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/DynamicMethodBuilder.cs new file mode 100644 index 0000000000..9564fb5ec7 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/DynamicMethodBuilder.cs @@ -0,0 +1,327 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using Sigil; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + /// + /// Helper class to create instances of using . + /// + /// The type of delegate + internal static class DynamicMethodBuilder + where TDelegate : Delegate + { + private static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(new KeyComparer()); + + /// + /// Gets a previously cache delegate used to call the specified method, + /// or creates and caches a new delegate if not found. + /// + /// The that contains the method. + /// The name of the method. + /// The OpCode to use in the method call. + /// The method's return type. + /// optional types for the method parameters + /// optional generic type arguments for a generic method + /// A that can be used to execute the dynamic method. + public static TDelegate GetOrCreateMethodCallDelegate( + Type type, + string methodName, + OpCodeValue callOpCode, + Type returnType = null, + Type[] methodParameterTypes = null, + Type[] methodGenericArguments = null) + { + return Cache.GetOrAdd( + new Key(type, methodName, callOpCode, returnType, methodParameterTypes, methodGenericArguments), + key => CreateMethodCallDelegate( + key.Type, + key.MethodName, + key.CallOpCode, + key.MethodParameterTypes, + key.MethodGenericArguments)); + } + + /// + /// Creates a simple using that + /// calls a method with the specified name and parameter types. + /// + /// The that contains the method to call when the returned delegate is executed.. + /// The name of the method to call when the returned delegate is executed. + /// The OpCode to use in the method call. + /// If not null, use method overload that matches the specified parameters. + /// If not null, use method overload that has the same number of generic arguments. + /// A that can be used to execute the dynamic method. + public static TDelegate CreateMethodCallDelegate( + Type type, + string methodName, + OpCodeValue callOpCode, + Type[] methodParameterTypes = null, + Type[] methodGenericArguments = null) + { + Type delegateType = typeof(TDelegate); + Type[] genericTypeArguments = delegateType.GenericTypeArguments; + + Type[] parameterTypes; + Type returnType; + + if (delegateType.Name.StartsWith("Func`")) + { + // last generic type argument is the return type + int parameterCount = genericTypeArguments.Length - 1; + parameterTypes = new Type[parameterCount]; + Array.Copy(genericTypeArguments, parameterTypes, parameterCount); + + returnType = genericTypeArguments[parameterCount]; + } + else if (delegateType.Name.StartsWith("Action`")) + { + parameterTypes = genericTypeArguments; + returnType = typeof(void); + } + else + { + throw new Exception($"Only Func<> or Action<> are supported in {nameof(CreateMethodCallDelegate)}."); + } + + // find any method that matches by name and parameter types + IEnumerable methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) + .Where(m => m.Name == methodName); + + // if methodParameterTypes was specified, check for a method that matches + if (methodParameterTypes != null) + { + methods = methods.Where( + m => + { + var ps = m.GetParameters(); + if (ps.Length != methodParameterTypes.Length) + { + return false; + } + + for (var i = 0; i < ps.Length; i++) + { + var t1 = ps[i].ParameterType; + var t2 = methodParameterTypes[i]; + + // generics can be tricky to compare for type equality + // so we will just check the namespace and name + if (t1.Namespace != t2.Namespace || t1.Name != t2.Name) + { + return false; + } + } + + return true; + }); + } + + if (methodGenericArguments != null) + { + methods = methods.Where( + m => m.IsGenericMethodDefinition && + m.GetGenericArguments().Length == methodGenericArguments.Length); + } + + MethodInfo methodInfo = methods.FirstOrDefault(); + if (methodInfo == null) + { + // method not found + // TODO: logging + return null; + } + + if (methodGenericArguments != null) + { + methodInfo = methodInfo.MakeGenericMethod(methodGenericArguments); + } + + Type[] effectiveParameterTypes; + + IEnumerable reflectedParameterTypes = methodInfo.GetParameters() + .Select(p => p.ParameterType); + if (methodInfo.IsStatic) + { + effectiveParameterTypes = reflectedParameterTypes.ToArray(); + } + else + { + // for instance methods, insert object's type as first element in array + effectiveParameterTypes = new[] { type } + .Concat(reflectedParameterTypes) + .ToArray(); + } + + Emit dynamicMethod = Emit.NewDynamicMethod(methodInfo.Name); + + // load each argument and cast or unbox as necessary + for (ushort argumentIndex = 0; argumentIndex < parameterTypes.Length; argumentIndex++) + { + Type delegateParameterType = parameterTypes[argumentIndex]; + Type underlyingParameterType = effectiveParameterTypes[argumentIndex]; + + dynamicMethod.LoadArgument(argumentIndex); + + if (underlyingParameterType.IsValueType && delegateParameterType == typeof(object)) + { + dynamicMethod.UnboxAny(underlyingParameterType); + } + else if (underlyingParameterType != delegateParameterType) + { + dynamicMethod.CastClass(underlyingParameterType); + } + } + + if (callOpCode == OpCodeValue.Call || methodInfo.IsStatic) + { + // non-virtual call (e.g. static method, or method override calling overriden implementation) + dynamicMethod.Call(methodInfo); + } + else if (callOpCode == OpCodeValue.Callvirt) + { + // Note: C# compiler uses CALLVIRT for non-virtual + // instance methods to get the cheap null check + dynamicMethod.CallVirtual(methodInfo); + } + else + { + throw new NotSupportedException($"OpCode {callOpCode} not supported when calling a method."); + } + + if (methodInfo.ReturnType.IsValueType && returnType == typeof(object)) + { + dynamicMethod.Box(methodInfo.ReturnType); + } + else if (methodInfo.ReturnType != returnType) + { + dynamicMethod.CastClass(returnType); + } + + dynamicMethod.Return(); + return dynamicMethod.CreateDelegate(); + } + + private struct Key + { + public readonly Type Type; + public readonly string MethodName; + public readonly OpCodeValue CallOpCode; + public readonly Type ReturnType; + public readonly Type[] MethodParameterTypes; + public readonly Type[] MethodGenericArguments; + + public Key(Type type, string methodName, OpCodeValue callOpCode, Type returnType, Type[] methodParameterTypes, Type[] methodGenericArguments) + { + Type = type; + MethodName = methodName; + CallOpCode = callOpCode; + ReturnType = returnType; + MethodParameterTypes = methodParameterTypes; + MethodGenericArguments = methodGenericArguments; + } + } + + private class KeyComparer : IEqualityComparer + { + public bool Equals(Key x, Key y) + { + if (!object.Equals(x.Type, y.Type)) + { + return false; + } + + if (!object.Equals(x.MethodName, y.MethodName)) + { + return false; + } + + if (!object.Equals(x.CallOpCode, y.CallOpCode)) + { + return false; + } + + if (!object.Equals(x.ReturnType, y.ReturnType)) + { + return false; + } + + if (!ArrayEquals(x.MethodParameterTypes, y.MethodParameterTypes)) + { + return false; + } + + if (!ArrayEquals(x.MethodGenericArguments, y.MethodGenericArguments)) + { + return false; + } + + return true; + } + + public int GetHashCode(Key obj) + { + unchecked + { + int hash = 17; + + if (obj.Type != null) + { + hash = (hash * 23) + obj.Type.GetHashCode(); + } + + if (obj.MethodName != null) + { + hash = (hash * 23) + obj.MethodName.GetHashCode(); + } + + hash = (hash * 23) + obj.CallOpCode.GetHashCode(); + + if (obj.MethodParameterTypes != null) + { + foreach (var t in obj.MethodParameterTypes) + { + if (t != null) + { + hash = (hash * 23) + t.GetHashCode(); + } + } + } + + if (obj.MethodGenericArguments != null) + { + foreach (var t in obj.MethodGenericArguments) + { + if (t != null) + { + hash = (hash * 23) + t.GetHashCode(); + } + } + } + + return hash; + } + } + + private static bool ArrayEquals(T[] array1, T[] array2) + { + if (array1 == null && array2 == null) + { + return true; + } + + if (array1 == null || array2 == null) + { + return false; + } + + return ((IStructuralEquatable)array1).Equals(array2, EqualityComparer.Default); + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/MemberResult.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/MemberResult.cs new file mode 100644 index 0000000000..54716a4815 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/MemberResult.cs @@ -0,0 +1,87 @@ +using System; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + internal readonly struct MemberResult + { + /// + /// A static value used to represent a member that was not found. + /// + public static readonly MemberResult NotFound = default; + + public readonly bool HasValue; + + private readonly T _value; + + public MemberResult(T value) + { + _value = value; + HasValue = true; + } + + public T Value => + HasValue + ? _value + : throw new InvalidOperationException("Reflected member not found."); + + public T GetValueOrDefault() + { + return _value; + } + + public MemberResult GetProperty(string propertyName) + { + if (!HasValue || Value == null || !Value.TryGetPropertyValue(propertyName, out TResult result)) + { + return MemberResult.NotFound; + } + + return new MemberResult(result); + } + + public MemberResult GetProperty(string propertyName) + { + return GetProperty(propertyName); + } + + public MemberResult GetField(string fieldName) + { + if (!HasValue || Value == null || !Value.TryGetFieldValue(fieldName, out TResult result)) + { + return MemberResult.NotFound; + } + + return new MemberResult(result); + } + + public MemberResult GetField(string fieldName) + { + return GetField(fieldName); + } + + public MemberResult CallMethod(string methodName, TArg1 arg1) + { + if (!HasValue || Value == null || !Value.TryCallMethod(methodName, arg1, out TResult result)) + { + return MemberResult.NotFound; + } + + return new MemberResult(result); + } + + public MemberResult CallMethod(string methodName, TArg1 arg1) + { + return CallMethod(methodName, arg1); + } + + public override string ToString() + { + if (!HasValue || Value == null) + { + return string.Empty; + } + + return Value.ToString(); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/MethodBuilder.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/MethodBuilder.cs new file mode 100644 index 0000000000..2a358b9894 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/MethodBuilder.cs @@ -0,0 +1,810 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Configuration; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; +using Sigil; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + internal class MethodBuilder + { + /// + /// Global dictionary for caching reflected delegates + /// + private static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(new KeyComparer()); + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(MethodBuilder)); + + private static readonly Type[] EmptyTypeArray = new Type[0]; + + /// + /// Feature flag used primarily for forcing testing of the token lookup strategy. + /// + // ReSharper disable once StaticMemberInGenericType + private static readonly bool ForceMdTokenLookup; + + /// + /// Feature flag used primarily for forcing testing of the fallback lookup strategy. + /// + // ReSharper disable once StaticMemberInGenericType + private static readonly bool ForceFallbackLookup; + + private readonly Module _resolutionModule; + private readonly int _mdToken; + private readonly int _originalOpCodeValue; + private readonly OpCodeValue _opCode; + private readonly string _methodName; + private readonly Guid? _moduleVersionId; + + private Type _returnType; + private MethodBase _methodBase; + private Type _concreteType; + private string _concreteTypeName; + private Type[] _parameters = EmptyTypeArray; + private Type[] _explicitParameterTypes = null; + private string[] _namespaceAndNameFilter = null; + private Type[] _declaringTypeGenerics; + private Type[] _methodGenerics; + private bool _forceMethodDefResolve; + + static MethodBuilder() + { + ForceMdTokenLookup = bool.TryParse(EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.Debug.ForceMdTokenLookup), out bool result) + ? result + : false; + ForceFallbackLookup = bool.TryParse(EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.Debug.ForceFallbackLookup), out result) + ? result && !ForceMdTokenLookup + : false; + } + + private MethodBuilder(Guid moduleVersionId, int mdToken, int opCode, string methodName) + : this(ModuleLookup.Get(moduleVersionId), mdToken, opCode, methodName) + { + // Save the Guid for logging purposes + _moduleVersionId = moduleVersionId; + } + + private MethodBuilder(Module resolutionModule, int mdToken, int opCode, string methodName) + { + _resolutionModule = resolutionModule; + _mdToken = mdToken; + _opCode = (OpCodeValue)opCode; + _originalOpCodeValue = opCode; + _methodName = methodName; + _forceMethodDefResolve = false; + } + + public static MethodBuilder Start(Guid moduleVersionId, int mdToken, int opCode, string methodName) + { + return new MethodBuilder(moduleVersionId, mdToken, opCode, methodName); + } + + public static MethodBuilder Start(Module module, int mdToken, int opCode, string methodName) + { + return new MethodBuilder( + module, + mdToken, + opCode, + methodName); + } + + public static MethodBuilder Start(long moduleVersionPtr, int mdToken, int opCode, string methodName) + { + return new MethodBuilder( + PointerHelpers.GetGuidFromNativePointer(moduleVersionPtr), + mdToken, + opCode, + methodName); + } + + public MethodBuilder WithConcreteType(Type type) + { + _concreteType = type; + _concreteTypeName = type?.FullName; + return this; + } + + public MethodBuilder WithNamespaceAndNameFilters(params string[] namespaceNameFilters) + { + _namespaceAndNameFilter = namespaceNameFilters; + return this; + } + + public MethodBuilder WithParameters(params Type[] parameters) + { + if (parameters == null) + { + throw new ArgumentNullException(nameof(parameters)); + } + + _parameters = parameters; + return this; + } + + public MethodBuilder WithParameters(params object[] parameters) + { + if (parameters == null) + { + throw new ArgumentNullException(nameof(parameters)); + } + + return WithParameters(Interception.ParamsToTypes(parameters)); + } + + public MethodBuilder WithParameters(TParam param1) + { + var types = new[] { param1?.GetType() }; + + return WithParameters(types); + } + + public MethodBuilder WithParameters(TParam1 param1, TParam2 param2) + { + var types = new[] { param1?.GetType(), param2?.GetType() }; + + return WithParameters(types); + } + + public MethodBuilder WithParameters(TParam1 param1, TParam2 param2, TParam3 param3) + { + var types = new[] { param1?.GetType(), param2?.GetType(), param3?.GetType() }; + + return WithParameters(types); + } + + public MethodBuilder WithParameters(TParam1 param1, TParam2 param2, TParam3 param3, TParam4 param4) + { + var types = new[] { param1?.GetType(), param2?.GetType(), param3?.GetType(), param4?.GetType() }; + + return WithParameters(types); + } + + public MethodBuilder WithExplicitParameterTypes(params Type[] types) + { + _explicitParameterTypes = types; + return this; + } + + public MethodBuilder WithMethodGenerics(params Type[] generics) + { + _methodGenerics = generics; + return this; + } + + public MethodBuilder WithDeclaringTypeGenerics(params Type[] generics) + { + _declaringTypeGenerics = generics; + return this; + } + + public MethodBuilder ForceMethodDefinitionResolution() + { + _forceMethodDefResolve = true; + return this; + } + + public MethodBuilder WithReturnType(Type returnType) + { + _returnType = returnType; + return this; + } + + public TDelegate Build() + { + var cacheKey = new Key( + this, + callingModule: _resolutionModule); + + return Cache.GetOrAdd(cacheKey, key => + { + // Validate requirements at the last possible moment + // Don't do more than needed before checking the cache + key.Builder.ValidateRequirements(); + return key.Builder.EmitDelegate(); + }); + } + + private TDelegate EmitDelegate() + { + var requiresBestEffortMatching = false; + + if (_resolutionModule != null) + { + try + { + // Don't resolve until we build, as it may be an unnecessary lookup because of the cache + // We also may need the generics which were specified + if (_forceMethodDefResolve || (_declaringTypeGenerics == null && _methodGenerics == null)) + { + _methodBase = + _resolutionModule.ResolveMethod(metadataToken: _mdToken); + } + else + { + _methodBase = + _resolutionModule.ResolveMethod( + metadataToken: _mdToken, + genericTypeArguments: _declaringTypeGenerics, + genericMethodArguments: _methodGenerics); + } + } + catch (Exception ex) + { + var message = $"Unable to resolve method {_concreteTypeName}.{_methodName} by metadata token: {_mdToken}"; + Log.Error(ex, message); + requiresBestEffortMatching = true; + } + } + else + { + Log.Warning($"Unable to resolve module version id {_moduleVersionId}. Using method builder fallback."); + } + + MethodInfo methodInfo = null; + + if (!requiresBestEffortMatching && _methodBase is MethodInfo info) + { + if (info.IsGenericMethodDefinition) + { + info = MakeGenericMethod(info); + } + + methodInfo = VerifyMethodFromToken(info); + } + + if (methodInfo == null && ForceMdTokenLookup) + { + throw new Exception($"Unable to resolve method {_concreteTypeName}.{_methodName} by metadata token: {_mdToken}. Exiting because {nameof(ForceMdTokenLookup)}() is true."); + } + else if (methodInfo == null || ForceFallbackLookup) + { + // mdToken didn't work out, fallback + methodInfo = TryFindMethod(); + } + + Type delegateType = typeof(TDelegate); + Type[] delegateGenericArgs = delegateType.GenericTypeArguments; + + Type[] delegateParameterTypes; + Type returnType; + + if (delegateType.Name.StartsWith("Func`")) + { + // last generic type argument is the return type + int parameterCount = delegateGenericArgs.Length - 1; + delegateParameterTypes = new Type[parameterCount]; + Array.Copy(delegateGenericArgs, delegateParameterTypes, parameterCount); + + returnType = delegateGenericArgs[parameterCount]; + } + else if (delegateType.Name.StartsWith("Action`")) + { + delegateParameterTypes = delegateGenericArgs; + returnType = typeof(void); + } + else + { + throw new Exception($"Only Func<> or Action<> are supported in {nameof(MethodBuilder)}."); + } + + if (methodInfo.IsGenericMethodDefinition) + { + methodInfo = MakeGenericMethod(methodInfo); + } + + Type[] effectiveParameterTypes; + + var reflectedParameterTypes = + methodInfo.GetParameters().Select(p => p.ParameterType); + + if (methodInfo.IsStatic) + { + effectiveParameterTypes = reflectedParameterTypes.ToArray(); + } + else + { + // for instance methods, insert object's type as first element in array + effectiveParameterTypes = new[] { _concreteType } + .Concat(reflectedParameterTypes) + .ToArray(); + } + + var dynamicMethod = Emit.NewDynamicMethod(methodInfo.Name); + + // load each argument and cast or unbox as necessary + for (ushort argumentIndex = 0; argumentIndex < delegateParameterTypes.Length; argumentIndex++) + { + Type delegateParameterType = delegateParameterTypes[argumentIndex]; + Type underlyingParameterType = effectiveParameterTypes[argumentIndex]; + + dynamicMethod.LoadArgument(argumentIndex); + + if (underlyingParameterType.IsValueType && delegateParameterType == typeof(object)) + { + dynamicMethod.UnboxAny(underlyingParameterType); + } + else if (underlyingParameterType != delegateParameterType) + { + dynamicMethod.CastClass(underlyingParameterType); + } + } + + if (_opCode == OpCodeValue.Call || methodInfo.IsStatic) + { + // non-virtual call (e.g. static method, or method override calling overriden implementation) + dynamicMethod.Call(methodInfo); + } + else if (_opCode == OpCodeValue.Callvirt) + { + // Note: C# compiler uses CALLVIRT for non-virtual + // instance methods to get the cheap null check + dynamicMethod.CallVirtual(methodInfo); + } + else + { + throw new NotSupportedException($"OpCode {_originalOpCodeValue} not supported when calling a method."); + } + + if (methodInfo.ReturnType.IsValueType && returnType == typeof(object)) + { + dynamicMethod.Box(methodInfo.ReturnType); + } + else if (methodInfo.ReturnType != returnType) + { + dynamicMethod.CastClass(returnType); + } + + dynamicMethod.Return(); + return dynamicMethod.CreateDelegate(); + } + + private MethodInfo MakeGenericMethod(MethodInfo methodInfo) + { + if (_methodGenerics == null || _methodGenerics.Length == 0) + { + throw new ArgumentException($"Must specify {nameof(_methodGenerics)} for a generic method."); + } + + return methodInfo.MakeGenericMethod(_methodGenerics); + } + + private MethodInfo VerifyMethodFromToken(MethodInfo methodInfo) + { + // Verify baselines to ensure this isn't the wrong method somehow + var detailMessage = $"Unexpected method: {_concreteTypeName}.{_methodName} received for mdToken: {_mdToken} in module: {_resolutionModule?.FullyQualifiedName ?? "NULL"}, {_resolutionModule?.ModuleVersionId ?? _moduleVersionId}"; + + if (!string.Equals(_methodName, methodInfo.Name)) + { + Log.Warning($"Method name mismatch: {detailMessage}"); + return null; + } + + if (!GenericsAreViable(methodInfo)) + { + Log.Warning($"Generics not viable: {detailMessage}"); + return null; + } + + if (!ParametersAreViable(methodInfo)) + { + Log.Warning($"Parameters not viable: {detailMessage}"); + return null; + } + + return methodInfo; + } + + private void ValidateRequirements() + { + if (_concreteType == null) + { + throw new ArgumentException($"{nameof(_concreteType)} must be specified."); + } + + if (string.IsNullOrWhiteSpace(_methodName)) + { + throw new ArgumentException($"There must be a {nameof(_methodName)} specified to ensure fallback {nameof(TryFindMethod)} is viable."); + } + + if (_namespaceAndNameFilter != null && _namespaceAndNameFilter.Length != _parameters.Length + 1) + { + throw new ArgumentException($"The length of {nameof(_namespaceAndNameFilter)} must match the length of {nameof(_parameters)} + 1 for the return type."); + } + + if (_explicitParameterTypes != null) + { + if (_explicitParameterTypes.Length != _parameters.Length) + { + throw new ArgumentException($"The {nameof(_explicitParameterTypes)} must match the {_parameters} count."); + } + + for (var i = 0; i < _explicitParameterTypes.Length; i++) + { + var explicitType = _explicitParameterTypes[i]; + var parameterType = _parameters[i]; + + if (parameterType == null) + { + // Nothing to check + continue; + } + + if (!explicitType.IsAssignableFrom(parameterType)) + { + throw new ArgumentException($"Parameter Index {i}: Explicit type {explicitType.FullName} is not assignable from {parameterType}"); + } + } + } + } + + private MethodInfo TryFindMethod() + { + var logDetail = $"mdToken {_mdToken} on {_concreteTypeName}.{_methodName} in {_resolutionModule?.FullyQualifiedName ?? "NULL"}, {_resolutionModule?.ModuleVersionId ?? _moduleVersionId}"; + Log.Warning($"Using fallback method matching ({logDetail})"); + + var statsd = Tracer.Instance.Statsd; + + if (statsd != null) + { + string[] tags = { $"instrumented-method:{_concreteTypeName}.{_methodName}" }; + statsd.AppendWarning(source: $"{nameof(MethodBuilder)}.{nameof(TryFindMethod)}", message: "Using fallback method matching", tags); + statsd.Send(); + } + + var methods = + _concreteType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + + // A legacy fallback attempt to match on the concrete type + methods = + methods + .Where(mi => mi.Name == _methodName && (_returnType == null || mi.ReturnType == _returnType)) + .ToArray(); + + var matchesOnNameAndReturn = methods.Length; + + if (_namespaceAndNameFilter != null) + { + methods = methods.Where(m => + { + var parameters = m.GetParameters(); + + if ((parameters.Length + 1) != _namespaceAndNameFilter.Length) + { + return false; + } + + var typesToCheck = new Type[] { m.ReturnType }.Concat(m.GetParameters().Select(p => p.ParameterType)).ToArray(); + for (var i = 0; i < typesToCheck.Length; i++) + { + if (_namespaceAndNameFilter[i] == ClrNames.Ignore) + { + // Allow for not specifying + continue; + } + + if ($"{typesToCheck[i].Namespace}.{typesToCheck[i].Name}" != _namespaceAndNameFilter[i]) + { + return false; + } + } + + return true; + }).ToArray(); + } + + if (methods.Length == 1) + { + Log.Information($"Resolved by name and namespaceName filters ({logDetail})"); + return methods[0]; + } + + methods = + methods + .Where(ParametersAreViable) + .ToArray(); + + if (methods.Length == 1) + { + Log.Information($"Resolved by viable parameters ({logDetail})"); + return methods[0]; + } + + methods = + methods + .Where(GenericsAreViable) + .ToArray(); + + if (methods.Length == 1) + { + Log.Information($"Resolved by viable generics ({logDetail})"); + return methods[0]; + } + + // Attempt to trim down further + methods = methods.Where(ParametersAreExact).ToArray(); + + if (methods.Length > 1) + { + throw new ArgumentException($"Unable to safely resolve method, found {methods.Length} matches ({logDetail})"); + } + + var methodInfo = methods.SingleOrDefault(); + + if (methodInfo == null) + { + throw new ArgumentException($"Unable to resolve method, started with {matchesOnNameAndReturn} by name match ({logDetail})"); + } + + return methodInfo; + } + + private bool ParametersAreViable(MethodInfo mi) + { + var parameters = mi.GetParameters(); + + if (parameters.Length != _parameters.Length) + { + // expected parameters don't match actual count + return false; + } + + for (var i = 0; i < parameters.Length; i++) + { + var candidateParameter = parameters[i]; + + var parameterType = candidateParameter.ParameterType; + + var expectedParameterType = GetExpectedParameterTypeByIndex(i); + + if (expectedParameterType == null) + { + // Skip the rest of this check, as we can't know the type + continue; + } + + if (parameterType.IsGenericParameter) + { + // This requires different evaluation + if (MeetsGenericArgumentRequirements(parameterType, expectedParameterType)) + { + // Good to go + continue; + } + + // We didn't meet this generic argument's requirements + return false; + } + + if (!parameterType.IsAssignableFrom(expectedParameterType)) + { + return false; + } + } + + return true; + } + + private bool ParametersAreExact(MethodInfo mi) + { + // We can already assume that the counts match by this point + var parameters = mi.GetParameters(); + + for (var i = 0; i < parameters.Length; i++) + { + var candidateParameter = parameters[i]; + + var parameterType = candidateParameter.ParameterType; + + var actualArgumentType = GetExpectedParameterTypeByIndex(i); + + if (actualArgumentType == null) + { + // Skip the rest of this check, as we can't know the type + continue; + } + + if (parameterType != actualArgumentType) + { + return false; + } + } + + return true; + } + + private Type GetExpectedParameterTypeByIndex(int i) + { + return _explicitParameterTypes != null + ? _explicitParameterTypes[i] + : _parameters[i]; + } + + private bool GenericsAreViable(MethodInfo mi) + { + // Non-Generic Method - { IsGenericMethod: false, ContainsGenericParameters: false, IsGenericMethodDefinition: false } + // Generic Method Definition - { IsGenericMethod: true, ContainsGenericParameters: true, IsGenericMethodDefinition: true } + // Open Constructed Method - { IsGenericMethod: true, ContainsGenericParameters: true, IsGenericMethodDefinition: false } + // Closed Constructed Method - { IsGenericMethod: true, ContainsGenericParameters: false, IsGenericMethodDefinition: false } + + if (_methodGenerics == null) + { + // We expect no generic arguments for this method + return mi.ContainsGenericParameters == false; + } + + if (!mi.IsGenericMethod) + { + // There is really nothing to compare here + // Make sure we aren't looking for generics where there aren't + return _methodGenerics?.Length == 0; + } + + var genericArgs = mi.GetGenericArguments(); + + if (genericArgs.Length != _methodGenerics.Length) + { + // Count of arguments mismatch + return false; + } + + foreach (var actualGenericArg in genericArgs) + { + if (actualGenericArg.IsGenericParameter) + { + var expectedGenericArg = _methodGenerics[actualGenericArg.GenericParameterPosition]; + + if (!MeetsGenericArgumentRequirements(actualGenericArg, expectedGenericArg)) + { + return false; + } + } + } + + return true; + } + + private bool MeetsGenericArgumentRequirements(Type actualGenericArg, Type expectedArg) + { + var constraints = actualGenericArg.GetGenericParameterConstraints(); + + if (constraints.Any(constraint => !constraint.IsAssignableFrom(expectedArg))) + { + // We have failed to meet a constraint + return false; + } + + return true; + } + + private struct Key + { + public readonly int CallingModuleMetadataToken; + public readonly MethodBuilder Builder; + + public Key( + MethodBuilder builder, + Module callingModule) + { + Builder = builder; + CallingModuleMetadataToken = callingModule.MetadataToken; + } + + public Type[] ExplicitParams => Builder._explicitParameterTypes ?? Builder._parameters; + } + + private class KeyComparer : IEqualityComparer + { + public bool Equals(Key x, Key y) + { + if (x.CallingModuleMetadataToken != y.CallingModuleMetadataToken) + { + return false; + } + + var builder1 = x.Builder; + var builder2 = y.Builder; + + if (builder1._mdToken != builder2._mdToken) + { + return false; + } + + if (builder1._opCode != builder2._opCode) + { + return false; + } + + if (builder1._concreteType != builder2._concreteType) + { + return false; + } + + if (!ArrayEquals(x.ExplicitParams, y.ExplicitParams)) + { + return false; + } + + if (!ArrayEquals(builder1._methodGenerics, builder2._methodGenerics)) + { + return false; + } + + if (!ArrayEquals(builder1._declaringTypeGenerics, builder2._declaringTypeGenerics)) + { + return false; + } + + return true; + } + + public int GetHashCode(Key obj) + { + unchecked + { + var builder = obj.Builder; + + int hash = 17; + hash = (hash * 23) + obj.CallingModuleMetadataToken.GetHashCode(); + hash = (hash * 23) + builder._mdToken.GetHashCode(); + hash = (hash * 23) + ((short)builder._opCode).GetHashCode(); + hash = (hash * 23) + builder._concreteType.GetHashCode(); + hash = (hash * 23) + GetHashCode(builder._methodGenerics); + hash = (hash * 23) + GetHashCode(obj.ExplicitParams); + hash = (hash * 23) + GetHashCode(builder._declaringTypeGenerics); + return hash; + } + } + + private static int GetHashCode(Type[] array) + { + if (array == null) + { + return 0; + } + + int value = array.Length; + + for (int i = 0; i < array.Length; i++) + { + value = unchecked((value * 31) + array[i]?.GetHashCode() ?? 0); + } + + return value; + } + + private static bool ArrayEquals(Type[] array1, Type[] array2) + { + if (array1 == null) + { + return array2 == null; + } + + if (array2 == null) + { + return false; + } + + if (array1.Length != array2.Length) + { + return false; + } + + for (int i = 0; i < array1.Length; i++) + { + if (array1[i] != array2[i]) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/ModuleLookup.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/ModuleLookup.cs new file mode 100644 index 0000000000..2f5771d0bc --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/ModuleLookup.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Concurrent; +using System.Reflection; +using System.Threading; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + internal static class ModuleLookup + { + /// + /// Some naive upper limit to resolving assemblies that we can use to stop making expensive calls. + /// + private const int MaxFailures = 50; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ModuleLookup)); + + private static ManualResetEventSlim _populationResetEvent = new ManualResetEventSlim(initialState: true); + private static ConcurrentDictionary _modules = new ConcurrentDictionary(); + + private static int _failures = 0; + private static bool _shortCircuitLogicHasLogged = false; + + public static Module GetByPointer(long moduleVersionPointer) + { + return Get(PointerHelpers.GetGuidFromNativePointer(moduleVersionPointer)); + } + + public static Module Get(Guid moduleVersionId) + { + // First attempt at cached values with no blocking + if (_modules.TryGetValue(moduleVersionId, out Module value)) + { + return value; + } + + // Block if a population event is happening + _populationResetEvent.Wait(); + + // See if the previous population event populated what we need + if (_modules.TryGetValue(moduleVersionId, out value)) + { + return value; + } + + if (_failures >= MaxFailures) + { + // For some unforeseeable reason we have failed on a lot of AppDomain lookups + if (!_shortCircuitLogicHasLogged) + { + Log.Warning("Datadog is unable to continue attempting module lookups for this AppDomain. Falling back to legacy method lookups."); + } + + return null; + } + + // Block threads on this event + _populationResetEvent.Reset(); + + try + { + PopulateModules(); + } + catch (Exception ex) + { + _failures++; + Log.Error(ex, "Error when populating modules."); + } + finally + { + // Continue threads blocked on this event + _populationResetEvent.Set(); + } + + _modules.TryGetValue(moduleVersionId, out value); + + return value; + } + + private static void PopulateModules() + { + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) + { + foreach (var module in assembly.Modules) + { + _modules.TryAdd(module.ModuleVersionId, module); + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/ObjectExtensions.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/ObjectExtensions.cs new file mode 100644 index 0000000000..6112cefa63 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/ObjectExtensions.cs @@ -0,0 +1,360 @@ +using System; +using System.Collections.Concurrent; +using System.Reflection; +using Datadog.Trace.Util; +using Sigil; + +namespace Datadog.Trace.ClrProfiler.Emit +{ + /// + /// Provides helper methods to access object members by emitting IL dynamically. + /// + internal static class ObjectExtensions + { + private static readonly ConcurrentDictionary Cache = new ConcurrentDictionary(); + private static readonly ConcurrentDictionary PropertyFetcherCache = new ConcurrentDictionary(); + + /// + /// Tries to call an instance method with the specified name, a single parameter, and a return value. + /// + /// The type of the method's single parameter. + /// The type of the method's result value. + /// The object to call the method on. + /// The name of the method to call. + /// The value to pass as the method's single argument. + /// The value returned by the method. + /// true if the method was found, false otherwise. + public static bool TryCallMethod(this object source, string methodName, TArg1 arg1, out TResult value) + { + var type = source.GetType(); + var paramType1 = typeof(TArg1); + + object cachedItem = Cache.GetOrAdd( + new PropertyFetcherCacheKey(type, paramType1, methodName), + key => + DynamicMethodBuilder> + .CreateMethodCallDelegate( + key.Type1, + key.Name, + OpCodeValue.Callvirt, + methodParameterTypes: new[] { key.Type2 })); + + if (cachedItem is Func func) + { + value = func(source, arg1); + return true; + } + + value = default; + return false; + } + + /// + /// Tries to call an instance method with the specified name, two parameters, and no return value. + /// + /// The type of the method's first parameter. + /// The type of the method's second parameter. + /// The object to call the method on. + /// The name of the method to call. + /// The value to pass as the method's first argument. + /// The value to pass as the method's second argument. + /// true if the method was found, false otherwise. + public static bool TryCallVoidMethod(this object source, string methodName, TArg1 arg1, TArg2 arg2) + { + var type = source.GetType(); + var paramType1 = typeof(TArg1); + var paramType2 = typeof(TArg2); + + object cachedItem = Cache.GetOrAdd( + new PropertyFetcherCacheKey(type, paramType1, paramType2, methodName), + key => + DynamicMethodBuilder> + .CreateMethodCallDelegate( + key.Type1, + key.Name, + OpCodeValue.Callvirt, + methodParameterTypes: new[] { key.Type2, key.Type3 })); + + if (cachedItem is Action func) + { + func(source, arg1, arg2); + return true; + } + + return false; + } + + /// + /// Tries to call an instance method with the specified name and a return value. + /// + /// The type of the method's result value. + /// The object to call the method on. + /// The name of the method to call. + /// The value returned by the method. + /// true if the method was found, false otherwise. + public static bool TryCallMethod(this object source, string methodName, out TResult value) + { + var type = source.GetType(); + + object cachedItem = Cache.GetOrAdd( + new PropertyFetcherCacheKey(type, null, methodName), + key => + DynamicMethodBuilder> + .CreateMethodCallDelegate( + key.Type1, + key.Name, + OpCodeValue.Callvirt)); + + if (cachedItem is Func func) + { + value = func(source); + return true; + } + + value = default; + return false; + } + + public static MemberResult CallMethod(this object source, string methodName, TArg1 arg1) + { + return source.TryCallMethod(methodName, arg1, out TResult result) + ? new MemberResult(result) + : MemberResult.NotFound; + } + + public static MemberResult CallMethod(this object source, string methodName, TArg1 arg1) + { + return CallMethod(source, methodName, arg1); + } + + public static MemberResult CallMethod(this object source, string methodName) + { + return source.TryCallMethod(methodName, out TResult result) + ? new MemberResult(result) + : MemberResult.NotFound; + } + + public static MemberResult CallVoidMethod(this object source, string methodName, TArg1 arg1, TArg2 arg2) + { + return source.TryCallVoidMethod(methodName, arg1, arg2) + ? new MemberResult(null) + : MemberResult.NotFound; + } + + /// + /// Tries to get the value of an instance property with the specified name. + /// + /// The type of the property. + /// The value that contains the property. + /// The name of the property. + /// The value of the property, or null if the property is not found. + /// true if the property exists, otherwise false. + public static bool TryGetPropertyValue(this object source, string propertyName, out TResult value) + { + if (source != null) + { + var type = source.GetType(); + + PropertyFetcher fetcher = PropertyFetcherCache.GetOrAdd( + GetKey(propertyName, type), + key => new PropertyFetcher(key.Name)); + + if (fetcher != null) + { + value = fetcher.Fetch(source, type); + return true; + } + } + + value = default; + return false; + } + + public static MemberResult GetProperty(this object source, string propertyName) + { + if (source == null) + { + return MemberResult.NotFound; + } + + return source.TryGetPropertyValue(propertyName, out TResult result) + ? new MemberResult(result) + : MemberResult.NotFound; + } + + public static MemberResult GetProperty(this object source, string propertyName) + { + return GetProperty(source, propertyName); + } + + /// + /// Tries to get the value of an instance field with the specified name. + /// + /// The type of the field. + /// The value that contains the field. + /// The name of the field. + /// The value of the field, or null if the field is not found. + /// true if the field exists, otherwise false. + public static bool TryGetFieldValue(this object source, string fieldName, out TResult value) + { + var type = source.GetType(); + + object cachedItem = Cache.GetOrAdd( + GetKey(fieldName, type), + key => CreateFieldDelegate(key.Type1, key.Name)); + + if (cachedItem is Func func) + { + value = func(source); + return true; + } + + value = default; + return false; + } + + public static MemberResult GetField(this object source, string fieldName) + { + return source.TryGetFieldValue(fieldName, out TResult result) + ? new MemberResult(result) + : MemberResult.NotFound; + } + + public static MemberResult GetField(this object source, string fieldName) + { + return GetField(source, fieldName); + } + + private static PropertyFetcherCacheKey GetKey(string name, Type type) + { + return new PropertyFetcherCacheKey(type, typeof(TResult), name); + } + + private static Func CreatePropertyDelegate(Type containerType, string propertyName) + { + PropertyInfo propertyInfo = containerType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (propertyInfo == null) + { + return null; + } + + var dynamicMethod = Emit>.NewDynamicMethod($"{containerType.FullName}.get_{propertyName}"); + dynamicMethod.LoadArgument(0); + + if (containerType.IsValueType) + { + dynamicMethod.Unbox(containerType); + } + else + { + dynamicMethod.CastClass(containerType); + } + + MethodInfo methodInfo = propertyInfo.GetMethod; + + if (methodInfo.IsStatic) + { + dynamicMethod.Call(methodInfo); + } + else + { + // C# compiler always uses CALLVIRT for instance methods + // to get the cheap null check, even if they are not virtual + dynamicMethod.CallVirtual(methodInfo); + } + + if (propertyInfo.PropertyType != typeof(TResult)) + { + if (propertyInfo.PropertyType.IsValueType) + { + dynamicMethod.Box(propertyInfo.PropertyType); + } + + dynamicMethod.CastClass(typeof(TResult)); + } + + dynamicMethod.Return(); + return dynamicMethod.CreateDelegate(); + } + + private static Func CreateFieldDelegate(Type containerType, string fieldName) + { + FieldInfo fieldInfo = containerType.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + + if (fieldInfo == null) + { + return null; + } + + var dynamicMethod = Emit>.NewDynamicMethod($"{containerType.FullName}.{fieldName}"); + dynamicMethod.LoadArgument(0); + + if (containerType.IsValueType) + { + dynamicMethod.UnboxAny(containerType); + } + else + { + dynamicMethod.CastClass(containerType); + } + + dynamicMethod.LoadField(fieldInfo); + + if (fieldInfo.FieldType.IsValueType && typeof(TResult) == typeof(object)) + { + dynamicMethod.Box(fieldInfo.FieldType); + } + else if (fieldInfo.FieldType != typeof(TResult)) + { + dynamicMethod.CastClass(typeof(TResult)); + } + + dynamicMethod.Return(); + return dynamicMethod.CreateDelegate(); + } + + private readonly struct PropertyFetcherCacheKey : IEquatable + { + public readonly Type Type1; + public readonly Type Type2; + public readonly Type Type3; + public readonly string Name; + + public PropertyFetcherCacheKey(Type type1, Type type2, string name) + : this(type1, type2, null, name) + { + } + + public PropertyFetcherCacheKey(Type type1, Type type2, Type type3, string name) + { + Type1 = type1 ?? throw new ArgumentNullException(nameof(type1)); + Type2 = type2; + Type3 = type3; + Name = name ?? throw new ArgumentNullException(nameof(name)); + } + + public bool Equals(PropertyFetcherCacheKey other) + { + return Equals(Type1, other.Type1) && Equals(Type2, other.Type2) && Equals(Type3, other.Type3) && Name == other.Name; + } + + public override bool Equals(object obj) + { + return obj is PropertyFetcherCacheKey other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = Type1.GetHashCode(); + hashCode = (hashCode * 397) ^ (Type2 != null ? Type2.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Type3 != null ? Type3.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Name.GetHashCode(); + return hashCode; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Emit/OpCodeValues.cs b/src/Datadog.Trace.ClrProfiler.Managed/Emit/OpCodeValues.cs new file mode 100644 index 0000000000..22a8b9f170 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Emit/OpCodeValues.cs @@ -0,0 +1,11 @@ +namespace Datadog.Trace.ClrProfiler.Emit +{ + internal enum OpCodeValue : short + { + /// + Call = 40, + + /// + Callvirt = 111 + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/GlobalSuppressions.cs b/src/Datadog.Trace.ClrProfiler.Managed/GlobalSuppressions.cs new file mode 100644 index 0000000000..a0519b8c86 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/GlobalSuppressions.cs @@ -0,0 +1,9 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage( + "StyleCop.CSharp.OrderingRules", + "SA1202:Elements must be ordered by access", + Justification = "Allow custom ordering in integrations.")] diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Helpers/AsyncHelper.cs b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/AsyncHelper.cs new file mode 100644 index 0000000000..f7a11137fa --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/AsyncHelper.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Concurrent; +using System.Reflection; +using System.Threading.Tasks; + +namespace Datadog.Trace.ClrProfiler.Helpers +{ + internal static class AsyncHelper + { + private static readonly ConcurrentDictionary MethodCache = new ConcurrentDictionary(); + + internal static object InvokeGenericTaskDelegate( + Type owningType, + Type taskResultType, + string nameOfIntegrationMethod, + Type integrationType, + params object[] parametersToPass) + { + var methodKey = new Key( + owningType, + taskResultType, + Interception.NullTypeArray, + Interception.ParamsToTypes(parametersToPass), + nameOfIntegrationMethod, + integrationType); + + var asyncDelegate = + MethodCache.GetOrAdd(methodKey, key => GetGenericAsyncMethodInfo(key.ReturnType, key.IntegrationName, key.IntegrationType)); + + return asyncDelegate.Invoke(null, parametersToPass); + } + + private static MethodInfo GetGenericAsyncMethodInfo(Type taskResultType, string nameOfIntegrationMethod, Type integrationType) + { + var method = integrationType.GetMethod(nameOfIntegrationMethod, BindingFlags.Static | BindingFlags.NonPublic); + + if (method == null) + { + throw new ArgumentException($"Method {nameOfIntegrationMethod} not found on {integrationType.Name} for async delegate access. "); + } + + if (method.IsStatic == false) + { + throw new ArgumentException($"Method {nameOfIntegrationMethod} on {integrationType.Name} must be static. "); + } + + if (method.ReturnType.Name != typeof(Task<>).Name) + { + throw new ArgumentException($"Method {nameOfIntegrationMethod} on {integrationType.Name} must have a return type of Task<>. "); + } + + return method.MakeGenericMethod(taskResultType); + } + + private readonly struct Key : IEquatable + { + public readonly Type OwningType; + public readonly Type ReturnType; + + public readonly Type[] GenericTypes; + public readonly Type[] ParameterTypes; + + public readonly string IntegrationName; + public readonly Type IntegrationType; + + public Key(Type owningType, Type returnType, Type[] genericTypes, Type[] parameterTypes, string integrationName, Type integrationType) + { + OwningType = owningType; + ReturnType = returnType; + GenericTypes = genericTypes; + ParameterTypes = parameterTypes; + IntegrationName = integrationName; + IntegrationType = integrationType; + } + + public bool Equals(Key other) + { + return Equals(OwningType, other.OwningType) + && Equals(ReturnType, other.ReturnType) + && ArrayEquals(GenericTypes, other.GenericTypes) + && ArrayEquals(ParameterTypes, other.ParameterTypes); + } + + public override bool Equals(object obj) + { + return obj is Key other && Equals(other); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (OwningType != null ? OwningType.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (ReturnType != null ? ReturnType.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ GetHashCode(GenericTypes); + hashCode = (hashCode * 397) ^ GetHashCode(ParameterTypes); + return hashCode; + } + } + + private static int GetHashCode(Type[] array) + { + if (array == null) + { + return 0; + } + + int value = array.Length; + + for (int i = 0; i < array.Length; i++) + { + value = unchecked((value * 31) + array[i]?.GetHashCode() ?? 0); + } + + return value; + } + + private static bool ArrayEquals(Type[] array1, Type[] array2) + { + if (array1 == null) + { + return array2 == null; + } + + if (array2 == null) + { + return false; + } + + if (array1.Length != array2.Length) + { + return false; + } + + for (int i = 0; i < array1.Length; i++) + { + if (array1[i] != array2[i]) + { + return false; + } + } + + return true; + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Helpers/Interception.cs b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/Interception.cs new file mode 100644 index 0000000000..512f717d20 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/Interception.cs @@ -0,0 +1,51 @@ +using System; +using System.Diagnostics; + +namespace Datadog.Trace.ClrProfiler.Helpers +{ + /// + /// Convenience properties and methods for integration definitions. + /// + internal static class Interception + { + internal const Type[] NullTypeArray = null; + internal static readonly object[] NoArgObjects = new object[0]; + internal static readonly Type[] NoArgTypes = Type.EmptyTypes; + internal static readonly Type VoidType = typeof(void); + + internal static Type[] ParamsToTypes(params object[] objectsToCheck) + { + var types = new Type[objectsToCheck.Length]; + + for (var i = 0; i < objectsToCheck.Length; i++) + { + types[i] = objectsToCheck[i]?.GetType(); + } + + return types; + } + + internal static string MethodKey( + Type owningType, + Type returnType, + Type[] genericTypes, + Type[] parameterTypes) + { + var key = $"{owningType?.AssemblyQualifiedName}_m_r{returnType?.AssemblyQualifiedName}"; + + for (ushort i = 0; i < (genericTypes?.Length ?? 0); i++) + { + Debug.Assert(genericTypes != null, nameof(genericTypes) + " != null"); + key = string.Concat(key, $"_g{genericTypes[i].AssemblyQualifiedName}"); + } + + for (ushort i = 0; i < (parameterTypes?.Length ?? 0); i++) + { + Debug.Assert(parameterTypes != null, nameof(parameterTypes) + " != null"); + key = string.Concat(key, $"_p{parameterTypes[i].AssemblyQualifiedName}"); + } + + return key; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Helpers/PointerHelpers.cs b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/PointerHelpers.cs new file mode 100644 index 0000000000..3333b603ce --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/PointerHelpers.cs @@ -0,0 +1,21 @@ +using System; +using System.Runtime.InteropServices; + +namespace Datadog.Trace.ClrProfiler.Helpers +{ + internal static class PointerHelpers + { + public static Guid GetGuidFromNativePointer(long nativePointer) + { + var ptr = new IntPtr(nativePointer); +#if NET45 + // deprecated + var moduleVersionId = (Guid)Marshal.PtrToStructure(ptr, typeof(Guid)); +#else + // added in net451 + var moduleVersionId = Marshal.PtrToStructure(ptr); +#endif + return moduleVersionId; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Helpers/ReflectionHttpHeadersCollection.cs b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/ReflectionHttpHeadersCollection.cs new file mode 100644 index 0000000000..caf09c9b07 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/ReflectionHttpHeadersCollection.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Headers; + +namespace Datadog.Trace.ClrProfiler.Helpers +{ + internal readonly struct ReflectionHttpHeadersCollection : IHeadersCollection + { + private readonly object _headers; + + public ReflectionHttpHeadersCollection(object headers) + { + _headers = headers ?? throw new ArgumentNullException(nameof(headers)); + } + + public IEnumerable GetValues(string name) + { + if (_headers.CallMethod("Contains", name).Value) + { + return _headers.CallMethod>("GetValues", name).Value ?? Enumerable.Empty(); + } + + return Enumerable.Empty(); + } + + public void Set(string name, string value) + { + _headers.CallMethod("Remove", name); + _headers.CallVoidMethod("Add", name, value); + } + + public void Add(string name, string value) + { + _headers.CallVoidMethod("Add", name, value); + } + + public void Remove(string name) + { + _headers.CallMethod("Remove", name); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Helpers/TaskExtensions.cs b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/TaskExtensions.cs new file mode 100644 index 0000000000..b31209393c --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Helpers/TaskExtensions.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Concurrent; +using System.Threading.Tasks; + +namespace Datadog.Trace.ClrProfiler.Helpers +{ + internal static class TaskExtensions + { + private static readonly ConcurrentDictionary, object>> Converters = new ConcurrentDictionary, object>>(); + + public static object Cast(this Task parent, Type taskResultType) + { + var converter = Converters.GetOrAdd( + taskResultType, + type => + { + var methodInfo = typeof(TaskExtensions) + .GetMethod(nameof(ConvertTaskImpl), System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) + .MakeGenericMethod(type); + + return (Func, object>)methodInfo.CreateDelegate(typeof(Func, object>)); + }); + + return converter(parent); + } + + private static async Task ConvertTaskImpl(Task parent) + { + return (T)await parent.ConfigureAwait(false); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Instrumentation.cs b/src/Datadog.Trace.ClrProfiler.Managed/Instrumentation.cs new file mode 100644 index 0000000000..29d219cf19 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Instrumentation.cs @@ -0,0 +1,61 @@ +using System; +using System.Text; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Provides instrumentation probes that can be injected into profiled code. + /// + public static class Instrumentation + { + /// + /// Gets the CLSID for the Datadog .NET profiler + /// + public static readonly string ProfilerClsid = "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(Instrumentation)); + + /// + /// Gets a value indicating whether Datadog's profiler is attached to the current process. + /// + /// + /// true if the profiler is currently attached; false otherwise. + /// + public static bool ProfilerAttached + { + get + { + try + { + return NativeMethods.IsProfilerAttached(); + } + catch (DllNotFoundException) + { + return false; + } + } + } + + /// + /// Initializes global instrumentation values. + /// + public static void Initialize() + { + try + { + var tracer = Tracer.Instance; + + if (tracer.Settings.DiagnosticSourceEnabled) + { + tracer.StartDiagnosticObservers(); + } + } + catch + { + // ignore + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/AdoNetConstants.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/AdoNetConstants.cs new file mode 100644 index 0000000000..4ff620f46a --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/AdoNetConstants.cs @@ -0,0 +1,42 @@ +namespace Datadog.Trace.ClrProfiler.Integrations.AdoNet +{ + internal static class AdoNetConstants + { + public static class AssemblyNames + { + // .NET Framework + public const string SystemData = "System.Data"; + + // .NET Core + public const string SystemDataCommon = "System.Data.Common"; + public const string SystemDataSqlClient = "System.Data.SqlClient"; + + // .NET Standard + public const string NetStandard = "netstandard"; + } + + public static class TypeNames + { + // ReSharper disable InconsistentNaming + public const string IDataReader = "System.Data.IDataReader"; + public const string IDbCommand = "System.Data.IDbCommand"; + // ReSharper restore InconsistentNaming + + public const string DbDataReader = "System.Data.Common.DbDataReader"; + public const string DbCommand = "System.Data.Common.DbCommand"; + public const string CommandBehavior = "System.Data.CommandBehavior"; + } + + public static class MethodNames + { + public const string ExecuteNonQuery = "ExecuteNonQuery"; + public const string ExecuteNonQueryAsync = "ExecuteNonQueryAsync"; + + public const string ExecuteScalar = "ExecuteScalar"; + public const string ExecuteScalarAsync = "ExecuteScalarAsync"; + + public const string ExecuteReader = "ExecuteReader"; + public const string ExecuteReaderAsync = "ExecuteReaderAsync"; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/DbCommandIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/DbCommandIntegration.cs new file mode 100644 index 0000000000..5d29d75fb2 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/DbCommandIntegration.cs @@ -0,0 +1,577 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.AdoNet +{ + /// + /// Instrumentation wrappers for . + /// + public static class DbCommandIntegration + { + private const string IntegrationName = "AdoNet"; + private const string Major4 = "4"; + private const string Major2 = "2"; + + private const string DbCommandTypeName = AdoNetConstants.TypeNames.DbCommand; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(DbCommandIntegration)); + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced "this" in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.DbDataReader }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.DbDataReader }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteReader( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(AdoNetConstants.TypeNames.DbDataReader) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced "this" in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.DbDataReader, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.DbDataReader, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteReaderWithBehavior( + object command, + int behavior, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + var commandBehavior = (CommandBehavior)behavior; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior) + .WithNamespaceAndNameFilters(AdoNetConstants.TypeNames.DbDataReader, AdoNetConstants.TypeNames.CommandBehavior) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand, commandBehavior); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteReaderAsync( + object command, + int behavior, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteReaderAsyncInternal( + command as DbCommand, + (CommandBehavior)behavior, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteReaderAsyncInternal( + DbCommand command, + CommandBehavior commandBehavior, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReaderAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, commandBehavior, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteNonQuery, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteNonQuery, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static int ExecuteNonQuery( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQuery; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Int32) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteNonQueryAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteNonQueryAsyncInternal( + command as DbCommand, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteNonQueryAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQueryAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteScalar, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteScalar, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteScalar( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalar; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Object) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = DbCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteScalarAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteScalarAsyncInternal( + command as DbCommand, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteScalarAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalarAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(DbCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: DbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/IDbCommandIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/IDbCommandIntegration.cs new file mode 100644 index 0000000000..bfd1f34706 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/IDbCommandIntegration.cs @@ -0,0 +1,305 @@ +using System; +using System.Data; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.AdoNet +{ + /// + /// Instrumentation wrappers for . + /// + // ReSharper disable once InconsistentNaming + public static class IDbCommandIntegration + { + private const string IntegrationName = "AdoNet"; + private const string Major4 = "4"; + private const string Major2 = "2"; + + // ReSharper disable once InconsistentNaming + private const string IDbCommandTypeName = AdoNetConstants.TypeNames.IDbCommand; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(IDbCommandIntegration)); + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced "this" in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.IDataReader }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.IDataReader }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteReader( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedInterface(IDbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(AdoNetConstants.TypeNames.IDataReader) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IDbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as IDbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for . + /// + /// The object referenced "this" in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.IDataReader, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { AdoNetConstants.TypeNames.IDataReader, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteReaderWithBehavior( + object command, + int behavior, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + var commandBehavior = (CommandBehavior)behavior; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedInterface(IDbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior) + .WithNamespaceAndNameFilters(AdoNetConstants.TypeNames.IDataReader, AdoNetConstants.TypeNames.CommandBehavior) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IDbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as IDbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand, commandBehavior); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for IDbCommand.ExecuteNonQuery(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static int ExecuteNonQuery( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQuery; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedInterface(IDbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Int32) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IDbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as IDbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for IDbCommand.ExecuteScalar(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataCommon }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.NetStandard }, + TargetType = IDbCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major2, + TargetMaximumVersion = Major2)] + public static object ExecuteScalar( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalar; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedInterface(IDbCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Object) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IDbCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as IDbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/NpgsqlCommandIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/NpgsqlCommandIntegration.cs new file mode 100644 index 0000000000..61be7a9dcd --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/NpgsqlCommandIntegration.cs @@ -0,0 +1,608 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.AdoNet +{ + /// + /// Instrumentation wrappers for . + /// + public static class NpgsqlCommandIntegration + { + private const string IntegrationName = "AdoNet"; + private const string Major4 = "4"; + + private const string NpgsqlAssemblyName = "Npgsql"; + private const string NpgsqlCommandTypeName = "Npgsql.NpgsqlCommand"; + private const string NpgsqlDataReaderTypeName = "Npgsql.NpgsqlDataReader"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(NpgsqlCommandIntegration)); + + /// + /// Instrumentation wrapper for NpgsqlCommand /> + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetSignatureTypes = new[] { NpgsqlDataReaderTypeName }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReader( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(NpgsqlDataReaderTypeName) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command as DbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(command); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReader(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetSignatureTypes = new[] { NpgsqlDataReaderTypeName, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReaderWithBehavior( + object command, + int behavior, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + Func instrumentedMethod; + var commandBehavior = (CommandBehavior)behavior; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior) + .WithNamespaceAndNameFilters(NpgsqlDataReaderTypeName, AdoNetConstants.TypeNames.CommandBehavior) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command as DbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(command, commandBehavior); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReaderAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReaderAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteReaderAsyncInternal( + (DbCommand)command, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteReaderAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReaderAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReaderAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetMethod = AdoNetConstants.MethodNames.ExecuteReaderAsync, + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReaderAsyncWithBehaviorAndCancellation( + object command, + int behavior, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteReaderAsyncWithBehaviorAndCancellationInternal( + (DbCommand)command, + (CommandBehavior)behavior, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteReaderAsyncWithBehaviorAndCancellationInternal( + DbCommand command, + CommandBehavior commandBehavior, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReaderAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, commandBehavior, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteNonQuery(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static int ExecuteNonQuery( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQuery; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Int32) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteNonQueryAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteNonQueryAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteNonQueryAsyncInternal( + command as DbCommand, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteNonQueryAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQueryAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteScalar(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { NpgsqlAssemblyName }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteScalar( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalar; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Object) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteScalarAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = NpgsqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteScalarAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + + return ExecuteScalarAsyncInternal( + command as DbCommand, + cancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteScalarAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalarAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(NpgsqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: NpgsqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/SqlCommandIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/SqlCommandIntegration.cs new file mode 100644 index 0000000000..2c8a876990 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AdoNet/SqlCommandIntegration.cs @@ -0,0 +1,519 @@ +using System; +using System.Data; +using System.Data.Common; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.AdoNet +{ + /// + /// Instrumentation wrappers for SqlCommand. + /// + public static class SqlCommandIntegration + { + private const string IntegrationName = "AdoNet"; + private const string Major4 = "4"; + + private const string SqlCommandTypeName = "System.Data.SqlClient.SqlCommand"; + private const string SqlDataReaderTypeName = "System.Data.SqlClient.SqlDataReader"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(SqlCommandIntegration)); + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReader(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetSignatureTypes = new[] { SqlDataReaderTypeName }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReader( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(SqlDataReaderTypeName) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command as DbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(command); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReader(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetMethod = AdoNetConstants.MethodNames.ExecuteReader, + TargetSignatureTypes = new[] { SqlDataReaderTypeName, AdoNetConstants.TypeNames.CommandBehavior }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReaderWithBehavior( + object command, + int behavior, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReader; + var commandBehavior = (CommandBehavior)behavior; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior) + .WithNamespaceAndNameFilters(SqlDataReaderTypeName, AdoNetConstants.TypeNames.CommandBehavior) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command as DbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(command, commandBehavior); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteReaderAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteReaderAsync( + object command, + int behavior, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + return ExecuteReaderAsyncInternal( + (DbCommand)command, + (CommandBehavior)behavior, + (CancellationToken)boxedCancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteReaderAsyncInternal( + DbCommand command, + CommandBehavior commandBehavior, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteReaderAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(commandBehavior, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, AdoNetConstants.TypeNames.CommandBehavior, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, commandBehavior, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteNonQuery(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Int32 }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static int ExecuteNonQuery( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQuery; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Int32) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteNonQueryAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteNonQueryAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + return ExecuteNonQueryAsyncInternal( + (DbCommand)command, + (CancellationToken)boxedCancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteNonQueryAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteNonQueryAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteScalar(). + /// + /// The object referenced by this in the instrumented method. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetSignatureTypes = new[] { ClrNames.Object }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteScalar( + object command, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalar; + Func instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithNamespaceAndNameFilters(ClrNames.Object) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + var dbCommand = command as DbCommand; + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, dbCommand, IntegrationName)) + { + try + { + return instrumentedMethod(dbCommand); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for SqlCommand.ExecuteScalarAsync(). + /// + /// The object referenced by this in the instrumented method. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssemblies = new[] { AdoNetConstants.AssemblyNames.SystemData, AdoNetConstants.AssemblyNames.SystemDataSqlClient }, + TargetType = SqlCommandTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object ExecuteScalarAsync( + object command, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + return ExecuteScalarAsyncInternal( + (DbCommand)command, + (CancellationToken)boxedCancellationToken, + opCode, + mdToken, + moduleVersionPtr); + } + + private static async Task ExecuteScalarAsyncInternal( + DbCommand command, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = AdoNetConstants.MethodNames.ExecuteScalarAsync; + Func> instrumentedMethod; + + try + { + var targetType = command.GetInstrumentedType(SqlCommandTypeName); + + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(targetType) + .WithParameters(cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: SqlCommandTypeName, + methodName: methodName, + instanceType: command.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ScopeFactory.CreateDbCommandScope(Tracer.Instance, command, IntegrationName)) + { + try + { + return await instrumentedMethod(command, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetMvcIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetMvcIntegration.cs new file mode 100644 index 0000000000..8f71bf6810 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetMvcIntegration.cs @@ -0,0 +1,362 @@ +#if !NETSTANDARD2_0 +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; +using System.Web.Routing; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// The ASP.NET MVC integration. + /// + public static class AspNetMvcIntegration + { + private const string IntegrationName = "AspNetMvc"; + private const string OperationName = "aspnet-mvc.request"; + private const string HttpContextKey = "__Datadog.Trace.ClrProfiler.Integrations.AspNetMvcIntegration"; + private const string MinimumVersion = "4"; + private const string MaximumVersion = "5"; + private const string AssemblyName = "System.Web.Mvc"; + + private const string AsyncActionInvokerTypeName = "System.Web.Mvc.Async.IAsyncActionInvoker"; + private const string ControllerContextTypeName = "System.Web.Mvc.ControllerContext"; + private const string RouteCollectionRouteTypeName = "System.Web.Mvc.Routing.RouteCollectionRoute"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(AspNetMvcIntegration)); + + /// + /// Creates a scope used to instrument an MVC action and populates some common details. + /// + /// The System.Web.Mvc.ControllerContext that was passed as an argument to the instrumented method. + /// A new scope used to instrument an MVC action. + public static Scope CreateScope(object controllerContext) + { + Scope scope = null; + + try + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + if (controllerContext == null || controllerContext.GetType().FullName != ControllerContextTypeName) + { + return null; + } + + var httpContext = controllerContext.GetProperty("HttpContext").GetValueOrDefault(); + + if (httpContext == null) + { + return null; + } + + string host = httpContext.Request.Headers.Get("Host"); + string httpMethod = httpContext.Request.HttpMethod.ToUpperInvariant(); + string url = httpContext.Request.RawUrl.ToLowerInvariant(); + string resourceName = null; + + RouteData routeData = controllerContext.GetProperty("RouteData").GetValueOrDefault(); + Route route = routeData?.Route as Route; + RouteValueDictionary routeValues = routeData?.Values; + + if (route == null && routeData?.Route.GetType().FullName == RouteCollectionRouteTypeName) + { + var routeMatches = routeValues?.GetValueOrDefault("MS_DirectRouteMatches") as List; + + if (routeMatches?.Count > 0) + { + // route was defined using attribute routing i.e. [Route("/path/{id}")] + // get route and routeValues from the RouteData in routeMatches + route = routeMatches[0].Route as Route; + routeValues = routeMatches[0].Values; + + if (route != null) + { + var resourceUrl = route.Url?.ToLowerInvariant() ?? string.Empty; + if (resourceUrl.FirstOrDefault() != '/') + { + resourceUrl = string.Concat("/", resourceUrl); + } + + resourceName = $"{httpMethod} {resourceUrl}"; + } + } + } + + if (string.IsNullOrEmpty(resourceName) && httpContext.Request.Url != null) + { + var cleanUri = UriHelpers.GetRelativeUrl(httpContext.Request.Url, tryRemoveIds: true); + resourceName = $"{httpMethod} {cleanUri.ToLowerInvariant()}"; + } + + string controllerName = (routeValues?.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); + string actionName = (routeValues?.GetValueOrDefault("action") as string)?.ToLowerInvariant(); + + if (string.IsNullOrEmpty(resourceName)) + { + // Keep the legacy resource name, just to have something + resourceName = $"{httpMethod} {controllerName}.{actionName}"; + } + + SpanContext propagatedContext = null; + var tracer = Tracer.Instance; + var tagsFromHeaders = Enumerable.Empty>(); + + if (tracer.ActiveScope == null) + { + try + { + // extract propagated http headers + var headers = httpContext.Request.Headers.Wrap(); + propagatedContext = SpanContextPropagator.Instance.Extract(headers); + tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headers, tracer.Settings.HeaderTags); + } + catch (Exception ex) + { + Log.Error(ex, "Error extracting propagated HTTP headers."); + } + } + + scope = Tracer.Instance.StartActive(OperationName, propagatedContext); + Span span = scope.Span; + + // Fail safe to catch templates in routing values + resourceName = + resourceName + .Replace("{controller}", controllerName) + .Replace("{action}", actionName); + + span.DecorateWebServerSpan( + resourceName: resourceName, + method: httpMethod, + host: host, + httpUrl: url, + tags: tagsFromHeaders); + span.SetTag(Tags.AspNetRoute, route?.Url); + span.SetTag(Tags.AspNetController, controllerName); + span.SetTag(Tags.AspNetAction, actionName); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + + /// + /// Wrapper method used to instrument System.Web.Mvc.Async.IAsyncActionInvoker.BeginInvokeAction(). + /// + /// The IAsyncActionInvoker instance. + /// The ControllerContext for the current request. + /// The name of the controller action. + /// An delegate. + /// An object that holds the state of the async operation. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the returned by the original BeginInvokeAction() that is later passed to . + [InterceptMethod( + CallerAssembly = AssemblyName, + TargetAssembly = AssemblyName, + TargetType = AsyncActionInvokerTypeName, + TargetSignatureTypes = new[] { ClrNames.IAsyncResult, ControllerContextTypeName, ClrNames.String, ClrNames.AsyncCallback, ClrNames.Object }, + TargetMinimumVersion = MinimumVersion, + TargetMaximumVersion = MaximumVersion)] + public static object BeginInvokeAction( + object asyncControllerActionInvoker, + object controllerContext, + object actionName, + object callback, + object state, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (asyncControllerActionInvoker == null) + { + throw new ArgumentNullException(nameof(asyncControllerActionInvoker)); + } + + Scope scope = null; + + try + { + if (HttpContext.Current != null) + { + scope = CreateScope(controllerContext); + HttpContext.Current.Items[HttpContextKey] = scope; + } + } + catch (Exception ex) + { + Log.Error(ex, "Error instrumenting method {0}", "System.Web.Mvc.Async.IAsyncActionInvoker.BeginInvokeAction()"); + } + + Func instrumentedMethod; + + try + { + var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName); + + instrumentedMethod = MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(BeginInvokeAction)) + .WithConcreteType(asyncActionInvokerType) + .WithParameters(controllerContext, actionName, callback, state) + .WithNamespaceAndNameFilters( + ClrNames.IAsyncResult, + "System.Web.Mvc.ControllerContext", + ClrNames.String, + ClrNames.AsyncCallback, + ClrNames.Object) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: AsyncActionInvokerTypeName, + methodName: nameof(BeginInvokeAction), + instanceType: asyncControllerActionInvoker.GetType().AssemblyQualifiedName); + throw; + } + + try + { + // call the original method, inspecting (but not catching) any unhandled exceptions + return instrumentedMethod(asyncControllerActionInvoker, controllerContext, actionName, callback, state); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + + /// + /// Wrapper method used to instrument System.Web.Mvc.Async.IAsyncActionInvoker.EndInvokeAction(). + /// + /// The IAsyncActionInvoker instance. + /// The returned by . + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the returned by the original EndInvokeAction(). + [InterceptMethod( + CallerAssembly = AssemblyName, + TargetAssembly = AssemblyName, + TargetType = AsyncActionInvokerTypeName, + TargetSignatureTypes = new[] { ClrNames.Bool, ClrNames.IAsyncResult }, + TargetMinimumVersion = MinimumVersion, + TargetMaximumVersion = MaximumVersion)] + public static bool EndInvokeAction( + object asyncControllerActionInvoker, + object asyncResult, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (asyncControllerActionInvoker == null) + { + throw new ArgumentNullException(nameof(asyncControllerActionInvoker)); + } + + Scope scope = null; + var httpContext = HttpContext.Current; + + try + { + scope = httpContext?.Items[HttpContextKey] as Scope; + } + catch (Exception ex) + { + Log.Error(ex, "Error instrumenting method {0}", $"{AsyncActionInvokerTypeName}.EndInvokeAction()"); + } + + Func instrumentedMethod; + + try + { + var asyncActionInvokerType = asyncControllerActionInvoker.GetInstrumentedInterface(AsyncActionInvokerTypeName); + + instrumentedMethod = MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(EndInvokeAction)) + .WithConcreteType(asyncActionInvokerType) + .WithParameters(asyncResult) + .WithNamespaceAndNameFilters(ClrNames.Bool, ClrNames.IAsyncResult) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: AsyncActionInvokerTypeName, + methodName: nameof(EndInvokeAction), + instanceType: asyncControllerActionInvoker.GetType().AssemblyQualifiedName); + throw; + } + + try + { + // call the original method, inspecting (but not catching) any unhandled exceptions + var result = instrumentedMethod(asyncControllerActionInvoker, asyncResult); + + if (scope != null) + { + scope.Span.SetServerStatusCode(httpContext.Response.StatusCode); + scope.Dispose(); + } + + return result; + } + catch (Exception ex) + { + if (scope != null) + { + scope.Span.SetException(ex); + + if (httpContext != null) + { + // We don't know how long it'll take for ASP.NET to invoke the callback, + // so we store the real finish time + var now = scope.Span.Context.TraceContext.UtcNow; + httpContext.AddOnRequestCompleted(h => OnRequestCompleted(h, scope, now)); + } + else + { + scope.Dispose(); + } + } + + throw; + } + } + + private static void OnRequestCompleted(HttpContext httpContext, Scope scope, DateTimeOffset finishTime) + { + scope.Span.SetServerStatusCode(httpContext.Response.StatusCode); + scope.Span.Finish(finishTime); + scope.Dispose(); + } + } +} + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetWebApi2Integration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetWebApi2Integration.cs new file mode 100644 index 0000000000..8ff6bba985 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/AspNet/AspNetWebApi2Integration.cs @@ -0,0 +1,330 @@ +#if !NETSTANDARD2_0 +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Contains instrumentation wrappers for ASP.NET Web API 5. + /// + public static class AspNetWebApi2Integration + { + private const string IntegrationName = "AspNetWebApi2"; + private const string OperationName = "aspnet-webapi.request"; + private const string Major5Minor1 = "5.1"; + private const string Major5 = "5"; + + private const string SystemWebHttpAssemblyName = "System.Web.Http"; + private const string HttpControllerTypeName = "System.Web.Http.Controllers.IHttpController"; + private const string HttpControllerContextTypeName = "System.Web.Http.Controllers.HttpControllerContext"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(AspNetWebApi2Integration)); + + /// + /// Calls the underlying ExecuteAsync and traces the request. + /// + /// The Api Controller + /// The controller context for the call + /// The cancellation token + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// A task with the result + [InterceptMethod( + TargetAssembly = SystemWebHttpAssemblyName, + TargetType = HttpControllerTypeName, + TargetSignatureTypes = new[] { ClrNames.HttpResponseMessageTask, HttpControllerContextTypeName, ClrNames.CancellationToken }, + TargetMinimumVersion = Major5Minor1, + TargetMaximumVersion = Major5)] + public static object ExecuteAsync( + object apiController, + object controllerContext, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (apiController == null) { throw new ArgumentNullException(nameof(apiController)); } + + var cancellationToken = (CancellationToken)boxedCancellationToken; + var callOpCode = (OpCodeValue)opCode; + var httpControllerType = apiController.GetInstrumentedInterface(HttpControllerTypeName); + + Type taskResultType; + + try + { + var request = controllerContext.GetProperty("Request").GetValueOrDefault(); + var httpRequestMessageType = request.GetInstrumentedType("System.Net.Http.HttpRequestMessage"); + + // The request should never be null, so get the base type found in System.Net.Http.dll + if (httpRequestMessageType != null) + { + var systemNetHttpAssembly = httpRequestMessageType.Assembly; + taskResultType = systemNetHttpAssembly.GetType("System.Net.Http.HttpResponseMessage", true); + } + + // This should never happen, but put in a reasonable fallback of finding the first System.Net.Http.dll in the AppDomain + else + { + Log.Warning($"{nameof(AspNetWebApi2Integration)}.{nameof(ExecuteAsync)}: Unable to find System.Net.Http.HttpResponseMessage Type from method arguments. Using fallback logic to find the Type needed for return type."); + var statsd = Tracer.Instance.Statsd; + if (statsd != null) + { + statsd.AppendWarning(source: $"{nameof(AspNetWebApi2Integration)}.{nameof(ExecuteAsync)}", message: "Unable to find System.Net.Http.HttpResponseMessage Type from method arguments. Using fallback logic to find the Type needed for return type.", null); + statsd.Send(); + } + + var systemNetHttpAssemblies = AppDomain.CurrentDomain.GetAssemblies().Where(assembly => assembly.GetName().Name.Equals("System.Net.Http", StringComparison.OrdinalIgnoreCase)); + var firstSystemNetHttpAssembly = systemNetHttpAssemblies.First(); + taskResultType = firstSystemNetHttpAssembly.GetType("System.Net.Http.HttpResponseMessage", true); + } + } + catch (Exception ex) + { + // This shouldn't happen because the System.Net.Http assembly should have been loaded if this method was called + // The profiled app will not continue working as expected without this method + Log.Error(ex, "Error finding types in the user System.Net.Http assembly."); + throw; + } + + Func instrumentedMethod = null; + + try + { + instrumentedMethod = MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(ExecuteAsync)) + .WithConcreteType(httpControllerType) + .WithParameters(controllerContext, cancellationToken) + .WithNamespaceAndNameFilters( + ClrNames.GenericTask, + HttpControllerContextTypeName, + ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: HttpControllerTypeName, + methodName: nameof(ExecuteAsync), + instanceType: apiController.GetType().AssemblyQualifiedName); + throw; + } + + return AsyncHelper.InvokeGenericTaskDelegate( + owningType: apiController.GetType(), + taskResultType: taskResultType, + nameOfIntegrationMethod: nameof(ExecuteAsyncInternal), + integrationType: typeof(AspNetWebApi2Integration), + instrumentedMethod, + apiController, + controllerContext, + cancellationToken); + } + + /// + /// Calls the underlying ExecuteAsync and traces the request. + /// + /// The type of the generic Task instantiation + /// The underlying ExecuteAsync method + /// The Api Controller + /// The controller context for the call + /// The cancellation token + /// A task with the result + private static async Task ExecuteAsyncInternal( + Func instrumentedMethod, + object apiController, + object controllerContext, + CancellationToken cancellationToken) + { + Scope scope = CreateScope(controllerContext); + + try + { + // call the original method, inspecting (and rethrowing) any unhandled exceptions + var task = (Task)instrumentedMethod(apiController, controllerContext, cancellationToken); + var responseMessage = await task; + + if (scope != null) + { + // some fields aren't set till after execution, so populate anything missing + UpdateSpan(controllerContext, scope.Span, Enumerable.Empty>()); + + var statusCode = responseMessage.GetProperty("StatusCode"); + scope.Span.SetServerStatusCode((int)statusCode.Value); + scope.Dispose(); + } + + return responseMessage; + } + catch (Exception ex) + { + if (scope != null) + { + // some fields aren't set till after execution, so populate anything missing + UpdateSpan(controllerContext, scope.Span, Enumerable.Empty>()); + scope.Span.SetException(ex); + + // We don't have access to the final status code at this point + // Ask the HttpContext to call us back to that we can get it + var httpContext = System.Web.HttpContext.Current; + + if (httpContext != null) + { + // We don't know how long it'll take for ASP.NET to invoke the callback, + // so we store the real finish time + var now = scope.Span.Context.TraceContext.UtcNow; + httpContext.AddOnRequestCompleted(h => OnRequestCompleted(h, scope, now)); + } + else + { + // Looks like we won't be able to get the final status code + scope.Dispose(); + } + } + + throw; + } + } + + private static Scope CreateScope(object controllerContext) + { + Scope scope = null; + + try + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + var tracer = Tracer.Instance; + var request = controllerContext.GetProperty("Request").GetValueOrDefault(); + SpanContext propagatedContext = null; + var tagsFromHeaders = Enumerable.Empty>(); + + if (request != null && tracer.ActiveScope == null) + { + try + { + // extract propagated http headers + var headers = request.GetProperty("Headers").GetValueOrDefault(); + var headersCollection = new ReflectionHttpHeadersCollection(headers); + + propagatedContext = SpanContextPropagator.Instance.Extract(headersCollection); + tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headersCollection, tracer.Settings.HeaderTags); + } + catch (Exception ex) + { + Log.Error(ex, "Error extracting propagated HTTP headers."); + } + } + + scope = tracer.StartActive(OperationName, propagatedContext); + UpdateSpan(controllerContext, scope.Span, tagsFromHeaders); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); + scope.Span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating scope."); + } + + return scope; + } + + private static void UpdateSpan(object controllerContext, Span span, IEnumerable> headerTags) + { + try + { + object request = controllerContext.GetProperty("Request").GetValueOrDefault(); + Uri requestUri = request.GetProperty("RequestUri").GetValueOrDefault(); + + string host = request.GetProperty("Headers").GetProperty("Host").GetValueOrDefault() ?? string.Empty; + string rawUrl = requestUri?.ToString().ToLowerInvariant() ?? string.Empty; + string absoluteUri = requestUri?.AbsoluteUri?.ToLowerInvariant() ?? string.Empty; + string method = request.GetProperty("Method").GetProperty("Method").GetValueOrDefault()?.ToUpperInvariant() ?? "GET"; + string route = null; + try + { + route = controllerContext.GetProperty("RouteData").GetProperty("Route").GetProperty("RouteTemplate").GetValueOrDefault(); + } + catch + { + } + + string resourceName = $"{method} {absoluteUri.ToLowerInvariant()}"; + + if (route != null) + { + resourceName = $"{method} {route.ToLowerInvariant()}"; + } + else if (requestUri != null) + { + var cleanUri = UriHelpers.GetRelativeUrl(requestUri, tryRemoveIds: true); + resourceName = $"{method} {cleanUri.ToLowerInvariant()}"; + } + + string controller = string.Empty; + string action = string.Empty; + try + { + var routeValues = controllerContext.GetProperty("RouteData").GetProperty>("Values").GetValueOrDefault(); + if (routeValues != null) + { + controller = (routeValues.GetValueOrDefault("controller") as string)?.ToLowerInvariant(); + action = (routeValues.GetValueOrDefault("action") as string)?.ToLowerInvariant(); + } + } + catch + { + } + + // Fail safe to catch templates in routing values + resourceName = + resourceName + .Replace("{controller}", controller) + .Replace("{action}", action); + + span.DecorateWebServerSpan( + resourceName: resourceName, + method: method, + host: host, + httpUrl: rawUrl, + tags: headerTags); + span.SetTag(Tags.AspNetAction, action); + span.SetTag(Tags.AspNetController, controller); + span.SetTag(Tags.AspNetRoute, route); + } + catch (Exception ex) + { + Log.Error(ex, "Error populating scope data."); + } + } + + private static void OnRequestCompleted(System.Web.HttpContext httpContext, Scope scope, DateTimeOffset finishTime) + { + scope.Span.SetServerStatusCode(httpContext.Response.StatusCode); + scope.Span.Finish(finishTime); + scope.Dispose(); + } + } +} + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet5Integration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet5Integration.cs new file mode 100644 index 0000000000..e4189fe615 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet5Integration.cs @@ -0,0 +1,199 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Traces an Elasticsearch pipeline + /// + public static class ElasticsearchNet5Integration + { + private const string IntegrationName = "ElasticsearchNet5"; + private const string Version5 = "5"; + private const string ElasticsearchAssembly = "Elasticsearch.Net"; + private const string RequestPipelineInterfaceTypeName = "Elasticsearch.Net.IRequestPipeline"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ElasticsearchNet5Integration)); + private static readonly Type ElasticsearchResponseType = Type.GetType("Elasticsearch.Net.ElasticsearchResponse`1, Elasticsearch.Net", throwOnError: false); + + /// + /// Traces a synchronous call to Elasticsearch. + /// + /// The type of the response + /// The pipeline for the original method + /// The request data + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + [InterceptMethod( + CallerAssembly = ElasticsearchAssembly, + TargetAssembly = ElasticsearchAssembly, + TargetType = RequestPipelineInterfaceTypeName, + TargetSignatureTypes = new[] { "Elasticsearch.Net.ElasticsearchResponse`1", "Elasticsearch.Net.RequestData" }, + TargetMinimumVersion = Version5, + TargetMaximumVersion = Version5)] + public static object CallElasticsearch( + object pipeline, + object requestData, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (pipeline == null) + { + throw new ArgumentNullException(nameof(pipeline)); + } + + const string methodName = nameof(CallElasticsearch); + Func callElasticSearch; + var pipelineType = pipeline.GetType(); + var genericArgument = typeof(TResponse); + + try + { + callElasticSearch = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(pipelineType) + .WithMethodGenerics(genericArgument) + .WithNamespaceAndNameFilters("Elasticsearch.Net.ElasticsearchResponse`1", "Elasticsearch.Net.RequestData") + .WithParameters(requestData) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: RequestPipelineInterfaceTypeName, + methodName: methodName, + instanceType: pipeline.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ElasticsearchNetCommon.CreateScope(Tracer.Instance, IntegrationName, pipeline, requestData)) + { + try + { + return callElasticSearch(pipeline, requestData); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Traces an asynchronous call to Elasticsearch. + /// + /// Type type of the response + /// The pipeline for the original method + /// The request data + /// A cancellation token + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + [InterceptMethod( + CallerAssembly = ElasticsearchAssembly, + TargetAssembly = ElasticsearchAssembly, + TargetType = RequestPipelineInterfaceTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1>", "Elasticsearch.Net.RequestData", ClrNames.CancellationToken }, + TargetMinimumVersion = Version5, + TargetMaximumVersion = Version5)] + public static object CallElasticsearchAsync( + object pipeline, + object requestData, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (pipeline == null) + { + throw new ArgumentNullException(nameof(pipeline)); + } + + var cancellationToken = (CancellationToken)boxedCancellationToken; + + var genericArgument = typeof(TResponse); + var genericResponseType = ElasticsearchResponseType.MakeGenericType(genericArgument); + + Func instrumentedMethod; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(CallElasticsearchAsync)) + .WithConcreteType(pipeline.GetType()) + .WithMethodGenerics(genericArgument) + .WithParameters(requestData, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, "Elasticsearch.Net.RequestData", ClrNames.CancellationToken) + .ForceMethodDefinitionResolution() + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: RequestPipelineInterfaceTypeName, + methodName: nameof(CallElasticsearchAsync), + instanceType: pipeline.GetType().AssemblyQualifiedName); + throw; + } + + return AsyncHelper.InvokeGenericTaskDelegate( + owningType: ElasticsearchNetCommon.RequestPipelineType, + taskResultType: genericResponseType, + nameOfIntegrationMethod: nameof(CallElasticsearchAsyncInternal), + integrationType: typeof(ElasticsearchNet5Integration), + pipeline, + requestData, + cancellationToken, + instrumentedMethod); + } + + /// + /// Traces an asynchronous call to Elasticsearch. + /// + /// Type type of the Task + /// The pipeline for the original method + /// The request data + /// A cancellation token + /// A delegate for the method we are instrumenting + /// The original result + private static async Task CallElasticsearchAsyncInternal( + object pipeline, + object requestData, + CancellationToken cancellationToken, + Func originalMethod) + { + using (var scope = ElasticsearchNetCommon.CreateScope(Tracer.Instance, IntegrationName, pipeline, requestData)) + { + try + { + var task = (Task)originalMethod(pipeline, requestData, cancellationToken); + return await task.ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet6Integration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet6Integration.cs new file mode 100644 index 0000000000..273db997e7 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNet6Integration.cs @@ -0,0 +1,187 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Traces an Elasticsearch pipeline + /// + public static class ElasticsearchNet6Integration + { + // NOTE: keep this name without the 6 to avoid breaking changes + private const string IntegrationName = "ElasticsearchNet"; + private const string Version6 = "6"; + private const string ElasticsearchAssemblyName = "Elasticsearch.Net"; + private const string RequestPipelineInterfaceTypeName = "Elasticsearch.Net.IRequestPipeline"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ElasticsearchNet6Integration)); + + /// + /// Traces a synchronous call to Elasticsearch. + /// + /// The type of the response + /// The pipeline for the original method + /// The request data + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + [InterceptMethod( + CallerAssembly = ElasticsearchAssemblyName, + TargetAssembly = ElasticsearchAssemblyName, + TargetType = RequestPipelineInterfaceTypeName, + TargetSignatureTypes = new[] { "T", "Elasticsearch.Net.RequestData" }, + TargetMinimumVersion = Version6, + TargetMaximumVersion = Version6)] + public static object CallElasticsearch( + object pipeline, + object requestData, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (pipeline == null) + { + throw new ArgumentNullException(nameof(pipeline)); + } + + const string methodName = nameof(CallElasticsearch); + Func callElasticSearch; + var pipelineType = pipeline.GetType(); + var genericArgument = typeof(TResponse); + + try + { + callElasticSearch = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(pipelineType) + .WithMethodGenerics(genericArgument) + .WithParameters(requestData) + .WithNamespaceAndNameFilters(ClrNames.Ignore, "Elasticsearch.Net.RequestData") + .Build(); + } + catch (Exception ex) + { + // profiled app will not continue working as expected without this method + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: RequestPipelineInterfaceTypeName, + methodName: methodName, + instanceType: pipeline.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = ElasticsearchNetCommon.CreateScope(Tracer.Instance, IntegrationName, pipeline, requestData)) + { + try + { + return callElasticSearch(pipeline, requestData); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Traces an asynchronous call to Elasticsearch. + /// + /// Type type of the response + /// The pipeline for the original method + /// The request data + /// A cancellation token + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + [InterceptMethod( + CallerAssembly = ElasticsearchAssemblyName, + TargetAssembly = ElasticsearchAssemblyName, + TargetType = RequestPipelineInterfaceTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", "Elasticsearch.Net.RequestData", ClrNames.CancellationToken }, + TargetMinimumVersion = Version6, + TargetMaximumVersion = Version6)] + public static object CallElasticsearchAsync( + object pipeline, + object requestData, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + var cancellationToken = (CancellationToken)boxedCancellationToken; + return CallElasticsearchAsyncInternal(pipeline, requestData, cancellationToken, opCode, mdToken, moduleVersionPtr); + } + + /// + /// Traces an asynchronous call to Elasticsearch. + /// + /// Type type of the response + /// The pipeline for the original method + /// The request data + /// A cancellation token + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + private static async Task CallElasticsearchAsyncInternal( + object pipeline, + object requestData, + CancellationToken cancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + const string methodName = "CallElasticsearchAsync"; + Func> callElasticSearchAsync; + var pipelineType = pipeline.GetType(); + var genericArgument = typeof(TResponse); + + try + { + callElasticSearchAsync = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(pipelineType) + .WithMethodGenerics(genericArgument) + .WithParameters(requestData, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, "Elasticsearch.Net.RequestData", ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: RequestPipelineInterfaceTypeName, + methodName: methodName, + instanceType: pipelineType.AssemblyQualifiedName); + throw; + } + + using (var scope = ElasticsearchNetCommon.CreateScope(Tracer.Instance, IntegrationName, pipeline, requestData)) + { + try + { + return await callElasticSearchAsync(pipeline, requestData, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNetCommon.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNetCommon.cs new file mode 100644 index 0000000000..207c82535d --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ElasticsearchNetCommon.cs @@ -0,0 +1,72 @@ +using System; +using System.Threading; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + internal static class ElasticsearchNetCommon + { + public const string OperationName = "elasticsearch.query"; + public const string ServiceName = "elasticsearch"; + public const string SpanType = "elasticsearch"; + public const string ComponentValue = "elasticsearch-net"; + public const string ElasticsearchActionKey = "elasticsearch.action"; + public const string ElasticsearchMethodKey = "elasticsearch.method"; + public const string ElasticsearchUrlKey = "elasticsearch.url"; + + public static readonly Type CancellationTokenType = typeof(CancellationToken); + public static readonly Type RequestPipelineType = Type.GetType("Elasticsearch.Net.IRequestPipeline, Elasticsearch.Net"); + public static readonly Type RequestDataType = Type.GetType("Elasticsearch.Net.RequestData, Elasticsearch.Net"); + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ElasticsearchNetCommon)); + + public static Scope CreateScope(Tracer tracer, string integrationName, object pipeline, object requestData) + { + if (!tracer.Settings.IsIntegrationEnabled(integrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + string requestName = pipeline.GetProperty("RequestParameters") + .GetValueOrDefault() + ?.GetType() + .Name + .Replace("RequestParameters", string.Empty); + + var pathAndQuery = requestData.GetProperty("PathAndQuery").GetValueOrDefault() ?? + requestData.GetProperty("Path").GetValueOrDefault(); + + string method = requestData.GetProperty("Method").GetValueOrDefault()?.ToString(); + var url = requestData.GetProperty("Uri").GetValueOrDefault()?.ToString(); + + var serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName); + + Scope scope = null; + + try + { + scope = tracer.StartActive(OperationName, serviceName: serviceName); + var span = scope.Span; + span.ResourceName = requestName ?? pathAndQuery ?? string.Empty; + span.Type = SpanType; + span.SetTag(Tags.InstrumentationName, ComponentValue); + span.SetTag(Tags.SpanKind, SpanKinds.Client); + span.SetTag(ElasticsearchActionKey, requestName); + span.SetTag(ElasticsearchMethodKey, method); + span.SetTag(ElasticsearchUrlKey, url); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/GraphQLIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/GraphQLIntegration.cs new file mode 100644 index 0000000000..abffaf3cd1 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/GraphQLIntegration.cs @@ -0,0 +1,413 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Tracing integration for GraphQL.Server.Transports.AspNetCore + /// + public static class GraphQLIntegration + { + private const string IntegrationName = "GraphQL"; + private const string ServiceName = "graphql"; + + private const string Major2 = "2"; + private const string Major2Minor3 = "2.3"; + + private const string ParseOperationName = "graphql.parse"; // Instrumentation not yet implemented + private const string ValidateOperationName = "graphql.validate"; + private const string ExecuteOperationName = "graphql.execute"; + private const string ResolveOperationName = "graphql.resolve"; // Instrumentation not yet implemented + + private const string GraphQLAssemblyName = "GraphQL"; + private const string GraphQLDocumentValidatorInterfaceName = "GraphQL.Validation.IDocumentValidator"; + private const string GraphQLExecutionResultName = "GraphQL.ExecutionResult"; + private const string GraphQLExecutionStrategyInterfaceName = "GraphQL.Execution.IExecutionStrategy"; + private const string GraphQLValidationResultInterfaceName = "GraphQL.Validation.IValidationResult"; + + private const string TaskOfGraphQLExecutionResult = "System.Threading.Tasks.Task`1<" + GraphQLExecutionResultName + ">"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(GraphQLIntegration)); + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The instance of GraphQL.Validation.IDocumentValidator. + /// The source of the original GraphQL query. + /// The GraphQL schema. + /// The GraphQL document. + /// The list of validation rules. + /// The user context. + /// The input variables. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssembly = GraphQLAssemblyName, + TargetType = GraphQLDocumentValidatorInterfaceName, + TargetSignatureTypes = new[] { GraphQLValidationResultInterfaceName, ClrNames.String, "GraphQL.Types.ISchema", "GraphQL.Language.AST.Document", "System.Collections.Generic.IEnumerable`1", ClrNames.Ignore, "GraphQL.Inputs" }, + TargetMinimumVersion = Major2Minor3, + TargetMaximumVersion = Major2)] + public static object Validate( + object documentValidator, + object originalQuery, + object schema, + object document, + object rules, + object userContext, + object inputs, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (documentValidator == null) { throw new ArgumentNullException(nameof(documentValidator)); } + + const string methodName = nameof(Validate); + + // At runtime, get a Type object for GraphQL.ExecutionResult + var documentValidatorInstanceType = documentValidator.GetType(); + + try + { + var graphQLAssembly = AppDomain.CurrentDomain + .GetAssemblies() + .Single(a => a.GetName().Name.Equals(GraphQLAssemblyName)); + } + catch (Exception ex) + { + // This shouldn't happen because the GraphQL assembly should have been loaded to construct various other types + // profiled app will not continue working as expected without this method + Log.Error(ex, $"Error finding types in the GraphQL assembly."); + throw; + } + + Func instrumentedMethod; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(documentValidatorInstanceType) + .WithParameters(originalQuery, schema, document, rules, userContext, inputs) + .WithNamespaceAndNameFilters( + GraphQLValidationResultInterfaceName, + ClrNames.String, + "GraphQL.Types.ISchema", + "GraphQL.Language.AST.Document", + "System.Collections.Generic.IEnumerable`1", + ClrNames.Ignore, + "GraphQL.Inputs") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: GraphQLDocumentValidatorInterfaceName, + methodName: methodName, + instanceType: documentValidator.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = CreateScopeFromValidate(document)) + { + try + { + var validationResult = instrumentedMethod(documentValidator, originalQuery, schema, document, rules, userContext, inputs); + RecordExecutionErrorsIfPresent(scope.Span, "GraphQL.Validation.ValidationError", validationResult.GetProperty("Errors").GetValueOrDefault()); + return validationResult; + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The instance of GraphQL.Execution.IExecutionStrategy. + /// The execution context of the GraphQL operation. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssembly = GraphQLAssemblyName, + TargetType = GraphQLExecutionStrategyInterfaceName, + TargetSignatureTypes = new[] { TaskOfGraphQLExecutionResult, "GraphQL.Execution.ExecutionContext" }, + TargetMinimumVersion = Major2Minor3, + TargetMaximumVersion = Major2)] + public static object ExecuteAsync(object executionStrategy, object context, int opCode, int mdToken, long moduleVersionPtr) + { + if (executionStrategy == null) { throw new ArgumentNullException(nameof(executionStrategy)); } + + const string methodName = nameof(ExecuteAsync); + + // At runtime, get a Type object for GraphQL.ExecutionResult + var executionStrategyInstanceType = executionStrategy.GetType(); + Type graphQLExecutionResultType; + Type executionStrategyInterfaceType; + + try + { + var graphQLAssembly = AppDomain.CurrentDomain.GetAssemblies() + .Single(a => a.GetName().Name.Equals(GraphQLAssemblyName)); + graphQLExecutionResultType = graphQLAssembly.GetType(GraphQLExecutionResultName, throwOnError: true); + executionStrategyInterfaceType = graphQLAssembly.GetType(GraphQLExecutionStrategyInterfaceName, throwOnError: true); + } + catch (Exception ex) + { + // This shouldn't happen because the GraphQL assembly should have been loaded to construct various other types + // profiled app will not continue working as expected without this method + Log.Error(ex, "Error finding types in the GraphQL assembly."); + throw; + } + + Func instrumentedMethod; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(executionStrategyInstanceType) + .WithParameters(context) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, "GraphQL.Execution.ExecutionContext") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: GraphQLExecutionStrategyInterfaceName, + methodName: methodName, + instanceType: executionStrategy.GetType().AssemblyQualifiedName); + throw; + } + + return AsyncHelper.InvokeGenericTaskDelegate( + owningType: executionStrategyInterfaceType, + taskResultType: graphQLExecutionResultType, + nameOfIntegrationMethod: nameof(CallGraphQLExecuteAsyncInternal), + integrationType: typeof(GraphQLIntegration), + executionStrategy, + context, + instrumentedMethod); + } + + private static async Task CallGraphQLExecuteAsyncInternal( + object executionStrategy, + object executionContext, + Func originalMethod) + { + using (var scope = CreateScopeFromExecuteAsync(executionContext)) + { + try + { + var task = (Task)originalMethod(executionStrategy, executionContext); + var executionResult = await task.ConfigureAwait(false); + RecordExecutionErrorsIfPresent(scope.Span, "GraphQL.ExecutionError", executionContext.GetProperty("Errors").GetValueOrDefault()); + return executionResult; + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static void DecorateSpan(Span span) + { + span.Type = SpanTypes.GraphQL; + span.SetTag(Tags.SpanKind, SpanKinds.Server); + span.SetTag(Tags.Language, TracerConstants.Language); + } + + private static Scope CreateScopeFromValidate(object document) + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Tracer tracer = Tracer.Instance; + string source = document.GetProperty("OriginalQuery") + .GetValueOrDefault(); + string serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName); + + Scope scope = null; + + try + { + scope = tracer.StartActive(ValidateOperationName, serviceName: serviceName); + var span = scope.Span; + DecorateSpan(span); + span.SetTag(Tags.GraphQLSource, source); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + + private static Scope CreateScopeFromExecuteAsync(object executionContext) + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Tracer tracer = Tracer.Instance; + string source = executionContext.GetProperty("Document") + .GetProperty("OriginalQuery") + .GetValueOrDefault(); + string operationName = executionContext.GetProperty("Operation") + .GetProperty("Name") + .GetValueOrDefault(); + string operationType = executionContext.GetProperty("Operation") + .GetProperty("OperationType") + .GetValueOrDefault() + .ToString(); + string serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName); + + Scope scope = null; + + try + { + scope = tracer.StartActive(ExecuteOperationName, serviceName: serviceName); + var span = scope.Span; + DecorateSpan(span); + span.ResourceName = $"{operationType} {operationName ?? "operation"}"; + + span.SetTag(Tags.GraphQLSource, source); + span.SetTag(Tags.GraphQLOperationName, operationName); + span.SetTag(Tags.GraphQLOperationType, operationType); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + + private static void RecordExecutionErrorsIfPresent(Span span, string errorType, object executionErrors) + { + var errorCount = executionErrors.GetProperty("Count").GetValueOrDefault(); + + if (errorCount > 0) + { + span.Error = true; + + span.SetTag(Trace.Tags.ErrorMsg, $"{errorCount} error(s)"); + span.SetTag(Trace.Tags.ErrorType, errorType); + span.SetTag(Trace.Tags.ErrorStack, ConstructErrorMessage(executionErrors)); + } + } + + private static string ConstructErrorMessage(object executionErrors) + { + if (executionErrors == null) + { + return string.Empty; + } + + var builder = new StringBuilder(); + var tab = " "; + builder.AppendLine("errors: ["); + + var enumerator = executionErrors.CallMethod>("GetEnumerator").GetValueOrDefault(); + + if (enumerator != null) + { + try + { + while (enumerator.MoveNext()) + { + var executionError = enumerator.GetProperty("Current").GetValueOrDefault(); + + builder.AppendLine($"{tab}{{"); + + var message = executionError.GetProperty("Message").GetValueOrDefault(); + if (message != null) + { + builder.AppendLine($"{tab + tab}\"message\": \"{message.Replace("\r", "\\r").Replace("\n", "\\n")}\","); + } + + var path = executionError.GetProperty>("Path").GetValueOrDefault(); + if (path != null) + { + builder.AppendLine($"{tab + tab}\"path\": \"{string.Join(".", path)}\","); + } + + var code = executionError.GetProperty("Code").GetValueOrDefault(); + if (code != null) + { + builder.AppendLine($"{tab + tab}\"code\": \"{code}\","); + } + + builder.AppendLine($"{tab + tab}\"locations\": ["); + var locations = executionError.GetProperty>("Locations").GetValueOrDefault(); + if (locations != null) + { + foreach (var location in locations) + { + var line = location.GetProperty("Line").GetValueOrDefault(); + var column = location.GetProperty("Column").GetValueOrDefault(); + + builder.AppendLine($"{tab + tab + tab}{{"); + builder.AppendLine($"{tab + tab + tab + tab}\"line\": {line},"); + builder.AppendLine($"{tab + tab + tab + tab}\"column\": {column}"); + builder.AppendLine($"{tab + tab + tab}}},"); + } + } + + builder.AppendLine($"{tab + tab}]"); + builder.AppendLine($"{tab}}},"); + } + + enumerator.Dispose(); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating GraphQL error message."); + return "errors: []"; + } + } + + builder.AppendLine("]"); + + return builder.ToString(); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/HttpMessageHandlerIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/HttpMessageHandlerIntegration.cs new file mode 100644 index 0000000000..8ac9e300be --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/HttpMessageHandlerIntegration.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Tracer integration for HttpClientHandler. + /// + public static class HttpMessageHandlerIntegration + { + private const string IntegrationName = "HttpMessageHandler"; + private const string SystemNetHttp = "System.Net.Http"; + private const string Major4 = "4"; + + private const string HttpMessageHandlerTypeName = "HttpMessageHandler"; + private const string HttpClientHandlerTypeName = "HttpClientHandler"; + + private const string HttpMessageHandler = SystemNetHttp + "." + HttpMessageHandlerTypeName; + private const string HttpClientHandler = SystemNetHttp + "." + HttpClientHandlerTypeName; + private const string SendAsync = "SendAsync"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(HttpMessageHandlerIntegration)); + private static readonly string[] NamespaceAndNameFilters = { ClrNames.GenericTask, ClrNames.HttpRequestMessage, ClrNames.CancellationToken }; + + private static Type _httpMessageHandlerResultType; + private static Type _httpClientHandlerResultType; + + /// + /// Instrumentation wrapper for HttpMessageHandler.SendAsync/>. + /// + /// The HttpMessageHandler instance to instrument. + /// The HttpRequestMessage that represents the current HTTP request. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the value returned by the inner method call. + [InterceptMethod( + TargetAssembly = SystemNetHttp, + TargetType = HttpMessageHandler, + TargetMethod = SendAsync, + TargetSignatureTypes = new[] { ClrNames.HttpResponseMessageTask, ClrNames.HttpRequestMessage, ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object HttpMessageHandler_SendAsync( + object handler, + object request, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + // original signature: + // Task HttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + var cancellationToken = (CancellationToken)boxedCancellationToken; + var callOpCode = (OpCodeValue)opCode; + var httpMessageHandler = handler.GetInstrumentedType(SystemNetHttp, HttpMessageHandlerTypeName); + + Func instrumentedMethod = null; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, SendAsync) + .WithConcreteType(httpMessageHandler) + .WithParameters(request, cancellationToken) + .WithNamespaceAndNameFilters(NamespaceAndNameFilters) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: HttpMessageHandler, + methodName: SendAsync, + instanceType: handler.GetType().AssemblyQualifiedName); + throw; + } + + var reportedType = callOpCode == OpCodeValue.Call ? httpMessageHandler : handler.GetType(); + var headers = request.GetProperty("Headers").GetValueOrDefault(); + + if (!(reportedType.FullName.Equals(HttpClientHandler, StringComparison.OrdinalIgnoreCase) || IsSocketsHttpHandlerEnabled(reportedType)) || + !IsTracingEnabled(headers)) + { + // skip instrumentation + return instrumentedMethod(handler, request, cancellationToken); + } + + Type taskResultType = _httpMessageHandlerResultType; + + if (taskResultType == null || taskResultType.Assembly != httpMessageHandler.Assembly) + { + try + { + var currentHttpAssembly = httpMessageHandler.Assembly; + taskResultType = currentHttpAssembly.GetType("System.Net.Http.HttpResponseMessage", true); + _httpMessageHandlerResultType = taskResultType; + } + catch (Exception ex) + { + // This shouldn't happen because the System.Net.Http assembly should have been loaded if this method was called + // profiled app will not continue working as expected without this method + Log.Error(ex, "Error finding types in the user System.Net.Http assembly."); + throw; + } + } + + return SendAsyncInternal( + instrumentedMethod, + reportedType, + headers, + handler, + request, + cancellationToken) + .Cast(taskResultType); + } + + /// + /// Instrumentation wrapper for HttpClientHandler.SendAsync. + /// + /// The HttpClientHandler instance to instrument. + /// The HttpRequestMessage that represents the current HTTP request. + /// The value used in the original method call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the value returned by the inner method call. + [InterceptMethod( + TargetAssembly = SystemNetHttp, + TargetType = HttpClientHandler, + TargetMethod = SendAsync, + TargetSignatureTypes = new[] { ClrNames.HttpResponseMessageTask, ClrNames.HttpRequestMessage, ClrNames.CancellationToken }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object HttpClientHandler_SendAsync( + object handler, + object request, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (handler == null) + { + throw new ArgumentNullException(nameof(handler)); + } + + // original signature: + // Task HttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + var cancellationToken = (CancellationToken)boxedCancellationToken; + var callOpCode = (OpCodeValue)opCode; + var httpClientHandler = handler.GetInstrumentedType(SystemNetHttp, HttpClientHandlerTypeName); + + Func instrumentedMethod = null; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, SendAsync) + .WithConcreteType(httpClientHandler) + .WithParameters(request, cancellationToken) + .WithNamespaceAndNameFilters(NamespaceAndNameFilters) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: HttpClientHandler, + methodName: SendAsync, + instanceType: handler.GetType().AssemblyQualifiedName); + throw; + } + + var headers = request.GetProperty("Headers").GetValueOrDefault(); + var reportedType = callOpCode == OpCodeValue.Call ? httpClientHandler : handler.GetType(); + + if (!(reportedType.FullName.Equals(HttpClientHandler, StringComparison.OrdinalIgnoreCase) || IsSocketsHttpHandlerEnabled(reportedType)) || + !IsTracingEnabled(headers)) + { + // skip instrumentation + return instrumentedMethod(handler, request, cancellationToken); + } + + Type taskResultType = _httpClientHandlerResultType; + + if (taskResultType == null || taskResultType.Assembly != httpClientHandler.Assembly) + { + try + { + var currentHttpAssembly = httpClientHandler.Assembly; + taskResultType = currentHttpAssembly.GetType("System.Net.Http.HttpResponseMessage", true); + _httpClientHandlerResultType = taskResultType; + } + catch (Exception ex) + { + // This shouldn't happen because the System.Net.Http assembly should have been loaded if this method was called + // profiled app will not continue working as expected without this method + Log.Error(ex, "Error finding types in the user System.Net.Http assembly."); + throw; + } + } + + return SendAsyncInternal( + instrumentedMethod, + reportedType, + headers, + handler, + request, + cancellationToken) + .Cast(taskResultType); + } + + private static async Task SendAsyncInternal( + Func sendAsync, + Type reportedType, + object headers, + object handler, + object request, + CancellationToken cancellationToken) + { + var httpMethod = request.GetProperty("Method").GetProperty("Method").GetValueOrDefault(); + var requestUri = request.GetProperty("RequestUri").GetValueOrDefault(); + + using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, httpMethod, requestUri, IntegrationName)) + { + try + { + if (scope != null) + { + scope.Span.SetTag("http-client-handler-type", reportedType.FullName); + + // add distributed tracing headers to the HTTP request + SpanContextPropagator.Instance.Inject(scope.Span.Context, new ReflectionHttpHeadersCollection(headers)); + } + + var task = (Task)sendAsync(handler, request, cancellationToken); + await task.ConfigureAwait(false); + + var response = task.GetProperty("Result").Value; + + // this tag can only be set after the response is returned + int statusCode = response.GetProperty("StatusCode").GetValueOrDefault(); + scope?.Span.SetTag(Tags.HttpStatusCode, (statusCode).ToString()); + + return response; + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static bool IsSocketsHttpHandlerEnabled(Type reportedType) + { + return Tracer.Instance.Settings.IsOptInIntegrationEnabled("HttpSocketsHandler") && reportedType.FullName.Equals("System.Net.Http.SocketsHttpHandler", StringComparison.OrdinalIgnoreCase); + } + + private static bool IsTracingEnabled(object headers) + { + if (headers.CallMethod("Contains", HttpHeaderNames.TracingEnabled).Value) + { + var headerValues = headers.CallMethod>("GetValues", HttpHeaderNames.TracingEnabled).Value; + if (headerValues != null && headerValues.Any(s => string.Equals(s, "false", StringComparison.OrdinalIgnoreCase))) + { + // tracing is disabled for this request via http header + return false; + } + } + + return true; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/LoggerExtensions.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/LoggerExtensions.cs new file mode 100644 index 0000000000..a469dfd922 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/LoggerExtensions.cs @@ -0,0 +1,47 @@ +using System; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.DogStatsd; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + internal static class LoggerExtensions + { + public static void ErrorRetrievingMethod( + this Vendors.Serilog.ILogger logger, + Exception exception, + long moduleVersionPointer, + int mdToken, + int opCode, + string instrumentedType, + string methodName, + string instanceType = null, + string[] relevantArguments = null) + { + var instrumentedMethod = $"{instrumentedType}.{methodName}(...)"; + + if (instanceType != null) + { + instrumentedMethod = $"{instrumentedMethod} on {instanceType}"; + } + + if (relevantArguments != null) + { + instrumentedMethod = $"{instrumentedMethod} with {string.Join(", ", relevantArguments)}"; + } + + var moduleVersionId = PointerHelpers.GetGuidFromNativePointer(moduleVersionPointer); + logger.Error( + exception, + $"Error (MVID: {moduleVersionId}, mdToken: {mdToken}, opCode: {opCode}) could not retrieve: {instrumentedMethod}"); + + var statsd = Tracer.Instance.Statsd; + + if (statsd != null) + { + string[] tags = { $"instrumented-method:{instrumentedMethod}" }; + statsd.AppendException(exception, source: instrumentedType, message: "Error retrieving instrumented method", tags); + statsd.Send(); + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/MongoDbIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/MongoDbIntegration.cs new file mode 100644 index 0000000000..c50beb4f2a --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/MongoDbIntegration.cs @@ -0,0 +1,488 @@ +using System; +using System.Net; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Tracing integration for MongoDB.Driver.Core. + /// + public static class MongoDbIntegration + { + private const string IntegrationName = "MongoDb"; + private const string OperationName = "mongodb.query"; + private const string ServiceName = "mongodb"; + + private const string Major2 = "2"; + private const string Major2Minor1 = "2.1"; + private const string Major2Minor2 = "2.2"; // Synchronous methods added in 2.2 + private const string MongoDbClientAssembly = "MongoDB.Driver.Core"; + private const string IWireProtocol = "MongoDB.Driver.Core.WireProtocol.IWireProtocol"; + private const string IWireProtocolGeneric = "MongoDB.Driver.Core.WireProtocol.IWireProtocol`1"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(MongoDbIntegration)); + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The IWireProtocol instance we are replacing. + /// The connection. + /// A cancellation token. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + [InterceptMethod( + TargetAssembly = MongoDbClientAssembly, + TargetType = IWireProtocol, + TargetSignatureTypes = new[] { ClrNames.Void, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken }, + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2)] + public static void Execute( + object wireProtocol, + object connection, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (wireProtocol == null) { throw new ArgumentNullException(nameof(wireProtocol)); } + + const string methodName = nameof(Execute); + Action execute; + var wireProtocolType = wireProtocol.GetType(); + + var cancellationToken = (CancellationToken)boxedCancellationToken; + + try + { + execute = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(wireProtocolType) + .WithParameters(connection, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.Void, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IWireProtocol, + methodName: methodName, + instanceType: wireProtocol.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = CreateScope(wireProtocol, connection)) + { + try + { + execute(wireProtocol, connection, cancellationToken); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The IWireProtocol`1 instance we are replacing. + /// The connection. + /// A cancellation token. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssembly = MongoDbClientAssembly, + TargetType = IWireProtocolGeneric, + TargetSignatureTypes = new[] { "T", "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken }, + TargetMethod = nameof(Execute), + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2)] + public static object ExecuteGeneric( + object wireProtocol, + object connection, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (wireProtocol == null) { throw new ArgumentNullException(nameof(wireProtocol)); } + + const string methodName = nameof(Execute); + Func execute; + var wireProtocolType = wireProtocol.GetType(); + + var cancellationToken = (CancellationToken)boxedCancellationToken; + + try + { + execute = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(wireProtocolType) + .WithParameters(connection, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.Ignore, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IWireProtocolGeneric, + methodName: methodName, + instanceType: wireProtocol.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = CreateScope(wireProtocol, connection)) + { + try + { + return execute(wireProtocol, connection, cancellationToken); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The IWireProtocol instance we are replacing. + /// The connection. + /// A cancellation token. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetMethod = nameof(ExecuteAsync), + TargetAssembly = MongoDbClientAssembly, + TargetType = IWireProtocol, + TargetSignatureTypes = new[] { ClrNames.Task, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken }, + TargetMinimumVersion = Major2Minor1, + TargetMaximumVersion = Major2)] + public static object ExecuteAsync( + object wireProtocol, + object connection, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (wireProtocol == null) { throw new ArgumentNullException(nameof(wireProtocol)); } + + var cancellationToken = (CancellationToken)boxedCancellationToken; + + const string methodName = nameof(ExecuteAsync); + var wireProtocolType = wireProtocol.GetType(); + var wireProtocolGenericArgs = GetGenericsFromWireProtocol(wireProtocolType); + + Func executeAsync; + + try + { + executeAsync = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(wireProtocolType) + .WithDeclaringTypeGenerics(wireProtocolGenericArgs) + .WithParameters(connection, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.Task, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: IWireProtocolGeneric, + methodName: methodName, + instanceType: wireProtocol.GetType().AssemblyQualifiedName); + throw; + } + + return ExecuteAsyncInternalNonGeneric(wireProtocol, connection, cancellationToken, executeAsync); + } + + /// + /// Wrap the original method by adding instrumentation code around it. + /// + /// The IWireProtocol`1 instance we are replacing. + /// The connection. + /// A cancellation token. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetMethod = nameof(ExecuteAsync), + TargetAssembly = MongoDbClientAssembly, + TargetType = IWireProtocolGeneric, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken }, + TargetMinimumVersion = Major2Minor1, + TargetMaximumVersion = Major2)] + public static object ExecuteAsyncGeneric( + object wireProtocol, + object connection, + object boxedCancellationToken, + int opCode, + int mdToken, + long moduleVersionPtr) + { + // The generic type for this method comes from the declaring type of wireProtocol + if (wireProtocol == null) { throw new ArgumentNullException(nameof(wireProtocol)); } + + var cancellationToken = (CancellationToken)boxedCancellationToken; + + var wireProtocolType = wireProtocol.GetType(); + var wireProtocolGenericArgs = GetGenericsFromWireProtocol(wireProtocolType); + + const string methodName = nameof(ExecuteAsync); + Func executeAsync; + + try + { + executeAsync = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(wireProtocolType) + .WithDeclaringTypeGenerics(wireProtocolGenericArgs) + .WithParameters(connection, cancellationToken) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, "MongoDB.Driver.Core.Connections.IConnection", ClrNames.CancellationToken) + .Build(); + } + catch (Exception ex) + { + // profiled app will not continue working as expected without this method + Log.Error(ex, $"Error resolving {wireProtocolType.Name}.{methodName}(IConnection connection, CancellationToken cancellationToken)"); + throw; + } + + return AsyncHelper.InvokeGenericTaskDelegate( + wireProtocolType, + wireProtocolGenericArgs[0], + nameof(ExecuteAsyncInternalGeneric), + typeof(MongoDbIntegration), + wireProtocol, + connection, + cancellationToken, + executeAsync); + } + + private static Type[] GetGenericsFromWireProtocol(Type wireProtocolType) + { + var interfaces = wireProtocolType.GetInterfaces(); + Type typeWeInstrument = null; + + for (var i = 0; i < interfaces.Length; i++) + { + if (string.Equals($"{interfaces[i].Namespace}.{interfaces[i].Name}", IWireProtocolGeneric)) + { + typeWeInstrument = interfaces[i]; + break; + } + } + + if (typeWeInstrument == null) + { + // We're likely in a non-generic context + return null; + } + + var genericArgs = typeWeInstrument.GetGenericArguments(); + + if (genericArgs.Length == 0) + { + throw new ArgumentException($"Expected generics to determine TaskResult from {wireProtocolType.AssemblyQualifiedName}"); + } + + return genericArgs; + } + + private static async Task ExecuteAsyncInternalNonGeneric( + object wireProtocol, + object connection, + CancellationToken cancellationToken, + Func originalMethod) + { + using (var scope = CreateScope(wireProtocol, connection)) + { + try + { + if (originalMethod == null) + { + throw new ArgumentNullException(nameof(originalMethod)); + } + + var taskObject = originalMethod(wireProtocol, connection, cancellationToken); + var task = (Task)taskObject; + await task.ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static async Task ExecuteAsyncInternalGeneric( + object wireProtocol, + object connection, + CancellationToken cancellationToken, + Func originalMethod) + { + using (var scope = CreateScope(wireProtocol, connection)) + { + try + { + var taskObject = originalMethod(wireProtocol, connection, cancellationToken); + var typedTask = (Task)taskObject; + return await typedTask.ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static Scope CreateScope(object wireProtocol, object connection) + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + string databaseName = null; + string host = null; + string port = null; + + try + { + if (wireProtocol.TryGetFieldValue("_databaseNamespace", out object databaseNamespace)) + { + databaseNamespace?.TryGetPropertyValue("DatabaseName", out databaseName); + } + } + catch (Exception ex) + { + Log.Warning(ex, "Unable to access DatabaseName property."); + } + + try + { + if (connection != null && connection.TryGetPropertyValue("EndPoint", out object endpoint)) + { + if (endpoint is IPEndPoint ipEndPoint) + { + host = ipEndPoint.Address.ToString(); + port = ipEndPoint.Port.ToString(); + } + else if (endpoint is DnsEndPoint dnsEndPoint) + { + host = dnsEndPoint.Host; + port = dnsEndPoint.Port.ToString(); + } + } + } + catch (Exception ex) + { + Log.Warning(ex, "Unable to access EndPoint properties."); + } + + string operationName = null; + string collectionName = null; + string query = null; + string resourceName = null; + + try + { + if (wireProtocol.TryGetFieldValue("_command", out object command) && command != null) + { + // the name of the first element in the command BsonDocument will be the operation type (insert, delete, find, etc) + // and its value is the collection name + if (command.TryCallMethod("GetElement", 0, out object firstElement) && firstElement != null) + { + firstElement.TryGetPropertyValue("Name", out operationName); + + if (firstElement.TryGetPropertyValue("Value", out object collectionNameObj) && collectionNameObj != null) + { + collectionName = collectionNameObj.ToString(); + } + } + + // get the "query" element from the command BsonDocument, if it exists + if (command.TryCallMethod("Contains", "query", out bool found) && found) + { + if (command.TryCallMethod("GetElement", "query", out object queryElement) && queryElement != null) + { + if (queryElement.TryGetPropertyValue("Value", out object queryValue) && queryValue != null) + { + query = queryValue.ToString(); + } + } + } + + resourceName = $"{operationName ?? "operation"} {databaseName ?? "database"} {query ?? "query"}"; + } + } + catch (Exception ex) + { + Log.Warning(ex, "Unable to access IWireProtocol.Command properties."); + } + + Tracer tracer = Tracer.Instance; + string serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName); + + Scope scope = null; + + try + { + scope = tracer.StartActive(OperationName, serviceName: serviceName); + var span = scope.Span; + span.Type = SpanTypes.MongoDb; + span.ResourceName = resourceName; + span.SetTag(Tags.DbName, databaseName); + span.SetTag(Tags.MongoDbQuery, query); + span.SetTag(Tags.MongoDbCollection, collectionName); + span.SetTag(Tags.OutHost, host); + span.SetTag(Tags.OutPort, port); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/RedisHelper.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/RedisHelper.cs new file mode 100644 index 0000000000..bd51cfaae0 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/RedisHelper.cs @@ -0,0 +1,58 @@ +using System; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + internal static class RedisHelper + { + private const string OperationName = "redis.command"; + private const string ServiceName = "redis"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(RedisHelper)); + + internal static Scope CreateScope(Tracer tracer, string integrationName, string host, string port, string rawCommand) + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(integrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + string serviceName = string.Join("-", tracer.DefaultServiceName, ServiceName); + Scope scope = null; + + try + { + scope = tracer.StartActive(OperationName, serviceName: serviceName); + int separatorIndex = rawCommand.IndexOf(' '); + string command; + + if (separatorIndex >= 0) + { + command = rawCommand.Substring(0, separatorIndex); + } + else + { + command = rawCommand; + } + + var span = scope.Span; + span.Type = SpanTypes.Redis; + span.ResourceName = command; + span.SetTag(Tags.RedisRawCommand, rawCommand); + span.SetTag(Tags.OutHost, host); + span.SetTag(Tags.OutPort, port); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ServiceStackRedisIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ServiceStackRedisIntegration.cs new file mode 100644 index 0000000000..b4b287f8f6 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/ServiceStackRedisIntegration.cs @@ -0,0 +1,130 @@ +using System; +using System.Linq; +using System.Text; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Wraps a RedisNativeClient. + /// + public static class ServiceStackRedisIntegration + { + private const string IntegrationName = "ServiceStackRedis"; + private const string Major4 = "4"; + private const string Major5 = "5"; + private const string RedisNativeClient = "ServiceStack.Redis.RedisNativeClient"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ServiceStackRedisIntegration)); + + /// + /// Traces SendReceive. + /// + /// The return type + /// The redis native client + /// The command with args + /// The function + /// An optional function to call to complete a pipeline + /// Whether or to send without waiting for the result + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original result + [InterceptMethod( + CallerAssembly = "ServiceStack.Redis", + TargetAssembly = "ServiceStack.Redis", + TargetType = RedisNativeClient, + TargetSignatureTypes = new[] { "T", "System.Byte[][]", "System.Func`1", "System.Action`1>", ClrNames.Bool }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major5)] + public static T SendReceive( + object redisNativeClient, + byte[][] cmdWithBinaryArgs, + object fn, + object completePipelineFn, + bool sendWithoutRead, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (redisNativeClient == null) + { + throw new ArgumentNullException(nameof(redisNativeClient)); + } + + Func instrumentedMethod; + + try + { + var instrumentedType = redisNativeClient.GetInstrumentedType(RedisNativeClient); + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(SendReceive)) + .WithConcreteType(instrumentedType) + .WithParameters(cmdWithBinaryArgs, fn, completePipelineFn, sendWithoutRead) + .WithMethodGenerics(typeof(T)) + .WithNamespaceAndNameFilters(ClrNames.Ignore, "System.Byte[][]", "System.Func`1", "System.Action`1", ClrNames.Bool) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: RedisNativeClient, + methodName: nameof(SendReceive), + instanceType: redisNativeClient.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = RedisHelper.CreateScope( + Tracer.Instance, + IntegrationName, + GetHost(redisNativeClient), + GetPort(redisNativeClient), + GetRawCommand(cmdWithBinaryArgs))) + { + try + { + return instrumentedMethod(redisNativeClient, cmdWithBinaryArgs, fn, completePipelineFn, sendWithoutRead); + } + catch (Exception ex) + { + scope?.Span?.SetException(ex); + throw; + } + } + } + + private static string GetHost(object redisNativeClient) + { + return redisNativeClient.GetProperty("Host").GetValueOrDefault() ?? string.Empty; + } + + private static string GetPort(object redisNativeClient) + { + return redisNativeClient.GetProperty("Port").GetValueOrDefault().ToString(); + } + + private static string GetRawCommand(byte[][] cmdWithBinaryArgs) + { + return string.Join( + " ", + cmdWithBinaryArgs.Select( + bs => + { + try + { + return Encoding.UTF8.GetString(bs); + } + catch + { + return string.Empty; + } + })); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/ConnectionMultiplexer.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/ConnectionMultiplexer.cs new file mode 100644 index 0000000000..843094fe6b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/ConnectionMultiplexer.cs @@ -0,0 +1,238 @@ +using System; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis +{ + /// + /// Wraps calls to the StackExchange redis library. + /// + public static class ConnectionMultiplexer + { + private const string IntegrationName = "StackExchangeRedis"; + private const string RedisAssembly = "StackExchange.Redis"; + private const string StrongNameRedisAssembly = "StackExchange.Redis.StrongName"; + private const string ConnectionMultiplexerTypeName = "StackExchange.Redis.ConnectionMultiplexer"; + private const string Major1 = "1"; + private const string Major2 = "2"; + + // Parameter types + private const string StackExchangeRedisServerEndPoint = "StackExchange.Redis.ServerEndPoint"; + private const string StackExchangeRedisMessage = "StackExchange.Redis.Message"; + private const string StackExchangeRedisResultProcessorGeneric = "StackExchange.Redis.ResultProcessor`1"; + private const string StackExchangeRedisResultProcessor = "StackExchange.Redis.ResultProcessor`1"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ConnectionMultiplexer)); + + /// + /// Execute a synchronous redis operation. + /// + /// The result type + /// The connection multiplexer running the command. + /// The message to send to redis. + /// The processor to handle the result. + /// The server to call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The result + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = RedisAssembly, + TargetAssembly = RedisAssembly, + TargetType = ConnectionMultiplexerTypeName, + TargetSignatureTypes = new[] { "T", StackExchangeRedisMessage, StackExchangeRedisResultProcessorGeneric, StackExchangeRedisServerEndPoint }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = StrongNameRedisAssembly, + TargetAssembly = StrongNameRedisAssembly, + TargetType = ConnectionMultiplexerTypeName, + TargetSignatureTypes = new[] { "T", StackExchangeRedisMessage, StackExchangeRedisResultProcessorGeneric, StackExchangeRedisServerEndPoint }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + public static T ExecuteSyncImpl( + object multiplexer, + object message, + object processor, + object server, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (multiplexer == null) + { + throw new ArgumentNullException(nameof(multiplexer)); + } + + var genericType = typeof(T); + var multiplexerType = multiplexer.GetInstrumentedType(ConnectionMultiplexerTypeName); + Func instrumentedMethod; + + try + { + instrumentedMethod = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(ExecuteSyncImpl)) + .WithConcreteType(multiplexerType) + .WithParameters(message, processor, server) + .WithMethodGenerics(genericType) + .WithNamespaceAndNameFilters( + ClrNames.Ignore, + StackExchangeRedisMessage, + StackExchangeRedisResultProcessor, + StackExchangeRedisServerEndPoint) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: ConnectionMultiplexerTypeName, + methodName: nameof(ExecuteSyncImpl), + instanceType: multiplexer.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = CreateScope(multiplexer, message)) + { + try + { + return instrumentedMethod(multiplexer, message, processor, server); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Execute an asynchronous redis operation. + /// + /// The result type + /// The connection multiplexer running the command. + /// The message to send to redis. + /// The processor to handle the result. + /// The state to use for the task. + /// The server to call. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// An asynchronous task. + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = RedisAssembly, + TargetAssembly = RedisAssembly, + TargetType = ConnectionMultiplexerTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", StackExchangeRedisMessage, StackExchangeRedisResultProcessorGeneric, ClrNames.Object, StackExchangeRedisServerEndPoint }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = StrongNameRedisAssembly, + TargetAssembly = StrongNameRedisAssembly, + TargetType = ConnectionMultiplexerTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", StackExchangeRedisMessage, StackExchangeRedisResultProcessorGeneric, ClrNames.Object, StackExchangeRedisServerEndPoint }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + public static object ExecuteAsyncImpl( + object multiplexer, + object message, + object processor, + object state, + object server, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (multiplexer == null) + { + throw new ArgumentNullException(nameof(multiplexer)); + } + + var genericType = typeof(T); + var multiplexerType = multiplexer.GetInstrumentedType(ConnectionMultiplexerTypeName); + Func> instrumentedMethod; + + try + { + instrumentedMethod = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, nameof(ExecuteAsyncImpl)) + .WithConcreteType(multiplexerType) + .WithParameters(message, processor, state, server) + .WithMethodGenerics(genericType) + .WithNamespaceAndNameFilters( + ClrNames.GenericTask, + StackExchangeRedisMessage, + StackExchangeRedisResultProcessor, + ClrNames.Object, + StackExchangeRedisServerEndPoint) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: ConnectionMultiplexerTypeName, + methodName: nameof(ExecuteAsyncImpl), + instanceType: multiplexer.GetType().AssemblyQualifiedName); + throw; + } + + return ExecuteAsyncImplInternal(multiplexer, message, processor, state, server, instrumentedMethod); + } + + /// + /// Execute an asynchronous redis operation. + /// + /// The result type + /// The connection multiplexer running the command. + /// The message to send to redis. + /// The processor to handle the result. + /// The state to use for the task. + /// The server to call. + /// The original method. + /// An asynchronous task. + private static async Task ExecuteAsyncImplInternal( + object multiplexer, + object message, + object processor, + object state, + object server, + Func> originalMethod) + { + using (var scope = CreateScope(multiplexer, message)) + { + try + { + return await originalMethod(multiplexer, message, processor, state, server).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static Scope CreateScope(object multiplexer, object message) + { + var config = StackExchangeRedisHelper.GetConfiguration(multiplexer); + var hostAndPort = StackExchangeRedisHelper.GetHostAndPort(config); + var rawCommand = StackExchangeRedisHelper.GetRawCommand(multiplexer, message); + + return RedisHelper.CreateScope(Tracer.Instance, IntegrationName, hostAndPort.Item1, hostAndPort.Item2, rawCommand); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/RedisBatch.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/RedisBatch.cs new file mode 100644 index 0000000000..656d4b2e8b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/RedisBatch.cs @@ -0,0 +1,168 @@ +using System; +using System.Reflection; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis +{ + /// + /// Traces StackExchange.Redis.RedisBatch + /// + public static class RedisBatch + { + private const string IntegrationName = "StackExchangeRedis"; + private const string RedisAssembly = "StackExchange.Redis"; + private const string StrongNameRedisAssembly = "StackExchange.Redis.StrongName"; + private const string RedisBaseTypeName = "StackExchange.Redis.RedisBase"; + private const string Major1 = "1"; + private const string Major2 = "2"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(RedisBatch)); + + private static Assembly _redisAssembly; + private static Type _redisBaseType; + private static Type _batchType; + + /// + /// Execute an asynchronous redis operation. + /// + /// The result type + /// The object this method is called on + /// The message + /// The result processor + /// The server + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// An asynchronous task. + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = RedisAssembly, + TargetAssembly = RedisAssembly, + TargetType = RedisBaseTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1", "StackExchange.Redis.ServerEndPoint" }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + [InterceptMethod( + Integration = IntegrationName, + CallerAssembly = StrongNameRedisAssembly, + TargetAssembly = StrongNameRedisAssembly, + TargetType = RedisBaseTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", "StackExchange.Redis.Message", "StackExchange.Redis.ResultProcessor`1", "StackExchange.Redis.ServerEndPoint" }, + TargetMinimumVersion = Major1, + TargetMaximumVersion = Major2)] + public static object ExecuteAsync( + object redisBase, + object message, + object processor, + object server, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (redisBase == null) + { + throw new ArgumentNullException(nameof(redisBase)); + } + + return ExecuteAsyncInternal(redisBase, message, processor, server, opCode, mdToken, moduleVersionPtr); + } + + /// + /// Execute an asynchronous redis operation. + /// + /// The result type + /// The object this method is called on + /// The message + /// The result processor + /// The server + /// The used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// An asynchronous task. + private static async Task ExecuteAsyncInternal( + object redisBase, + object message, + object processor, + object server, + int callOpCode, + int mdToken, + long moduleVersionPtr) + { + if (redisBase == null) + { + throw new ArgumentNullException(nameof(redisBase)); + } + + var thisType = redisBase.GetType(); + + if (_redisAssembly == null) + { + // get these only once and cache them, + // no need for locking, race conditions are not a problem + _redisAssembly = thisType.Assembly; + _redisBaseType = _redisAssembly.GetType("StackExchange.Redis.RedisBase"); + _batchType = _redisAssembly.GetType("StackExchange.Redis.RedisBatch"); + } + + Func> instrumentedMethod; + + try + { + instrumentedMethod = MethodBuilder>> + .Start(moduleVersionPtr, mdToken, callOpCode, nameof(ExecuteAsync)) + .WithConcreteType(_redisBaseType) + .WithMethodGenerics(typeof(T)) + .WithParameters(message, processor, server) + .WithNamespaceAndNameFilters( + ClrNames.GenericTask, + "StackExchange.Redis.Message", + "StackExchange.Redis.ResultProcessor`1", + "StackExchange.Redis.ServerEndPoint") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: callOpCode, + instrumentedType: RedisBaseTypeName, + methodName: nameof(ExecuteAsync), + instanceType: thisType.AssemblyQualifiedName); + throw; + } + + // we only trace RedisBatch methods here + if (thisType == _batchType) + { + using (var scope = CreateScope(redisBase, message)) + { + try + { + return await instrumentedMethod(redisBase, message, processor, server).ConfigureAwait(false); + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + return await instrumentedMethod(redisBase, message, processor, server).ConfigureAwait(false); + } + + private static Scope CreateScope(object batch, object message) + { + var multiplexer = StackExchangeRedisHelper.GetMultiplexer(batch); + var config = StackExchangeRedisHelper.GetConfiguration(multiplexer); + var hostAndPort = StackExchangeRedisHelper.GetHostAndPort(config); + var cmd = StackExchangeRedisHelper.GetRawCommand(batch, message); + + return RedisHelper.CreateScope(Tracer.Instance, IntegrationName, hostAndPort.Item1, hostAndPort.Item2, cmd); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/StackExchangeRedisHelper.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/StackExchangeRedisHelper.cs new file mode 100644 index 0000000000..896002cd44 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/StackExchange.Redis/StackExchangeRedisHelper.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using Datadog.Trace.ClrProfiler.Emit; + +namespace Datadog.Trace.ClrProfiler.Integrations.StackExchange.Redis +{ + /// + /// Base class for redis integration. + /// + internal static class StackExchangeRedisHelper + { + /// + /// Get the configuration for the multiplexer. + /// + /// The multiplexer + /// The configuration + public static string GetConfiguration(object multiplexer) + { + return multiplexer.GetProperty("Configuration").GetValueOrDefault(); + } + + /// + /// Get the host and port from the config + /// + /// The config + /// The host and port + public static Tuple GetHostAndPort(string config) + { + string host = null; + string port = null; + + if (config != null) + { + // config can contain several settings separated by commas: + // hostname:port,name=MyName,keepAlive=180,syncTimeout=10000,abortConnect=False + // split in commas, find the one without '=', split that one on ':' + string[] hostAndPort = config.Split(',') + .FirstOrDefault(p => !p.Contains("=")) + ?.Split(':'); + + if (hostAndPort != null) + { + host = hostAndPort[0]; + } + + // check length because port is optional + if (hostAndPort?.Length > 1) + { + port = hostAndPort[1]; + } + } + + return new Tuple(host, port); + } + + /// + /// Get the raw command. + /// + /// The multiplexer + /// The message + /// The raw command + public static string GetRawCommand(object multiplexer, object message) + { + return message.GetProperty("CommandAndKey").GetValueOrDefault() ?? "COMMAND"; + } + + /// + /// GetMultiplexer returns the Multiplexer for an object + /// + /// The object + /// The multiplexer + public static object GetMultiplexer(object obj) + { + return obj.GetField("multiplexer").GetValueOrDefault(); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/AsyncTool.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/AsyncTool.cs new file mode 100644 index 0000000000..acfba173b6 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/AsyncTool.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; + +namespace Datadog.Trace.ClrProfiler.Integrations.Testing +{ + /// + /// This class is similar to AsyncHelper but removes the params array allocation, the string key allocation and the invoke by reflection. + /// + internal static class AsyncTool + { + private static readonly ConcurrentDictionary ContinuationsGeneratorCache = new ConcurrentDictionary(); + + /// + /// Adds a continuation based on the current returnValue + /// + /// Type of the state + /// Return value + /// Exception + /// State value + /// Continuation delegate + /// Continuation generator + /// Return value after the continuation + public static object AddContinuation(object returnValue, Exception ex, TState state, Func continuation, TaskContinuationGenerator generator = null) + { + if (returnValue is Task returnTask && ex is null) + { + generator ??= GetContinuationFrom(returnTask.GetType()); + return generator.SetTaskContinuation(returnTask, state, continuation); + } + + return continuation(returnValue, ex, state); + } + + /// + /// Adds a continuation based on the current returnValue + /// + /// Type of the state + /// Return value + /// Exception + /// State value + /// Continuation delegate + /// Continuation generator + /// Return value after the continuation + public static object AddContinuation(object returnValue, Exception ex, TState state, Func> continuation, TaskContinuationGenerator generator = null) + { + if (returnValue is Task returnTask && ex is null) + { + generator ??= GetContinuationFrom(returnTask.GetType()); + return generator.SetTaskContinuationAsync(returnTask, state, continuation); + } + + SynchronizationContext currentContext = SynchronizationContext.Current; + try + { + SynchronizationContext.SetSynchronizationContext(null); + return continuation(returnValue, ex, state).GetAwaiter().GetResult(); + } + finally + { + SynchronizationContext.SetSynchronizationContext(currentContext); + } + } + + /// + /// Gets the task continuation generator + /// + /// Task type + /// Task continuation generator for this kind of task + public static TaskContinuationGenerator GetTaskContinuationGenerator(Type type) + { + return GetContinuationFrom(type); + } + + private static TaskContinuationGenerator GetContinuationFrom(Type type) + { + return ContinuationsGeneratorCache.GetOrAdd(type, tType => + { + // We need to find the appropiate generic parameter for the task + + Type currentType = tType; + while (currentType != null) + { + Type[] typeArguments = currentType.GenericTypeArguments ?? Type.EmptyTypes; + switch (typeArguments.Length) + { + case 0: + return new TaskContinuationGenerator(); + case 1: + return (TaskContinuationGenerator)Activator.CreateInstance(typeof(TaskContinuationGenerator<>).MakeGenericType(typeArguments[0])); + default: + currentType = currentType.BaseType; + break; + } + } + + return new TaskContinuationGenerator(); + }); + } + + internal sealed class TaskContinuationGenerator : TaskContinuationGenerator + { + public override Task SetTaskContinuation(Task previousTask, TState state, Func continuation) + { + if (previousTask.Status == TaskStatus.RanToCompletion) + { + return Task.FromResult((TResult)continuation(((Task)previousTask).Result, null, state)); + } + + return InternalSetTaskContinuation((Task)previousTask, state, continuation); + } + + public override Task SetTaskContinuationAsync(Task previousTask, TState state, Func> continuation) + => SetTaskContinuationAsync((Task)previousTask, state, continuation); + + private static async Task InternalSetTaskContinuation(Task previousTask, TState state, Func continuation) + { + TResult result = default; + try + { + result = await previousTask.ConfigureAwait(false); + } + catch (Exception ex) + { + continuation(result, ex, state); + throw; + } + + return (TResult)continuation(result, null, state); + } + + private static async Task SetTaskContinuationAsync(Task previousTask, TState state, Func> continuation) + { + if (previousTask.Status == TaskStatus.RanToCompletion) + { + return (TResult)await continuation(previousTask.Result, null, state).ConfigureAwait(false); + } + + TResult result = default; + try + { + result = await previousTask.ConfigureAwait(false); + } + catch (Exception ex) + { + await continuation(result, ex, state).ConfigureAwait(false); + throw; + } + + return (TResult)await continuation(result, null, state).ConfigureAwait(false); + } + } + + internal class TaskContinuationGenerator + { + public virtual Task SetTaskContinuation(Task previousTask, TState state, Func continuation) + { + if (previousTask.Status == TaskStatus.RanToCompletion) + { + continuation(null, null, state); +#if NET45 + // "If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion state before it's returned to the caller." + // https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall?redirectedfrom=MSDN&view=netframework-4.5.2#System_Threading_Tasks_Task_WhenAll_System_Threading_Tasks_Task___ + return Task.WhenAll(); +#else + return Task.CompletedTask; +#endif + } + + return InternalSetTaskContinuation(previousTask, state, continuation); + } + + private static async Task InternalSetTaskContinuation(Task previousTask, TState state, Func continuation) + { + try + { + await previousTask.ConfigureAwait(false); + } + catch (Exception ex) + { + continuation(null, ex, state); + throw; + } + + continuation(null, null, state); + } + + public virtual Task SetTaskContinuationAsync(Task previousTask, TState state, Func> continuation) + { + if (previousTask.Status == TaskStatus.RanToCompletion) + { + return continuation(null, null, state); + } + + return InternalSetTaskContinuationAsync(previousTask, state, continuation); + } + + private static async Task InternalSetTaskContinuationAsync(Task previousTask, TState state, Func> continuation) + { + try + { + await previousTask.ConfigureAwait(false); + } + catch (Exception ex) + { + await continuation(null, ex, state).ConfigureAwait(false); + throw; + } + + await continuation(null, null, state).ConfigureAwait(false); + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/TestLoggerExtensions.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/TestLoggerExtensions.cs new file mode 100644 index 0000000000..7cffb08d6c --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/TestLoggerExtensions.cs @@ -0,0 +1,18 @@ +namespace Datadog.Trace.ClrProfiler.Integrations.Testing +{ + /// + /// Test logger extensions + /// + internal static class TestLoggerExtensions + { + public static void TestMethodNotFound(this Vendors.Serilog.ILogger logger) + { + logger.Error("Error: the test method can't be retrieved."); + } + + public static void TestClassTypeNotFound(this Vendors.Serilog.ILogger logger) + { + logger.Error("Error: the test class type can't be retrieved."); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/XUnitIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/XUnitIntegration.cs new file mode 100644 index 0000000000..53b9b26b7b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/Testing/XUnitIntegration.cs @@ -0,0 +1,522 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Datadog.Trace.Ci; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations.Testing +{ + /// + /// Tracing integration for XUnit testing framework + /// + public static class XUnitIntegration + { + private const string IntegrationName = "XUnit"; + private const string Major2 = "2"; + private const string Major2Minor2 = "2.2"; + + private const string XUnitNetCoreAssembly = "xunit.execution.dotnet"; + private const string XUnitDesktopAssembly = "xunit.execution.desktop"; + + private const string XUnitTestInvokerType = "Xunit.Sdk.TestInvoker`1"; + private const string XUnitTestRunnerType = "Xunit.Sdk.TestRunner`1"; + private const string XUnitTestAssemblyRunnerType = "Xunit.Sdk.TestAssemblyRunner`1"; + private const string XUnitTestOutputHelperType = "Xunit.Sdk.TestOutputHelper"; + + private const string XUnitRunAsyncMethod = "RunAsync"; + private const string XUnitRunTestCollectionAsyncMethod = "RunTestCollectionAsync"; + private const string XUnitQueueTestOutputMethod = "QueueTestOutput"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(XUnitIntegration)); + private static readonly FrameworkDescription _runtimeDescription; + + static XUnitIntegration() + { + // Preload environment variables. + CIEnvironmentValues.DecorateSpan(null); + + _runtimeDescription = FrameworkDescription.Create(); + } + + /// + /// Wrap the original Xunit.Sdk.TestInvoker`1.RunAsync method by adding instrumentation code around it. + /// + /// The TestInvoker instance we are replacing. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssemblies = new[] { XUnitNetCoreAssembly, XUnitDesktopAssembly }, + TargetType = XUnitTestInvokerType, + TargetMethod = XUnitRunAsyncMethod, + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1" })] + public static object TestInvoker_RunAsync( + object testInvoker, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (testInvoker == null) { throw new ArgumentNullException(nameof(testInvoker)); } + + Type testInvokerType = testInvoker.GetType(); + Func executeAsync; + + try + { + executeAsync = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, XUnitRunAsyncMethod) + .WithConcreteType(testInvokerType) + .WithDeclaringTypeGenerics(testInvokerType.BaseType.GenericTypeArguments) + .WithNamespaceAndNameFilters(ClrNames.GenericTask) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: XUnitTestInvokerType, + methodName: XUnitRunAsyncMethod, + instanceType: testInvokerType.AssemblyQualifiedName); + throw; + } + + object returnValue = null; + Exception exception = null; + try + { + returnValue = executeAsync(testInvoker); + } + catch (TargetInvocationException ex) + { + exception = ex.InnerException; + throw; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + returnValue = AsyncTool.AddContinuation(returnValue, exception, testInvoker, (r, ex, state) => InvokerContinuation(r, ex, state)); + } + + return returnValue; + } + + private static object InvokerContinuation(object returnValue, Exception ex, object state) + { + if (state.TryGetPropertyValue("Aggregator", out object aggregator)) + { + if (aggregator.TryCallMethod("ToException", out Exception testException)) + { + Span span = Tracer.Instance?.ActiveScope?.Span; + if (span != null && testException != null) + { + span.SetException(testException); + span.SetTag(TestTags.Status, TestTags.StatusFail); + } + } + } + + return returnValue; + } + + /// + /// Wrap the original Xunit.Sdk.TestRunner`1.RunAsync method by adding instrumentation code around it + /// + /// The TestRunner instance we are replacing. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssemblies = new[] { XUnitNetCoreAssembly, XUnitDesktopAssembly }, + TargetType = XUnitTestRunnerType, + TargetMethod = XUnitRunAsyncMethod, + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1" })] + public static object TestRunner_RunAsync( + object testRunner, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (testRunner == null) { throw new ArgumentNullException(nameof(testRunner)); } + + Type testRunnerType = testRunner.GetType(); + Func executeAsync; + + try + { + executeAsync = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, XUnitRunAsyncMethod) + .WithConcreteType(testRunnerType) + .WithDeclaringTypeGenerics(testRunnerType.BaseType.GenericTypeArguments) + .WithNamespaceAndNameFilters(ClrNames.GenericTask) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: XUnitTestRunnerType, + methodName: XUnitRunAsyncMethod, + instanceType: testRunnerType.AssemblyQualifiedName); + throw; + } + + Scope scope = CreateScope(testRunner); + if (scope is null) + { + return executeAsync(testRunner); + } + + object returnValue = null; + Exception exception = null; + try + { + // reset the start time of the span just before running the test + scope.Span.ResetStartTime(); + + // starts the test execution + returnValue = executeAsync(testRunner); + } + catch (TargetInvocationException ex) + { + exception = ex.InnerException; + throw; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + returnValue = AsyncTool.AddContinuation(returnValue, exception, scope, (r, ex, state) => TestRunnerContinuation(r, ex, state)); + } + + return returnValue; + } + + private static object TestRunnerContinuation(object returnValue, Exception ex, Scope scope) + { + if (scope.Span.GetTag(TestTags.Status) == null) + { + if (ex != null) + { + scope.Span.SetException(ex); + scope.Span.SetTag(TestTags.Status, TestTags.StatusFail); + } + else + { + scope.Span.SetTag(TestTags.Status, TestTags.StatusPass); + } + } + + scope.Dispose(); + return returnValue; + } + + /// + /// Wrap the original Xunit.Sdk.XunitTestAssemblyRunner.BeforeTestAssemblyFinishedAsync method by adding instrumentation code around it + /// + /// The XunitTestAssemblyRunner instance we are replacing. + /// Message bus instance + /// Test collection instance + /// Test cases instance + /// Cancellation token source + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The original method's return value. + [InterceptMethod( + TargetAssemblies = new[] { XUnitNetCoreAssembly, XUnitDesktopAssembly }, + TargetType = XUnitTestAssemblyRunnerType, + TargetMethod = XUnitRunTestCollectionAsyncMethod, + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1", "Xunit.Sdk.IMessageBus", "Xunit.Abstractions.ITestCollection", "System.Collections.Generic.IEnumerable`1", "System.Threading.CancellationTokenSource" })] + public static object AssemblyRunner_RunAsync( + object xunitTestAssemblyRunner, + object messageBus, + object testCollection, + object testCases, + object cancellationTokenSource, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (xunitTestAssemblyRunner == null) { throw new ArgumentNullException(nameof(xunitTestAssemblyRunner)); } + + Type xunitTestAssemblyRunnerType = xunitTestAssemblyRunner.GetType(); + Func executeAsync; + + try + { + executeAsync = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, XUnitRunTestCollectionAsyncMethod) + .WithConcreteType(xunitTestAssemblyRunnerType) + .WithParameters(messageBus, testCollection, testCases, cancellationTokenSource) + .WithNamespaceAndNameFilters(ClrNames.GenericTask, "Xunit.Sdk.IMessageBus", "Xunit.Abstractions.ITestCollection", "System.Collections.Generic.IEnumerable`1", "System.Threading.CancellationTokenSource") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: XUnitTestAssemblyRunnerType, + methodName: XUnitRunTestCollectionAsyncMethod, + instanceType: xunitTestAssemblyRunnerType.AssemblyQualifiedName); + throw; + } + + object returnValue = null; + Exception exception = null; + try + { + returnValue = executeAsync(xunitTestAssemblyRunner, messageBus, testCollection, testCases, cancellationTokenSource); + } + catch (TargetInvocationException ex) + { + exception = ex.InnerException; + throw; + } + catch (Exception ex) + { + exception = ex; + throw; + } + finally + { + returnValue = AsyncTool.AddContinuation( + returnValue, + exception, + null, + async (r, ex, state) => + { + // We have to ensure the flush of the buffer after we finish the tests of an assembly. + // For some reason, sometimes when all test are finished none of the callbacks to handling the tracer disposal is triggered. + // So the last spans in buffer aren't send to the agent. + // Other times we reach the 500 items of the buffer in a sec and the tracer start to drop spans. + // In a test scenario we must keep all spans. + await Tracer.Instance.FlushAsync().ConfigureAwait(false); + return r; + }); + } + + return returnValue; + } + + private static Scope CreateScope(object testSdk) + { + if (!Tracer.Instance.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Scope scope = null; + try + { + string testSuite = null; + string testName = null; + string skipReason = null; + List> testArguments = null; + List> testTraits = null; + + // Get test type + if (!testSdk.TryGetPropertyValue("TestClass", out Type testClassType)) + { + // if we don't have the test class type, we can't extract the info that we need. + Log.TestClassTypeNotFound(); + return null; + } + + // Get test method + if (!testSdk.TryGetPropertyValue("TestMethod", out MethodInfo testMethod)) + { + // if we don't have the test method info, we can't extract the info that we need. + Log.TestMethodNotFound(); + return null; + } + + // Get test name + testName = testMethod.Name; + + // Get skip reason + testSdk.TryGetPropertyValue("SkipReason", out skipReason); + + // Get traits + if (testSdk.TryGetPropertyValue("TestCase", out object testCase)) + { + if (testCase.TryGetPropertyValue>>("Traits", out Dictionary> traits) && traits != null) + { + if (traits.Count > 0) + { + testTraits = new List>(); + + foreach (KeyValuePair> traitValue in traits) + { + testTraits.Add(new KeyValuePair($"{TestTags.Traits}.{traitValue.Key}", string.Join(", ", traitValue.Value) ?? "(null)")); + } + } + } + } + + AssemblyName testInvokerAssemblyName = testSdk.GetType().Assembly.GetName(); + AssemblyName testClassInstanceAssemblyName = testClassType.Assembly?.GetName(); + + testSuite = testClassType.ToString(); + + // Get test parameters + ParameterInfo[] methodParameters = testMethod.GetParameters(); + if (methodParameters?.Length > 0) + { + if (testSdk.TryGetPropertyValue("TestMethodArguments", out object[] testMethodArguments)) + { + testArguments = new List>(); + + for (int i = 0; i < methodParameters.Length; i++) + { + if (i < testMethodArguments.Length) + { + testArguments.Add(new KeyValuePair($"{TestTags.Arguments}.{methodParameters[i].Name}", testMethodArguments[i]?.ToString() ?? "(null)")); + } + else + { + testArguments.Add(new KeyValuePair($"{TestTags.Arguments}.{methodParameters[i].Name}", "(default)")); + } + } + } + } + + Tracer tracer = Tracer.Instance; + string testFramework = "xUnit " + testInvokerAssemblyName.Version.ToString(); + + scope = tracer.StartActive("xunit.test"); + Span span = scope.Span; + span.SetMetric(Tags.Analytics, 1.0d); + + span.Type = SpanTypes.Test; + span.SetTraceSamplingPriority(SamplingPriority.UserKeep); + span.ResourceName = $"{testSuite}.{testName}"; + span.SetTag(TestTags.Suite, testSuite); + span.SetTag(TestTags.Name, testName); + span.SetTag(TestTags.Framework, testFramework); + span.SetTag(TestTags.Type, TestTags.TypeTest); + CIEnvironmentValues.DecorateSpan(span); + + span.SetTag(CommonTags.RuntimeName, _runtimeDescription.Name); + span.SetTag(CommonTags.RuntimeOSArchitecture, _runtimeDescription.OSArchitecture); + span.SetTag(CommonTags.RuntimeOSPlatform, _runtimeDescription.OSPlatform); + span.SetTag(CommonTags.RuntimeProcessArchitecture, _runtimeDescription.ProcessArchitecture); + span.SetTag(CommonTags.RuntimeVersion, _runtimeDescription.ProductVersion); + + if (testArguments != null) + { + foreach (KeyValuePair argument in testArguments) + { + span.SetTag(argument.Key, argument.Value); + } + } + + if (testTraits != null) + { + foreach (KeyValuePair trait in testTraits) + { + span.SetTag(trait.Key, trait.Value); + } + } + + if (skipReason != null) + { + span.SetTag(TestTags.Status, TestTags.StatusSkip); + span.SetTag(TestTags.SkipReason, skipReason); + span.Finish(TimeSpan.Zero); + scope.Dispose(); + return null; + } + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + + /// + /// Wrap the original Xunit.Sdk.TestOutputHelper.QueueTestOutput to add the TraceId and SpanId prefix to all outputs. + /// + /// The Xunit.Sdk.TestOutputHelper instance + /// The string output instance + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + [InterceptMethod( + TargetAssemblies = new[] { XUnitNetCoreAssembly, XUnitDesktopAssembly }, + TargetType = XUnitTestOutputHelperType, + TargetMethod = XUnitQueueTestOutputMethod, + TargetMinimumVersion = Major2Minor2, + TargetMaximumVersion = Major2, + TargetSignatureTypes = new[] { ClrNames.Void, ClrNames.String })] + public static void TestOutputHelper_QueueTestOutput( + object testOutputHelper, + object output, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (testOutputHelper == null) { throw new ArgumentNullException(nameof(testOutputHelper)); } + + Type testOutputHelperType = testOutputHelper.GetType(); + Action execute; + + try + { + execute = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, XUnitQueueTestOutputMethod) + .WithConcreteType(testOutputHelperType) + .WithParameters(output) + .WithNamespaceAndNameFilters(ClrNames.Void, ClrNames.String) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: XUnitTestOutputHelperType, + methodName: XUnitQueueTestOutputMethod, + instanceType: testOutputHelperType.AssemblyQualifiedName); + throw; + } + + output = $"[{CorrelationIdentifier.TraceIdKey}={CorrelationIdentifier.TraceId},{CorrelationIdentifier.SpanIdKey}={CorrelationIdentifier.SpanId}]{output}"; + execute(testOutputHelper, output); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WcfIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WcfIntegration.cs new file mode 100644 index 0000000000..1abf57890b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WcfIntegration.cs @@ -0,0 +1,170 @@ +#if !NETSTANDARD2_0 +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.ServiceModel.Channels; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// WcfIntegration + /// + public static class WcfIntegration + { + private const string IntegrationName = "Wcf"; + private const string Major4 = "4"; + + private const string ChannelHandlerTypeName = "System.ServiceModel.Dispatcher.ChannelHandler"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(WcfIntegration)); + + /// + /// Instrumentation wrapper for System.ServiceModel.Dispatcher.ChannelHandler + /// + /// The ChannelHandler instance. + /// A System.ServiceModel.Channels.RequestContext implementation instance. + /// A System.ServiceModel.OperationContext instance. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// The value returned by the instrumented method. + [InterceptMethod( + TargetAssembly = "System.ServiceModel", + TargetType = ChannelHandlerTypeName, + TargetSignatureTypes = new[] { ClrNames.Bool, "System.ServiceModel.Channels.RequestContext", "System.ServiceModel.OperationContext" }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static bool HandleRequest( + object channelHandler, + object requestContext, + object currentOperationContext, + int opCode, + int mdToken, + long moduleVersionPtr) + { + if (channelHandler == null) + { + throw new ArgumentNullException(nameof(channelHandler)); + } + + Func instrumentedMethod; + var declaringType = channelHandler.GetInstrumentedType(ChannelHandlerTypeName); + + try + { + instrumentedMethod = MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, nameof(HandleRequest)) + .WithConcreteType(declaringType) + .WithParameters(requestContext, currentOperationContext) + .WithNamespaceAndNameFilters( + ClrNames.Bool, + "System.ServiceModel.Channels.RequestContext", + "System.ServiceModel.OperationContext") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: ChannelHandlerTypeName, + methodName: nameof(HandleRequest), + instanceType: channelHandler.GetType().AssemblyQualifiedName); + throw; + } + + using (var scope = CreateScope(requestContext as RequestContext)) + { + try + { + return instrumentedMethod(channelHandler, requestContext, currentOperationContext); + } + catch (Exception ex) + { + scope.Span.SetException(ex); + throw; + } + } + } + + private static Scope CreateScope(RequestContext requestContext) + { + var requestMessage = requestContext?.RequestMessage; + + if (requestMessage == null) + { + return null; + } + + var tracer = Tracer.Instance; + + if (!tracer.Settings.IsIntegrationEnabled(IntegrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Scope scope = null; + + try + { + SpanContext propagatedContext = null; + var tagsFromHeaders = Enumerable.Empty>(); + string host = null; + string httpMethod = null; + + if (requestMessage.Properties.TryGetValue("httpRequest", out var httpRequestProperty) && + httpRequestProperty is HttpRequestMessageProperty httpRequestMessageProperty) + { + // we're using an http transport + host = httpRequestMessageProperty.Headers[HttpRequestHeader.Host]; + httpMethod = httpRequestMessageProperty.Method?.ToUpperInvariant(); + + // try to extract propagated context values from http headers + if (tracer.ActiveScope == null) + { + try + { + var headers = httpRequestMessageProperty.Headers.Wrap(); + propagatedContext = SpanContextPropagator.Instance.Extract(headers); + tagsFromHeaders = SpanContextPropagator.Instance.ExtractHeaderTags(headers, tracer.Settings.HeaderTags); + } + catch (Exception ex) + { + Log.Error(ex, "Error extracting propagated HTTP headers."); + } + } + } + + scope = tracer.StartActive("wcf.request", propagatedContext); + var span = scope.Span; + + span.DecorateWebServerSpan( + resourceName: requestMessage.Headers.Action ?? requestMessage.Headers.To?.LocalPath, + httpMethod, + host, + httpUrl: requestMessage.Headers.To?.AbsoluteUri, + tags: tagsFromHeaders); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + // always returns the scope, even if it's null + return scope; + } + } +} + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WebRequestIntegration.cs b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WebRequestIntegration.cs new file mode 100644 index 0000000000..2f53cd272b --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/Integrations/WebRequestIntegration.cs @@ -0,0 +1,201 @@ +using System; +using System.Net; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.ClrProfiler.Integrations +{ + /// + /// Tracer integration for WebRequest. + /// + public static class WebRequestIntegration + { + private const string WebRequestTypeName = "System.Net.WebRequest"; + private const string IntegrationName = "WebRequest"; + private const string Major4 = "4"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(WebRequestIntegration)); + + /// + /// Instrumentation wrapper for . + /// + /// The instance to instrument. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the value returned by the inner method call. + [InterceptMethod( + TargetAssembly = "System", // .NET Framework + TargetType = WebRequestTypeName, + TargetSignatureTypes = new[] { "System.Net.WebResponse" }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssembly = "System.Net.Requests", // .NET Core + TargetType = WebRequestTypeName, + TargetSignatureTypes = new[] { "System.Net.WebResponse" }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object GetResponse(object webRequest, int opCode, int mdToken, long moduleVersionPtr) + { + if (webRequest == null) + { + throw new ArgumentNullException(nameof(webRequest)); + } + + const string methodName = nameof(GetResponse); + + Func callGetResponse; + + try + { + var instrumentedType = webRequest.GetInstrumentedType("System.Net.WebRequest"); + callGetResponse = + MethodBuilder> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(instrumentedType) + .WithNamespaceAndNameFilters("System.Net.WebResponse") + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: WebRequestTypeName, + methodName: methodName, + instanceType: webRequest.GetType().AssemblyQualifiedName); + throw; + } + + var request = (WebRequest)webRequest; + + if (!(request is HttpWebRequest) || !IsTracingEnabled(request)) + { + return callGetResponse(webRequest); + } + + using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, request.Method, request.RequestUri, IntegrationName)) + { + try + { + if (scope != null) + { + // add distributed tracing headers to the HTTP request + SpanContextPropagator.Instance.Inject(scope.Span.Context, request.Headers.Wrap()); + } + + WebResponse response = callGetResponse(webRequest); + + if (scope != null && response is HttpWebResponse webResponse) + { + scope.Span.SetTag(Tags.HttpStatusCode, ((int)webResponse.StatusCode).ToString()); + } + + return response; + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + /// + /// Instrumentation wrapper for . + /// + /// The instance to instrument. + /// The OpCode used in the original method call. + /// The mdToken of the original method call. + /// A pointer to the module version GUID. + /// Returns the value returned by the inner method call. + [InterceptMethod( + TargetAssembly = "System", // .NET Framework + TargetType = WebRequestTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1" }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + [InterceptMethod( + TargetAssembly = "System.Net.Requests", // .NET Core + TargetType = WebRequestTypeName, + TargetSignatureTypes = new[] { "System.Threading.Tasks.Task`1" }, + TargetMinimumVersion = Major4, + TargetMaximumVersion = Major4)] + public static object GetResponseAsync(object webRequest, int opCode, int mdToken, long moduleVersionPtr) + { + const string methodName = nameof(GetResponseAsync); + Func> callGetResponseAsync; + + try + { + var instrumentedType = webRequest.GetInstrumentedType("System.Net.WebRequest"); + callGetResponseAsync = + MethodBuilder>> + .Start(moduleVersionPtr, mdToken, opCode, methodName) + .WithConcreteType(instrumentedType) + .WithNamespaceAndNameFilters(ClrNames.GenericTask) + .Build(); + } + catch (Exception ex) + { + Log.ErrorRetrievingMethod( + exception: ex, + moduleVersionPointer: moduleVersionPtr, + mdToken: mdToken, + opCode: opCode, + instrumentedType: WebRequestTypeName, + methodName: methodName, + instanceType: webRequest.GetType().AssemblyQualifiedName); + throw; + } + + return GetResponseAsyncInternal((WebRequest)webRequest, callGetResponseAsync); + } + + private static async Task GetResponseAsyncInternal(WebRequest webRequest, Func> originalMethod) + { + if (!(webRequest is HttpWebRequest) || !IsTracingEnabled(webRequest)) + { + return await originalMethod(webRequest).ConfigureAwait(false); + } + + using (var scope = ScopeFactory.CreateOutboundHttpScope(Tracer.Instance, webRequest.Method, webRequest.RequestUri, IntegrationName)) + { + try + { + if (scope != null) + { + // add distributed tracing headers to the HTTP request + SpanContextPropagator.Instance.Inject(scope.Span.Context, webRequest.Headers.Wrap()); + } + + WebResponse response = await originalMethod(webRequest).ConfigureAwait(false); + + if (scope != null && response is HttpWebResponse webResponse) + { + scope.Span.SetTag(Tags.HttpStatusCode, ((int)webResponse.StatusCode).ToString()); + } + + return response; + } + catch (Exception ex) + { + scope?.Span.SetException(ex); + throw; + } + } + } + + private static bool IsTracingEnabled(WebRequest request) + { + // check if tracing is disabled for this request via http header + string value = request.Headers[HttpHeaderNames.TracingEnabled]; + return !string.Equals(value, "false", StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/MemberAccessor.cs b/src/Datadog.Trace.ClrProfiler.Managed/MemberAccessor.cs new file mode 100644 index 0000000000..708bbb2f4f --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/MemberAccessor.cs @@ -0,0 +1,52 @@ +using System; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Provides helper methods to access object members by emitting IL dynamically. + /// + [Obsolete("This type will be removed in a future version of this library.")] + public static class MemberAccessor + { + /// + /// Tries to call an instance method with the specified name, a single parameter, and a return value. + /// + /// The type of the method's single parameter. + /// The type of the method's result value. + /// The object to call the method on. + /// The name of the method to call. + /// The value to pass as the method's single argument. + /// The value returned by the method. + /// true if the method was found, false otherwise. + public static bool TryCallMethod(this object source, string methodName, TArg1 arg1, out TResult value) + { + return Emit.ObjectExtensions.TryCallMethod(source, methodName, arg1, out value); + } + + /// + /// Tries to get the value of an instance property with the specified name. + /// + /// The type of the property. + /// The value that contains the property. + /// The name of the property. + /// The value of the property, or null if the property is not found. + /// true if the property exists, otherwise false. + public static bool TryGetPropertyValue(this object source, string propertyName, out TResult value) + { + return Emit.ObjectExtensions.TryGetPropertyValue(source, propertyName, out value); + } + + /// + /// Tries to get the value of an instance field with the specified name. + /// + /// The type of the field. + /// The value that contains the field. + /// The name of the field. + /// The value of the field, or null if the field is not found. + /// true if the field exists, otherwise false. + public static bool TryGetFieldValue(this object source, string fieldName, out TResult value) + { + return Emit.ObjectExtensions.TryGetFieldValue(source, fieldName, out value); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/MetadataNames.cs b/src/Datadog.Trace.ClrProfiler.Managed/MetadataNames.cs new file mode 100644 index 0000000000..abec3c54a8 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/MetadataNames.cs @@ -0,0 +1,38 @@ +using System; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Holds names obtained through the metadata interface. + /// + public class MetadataNames + { + /// + /// Initializes a new instance of the class. + /// + /// The module's name. + /// The type's name. + /// The method's name. + public MetadataNames(string moduleName, string typeName, string methodName) + { + ModuleName = moduleName ?? throw new ArgumentNullException(nameof(moduleName)); + TypeName = typeName ?? throw new ArgumentNullException(nameof(typeName)); + MethodName = methodName ?? throw new ArgumentNullException(nameof(methodName)); + } + + /// + /// Gets the module's name. + /// + public string ModuleName { get; } + + /// + /// Gets the type's full name. + /// + public string TypeName { get; } + + /// + /// Gets the method's name. + /// + public string MethodName { get; } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/NativeMethods.cs b/src/Datadog.Trace.ClrProfiler.Managed/NativeMethods.cs new file mode 100644 index 0000000000..9ab64e6f1d --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/NativeMethods.cs @@ -0,0 +1,36 @@ +using System; +using System.Runtime.InteropServices; + +// ReSharper disable MemberHidesStaticFromOuterClass +namespace Datadog.Trace.ClrProfiler +{ + internal static class NativeMethods + { + private static readonly bool IsWindows = string.Equals(FrameworkDescription.Create().OSPlatform, "Windows", StringComparison.OrdinalIgnoreCase); + + public static bool IsProfilerAttached() + { + if (IsWindows) + { + return Windows.IsProfilerAttached(); + } + + return NonWindows.IsProfilerAttached(); + } + + // the "dll" extension is required on .NET Framework + // and optional on .NET Core + private static class Windows + { + [DllImport("Datadog.Trace.ClrProfiler.Native.dll")] + public static extern bool IsProfilerAttached(); + } + + // assume .NET Core if not running on Windows + private static class NonWindows + { + [DllImport("Datadog.Trace.ClrProfiler.Native")] + public static extern bool IsProfilerAttached(); + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Managed/ScopeFactory.cs b/src/Datadog.Trace.ClrProfiler.Managed/ScopeFactory.cs new file mode 100644 index 0000000000..76976f06c8 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Managed/ScopeFactory.cs @@ -0,0 +1,162 @@ +using System; +using System.Data; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace.ClrProfiler +{ + /// + /// Convenience class that creates scopes and populates them with some standard details. + /// + internal static class ScopeFactory + { + public const string OperationName = "http.request"; + public const string ServiceName = "http-client"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ScopeFactory)); + + /// + /// Creates a scope for outbound http requests and populates some common details. + /// + /// The tracer instance to use to create the new scope. + /// The HTTP method used by the request. + /// The URI requested by the request. + /// The name of the integration creating this scope. + /// A new pre-populated scope. + public static Scope CreateOutboundHttpScope(Tracer tracer, string httpMethod, Uri requestUri, string integrationName) + { + if (!tracer.Settings.IsIntegrationEnabled(integrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Scope scope = null; + + try + { + Span parent = tracer.ActiveScope?.Span; + + if (parent != null && + parent.Type == SpanTypes.Http && + parent.GetTag(Tags.InstrumentationName) != null) + { + // we are already instrumenting this, + // don't instrument nested methods that belong to the same stacktrace + // e.g. HttpClientHandler.SendAsync() -> SocketsHttpHandler.SendAsync() + return null; + } + + string resourceUrl = requestUri != null ? UriHelpers.CleanUri(requestUri, removeScheme: true, tryRemoveIds: true) : null; + string httpUrl = requestUri != null ? UriHelpers.CleanUri(requestUri, removeScheme: false, tryRemoveIds: false) : null; + + scope = tracer.StartActive(OperationName, serviceName: $"{tracer.DefaultServiceName}-{ServiceName}"); + var span = scope.Span; + + span.Type = SpanTypes.Http; + span.ResourceName = $"{httpMethod} {resourceUrl}"; + + span.SetTag(Tags.SpanKind, SpanKinds.Client); + span.SetTag(Tags.HttpMethod, httpMethod?.ToUpperInvariant()); + span.SetTag(Tags.HttpUrl, httpUrl); + span.SetTag(Tags.InstrumentationName, integrationName); + + // set analytics sample rate if enabled + if (integrationName != null) + { + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + // always returns the scope, even if it's null because we couldn't create it, + // or we couldn't populate it completely (some tags is better than no tags) + return scope; + } + + public static Scope CreateDbCommandScope(Tracer tracer, IDbCommand command, string integrationName) + { + if (!tracer.Settings.IsIntegrationEnabled(integrationName)) + { + // integration disabled, don't create a scope, skip this trace + return null; + } + + Scope scope = null; + + try + { + string dbType = GetDbType(command.GetType().Name); + + if (dbType == null) + { + // don't create a scope, skip this trace + return null; + } + + Span parent = tracer.ActiveScope?.Span; + + if (parent != null && + parent.Type == SpanTypes.Sql && + parent.GetTag(Tags.DbType) == dbType && + parent.ResourceName == command.CommandText) + { + // we are already instrumenting this, + // don't instrument nested methods that belong to the same stacktrace + // e.g. ExecuteReader() -> ExecuteReader(commandBehavior) + return null; + } + + string serviceName = $"{tracer.DefaultServiceName}-{dbType}"; + string operationName = $"{dbType}.query"; + + scope = tracer.StartActive(operationName, serviceName: serviceName); + var span = scope.Span; + span.SetTag(Tags.DbType, dbType); + span.SetTag(Tags.InstrumentationName, integrationName); + span.AddTagsFromDbCommand(command); + + // set analytics sample rate if enabled + var analyticsSampleRate = tracer.Settings.GetIntegrationAnalyticsSampleRate(integrationName, enabledWithGlobalSetting: false); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + } + catch (Exception ex) + { + Log.Error(ex, "Error creating or populating scope."); + } + + return scope; + } + + public static string GetDbType(string commandTypeName) + { + switch (commandTypeName) + { + case "SqlCommand": + return "sql-server"; + case "NpgsqlCommand": + return "postgres"; + case "MySqlCommand": + return "mysql"; + case "OracleCommand": + return "oracle"; + case "InterceptableDbCommand": + case "ProfiledDbCommand": + // don't create spans for these + return null; + default: + const string commandSuffix = "Command"; + + // remove "Command" suffix if present + return commandTypeName.EndsWith(commandSuffix) + ? commandTypeName.Substring(0, commandTypeName.Length - commandSuffix.Length).ToLowerInvariant() + : commandTypeName.ToLowerInvariant(); + } + } + } +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt b/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt new file mode 100644 index 0000000000..8c51d8abec --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required (VERSION 3.8) +cmake_policy(SET CMP0015 NEW) + +project("Datadog.Trace.ClrProfiler.Native" VERSION 1.19.1) + +add_compile_options(-std=c++11 -fPIC -fms-extensions) +add_compile_options(-DBIT64 -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX -DUNICODE) +add_compile_options(-Wno-invalid-noreturn -Wno-macro-redefined) + +SET(MANAGED_LOADER_DIRECTORY + ${CMAKE_SOURCE_DIR}/../bin/ProfilerResources/netcoreapp2.0 +) + +add_custom_command( + OUTPUT Datadog.Trace.ClrProfiler.Managed.Loader.dll.o + COMMAND cp "${MANAGED_LOADER_DIRECTORY}/Datadog.Trace.ClrProfiler.Managed.Loader.dll" Datadog.Trace.ClrProfiler.Managed.Loader.dll && ld -r -b binary -o Datadog.Trace.ClrProfiler.Managed.Loader.dll.o Datadog.Trace.ClrProfiler.Managed.Loader.dll + DEPENDS ${MANAGED_LOADER_DIRECTORY}/Datadog.Trace.ClrProfiler.Managed.Loader.dll +) +add_custom_command( + OUTPUT Datadog.Trace.ClrProfiler.Managed.Loader.pdb.o + COMMAND cp "${MANAGED_LOADER_DIRECTORY}/Datadog.Trace.ClrProfiler.Managed.Loader.pdb" Datadog.Trace.ClrProfiler.Managed.Loader.pdb && ld -r -b binary -o Datadog.Trace.ClrProfiler.Managed.Loader.pdb.o Datadog.Trace.ClrProfiler.Managed.Loader.pdb + DEPENDS ${MANAGED_LOADER_DIRECTORY}/Datadog.Trace.ClrProfiler.Managed.Loader.pdb +) +SET(GENERATED_OBJ_FILES + ${CMAKE_BINARY_DIR}/Datadog.Trace.ClrProfiler.Managed.Loader.dll.o + ${CMAKE_BINARY_DIR}/Datadog.Trace.ClrProfiler.Managed.Loader.pdb.o +) +SET_SOURCE_FILES_PROPERTIES( + ${GENERATED_OBJ_FILES} + PROPERTIES + EXTERNAL_OBJECT false + GENERATED true +) + +add_library("Datadog.Trace.ClrProfiler.Native.static" STATIC + class_factory.cpp + clr_helpers.cpp + cor_profiler_base.cpp + cor_profiler.cpp + il_rewriter_wrapper.cpp + il_rewriter.cpp + integration_loader.cpp + integration.cpp + logging.cpp + metadata_builder.cpp + miniutf.cpp + sig_helpers.cpp + string.cpp + util.cpp + ${GENERATED_OBJ_FILES} +) +set_target_properties("Datadog.Trace.ClrProfiler.Native.static" PROPERTIES PREFIX "") +target_include_directories("Datadog.Trace.ClrProfiler.Native.static" + PUBLIC ../../lib/coreclr/src/pal/inc/rt + PUBLIC ../../lib/coreclr/src/pal/prebuilt/inc + PUBLIC ../../lib/coreclr/src/pal/inc + PUBLIC ../../lib/coreclr/src/inc + PUBLIC $ + PUBLIC $ +) +target_link_libraries("Datadog.Trace.ClrProfiler.Native.static" + /opt/re2/obj/libre2.a + -static-libgcc + -static-libstdc++ +) + +add_library("Datadog.Trace.ClrProfiler.Native" SHARED + dllmain.cpp + interop.cpp +) +set_target_properties("Datadog.Trace.ClrProfiler.Native" PROPERTIES PREFIX "") +target_link_libraries("Datadog.Trace.ClrProfiler.Native" "Datadog.Trace.ClrProfiler.Native.static") diff --git a/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.DLL.vcxproj b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.DLL.vcxproj new file mode 100644 index 0000000000..3e9eff85fe --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.DLL.vcxproj @@ -0,0 +1,213 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {C0C8D381-D6B9-4C76-9428-F40F2FA93A9A} + DatadogTraceClrProfilerNativeDLL + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + bin\$(Configuration)\x86\ + obj\$(Configuration)\x86\ + Datadog.Trace.ClrProfiler.Native + .dll + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\$(Platform)\ + Datadog.Trace.ClrProfiler.Native + .dll + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\$(Platform)\ + Datadog.Trace.ClrProfiler.Native + .dll + + + bin\$(Configuration)\x86\ + obj\$(Configuration)\x86\ + Datadog.Trace.ClrProfiler.Native + .dll + + + + Level3 + Disabled + MultiThreadedDebug + false + true + stdcpp17 + true + true + + + Windows + true + .\Datadog.Trace.ClrProfiler.Native.def + + + IF EXIST $(SolutionDir)\pre-build-events-cpp.bat CALL $(SolutionDir)\pre-build-events-cpp.bat "$(TargetPath)" "$(TargetFileName)" "$(TargetDir)" "$(TargetName)" + + + Remove potentially locked outputs (dll/pdb/xml) + + + + + Level3 + Disabled + true + MultiThreadedDebug + true + stdcpp17 + true + + + Windows + true + .\Datadog.Trace.ClrProfiler.Native.def + + + IF EXIST $(SolutionDir)\pre-build-events-cpp.bat CALL $(SolutionDir)\pre-build-events-cpp.bat "$(TargetPath)" "$(TargetFileName)" "$(TargetDir)" "$(TargetName)" + Remove potentially locked outputs (dll/pdb/xml) + + + + + Level3 + MaxSpeed + MultiThreaded + true + AnySuitable + true + Speed + true + true + stdcpp17 + true + + + Windows + true + true + true + .\Datadog.Trace.ClrProfiler.Native.def + + + IF EXIST $(SolutionDir)\pre-build-events-cpp.bat CALL $(SolutionDir)\pre-build-events-cpp.bat "$(TargetPath)" "$(TargetFileName)" "$(TargetDir)" "$(TargetName)" + Remove potentially locked outputs (dll/pdb/xml) + + + + + Level3 + MaxSpeed + MultiThreaded + true + AnySuitable + true + Speed + true + true + stdcpp17 + true + + + Windows + true + true + true + .\Datadog.Trace.ClrProfiler.Native.def + + + IF EXIST $(SolutionDir)\pre-build-events-cpp.bat CALL $(SolutionDir)\pre-build-events-cpp.bat "$(TargetPath)" "$(TargetFileName)" "$(TargetDir)" "$(TargetName)" + Remove potentially locked outputs (dll/pdb/xml) + + + + + {91b6272f-5780-4c94-8071-dbba7b4f67f3} + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.def b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.def new file mode 100644 index 0000000000..ef534202d2 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.def @@ -0,0 +1,7 @@ +LIBRARY "Datadog.Trace.ClrProfiler.Native.dll" + +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + IsProfilerAttached + GetAssemblyAndSymbolsBytes diff --git a/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.vcxproj b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.vcxproj new file mode 100644 index 0000000000..08b5577f7e --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/Datadog.Trace.ClrProfiler.Native.vcxproj @@ -0,0 +1,196 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {91B6272F-5780-4C94-8071-DBBA7B4F67F3} + Win32Proj + ClrProfiler + 10.0 + ..\..\lib\coreclr + Datadog.Trace.ClrProfiler.Native + + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + true + v142 + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + StaticLibrary + false + v142 + true + Unicode + + + + + + + + + true + bin\$(Configuration)\$(Platform)\static\ + obj\$(Configuration)\$(Platform)\static\ + $(CORECLR_PATH)\src\pal\prebuilt\inc;$(CORECLR_PATH)\src\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + true + bin\$(Configuration)\x86\static\ + obj\$(Configuration)\x86\static\ + $(CORECLR_PATH)\src\pal\prebuilt\inc;$(CORECLR_PATH)\src\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + false + bin\$(Configuration)\$(Platform)\static\ + obj\$(Configuration)\$(Platform)\static\ + $(CORECLR_PATH)\src\pal\prebuilt\inc;$(CORECLR_PATH)\src\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + false + bin\$(Configuration)\x86\static\ + obj\$(Configuration)\x86\static\ + $(CORECLR_PATH)\src\pal\prebuilt\inc;$(CORECLR_PATH)\src\inc;$(VC_IncludePath);$(WindowsSDK_IncludePath); + + + + Level3 + Disabled + MultiThreadedDebug + stdcpp17 + false + true + true + true + BIT64;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + + + Level3 + Disabled + MultiThreadedDebug + stdcpp17 + true + true + true + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + MachineX86 + + + + + Level3 + MaxSpeed + MultiThreaded + stdcpp17 + AnySuitable + true + Speed + true + true + true + true + _TARGET_64BIT;_UNICODE;UNICODE;%(PreprocessorDefinitions) + + + + + Level3 + MaxSpeed + MultiThreaded + stdcpp17 + AnySuitable + true + Speed + true + true + true + true + _UNICODE;UNICODE;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props b/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props new file mode 100644 index 0000000000..8c119d5413 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/Directory.Build.props @@ -0,0 +1,2 @@ + + diff --git a/src/Datadog.Trace.ClrProfiler.Native/Resource.rc b/src/Datadog.Trace.ClrProfiler.Native/Resource.rc new file mode 100644 index 0000000000..7b14bc0cc2 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/Resource.rc @@ -0,0 +1,110 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,19,1,0 + PRODUCTVERSION 1,19,1,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Datadog, Inc." + VALUE "FileDescription", "Datadog CLR Profiler" + VALUE "FileVersion", "1.19.1.0" + VALUE "InternalName", "Datadog.Trace.ClrProfiler.Native.DLL" + VALUE "LegalCopyright", "Copyright 2017 Datadog, Inc." + VALUE "OriginalFilename", "Datadog.Trace.ClrProfiler.Native.DLL" + VALUE "ProductName", "Datadog .NET Tracer" + VALUE "ProductVersion", "1.19.1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////////// +// +// ASSEMBLY +// + +NETCOREAPP20_MANAGED_ENTRYPOINT_DLL ASSEMBLY "..\\bin\\ProfilerResources\\netcoreapp2.0\\Datadog.Trace.ClrProfiler.Managed.Loader.dll" +NETCOREAPP20_MANAGED_ENTRYPOINT_SYMBOLS SYMBOLS "..\\bin\\ProfilerResources\\netcoreapp2.0\\Datadog.Trace.ClrProfiler.Managed.Loader.pdb" +NET45_MANAGED_ENTRYPOINT_DLL ASSEMBLY "..\\bin\\ProfilerResources\\net45\\Datadog.Trace.ClrProfiler.Managed.Loader.dll" +NET45_MANAGED_ENTRYPOINT_SYMBOLS SYMBOLS "..\\bin\\ProfilerResources\\net45\\Datadog.Trace.ClrProfiler.Managed.Loader.pdb" + + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/Datadog.Trace.ClrProfiler.Native/class_factory.cpp b/src/Datadog.Trace.ClrProfiler.Native/class_factory.cpp new file mode 100644 index 0000000000..7aa6873d75 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/class_factory.cpp @@ -0,0 +1,61 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. + +#include "class_factory.h" +#include "cor_profiler.h" +#include "logging.h" +#include "version.h" + +ClassFactory::ClassFactory() : refCount(0) {} + +ClassFactory::~ClassFactory() {} + +HRESULT STDMETHODCALLTYPE ClassFactory::QueryInterface(REFIID riid, + void** ppvObject) { + if (riid == IID_IUnknown || riid == IID_IClassFactory) { + *ppvObject = this; + this->AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE ClassFactory::AddRef() { + return std::atomic_fetch_add(&this->refCount, 1) + 1; +} + +ULONG STDMETHODCALLTYPE ClassFactory::Release() { + int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; + if (count <= 0) { + delete this; + } + + return count; +} + +// profiler entry point +HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown* pUnkOuter, + REFIID riid, + void** ppvObject) { + if (pUnkOuter != nullptr) { + *ppvObject = nullptr; + return CLASS_E_NOAGGREGATION; + } + + trace::Info("Datadog CLR Profiler ", PROFILER_VERSION, +#ifdef BIT64 + " 64-bit" +#else + " 32-bit" +#endif + ); + trace::Debug("ClassFactory::CreateInstance"); + + auto profiler = new trace::CorProfiler(); + return profiler->QueryInterface(riid, ppvObject); +} + +HRESULT STDMETHODCALLTYPE ClassFactory::LockServer(BOOL fLock) { return S_OK; } diff --git a/src/Datadog.Trace.ClrProfiler.Native/class_factory.h b/src/Datadog.Trace.ClrProfiler.Native/class_factory.h new file mode 100644 index 0000000000..c7a36b8daa --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/class_factory.h @@ -0,0 +1,27 @@ +#ifndef DD_CLR_PROFILER_CLASS_FACTORY_H_ +#define DD_CLR_PROFILER_CLASS_FACTORY_H_ + +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. + +#include +#include "unknwn.h" + +class ClassFactory : public IClassFactory { + private: + std::atomic refCount; + + public: + ClassFactory(); + virtual ~ClassFactory(); + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, + void** ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef(void) override; + ULONG STDMETHODCALLTYPE Release(void) override; + HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown* pUnkOuter, REFIID riid, + void** ppvObject) override; + HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override; +}; + +#endif // DD_CLR_PROFILER_CLASS_FACTORY_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.cpp b/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.cpp new file mode 100644 index 0000000000..14438d83c6 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.cpp @@ -0,0 +1,1002 @@ +#include "clr_helpers.h" + +#include + +#include +#include +#include "environment_variables.h" +#include "logging.h" +#include "macros.h" +#include "pal.h" +#include "sig_helpers.h" + +namespace trace { + +RuntimeInformation GetRuntimeInformation(ICorProfilerInfo3* info) { + COR_PRF_RUNTIME_TYPE runtime_type; + USHORT major_version; + USHORT minor_version; + USHORT build_version; + USHORT qfe_version; + + auto hr = info->GetRuntimeInformation(nullptr, &runtime_type, &major_version, &minor_version, &build_version, &qfe_version, 0, nullptr, nullptr); + if (FAILED(hr)) { + return {}; + } + + return {runtime_type, major_version, minor_version, build_version, qfe_version}; +} + +AssemblyInfo GetAssemblyInfo(ICorProfilerInfo3* info, + const AssemblyID& assembly_id) { + WCHAR assembly_name[kNameMaxSize]; + DWORD assembly_name_len = 0; + AppDomainID app_domain_id; + ModuleID manifest_module_id; + + auto hr = info->GetAssemblyInfo(assembly_id, kNameMaxSize, &assembly_name_len, + assembly_name, &app_domain_id, &manifest_module_id); + + if (FAILED(hr) || assembly_name_len == 0) { + return {}; + } + + WCHAR app_domain_name[kNameMaxSize]; + DWORD app_domain_name_len = 0; + + hr = info->GetAppDomainInfo(app_domain_id, kNameMaxSize, &app_domain_name_len, + app_domain_name, nullptr); + + if (FAILED(hr) || app_domain_name_len == 0) { + return {}; + } + + return {assembly_id, WSTRING(assembly_name), manifest_module_id, app_domain_id, + WSTRING(app_domain_name)}; +} + +AssemblyMetadata GetAssemblyImportMetadata( + const ComPtr& assembly_import) { + mdAssembly current = mdAssemblyNil; + auto hr = assembly_import->GetAssemblyFromScope(¤t); + if (FAILED(hr)) { + return {}; + } + WCHAR name[kNameMaxSize]; + DWORD name_len = 0; + ASSEMBLYMETADATA assembly_metadata{}; + DWORD assembly_flags = 0; + const ModuleID placeholder_module_id = 0; + + hr = assembly_import->GetAssemblyProps(current, nullptr, nullptr, nullptr, + name, kNameMaxSize, &name_len, + &assembly_metadata, &assembly_flags); + if (FAILED(hr) || name_len == 0) { + return {}; + } + return AssemblyMetadata( + placeholder_module_id, name, current, assembly_metadata.usMajorVersion, + assembly_metadata.usMinorVersion, assembly_metadata.usBuildNumber, + assembly_metadata.usRevisionNumber); +} + +AssemblyMetadata GetReferencedAssemblyMetadata( + const ComPtr& assembly_import, + const mdAssemblyRef& assembly_ref) { + WCHAR name[kNameMaxSize]; + DWORD name_len = 0; + ASSEMBLYMETADATA assembly_metadata{}; + DWORD assembly_flags = 0; + const ModuleID module_id_placeholder = 0; + const auto hr = assembly_import->GetAssemblyRefProps( + assembly_ref, nullptr, nullptr, name, kNameMaxSize, &name_len, + &assembly_metadata, nullptr, nullptr, &assembly_flags); + if (FAILED(hr) || name_len == 0) { + return {}; + } + return AssemblyMetadata( + module_id_placeholder, name, assembly_ref, + assembly_metadata.usMajorVersion, assembly_metadata.usMinorVersion, + assembly_metadata.usBuildNumber, assembly_metadata.usRevisionNumber); +} + +std::vector GetSignatureByteRepresentation( + ULONG signature_length, PCCOR_SIGNATURE raw_signature) { + std::vector signature_data(signature_length); + for (ULONG i = 0; i < signature_length; i++) { + signature_data[i] = raw_signature[i]; + } + + return signature_data; +} + +FunctionInfo GetFunctionInfo(const ComPtr& metadata_import, + const mdToken& token) { + mdToken parent_token = mdTokenNil; + mdToken method_spec_token = mdTokenNil; + mdToken method_def_token = mdTokenNil; + WCHAR function_name[kNameMaxSize]{}; + DWORD function_name_len = 0; + + PCCOR_SIGNATURE raw_signature; + ULONG raw_signature_len; + BOOL is_generic = false; + std::vector final_signature_bytes; + std::vector method_spec_signature; + + HRESULT hr = E_FAIL; + const auto token_type = TypeFromToken(token); + switch (token_type) { + case mdtMemberRef: + hr = metadata_import->GetMemberRefProps( + token, &parent_token, function_name, kNameMaxSize, &function_name_len, + &raw_signature, &raw_signature_len); + break; + case mdtMethodDef: + hr = metadata_import->GetMemberProps( + token, &parent_token, function_name, kNameMaxSize, &function_name_len, + nullptr, &raw_signature, &raw_signature_len, nullptr, nullptr, + nullptr, nullptr, nullptr); + break; + case mdtMethodSpec: { + hr = metadata_import->GetMethodSpecProps( + token, &parent_token, &raw_signature, &raw_signature_len); + is_generic = true; + if (FAILED(hr)) { + return {}; + } + const auto generic_info = GetFunctionInfo(metadata_import, parent_token); + final_signature_bytes = generic_info.signature.data; + method_spec_signature = + GetSignatureByteRepresentation(raw_signature_len, raw_signature); + std::memcpy(function_name, generic_info.name.c_str(), + sizeof(WCHAR) * (generic_info.name.length() + 1)); + function_name_len = DWORD(generic_info.name.length() + 1); + method_spec_token = token; + method_def_token = generic_info.id; + } break; + default: + Warn("[trace::GetFunctionInfo] unknown token type: {}", token_type); + return {}; + } + if (FAILED(hr) || function_name_len == 0) { + return {}; + } + + // parent_token could be: TypeDef, TypeRef, TypeSpec, ModuleRef, MethodDef + const auto type_info = GetTypeInfo(metadata_import, parent_token); + + if (is_generic) { + // use the generic constructor and feed both method signatures + return {method_spec_token, + WSTRING(function_name), + type_info, + MethodSignature(final_signature_bytes), + MethodSignature(method_spec_signature), + method_def_token}; + } + + final_signature_bytes = + GetSignatureByteRepresentation(raw_signature_len, raw_signature); + + return {token, WSTRING(function_name), type_info, + MethodSignature(final_signature_bytes)}; +} + +ModuleInfo GetModuleInfo(ICorProfilerInfo3* info, const ModuleID& module_id) { + const DWORD module_path_size = 260; + WCHAR module_path[module_path_size]{}; + DWORD module_path_len = 0; + LPCBYTE base_load_address; + AssemblyID assembly_id = 0; + DWORD module_flags = 0; + const HRESULT hr = info->GetModuleInfo2( + module_id, &base_load_address, module_path_size, &module_path_len, + module_path, &assembly_id, &module_flags); + if (FAILED(hr) || module_path_len == 0) { + return {}; + } + return {module_id, WSTRING(module_path), GetAssemblyInfo(info, assembly_id), + module_flags}; +} + +TypeInfo GetTypeInfo(const ComPtr& metadata_import, + const mdToken& token) { + mdToken parent_token = mdTokenNil; + WCHAR type_name[kNameMaxSize]{}; + DWORD type_name_len = 0; + + HRESULT hr = E_FAIL; + const auto token_type = TypeFromToken(token); + + switch (token_type) { + case mdtTypeDef: + hr = metadata_import->GetTypeDefProps(token, type_name, kNameMaxSize, + &type_name_len, nullptr, nullptr); + break; + case mdtTypeRef: + hr = metadata_import->GetTypeRefProps(token, &parent_token, type_name, + kNameMaxSize, &type_name_len); + break; + case mdtTypeSpec: { + PCCOR_SIGNATURE signature{}; + ULONG signature_length{}; + + hr = metadata_import->GetTypeSpecFromToken(token, &signature, + &signature_length); + + if (FAILED(hr) || signature_length < 3) { + return {}; + } + + if (signature[0] & ELEMENT_TYPE_GENERICINST) { + mdToken type_token; + CorSigUncompressToken(&signature[2], &type_token); + return GetTypeInfo(metadata_import, type_token); + } + } break; + case mdtModuleRef: + metadata_import->GetModuleRefProps(token, type_name, kNameMaxSize, + &type_name_len); + break; + case mdtMemberRef: + return GetFunctionInfo(metadata_import, token).type; + break; + case mdtMethodDef: + return GetFunctionInfo(metadata_import, token).type; + break; + } + if (FAILED(hr) || type_name_len == 0) { + return {}; + } + + return {token, WSTRING(type_name)}; +} + +mdAssemblyRef FindAssemblyRef( + const ComPtr& assembly_import, + const WSTRING& assembly_name) { + for (mdAssemblyRef assembly_ref : EnumAssemblyRefs(assembly_import)) { + if (GetReferencedAssemblyMetadata(assembly_import, assembly_ref).name == + assembly_name) { + return assembly_ref; + } + } + return mdAssemblyRefNil; +} + +std::vector FilterIntegrationsByName( + const std::vector& integrations, + const std::vector& disabled_integration_names) { + std::vector enabled; + + for (auto& i : integrations) { + bool disabled = false; + for (auto& disabled_integration : disabled_integration_names) { + if (i.integration_name == disabled_integration) { + // this integration is disabled, skip it + disabled = true; + break; + } + } + + if (!disabled) { + enabled.push_back(i); + } + } + + return enabled; +} + +std::vector FlattenIntegrations( + const std::vector& integrations) { + std::vector flattened; + + for (auto& i : integrations) { + for (auto& mr : i.method_replacements) { + flattened.emplace_back(i.integration_name, mr); + } + } + + return flattened; +} + +std::vector FilterIntegrationsByCaller( + const std::vector& integration_methods, + const AssemblyInfo assembly) { + std::vector enabled; + + for (auto& i : integration_methods) { + if (i.replacement.caller_method.assembly.name.empty() || + i.replacement.caller_method.assembly.name == assembly.name) { + enabled.push_back(i); + } + } + + return enabled; +} + +bool AssemblyMeetsIntegrationRequirements( + const AssemblyMetadata metadata, + const MethodReplacement method_replacement) { + const auto target = method_replacement.target_method; + + if (target.assembly.name != metadata.name) { + // not the expected assembly + return false; + } + + if (target.min_version > metadata.version) { + return false; + } + + if (target.max_version < metadata.version) { + return false; + } + + return true; +} + +std::vector FilterIntegrationsByTarget( + const std::vector& integration_methods, + const ComPtr& assembly_import) { + std::vector enabled; + + const auto assembly_metadata = GetAssemblyImportMetadata(assembly_import); + + for (auto& i : integration_methods) { + bool found = false; + if (AssemblyMeetsIntegrationRequirements(assembly_metadata, + i.replacement)) { + found = true; + } + for (auto& assembly_ref : EnumAssemblyRefs(assembly_import)) { + const auto metadata_ref = + GetReferencedAssemblyMetadata(assembly_import, assembly_ref); + // Info(L"-- assembly ref: " , assembly_name , " to " , ref_name); + if (AssemblyMeetsIntegrationRequirements(metadata_ref, i.replacement)) { + found = true; + } + } + if (found) { + enabled.push_back(i); + } + } + + return enabled; +} + +std::vector FilterIntegrationsByTargetAssemblyName( + const std::vector& integration_methods, + const std::vector& excluded_assembly_names) { + std::vector methods; + + for (auto& i : integration_methods) { + bool assembly_excluded = false; + + for (auto& excluded_assembly_name : excluded_assembly_names) { + if (i.replacement.target_method.assembly.name == excluded_assembly_name) { + assembly_excluded = true; + break; + } + } + + if (!assembly_excluded) { + methods.emplace_back(i); + } + } + + return methods; +} + +mdMethodSpec DefineMethodSpec(const ComPtr& metadata_emit, + const mdToken& token, + const MethodSignature& signature) { + mdMethodSpec spec = mdMethodSpecNil; + auto hr = metadata_emit->DefineMethodSpec( + token, signature.data.data(), ULONG(signature.data.size()), &spec); + if (FAILED(hr)) { + Warn("[DefineMethodSpec] failed to define method spec"); + } + return spec; +} + +bool DisableOptimizations() { + const auto disable_optimizations = + GetEnvironmentValue(environment::clr_disable_optimizations); + + if (disable_optimizations == "1"_W || + disable_optimizations == "true"_W) { + return true; + } + + // default to false: don't disable JIT optimizations + return false; +} + +TypeInfo RetrieveTypeForSignature( + const ComPtr& metadata_import, + const FunctionInfo& function_info, const size_t current_index, + ULONG& token_length) { + mdToken type_token; + const auto type_token_start = + PCCOR_SIGNATURE(&function_info.signature.data[current_index]); + token_length = CorSigUncompressToken(type_token_start, &type_token); + auto type_data = GetTypeInfo(metadata_import, type_token); + return type_data; +} + +bool TryParseSignatureTypes(const ComPtr& metadata_import, + const FunctionInfo& function_info, + std::vector& signature_result) { + try { + const auto signature_size = function_info.signature.data.size(); + const auto generic_count = function_info.signature.NumberOfTypeArguments(); + const auto param_count = function_info.signature.NumberOfArguments(); + size_t current_index = 2; // Where the parameters actually start + + if (generic_count > 0) { + current_index++; // offset by one because the method is generic + } + + const auto expected_number_of_types = param_count + 1; + size_t current_type_index = 0; + std::vector type_names(expected_number_of_types); + + std::stack generic_arg_stack; + WSTRING append_to_type = ""_W; + WSTRING current_type_name = ""_W; + + for (; current_index < signature_size; current_index++) { + mdToken type_token; + ULONG token_length; + auto param_piece = function_info.signature.data[current_index]; + const auto cor_element_type = CorElementType(param_piece); + + switch (cor_element_type) { + case ELEMENT_TYPE_VOID: { + current_type_name.append("System.Void"_W); + break; + } + + case ELEMENT_TYPE_BOOLEAN: { + current_type_name.append("System.Boolean"_W); + break; + } + + case ELEMENT_TYPE_CHAR: { + current_type_name.append("System.Char16"_W); + break; + } + + case ELEMENT_TYPE_I1: { + current_type_name.append("System.SByte"_W); + break; + } + + case ELEMENT_TYPE_U1: { + current_type_name.append("System.Byte"_W); + break; + } + + case ELEMENT_TYPE_I2: { + current_type_name.append("System.Int16"_W); + break; + } + + case ELEMENT_TYPE_U2: { + current_type_name.append("System.UInt16"_W); + break; + } + + case ELEMENT_TYPE_I4: { + current_type_name.append("System.Int32"_W); + break; + } + + case ELEMENT_TYPE_U4: { + current_type_name.append("System.UInt32"_W); + break; + } + + case ELEMENT_TYPE_I8: { + current_type_name.append("System.Int64"_W); + break; + } + + case ELEMENT_TYPE_U8: { + current_type_name.append("System.UInt64"_W); + break; + } + + case ELEMENT_TYPE_R4: { + current_type_name.append("System.Single"_W); + break; + } + + case ELEMENT_TYPE_R8: { + current_type_name.append("System.Double"_W); + break; + } + + case ELEMENT_TYPE_STRING: { + current_type_name.append("System.String"_W); + break; + } + + case ELEMENT_TYPE_OBJECT: { + current_type_name.append("System.Object"_W); + break; + } + + case ELEMENT_TYPE_VALUETYPE: + case ELEMENT_TYPE_CLASS: { + current_index++; + auto type_data = RetrieveTypeForSignature( + metadata_import, function_info, current_index, token_length); + + mdToken examined_type_token = type_data.id; + auto examined_type_name = type_data.name; + auto ongoing_type_name = examined_type_name; + + // check for whether this may be a nested class + while (examined_type_name.find_first_of("."_W) == std::string::npos) { + // This may possibly be a nested class, check for the parent + mdToken potentialParentToken; + metadata_import->GetNestedClassProps(examined_type_token, + &potentialParentToken); + + if (potentialParentToken == mdTokenNil) { + break; + } + + auto nesting_type = + GetTypeInfo(metadata_import, potentialParentToken); + + examined_type_token = nesting_type.id; + examined_type_name = nesting_type.name; + + ongoing_type_name = examined_type_name + "+"_W + ongoing_type_name; + } + + // index will be moved up one on every loop + // handle tokens which have more than one byte + current_index += token_length - 1; + current_type_name.append(ongoing_type_name); + break; + } + + case ELEMENT_TYPE_SZARRAY: { + append_to_type.append("[]"_W); + while (function_info.signature.data[(current_index + 1)] == + ELEMENT_TYPE_SZARRAY) { + append_to_type.append("[]"_W); + current_index++; + } + // Next will be the type of the array(s) + continue; + } + + case ELEMENT_TYPE_MVAR: { + // We are likely parsing a standalone generic param + token_length = CorSigUncompressToken( + PCCOR_SIGNATURE(&function_info.signature.data[current_index]), + &type_token); + current_type_name.append("T"_W); + current_index += token_length; + // TODO: implement conventions for generics (eg., TC1, TC2, TM1, TM2) + // current_type_name.append(std::to_wstring(type_token)); + break; + } + + case ELEMENT_TYPE_VAR: { + // We are likely within a generic variant + token_length = CorSigUncompressToken( + PCCOR_SIGNATURE(&function_info.signature.data[current_index]), + &type_token); + current_type_name.append("T"_W); + current_index += token_length; + // TODO: implement conventions for generics (eg., TC1, TC2, TM1, TM2) + // current_type_name.append(std::to_wstring(type_token)); + break; + } + + case ELEMENT_TYPE_GENERICINST: { + // skip past generic type indicator token + current_index++; + // skip past actual generic type token (probably a class) + current_index++; + const auto generic_type_data = RetrieveTypeForSignature( + metadata_import, function_info, current_index, token_length); + auto type_name = generic_type_data.name; + current_type_name.append(type_name); + current_type_name.append("<"_W); // Begin generic args + + // Because we are starting a new generic, decrement any existing level + if (!generic_arg_stack.empty()) { + generic_arg_stack.top()--; + } + + // figure out how many generic args this type has + const auto index_of_tick = type_name.find_last_of('`'); + auto num_args_text = ToString(type_name.substr(index_of_tick + 1)); + auto actual_arg_count = std::stoi(num_args_text, nullptr); + generic_arg_stack.push(actual_arg_count); + current_index += token_length; + // Next will be the variants + continue; + } + + case ELEMENT_TYPE_BYREF: { + // TODO: This hasn't been encountered yet + current_type_name.append("ref"_W); + break; + } + + case ELEMENT_TYPE_END: { + // we already handle the generic by counting args + continue; + } + + default: { + // This is unexpected and we should report that, and not instrument + current_type_name.append(ToWSTRING(ToString(cor_element_type))); + break; + } + } + + if (!append_to_type.empty()) { + current_type_name.append(append_to_type); + append_to_type = ""_W; + } + + if (!generic_arg_stack.empty()) { + // decrement this level's args + generic_arg_stack.top()--; + + if (generic_arg_stack.top() > 0) { + // we're in the middle of generic type args + current_type_name.append(", "_W); + } + } + + while (!generic_arg_stack.empty() && generic_arg_stack.top() == 0) { + // unwind the generics with no args left + generic_arg_stack.pop(); + current_type_name.append(">"_W); + + if (!generic_arg_stack.empty() && generic_arg_stack.top() > 0) { + // We are in a nested generic and we need a comma to separate args + current_type_name.append(", "_W); + } + } + + if (!generic_arg_stack.empty()) { + continue; + } + + if (current_type_index >= expected_number_of_types) { + // We missed something, drop out for safety + return false; + } + + type_names[current_type_index] = current_type_name; + current_type_name = ""_W; + current_type_index++; + } + + signature_result = type_names; + + } catch (...) { + // TODO: Add precise exceptions and log + // We were unable to parse for some reason + // Return that we've failed + return false; + } + + return true; +} + +HRESULT CreateAssemblyRefToMscorlib(const ComPtr& assembly_emit, mdAssemblyRef* mscorlib_ref) { + // Define an AssemblyRef to mscorlib, needed to create TypeRefs later + ASSEMBLYMETADATA metadata{}; + metadata.usMajorVersion = 4; + metadata.usMinorVersion = 0; + metadata.usBuildNumber = 0; + metadata.usRevisionNumber = 0; + BYTE public_key[] = {0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89}; + HRESULT hr = assembly_emit->DefineAssemblyRef(public_key, sizeof(public_key), + "mscorlib"_W.c_str(), &metadata, NULL, 0, 0, + mscorlib_ref); + + return hr; +} + +bool ReturnTypeTokenforValueTypeElementType(PCCOR_SIGNATURE p_sig, + const ComPtr& metadata_emit, + const ComPtr& assembly_emit, + mdToken* ret_type_token) { + const auto cor_element_type = CorElementType(*p_sig); + WSTRING managed_type_name = ""_W; + + switch (cor_element_type) { + case ELEMENT_TYPE_VALUETYPE: { + ULONG result; + result = CorSigUncompressToken(p_sig + 1, ret_type_token); + if (result == -1) { + Warn("[trace::ReturnTypeTokenforElementType] ELEMENT_TYPE_VALUETYPE failed to find uncompress TypeRef or TypeDef"); + return false; + } + + return true; + } + + case ELEMENT_TYPE_VOID: // 0x01 // System.Void (struct) + managed_type_name = "System.Void"_W; + break; + case ELEMENT_TYPE_BOOLEAN: // 0x02 // System.Boolean (struct) + managed_type_name = "System.Boolean"_W; + break; + case ELEMENT_TYPE_CHAR: // 0x03 // System.Char (struct) + managed_type_name = "System.Char"_W; + break; + case ELEMENT_TYPE_I1: // 0x04 // System.SByte (struct) + managed_type_name = "System.SByte"_W; + break; + case ELEMENT_TYPE_U1: // 0x05 // System.Byte (struct) + managed_type_name = "System.Byte"_W; + break; + case ELEMENT_TYPE_I2: // 0x06 // System.Int16 (struct) + managed_type_name = "System.Int16"_W; + break; + case ELEMENT_TYPE_U2: // 0x07 // System.UInt16 (struct) + managed_type_name = "System.UInt16"_W; + break; + case ELEMENT_TYPE_I4: // 0x08 // System.Int32 (struct) + managed_type_name = "System.Int32"_W; + break; + case ELEMENT_TYPE_U4: // 0x09 // System.UInt32 (struct) + managed_type_name = "System.UInt32"_W; + break; + case ELEMENT_TYPE_I8: // 0x0a // System.Int64 (struct) + managed_type_name = "System.Int64"_W; + break; + case ELEMENT_TYPE_U8: // 0x0b // System.UInt64 (struct) + managed_type_name = "System.UInt64"_W; + break; + case ELEMENT_TYPE_R4: // 0x0c // System.Single (struct) + managed_type_name = "System.Single"_W; + break; + case ELEMENT_TYPE_R8: // 0x0d // System.Double (struct) + managed_type_name = "System.Double"_W; + break; + case ELEMENT_TYPE_TYPEDBYREF: // 0X16 // System.TypedReference (struct) + managed_type_name = "System.TypedReference"_W; + break; + case ELEMENT_TYPE_I: // 0x18 // System.IntPtr (struct) + managed_type_name = "System.IntPtr"_W; + break; + case ELEMENT_TYPE_U: // 0x19 // System.UIntPtr (struct) + managed_type_name = "System.UIntPtr"_W; + break; + default: + return false; + } + + // Create reference to Mscorlib + mdModuleRef mscorlib_ref; + HRESULT hr; + hr = CreateAssemblyRefToMscorlib(assembly_emit, &mscorlib_ref); + + if (FAILED(hr)) { + Warn("[trace::ReturnTypeTokenforElementType] failed to define AssemblyRef to mscorlib"); + return false; + } + + // Create/Get TypeRef to the listed type + if (managed_type_name == ""_W) { + Warn("[trace::ReturnTypeTokenforElementType] no managed type name given"); + return false; + } + + hr = metadata_emit->DefineTypeRefByName( + mscorlib_ref, managed_type_name.c_str(), ret_type_token); + + if (FAILED(hr)) { + Warn("[trace::ReturnTypeTokenforElementType] unable to create type ref for managed_type_name=", managed_type_name); + return false; + } + + return true; +} + +bool ReturnTypeIsValueTypeOrGeneric( + const ComPtr& metadata_import, + const ComPtr& metadata_emit, + const ComPtr& assembly_emit, + const mdToken targetFunctionToken, + const MethodSignature targetFunctionSignature, + mdToken* ret_type_token) { + + // MethodDefSig Format: [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) ParamCount RetType Param* [SENTINEL Param+] + const auto generic_count = targetFunctionSignature.NumberOfTypeArguments(); + size_t method_def_sig_index = generic_count == 0 ? 2 : 3; // Initialize the index to point to RetType + auto ret_type_byte = targetFunctionSignature.data[method_def_sig_index]; + const auto ret_type = CorElementType(ret_type_byte); + + switch (ret_type) { + case ELEMENT_TYPE_VOID: + // No object is returned, so return false. + return false; + + case ELEMENT_TYPE_GENERICINST: { + // Format: GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * + // Example: Task. Return true if the type is a VALUETYPE + if (targetFunctionSignature.data[method_def_sig_index + 1] != ELEMENT_TYPE_VALUETYPE) { + return false; + } + + PCCOR_SIGNATURE p_start_byte = PCCOR_SIGNATURE(&targetFunctionSignature.data[method_def_sig_index]); + PCCOR_SIGNATURE p_end_byte = p_start_byte; + if (!ParseType(&p_end_byte)) { + return false; + } + + size_t length = p_end_byte - p_start_byte; + HRESULT hr = metadata_emit->GetTokenFromTypeSpec(p_start_byte, (ULONG) length, ret_type_token); + return SUCCEEDED(hr); + } + + case ELEMENT_TYPE_VAR: + case ELEMENT_TYPE_MVAR: { + // Format: VAR number + // Format: MVAR number + + // Extract the number, which is an index into the generic type arguments of the method or the type + method_def_sig_index++; // Advance the current_index to point to "number" + ULONG generic_type_index; + if (CorSigUncompressData(PCCOR_SIGNATURE(&targetFunctionSignature.data[method_def_sig_index]), + &generic_type_index) == -1) { + Warn("[trace::ReturnTypeIsValueTypeOrGeneric] element_type=", ret_type, ": unable to read VAR|MVAR index"); + return false; + } + + // Get the signature of the MethodSpec or the method's parent TypeSpec + // Each spec will clearly list the types used for the generic type variables + const auto token_type = TypeFromToken(targetFunctionToken); + mdToken parent_token = mdTokenNil; + HRESULT hr; + PCCOR_SIGNATURE spec_signature{}; + ULONG spec_signature_length{}; + + switch (token_type) { + case mdtMemberRef: + // The compiler will never make method calls to generic methods without + // the generic context, so we never expect to hit this at + // run-time. If we are evaluating the MethodDef/MethodRef of a generic + // method return false because it is invalid. + if (generic_count > 0) { + return false; + } + + hr = metadata_import->GetMemberRefProps(targetFunctionToken, + &parent_token, nullptr, 0, + nullptr, nullptr, nullptr); + if (SUCCEEDED(hr)) { + hr = metadata_import->GetTypeSpecFromToken(parent_token, &spec_signature, + &spec_signature_length); + } + break; + case mdtMethodDef: + // The compiler will never make method calls to generic methods without + // the generic context, so we never expect to hit this at + // run-time. If we are evaluating the MethodDef/MethodRef of a generic + // method return false because it is invalid. + if (generic_count > 0) { + return false; + } + + hr = metadata_import->GetMemberProps( + targetFunctionToken, &parent_token, nullptr, 0, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr); + if (SUCCEEDED(hr)) { + hr = metadata_import->GetTypeSpecFromToken(parent_token, &spec_signature, + &spec_signature_length); + } + break; + case mdtMethodSpec: + hr = metadata_import->GetMethodSpecProps(targetFunctionToken, + &parent_token, &spec_signature, &spec_signature_length); + break; + default: + Warn("[trace::ReturnTypeIsValueTypeOrGeneric] element_type=", ret_type, ": function token was not a MemberRef, MethodDef, or MethodSpec"); + return false; + } + + if (FAILED(hr)) { + Warn("[trace::ReturnTypeIsValueTypeOrGeneric] element_type=", ret_type, ": failed to get parent token or signature"); + return false; + } + + // Determine the index of GenArgCount in the signature + size_t parent_token_index; + if (token_type == mdtMemberRef || token_type == mdtMethodDef) { + // TypeSpec Format: GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type Type* + // Skip over TypeDefOrRefEncoded by parsing the signature at index 2 + parent_token_index = 2; + mdToken dummy_token; + ULONG token_length = CorSigUncompressToken( + &spec_signature[parent_token_index], &dummy_token); + parent_token_index += token_length; + } else if (token_type == mdtMethodSpec) { + // MethodSpec Format: GENRICINST GenArgCount Type Type* + parent_token_index = 1; + } else { + Warn("[trace::ReturnTypeIsValueTypeOrGeneric] element_type=", ret_type, ": token_type (", token_type , ") not recognized"); + return false; + } + + // Read the value of GenArgCount in the signature + ULONG num_generic_arguments; + parent_token_index += CorSigUncompressData( + &spec_signature[parent_token_index], &num_generic_arguments); + + // Get a pointer to first type after GenArgCount that we can increment to read the signature + PCCOR_SIGNATURE p_current_byte = spec_signature + parent_token_index; + + // Iterate to specified generic type argument index and return the appropriate class token or TypeSpec + for (size_t i = 0; i < num_generic_arguments; i++) { + if (i != generic_type_index) { + if (!ParseType(&p_current_byte)) { + Warn( + "[trace::ReturnTypeIsValueTypeOrGeneric] element_type=", ret_type, ": Unable to parse " + "generic type argument ", i, + "from signature of parent_token:", parent_token); + return false; + } + } else if (*p_current_byte == ELEMENT_TYPE_MVAR || + *p_current_byte == ELEMENT_TYPE_VAR) { + // The method was defined with a method-level generic type argument from the caller. Return the TypeSpec token for the `M#` MVAR description, or + // The method was defined with a type-level generic type argument from the caller. Return the TypeSpec token for the `T#` VAR description + hr = metadata_emit->GetTokenFromTypeSpec(p_current_byte, 2, + ret_type_token); + return SUCCEEDED(hr); + } else if (*p_current_byte == ELEMENT_TYPE_GENERICINST) { + // Format: GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * + // Example: Task. Return true if the type is a VALUETYPE + if (*(p_current_byte + 1) != ELEMENT_TYPE_VALUETYPE) { + return false; + } + + PCCOR_SIGNATURE p_start_byte = p_current_byte; + PCCOR_SIGNATURE p_end_byte = p_start_byte; + if (!ParseType(&p_end_byte)) { + return false; + } + + size_t length = p_end_byte - p_start_byte; + HRESULT hr = metadata_emit->GetTokenFromTypeSpec(p_start_byte, (ULONG) length, + ret_type_token); + return SUCCEEDED(hr); + } else { + return ReturnTypeTokenforValueTypeElementType( + p_current_byte, + metadata_emit, + assembly_emit, + ret_type_token); + } + } + + return false; + } + + default: + return ReturnTypeTokenforValueTypeElementType( + PCCOR_SIGNATURE(&targetFunctionSignature.data[method_def_sig_index]), + metadata_emit, + assembly_emit, + ret_type_token); + } +} +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h b/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h new file mode 100644 index 0000000000..176942ad34 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h @@ -0,0 +1,378 @@ +#ifndef DD_CLR_PROFILER_CLR_HELPERS_H_ +#define DD_CLR_PROFILER_CLR_HELPERS_H_ + +#include +#include +#include +#include + +#include "com_ptr.h" +#include "integration.h" +#include + +namespace trace { +class ModuleMetadata; + +const size_t kNameMaxSize = 1024; +const ULONG kEnumeratorMax = 256; + +template +class EnumeratorIterator; + +template +class Enumerator { + private: + const std::function callback_; + const std::function close_; + mutable HCORENUM ptr_; + + public: + Enumerator(std::function callback, + std::function close) + : callback_(callback), close_(close), ptr_(nullptr) {} + + Enumerator(const Enumerator& other) = default; + + Enumerator& operator=(const Enumerator& other) = default; + + ~Enumerator() { close_(ptr_); } + + EnumeratorIterator begin() const { + return EnumeratorIterator(this, S_OK); + } + + EnumeratorIterator end() const { + return EnumeratorIterator(this, S_FALSE); + } + + HRESULT Next(T arr[], ULONG max, ULONG* cnt) const { + return callback_(&ptr_, arr, max, cnt); + } +}; + +template +class EnumeratorIterator { + private: + const Enumerator* enumerator_; + HRESULT status_ = S_FALSE; + T arr_[kEnumeratorMax]{}; + ULONG idx_ = 0; + ULONG sz_ = 0; + + public: + EnumeratorIterator(const Enumerator* enumerator, HRESULT status) + : enumerator_(enumerator) { + if (status == S_OK) { + status_ = enumerator_->Next(arr_, kEnumeratorMax, &sz_); + if (status_ == S_OK && sz_ == 0) { + status_ = S_FALSE; + } + } else { + status_ = status; + } + } + + bool operator!=(EnumeratorIterator const& other) const { + return enumerator_ != other.enumerator_ || + (status_ == S_OK) != (other.status_ == S_OK); + } + + T const& operator*() const { return arr_[idx_]; } + + EnumeratorIterator& operator++() { + if (idx_ < sz_ - 1) { + idx_++; + } else { + idx_ = 0; + status_ = enumerator_->Next(arr_, kEnumeratorMax, &sz_); + if (status_ == S_OK && sz_ == 0) { + status_ = S_FALSE; + } + } + return *this; + } +}; + +static Enumerator EnumTypeDefs( + const ComPtr& metadata_import) { + return Enumerator( + [metadata_import](HCORENUM* ptr, mdTypeDef arr[], ULONG max, + ULONG* cnt) -> HRESULT { + return metadata_import->EnumTypeDefs(ptr, arr, max, cnt); + }, + [metadata_import](HCORENUM ptr) -> void { + metadata_import->CloseEnum(ptr); + }); +} + +static Enumerator EnumTypeRefs( + const ComPtr& metadata_import) { + return Enumerator( + [metadata_import](HCORENUM* ptr, mdTypeRef arr[], ULONG max, + ULONG* cnt) -> HRESULT { + return metadata_import->EnumTypeRefs(ptr, arr, max, cnt); + }, + [metadata_import](HCORENUM ptr) -> void { + metadata_import->CloseEnum(ptr); + }); +} + +static Enumerator EnumMethods( + const ComPtr& metadata_import, + const mdToken& parent_token) { + return Enumerator( + [metadata_import, parent_token](HCORENUM* ptr, mdMethodDef arr[], + ULONG max, ULONG* cnt) -> HRESULT { + return metadata_import->EnumMethods(ptr, parent_token, arr, max, cnt); + }, + [metadata_import](HCORENUM ptr) -> void { + metadata_import->CloseEnum(ptr); + }); +} + +static Enumerator EnumMemberRefs( + const ComPtr& metadata_import, + const mdToken& parent_token) { + return Enumerator( + [metadata_import, parent_token](HCORENUM* ptr, mdMemberRef arr[], + ULONG max, ULONG* cnt) -> HRESULT { + return metadata_import->EnumMemberRefs(ptr, parent_token, arr, max, + cnt); + }, + [metadata_import](HCORENUM ptr) -> void { + metadata_import->CloseEnum(ptr); + }); +} + +static Enumerator EnumModuleRefs( + const ComPtr& metadata_import) { + return Enumerator( + [metadata_import](HCORENUM* ptr, mdModuleRef arr[], ULONG max, + ULONG* cnt) -> HRESULT { + return metadata_import->EnumModuleRefs(ptr, arr, max, cnt); + }, + [metadata_import](HCORENUM ptr) -> void { + metadata_import->CloseEnum(ptr); + }); +} + +static Enumerator EnumAssemblyRefs( + const ComPtr& assembly_import) { + return Enumerator( + [assembly_import](HCORENUM* ptr, mdAssemblyRef arr[], ULONG max, + ULONG* cnt) -> HRESULT { + return assembly_import->EnumAssemblyRefs(ptr, arr, max, cnt); + }, + [assembly_import](HCORENUM ptr) -> void { + assembly_import->CloseEnum(ptr); + }); +} + +struct RuntimeInformation { + COR_PRF_RUNTIME_TYPE runtime_type; + USHORT major_version; + USHORT minor_version; + USHORT build_version; + USHORT qfe_version; + + RuntimeInformation() : runtime_type((COR_PRF_RUNTIME_TYPE)0x0), major_version(0), minor_version(0), build_version(0), qfe_version(0) {} + + RuntimeInformation(COR_PRF_RUNTIME_TYPE runtime_type, USHORT major_version, USHORT minor_version, USHORT build_version, USHORT qfe_version) + : runtime_type(runtime_type), + major_version(major_version), + minor_version(minor_version), + build_version(build_version), + qfe_version(qfe_version) {} + + RuntimeInformation& operator=(const RuntimeInformation& other) { + runtime_type = other.runtime_type; + major_version = other.major_version; + minor_version = other.minor_version; + build_version = other.build_version; + qfe_version = other.qfe_version; + return *this; + } + + bool is_desktop() const { return runtime_type == COR_PRF_DESKTOP_CLR; } + bool is_core() const { return runtime_type == COR_PRF_CORE_CLR; } +}; + +struct AssemblyInfo { + const AssemblyID id; + const WSTRING name; + const ModuleID manifest_module_id; + const AppDomainID app_domain_id; + const WSTRING app_domain_name; + + AssemblyInfo() : id(0), name(""_W), manifest_module_id(0), app_domain_id(0), app_domain_name(""_W) {} + + AssemblyInfo(AssemblyID id, WSTRING name, ModuleID manifest_module_id, AppDomainID app_domain_id, + WSTRING app_domain_name) + : id(id), + name(name), + manifest_module_id(manifest_module_id), + app_domain_id(app_domain_id), + app_domain_name(app_domain_name) {} + + bool IsValid() const { return id != 0; } +}; + +struct AssemblyMetadata { + const ModuleID module_id; + const WSTRING name; + const mdAssembly assembly_token; + const Version version; + + AssemblyMetadata() : module_id(0), name(""_W), assembly_token(mdTokenNil) {} + + AssemblyMetadata(ModuleID module_id, WSTRING name, mdAssembly assembly_token, + USHORT major, USHORT minor, USHORT build, USHORT revision) + : module_id(module_id), + name(name), + assembly_token(assembly_token), + version(Version(major, minor, build, revision)) {} + + bool IsValid() const { return module_id != 0; } +}; + +struct ModuleInfo { + const ModuleID id; + const WSTRING path; + const AssemblyInfo assembly; + const DWORD flags; + + ModuleInfo() : id(0), path(""_W), assembly({}), flags(0) {} + ModuleInfo(ModuleID id, WSTRING path, AssemblyInfo assembly, DWORD flags) + : id(id), path(path), assembly(assembly), flags(flags) {} + + bool IsValid() const { return id != 0; } + + bool IsWindowsRuntime() const { + return ((flags & COR_PRF_MODULE_WINDOWS_RUNTIME) != 0); + } +}; + +struct TypeInfo { + const mdToken id; + const WSTRING name; + + TypeInfo() : id(0), name(""_W) {} + TypeInfo(mdToken id, WSTRING name) : id(id), name(name) {} + + bool IsValid() const { return id != 0; } +}; + +struct FunctionInfo { + const mdToken id; + const WSTRING name; + const TypeInfo type; + const BOOL is_generic; + const MethodSignature signature; + const MethodSignature function_spec_signature; + const mdToken method_def_id; + + FunctionInfo() + : id(0), name(""_W), type({}), is_generic(false), method_def_id(0) {} + + FunctionInfo(mdToken id, WSTRING name, TypeInfo type, + MethodSignature signature, + MethodSignature function_spec_signature, mdToken method_def_id) + : id(id), + name(name), + type(type), + is_generic(true), + signature(signature), + function_spec_signature(function_spec_signature), + method_def_id(method_def_id) {} + + FunctionInfo(mdToken id, WSTRING name, TypeInfo type, + MethodSignature signature) + : id(id), + name(name), + type(type), + is_generic(false), + signature(signature), + method_def_id(0) {} + + bool IsValid() const { return id != 0; } +}; + +RuntimeInformation GetRuntimeInformation(ICorProfilerInfo3* info); + +AssemblyInfo GetAssemblyInfo(ICorProfilerInfo3* info, + const AssemblyID& assembly_id); + +AssemblyMetadata GetAssemblyMetadata( + const ModuleID& module_id, + const ComPtr& assembly_import); + +AssemblyMetadata GetAssemblyImportMetadata( + const ComPtr& assembly_import); + +AssemblyMetadata GetReferencedAssemblyMetadata( + const ComPtr& assembly_import, + const mdAssemblyRef& assembly_ref); + +FunctionInfo GetFunctionInfo(const ComPtr& metadata_import, + const mdToken& token); + +ModuleInfo GetModuleInfo(ICorProfilerInfo3* info, const ModuleID& module_id); + +TypeInfo GetTypeInfo(const ComPtr& metadata_import, + const mdToken& token); + +mdAssemblyRef FindAssemblyRef( + const ComPtr& assembly_import, + const WSTRING& assembly_name); + +// FilterIntegrationsByName removes integrations whose names are specified in +// disabled_integration_names +std::vector FilterIntegrationsByName( + const std::vector& integrations, + const std::vector& disabled_integration_names); + +// FlattenIntegrations flattens integrations to per method structures +std::vector FlattenIntegrations( + const std::vector& integrations); + +// FilterIntegrationsByCaller removes any integrations which have a caller and +// its not set to the module +std::vector FilterIntegrationsByCaller( + const std::vector& integration_methods, + const AssemblyInfo assembly); + +// FilterIntegrationsByTarget removes any integrations which have a target not +// referenced by the module's assembly import +std::vector FilterIntegrationsByTarget( + const std::vector& integration_methods, + const ComPtr& assembly_import); + +// FilterIntegrationsByTargetAssemblyName removes any integrations which target any +// of the specified assemblies +std::vector FilterIntegrationsByTargetAssemblyName( + const std::vector& integration_methods, + const std::vector& excluded_assembly_names); + +mdMethodSpec DefineMethodSpec(const ComPtr& metadata_emit, + const mdToken& token, + const MethodSignature& signature); + +bool DisableOptimizations(); + +bool TryParseSignatureTypes(const ComPtr& metadata_import, + const FunctionInfo& function_info, + std::vector& signature_result); + +HRESULT CreateAssemblyRefToMscorlib( + const ComPtr& assembly_emit, + mdAssemblyRef* mscorlib_ref); + +bool ReturnTypeIsValueTypeOrGeneric(const ComPtr& metadata_import, + const ComPtr& metadata_emit, + const ComPtr& assembly_emit, + const mdToken targetFunctionToken, + const MethodSignature targetFunctionSignature, + mdToken* ret_type_token); +} // namespace trace + +#endif // DD_CLR_PROFILER_CLR_HELPERS_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/com_ptr.h b/src/Datadog.Trace.ClrProfiler.Native/com_ptr.h new file mode 100644 index 0000000000..e18ee72ad9 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/com_ptr.h @@ -0,0 +1,144 @@ +#ifndef DD_CLR_PROFILER_COM_PTR_H_ +#define DD_CLR_PROFILER_COM_PTR_H_ + +#include +#include + +// https://msdn.microsoft.com/en-us/magazine/dn904668.aspx + +template +class RemoveAddRefRelease : public Interface { + ULONG __stdcall AddRef(); + ULONG __stdcall Release(); +}; + +template +class ComPtr { + public: + ComPtr() noexcept = default; + + ComPtr(ComPtr const& other) noexcept : m_ptr(other.m_ptr) { + InternalAddRef(); + } + + template + friend class ComPtr; + + template + ComPtr(ComPtr const& other) noexcept : m_ptr(other.m_ptr) { + InternalAddRef(); + } + + template + ComPtr(ComPtr&& other) noexcept : m_ptr(other.m_ptr) { + other.m_ptr = nullptr; + } + + ~ComPtr() noexcept { InternalRelease(); } + + void Swap(ComPtr& other) noexcept { + Interface* temp = m_ptr; + m_ptr = other.m_ptr; + other.m_ptr = temp; + } + + void Reset() noexcept { InternalRelease(); } + + Interface* Get() const noexcept { return m_ptr; } + + Interface* Detach() noexcept { + Interface* temp = m_ptr; + m_ptr = nullptr; + return temp; + } + + void Copy(Interface* other) noexcept { InternalCopy(other); } + + void Attach(Interface* other) noexcept { + InternalRelease(); + m_ptr = other; + } + + Interface** GetAddressOf() noexcept { + assert(m_ptr == nullptr); + return &m_ptr; + } + + void CopyTo(Interface** other) const noexcept { + InternalAddRef(); + *other = m_ptr; + } + + template + ComPtr As(IID iid) const noexcept { + ComPtr temp; + m_ptr->QueryInterface(iid, reinterpret_cast(temp.GetAddressOf())); + return temp; + } + + bool IsNull() const noexcept { return nullptr == m_ptr; } + + ComPtr& operator=(ComPtr const& other) noexcept { + InternalCopy(other.m_ptr); + return *this; + } + + template + ComPtr& operator=(ComPtr const& other) noexcept { + InternalCopy(other.m_ptr); + return *this; + } + + template + ComPtr& operator=(ComPtr&& other) noexcept { + InternalMove(other); + return *this; + } + + RemoveAddRefRelease* operator->() const noexcept { + return static_cast*>(m_ptr); + } + + explicit operator bool() const noexcept { return nullptr != m_ptr; } + + private: + Interface* m_ptr = nullptr; + + void InternalAddRef() const noexcept { + if (m_ptr) { + m_ptr->AddRef(); + } + } + + void InternalRelease() noexcept { + Interface* temp = m_ptr; + if (temp) { + m_ptr = nullptr; + temp->Release(); + } + } + + void InternalCopy(Interface* other) noexcept { + if (m_ptr != other) { + InternalRelease(); + m_ptr = other; + InternalAddRef(); + } + } + + template + void InternalMove(ComPtr& other) noexcept { + if (m_ptr != other.m_ptr) { + InternalRelease(); + m_ptr = other.m_ptr; + other.m_ptr = nullptr; + } + } +}; + +template +void swap(ComPtr& left, ComPtr& right) noexcept { + left.Swap(right); +} + +#endif // DD_CLR_PROFILER_COM_PTR_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.cpp b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.cpp new file mode 100644 index 0000000000..65f4eb1cdd --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.cpp @@ -0,0 +1,1896 @@ +#include "cor_profiler.h" + +#include +#include +#include "corhlpr.h" + +#include "version.h" +#include "clr_helpers.h" +#include "dd_profiler_constants.h" +#include "dllmain.h" +#include "environment_variables.h" +#include "il_rewriter.h" +#include "il_rewriter_wrapper.h" +#include "integration_loader.h" +#include "logging.h" +#include "metadata_builder.h" +#include "module_metadata.h" +#include "pal.h" +#include "sig_helpers.h" +#include "resource.h" +#include "util.h" + +namespace trace { + +CorProfiler* profiler = nullptr; + +// +// ICorProfilerCallback methods +// +HRESULT STDMETHODCALLTYPE +CorProfiler::Initialize(IUnknown* cor_profiler_info_unknown) { + // check if debug mode is enabled + const auto debug_enabled_value = + GetEnvironmentValue(environment::debug_enabled); + + if (debug_enabled_value == "1"_W || debug_enabled_value == "true"_W) { + debug_logging_enabled = true; + } + + CorProfilerBase::Initialize(cor_profiler_info_unknown); + + // check if tracing is completely disabled + const WSTRING tracing_enabled = + GetEnvironmentValue(environment::tracing_enabled); + + if (tracing_enabled == "0"_W || tracing_enabled == "false"_W) { + Info("DATADOG TRACER DIAGNOSTICS - Profiler disabled in ", environment::tracing_enabled); + return E_FAIL; + } + + const auto process_name = GetCurrentProcessName(); + const auto include_process_names = + GetEnvironmentValues(environment::include_process_names); + + // if there is a process inclusion list, attach profiler only if this + // process's name is on the list + if (!include_process_names.empty() && + !Contains(include_process_names, process_name)) { + Info("DATADOG TRACER DIAGNOSTICS - Profiler disabled: ", process_name, " not found in ", + environment::include_process_names, "."); + return E_FAIL; + } + + const auto exclude_process_names = + GetEnvironmentValues(environment::exclude_process_names); + + // attach profiler only if this process's name is NOT on the list + if (Contains(exclude_process_names, process_name)) { + Info("DATADOG TRACER DIAGNOSTICS - Profiler disabled: ", process_name, " found in ", + environment::exclude_process_names, "."); + return E_FAIL; + } + + // get Profiler interface + HRESULT hr = cor_profiler_info_unknown->QueryInterface( + &this->info_); + if (FAILED(hr)) { + Warn("DATADOG TRACER DIAGNOSTICS - Failed to attach profiler: interface ICorProfilerInfo3 not found."); + return E_FAIL; + } + + Info("Environment variables:"); + + for (auto&& env_var : env_vars_to_display) { + Info(" ", env_var, "=", GetEnvironmentValue(env_var)); + } + + const WSTRING azure_app_services_value = + GetEnvironmentValue(environment::azure_app_services); + + if (azure_app_services_value == "1"_W) { + Info("Profiler is operating within Azure App Services context."); + in_azure_app_services = true; + + const auto app_pool_id_value = + GetEnvironmentValue(environment::azure_app_services_app_pool_id); + + if (app_pool_id_value.size() > 1 && app_pool_id_value.at(0) == '~') { + Info("DATADOG TRACER DIAGNOSTICS - Profiler disabled: ", environment::azure_app_services_app_pool_id, + " ", app_pool_id_value, + " is recognized as an Azure App Services infrastructure process."); + return E_FAIL; + } + + const auto cli_telemetry_profile_value = GetEnvironmentValue( + environment::azure_app_services_cli_telemetry_profile_value); + + if (cli_telemetry_profile_value == "AzureKudu"_W) { + Info("DATADOG TRACER DIAGNOSTICS - Profiler disabled: ", app_pool_id_value, + " is recognized as Kudu, an Azure App Services reserved process."); + return E_FAIL; + } + } + + // get path to integration definition JSON files + const WSTRING integrations_paths = + GetEnvironmentValue(environment::integrations_path); + + if (integrations_paths.empty()) { + Warn("DATADOG TRACER DIAGNOSTICS - Profiler disabled: ", environment::integrations_path, + " environment variable not set."); + return E_FAIL; + } + + // load all available integrations from JSON files + const std::vector all_integrations = + LoadIntegrationsFromEnvironment(); + + // get list of disabled integration names + const std::vector disabled_integration_names = + GetEnvironmentValues(environment::disabled_integrations); + + // remove disabled integrations + const std::vector integrations = + FilterIntegrationsByName(all_integrations, disabled_integration_names); + + // check if there are any enabled integrations left + if (integrations.empty()) { + Warn("DATADOG TRACER DIAGNOSTICS - Profiler disabled: no enabled integrations found."); + return E_FAIL; + } + + integration_methods_ = FlattenIntegrations(integrations); + + const WSTRING netstandard_enabled = + GetEnvironmentValue(environment::netstandard_enabled); + + // temporarily skip the calls into netstandard.dll that were added in + // https://github.com/DataDog/dd-trace-dotnet/pull/753. + // users can opt-in to the additional instrumentation by setting environment + // variable DD_TRACE_NETSTANDARD_ENABLED + if (netstandard_enabled != "1"_W && netstandard_enabled != "true"_W) { + integration_methods_ = FilterIntegrationsByTargetAssemblyName( + integration_methods_, {"netstandard"_W}); + } + + DWORD event_mask = COR_PRF_MONITOR_JIT_COMPILATION | + COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST | + COR_PRF_DISABLE_INLINING | COR_PRF_MONITOR_MODULE_LOADS | + COR_PRF_MONITOR_ASSEMBLY_LOADS | + COR_PRF_DISABLE_ALL_NGEN_IMAGES; + + if (DisableOptimizations()) { + Info("Disabling all code optimizations."); + event_mask |= COR_PRF_DISABLE_OPTIMIZATIONS; + } + + const WSTRING domain_neutral_instrumentation = + GetEnvironmentValue(environment::domain_neutral_instrumentation); + + if (domain_neutral_instrumentation == "1"_W || domain_neutral_instrumentation == "true"_W) { + instrument_domain_neutral_assemblies = true; + } + + // set event mask to subscribe to events and disable NGEN images + // get ICorProfilerInfo6 for net452+ + ICorProfilerInfo6* info6; + hr = cor_profiler_info_unknown->QueryInterface(&info6); + + if (SUCCEEDED(hr)) { + Debug("Interface ICorProfilerInfo6 found."); + hr = info6->SetEventMask2(event_mask, COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES); + + if (instrument_domain_neutral_assemblies) { + Info("Note: The ", environment::domain_neutral_instrumentation, " environment variable is not needed when running on .NET Framework 4.5.2 or higher, and will be ignored."); + } + } else { + hr = this->info_->SetEventMask(event_mask); + + if (instrument_domain_neutral_assemblies) { + Info("Detected environment variable ", environment::domain_neutral_instrumentation, + "=", domain_neutral_instrumentation); + Info("Enabling automatic instrumentation of methods called from domain-neutral assemblies. ", + "Please ensure that there is only one AppDomain or, if applications are being hosted in IIS, ", + "ensure that all Application Pools have at most one application each. ", + "Otherwise, a sharing violation (HRESULT 0x80131401) may occur."); + } + } + if (FAILED(hr)) { + Warn("DATADOG TRACER DIAGNOSTICS - Failed to attach profiler: unable to set event mask."); + return E_FAIL; + } + + runtime_information_ = GetRuntimeInformation(this->info_); + if (process_name == "w3wp.exe"_W || + process_name == "iisexpress.exe"_W) { + is_desktop_iis = runtime_information_.is_desktop(); + } + + // we're in! + Info("Profiler attached."); + this->info_->AddRef(); + is_attached_ = true; + profiler = this; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfiler::AssemblyLoadFinished(AssemblyID assembly_id, + HRESULT hr_status) { + if (FAILED(hr_status)) { + // if assembly failed to load, skip it entirely, + // otherwise we can crash the process if module is not valid + CorProfilerBase::AssemblyLoadFinished(assembly_id, hr_status); + return S_OK; + } + + if (!is_attached_) { + return S_OK; + } + + if (debug_logging_enabled) { + Debug("AssemblyLoadFinished: ", assembly_id, " ", hr_status); + } + + // keep this lock until we are done using the module, + // to prevent it from unloading while in use + std::lock_guard guard(module_id_to_info_map_lock_); + + const auto assembly_info = GetAssemblyInfo(this->info_, assembly_id); + if (!assembly_info.IsValid()) { + return S_OK; + } + + ComPtr metadata_interfaces; + auto hr = this->info_->GetModuleMetaData(assembly_info.manifest_module_id, ofRead | ofWrite, + IID_IMetaDataImport2, + metadata_interfaces.GetAddressOf()); + + if (FAILED(hr)) { + Warn("AssemblyLoadFinished failed to get metadata interface for module id ", assembly_info.manifest_module_id, + " from assembly ", assembly_info.name); + return S_OK; + } + + // Get the IMetaDataAssemblyImport interface to get metadata from the managed assembly + const auto assembly_import = metadata_interfaces.As( + IID_IMetaDataAssemblyImport); + const auto assembly_metadata = GetAssemblyImportMetadata(assembly_import); + + if (debug_logging_enabled) { + Debug("AssemblyLoadFinished: AssemblyName=", assembly_info.name, " AssemblyVersion=", assembly_metadata.version.str()); + } + + if (assembly_info.name == "Datadog.Trace.ClrProfiler.Managed"_W) { + // Configure a version string to compare with the profiler version + WSTRINGSTREAM ws; + ws << ToWSTRING(assembly_metadata.version.major) << '.'_W + << ToWSTRING(assembly_metadata.version.minor) << '.'_W + << ToWSTRING(assembly_metadata.version.build); + + auto assembly_version = ws.str(); + + // Check that Major.Minor.Build match the profiler version + if (assembly_version == ToWSTRING(PROFILER_VERSION)) { + Info("AssemblyLoadFinished: Datadog.Trace.ClrProfiler.Managed v", assembly_version, " matched profiler version v", PROFILER_VERSION); + managed_profiler_loaded_app_domains.insert(assembly_info.app_domain_id); + + if (runtime_information_.is_desktop() && corlib_module_loaded) { + // Set the managed_profiler_loaded_domain_neutral flag whenever the managed profiler is loaded shared + if (assembly_info.app_domain_id == corlib_app_domain_id) { + Info("AssemblyLoadFinished: Datadog.Trace.ClrProfiler.Managed was loaded domain-neutral"); + managed_profiler_loaded_domain_neutral = true; + } + else { + Info("AssemblyLoadFinished: Datadog.Trace.ClrProfiler.Managed was not loaded domain-neutral"); + } + } + } + else { + Warn("AssemblyLoadFinished: Datadog.Trace.ClrProfiler.Managed v", assembly_version, " did not match profiler version v", PROFILER_VERSION); + } + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfiler::ModuleLoadFinished(ModuleID module_id, + HRESULT hr_status) { + if (FAILED(hr_status)) { + // if module failed to load, skip it entirely, + // otherwise we can crash the process if module is not valid + CorProfilerBase::ModuleLoadFinished(module_id, hr_status); + return S_OK; + } + + if (!is_attached_) { + return S_OK; + } + + // keep this lock until we are done using the module, + // to prevent it from unloading while in use + std::lock_guard guard(module_id_to_info_map_lock_); + + const auto module_info = GetModuleInfo(this->info_, module_id); + if (!module_info.IsValid()) { + return S_OK; + } + + if (debug_logging_enabled) { + Debug("ModuleLoadFinished: ", module_id, " ", module_info.assembly.name, + " AppDomain ", module_info.assembly.app_domain_id, " ", + module_info.assembly.app_domain_name); + } + + AppDomainID app_domain_id = module_info.assembly.app_domain_id; + + // Identify the AppDomain ID of mscorlib which will be the Shared Domain + // because mscorlib is always a domain-neutral assembly + if (!corlib_module_loaded && + (module_info.assembly.name == "mscorlib"_W || + module_info.assembly.name == "System.Private.CoreLib"_W)) { + corlib_module_loaded = true; + corlib_app_domain_id = app_domain_id; + return S_OK; + } + + // In IIS, the startup hook will be inserted into a method in System.Web (which is domain-neutral) + // but the Datadog.Trace.ClrProfiler.Managed.Loader assembly that the startup hook loads from a + // byte array will be loaded into a non-shared AppDomain. + // In this case, do not insert another startup hook into that non-shared AppDomain + if (module_info.assembly.name == "Datadog.Trace.ClrProfiler.Managed.Loader"_W) { + Info("ModuleLoadFinished: Datadog.Trace.ClrProfiler.Managed.Loader loaded into AppDomain ", + app_domain_id, " ", module_info.assembly.app_domain_name); + first_jit_compilation_app_domains.insert(app_domain_id); + return S_OK; + } + + if (module_info.IsWindowsRuntime()) { + // We cannot obtain writable metadata interfaces on Windows Runtime modules + // or instrument their IL. + Debug("ModuleLoadFinished skipping Windows Metadata module: ", module_id, + " ", module_info.assembly.name); + return S_OK; + } + + for (auto&& skip_assembly_pattern : skip_assembly_prefixes) { + if (module_info.assembly.name.rfind(skip_assembly_pattern, 0) == 0) { + Debug("ModuleLoadFinished skipping module by pattern: ", module_id, " ", + module_info.assembly.name); + return S_OK; + } + } + + for (auto&& skip_assembly : skip_assemblies) { + if (module_info.assembly.name == skip_assembly) { + Debug("ModuleLoadFinished skipping known module: ", module_id, " ", + module_info.assembly.name); + return S_OK; + } + } + + std::vector filtered_integrations = + FilterIntegrationsByCaller(integration_methods_, module_info.assembly); + + if (filtered_integrations.empty()) { + // we don't need to instrument anything in this module, skip it + Debug("ModuleLoadFinished skipping module (filtered by caller): ", + module_id, " ", module_info.assembly.name); + return S_OK; + } + + ComPtr metadata_interfaces; + auto hr = this->info_->GetModuleMetaData(module_id, ofRead | ofWrite, + IID_IMetaDataImport2, + metadata_interfaces.GetAddressOf()); + + if (FAILED(hr)) { + Warn("ModuleLoadFinished failed to get metadata interface for ", module_id, + " ", module_info.assembly.name); + return S_OK; + } + + const auto metadata_import = + metadata_interfaces.As(IID_IMetaDataImport); + const auto metadata_emit = + metadata_interfaces.As(IID_IMetaDataEmit); + const auto assembly_import = metadata_interfaces.As( + IID_IMetaDataAssemblyImport); + const auto assembly_emit = + metadata_interfaces.As(IID_IMetaDataAssemblyEmit); + + // don't skip Microsoft.AspNetCore.Hosting so we can run the startup hook and + // subscribe to DiagnosticSource events. + // don't skip Dapper: it makes ADO.NET calls even though it doesn't reference + // System.Data or System.Data.Common + if (module_info.assembly.name != "Microsoft.AspNetCore.Hosting"_W && + module_info.assembly.name != "Dapper"_W) { + filtered_integrations = + FilterIntegrationsByTarget(filtered_integrations, assembly_import); + + if (filtered_integrations.empty()) { + // we don't need to instrument anything in this module, skip it + Debug("ModuleLoadFinished skipping module (filtered by target): ", + module_id, " ", module_info.assembly.name); + return S_OK; + } + } + + mdModule module; + hr = metadata_import->GetModuleFromScope(&module); + if (FAILED(hr)) { + Warn("ModuleLoadFinished failed to get module metadata token for ", + module_id, " ", module_info.assembly.name); + return S_OK; + } + + GUID module_version_id; + hr = metadata_import->GetScopeProps(nullptr, 0, nullptr, &module_version_id); + if (FAILED(hr)) { + Warn("ModuleLoadFinished failed to get module_version_id for ", module_id, + " ", module_info.assembly.name); + return S_OK; + } + + ModuleMetadata* module_metadata = new ModuleMetadata( + metadata_import, metadata_emit, assembly_import, assembly_emit, + module_info.assembly.name, app_domain_id, + module_version_id, filtered_integrations); + + // store module info for later lookup + module_id_to_info_map_[module_id] = module_metadata; + + Debug("ModuleLoadFinished stored metadata for ", module_id, " ", + module_info.assembly.name, " AppDomain ", + module_info.assembly.app_domain_id, " ", + module_info.assembly.app_domain_name); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfiler::ModuleUnloadStarted(ModuleID module_id) { + if (debug_logging_enabled) { + const auto module_info = GetModuleInfo(this->info_, module_id); + + if (module_info.IsValid()) { + Debug("ModuleUnloadStarted: ", module_id, " ", module_info.assembly.name, + " AppDomain ", module_info.assembly.app_domain_id, " ", + module_info.assembly.app_domain_name); + } else { + Debug("ModuleUnloadStarted: ", module_id); + } + } + + // take this lock so we block until the + // module metadata is not longer being used + std::lock_guard guard(module_id_to_info_map_lock_); + + // remove module metadata from map + if (module_id_to_info_map_.count(module_id) > 0) { + ModuleMetadata* metadata = module_id_to_info_map_[module_id]; + + // remove appdomain id from managed_profiler_loaded_app_domains set + if (managed_profiler_loaded_app_domains.find(metadata->app_domain_id) != + managed_profiler_loaded_app_domains.end()) { + managed_profiler_loaded_app_domains.erase(metadata->app_domain_id); + } + + module_id_to_info_map_.erase(module_id); + delete metadata; + } + + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfiler::Shutdown() { + CorProfilerBase::Shutdown(); + + // keep this lock until we are done using the module, + // to prevent it from unloading while in use + std::lock_guard guard(module_id_to_info_map_lock_); + + is_attached_ = false; + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfiler::JITCompilationStarted( + FunctionID function_id, BOOL is_safe_to_block) { + if (!is_attached_ || !is_safe_to_block) { + return S_OK; + } + + // keep this lock until we are done using the module, + // to prevent it from unloading while in use + std::lock_guard guard(module_id_to_info_map_lock_); + + ModuleID module_id; + mdToken function_token = mdTokenNil; + + HRESULT hr = this->info_->GetFunctionInfo(function_id, nullptr, &module_id, + &function_token); + + if (FAILED(hr)) { + Warn("JITCompilationStarted: Call to ICorProfilerInfo3.GetFunctionInfo() failed for ", function_id); + return S_OK; + } + + // Verify that we have the metadata for this module + ModuleMetadata* module_metadata = nullptr; + if (module_id_to_info_map_.count(module_id) > 0) { + module_metadata = module_id_to_info_map_[module_id]; + } + + if (module_metadata == nullptr) { + // we haven't stored a ModuleMetadata for this module, + // so we can't modify its IL + return S_OK; + } + + // get function info + const auto caller = + GetFunctionInfo(module_metadata->metadata_import, function_token); + if (!caller.IsValid()) { + return S_OK; + } + + if (debug_logging_enabled) { + Debug("JITCompilationStarted: function_id=", function_id, + " token=", function_token, " name=", caller.type.name, ".", + caller.name, "()"); + } + + // IIS: Ensure that the startup hook is inserted into System.Web.Compilation.BuildManager.InvokePreStartInitMethods. + // This will be the first call-site considered for the startup hook injection, + // which correctly loads Datadog.Trace.ClrProfiler.Managed.Loader into the application's + // own AppDomain because at this point in the code path, the ApplicationImpersonationContext + // has been started. + // + // Note: This check must only run on desktop because it is possible (and the default) to host + // ASP.NET Core in-process, so a new .NET Core runtime is instantiated and run in the same w3wp.exe process + auto valid_startup_hook_callsite = true; + if (is_desktop_iis) { + valid_startup_hook_callsite = + module_metadata->assemblyName == "System.Web"_W && + caller.type.name == "System.Web.Compilation.BuildManager"_W && + caller.name == "InvokePreStartInitMethods"_W; + } else if (module_metadata->assemblyName == "System"_W || + module_metadata->assemblyName == "System.Net.Http"_W) { + valid_startup_hook_callsite = false; + } + + // The first time a method is JIT compiled in an AppDomain, insert our startup + // hook which, at a minimum, must add an AssemblyResolve event so we can find + // Datadog.Trace.ClrProfiler.Managed.dll and its dependencies on-disk since it + // is no longer provided in a NuGet package + if (valid_startup_hook_callsite && + first_jit_compilation_app_domains.find(module_metadata->app_domain_id) == + first_jit_compilation_app_domains.end()) { + bool domain_neutral_assembly = runtime_information_.is_desktop() && corlib_module_loaded && module_metadata->app_domain_id == corlib_app_domain_id; + Info("JITCompilationStarted: Startup hook registered in function_id=", function_id, + " token=", function_token, " name=", caller.type.name, ".", + caller.name, "(), assembly_name=", module_metadata->assemblyName, + " app_domain_id=", module_metadata->app_domain_id, + " domain_neutral=", domain_neutral_assembly); + + first_jit_compilation_app_domains.insert(module_metadata->app_domain_id); + + hr = RunILStartupHook(module_metadata->metadata_emit, module_id, + function_token); + + if (FAILED(hr)) { + Warn("JITCompilationStarted: Call to RunILStartupHook() failed for ", module_id, " ", function_token); + return S_OK; + } + } + + // we don't actually need to instrument anything in + // Microsoft.AspNetCore.Hosting, it was included only to ensure the startup + // hook is called for AspNetCore applications + if (module_metadata->assemblyName == "Microsoft.AspNetCore.Hosting"_W) { + return S_OK; + } + + // Get valid method replacements for this caller method + const auto method_replacements = + module_metadata->GetMethodReplacementsForCaller(caller); + if (method_replacements.empty()) { + return S_OK; + } + + // Perform method insertion calls + hr = ProcessInsertionCalls(module_metadata, + function_id, + module_id, + function_token, + caller, + method_replacements); + + if (FAILED(hr)) { + Warn("JITCompilationStarted: Call to ProcessInsertionCalls() failed for ", function_id, " ", module_id, " ", function_token); + return S_OK; + } + + // Perform method replacement calls + hr = ProcessReplacementCalls(module_metadata, + function_id, + module_id, + function_token, + caller, + method_replacements); + + if (FAILED(hr)) { + Warn("JITCompilationStarted: Call to ProcessReplacementCalls() failed for ", function_id, " ", module_id, " ", function_token); + return S_OK; + } + + return S_OK; +} + +// +// ICorProfilerCallback6 methods +// +HRESULT STDMETHODCALLTYPE CorProfiler::GetAssemblyReferences( + const WCHAR* wszAssemblyPath, + ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) { + if (in_azure_app_services) { + Debug("GetAssemblyReferences skipping entire callback because this is running in Azure App Services, which isn't yet supported for this feature. AssemblyPath=", wszAssemblyPath); + return S_OK; + } + + // Convert the assembly path to the assembly name, assuming the assembly name + // is either or .dll + auto assemblyPathString = ToString(wszAssemblyPath); + auto filename = + assemblyPathString.substr(assemblyPathString.find_last_of("\\/") + 1); + auto lastNiDllPeriodIndex = filename.rfind(".ni.dll"); + auto lastDllPeriodIndex = filename.rfind(".dll"); + if (lastNiDllPeriodIndex != std::string::npos) { + filename.erase(lastNiDllPeriodIndex, 7); + } else if (lastDllPeriodIndex != std::string::npos) { + filename.erase(lastDllPeriodIndex, 4); + } + + const WSTRING assembly_name = ToWSTRING(filename); + + // Skip known framework assemblies that we will not instrument and, + // as a result, will not need an assembly reference to the + // managed profiler + for (auto&& skip_assembly_pattern : skip_assembly_prefixes) { + if (assembly_name.rfind(skip_assembly_pattern, 0) == 0) { + Debug("GetAssemblyReferences skipping module by pattern: Name=", + assembly_name, " Path=", wszAssemblyPath); + return S_OK; + } + } + + for (auto&& skip_assembly : skip_assemblies) { + if (assembly_name == skip_assembly) { + Debug("GetAssemblyReferences skipping known assembly: Name=", + assembly_name, " Path=", wszAssemblyPath); + return S_OK; + } + } + + // Construct an ASSEMBLYMETADATA structure for the managed profiler that can + // be consumed by the runtime + const AssemblyReference assemblyReference = trace::AssemblyReference(managed_profiler_full_assembly_version); + ASSEMBLYMETADATA assembly_metadata{}; + + assembly_metadata.usMajorVersion = assemblyReference.version.major; + assembly_metadata.usMinorVersion = assemblyReference.version.minor; + assembly_metadata.usBuildNumber = assemblyReference.version.build; + assembly_metadata.usRevisionNumber = assemblyReference.version.revision; + if (assemblyReference.locale == "neutral"_W) { + assembly_metadata.szLocale = const_cast("\0"_W.c_str()); + assembly_metadata.cbLocale = 0; + } else { + assembly_metadata.szLocale = + const_cast(assemblyReference.locale.c_str()); + assembly_metadata.cbLocale = (DWORD)(assemblyReference.locale.size()); + } + + DWORD public_key_size = 8; + if (assemblyReference.public_key == trace::PublicKey()) { + public_key_size = 0; + } + + COR_PRF_ASSEMBLY_REFERENCE_INFO asmRefInfo; + asmRefInfo.pbPublicKeyOrToken = + (void*)&assemblyReference.public_key.data[0]; + asmRefInfo.cbPublicKeyOrToken = public_key_size; + asmRefInfo.szName = assemblyReference.name.c_str(); + asmRefInfo.pMetaData = &assembly_metadata; + asmRefInfo.pbHashValue = nullptr; + asmRefInfo.cbHashValue = 0; + asmRefInfo.dwAssemblyRefFlags = 0; + + // Attempt to extend the assembly closure of the provided assembly to include + // the managed profiler + auto hr = pAsmRefProvider->AddAssemblyReference(&asmRefInfo); + if (FAILED(hr)) { + Warn("GetAssemblyReferences failed for call from ", wszAssemblyPath); + return S_OK; + } + + Debug("GetAssemblyReferences extending assembly closure for ", + assembly_name, " to include ", asmRefInfo.szName, + ". Path=", wszAssemblyPath); + instrument_domain_neutral_assemblies = true; + + return S_OK; +} + +bool CorProfiler::IsAttached() const { return is_attached_; } + +// +// Helper methods +// +HRESULT CorProfiler::ProcessReplacementCalls( + ModuleMetadata* module_metadata, + const FunctionID function_id, + const ModuleID module_id, + const mdToken function_token, + const trace::FunctionInfo& caller, + const std::vector method_replacements) { + ILRewriter rewriter(this->info_, nullptr, module_id, function_token); + bool modified = false; + auto hr = rewriter.Import(); + + if (FAILED(hr)) { + Warn("ProcessReplacementCalls: Call to ILRewriter.Import() failed for ", module_id, " ", function_token); + return hr; + } + + // Perform method call replacements + for (auto& method_replacement : method_replacements) { + // Exit early if the method replacement isn't actually doing a replacement + if (method_replacement.wrapper_method.action != "ReplaceTargetMethod"_W) { + continue; + } + + const auto& wrapper_method_key = + method_replacement.wrapper_method.get_method_cache_key(); + // Exit early if we previously failed to store the method ref for this wrapper_method + if (module_metadata->IsFailedWrapperMemberKey(wrapper_method_key)) { + continue; + } + + // for each IL instruction + for (ILInstr* pInstr = rewriter.GetILList()->m_pNext; + pInstr != rewriter.GetILList(); pInstr = pInstr->m_pNext) { + // only CALL or CALLVIRT + if (pInstr->m_opcode != CEE_CALL && pInstr->m_opcode != CEE_CALLVIRT) { + continue; + } + + // get the target function info, continue if its invalid + auto target = + GetFunctionInfo(module_metadata->metadata_import, pInstr->m_Arg32); + if (!target.IsValid()) { + continue; + } + + // make sure the type and method names match + if (method_replacement.target_method.type_name != target.type.name || + method_replacement.target_method.method_name != target.name) { + continue; + } + + // we add 3 parameters to every wrapper method: opcode, mdToken, and + // module_version_id + const short added_parameters_count = 3; + + auto wrapper_method_signature_size = + method_replacement.wrapper_method.method_signature.data.size(); + + if (wrapper_method_signature_size < (added_parameters_count + 3)) { + // wrapper signature must have at least 6 bytes + // 0:{CallingConvention}|1:{ParamCount}|2:{ReturnType}|3:{OpCode}|4:{mdToken}|5:{ModuleVersionId} + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted skipping function call: wrapper signature " + "too short. function_id=", + function_id, " token=", function_token, + " wrapper_method=", method_replacement.wrapper_method.type_name, + ".", method_replacement.wrapper_method.method_name, + "() wrapper_method_signature_size=", + wrapper_method_signature_size); + } + + continue; + } + + auto expected_number_args = method_replacement.wrapper_method + .method_signature.NumberOfArguments(); + + // subtract the last arguments we add to every wrapper + expected_number_args = expected_number_args - added_parameters_count; + + if (target.signature.IsInstanceMethod()) { + // We always pass the instance as the first argument + expected_number_args--; + } + + auto target_arg_count = target.signature.NumberOfArguments(); + + if (expected_number_args != target_arg_count) { + // Number of arguments does not match our wrapper method + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted skipping function call: argument counts " + "don't match. function_id=", + function_id, " token=", function_token, + " target_name=", target.type.name, ".", target.name, + "() expected_number_args=", expected_number_args, + " target_arg_count=", target_arg_count); + } + + continue; + } + + // Resolve the MethodRef now. If the method is generic, we'll need to use it + // to define a MethodSpec + // Generate a method ref token for the wrapper method + mdMemberRef wrapper_method_ref = mdMemberRefNil; + auto generated_wrapper_method_ref = GetWrapperMethodRef(module_metadata, + module_id, + method_replacement, + wrapper_method_ref); + if (!generated_wrapper_method_ref) { + Warn( + "JITCompilationStarted failed to obtain wrapper method ref for ", + method_replacement.wrapper_method.type_name, ".", method_replacement.wrapper_method.method_name, "().", + " function_id=", function_id, " function_token=", function_token, + " name=", caller.type.name, ".", caller.name, "()"); + continue; + } + + auto method_def_md_token = target.id; + + if (target.is_generic) { + if (target.signature.NumberOfTypeArguments() != + method_replacement.wrapper_method.method_signature + .NumberOfTypeArguments()) { + // Number of generic arguments does not match our wrapper method + continue; + } + + // we need to emit a method spec to populate the generic arguments + wrapper_method_ref = + DefineMethodSpec(module_metadata->metadata_emit, wrapper_method_ref, + target.function_spec_signature); + method_def_md_token = target.method_def_id; + } + + std::vector actual_sig; + const auto successfully_parsed_signature = TryParseSignatureTypes( + module_metadata->metadata_import, target, actual_sig); + auto expected_sig = + method_replacement.target_method.signature_types; + + if (!successfully_parsed_signature) { + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted skipping function call: failed to parse " + "signature. function_id=", + function_id, " token=", function_token, + " target_name=", target.type.name, ".", target.name, "()", + " successfully_parsed_signature=", successfully_parsed_signature, + " sig_types.size()=", actual_sig.size(), + " expected_sig_types.size()=", expected_sig.size()); + } + + continue; + } + + if (actual_sig.size() != expected_sig.size()) { + // we can't safely assume our wrapper methods handle the types + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted skipping function call: unexpected type " + "count. function_id=", + function_id, " token=", function_token, + " target_name=", target.type.name, ".", target.name, + "() successfully_parsed_signature=", + successfully_parsed_signature, + " sig_types.size()=", actual_sig.size(), + " expected_sig_types.size()=", expected_sig.size()); + } + + continue; + } + + auto is_match = true; + for (size_t i = 0; i < expected_sig.size(); i++) { + if (expected_sig[i] == "_"_W) { + // We are supposed to ignore this index + continue; + } + if (expected_sig[i] != actual_sig[i]) { + // we have a type mismatch, drop out + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted skipping function call: types don't " + "match. function_id=", + function_id, " token=", function_token, + " target_name=", target.type.name, ".", target.name, + "() actual[", i, "]=", actual_sig[i], ", expected[", + i, "]=", expected_sig[i]); + } + + is_match = false; + break; + } + } + + if (!is_match) { + // signatures don't match + continue; + } + + bool caller_assembly_is_domain_neutral = + runtime_information_.is_desktop() && corlib_module_loaded && + module_metadata->app_domain_id == corlib_app_domain_id; + + // At this point we know we've hit a match. Error out if + // 1) The managed profiler has not been loaded yet + // 2) The caller is domain-neutral AND we want to instrument domain-neutral assemblies AND the Profiler has already been loaded + if (!ProfilerAssemblyIsLoadedIntoAppDomain(module_metadata->app_domain_id)) { + Warn( + "JITCompilationStarted skipping method: Method replacement " + "found but the managed profiler has not yet been loaded " + "into AppDomain with id=", module_metadata->app_domain_id, + " function_id=", function_id, " token=", function_token, + " caller_name=", caller.type.name, ".", caller.name, "()", + " target_name=", target.type.name, ".", target.name, "()"); + continue; + } + + // At this point we know we've hit a match. Error out if + // 1) The calling assembly is domain-neutral + // 2) The profiler is not configured to instrument domain-neutral assemblies + if (caller_assembly_is_domain_neutral && !instrument_domain_neutral_assemblies) { + Warn( + "JITCompilationStarted skipping method: Method replacement", + " found but the calling assembly ", module_metadata->assemblyName, + " has been loaded domain-neutral so its code is being shared across AppDomains," + " making it unsafe for automatic instrumentation.", + " function_id=", function_id, " token=", function_token, + " caller_name=", caller.type.name, ".", caller.name, "()", + " target_name=", target.type.name, ".", target.name, "()"); + continue; + } + + const auto original_argument = pInstr->m_Arg32; + const void* module_version_id_ptr = &module_metadata->module_version_id; + + // Begin IL Modification + ILRewriterWrapper rewriter_wrapper(&rewriter); + rewriter_wrapper.SetILPosition(pInstr); + + // IL Modification #1: Replace original method call with a NOP, so that all original + // jump targets resolve correctly and we correctly populate the + // stack with additional arguments + // + // IMPORTANT: Conditional branches may jump to the original call instruction which + // resulted in the InvalidProgramException seen in + // https://github.com/DataDog/dd-trace-dotnet/pull/542. To avoid this, we'll do + // the rest of our IL modifications AFTER this instruction. + auto original_methodcall_opcode = pInstr->m_opcode; + pInstr->m_opcode = CEE_NOP; + pInstr = pInstr->m_pNext; + rewriter_wrapper.SetILPosition(pInstr); + + // IL Modification #2: Conditionally box System.Threading.CancellationToken + // if it is the last argument in the target method. + // + // If the last argument in the method signature is of the type + // System.Threading.CancellationToken (a struct) then box it before calling our + // integration method. This resolves https://github.com/DataDog/dd-trace-dotnet/issues/662, + // in which we did not box the System.Threading.CancellationToken object, even though the + // wrapper method expects an object. In that issue we observed some strange CLR behavior + // when the target method was in System.Data and the environment was 32-bit .NET Framework: + // the CLR swapped the values of the CancellationToken argument and the opCode argument. + // For example, the VIRTCALL opCode is '0x6F' and this value would be placed at the memory + // location assigned to the CancellationToken variable. Since we treat the CancellationToken + // variable as an object, this '0x6F' would be dereference to access the underlying object, + // and an invalid memory read would occur and crash the application. + // + // Currently, all integrations that use System.Threading.CancellationToken (a struct) + // have the argument as the last argument in the signature (lucky us!). + // For now, we'll do the following: + // 1) Get the method signature of the original target method + // 2) Read the signature until the final argument type + // 3) If the type begins with `ELEMENT_TYPE_VALUETYPE`, uncompress the compressed type token that follows + // 4) If the type token represents System.Threading.CancellationToken, emit a 'box ' IL instruction before calling our wrapper method + auto original_method_def = target.id; + size_t argument_count = target.signature.NumberOfArguments(); + size_t return_type_index = target.signature.IndexOfReturnType(); + PCCOR_SIGNATURE pSigCurrent = PCCOR_SIGNATURE(&target.signature.data[return_type_index]); // index to the location of the return type + bool signature_read_success = true; + + // iterate until the pointer is pointing at the last argument + for (size_t signature_types_index = 0; signature_types_index < argument_count; signature_types_index++) { + if (!ParseType(&pSigCurrent)) { + signature_read_success = false; + break; + } + } + + // read the last argument type + if (signature_read_success && *pSigCurrent == ELEMENT_TYPE_VALUETYPE) { + pSigCurrent++; + mdToken valuetype_type_token = CorSigUncompressToken(pSigCurrent); + + // Currently, we only expect to see `System.Threading.CancellationToken` as a valuetype in this position + // If we expand this to a general case, we would always perform the boxing regardless of type + if (GetTypeInfo(module_metadata->metadata_import, valuetype_type_token).name == "System.Threading.CancellationToken"_W) { + rewriter_wrapper.Box(valuetype_type_token); + } + } + + // IL Modification #3: Insert a non-virtual call (CALL) to the instrumentation wrapper. + // Always use CALL because the wrapper methods are all static. + rewriter_wrapper.CallMember(wrapper_method_ref, false); + rewriter_wrapper.SetILPosition(pInstr->m_pPrev); // Set ILPosition to method call + + // IL Modification #4: Push the following additional arguments on the evaluation stack in the + // following order, which all integration wrapper methods expect: + // 1) [int32] original CALL/CALLVIRT opCode + // 2) [int32] mdToken for original method call target + // 3) [int64] pointer to MVID + rewriter_wrapper.LoadInt32(original_methodcall_opcode); + rewriter_wrapper.LoadInt32(method_def_md_token); + rewriter_wrapper.LoadInt64(reinterpret_cast(module_version_id_ptr)); + + // IL Modification #5: Conditionally emit an unbox.any instruction on the return value + // of the wrapper method if we return an object but the original + // method call returned a valuetype or a generic type. + // + // This resolves https://github.com/DataDog/dd-trace-dotnet/pull/566, which raised a + // System.EntryPointNotFoundException. This occurred because the return type of the + // generic method was a generic type that evaluated to a value type at runtime. As a + // result, this caller method expected an unboxed representation of the return value, + // even though we can only return values of type object. So if we detect that the + // expected return type is a valuetype or a generic type, issue an unbox.any + // instruction that will unbox it. + mdToken typeToken; + if (method_replacement.wrapper_method.method_signature.ReturnTypeIsObject() + && ReturnTypeIsValueTypeOrGeneric(module_metadata->metadata_import, + module_metadata->metadata_emit, + module_metadata->assembly_emit, + target.id, + target.signature, + &typeToken)) { + if (debug_logging_enabled) { + Debug( + "JITCompilationStarted inserting 'unbox.any ", typeToken, + "' instruction after calling target function." + " function_id=", function_id, + " token=", function_token, + " target_name=", target.type.name, ".", target.name,"()"); + } + rewriter_wrapper.UnboxAnyAfter(typeToken); + } + + // End IL Modification + modified = true; + Info("*** JITCompilationStarted() replaced calls from ", caller.type.name, + ".", caller.name, "() to ", + method_replacement.target_method.type_name, ".", + method_replacement.target_method.method_name, "() ", + original_argument, " with calls to ", + method_replacement.wrapper_method.type_name, ".", + method_replacement.wrapper_method.method_name, "() ", + wrapper_method_ref); + } + } + + if (modified) { + hr = rewriter.Export(); + + if (FAILED(hr)) { + Warn("ProcessReplacementCalls: Call to ILRewriter.Export() failed for ModuleID=", module_id, " ", function_token); + return hr; + } + } + + return S_OK; +} + +HRESULT CorProfiler::ProcessInsertionCalls( + ModuleMetadata* module_metadata, + const FunctionID function_id, + const ModuleID module_id, + const mdToken function_token, + const FunctionInfo& caller, + const std::vector method_replacements) { + + ILRewriter rewriter(this->info_, nullptr, module_id, function_token); + bool modified = false; + + auto hr = rewriter.Import(); + + if (FAILED(hr)) { + Warn("ProcessInsertionCalls: Call to ILRewriter.Import() failed for ", module_id, " ", function_token); + return hr; + } + + ILRewriterWrapper rewriter_wrapper(&rewriter); + ILInstr* firstInstr = rewriter.GetILList()->m_pNext; + ILInstr* lastInstr = rewriter.GetILList()->m_pPrev; // Should be a 'ret' instruction + + for (auto& method_replacement : method_replacements) { + if (method_replacement.wrapper_method.action == "ReplaceTargetMethod"_W) { + continue; + } + + const auto& wrapper_method_key = + method_replacement.wrapper_method.get_method_cache_key(); + + // Exit early if we previously failed to store the method ref for this wrapper_method + if (module_metadata->IsFailedWrapperMemberKey(wrapper_method_key)) { + continue; + } + + // Generate a method ref token for the wrapper method + mdMemberRef wrapper_method_ref = mdMemberRefNil; + auto generated_wrapper_method_ref = GetWrapperMethodRef(module_metadata, + module_id, + method_replacement, + wrapper_method_ref); + if (!generated_wrapper_method_ref) { + Warn( + "JITCompilationStarted failed to obtain wrapper method ref for ", + method_replacement.wrapper_method.type_name, ".", method_replacement.wrapper_method.method_name, "().", + " function_id=", function_id, " function_token=", function_token, + " name=", caller.type.name, ".", caller.name, "()"); + continue; + } + + // After successfully getting the method reference, insert a call to it + if (method_replacement.wrapper_method.action == "InsertFirst"_W) { + // Get first instruction and set the rewriter to that location + rewriter_wrapper.SetILPosition(firstInstr); + rewriter_wrapper.CallMember(wrapper_method_ref, false); + firstInstr = firstInstr->m_pPrev; + modified = true; + + Info("*** JITCompilationStarted() : InsertFirst inserted call to ", + method_replacement.wrapper_method.type_name, ".", + method_replacement.wrapper_method.method_name, "() ", wrapper_method_ref, + " to the beginning of method", + caller.type.name,".", caller.name, "()"); + } + } + + if (modified) { + hr = rewriter.Export(); + + if (FAILED(hr)) { + Warn("ProcessInsertionCalls: Call to ILRewriter.Export() failed for ModuleID=", module_id, " ", function_token); + return hr; + } + } + + return S_OK; +} + +bool CorProfiler::GetWrapperMethodRef( + ModuleMetadata* module_metadata, + ModuleID module_id, + const MethodReplacement& method_replacement, + mdMemberRef& wrapper_method_ref) { + const auto& wrapper_method_key = + method_replacement.wrapper_method.get_method_cache_key(); + + // Resolve the MethodRef now. If the method is generic, we'll need to use it + // later to define a MethodSpec + if (!module_metadata->TryGetWrapperMemberRef(wrapper_method_key, + wrapper_method_ref)) { + const auto module_info = GetModuleInfo(this->info_, module_id); + if (!module_info.IsValid()) { + return false; + } + + mdModule module; + auto hr = module_metadata->metadata_import->GetModuleFromScope(&module); + if (FAILED(hr)) { + Warn( + "JITCompilationStarted failed to get module metadata token for " + "module_id=", module_id, " module_name=", module_info.assembly.name); + return false; + } + + const MetadataBuilder metadata_builder( + *module_metadata, module, module_metadata->metadata_import, + module_metadata->metadata_emit, module_metadata->assembly_import, + module_metadata->assembly_emit); + + // for each wrapper assembly, emit an assembly reference + hr = metadata_builder.EmitAssemblyRef( + method_replacement.wrapper_method.assembly); + if (FAILED(hr)) { + Warn( + "JITCompilationStarted failed to emit wrapper assembly ref for assembly=", + method_replacement.wrapper_method.assembly.name, + ", Version=", method_replacement.wrapper_method.assembly.version.str(), + ", Culture=", method_replacement.wrapper_method.assembly.locale, + " PublicKeyToken=", method_replacement.wrapper_method.assembly.public_key.str()); + return false; + } + + // for each method replacement in each enabled integration, + // emit a reference to the instrumentation wrapper methods + hr = metadata_builder.StoreWrapperMethodRef(method_replacement); + if (FAILED(hr)) { + Warn( + "JITCompilationStarted failed to obtain wrapper method ref for ", + method_replacement.wrapper_method.type_name, ".", method_replacement.wrapper_method.method_name, "()."); + return false; + } else { + module_metadata->TryGetWrapperMemberRef(wrapper_method_key, + wrapper_method_ref); + } + } + + return true; +} + +bool CorProfiler::ProfilerAssemblyIsLoadedIntoAppDomain(AppDomainID app_domain_id) { + return managed_profiler_loaded_domain_neutral || + managed_profiler_loaded_app_domains.find(app_domain_id) != + managed_profiler_loaded_app_domains.end(); +} + +// +// Startup methods +// +HRESULT CorProfiler::RunILStartupHook( + const ComPtr& metadata_emit, const ModuleID module_id, + const mdToken function_token) { + mdMethodDef ret_method_token; + auto hr = GenerateVoidILStartupMethod(module_id, &ret_method_token); + + if (FAILED(hr)) { + Warn("RunILStartupHook: Call to GenerateVoidILStartupMethod failed for ", module_id); + return hr; + } + + ILRewriter rewriter(this->info_, nullptr, module_id, function_token); + hr = rewriter.Import(); + + if (FAILED(hr)) { + Warn("RunILStartupHook: Call to ILRewriter.Import() failed for ", module_id, " ", function_token); + return hr; + } + + ILRewriterWrapper rewriter_wrapper(&rewriter); + + // Get first instruction and set the rewriter to that location + ILInstr* pInstr = rewriter.GetILList()->m_pNext; + rewriter_wrapper.SetILPosition(pInstr); + rewriter_wrapper.CallMember(ret_method_token, false); + hr = rewriter.Export(); + + if (FAILED(hr)) { + Warn("RunILStartupHook: Call to ILRewriter.Export() failed for ModuleID=", module_id, " ", function_token); + return hr; + } + + return S_OK; +} + +HRESULT CorProfiler::GenerateVoidILStartupMethod(const ModuleID module_id, + mdMethodDef* ret_method_token) { + ComPtr metadata_interfaces; + auto hr = this->info_->GetModuleMetaData(module_id, ofRead | ofWrite, + IID_IMetaDataImport2, + metadata_interfaces.GetAddressOf()); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: failed to get metadata interface for ", module_id); + return hr; + } + + const auto metadata_import = + metadata_interfaces.As(IID_IMetaDataImport); + const auto metadata_emit = + metadata_interfaces.As(IID_IMetaDataEmit); + const auto assembly_import = metadata_interfaces.As( + IID_IMetaDataAssemblyImport); + const auto assembly_emit = + metadata_interfaces.As(IID_IMetaDataAssemblyEmit); + + mdModuleRef mscorlib_ref; + hr = CreateAssemblyRefToMscorlib(assembly_emit, &mscorlib_ref); + + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: failed to define AssemblyRef to mscorlib"); + return hr; + } + + // Define a TypeRef for System.Object + mdTypeRef object_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, "System.Object"_W.c_str(), + &object_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Define a new TypeDef __DDVoidMethodType__ that extends System.Object + mdTypeDef new_type_def; + hr = metadata_emit->DefineTypeDef("__DDVoidMethodType__"_W.c_str(), tdAbstract | tdSealed, + object_type_ref, NULL, &new_type_def); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeDef failed"); + return hr; + } + + // Define a new static method __DDVoidMethodCall__ on the new type that has a void return type and takes no arguments + BYTE initialize_signature[] = { + IMAGE_CEE_CS_CALLCONV_DEFAULT, // Calling convention + 0, // Number of parameters + ELEMENT_TYPE_VOID, // Return type + ELEMENT_TYPE_OBJECT // List of parameter types + }; + hr = metadata_emit->DefineMethod(new_type_def, + "__DDVoidMethodCall__"_W.c_str(), + mdStatic, + initialize_signature, + sizeof(initialize_signature), + 0, + 0, + ret_method_token); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMethod failed"); + return hr; + } + + // Define a method on the managed side that will PInvoke into the profiler method: + // C++: void GetAssemblyAndSymbolsBytes(BYTE** pAssemblyArray, int* assemblySize, BYTE** pSymbolsArray, int* symbolsSize) + // C#: static extern void GetAssemblyAndSymbolsBytes(out IntPtr assemblyPtr, out int assemblySize, out IntPtr symbolsPtr, out int symbolsSize) + mdMethodDef pinvoke_method_def; + COR_SIGNATURE get_assembly_bytes_signature[] = { + IMAGE_CEE_CS_CALLCONV_DEFAULT, // Calling convention + 4, // Number of parameters + ELEMENT_TYPE_VOID, // Return type + ELEMENT_TYPE_BYREF, // List of parameter types + ELEMENT_TYPE_I, + ELEMENT_TYPE_BYREF, + ELEMENT_TYPE_I4, + ELEMENT_TYPE_BYREF, + ELEMENT_TYPE_I, + ELEMENT_TYPE_BYREF, + ELEMENT_TYPE_I4, + }; + hr = metadata_emit->DefineMethod( + new_type_def, "GetAssemblyAndSymbolsBytes"_W.c_str(), mdStatic | mdPinvokeImpl | mdHideBySig, + get_assembly_bytes_signature, sizeof(get_assembly_bytes_signature), 0, 0, + &pinvoke_method_def); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMethod failed"); + return hr; + } + + metadata_emit->SetMethodImplFlags(pinvoke_method_def, miPreserveSig); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: SetMethodImplFlags failed"); + return hr; + } + +#ifdef _WIN32 + WSTRING native_profiler_file = "DATADOG.TRACE.CLRPROFILER.NATIVE.DLL"_W; +#else // _WIN32 + +#ifdef BIT64 + WSTRING native_profiler_file = GetEnvironmentValue("CORECLR_PROFILER_PATH_64"_W); + Debug("GenerateVoidILStartupMethod: Linux: CORECLR_PROFILER_PATH_64 defined as: ", native_profiler_file); + if (native_profiler_file == ""_W) { + native_profiler_file = GetEnvironmentValue("CORECLR_PROFILER_PATH"_W); + Debug("GenerateVoidILStartupMethod: Linux: CORECLR_PROFILER_PATH defined as: ", native_profiler_file); + } +#else // BIT64 + WSTRING native_profiler_file = GetEnvironmentValue("CORECLR_PROFILER_PATH_32"_W); + Debug("GenerateVoidILStartupMethod: Linux: CORECLR_PROFILER_PATH_32 defined as: ", native_profiler_file); + if (native_profiler_file == ""_W) { + native_profiler_file = GetEnvironmentValue("CORECLR_PROFILER_PATH"_W); + Debug("GenerateVoidILStartupMethod: Linux: CORECLR_PROFILER_PATH defined as: ", native_profiler_file); + } +#endif // BIT64 +Debug("GenerateVoidILStartupMethod: Linux: Setting the PInvoke native profiler library path to ", native_profiler_file); + +#endif // _WIN32 + + mdModuleRef profiler_ref; + hr = metadata_emit->DefineModuleRef(native_profiler_file.c_str(), + &profiler_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineModuleRef failed"); + return hr; + } + + hr = metadata_emit->DefinePinvokeMap(pinvoke_method_def, + 0, + "GetAssemblyAndSymbolsBytes"_W.c_str(), + profiler_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefinePinvokeMap failed"); + return hr; + } + + // Get a TypeRef for System.Byte + mdTypeRef byte_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, + "System.Byte"_W.c_str(), + &byte_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Get a TypeRef for System.Runtime.InteropServices.Marshal + mdTypeRef marshal_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, + "System.Runtime.InteropServices.Marshal"_W.c_str(), + &marshal_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Get a MemberRef for System.Runtime.InteropServices.Marshal.Copy(IntPtr, Byte[], int, int) + mdMemberRef marshal_copy_member_ref; + COR_SIGNATURE marshal_copy_signature[] = { + IMAGE_CEE_CS_CALLCONV_DEFAULT, // Calling convention + 4, // Number of parameters + ELEMENT_TYPE_VOID, // Return type + ELEMENT_TYPE_I, // List of parameter types + ELEMENT_TYPE_SZARRAY, + ELEMENT_TYPE_U1, + ELEMENT_TYPE_I4, + ELEMENT_TYPE_I4 + }; + hr = metadata_emit->DefineMemberRef( + marshal_type_ref, "Copy"_W.c_str(), marshal_copy_signature, + sizeof(marshal_copy_signature), &marshal_copy_member_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMemberRef failed"); + return hr; + } + + // Get a TypeRef for System.Reflection.Assembly + mdTypeRef system_reflection_assembly_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, + "System.Reflection.Assembly"_W.c_str(), + &system_reflection_assembly_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Get a MemberRef for System.Object.ToString() + mdTypeRef system_object_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, + "System.Object"_W.c_str(), + &system_object_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Get a TypeRef for System.AppDomain + mdTypeRef system_appdomain_type_ref; + hr = metadata_emit->DefineTypeRefByName(mscorlib_ref, + "System.AppDomain"_W.c_str(), + &system_appdomain_type_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineTypeRefByName failed"); + return hr; + } + + // Get a MemberRef for System.AppDomain.get_CurrentDomain() + // and System.AppDomain.Assembly.Load(byte[], byte[]) + + // Create method signature for AppDomain.CurrentDomain property + COR_SIGNATURE appdomain_get_current_domain_signature_start[] = { + IMAGE_CEE_CS_CALLCONV_DEFAULT, + 0, + ELEMENT_TYPE_CLASS, // ret = System.AppDomain + // insert compressed token for System.AppDomain TypeRef here + }; + ULONG start_length = sizeof(appdomain_get_current_domain_signature_start); + + BYTE system_appdomain_type_ref_compressed_token[4]; + ULONG token_length = CorSigCompressToken(system_appdomain_type_ref, system_appdomain_type_ref_compressed_token); + + COR_SIGNATURE* appdomain_get_current_domain_signature = new COR_SIGNATURE[start_length + token_length]; + memcpy(appdomain_get_current_domain_signature, + appdomain_get_current_domain_signature_start, + start_length); + memcpy(&appdomain_get_current_domain_signature[start_length], + system_appdomain_type_ref_compressed_token, + token_length); + + mdMemberRef appdomain_get_current_domain_member_ref; + hr = metadata_emit->DefineMemberRef( + system_appdomain_type_ref, + "get_CurrentDomain"_W.c_str(), + appdomain_get_current_domain_signature, + start_length + token_length, + &appdomain_get_current_domain_member_ref); + delete[] appdomain_get_current_domain_signature; + + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMemberRef failed"); + return hr; + } + + // Create method signature for AppDomain.Load(byte[], byte[]) + COR_SIGNATURE appdomain_load_signature_start[] = { + IMAGE_CEE_CS_CALLCONV_HASTHIS, + 2, + ELEMENT_TYPE_CLASS // ret = System.Reflection.Assembly + // insert compressed token for System.Reflection.Assembly TypeRef here + }; + COR_SIGNATURE appdomain_load_signature_end[] = { + ELEMENT_TYPE_SZARRAY, + ELEMENT_TYPE_U1, + ELEMENT_TYPE_SZARRAY, + ELEMENT_TYPE_U1 + }; + start_length = sizeof(appdomain_load_signature_start); + ULONG end_length = sizeof(appdomain_load_signature_end); + + BYTE system_reflection_assembly_type_ref_compressed_token[4]; + token_length = CorSigCompressToken(system_reflection_assembly_type_ref, system_reflection_assembly_type_ref_compressed_token); + + COR_SIGNATURE* appdomain_load_signature = new COR_SIGNATURE[start_length + token_length + end_length]; + memcpy(appdomain_load_signature, + appdomain_load_signature_start, + start_length); + memcpy(&appdomain_load_signature[start_length], + system_reflection_assembly_type_ref_compressed_token, + token_length); + memcpy(&appdomain_load_signature[start_length + token_length], + appdomain_load_signature_end, + end_length); + + mdMemberRef appdomain_load_member_ref; + hr = metadata_emit->DefineMemberRef( + system_appdomain_type_ref, "Load"_W.c_str(), + appdomain_load_signature, + start_length + token_length + end_length, + &appdomain_load_member_ref); + delete[] appdomain_load_signature; + + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMemberRef failed"); + return hr; + } + + // Create method signature for Assembly.CreateInstance(string) + COR_SIGNATURE assembly_create_instance_signature[] = { + IMAGE_CEE_CS_CALLCONV_HASTHIS, + 1, + ELEMENT_TYPE_OBJECT, // ret = System.Object + ELEMENT_TYPE_STRING + }; + + mdMemberRef assembly_create_instance_member_ref; + hr = metadata_emit->DefineMemberRef( + system_reflection_assembly_type_ref, "CreateInstance"_W.c_str(), + assembly_create_instance_signature, + sizeof(assembly_create_instance_signature), + &assembly_create_instance_member_ref); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineMemberRef failed"); + return hr; + } + + // Create a string representing "Datadog.Trace.ClrProfiler.Managed.Loader.Startup" + // Create OS-specific implementations because on Windows, creating the string via + // "Datadog.Trace.ClrProfiler.Managed.Loader.Startup"_W.c_str() does not create the + // proper string for CreateInstance to successfully call +#ifdef _WIN32 + LPCWSTR load_helper_str = + L"Datadog.Trace.ClrProfiler.Managed.Loader.Startup"; + auto load_helper_str_size = wcslen(load_helper_str); +#else + char16_t load_helper_str[] = + u"Datadog.Trace.ClrProfiler.Managed.Loader.Startup"; + auto load_helper_str_size = std::char_traits::length(load_helper_str); +#endif + + mdString load_helper_token; + hr = metadata_emit->DefineUserString(load_helper_str, (ULONG) load_helper_str_size, + &load_helper_token); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: DefineUserString failed"); + return hr; + } + + ULONG string_len = 0; + WCHAR string_contents[kNameMaxSize]{}; + hr = metadata_import->GetUserString(load_helper_token, string_contents, + kNameMaxSize, &string_len); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: fail quickly", module_id); + return hr; + } + + // Generate a locals signature defined in the following way: + // [0] System.IntPtr ("assemblyPtr" - address of assembly bytes) + // [1] System.Int32 ("assemblySize" - size of assembly bytes) + // [2] System.IntPtr ("symbolsPtr" - address of symbols bytes) + // [3] System.Int32 ("symbolsSize" - size of symbols bytes) + // [4] System.Byte[] ("assemblyBytes" - managed byte array for assembly) + // [5] System.Byte[] ("symbolsBytes" - managed byte array for symbols) + // [6] class System.Reflection.Assembly ("loadedAssembly" - assembly instance to save loaded assembly) + mdSignature locals_signature_token; + COR_SIGNATURE locals_signature[15] = { + IMAGE_CEE_CS_CALLCONV_LOCAL_SIG, // Calling convention + 7, // Number of variables + ELEMENT_TYPE_I, // List of variable types + ELEMENT_TYPE_I4, + ELEMENT_TYPE_I, + ELEMENT_TYPE_I4, + ELEMENT_TYPE_SZARRAY, + ELEMENT_TYPE_U1, + ELEMENT_TYPE_SZARRAY, + ELEMENT_TYPE_U1, + ELEMENT_TYPE_CLASS + // insert compressed token for System.Reflection.Assembly TypeRef here + }; + CorSigCompressToken(system_reflection_assembly_type_ref, + &locals_signature[11]); + hr = metadata_emit->GetTokenFromSig(locals_signature, sizeof(locals_signature), + &locals_signature_token); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: Unable to generate locals signature. ModuleID=", module_id); + return hr; + } + + ///////////////////////////////////////////// + // Add IL instructions into the void method + ILRewriter rewriter_void(this->info_, nullptr, module_id, *ret_method_token); + rewriter_void.InitializeTiny(); + rewriter_void.SetTkLocalVarSig(locals_signature_token); + ILInstr* pFirstInstr = rewriter_void.GetILList()->m_pNext; + ILInstr* pNewInstr = NULL; + + // Step 1) Call void GetAssemblyAndSymbolsBytes(out IntPtr assemblyPtr, out int assemblySize, out IntPtr symbolsPtr, out int symbolsSize) + + // ldloca.s 0 : Load the address of the "assemblyPtr" variable (locals index 0) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOCA_S; + pNewInstr->m_Arg32 = 0; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloca.s 1 : Load the address of the "assemblySize" variable (locals index 1) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOCA_S; + pNewInstr->m_Arg32 = 1; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloca.s 2 : Load the address of the "symbolsPtr" variable (locals index 2) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOCA_S; + pNewInstr->m_Arg32 = 2; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloca.s 3 : Load the address of the "symbolsSize" variable (locals index 3) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOCA_S; + pNewInstr->m_Arg32 = 3; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // call void GetAssemblyAndSymbolsBytes(out IntPtr assemblyPtr, out int assemblySize, out IntPtr symbolsPtr, out int symbolsSize) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALL; + pNewInstr->m_Arg32 = pinvoke_method_def; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // Step 2) Call void Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length) to populate the managed assembly bytes + + // ldloc.1 : Load the "assemblySize" variable (locals index 1) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_1; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // newarr System.Byte : Create a new Byte[] to hold a managed copy of the assembly data + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_NEWARR; + pNewInstr->m_Arg32 = byte_type_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // stloc.s 4 : Assign the Byte[] to the "assemblyBytes" variable (locals index 4) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_STLOC_S; + pNewInstr->m_Arg8 = 4; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.0 : Load the "assemblyPtr" variable (locals index 0) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_0; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.s 4 : Load the "assemblyBytes" variable (locals index 4) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_S; + pNewInstr->m_Arg8 = 4; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldc.i4.0 : Load the integer 0 for the Marshal.Copy startIndex parameter + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDC_I4_0; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.1 : Load the "assemblySize" variable (locals index 1) for the Marshal.Copy length parameter + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_1; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // call Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALL; + pNewInstr->m_Arg32 = marshal_copy_member_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // Step 3) Call void Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length) to populate the symbols bytes + + // ldloc.3 : Load the "symbolsSize" variable (locals index 3) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_3; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // newarr System.Byte : Create a new Byte[] to hold a managed copy of the symbols data + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_NEWARR; + pNewInstr->m_Arg32 = byte_type_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // stloc.s 5 : Assign the Byte[] to the "symbolsBytes" variable (locals index 5) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_STLOC_S; + pNewInstr->m_Arg8 = 5; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.2 : Load the "symbolsPtr" variables (locals index 2) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_2; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.s 5 : Load the "symbolsBytes" variable (locals index 5) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_S; + pNewInstr->m_Arg8 = 5; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldc.i4.0 : Load the integer 0 for the Marshal.Copy startIndex parameter + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDC_I4_0; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.3 : Load the "symbolsSize" variable (locals index 3) for the Marshal.Copy length parameter + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_3; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // call void Marshal.Copy(IntPtr source, byte[] destination, int startIndex, int length) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALL; + pNewInstr->m_Arg32 = marshal_copy_member_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // Step 4) Call System.Reflection.Assembly System.AppDomain.CurrentDomain.Load(byte[], byte[])) + + // call System.AppDomain System.AppDomain.CurrentDomain property + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALL; + pNewInstr->m_Arg32 = appdomain_get_current_domain_member_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.s 4 : Load the "assemblyBytes" variable (locals index 4) for the first byte[] parameter of AppDomain.Load(byte[], byte[]) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_S; + pNewInstr->m_Arg8 = 4; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldloc.s 5 : Load the "symbolsBytes" variable (locals index 5) for the second byte[] parameter of AppDomain.Load(byte[], byte[]) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_S; + pNewInstr->m_Arg8 = 5; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // callvirt System.Reflection.Assembly System.AppDomain.Load(uint8[], uint8[]) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALLVIRT; + pNewInstr->m_Arg32 = appdomain_load_member_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // stloc.s 6 : Assign the System.Reflection.Assembly object to the "loadedAssembly" variable (locals index 6) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_STLOC_S; + pNewInstr->m_Arg8 = 6; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // Step 4) Call instance method Assembly.CreateInstance("Datadog.Trace.ClrProfiler.Managed.Loader.Startup") + + // ldloc.s 6 : Load the "loadedAssembly" variable (locals index 6) to call Assembly.CreateInstance + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDLOC_S; + pNewInstr->m_Arg8 = 6; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // ldstr "Datadog.Trace.ClrProfiler.Managed.Loader.Startup" + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_LDSTR; + pNewInstr->m_Arg32 = load_helper_token; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // callvirt System.Object System.Reflection.Assembly.CreateInstance(string) + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_CALLVIRT; + pNewInstr->m_Arg32 = assembly_create_instance_member_ref; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // pop the returned object + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_POP; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + // return + pNewInstr = rewriter_void.NewILInstr(); + pNewInstr->m_opcode = CEE_RET; + rewriter_void.InsertBefore(pFirstInstr, pNewInstr); + + hr = rewriter_void.Export(); + if (FAILED(hr)) { + Warn("GenerateVoidILStartupMethod: Call to ILRewriter.Export() failed for ModuleID=", module_id); + return hr; + } + + return S_OK; +} + +#ifndef _WIN32 +extern uint8_t dll_start[] asm("_binary_Datadog_Trace_ClrProfiler_Managed_Loader_dll_start"); +extern uint8_t dll_end[] asm("_binary_Datadog_Trace_ClrProfiler_Managed_Loader_dll_end"); + +extern uint8_t pdb_start[] asm("_binary_Datadog_Trace_ClrProfiler_Managed_Loader_pdb_start"); +extern uint8_t pdb_end[] asm("_binary_Datadog_Trace_ClrProfiler_Managed_Loader_pdb_end"); +#endif + +void CorProfiler::GetAssemblyAndSymbolsBytes(BYTE** pAssemblyArray, int* assemblySize, BYTE** pSymbolsArray, int* symbolsSize) const { +#ifdef _WIN32 + HINSTANCE hInstance = DllHandle; + LPCWSTR dllLpName; + LPCWSTR symbolsLpName; + + if (runtime_information_.is_desktop()) { + dllLpName = MAKEINTRESOURCE(NET45_MANAGED_ENTRYPOINT_DLL); + symbolsLpName = MAKEINTRESOURCE(NET45_MANAGED_ENTRYPOINT_SYMBOLS); + } else { + dllLpName = MAKEINTRESOURCE(NETCOREAPP20_MANAGED_ENTRYPOINT_DLL); + symbolsLpName = MAKEINTRESOURCE(NETCOREAPP20_MANAGED_ENTRYPOINT_SYMBOLS); + } + + HRSRC hResAssemblyInfo = FindResource(hInstance, dllLpName, L"ASSEMBLY"); + HGLOBAL hResAssembly = LoadResource(hInstance, hResAssemblyInfo); + *assemblySize = SizeofResource(hInstance, hResAssemblyInfo); + *pAssemblyArray = (LPBYTE)LockResource(hResAssembly); + + HRSRC hResSymbolsInfo = FindResource(hInstance, symbolsLpName, L"SYMBOLS"); + HGLOBAL hResSymbols = LoadResource(hInstance, hResSymbolsInfo); + *symbolsSize = SizeofResource(hInstance, hResSymbolsInfo); + *pSymbolsArray = (LPBYTE)LockResource(hResSymbols); +#else + *assemblySize = dll_end - dll_start; + *pAssemblyArray = (BYTE*)dll_start; + + *symbolsSize = pdb_end - pdb_start; + *pSymbolsArray = (BYTE*)pdb_start; +#endif + return; +} +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.h b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.h new file mode 100644 index 0000000000..c0eca4e183 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler.h @@ -0,0 +1,118 @@ +#ifndef DD_CLR_PROFILER_COR_PROFILER_H_ +#define DD_CLR_PROFILER_COR_PROFILER_H_ + +#include +#include +#include +#include +#include "cor.h" +#include "corprof.h" + +#include "cor_profiler_base.h" +#include "environment_variables.h" +#include "integration.h" +#include "module_metadata.h" +#include "pal.h" + +namespace trace { + +class CorProfiler : public CorProfilerBase { + private: + bool is_attached_ = false; + RuntimeInformation runtime_information_; + std::vector integration_methods_; + + // Startup helper variables + bool first_jit_compilation_completed = false; + + bool instrument_domain_neutral_assemblies = false; + bool corlib_module_loaded = false; + AppDomainID corlib_app_domain_id; + bool managed_profiler_loaded_domain_neutral = false; + std::unordered_set managed_profiler_loaded_app_domains; + std::unordered_set first_jit_compilation_app_domains; + bool in_azure_app_services = false; + bool is_desktop_iis = false; + + // + // Module helper variables + // + std::mutex module_id_to_info_map_lock_; + std::unordered_map module_id_to_info_map_; + + // + // Helper methods + // + bool GetWrapperMethodRef(ModuleMetadata* module_metadata, + ModuleID module_id, + const MethodReplacement& method_replacement, + mdMemberRef& wrapper_method_ref); + HRESULT ProcessReplacementCalls(ModuleMetadata* module_metadata, + const FunctionID function_id, + const ModuleID module_id, + const mdToken function_token, + const FunctionInfo& caller, + const std::vector method_replacements); + HRESULT ProcessInsertionCalls(ModuleMetadata* module_metadata, + const FunctionID function_id, + const ModuleID module_id, + const mdToken function_token, + const FunctionInfo& caller, + const std::vector method_replacements); + bool ProfilerAssemblyIsLoadedIntoAppDomain(AppDomainID app_domain_id); + + // + // Startup methods + // + HRESULT RunILStartupHook(const ComPtr&, + const ModuleID module_id, + const mdToken function_token); + HRESULT GenerateVoidILStartupMethod(const ModuleID module_id, + mdMethodDef* ret_method_token); + + public: + CorProfiler() = default; + + bool IsAttached() const; + + void GetAssemblyAndSymbolsBytes(BYTE** pAssemblyArray, int* assemblySize, + BYTE** pSymbolsArray, int* symbolsSize) const; + + // + // ICorProfilerCallback methods + // + HRESULT STDMETHODCALLTYPE + Initialize(IUnknown* cor_profiler_info_unknown) override; + + HRESULT STDMETHODCALLTYPE AssemblyLoadFinished(AssemblyID assembly_id, + HRESULT hr_status) override; + + HRESULT STDMETHODCALLTYPE ModuleLoadFinished(ModuleID module_id, + HRESULT hr_status) override; + + HRESULT STDMETHODCALLTYPE ModuleUnloadStarted(ModuleID module_id) override; + + HRESULT STDMETHODCALLTYPE + JITCompilationStarted(FunctionID function_id, BOOL is_safe_to_block) override; + + HRESULT STDMETHODCALLTYPE Shutdown() override; + + // + // ICorProfilerCallback6 methods + // + HRESULT STDMETHODCALLTYPE GetAssemblyReferences( + const WCHAR* wszAssemblyPath, + ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) override; +}; + +// Note: Generally you should not have a single, global callback implementation, +// as that prevents your profiler from analyzing multiply loaded in-process +// side-by-side CLRs. However, this profiler implements the "profile-first" +// alternative of dealing with multiple in-process side-by-side CLR instances. +// First CLR to try to load us into this process wins; so there can only be one +// callback implementation created. (See ProfilerCallback::CreateObject.) +extern CorProfiler* profiler; // global reference to callback object + +} // namespace trace + +#endif // DD_CLR_PROFILER_COR_PROFILER_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.cpp b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.cpp new file mode 100644 index 0000000000..004a480b50 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.cpp @@ -0,0 +1,478 @@ +#include "cor_profiler_base.h" +#include "logging.h" + +namespace trace { + +CorProfilerBase::CorProfilerBase() : ref_count_(0), info_(nullptr) {} + +CorProfilerBase::~CorProfilerBase() { + if (this->info_ != nullptr) { + this->info_->Release(); + this->info_ = nullptr; + } +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::Initialize(IUnknown *pICorProfilerInfoUnk) { + Debug("Initialize"); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::Shutdown() { + Debug("Shutdown"); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::AppDomainCreationStarted(AppDomainID appDomainId) { + Debug("AppDomainCreationStarted: ", appDomainId); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::AppDomainCreationFinished( + AppDomainID appDomainId, HRESULT hrStatus) { + Debug("AppDomainCreationFinished: ", appDomainId, " hrStatus=", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::AppDomainShutdownStarted(AppDomainID appDomainId) { + Debug("AppDomainShutdownStarted: ", appDomainId); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::AppDomainShutdownFinished( + AppDomainID appDomainId, HRESULT hrStatus) { + Debug("AppDomainShutdownFinished: ", appDomainId, " ", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::AssemblyLoadStarted(AssemblyID assemblyId) { + Debug("AssemblyLoadStarted: ", assemblyId); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) { + Debug("AssemblyLoadFinished: ", assemblyId, " ", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::AssemblyUnloadStarted(AssemblyID assemblyId) { + Debug("AssemblyUnloadStarted: ", assemblyId); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::AssemblyUnloadFinished( + AssemblyID assemblyId, HRESULT hrStatus) { + Debug("AssemblyUnloadFinished: ", assemblyId, " ", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ModuleLoadStarted(ModuleID moduleId) { + Debug("ModuleLoadStarted: ", moduleId); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) { + Debug("ModuleLoadFinished: ", moduleId, " ", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ModuleUnloadStarted(ModuleID moduleId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) { + Debug("ModuleUnloadFinished: ", moduleId, " ", hrStatus); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ModuleAttachedToAssembly( + ModuleID moduleId, AssemblyID AssemblyId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ClassLoadStarted(ClassID classId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ClassLoadFinished(ClassID classId, + HRESULT hrStatus) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ClassUnloadStarted(ClassID classId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ClassUnloadFinished(ClassID classId, HRESULT hrStatus) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::FunctionUnloadStarted(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::JITCompilationStarted( + FunctionID functionId, BOOL fIsSafeToBlock) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::JITCompilationFinished( + FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::JITCachedFunctionSearchStarted( + FunctionID functionId, BOOL *pbUseCachedFunction) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::JITCachedFunctionSearchFinished( + FunctionID functionId, COR_PRF_JIT_CACHE result) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::JITFunctionPitched(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::JITInlining(FunctionID callerId, + FunctionID calleeId, + BOOL *pfShouldInline) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ThreadCreated(ThreadID threadId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ThreadDestroyed(ThreadID threadId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ThreadAssignedToOSThread( + ThreadID managedThreadId, DWORD osThreadId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RemotingClientInvocationStarted() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RemotingClientSendingMessage(GUID *pCookie, BOOL fIsAsync) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RemotingClientReceivingReply(GUID *pCookie, BOOL fIsAsync) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RemotingClientInvocationFinished() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RemotingServerReceivingMessage(GUID *pCookie, BOOL fIsAsync) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RemotingServerInvocationStarted() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RemotingServerInvocationReturned() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RemotingServerSendingReply(GUID *pCookie, BOOL fIsAsync) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::UnmanagedToManagedTransition( + FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ManagedToUnmanagedTransition( + FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RuntimeSuspendFinished() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RuntimeSuspendAborted() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RuntimeResumeStarted() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RuntimeResumeFinished() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RuntimeThreadSuspended(ThreadID threadId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RuntimeThreadResumed(ThreadID threadId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::MovedReferences( + ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], + ObjectID newObjectIDRangeStart[], ULONG cObjectIDRangeLength[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ObjectAllocated(ObjectID objectId, + ClassID classId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ObjectsAllocatedByClass( + ULONG cClassCount, ClassID classIds[], ULONG cObjects[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ObjectReferences(ObjectID objectId, ClassID classId, + ULONG cObjectRefs, ObjectID objectRefIds[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::RootReferences(ULONG cRootRefs, ObjectID rootRefIds[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionThrown(ObjectID thrownObjectId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionSearchFunctionEnter(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionSearchFunctionLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionSearchFilterEnter(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionSearchFilterLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionSearchCatcherFound(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionOSHandlerEnter(UINT_PTR __unused) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionOSHandlerLeave(UINT_PTR __unused) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionUnwindFunctionEnter(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionUnwindFunctionLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ExceptionUnwindFinallyEnter(FunctionID functionId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionUnwindFinallyLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionCatcherEnter( + FunctionID functionId, ObjectID objectId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionCatcherLeave() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::COMClassicVTableCreated( + ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, + ULONG cSlots) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::COMClassicVTableDestroyed( + ClassID wrappedClassId, REFGUID implementedIID, void *pVTable) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionCLRCatcherFound() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ExceptionCLRCatcherExecute() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ThreadNameChanged(ThreadID threadId, + ULONG cchName, + WCHAR name[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::GarbageCollectionStarted( + int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::SurvivingReferences( + ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], + ULONG cObjectIDRangeLength[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::GarbageCollectionFinished() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::FinalizeableObjectQueued( + DWORD finalizerFlags, ObjectID objectID) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::RootReferences2( + ULONG cRootRefs, ObjectID rootRefIds[], COR_PRF_GC_ROOT_KIND rootKinds[], + COR_PRF_GC_ROOT_FLAGS rootFlags[], UINT_PTR rootIds[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::HandleCreated(GCHandleID handleId, ObjectID initialObjectId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::HandleDestroyed(GCHandleID handleId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::InitializeForAttach( + IUnknown *pCorProfilerInfoUnk, void *pvClientData, UINT cbClientData) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ProfilerAttachComplete() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ProfilerDetachSucceeded() { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ReJITCompilationStarted( + FunctionID functionId, ReJITID rejitId, BOOL fIsSafeToBlock) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::GetReJITParameters( + ModuleID moduleId, mdMethodDef methodId, + ICorProfilerFunctionControl *pFunctionControl) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ReJITCompilationFinished( + FunctionID functionId, ReJITID rejitId, HRESULT hrStatus, + BOOL fIsSafeToBlock) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::ReJITError(ModuleID moduleId, + mdMethodDef methodId, + FunctionID functionId, + HRESULT hrStatus) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::MovedReferences2( + ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], + ObjectID newObjectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::SurvivingReferences2( + ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], + SIZE_T cObjectIDRangeLength[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ConditionalWeakTableElementReferences(ULONG cRootRefs, + ObjectID keyRefIds[], + ObjectID valueRefIds[], + GCHandleID rootIds[]) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::GetAssemblyReferences( + const WCHAR *wszAssemblyPath, + ICorProfilerAssemblyReferenceProvider *pAsmRefProvider) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CorProfilerBase::ModuleInMemorySymbolsUpdated(ModuleID moduleId) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::DynamicMethodJITCompilationStarted( + FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE ilHeader, + ULONG cbILHeader) { + return S_OK; +} + +HRESULT STDMETHODCALLTYPE CorProfilerBase::DynamicMethodJITCompilationFinished( + FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { + return S_OK; +} + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.h b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.h new file mode 100644 index 0000000000..fd208cad28 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/cor_profiler_base.h @@ -0,0 +1,228 @@ +#ifndef DD_CLR_PROFILER_COR_PROFILER_BASE_H_ +#define DD_CLR_PROFILER_COR_PROFILER_BASE_H_ + +#include +#include +#include + +namespace trace { + +class CorProfilerBase : public ICorProfilerCallback8 { + private: + std::atomic ref_count_; + + protected: + ICorProfilerInfo3* info_; + + public: + CorProfilerBase(); + virtual ~CorProfilerBase(); + + HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk) override; + HRESULT STDMETHODCALLTYPE Shutdown() override; + HRESULT STDMETHODCALLTYPE + AppDomainCreationStarted(AppDomainID appDomainId) override; + HRESULT STDMETHODCALLTYPE + AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE + AppDomainShutdownStarted(AppDomainID appDomainId) override; + HRESULT STDMETHODCALLTYPE + AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE AssemblyLoadStarted(AssemblyID assemblyId) override; + HRESULT STDMETHODCALLTYPE AssemblyLoadFinished(AssemblyID assemblyId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE + AssemblyUnloadStarted(AssemblyID assemblyId) override; + HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished(AssemblyID assemblyId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE ModuleLoadStarted(ModuleID moduleId) override; + HRESULT STDMETHODCALLTYPE ModuleLoadFinished(ModuleID moduleId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE ModuleUnloadStarted(ModuleID moduleId) override; + HRESULT STDMETHODCALLTYPE ModuleUnloadFinished(ModuleID moduleId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE + ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) override; + HRESULT STDMETHODCALLTYPE ClassLoadStarted(ClassID classId) override; + HRESULT STDMETHODCALLTYPE ClassLoadFinished(ClassID classId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE ClassUnloadStarted(ClassID classId) override; + HRESULT STDMETHODCALLTYPE ClassUnloadFinished(ClassID classId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE + FunctionUnloadStarted(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE JITCompilationStarted(FunctionID functionId, + BOOL fIsSafeToBlock) override; + HRESULT STDMETHODCALLTYPE JITCompilationFinished( + FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override; + HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchStarted( + FunctionID functionId, BOOL* pbUseCachedFunction) override; + HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchFinished( + FunctionID functionId, COR_PRF_JIT_CACHE result) override; + HRESULT STDMETHODCALLTYPE JITFunctionPitched(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE JITInlining(FunctionID callerId, + FunctionID calleeId, + BOOL* pfShouldInline) override; + HRESULT STDMETHODCALLTYPE ThreadCreated(ThreadID threadId) override; + HRESULT STDMETHODCALLTYPE ThreadDestroyed(ThreadID threadId) override; + HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread(ThreadID managedThreadId, + DWORD osThreadId) override; + HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted() override; + HRESULT STDMETHODCALLTYPE + RemotingClientSendingMessage(GUID* pCookie, BOOL fIsAsync) override; + HRESULT STDMETHODCALLTYPE + RemotingClientReceivingReply(GUID* pCookie, BOOL fIsAsync) override; + HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished() override; + HRESULT STDMETHODCALLTYPE + RemotingServerReceivingMessage(GUID* pCookie, BOOL fIsAsync) override; + HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted() override; + HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned() override; + HRESULT STDMETHODCALLTYPE RemotingServerSendingReply(GUID* pCookie, + BOOL fIsAsync) override; + HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition( + FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override; + HRESULT STDMETHODCALLTYPE ManagedToUnmanagedTransition( + FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override; + HRESULT STDMETHODCALLTYPE + RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) override; + HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished() override; + HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted() override; + HRESULT STDMETHODCALLTYPE RuntimeResumeStarted() override; + HRESULT STDMETHODCALLTYPE RuntimeResumeFinished() override; + HRESULT STDMETHODCALLTYPE RuntimeThreadSuspended(ThreadID threadId) override; + HRESULT STDMETHODCALLTYPE RuntimeThreadResumed(ThreadID threadId) override; + HRESULT STDMETHODCALLTYPE MovedReferences( + ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], + ObjectID newObjectIDRangeStart[], ULONG cObjectIDRangeLength[]) override; + HRESULT STDMETHODCALLTYPE ObjectAllocated(ObjectID objectId, + ClassID classId) override; + HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass(ULONG cClassCount, + ClassID classIds[], + ULONG cObjects[]) override; + HRESULT STDMETHODCALLTYPE ObjectReferences(ObjectID objectId, ClassID classId, + ULONG cObjectRefs, + ObjectID objectRefIds[]) override; + HRESULT STDMETHODCALLTYPE RootReferences(ULONG cRootRefs, + ObjectID rootRefIds[]) override; + HRESULT STDMETHODCALLTYPE ExceptionThrown(ObjectID thrownObjectId) override; + HRESULT STDMETHODCALLTYPE + ExceptionSearchFunctionEnter(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave() override; + HRESULT STDMETHODCALLTYPE + ExceptionSearchFilterEnter(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave() override; + HRESULT STDMETHODCALLTYPE + ExceptionSearchCatcherFound(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE ExceptionOSHandlerEnter(UINT_PTR __unused) override; + HRESULT STDMETHODCALLTYPE ExceptionOSHandlerLeave(UINT_PTR __unused) override; + HRESULT STDMETHODCALLTYPE + ExceptionUnwindFunctionEnter(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave() override; + HRESULT STDMETHODCALLTYPE + ExceptionUnwindFinallyEnter(FunctionID functionId) override; + HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave() override; + HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter(FunctionID functionId, + ObjectID objectId) override; + HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave() override; + HRESULT STDMETHODCALLTYPE COMClassicVTableCreated(ClassID wrappedClassId, + REFGUID implementedIID, + void* pVTable, + ULONG cSlots) override; + HRESULT STDMETHODCALLTYPE COMClassicVTableDestroyed(ClassID wrappedClassId, + REFGUID implementedIID, + void* pVTable) override; + HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound() override; + HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute() override; + HRESULT STDMETHODCALLTYPE ThreadNameChanged(ThreadID threadId, ULONG cchName, + WCHAR name[]) override; + HRESULT STDMETHODCALLTYPE + GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], + COR_PRF_GC_REASON reason) override; + HRESULT STDMETHODCALLTYPE SurvivingReferences( + ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], + ULONG cObjectIDRangeLength[]) override; + HRESULT STDMETHODCALLTYPE GarbageCollectionFinished() override; + HRESULT STDMETHODCALLTYPE + FinalizeableObjectQueued(DWORD finalizerFlags, ObjectID objectID) override; + HRESULT STDMETHODCALLTYPE RootReferences2(ULONG cRootRefs, + ObjectID rootRefIds[], + COR_PRF_GC_ROOT_KIND rootKinds[], + COR_PRF_GC_ROOT_FLAGS rootFlags[], + UINT_PTR rootIds[]) override; + HRESULT STDMETHODCALLTYPE HandleCreated(GCHandleID handleId, + ObjectID initialObjectId) override; + HRESULT STDMETHODCALLTYPE HandleDestroyed(GCHandleID handleId) override; + HRESULT STDMETHODCALLTYPE InitializeForAttach(IUnknown* pCorProfilerInfoUnk, + void* pvClientData, + UINT cbClientData) override; + HRESULT STDMETHODCALLTYPE ProfilerAttachComplete() override; + HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded() override; + HRESULT STDMETHODCALLTYPE ReJITCompilationStarted( + FunctionID functionId, ReJITID rejitId, BOOL fIsSafeToBlock) override; + HRESULT STDMETHODCALLTYPE + GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, + ICorProfilerFunctionControl* pFunctionControl) override; + HRESULT STDMETHODCALLTYPE + ReJITCompilationFinished(FunctionID functionId, ReJITID rejitId, + HRESULT hrStatus, BOOL fIsSafeToBlock) override; + HRESULT STDMETHODCALLTYPE ReJITError(ModuleID moduleId, mdMethodDef methodId, + FunctionID functionId, + HRESULT hrStatus) override; + HRESULT STDMETHODCALLTYPE MovedReferences2( + ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], + ObjectID newObjectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) override; + HRESULT STDMETHODCALLTYPE SurvivingReferences2( + ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], + SIZE_T cObjectIDRangeLength[]) override; + HRESULT STDMETHODCALLTYPE ConditionalWeakTableElementReferences( + ULONG cRootRefs, ObjectID keyRefIds[], ObjectID valueRefIds[], + GCHandleID rootIds[]) override; + HRESULT STDMETHODCALLTYPE GetAssemblyReferences( + const WCHAR* wszAssemblyPath, + ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) override; + HRESULT STDMETHODCALLTYPE + ModuleInMemorySymbolsUpdated(ModuleID moduleId) override; + + HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationStarted( + FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE ilHeader, + ULONG cbILHeader) override; + HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationFinished( + FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override; + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, + void** ppvObject) override { + if (riid == __uuidof(ICorProfilerCallback8) || + riid == __uuidof(ICorProfilerCallback7) || + riid == __uuidof(ICorProfilerCallback6) || + riid == __uuidof(ICorProfilerCallback5) || + riid == __uuidof(ICorProfilerCallback4) || + riid == __uuidof(ICorProfilerCallback3) || + riid == __uuidof(ICorProfilerCallback2) || + riid == __uuidof(ICorProfilerCallback) || riid == IID_IUnknown) { + *ppvObject = this; + this->AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef(void) override { + return std::atomic_fetch_add(&this->ref_count_, 1) + 1; + } + + ULONG STDMETHODCALLTYPE Release(void) override { + int count = std::atomic_fetch_sub(&this->ref_count_, 1) - 1; + + if (count <= 0) { + delete this; + } + + return count; + } +}; + +} // namespace trace + +#endif // DD_CLR_PROFILER_PROFILER_BASE_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/dd_profiler_constants.h b/src/Datadog.Trace.ClrProfiler.Native/dd_profiler_constants.h new file mode 100644 index 0000000000..f119631fdf --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/dd_profiler_constants.h @@ -0,0 +1,63 @@ +#pragma once +#include + +#include "environment_variables.h" +#include "logging.h" + +namespace trace { + + WSTRING env_vars_to_display[]{ + environment::tracing_enabled, + environment::debug_enabled, + environment::profiler_home_path, + environment::integrations_path, + environment::include_process_names, + environment::exclude_process_names, + environment::agent_host, + environment::agent_port, + environment::env, + environment::service_name, + environment::service_version, + environment::disabled_integrations, + environment::clr_disable_optimizations, + environment::domain_neutral_instrumentation, + environment::azure_app_services, + environment::azure_app_services_app_pool_id, + environment::azure_app_services_cli_telemetry_profile_value}; + + WSTRING skip_assembly_prefixes[]{ + "Datadog.Trace"_W, + "MessagePack"_W, + "Microsoft.AI"_W, + "Microsoft.ApplicationInsights"_W, + "Microsoft.Build"_W, + "Microsoft.CSharp"_W, + "Microsoft.Extensions"_W, + "Microsoft.Web.Compilation.Snapshots"_W, + "Sigil"_W, + "System.Core"_W, + "System.Console"_W, + "System.Collections"_W, + "System.ComponentModel"_W, + "System.Diagnostics"_W, + "System.Drawing"_W, + "System.EnterpriseServices"_W, + "System.IO"_W, + "System.Runtime"_W, + "System.Text"_W, + "System.Threading"_W, + "System.Xml"_W, + "Newtonsoft"_W,}; + + WSTRING skip_assemblies[]{ + "mscorlib"_W, + "netstandard"_W, + "System.Configuration"_W, + "Microsoft.AspNetCore.Razor.Language"_W, + "Microsoft.AspNetCore.Mvc.RazorPages"_W, + "Anonymously Hosted DynamicMethods Assembly"_W, + "ISymWrapper"_W}; + + WSTRING managed_profiler_full_assembly_version = "Datadog.Trace.ClrProfiler.Managed, Version=1.19.1.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"_W; + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/dllmain.cpp b/src/Datadog.Trace.ClrProfiler.Native/dllmain.cpp new file mode 100644 index 0000000000..7156ef91c8 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/dllmain.cpp @@ -0,0 +1,51 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. + +#include "dllmain.h" +#include "class_factory.h" + +const IID IID_IUnknown = {0x00000000, + 0x0000, + 0x0000, + {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; + +const IID IID_IClassFactory = { + 0x00000001, + 0x0000, + 0x0000, + {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}}; + +HINSTANCE DllHandle; + +extern "C" { +BOOL STDMETHODCALLTYPE DllMain(HMODULE hModule, DWORD ul_reason_for_call, + LPVOID lpReserved) { + DllHandle = hModule; + return TRUE; +} + +HRESULT STDMETHODCALLTYPE DllGetClassObject(REFCLSID rclsid, REFIID riid, + LPVOID* ppv) { + // {846F5F1C-F9AE-4B07-969E-05C26BC060D8} + const GUID CLSID_CorProfiler = { + 0x846f5f1c, + 0xf9ae, + 0x4b07, + {0x96, 0x9e, 0x5, 0xc2, 0x6b, 0xc0, 0x60, 0xd8}}; + + if (ppv == NULL || rclsid != CLSID_CorProfiler) { + return E_FAIL; + } + + auto factory = new ClassFactory; + + if (factory == NULL) { + return E_FAIL; + } + + return factory->QueryInterface(riid, ppv); +} + +HRESULT STDMETHODCALLTYPE DllCanUnloadNow() { return S_OK; } +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/dllmain.h b/src/Datadog.Trace.ClrProfiler.Native/dllmain.h new file mode 100644 index 0000000000..7c4dce2d6c --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/dllmain.h @@ -0,0 +1,8 @@ +#ifndef DD_CLR_PROFILER_DLLMAIN_H_ +#define DD_CLR_PROFILER_DLLMAIN_H_ + +#include "class_factory.h" + +extern HINSTANCE DllHandle; + +#endif // DD_CLR_PROFILER_DLLMAIN_H_ \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Native/environment_variables.h b/src/Datadog.Trace.ClrProfiler.Native/environment_variables.h new file mode 100644 index 0000000000..a4b2452f9a --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/environment_variables.h @@ -0,0 +1,101 @@ +#ifndef DD_CLR_PROFILER_ENVIRONMENT_VARIABLES_H_ +#define DD_CLR_PROFILER_ENVIRONMENT_VARIABLES_H_ + +#include "string.h" // NOLINT + +namespace trace { +namespace environment { + +// Sets whether the profiler is enabled. Default is true. +// Setting this to false disabled the profiler entirely. +const WSTRING tracing_enabled = "DD_TRACE_ENABLED"_W; + +// Sets whether debug mode is enabled. Default is false. +const WSTRING debug_enabled = "DD_TRACE_DEBUG"_W; + +// Sets the paths to integration definition JSON files. +// Supports multiple values separated with semi-colons, for example: +// "C:\Program Files\Datadog .NET Tracer\integrations.json;D:\temp\test_integrations.json" +const WSTRING integrations_path = "DD_INTEGRATIONS"_W; + +// Sets the path to the profiler's home directory, for example: +// "C:\Program Files\Datadog .NET Tracer\" or "/opt/datadog/" +const WSTRING profiler_home_path = "DD_DOTNET_TRACER_HOME"_W; + +// Sets the filename of executables the profiler can attach to. +// If not defined (default), the profiler will attach to any process. +// Supports multiple values separated with semi-colons, for example: +// "MyApp.exe;dotnet.exe" +const WSTRING include_process_names = "DD_PROFILER_PROCESSES"_W; + +// Sets the filename of executables the profiler cannot attach to. +// If not defined (default), the profiler will attach to any process. +// Supports multiple values separated with semi-colons, for example: +// "MyApp.exe;dotnet.exe" +const WSTRING exclude_process_names = "DD_PROFILER_EXCLUDE_PROCESSES"_W; + +// Sets the Agent's host. Default is localhost. +const WSTRING agent_host = "DD_AGENT_HOST"_W; + +// Sets the Agent's port. Default is 8126. +const WSTRING agent_port = "DD_TRACE_AGENT_PORT"_W; + +// Sets the "env" tag for every span. +const WSTRING env = "DD_ENV"_W; + +// Sets the default service name for every span. +// If not set, Tracer will try to determine service name automatically +// from application name (e.g. entry assembly or IIS application name). +const WSTRING service_name = "DD_SERVICE"_W; + +// Sets the "service_version" tag for every span that belong to the root service (and not an external service). +const WSTRING service_version = "DD_VERSION"_W; + +// Sets a list of integrations to disable. All other integrations will remain +// enabled. If not set (default), all integrations are enabled. Supports +// multiple values separated with semi-colons, for example: +// "ElasticsearchNet;AspNetWebApi2" +const WSTRING disabled_integrations = "DD_DISABLED_INTEGRATIONS"_W; + +// Sets the path for the profiler's log file. +// If not set, default is +// "%ProgramData%"\Datadog .NET Tracer\logs\dotnet-profiler.log" on Windows or +// "/var/log/datadog/dotnet/dotnet-profiler.log" on Linux. +const WSTRING log_path = "DD_TRACE_LOG_PATH"_W; + +// Sets whether to disable all JIT optimizations. +// Default value is false (do not disable all optimizations). +// https://github.com/dotnet/coreclr/issues/24676 +// https://github.com/dotnet/coreclr/issues/12468 +const WSTRING clr_disable_optimizations = "DD_CLR_DISABLE_OPTIMIZATIONS"_W; + +// Sets whether to intercept method calls when the caller method is inside a +// domain-neutral assembly. This is dangerous because the integration assembly +// Datadog.Trace.ClrProfiler.Managed.dll must also be loaded domain-neutral, +// otherwise a sharing violation (HRESULT 0x80131401) may occur. This setting should only be +// enabled when there is only one AppDomain or, when hosting applications in IIS, +// the user can guarantee that all Application Pools on the system have at most +// one application. +// Default is false. Only used in .NET Framework 4.5 and 4.5.1. +// https://github.com/DataDog/dd-trace-dotnet/pull/671 +const WSTRING domain_neutral_instrumentation = "DD_TRACE_DOMAIN_NEUTRAL_INSTRUMENTATION"_W; + +// Indicates whether the profiler is running in the context +// of Azure App Services +const WSTRING azure_app_services = "DD_AZURE_APP_SERVICES"_W; + +// The app_pool_id in the context of azure app services +const WSTRING azure_app_services_app_pool_id = "APP_POOL_ID"_W; + +// The DOTNET_CLI_TELEMETRY_PROFILE in the context of azure app services +const WSTRING azure_app_services_cli_telemetry_profile_value = + "DOTNET_CLI_TELEMETRY_PROFILE"_W; + +// Determine whether to instrument calls into netstandard.dll. +// Default to false for now to avoid the unexpected overhead of additional spans. +const WSTRING netstandard_enabled = "DD_TRACE_NETSTANDARD_ENABLED"_W; + +} // namespace environment +} // namespace trace + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.cpp b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.cpp new file mode 100644 index 0000000000..d7c235ed94 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.cpp @@ -0,0 +1,654 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. + +#include + +#include "il_rewriter.h" + +#undef IfFailRet +#define IfFailRet(EXPR) \ + do { \ + HRESULT hr = (EXPR); \ + if (FAILED(hr)) { \ + return (hr); \ + } \ + } while (0) + +#undef IfNullRet +#define IfNullRet(EXPR) \ + do { \ + if ((EXPR) == NULL) return E_OUTOFMEMORY; \ + } while (0) + +#define OPCODEFLAGS_SizeMask 0x0F +#define OPCODEFLAGS_BranchTarget 0x10 +#define OPCODEFLAGS_Switch 0x20 + +static const BYTE s_OpCodeFlags[] = { +#define InlineNone 0 +#define ShortInlineVar 1 +#define InlineVar 2 +#define ShortInlineI 1 +#define InlineI 4 +#define InlineI8 8 +#define ShortInlineR 4 +#define InlineR 8 +#define ShortInlineBrTarget 1 | OPCODEFLAGS_BranchTarget +#define InlineBrTarget 4 | OPCODEFLAGS_BranchTarget +#define InlineMethod 4 +#define InlineField 4 +#define InlineType 4 +#define InlineString 4 +#define InlineSig 4 +#define InlineRVA 4 +#define InlineTok 4 +#define InlineSwitch 0 | OPCODEFLAGS_Switch + +#define OPDEF(c, s, pop, push, args, type, l, s1, s2, flow) args, +#include "opcode.def" +#undef OPDEF + +#undef InlineNone +#undef ShortInlineVar +#undef InlineVar +#undef ShortInlineI +#undef InlineI +#undef InlineI8 +#undef ShortInlineR +#undef InlineR +#undef ShortInlineBrTarget +#undef InlineBrTarget +#undef InlineMethod +#undef InlineField +#undef InlineType +#undef InlineString +#undef InlineSig +#undef InlineRVA +#undef InlineTok +#undef InlineSwitch + 0, + // CEE_COUNT + 4 | OPCODEFLAGS_BranchTarget, + // CEE_SWITCH_ARG +}; + +static int k_rgnStackPushes[] = { + +#define OPDEF(c, s, pop, push, args, type, l, s1, s2, ctrl) push, + +#define Push0 0 +#define Push1 1 +#define PushI 1 +#define PushI4 1 +#define PushR4 1 +#define PushI8 1 +#define PushR8 1 +#define PushRef 1 +#define VarPush \ + 1 // Test code doesn't call vararg fcns, so this should not be used + +#include "opcode.def" + +#undef Push0 +#undef Push1 +#undef PushI +#undef PushI4 +#undef PushR4 +#undef PushI8 +#undef PushR8 +#undef PushRef +#undef VarPush +#undef OPDEF +}; + +ILRewriter::ILRewriter( + ICorProfilerInfo* pICorProfilerInfo, + ICorProfilerFunctionControl* pICorProfilerFunctionControl, + ModuleID moduleID, mdToken tkMethod) + : m_pICorProfilerInfo(pICorProfilerInfo), + m_pICorProfilerFunctionControl(pICorProfilerFunctionControl), + m_moduleId(moduleID), + m_tkMethod(tkMethod), + m_fGenerateTinyHeader(false), + m_pEH(nullptr), + m_pOffsetToInstr(nullptr), + m_pOutputBuffer(nullptr), + m_pIMethodMalloc(nullptr) { + m_IL.m_pNext = &m_IL; + m_IL.m_pPrev = &m_IL; + + m_nInstrs = 0; +} + +ILRewriter::~ILRewriter() { + ILInstr* p = m_IL.m_pNext; + while (p != &m_IL) { + ILInstr* t = p->m_pNext; + delete p; + p = t; + } + delete[] m_pEH; + delete[] m_pOffsetToInstr; + delete[] m_pOutputBuffer; + + if (m_pIMethodMalloc) { + m_pIMethodMalloc->Release(); + } +} + +void ILRewriter::InitializeTiny() { + m_tkLocalVarSig = 0; + m_maxStack = 8; + m_flags = CorILMethod_TinyFormat; + m_CodeSize = 0; + m_nEH = 0; + m_fGenerateTinyHeader = true; +} + +void ILRewriter::SetTkLocalVarSig(mdToken tkLocalVarSig) { + m_tkLocalVarSig = tkLocalVarSig; + m_fGenerateTinyHeader = false; +} + +HRESULT ILRewriter::Import() { + LPCBYTE pMethodBytes; + + IfFailRet(m_pICorProfilerInfo->GetILFunctionBody(m_moduleId, m_tkMethod, + &pMethodBytes, nullptr)); + + COR_ILMETHOD_DECODER decoder((COR_ILMETHOD*)pMethodBytes); + + // Import the header flags + m_tkLocalVarSig = decoder.GetLocalVarSigTok(); + m_maxStack = decoder.GetMaxStack(); + m_flags = (decoder.GetFlags() & CorILMethod_InitLocals); + + m_CodeSize = decoder.GetCodeSize(); + + IfFailRet(ImportIL(decoder.Code)); + + IfFailRet(ImportEH(decoder.EH, decoder.EHCount())); + + return S_OK; +} + +HRESULT ILRewriter::ImportIL(LPCBYTE pIL) { + m_pOffsetToInstr = new ILInstr*[m_CodeSize + 1]; + IfNullRet(m_pOffsetToInstr); + + ZeroMemory(m_pOffsetToInstr, m_CodeSize * sizeof(ILInstr*)); + + // Set the sentinel instruction + m_pOffsetToInstr[m_CodeSize] = &m_IL; + m_IL.m_opcode = -1; + + bool fBranch = false; + unsigned offset = 0; + while (offset < m_CodeSize) { + unsigned startOffset = offset; + unsigned opcode = pIL[offset++]; + + if (opcode == CEE_PREFIX1) { + if (offset >= m_CodeSize) { + return COR_E_INVALIDPROGRAM; + } + opcode = 0x100 + pIL[offset++]; + } + + if ((CEE_PREFIX7 <= opcode) && (opcode <= CEE_PREFIX2)) { + // NOTE: CEE_PREFIX2-7 are currently not supported + return COR_E_INVALIDPROGRAM; + } + + if (opcode >= CEE_COUNT) { + return COR_E_INVALIDPROGRAM; + } + + BYTE flags = s_OpCodeFlags[opcode]; + + int size = (flags & OPCODEFLAGS_SizeMask); + if (offset + size > m_CodeSize) { + return COR_E_INVALIDPROGRAM; + } + + ILInstr* pInstr = NewILInstr(); + IfNullRet(pInstr); + + pInstr->m_opcode = opcode; + + InsertBefore(&m_IL, pInstr); + + m_pOffsetToInstr[startOffset] = pInstr; + + switch (flags) { + case 0: + break; + case 1: + pInstr->m_Arg8 = *(UNALIGNED INT8*)&(pIL[offset]); + break; + case 2: + pInstr->m_Arg16 = *(UNALIGNED INT16*)&(pIL[offset]); + break; + case 4: + pInstr->m_Arg32 = *(UNALIGNED INT32*)&(pIL[offset]); + break; + case 8: + pInstr->m_Arg64 = *(UNALIGNED INT64*)&(pIL[offset]); + break; + case 1 | OPCODEFLAGS_BranchTarget: + pInstr->m_Arg32 = offset + 1 + *(UNALIGNED INT8*)&(pIL[offset]); + fBranch = true; + break; + case 4 | OPCODEFLAGS_BranchTarget: + pInstr->m_Arg32 = offset + 4 + *(UNALIGNED INT32*)&(pIL[offset]); + fBranch = true; + break; + case 0 | OPCODEFLAGS_Switch: { + if (offset + sizeof(INT32) > m_CodeSize) { + return COR_E_INVALIDPROGRAM; + } + + unsigned nTargets = *(UNALIGNED INT32*)&(pIL[offset]); + pInstr->m_Arg32 = nTargets; + offset += sizeof(INT32); + + unsigned base = offset + nTargets * sizeof(INT32); + + for (unsigned iTarget = 0; iTarget < nTargets; iTarget++) { + if (offset + sizeof(INT32) > m_CodeSize) { + return COR_E_INVALIDPROGRAM; + } + + pInstr = NewILInstr(); + IfNullRet(pInstr); + + pInstr->m_opcode = CEE_SWITCH_ARG; + + pInstr->m_Arg32 = base + *(UNALIGNED INT32*)&(pIL[offset]); + offset += sizeof(INT32); + + InsertBefore(&m_IL, pInstr); + } + fBranch = true; + break; + } + default: + return COR_E_INVALIDPROGRAM; + } + offset += size; + } + + if (offset != m_CodeSize) { + return COR_E_INVALIDPROGRAM; + } + + if (fBranch) { + // Go over all control flow instructions and resolve the targets + for (ILInstr* pInstr = m_IL.m_pNext; pInstr != &m_IL; + pInstr = pInstr->m_pNext) { + if (s_OpCodeFlags[pInstr->m_opcode] & OPCODEFLAGS_BranchTarget) { + IfFailRet(GetInstrFromOffset(pInstr->m_Arg32, &pInstr->m_pTarget)); + } + } + } + + return S_OK; +} + +HRESULT ILRewriter::ImportEH(const COR_ILMETHOD_SECT_EH* pILEH, unsigned nEH) { + if(m_pEH != nullptr) + { + return COR_E_INVALIDOPERATION; + } + + m_nEH = nEH; + + if (nEH == 0) return S_OK; + + IfNullRet(m_pEH = new EHClause[m_nEH]); + for (unsigned iEH = 0; iEH < m_nEH; iEH++) { + // If the EH clause is in tiny form, the call to pILEH->EHClause() below + // will use this as a scratch buffer to expand the EH clause into its fat + // form. + COR_ILMETHOD_SECT_EH_CLAUSE_FAT scratch; + + const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo; + ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)pILEH->EHClause(iEH, &scratch); + + EHClause* clause = &(m_pEH[iEH]); + clause->m_Flags = ehInfo->GetFlags(); + ILInstr* pInstr = nullptr; + + IfFailRet(GetInstrFromOffset(ehInfo->GetTryOffset(), &pInstr)); + clause->m_pTryBegin = pInstr; + + IfFailRet(GetInstrFromOffset(ehInfo->GetTryOffset() + ehInfo->GetTryLength(), &pInstr)); + clause->m_pTryEnd = pInstr; + + IfFailRet(GetInstrFromOffset(ehInfo->GetHandlerOffset(), &pInstr)); + clause->m_pHandlerBegin = pInstr; + + IfFailRet(GetInstrFromOffset(ehInfo->GetHandlerOffset() + ehInfo->GetHandlerLength(), &pInstr)); + clause->m_pHandlerEnd = pInstr->m_pPrev; + + if ((clause->m_Flags & COR_ILEXCEPTION_CLAUSE_FILTER) == 0) { + clause->m_ClassToken = ehInfo->GetClassToken(); + } else { + IfFailRet(GetInstrFromOffset(ehInfo->GetFilterOffset(), &pInstr)); + clause->m_pFilter = pInstr; + } + } + + return S_OK; +} + +ILInstr* ILRewriter::NewILInstr() { + m_nInstrs++; + return new ILInstr(); +} + +HRESULT ILRewriter::GetInstrFromOffset(unsigned offset, ILInstr** ppInstr) { + if (offset <= m_CodeSize) { + ILInstr* result = m_pOffsetToInstr[offset]; + + if(result != nullptr) { + *ppInstr = result; + return S_OK; + } + } + + return COR_E_INVALIDPROGRAM; +} + +void ILRewriter::InsertBefore(ILInstr* pWhere, ILInstr* pWhat) { + pWhat->m_pNext = pWhere; + pWhat->m_pPrev = pWhere->m_pPrev; + + pWhat->m_pNext->m_pPrev = pWhat; + pWhat->m_pPrev->m_pNext = pWhat; + + AdjustState(pWhat); +} + +void ILRewriter::InsertAfter(ILInstr* pWhere, ILInstr* pWhat) { + pWhat->m_pNext = pWhere->m_pNext; + pWhat->m_pPrev = pWhere; + + pWhat->m_pNext->m_pPrev = pWhat; + pWhat->m_pPrev->m_pNext = pWhat; + + AdjustState(pWhat); +} + +void ILRewriter::AdjustState(ILInstr* pNewInstr) { + m_maxStack += k_rgnStackPushes[pNewInstr->m_opcode]; +} + +ILInstr* ILRewriter::GetILList() { return &m_IL; } + +HRESULT ILRewriter::Export() { + // One instruction produces 2 + sizeof(native int) bytes in the worst case + // which can be 10 bytes for 64-bit. For simplification we just use 10 here. + unsigned maxSize = m_nInstrs * 10; + + m_pOutputBuffer = new BYTE[maxSize]; + IfNullRet(m_pOutputBuffer); + +again: + BYTE* pIL = m_pOutputBuffer; + + bool fBranch = false; + unsigned offset = 0; + + // Go over all instructions and produce code for them + for (ILInstr* pInstr = m_IL.m_pNext; pInstr != &m_IL; + pInstr = pInstr->m_pNext) { + + if(offset >= maxSize) + { + return COR_E_INDEXOUTOFRANGE; + } + + pInstr->m_offset = offset; + + unsigned opcode = pInstr->m_opcode; + if (opcode < CEE_COUNT) { + // CEE_PREFIX1 refers not to instruction prefixes (like tail.), but to + // the lead byte of multi-byte opcodes. For now, the only lead byte + // supported is CEE_PREFIX1 = 0xFE. + if (opcode >= 0x100) m_pOutputBuffer[offset++] = CEE_PREFIX1; + + // This appears to depend on an implicit conversion from + // unsigned opcode down to BYTE, to deliberately lose data and have + // opcode >= 0x100 wrap around to 0. + m_pOutputBuffer[offset++] = (opcode & 0xFF); + } + + if (pInstr->m_opcode >= (sizeof(s_OpCodeFlags) / sizeof(BYTE))) + { + return COR_E_INVALIDPROGRAM; + } + + BYTE flags = s_OpCodeFlags[pInstr->m_opcode]; + switch (flags) { + case 0: + break; + case 1: + *(UNALIGNED INT8*)&(pIL[offset]) = pInstr->m_Arg8; + break; + case 2: + *(UNALIGNED INT16*)&(pIL[offset]) = pInstr->m_Arg16; + break; + case 4: + *(UNALIGNED INT32*)&(pIL[offset]) = pInstr->m_Arg32; + break; + case 8: + *(UNALIGNED INT64*)&(pIL[offset]) = pInstr->m_Arg64; + break; + case 1 | OPCODEFLAGS_BranchTarget: + fBranch = true; + break; + case 4 | OPCODEFLAGS_BranchTarget: + fBranch = true; + break; + case 0 | OPCODEFLAGS_Switch: + *(UNALIGNED INT32*)&(pIL[offset]) = pInstr->m_Arg32; + offset += sizeof(INT32); + break; + default: + return COR_E_INVALIDPROGRAM; + } + offset += (flags & OPCODEFLAGS_SizeMask); + } + m_IL.m_offset = offset; + + if (fBranch) { + bool fTryAgain = false; + unsigned switchBase = 0; + + // Go over all control flow instructions and resolve the targets + for (ILInstr* pInstr = m_IL.m_pNext; pInstr != &m_IL; + pInstr = pInstr->m_pNext) { + unsigned opcode = pInstr->m_opcode; + + if (pInstr->m_opcode == CEE_SWITCH) { + switchBase = + pInstr->m_offset + 1 + sizeof(INT32) * (pInstr->m_Arg32 + 1); + continue; + } + if (opcode == CEE_SWITCH_ARG) { + // Switch args are special + *(UNALIGNED INT32*)&(pIL[pInstr->m_offset]) = + pInstr->m_pTarget->m_offset - switchBase; + continue; + } + + BYTE flags = s_OpCodeFlags[pInstr->m_opcode]; + + if (flags & OPCODEFLAGS_BranchTarget) { + int delta = pInstr->m_pTarget->m_offset - pInstr->m_pNext->m_offset; + + switch (flags) { + case 1 | OPCODEFLAGS_BranchTarget: + // Check if delta is too big to fit into an INT8. + // + // (see #pragma at top of file) + if ((INT8)delta != delta) { + if (opcode == CEE_LEAVE_S) { + pInstr->m_opcode = CEE_LEAVE; + } else { + if(!(opcode >= CEE_BR_S && opcode <= CEE_BLT_UN_S)) + { + return COR_E_INVALIDPROGRAM; + } + + pInstr->m_opcode = opcode - CEE_BR_S + CEE_BR; + + if(!(pInstr->m_opcode >= CEE_BR && pInstr->m_opcode <= CEE_BLT_UN)) + { + return COR_E_INVALIDPROGRAM; + } + } + fTryAgain = true; + continue; + } + *(UNALIGNED INT8*)&(pIL[pInstr->m_pNext->m_offset - sizeof(INT8)]) = + delta; + break; + case 4 | OPCODEFLAGS_BranchTarget: + *(UNALIGNED INT32*)&( + pIL[pInstr->m_pNext->m_offset - sizeof(INT32)]) = delta; + break; + default: + return COR_E_INVALIDPROGRAM; + } + } + } + + // Do the whole thing again if we changed the size of some branch targets + if (fTryAgain) goto again; + } + + unsigned codeSize = offset; + unsigned totalSize; + LPBYTE pBody = NULL; + if (m_fGenerateTinyHeader) { + // Make sure we can fit in a tiny header + if (codeSize >= 64) return E_FAIL; + + totalSize = sizeof(IMAGE_COR_ILMETHOD_TINY) + codeSize; + pBody = AllocateILMemory(totalSize); + IfNullRet(pBody); + + BYTE* pCurrent = pBody; + + // Here's the tiny header + *pCurrent = (BYTE)(CorILMethod_TinyFormat | (codeSize << 2)); + pCurrent += sizeof(IMAGE_COR_ILMETHOD_TINY); + + // And the body + CopyMemory(pCurrent, m_pOutputBuffer, codeSize); + } else { + // Use FAT header + + unsigned alignedCodeSize = (offset + 3) & ~3; + + totalSize = sizeof(IMAGE_COR_ILMETHOD_FAT) + alignedCodeSize + + (m_nEH ? (sizeof(IMAGE_COR_ILMETHOD_SECT_FAT) + + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * m_nEH) + : 0); + + pBody = AllocateILMemory(totalSize); + IfNullRet(pBody); + + BYTE* pCurrent = pBody; + + IMAGE_COR_ILMETHOD_FAT* pHeader = (IMAGE_COR_ILMETHOD_FAT*)pCurrent; + pHeader->Flags = + m_flags | (m_nEH ? CorILMethod_MoreSects : 0) | CorILMethod_FatFormat; + pHeader->Size = sizeof(IMAGE_COR_ILMETHOD_FAT) / sizeof(DWORD); + pHeader->MaxStack = m_maxStack; + pHeader->CodeSize = offset; + pHeader->LocalVarSigTok = m_tkLocalVarSig; + + pCurrent = (BYTE*)(pHeader + 1); + + CopyMemory(pCurrent, m_pOutputBuffer, codeSize); + pCurrent += alignedCodeSize; + + if (m_nEH != 0) { + IMAGE_COR_ILMETHOD_SECT_FAT* pEH = (IMAGE_COR_ILMETHOD_SECT_FAT*)pCurrent; + pEH->Kind = CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat; + pEH->DataSize = + (unsigned)(sizeof(IMAGE_COR_ILMETHOD_SECT_FAT) + + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * m_nEH); + + pCurrent = (BYTE*)(pEH + 1); + + for (unsigned iEH = 0; iEH < m_nEH; iEH++) { + EHClause* pSrc = &(m_pEH[iEH]); + IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* pDst = + (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)pCurrent; + + pDst->Flags = pSrc->m_Flags; + pDst->TryOffset = pSrc->m_pTryBegin->m_offset; + pDst->TryLength = + pSrc->m_pTryEnd->m_offset - pSrc->m_pTryBegin->m_offset; + pDst->HandlerOffset = pSrc->m_pHandlerBegin->m_offset; + pDst->HandlerLength = pSrc->m_pHandlerEnd->m_pNext->m_offset - + pSrc->m_pHandlerBegin->m_offset; + if ((pSrc->m_Flags & COR_ILEXCEPTION_CLAUSE_FILTER) == 0) + pDst->ClassToken = pSrc->m_ClassToken; + else + pDst->FilterOffset = pSrc->m_pFilter->m_offset; + + pCurrent = (BYTE*)(pDst + 1); + } + } + } + + IfFailRet(SetILFunctionBody(totalSize, pBody)); + DeallocateILMemory(pBody); + + return S_OK; +} + +HRESULT ILRewriter::SetILFunctionBody(unsigned size, LPBYTE pBody) { + if (m_pICorProfilerFunctionControl != nullptr) { + // We're supplying IL for a rejit, so use the rejit mechanism + IfFailRet(m_pICorProfilerFunctionControl->SetILFunctionBody(size, pBody)); + } else { + // "classic-style" instrumentation on first JIT, so use old mechanism + IfFailRet( + m_pICorProfilerInfo->SetILFunctionBody(m_moduleId, m_tkMethod, pBody)); + } + + return S_OK; +} + +LPBYTE ILRewriter::AllocateILMemory(unsigned size) { + if (m_pICorProfilerFunctionControl != nullptr) { + // We're supplying IL for a rejit, so we can just allocate from + // the heap + return new BYTE[size]; + } + + // Else, this is "classic-style" instrumentation on first JIT, and + // need to use the CLR's IL allocator + + if (FAILED(m_pICorProfilerInfo->GetILFunctionBodyAllocator( + m_moduleId, &m_pIMethodMalloc))) + return nullptr; + + return (LPBYTE)m_pIMethodMalloc->Alloc(size); +} + +void ILRewriter::DeallocateILMemory(LPBYTE pBody) { + if (m_pICorProfilerFunctionControl == nullptr) { + // Old-style instrumentation does not provide a way to free up bytes + return; + } + + delete[] pBody; +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.h b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.h new file mode 100644 index 0000000000..52a1964738 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter.h @@ -0,0 +1,130 @@ +#ifndef DD_CLR_PROFILER_IL_REWRITER_H_ +#define DD_CLR_PROFILER_IL_REWRITER_H_ + +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full +// license information. + +#include +#include + +typedef enum { +#define OPDEF(c, s, pop, push, args, type, l, s1, s2, ctrl) c, +#include "opcode.def" +#undef OPDEF + CEE_COUNT, + CEE_SWITCH_ARG, + // special internal instructions +} OPCODE; + +struct ILInstr { + ILInstr* m_pNext; + ILInstr* m_pPrev; + + unsigned m_opcode; + unsigned m_offset; + + union { + ILInstr* m_pTarget; + INT8 m_Arg8; + INT16 m_Arg16; + INT32 m_Arg32; + INT64 m_Arg64; + }; +}; + +struct EHClause { + CorExceptionFlag m_Flags; + ILInstr* m_pTryBegin; + ILInstr* m_pTryEnd; + ILInstr* m_pHandlerBegin; // First instruction inside the handler + ILInstr* m_pHandlerEnd; // Last instruction inside the handler + union { + DWORD m_ClassToken; // use for type-based exception handlers + ILInstr* m_pFilter; // use for filter-based exception handlers + // (COR_ILEXCEPTION_CLAUSE_FILTER is set) + }; +}; + +class ILRewriter { + private: + ICorProfilerInfo* m_pICorProfilerInfo; + ICorProfilerFunctionControl* m_pICorProfilerFunctionControl; + + ModuleID m_moduleId; + mdToken m_tkMethod; + + mdToken m_tkLocalVarSig; + unsigned m_maxStack; + unsigned m_flags; + bool m_fGenerateTinyHeader; + + ILInstr m_IL; // Double linked list of all il instructions + + unsigned m_nEH; + EHClause* m_pEH; + + // Helper table for importing. Sparse array that maps BYTE offset of + // beginning of an instruction to that instruction's ILInstr*. BYTE offsets + // that don't correspond to the beginning of an instruction are mapped to + // NULL. + ILInstr** m_pOffsetToInstr; + unsigned m_CodeSize; + + unsigned m_nInstrs; + + BYTE* m_pOutputBuffer; + + IMethodMalloc* m_pIMethodMalloc; + + public: + ILRewriter(ICorProfilerInfo* pICorProfilerInfo, + ICorProfilerFunctionControl* pICorProfilerFunctionControl, + ModuleID moduleID, mdToken tkMethod); + + ~ILRewriter(); + + void InitializeTiny(); + + void SetTkLocalVarSig(mdToken tkLocalVarSig); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // I M P O R T + // + //////////////////////////////////////////////////////////////////////////////////////////////// + + HRESULT Import(); + + HRESULT ImportIL(LPCBYTE pIL); + + HRESULT ImportEH(const COR_ILMETHOD_SECT_EH* pILEH, unsigned nEH); + + ILInstr* NewILInstr(); + + HRESULT GetInstrFromOffset(unsigned offset, ILInstr** ppInstr); + + void InsertBefore(ILInstr* pWhere, ILInstr* pWhat); + + void InsertAfter(ILInstr* pWhere, ILInstr* pWhat); + + void AdjustState(ILInstr* pNewInstr); + + ILInstr* GetILList(); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // + // E X P O R T + // + //////////////////////////////////////////////////////////////////////////////////////////////// + + HRESULT Export(); + + HRESULT SetILFunctionBody(unsigned size, LPBYTE pBody); + + LPBYTE AllocateILMemory(unsigned size); + + void DeallocateILMemory(LPBYTE pBody); +}; + +#endif // DD_CLR_PROFILER_IL_REWRITER_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.cpp b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.cpp new file mode 100644 index 0000000000..f62cedd071 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.cpp @@ -0,0 +1,156 @@ +#include "il_rewriter_wrapper.h" + +ILRewriter* ILRewriterWrapper::GetILRewriter() const { return m_ILRewriter; } + +void ILRewriterWrapper::SetILPosition(ILInstr* pILInstr) { + m_ILInstr = pILInstr; +} + +void ILRewriterWrapper::Pop() const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_POP; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::LoadNull() const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_LDNULL; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::LoadInt64(const INT64 value) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_LDC_I8; + pNewInstr->m_Arg64 = value; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::LoadInt32(const INT32 value) const { + static const std::vector opcodes = { + CEE_LDC_I4_0, CEE_LDC_I4_1, CEE_LDC_I4_2, CEE_LDC_I4_3, CEE_LDC_I4_4, + CEE_LDC_I4_5, CEE_LDC_I4_6, CEE_LDC_I4_7, CEE_LDC_I4_8, + }; + + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + + if (value >= 0 && value <= 8) { + pNewInstr->m_opcode = opcodes[value]; + } else if (-128 <= value && value <= 127) { + pNewInstr->m_opcode = CEE_LDC_I4_S; + pNewInstr->m_Arg8 = static_cast(value); + } else { + pNewInstr->m_opcode = CEE_LDC_I4; + pNewInstr->m_Arg32 = value; + } + + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::LoadArgument(const UINT16 index) const { + static const std::vector opcodes = { + CEE_LDARG_0, + CEE_LDARG_1, + CEE_LDARG_2, + CEE_LDARG_3, + }; + + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + + if (index >= 0 && index <= 3) { + pNewInstr->m_opcode = opcodes[index]; + } else if (index <= 255) { + pNewInstr->m_opcode = CEE_LDARG_S; + pNewInstr->m_Arg8 = static_cast(index); + } else { + pNewInstr->m_opcode = CEE_LDARG; + pNewInstr->m_Arg16 = index; + } + + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::Cast(const mdTypeRef type_ref) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_CASTCLASS; + pNewInstr->m_Arg32 = type_ref; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::Box(const mdTypeRef type_ref) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_BOX; + pNewInstr->m_Arg32 = type_ref; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::UnboxAny(const mdTypeRef type_ref) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_UNBOX_ANY; + pNewInstr->m_Arg32 = type_ref; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::UnboxAnyAfter(const mdTypeRef type_ref) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_UNBOX_ANY; + pNewInstr->m_Arg32 = type_ref; + m_ILRewriter->InsertAfter(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::CreateArray(const mdTypeRef type_ref, + const INT32 size) const { + mdTypeRef typeRef = mdTypeRefNil; + LoadInt32(size); + + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_NEWARR; + pNewInstr->m_Arg32 = type_ref; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::CallMember(const mdMemberRef& member_ref, + const bool is_virtual) const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = is_virtual ? CEE_CALLVIRT : CEE_CALL; + pNewInstr->m_Arg32 = member_ref; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::Duplicate() const { + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_DUP; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +void ILRewriterWrapper::BeginLoadValueIntoArray(const INT32 arrayIndex) const { + // duplicate the array reference + Duplicate(); + + // load the specified array index + LoadInt32(arrayIndex); +} + +void ILRewriterWrapper::EndLoadValueIntoArray() const { + // stelem.ref (store value into array at the specified index) + ILInstr* pNewInstr = m_ILRewriter->NewILInstr(); + pNewInstr->m_opcode = CEE_STELEM_REF; + m_ILRewriter->InsertBefore(m_ILInstr, pNewInstr); +} + +bool ILRewriterWrapper::ReplaceMethodCalls( + const mdMemberRef old_method_ref, const mdMemberRef new_method_ref) const { + bool modified = false; + + for (ILInstr* pInstr = m_ILRewriter->GetILList()->m_pNext; + pInstr != m_ILRewriter->GetILList(); pInstr = pInstr->m_pNext) { + if ((pInstr->m_opcode == CEE_CALL || pInstr->m_opcode == CEE_CALLVIRT) && + pInstr->m_Arg32 == static_cast(old_method_ref)) { + pInstr->m_opcode = CEE_CALL; + pInstr->m_Arg32 = new_method_ref; + + modified = true; + } + } + + return modified; +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.h b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.h new file mode 100644 index 0000000000..5525b2029d --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/il_rewriter_wrapper.h @@ -0,0 +1,36 @@ +#ifndef DD_CLR_PROFILER_IL_REWRITER_WRAPPER_H_ +#define DD_CLR_PROFILER_IL_REWRITER_WRAPPER_H_ + +#include "il_rewriter.h" +#include "module_metadata.h" + +class ILRewriterWrapper { + private: + ILRewriter* const m_ILRewriter; + ILInstr* m_ILInstr; + + public: + ILRewriterWrapper(ILRewriter* const il_rewriter) + : m_ILRewriter(il_rewriter), m_ILInstr(nullptr) {} + + ILRewriter* GetILRewriter() const; + void SetILPosition(ILInstr* pILInstr); + void Pop() const; + void LoadNull() const; + void LoadInt64(INT64 value) const; + void LoadInt32(INT32 value) const; + void LoadArgument(UINT16 index) const; + void Cast(mdTypeRef type_ref) const; + void Box(mdTypeRef type_ref) const; + void UnboxAny(mdTypeRef type_ref) const; + void UnboxAnyAfter(mdTypeRef type_ref) const; + void CreateArray(mdTypeRef type_ref, INT32 size) const; + void CallMember(const mdMemberRef& member_ref, bool is_virtual) const; + void Duplicate() const; + void BeginLoadValueIntoArray(INT32 arrayIndex) const; + void EndLoadValueIntoArray() const; + bool ReplaceMethodCalls(mdMemberRef old_method_ref, + mdMemberRef new_method_ref) const; +}; + +#endif // DD_CLR_PROFILER_IL_REWRITER_WRAPPER_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/integration.cpp b/src/Datadog.Trace.ClrProfiler.Native/integration.cpp new file mode 100644 index 0000000000..eba8dd3428 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/integration.cpp @@ -0,0 +1,131 @@ + +#include "integration.h" + +#ifdef _WIN32 +#include +#else +#include +#endif +#include + +#include "util.h" + +namespace trace { + +AssemblyReference::AssemblyReference(const WSTRING& str) + : name(GetNameFromAssemblyReferenceString(str)), + version(GetVersionFromAssemblyReferenceString(str)), + locale(GetLocaleFromAssemblyReferenceString(str)), + public_key(GetPublicKeyFromAssemblyReferenceString(str)) {} + +namespace { + +WSTRING GetNameFromAssemblyReferenceString(const WSTRING& wstr) { + WSTRING name = wstr; + + auto pos = name.find(','_W); + if (pos != WSTRING::npos) { + name = name.substr(0, pos); + } + + // strip spaces + pos = name.rfind(' '_W); + if (pos != WSTRING::npos) { + name = name.substr(0, pos); + } + + return name; +} + +Version GetVersionFromAssemblyReferenceString(const WSTRING& str) { + unsigned short major = 0; + unsigned short minor = 0; + unsigned short build = 0; + unsigned short revision = 0; + +#ifdef _WIN32 + + static auto re = + std::wregex("Version=([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)"_W); + + std::wsmatch match; + if (std::regex_search(str, match, re) && match.size() == 5) { + WSTRINGSTREAM(match.str(1)) >> major; + WSTRINGSTREAM(match.str(2)) >> minor; + WSTRINGSTREAM(match.str(3)) >> build; + WSTRINGSTREAM(match.str(4)) >> revision; + } + +#else + + static re2::RE2 re("Version=([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)", + RE2::Quiet); + re2::RE2::FullMatch(ToString(str), re, &major, &minor, &build, &revision); + +#endif + + return {major, minor, build, revision}; +} + +WSTRING GetLocaleFromAssemblyReferenceString(const WSTRING& str) { + WSTRING locale = "neutral"_W; + +#ifdef _WIN32 + + static auto re = std::wregex("Culture=([a-zA-Z0-9]+)"_W); + std::wsmatch match; + if (std::regex_search(str, match, re) && match.size() == 2) { + locale = match.str(1); + } + +#else + + static re2::RE2 re("Culture=([a-zA-Z0-9]+)", RE2::Quiet); + + std::string match; + if (re2::RE2::FullMatch(ToString(str), re, &match)) { + locale = ToWSTRING(match); + } + +#endif + + return locale; +} + +PublicKey GetPublicKeyFromAssemblyReferenceString(const WSTRING& str) { + BYTE data[8] = {0}; + +#ifdef _WIN32 + + static auto re = std::wregex("PublicKeyToken=([a-fA-F0-9]{16})"_W); + std::wsmatch match; + if (std::regex_search(str, match, re) && match.size() == 2) { + for (int i = 0; i < 8; i++) { + auto s = match.str(1).substr(i * 2, 2); + unsigned long x; + WSTRINGSTREAM(s) >> std::hex >> x; + data[i] = BYTE(x); + } + } + +#else + + static re2::RE2 re("PublicKeyToken=([a-fA-F0-9]{16})"); + std::string match; + if (re2::RE2::FullMatch(ToString(str), re, &match)) { + for (int i = 0; i < 8; i++) { + auto s = match.substr(i * 2, 2); + unsigned long x; + std::stringstream(s) >> std::hex >> x; + data[i] = BYTE(x); + } + } + +#endif + + return PublicKey(data); +} + +} // namespace + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/integration.h b/src/Datadog.Trace.ClrProfiler.Native/integration.h new file mode 100644 index 0000000000..a37e685c70 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/integration.h @@ -0,0 +1,306 @@ +#ifndef DD_CLR_PROFILER_INTEGRATION_H_ +#define DD_CLR_PROFILER_INTEGRATION_H_ + +#include +#include +#include +#include + +#include "string.h" + +#undef major +#undef minor + +namespace trace { + +const size_t kPublicKeySize = 8; + +// PublicKey represents an Assembly Public Key token, which is an 8 byte binary +// RSA key. +struct PublicKey { + const BYTE data[kPublicKeySize]; + + PublicKey() : data{0} {} + PublicKey(const BYTE (&arr)[kPublicKeySize]) + : data{arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7]} {} + + inline bool operator==(const PublicKey& other) const { + for (int i = 0; i < kPublicKeySize; i++) { + if (data[i] != other.data[i]) { + return false; + } + } + return true; + } + + inline WSTRING str() const { + std::stringstream ss; + for (int i = 0; i < kPublicKeySize; i++) { + ss << std::setfill('0') << std::setw(2) << std::hex + << static_cast(data[i]); + } + return ToWSTRING(ss.str()); + } +}; + +// Version is an Assembly version in the form Major.Minor.Build.Revision +// (1.0.0.0) +struct Version { + const unsigned short major; + const unsigned short minor; + const unsigned short build; + const unsigned short revision; + + Version() : major(0), minor(0), build(0), revision(0) {} + Version(const unsigned short major, const unsigned short minor, + const unsigned short build, const unsigned short revision) + : major(major), minor(minor), build(build), revision(revision) {} + + inline bool operator==(const Version& other) const { + return major == other.major && minor == other.minor && + build == other.build && revision == other.revision; + } + + inline WSTRING str() const { + WSTRINGSTREAM ss; + ss << major << "."_W << minor << "."_W << build << "."_W << revision; + return ss.str(); + } + + inline bool operator<(const Version& other) const { + if (major < other.major) { + return true; + } + if (major == other.major && minor < other.minor) { + return true; + } + if (major == other.major && minor == other.minor && build < other.build) { + return true; + } + return false; + } + + inline bool operator>(const Version& other) const { + if (major > other.major) { + return true; + } + if (major == other.major && minor > other.minor) { + return true; + } + if (major == other.major && minor == other.minor && build > other.build) { + return true; + } + return false; + } +}; + +// An AssemblyReference is a reference to a .Net assembly. In general it will +// look like: +// Some.Assembly.Name, Version=1.0.0.0, Culture=neutral, +// PublicKeyToken=abcdef0123456789 +struct AssemblyReference { + const WSTRING name; + const Version version; + const WSTRING locale; + const PublicKey public_key; + + AssemblyReference() {} + AssemblyReference(const WSTRING& str); + + inline bool operator==(const AssemblyReference& other) const { + return name == other.name && version == other.version && + locale == other.locale && public_key == other.public_key; + } + + inline WSTRING str() const { + WSTRINGSTREAM ss; + ss << name << ", Version="_W << version.str() << ", Culture="_W << locale + << ", PublicKeyToken="_W << public_key.str(); + return ss.str(); + } +}; + +// A MethodSignature is a byte array. The format is: +// [calling convention, number of parameters, return type, parameter type...] +// For types see CorElementType +struct MethodSignature { + public: + const std::vector data; + + MethodSignature() {} + MethodSignature(const std::vector& data) : data(data) {} + + inline bool operator==(const MethodSignature& other) const { + return data == other.data; + } + + CorCallingConvention CallingConvention() const { + return CorCallingConvention(data.empty() ? 0 : data[0]); + } + + size_t NumberOfTypeArguments() const { + if (data.size() > 1 && + (CallingConvention() & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0) { + return data[1]; + } + return 0; + } + + size_t NumberOfArguments() const { + if (data.size() > 2 && + (CallingConvention() & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0) { + return data[2]; + } + if (data.size() > 1) { + return data[1]; + } + return 0; + } + + bool ReturnTypeIsObject() const { + if (data.size() > 2 && + (CallingConvention() & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0) { + return data[3] == ELEMENT_TYPE_OBJECT; + } + if (data.size() > 1) { + return data[2] == ELEMENT_TYPE_OBJECT; + } + + return false; + } + + size_t IndexOfReturnType() const { + if (data.size() > 2 && + (CallingConvention() & IMAGE_CEE_CS_CALLCONV_GENERIC) != 0) { + return 3; + } + if (data.size() > 1) { + return 2; + } + return 0; + } + + WSTRING str() const { + WSTRINGSTREAM ss; + for (auto& b : data) { + ss << std::hex << std::setfill('0'_W) << std::setw(2) << static_cast(b); + } + return ss.str(); + } + + BOOL IsInstanceMethod() const { + return (CallingConvention() & IMAGE_CEE_CS_CALLCONV_HASTHIS) != 0; + } +}; + +struct MethodReference { + const AssemblyReference assembly; + const WSTRING type_name; + const WSTRING method_name; + const WSTRING action; + const MethodSignature method_signature; + const Version min_version; + const Version max_version; + const std::vector signature_types; + + MethodReference() + : min_version(Version(0, 0, 0, 0)), + max_version(Version(USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX)) {} + + MethodReference(const WSTRING& assembly_name, WSTRING type_name, WSTRING method_name, + WSTRING action, Version min_version, Version max_version, + const std::vector& method_signature, + const std::vector& signature_types) + : assembly(assembly_name), + type_name(type_name), + method_name(method_name), + action(action), + method_signature(method_signature), + min_version(min_version), + max_version(max_version), + signature_types(signature_types) {} + + inline WSTRING get_type_cache_key() const { + return "["_W + assembly.name + "]"_W + type_name + "_vMin_"_W + + min_version.str() + "_vMax_"_W + max_version.str(); + } + + inline WSTRING get_method_cache_key() const { + return "["_W + assembly.name + "]"_W + type_name + "."_W + method_name + + "_vMin_"_W + min_version.str() + "_vMax_"_W + max_version.str(); + } + + inline bool operator==(const MethodReference& other) const { + return assembly == other.assembly && type_name == other.type_name && + min_version == other.min_version && + max_version == other.max_version && + method_name == other.method_name && + method_signature == other.method_signature; + } +}; + +struct MethodReplacement { + const MethodReference caller_method; + const MethodReference target_method; + const MethodReference wrapper_method; + + MethodReplacement() {} + + MethodReplacement(MethodReference caller_method, + MethodReference target_method, + MethodReference wrapper_method) + : caller_method(caller_method), + target_method(target_method), + wrapper_method(wrapper_method) {} + + inline bool operator==(const MethodReplacement& other) const { + return caller_method == other.caller_method && + target_method == other.target_method && + wrapper_method == other.wrapper_method; + } +}; + +struct Integration { + const WSTRING integration_name; + std::vector method_replacements; + + Integration() : integration_name(""_W), method_replacements({}) {} + + Integration(WSTRING integration_name, + std::vector method_replacements) + : integration_name(integration_name), + method_replacements(method_replacements) {} + + inline bool operator==(const Integration& other) const { + return integration_name == other.integration_name && + method_replacements == other.method_replacements; + } +}; + +struct IntegrationMethod { + const WSTRING integration_name; + MethodReplacement replacement; + + IntegrationMethod() : integration_name(""_W), replacement({}) {} + + IntegrationMethod(WSTRING integration_name, MethodReplacement replacement) + : integration_name(integration_name), replacement(replacement) {} + + inline bool operator==(const IntegrationMethod& other) const { + return integration_name == other.integration_name && + replacement == other.replacement; + } +}; + +namespace { + +WSTRING GetNameFromAssemblyReferenceString(const WSTRING& wstr); +Version GetVersionFromAssemblyReferenceString(const WSTRING& wstr); +WSTRING GetLocaleFromAssemblyReferenceString(const WSTRING& wstr); +PublicKey GetPublicKeyFromAssemblyReferenceString(const WSTRING& wstr); + +} // namespace + +} // namespace trace + +#endif // DD_CLR_PROFILER_INTEGRATION_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/integration_loader.cpp b/src/Datadog.Trace.ClrProfiler.Native/integration_loader.cpp new file mode 100644 index 0000000000..abe9b31a4a --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/integration_loader.cpp @@ -0,0 +1,227 @@ +#include "integration_loader.h" + +#include +#include + +#include "environment_variables.h" +#include "logging.h" +#include "util.h" + +namespace trace { + +using json = nlohmann::json; + +std::vector LoadIntegrationsFromEnvironment() { + std::vector integrations; + for (const auto f : GetEnvironmentValues(environment::integrations_path)) { + Debug("Loading integrations from file: ", f); + auto is = LoadIntegrationsFromFile(f); + for (auto& i : is) { + integrations.push_back(i); + } + } + return integrations; +} + +std::vector LoadIntegrationsFromFile(const WSTRING& file_path) { + std::vector integrations; + + try { + std::ifstream stream; + stream.open(ToString(file_path)); + + if (static_cast(stream)) { + integrations = LoadIntegrationsFromStream(stream); + } else { + Warn("Failed to load integrations from file ", file_path); + } + + stream.close(); + } catch (...) { + auto ex = std::current_exception(); + try { + if (ex) { + std::rethrow_exception(ex); + } + } catch (const std::exception& ex) { + Warn("Failed to load integrations: ", ex.what()); + } + } + + return integrations; +} + +std::vector LoadIntegrationsFromStream(std::istream& stream) { + std::vector integrations; + + try { + json j; + // parse the stream + stream >> j; + + for (auto& el : j) { + auto i = IntegrationFromJson(el); + if (std::get<1>(i)) { + integrations.push_back(std::get<0>(i)); + } + } + + // Debug("Loaded integrations: ", j.dump()); + } catch (const json::parse_error& e) { + Warn("Invalid integrations:", e.what()); + } catch (const json::type_error& e) { + Warn("Invalid integrations:", e.what()); + } catch (...) { + auto ex = std::current_exception(); + try { + if (ex) { + std::rethrow_exception(ex); + } + } catch (const std::exception& ex) { + Warn("Failed to load integrations: ", ex.what()); + } + } + + return integrations; +} + +namespace { + +std::pair IntegrationFromJson(const json::value_type& src) { + if (!src.is_object()) { + return std::make_pair({}, false); + } + + // first get the name, which is required + const auto name = ToWSTRING(src.value("name", "")); + if (name.empty()) { + Warn("Integration name is missing for integration: ", src.dump()); + return std::make_pair({}, false); + } + + std::vector replacements; + auto arr = src.value("method_replacements", json::array()); + if (arr.is_array()) { + for (auto& el : arr) { + auto mr = MethodReplacementFromJson(el); + if (std::get<1>(mr)) { + replacements.push_back(std::get<0>(mr)); + } + } + } + return std::make_pair({name, replacements}, true); +} + +std::pair MethodReplacementFromJson( + const json::value_type& src) { + if (!src.is_object()) { + return std::make_pair({}, false); + } + + const auto caller = + MethodReferenceFromJson(src.value("caller", json::object()), false, false); + const auto target = + MethodReferenceFromJson(src.value("target", json::object()), true, false); + const auto wrapper = + MethodReferenceFromJson(src.value("wrapper", json::object()), false, true); + return std::make_pair({caller, target, wrapper}, + true); +} + +MethodReference MethodReferenceFromJson(const json::value_type& src, + const bool is_target_method, + const bool is_wrapper_method) { + if (!src.is_object()) { + return {}; + } + + const auto assembly = ToWSTRING(src.value("assembly", "")); + const auto type = ToWSTRING(src.value("type", "")); + const auto method = ToWSTRING(src.value("method", "")); + auto raw_signature = src.value("signature", json::array()); + + const auto eoj = src.end(); + USHORT min_major = 0; + USHORT min_minor = 0; + USHORT min_patch = 0; + USHORT max_major = USHRT_MAX; + USHORT max_minor = USHRT_MAX; + USHORT max_patch = USHRT_MAX; + std::vector signature_type_array; + WSTRING action = ""_W; + + if (is_target_method) { + // these fields only exist in the target definition + + if (src.find("minimum_major") != eoj) { + min_major = src["minimum_major"].get(); + } + if (src.find("minimum_minor") != eoj) { + min_minor = src["minimum_minor"].get(); + } + if (src.find("minimum_patch") != eoj) { + min_patch = src["minimum_patch"].get(); + } + if (src.find("maximum_major") != eoj) { + max_major = src["maximum_major"].get(); + } + if (src.find("maximum_minor") != eoj) { + max_minor = src["maximum_minor"].get(); + } + if (src.find("maximum_patch") != eoj) { + max_patch = src["maximum_patch"].get(); + } + + if (src.find("signature_types") != eoj) { + // c++ is unable to handle null values in this array + // we would need to write out own parsing here for null values + auto sig_types = src["signature_types"].get>(); + signature_type_array = std::vector(sig_types.size()); + for (auto i = sig_types.size() - 1; i < sig_types.size(); i--) { + signature_type_array[i] = ToWSTRING(sig_types[i]); + } + } + } else if (is_wrapper_method) { + action = ToWSTRING(src.value("action", "")); + } + + std::vector signature; + if (raw_signature.is_array()) { + for (auto& el : raw_signature) { + if (el.is_number_unsigned()) { + signature.push_back(BYTE(el.get())); + } + } + } else if (raw_signature.is_string()) { + // load as a hex string + std::string str = raw_signature; + bool flip = false; + char prev = 0; + for (auto& c : str) { + BYTE b = 0; + if ('0' <= c && c <= '9') { + b = c - '0'; + } else if ('a' <= c && c <= 'f') { + b = c - 'a' + 10; + } else if ('A' <= c && c <= 'F') { + b = c - 'A' + 10; + } else { + // skip any non-hex character + continue; + } + if (flip) { + signature.push_back((prev << 4) + b); + } + flip = !flip; + prev = b; + } + } + return MethodReference(assembly, type, method, action, + Version(min_major, min_minor, min_patch, 0), + Version(max_major, max_minor, max_patch, USHRT_MAX), + signature, signature_type_array); +} + +} // namespace + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/integration_loader.h b/src/Datadog.Trace.ClrProfiler.Native/integration_loader.h new file mode 100644 index 0000000000..a8a8fe2f31 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/integration_loader.h @@ -0,0 +1,38 @@ +#ifndef DD_CLR_PROFILER_INTEGRATION_LOADER_H_ +#define DD_CLR_PROFILER_INTEGRATION_LOADER_H_ + +#include +#include +#include +#include +#include + +#include "integration.h" +#include "macros.h" + +namespace trace { + +using json = nlohmann::json; + +// LoadIntegrationsFromEnvironment loads integrations from any files specified +// in the DD_INTEGRATIONS environment variable +std::vector LoadIntegrationsFromEnvironment(); +// LoadIntegrationsFromFile loads the integrations from a file +std::vector LoadIntegrationsFromFile(const WSTRING& file_path); +// LoadIntegrationsFromFile loads the integrations from a stream +std::vector LoadIntegrationsFromStream(std::istream& stream); + +namespace { + +std::pair IntegrationFromJson(const json::value_type& src); +std::pair MethodReplacementFromJson( + const json::value_type& src); +MethodReference MethodReferenceFromJson(const json::value_type& src, + const bool is_target_method, + const bool is_wrapper_method); + +} // namespace + +} // namespace trace + +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Native/interop.cpp b/src/Datadog.Trace.ClrProfiler.Native/interop.cpp new file mode 100644 index 0000000000..d064382626 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/interop.cpp @@ -0,0 +1,17 @@ +//--------------------------------------------------------------------------------------- +// Exports that managed code from Datadog.Trace.ClrProfiler.Managed.dll will +// P/Invoke into +// +// NOTE: Must keep these signatures in sync with the DllImports in +// NativeMethods.cs! +//--------------------------------------------------------------------------------------- + +#include "cor_profiler.h" + +EXTERN_C BOOL STDAPICALLTYPE IsProfilerAttached() { + return trace::profiler->IsAttached(); +} + +EXTERN_C VOID STDAPICALLTYPE GetAssemblyAndSymbolsBytes(BYTE** pAssemblyArray, int* assemblySize, BYTE** pSymbolsArray, int* symbolsSize) { + return trace::profiler->GetAssemblyAndSymbolsBytes(pAssemblyArray, assemblySize, pSymbolsArray, symbolsSize); +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/logging.cpp b/src/Datadog.Trace.ClrProfiler.Native/logging.cpp new file mode 100644 index 0000000000..843e5a7bd0 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/logging.cpp @@ -0,0 +1,44 @@ +#include "logging.h" + +#include +#include +#include + +#include "pal.h" + +namespace trace { + +bool debug_logging_enabled = false; + +void Log(const std::string& str) { + static auto current_process_name = ToString(GetCurrentProcessName()); + + std::stringstream ss; + ss << "[" << current_process_name << "] " << GetPID() << ": " << str + << std::endl; + auto line = ss.str(); + + try { + const auto path = ToString(DatadogLogFilePath()); + +#ifdef _WIN32 + // on VC++, use std::filesystem (C++ 17) to + // create directory if missing + const auto log_path = std::filesystem::path(path); + + if (log_path.has_parent_path()) { + const auto parent_path = log_path.parent_path(); + + if (!std::filesystem::exists(parent_path)) { + std::filesystem::create_directories(parent_path); + } + } +#endif + + std::ofstream out(path, std::ios::app); + out << line; + } catch (...) { + } +} + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/logging.h b/src/Datadog.Trace.ClrProfiler.Native/logging.h new file mode 100644 index 0000000000..2daed5d0b1 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/logging.h @@ -0,0 +1,43 @@ +#ifndef DD_CLR_PROFILER_LOGGING_H_ +#define DD_CLR_PROFILER_LOGGING_H_ + +#include "string.h" // NOLINT + +namespace trace { + +extern bool debug_logging_enabled; + +void Log(const std::string &str); + +template +std::string LogToString(Arg const &arg) { + return ToString(arg); +} + +template +std::string LogToString(Args const &... args) { + std::ostringstream oss; + int a[] = {0, ((void)(oss << LogToString(args)), 0)...}; + return oss.str(); +} + +template +void Debug(const Args... args) { + if (debug_logging_enabled) { + Log("[debug] " + LogToString(args...)); + } +} + +template +void Info(const Args... args) { + Log("[info] " + LogToString(args...)); +} + +template +void Warn(const Args... args) { + Log("[warn] " + LogToString(args...)); +} + +} // namespace trace + +#endif // DD_CLR_PROFILER_LOGGING_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/macros.h b/src/Datadog.Trace.ClrProfiler.Native/macros.h new file mode 100644 index 0000000000..0c72db3a36 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/macros.h @@ -0,0 +1,15 @@ +#ifndef DD_CLR_PROFILER_MACROS_H_ +#define DD_CLR_PROFILER_MACROS_H_ + +#include +#include + +#define RETURN_IF_FAILED(EXPR) \ + do { \ + hr = (EXPR); \ + if (FAILED(hr)) { \ + return (hr); \ + } \ + } while (0) + +#endif // DD_CLR_PROFILER_MACROS_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.cpp b/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.cpp new file mode 100644 index 0000000000..4856ec67bc --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.cpp @@ -0,0 +1,150 @@ +#include +#include + +#include "clr_helpers.h" +#include "logging.h" +#include "macros.h" +#include "metadata_builder.h" + +namespace trace { + +HRESULT MetadataBuilder::EmitAssemblyRef( + const trace::AssemblyReference& assembly_ref) const { + ASSEMBLYMETADATA assembly_metadata{}; + assembly_metadata.usMajorVersion = assembly_ref.version.major; + assembly_metadata.usMinorVersion = assembly_ref.version.minor; + assembly_metadata.usBuildNumber = assembly_ref.version.build; + assembly_metadata.usRevisionNumber = assembly_ref.version.revision; + if (assembly_ref.locale == "neutral"_W) { + assembly_metadata.szLocale = nullptr; + assembly_metadata.cbLocale = 0; + } else { + assembly_metadata.szLocale = + const_cast(assembly_ref.locale.c_str()); + assembly_metadata.cbLocale = (DWORD)(assembly_ref.locale.size()); + } + + DWORD public_key_size = 8; + if (assembly_ref.public_key == trace::PublicKey()) { + public_key_size = 0; + } + + mdAssemblyRef assembly_ref_out; + const HRESULT hr = assembly_emit_->DefineAssemblyRef( + &assembly_ref.public_key.data[0], public_key_size, + assembly_ref.name.c_str(), &assembly_metadata, + // hash blob + nullptr, + // cb of hash blob + 0, + // flags + 0, &assembly_ref_out); + + if (FAILED(hr)) { + Warn("DefineAssemblyRef failed"); + } + return S_OK; +} + +HRESULT MetadataBuilder::FindWrapperTypeRef( + const MethodReplacement& method_replacement, + mdTypeRef& type_ref_out) const { + const auto& cache_key = + method_replacement.wrapper_method.get_type_cache_key(); + mdTypeRef type_ref = mdTypeRefNil; + + if (metadata_.TryGetWrapperParentTypeRef(cache_key, type_ref)) { + // this type was already resolved + type_ref_out = type_ref; + return S_OK; + } + + HRESULT hr; + type_ref = mdTypeRefNil; + + if (metadata_.assemblyName == + method_replacement.wrapper_method.assembly.name) { + // type is defined in this assembly + hr = metadata_emit_->DefineTypeRefByName( + module_, method_replacement.wrapper_method.type_name.c_str(), + &type_ref); + } else { + // type is defined in another assembly, + // find a reference to the assembly where type lives + const auto assembly_ref = FindAssemblyRef( + assembly_import_, method_replacement.wrapper_method.assembly.name); + if (assembly_ref == mdAssemblyRefNil) { + // TODO: emit assembly reference if not found? + Warn("Assembly reference for", + method_replacement.wrapper_method.assembly.name, " not found"); + return E_FAIL; + } + + // search for an existing reference to the type + hr = metadata_import_->FindTypeRef( + assembly_ref, method_replacement.wrapper_method.type_name.c_str(), + &type_ref); + + if (hr == HRESULT(0x80131130) /* record not found on lookup */) { + // if typeRef not found, create a new one by emitting a metadata token + hr = metadata_emit_->DefineTypeRefByName( + assembly_ref, method_replacement.wrapper_method.type_name.c_str(), + &type_ref); + } + } + + RETURN_IF_FAILED(hr); + + // cache the typeRef in case we need it again + metadata_.SetWrapperParentTypeRef(cache_key, type_ref); + type_ref_out = type_ref; + return S_OK; +} + +HRESULT MetadataBuilder::StoreWrapperMethodRef( + const MethodReplacement& method_replacement) const { + const auto& cache_key = + method_replacement.wrapper_method.get_method_cache_key(); + mdMemberRef member_ref = mdMemberRefNil; + + if (metadata_.TryGetWrapperMemberRef(cache_key, member_ref)) { + // this member was already resolved + return S_OK; + } + + mdTypeRef type_ref = mdTypeRefNil; + HRESULT hr = FindWrapperTypeRef(method_replacement, type_ref); + if (FAILED(hr)) { + // Record that this cache_key failed + metadata_.SetFailedWrapperMemberKey(cache_key); + return hr; + } + + member_ref = mdMemberRefNil; + + hr = metadata_import_->FindMemberRef( + type_ref, method_replacement.wrapper_method.method_name.c_str(), + method_replacement.wrapper_method.method_signature.data.data(), + (DWORD)(method_replacement.wrapper_method.method_signature.data.size()), + &member_ref); + + if (hr == HRESULT(0x80131130) /* record not found on lookup */) { + // if memberRef not found, create it by emitting a metadata token + hr = metadata_emit_->DefineMemberRef( + type_ref, method_replacement.wrapper_method.method_name.c_str(), + method_replacement.wrapper_method.method_signature.data.data(), + (DWORD)(method_replacement.wrapper_method.method_signature.data.size()), + &member_ref); + } + + if (FAILED(hr)) { + // Record that this cache_key failed + metadata_.SetFailedWrapperMemberKey(cache_key); + return hr; + } + + metadata_.SetWrapperMemberRef(cache_key, member_ref); + return S_OK; +} + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.h b/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.h new file mode 100644 index 0000000000..8ab52d813d --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/metadata_builder.h @@ -0,0 +1,42 @@ +#pragma once + +#include + +#include "com_ptr.h" +#include "logging.h" +#include "module_metadata.h" + +namespace trace { + +class MetadataBuilder { + private: + ModuleMetadata& metadata_; + const mdModule module_ = mdModuleNil; + const ComPtr metadata_import_{}; + const ComPtr metadata_emit_{}; + const ComPtr assembly_import_{}; + const ComPtr assembly_emit_{}; + + HRESULT FindWrapperTypeRef(const MethodReplacement& method_replacement, + mdTypeRef& type_ref_out) const; + + public: + MetadataBuilder(ModuleMetadata& metadata, const mdModule module, + ComPtr metadata_import, + ComPtr metadata_emit, + ComPtr assembly_import, + ComPtr assembly_emit) + : metadata_(metadata), + module_(module), + metadata_import_(metadata_import), + metadata_emit_(metadata_emit), + assembly_import_(assembly_import), + assembly_emit_(assembly_emit) {} + + HRESULT StoreWrapperMethodRef( + const MethodReplacement& method_replacement) const; + + HRESULT EmitAssemblyRef(const trace::AssemblyReference& assembly_ref) const; +}; + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/miniutf.cpp b/src/Datadog.Trace.ClrProfiler.Native/miniutf.cpp new file mode 100644 index 0000000000..f219fc63b5 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/miniutf.cpp @@ -0,0 +1,408 @@ +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "miniutf.hpp" + +#include + +namespace miniutf { + +#include "miniutfdata.h" + +/* * * * * * * * * * + * Encoding + * * * * * * * * * */ + +void utf8_encode(char32_t pt, std::string& out) { + if (pt < 0x80) { + out += static_cast(pt); + } else if (pt < 0x800) { + out += {static_cast((pt >> 6) | 0xC0), + static_cast((pt & 0x3F) | 0x80)}; + } else if (pt < 0x10000) { + out += {static_cast((pt >> 12) | 0xE0), + static_cast(((pt >> 6) & 0x3F) | 0x80), + static_cast((pt & 0x3F) | 0x80)}; + } else if (pt < 0x110000) { + out += {static_cast((pt >> 18) | 0xF0), + static_cast(((pt >> 12) & 0x3F) | 0x80), + static_cast(((pt >> 6) & 0x3F) | 0x80), + static_cast((pt & 0x3F) | 0x80)}; + } else { +#pragma warning(disable : 4309) + out += {static_cast(0xEF), static_cast(0xBF), + static_cast(0xBD)}; // U+FFFD +#pragma warning(default : 4309) + } +} + +void utf16_encode(char32_t pt, std::u16string& out) { + if (pt < 0x10000) { + out += static_cast(pt); + } else if (pt < 0x110000) { + out += {static_cast(((pt - 0x10000) >> 10) + 0xD800), + static_cast((pt & 0x3FF) + 0xDC00)}; + } else { + out += 0xFFFD; + } +} + +/* * * * * * * * * * + * Decoding logic + * * * * * * * * * */ + +struct offset_pt { + int offset; + char32_t pt; +}; + +static constexpr const offset_pt invalid_pt = {-1, 0}; + +/* + * Decode a codepoint starting at str[i], and return the number of code units + * (bytes, for UTF-8) consumed and the result. If no valid codepoint is at + * str[i], return invalid_pt. + */ +static offset_pt utf8_decode_check(const std::string& str, + std::string::size_type i) { + uint32_t b0, b1, b2, b3; + + b0 = static_cast(str[i]); + + if (b0 < 0x80) { + // 1-byte character + return {1, b0}; + } else if (b0 < 0xC0) { + // Unexpected continuation byte + return invalid_pt; + } else if (b0 < 0xE0) { + // 2-byte character + if (((b1 = str[i + 1]) & 0xC0) != 0x80) return invalid_pt; + + char32_t pt = (b0 & 0x1F) << 6 | (b1 & 0x3F); + if (pt < 0x80) return invalid_pt; + + return {2, pt}; + } else if (b0 < 0xF0) { + // 3-byte character + if (((b1 = str[i + 1]) & 0xC0) != 0x80) return invalid_pt; + if (((b2 = str[i + 2]) & 0xC0) != 0x80) return invalid_pt; + + char32_t pt = (b0 & 0x0F) << 12 | (b1 & 0x3F) << 6 | (b2 & 0x3F); + if (pt < 0x800) return invalid_pt; + + return {3, pt}; + } else if (b0 < 0xF8) { + // 4-byte character + if (((b1 = str[i + 1]) & 0xC0) != 0x80) return invalid_pt; + if (((b2 = str[i + 2]) & 0xC0) != 0x80) return invalid_pt; + if (((b3 = str[i + 3]) & 0xC0) != 0x80) return invalid_pt; + + char32_t pt = + (b0 & 0x0F) << 18 | (b1 & 0x3F) << 12 | (b2 & 0x3F) << 6 | (b3 & 0x3F); + if (pt < 0x10000 || pt >= 0x110000) return invalid_pt; + + return {4, pt}; + } else { + // Codepoint out of range + return invalid_pt; + } +} + +// UTF-16 decode helpers. +static inline bool is_high_surrogate(char16_t c) { + return (c >= 0xD800) && (c < 0xDC00); +} +static inline bool is_low_surrogate(char16_t c) { + return (c >= 0xDC00) && (c < 0xE000); +} + +/* + * Like utf8_decode_check, but for UTF-16. + */ +static offset_pt utf16_decode_check(const std::u16string& str, + std::u16string::size_type i) { + if (is_high_surrogate(str[i]) && is_low_surrogate(str[i + 1])) { + // High surrogate followed by low surrogate + char32_t pt = (((str[i] - 0xD800) << 10) | (str[i + 1] - 0xDC00)) + 0x10000; + return {2, pt}; + } else if (is_high_surrogate(str[i]) || is_low_surrogate(str[i])) { + // High surrogate *not* followed by low surrogate, or unpaired low surrogate + return invalid_pt; + } else { + return {1, str[i]}; + } +} + +/* + * UTF-32 is very easy to check. + */ +static offset_pt utf32_decode_check(const std::u32string& str, + std::u32string::size_type i) { + if (str[i] < 0x110000) { + return {1, str[i]}; + } else { + return invalid_pt; + } +} + +/* * * * * * * * * * + * Decoding wrappers + * * * * * * * * * */ + +char32_t utf8_decode(const std::string& str, std::string::size_type& i, + bool* replacement_flag) { + offset_pt res = utf8_decode_check(str, i); + if (res.offset < 0) { + if (replacement_flag) *replacement_flag = true; + i += 1; + return 0xFFFD; + } else { + i += res.offset; + return res.pt; + } +} + +char32_t utf16_decode(const std::u16string& str, std::u16string::size_type& i, + bool* replacement_flag) { + offset_pt res = utf16_decode_check(str, i); + if (res.offset < 0) { + if (replacement_flag) *replacement_flag = true; + i += 1; + return 0xFFFD; + } else { + i += res.offset; + return res.pt; + } +} + +/* * * * * * * * * * + * Checking + * * * * * * * * * */ + +template +bool check_helper(const Tfunc& func, const Tstring& str) { + for (typename Tstring::size_type i = 0; i < str.length();) { + offset_pt res = func(str, i); + if (res.offset < 0) return false; + i += res.offset; + } + return true; +} + +bool utf8_check(const std::string& str) { + return check_helper(utf8_decode_check, str); +} +bool utf16_check(const std::u16string& str) { + return check_helper(utf16_decode_check, str); +} +bool utf32_check(const std::u32string& str) { + return check_helper(utf32_decode_check, str); +} + +/* * * * * * * * * * + * Conversion + * * * * * * * * * */ + +std::u32string to_utf32(const std::string& str) { + std::u32string out; + out.reserve(str.length()); // likely overallocate + for (std::string::size_type i = 0; i < str.length();) + out += utf8_decode(str, i); + return out; +} + +std::u16string to_utf16(const std::string& str) { + std::u16string out; + out.reserve(str.length()); // likely overallocate + for (std::string::size_type i = 0; i < str.length();) + utf16_encode(utf8_decode(str, i), out); + return out; +} + +std::string to_utf8(const std::u16string& str) { + std::string out; + out.reserve(str.length() * 3 / 2); // estimate + for (std::u16string::size_type i = 0; i < str.length();) + utf8_encode(utf16_decode(str, i), out); + return out; +} + +std::string to_utf8(const std::u32string& str) { + std::string out; + out.reserve(str.length() * 3 / 2); // estimate + for (char32_t pt : str) utf8_encode(pt, out); + return out; +} + +/* * * * * * * * * * + * Lowercase + * * * * * * * * * */ + +std::string lowercase(const std::string& str) { + std::string out; + out.reserve(str.size()); + for (size_t i = 0; i < str.length();) { + int32_t pt = utf8_decode(str, i); + utf8_encode(pt + lowercase_offset(pt), out); + } + return out; +} + +/* * * * * * * * * * + * Composition + * * * * * * * * * */ + +/* + * Write the canonical decomposition of pt to out. + */ +static void unicode_decompose(char32_t pt, std::u32string& out) { + // Special-case: Hangul decomposition + if (pt >= 0xAC00 && pt < 0xD7A4) { + out += 0x1100 + (pt - 0xAC00) / 588; + out += 0x1161 + ((pt - 0xAC00) % 588) / 28; + if ((pt - 0xAC00) % 28) out += 0x11A7 + (pt - 0xAC00) % 28; + return; + } + + // Otherwise, look up in the decomposition table + int32_t decomp_start_idx = decomp_idx(pt); + if (!decomp_start_idx) { + out += pt; + return; + } + + size_t length = (decomp_start_idx >> 14) + 1; + decomp_start_idx &= (1 << 14) - 1; + + for (size_t i = 0; i < length; i++) { + out += xref[decomp_seq[decomp_start_idx + i]]; + } +} + +/* + * If there is a Primary Composite equivalent to , return it. Otherwise + * return 0. + */ +static uint32_t unicode_compose(uint32_t L, uint32_t C) { + int comp_seq_idx; + + /* Algorithmic Hangul composition */ + if (L >= 0x1100 && L < 0x1113 && C >= 0x1161 && C < 0x1176) + return ((L - 0x1100) * 21 + C - 0x1161) * 28 + 0xAC00; + + if (L >= 0xAC00 && L < 0xD7A4 && !((L - 0xAC00) % 28) && C >= 0x11A8 && + C < 0x11C3) + return L + C - 0x11A7; + + /* Predefined composition mapping */ + comp_seq_idx = comp_idx(L); + do { + if (xref[comp_seq[comp_seq_idx * 2] & ~0x8000] == C) + return xref[comp_seq[comp_seq_idx * 2 + 1]]; + } while (!(comp_seq[(comp_seq_idx++) * 2] & 0x8000)); + + return 0; +} + +std::u32string normalize32(const std::string& str, bool compose, + bool* replacement_flag) { + if (str.empty()) return {}; + + // Decode and decompose + std::u32string codepoints; + codepoints.reserve(str.size()); + for (size_t i = 0; i < str.length();) { + uint32_t pt = utf8_decode(str, i, replacement_flag); + unicode_decompose(pt, codepoints); + } + + // Canonical Ordering Algorithm: sort all runs of characters with nonzero + // combining class. + size_t start = 0; + while (start < codepoints.length()) { + if (!ccc(codepoints[start])) { + start++; + continue; + } + + size_t end = start + 1; + while (end < codepoints.length() && ccc(codepoints[end])) { + end++; + } + + if (end - start > 1) { + std::stable_sort(codepoints.begin() + start, codepoints.begin() + end, + [](char32_t a, char32_t b) { return ccc(a) < ccc(b); }); + } + + start = end + 1; + } + + if (compose) { + size_t i = 1; + int last_class = -1, starter_pos = 0, target_pos = 1; + char32_t starter = codepoints[0]; + + while (i < codepoints.length()) { + char32_t ch = codepoints[i]; + int ch_class = ccc(ch); + + uint32_t composite = unicode_compose(starter, ch); + if (composite && last_class < ch_class) { + codepoints[starter_pos] = composite; + starter = composite; + } else if (ch_class == 0) { + starter_pos = target_pos; + starter = ch; + last_class = -1; + codepoints[target_pos] = ch; + target_pos++; + } else { + last_class = ch_class; + codepoints[target_pos] = ch; + target_pos++; + } + + i++; + } + + codepoints.resize(target_pos); + } + + return codepoints; +} + +std::string normalize8(const std::string& str, bool compose, + bool* replacement_flag) { + std::u32string codepoints = normalize32(str, compose, replacement_flag); + return to_utf8(codepoints); +} + +std::string nfc(const std::string& str, bool* replacement_flag) { + return normalize8(str, true, replacement_flag); +} + +std::string nfd(const std::string& str, bool* replacement_flag) { + return normalize8(str, false, replacement_flag); +} + +} // namespace miniutf diff --git a/src/Datadog.Trace.ClrProfiler.Native/miniutf.hpp b/src/Datadog.Trace.ClrProfiler.Native/miniutf.hpp new file mode 100644 index 0000000000..5880c15a70 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/miniutf.hpp @@ -0,0 +1,110 @@ +/* Copyright (c) 2013 Dropbox, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * 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. + */ + +#pragma once + +#include + +namespace miniutf { + +/* + * Character-at-a-time encoding. Convert pt to UTF-8/16 and append to out. + * + * If pt is invalid (greater than U+10FFFF), U+FFFD will be encoded instead. + */ +void utf8_encode(char32_t pt, std::string & out); +void utf16_encode(char32_t pt, std::u16string & out); + +/* + * Character-at-a-time decoding. Decodes and returns the codepoint starting at str[pos], + * and then advance pos by the appropriate amount. + * + * If an invalid codepoint is found, return U+FFFD, add 1 to pos, and (if replacement_flag is + * non-null) set *replacement_flag to true. + */ +char32_t utf8_decode(const std::string & str, + std::string::size_type & pos, + bool * replacement_flag = nullptr); +char32_t utf16_decode(const std::u16string & str, + std::u16string::size_type & pos, + bool * replacement_flag = nullptr); + +/* + * Return true if str is valid UTF-8, -16, or -32. + * + * - UTF-8 is valid if it contains no misplaced or missing continuation bytes, no overlong + * encodings, and no codepoints above U+10FFFF. + * + * - UTF-16 is valid if it contains no unpaired surrogates. (There's no way to attempt + * to represent codepoints above U+10FFFF in UTF-16.) + * + * - UTF-32 is valid if it contains no codepoints above U+10FFFF. + */ +bool utf8_check(const std::string & str); +bool utf16_check(const std::string & str); +bool utf32_check(const std::string & str); + +/* + * Convert back and forth between UTF-8 and UTF-16 or UTF-32. + * + * These functions replace invalid sections of input with U+FFFD. If this is not desired, + * use utf8_check (above) first to check that the input is valid. + */ +std::u32string to_utf32(const std::string & str); +std::u16string to_utf16(const std::string & str); +std::string to_utf8(const std::u16string & str); +std::string to_utf8(const std::u32string & str); + +/* + * Convert str to lowercase, per the built-in Unicode lowercasing map (codepoint-by-codepoint). + */ +std::string lowercase(const std::string & str); + +/* + * Decompose str. Then, if compose is set, recompose it. + * + * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and + * replacement_flag is specified, it will be set to true. + */ +std::string normalize8(const std::string & str, + bool compose, + bool * replacement_flag = nullptr); +std::u32string normalize32(const std::string & str, + bool compose, + bool * replacement_flag = nullptr); + +/* + * Convert str to Normalization Form C. Equivalent to normalize8(str, true, replacement_flag). + * + * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and + * replacement_flag is specified, *replacement_flag will be set to true. + */ +std::string nfc(const std::string & str, bool * replacement_flag = nullptr); + +/* + * Convert str to Normalization Form D. Equivalent to normalize8(in, false, replacement_flag). + * + * If replacement characters are used during decoding (i.e. str contains invalid UTF-8), and + * replacement_flag is specified, *replacement_flag will be set to true. + */ +std::string nfd(const std::string & str, bool * replacement_flag = nullptr); + +} // namespace miniutf diff --git a/src/Datadog.Trace.ClrProfiler.Native/miniutfdata.h b/src/Datadog.Trace.ClrProfiler.Native/miniutfdata.h new file mode 100644 index 0000000000..1328ae7e17 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/miniutfdata.h @@ -0,0 +1,1901 @@ +static const uint32_t xref[] = { + 0, 59, 60, 61, 62, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, 79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114, 115, + 116, 117, 118, 119, 120, 121, 122, 168, 180, 183, 192, 193, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 209, 210, + 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 241, 242, + 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 256, 257, 258, + 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 308, 309, 310, 311, 313, 314, 315, 316, 317, 318, 323, 324, 325, 326, + 327, 328, 332, 333, 334, 335, 336, 337, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 360, 361, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 416, 417, 431, 432, 439, 461, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 478, 479, 480, 481, 482, 483, 486, 487, 488, 489, 490, 491, 492, + 493, 494, 495, 496, 500, 501, 504, 505, 506, 507, 508, 509, 510, 511, + 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, + 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, + 542, 543, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, + 562, 563, 658, 697, 768, 769, 770, 771, 772, 774, 775, 776, 777, 778, + 779, 780, 783, 785, 787, 788, 795, 803, 804, 805, 806, 807, 808, 813, + 814, 816, 817, 824, 832, 833, 834, 835, 836, 837, 884, 894, 901, 902, + 903, 904, 905, 906, 908, 910, 911, 912, 913, 917, 919, 921, 927, 929, + 933, 937, 938, 939, 940, 941, 942, 943, 944, 945, 949, 951, 953, 959, + 961, 965, 969, 970, 971, 972, 973, 974, 978, 979, 980, 1024, 1025, + 1027, 1030, 1031, 1036, 1037, 1038, 1040, 1043, 1045, 1046, 1047, + 1048, 1049, 1050, 1054, 1059, 1063, 1067, 1069, 1072, 1075, 1077, + 1078, 1079, 1080, 1081, 1082, 1086, 1091, 1095, 1099, 1101, 1104, + 1105, 1107, 1110, 1111, 1116, 1117, 1118, 1140, 1141, 1142, 1143, + 1217, 1218, 1232, 1233, 1234, 1235, 1238, 1239, 1240, 1241, 1242, + 1243, 1244, 1245, 1246, 1247, 1250, 1251, 1252, 1253, 1254, 1255, + 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, + 1267, 1268, 1269, 1272, 1273, 1460, 1463, 1464, 1465, 1468, 1471, + 1473, 1474, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1496, 1497, + 1498, 1499, 1500, 1502, 1504, 1505, 1507, 1508, 1510, 1511, 1512, + 1513, 1514, 1522, 1570, 1571, 1572, 1573, 1574, 1575, 1608, 1610, + 1619, 1620, 1621, 1728, 1729, 1730, 1746, 1747, 1749, 2325, 2326, + 2327, 2332, 2337, 2338, 2344, 2345, 2347, 2351, 2352, 2353, 2355, + 2356, 2364, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2465, + 2466, 2479, 2492, 2494, 2503, 2507, 2508, 2519, 2524, 2525, 2527, + 2582, 2583, 2588, 2603, 2610, 2611, 2614, 2616, 2620, 2649, 2650, + 2651, 2654, 2849, 2850, 2876, 2878, 2887, 2888, 2891, 2892, 2902, + 2903, 2908, 2909, 2962, 2964, 3006, 3014, 3015, 3018, 3019, 3020, + 3031, 3142, 3144, 3158, 3263, 3264, 3266, 3270, 3271, 3272, 3274, + 3275, 3285, 3286, 3390, 3398, 3399, 3402, 3403, 3404, 3415, 3530, + 3535, 3545, 3546, 3548, 3549, 3550, 3551, 3904, 3906, 3907, 3916, + 3917, 3921, 3922, 3926, 3927, 3931, 3932, 3945, 3953, 3954, 3955, + 3956, 3957, 3958, 3960, 3968, 3969, 3984, 3986, 3987, 3996, 3997, + 4001, 4002, 4006, 4007, 4011, 4012, 4018, 4019, 4021, 4023, 4025, + 4133, 4134, 4142, 6917, 6918, 6919, 6920, 6921, 6922, 6923, 6924, + 6925, 6926, 6929, 6930, 6965, 6970, 6971, 6972, 6973, 6974, 6975, + 6976, 6977, 6978, 6979, 7680, 7681, 7682, 7683, 7684, 7685, 7686, + 7687, 7688, 7689, 7690, 7691, 7692, 7693, 7694, 7695, 7696, 7697, + 7698, 7699, 7700, 7701, 7702, 7703, 7704, 7705, 7706, 7707, 7708, + 7709, 7710, 7711, 7712, 7713, 7714, 7715, 7716, 7717, 7718, 7719, + 7720, 7721, 7722, 7723, 7724, 7725, 7726, 7727, 7728, 7729, 7730, + 7731, 7732, 7733, 7734, 7735, 7736, 7737, 7738, 7739, 7740, 7741, + 7742, 7743, 7744, 7745, 7746, 7747, 7748, 7749, 7750, 7751, 7752, + 7753, 7754, 7755, 7756, 7757, 7758, 7759, 7760, 7761, 7762, 7763, + 7764, 7765, 7766, 7767, 7768, 7769, 7770, 7771, 7772, 7773, 7774, + 7775, 7776, 7777, 7778, 7779, 7780, 7781, 7782, 7783, 7784, 7785, + 7786, 7787, 7788, 7789, 7790, 7791, 7792, 7793, 7794, 7795, 7796, + 7797, 7798, 7799, 7800, 7801, 7802, 7803, 7804, 7805, 7806, 7807, + 7808, 7809, 7810, 7811, 7812, 7813, 7814, 7815, 7816, 7817, 7818, + 7819, 7820, 7821, 7822, 7823, 7824, 7825, 7826, 7827, 7828, 7829, + 7830, 7831, 7832, 7833, 7835, 7840, 7841, 7842, 7843, 7844, 7845, + 7846, 7847, 7848, 7849, 7850, 7851, 7852, 7853, 7854, 7855, 7856, + 7857, 7858, 7859, 7860, 7861, 7862, 7863, 7864, 7865, 7866, 7867, + 7868, 7869, 7870, 7871, 7872, 7873, 7874, 7875, 7876, 7877, 7878, + 7879, 7880, 7881, 7882, 7883, 7884, 7885, 7886, 7887, 7888, 7889, + 7890, 7891, 7892, 7893, 7894, 7895, 7896, 7897, 7898, 7899, 7900, + 7901, 7902, 7903, 7904, 7905, 7906, 7907, 7908, 7909, 7910, 7911, + 7912, 7913, 7914, 7915, 7916, 7917, 7918, 7919, 7920, 7921, 7922, + 7923, 7924, 7925, 7926, 7927, 7928, 7929, 7936, 7937, 7938, 7939, + 7940, 7941, 7942, 7943, 7944, 7945, 7946, 7947, 7948, 7949, 7950, + 7951, 7952, 7953, 7954, 7955, 7956, 7957, 7960, 7961, 7962, 7963, + 7964, 7965, 7968, 7969, 7970, 7971, 7972, 7973, 7974, 7975, 7976, + 7977, 7978, 7979, 7980, 7981, 7982, 7983, 7984, 7985, 7986, 7987, + 7988, 7989, 7990, 7991, 7992, 7993, 7994, 7995, 7996, 7997, 7998, + 7999, 8000, 8001, 8002, 8003, 8004, 8005, 8008, 8009, 8010, 8011, + 8012, 8013, 8016, 8017, 8018, 8019, 8020, 8021, 8022, 8023, 8025, + 8027, 8029, 8031, 8032, 8033, 8034, 8035, 8036, 8037, 8038, 8039, + 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, 8048, 8049, 8050, + 8051, 8052, 8053, 8054, 8055, 8056, 8057, 8058, 8059, 8060, 8061, + 8064, 8065, 8066, 8067, 8068, 8069, 8070, 8071, 8072, 8073, 8074, + 8075, 8076, 8077, 8078, 8079, 8080, 8081, 8082, 8083, 8084, 8085, + 8086, 8087, 8088, 8089, 8090, 8091, 8092, 8093, 8094, 8095, 8096, + 8097, 8098, 8099, 8100, 8101, 8102, 8103, 8104, 8105, 8106, 8107, + 8108, 8109, 8110, 8111, 8112, 8113, 8114, 8115, 8116, 8118, 8119, + 8120, 8121, 8122, 8123, 8124, 8126, 8127, 8129, 8130, 8131, 8132, + 8134, 8135, 8136, 8137, 8138, 8139, 8140, 8141, 8142, 8143, 8144, + 8145, 8146, 8147, 8150, 8151, 8152, 8153, 8154, 8155, 8157, 8158, + 8159, 8160, 8161, 8162, 8163, 8164, 8165, 8166, 8167, 8168, 8169, + 8170, 8171, 8172, 8173, 8174, 8175, 8178, 8179, 8180, 8182, 8183, + 8184, 8185, 8186, 8187, 8188, 8189, 8190, 8192, 8193, 8194, 8195, + 8486, 8490, 8491, 8592, 8594, 8596, 8602, 8603, 8622, 8653, 8654, + 8655, 8656, 8658, 8660, 8707, 8708, 8712, 8713, 8715, 8716, 8739, + 8740, 8741, 8742, 8764, 8769, 8771, 8772, 8773, 8775, 8776, 8777, + 8781, 8800, 8801, 8802, 8804, 8805, 8813, 8814, 8815, 8816, 8817, + 8818, 8819, 8820, 8821, 8822, 8823, 8824, 8825, 8826, 8827, 8828, + 8829, 8832, 8833, 8834, 8835, 8836, 8837, 8838, 8839, 8840, 8841, + 8849, 8850, 8866, 8872, 8873, 8875, 8876, 8877, 8878, 8879, 8882, + 8883, 8884, 8885, 8928, 8929, 8930, 8931, 8938, 8939, 8940, 8941, + 9001, 9002, 10972, 10973, 12296, 12297, 12358, 12363, 12364, 12365, + 12366, 12367, 12368, 12369, 12370, 12371, 12372, 12373, 12374, 12375, + 12376, 12377, 12378, 12379, 12380, 12381, 12382, 12383, 12384, 12385, + 12386, 12388, 12389, 12390, 12391, 12392, 12393, 12399, 12400, 12401, + 12402, 12403, 12404, 12405, 12406, 12407, 12408, 12409, 12410, 12411, + 12412, 12413, 12436, 12441, 12442, 12445, 12446, 12454, 12459, 12460, + 12461, 12462, 12463, 12464, 12465, 12466, 12467, 12468, 12469, 12470, + 12471, 12472, 12473, 12474, 12475, 12476, 12477, 12478, 12479, 12480, + 12481, 12482, 12484, 12485, 12486, 12487, 12488, 12489, 12495, 12496, + 12497, 12498, 12499, 12500, 12501, 12502, 12503, 12504, 12505, 12506, + 12507, 12508, 12509, 12527, 12528, 12529, 12530, 12532, 12535, 12536, + 12537, 12538, 12541, 12542, 13470, 13497, 13499, 13535, 13589, 14062, + 14076, 14209, 14383, 14434, 14460, 14535, 14563, 14620, 14650, 14894, + 14956, 15076, 15112, 15129, 15177, 15261, 15384, 15438, 15667, 15766, + 16044, 16056, 16155, 16380, 16392, 16408, 16441, 16454, 16534, 16611, + 16687, 16898, 16935, 17056, 17153, 17204, 17241, 17365, 17369, 17419, + 17515, 17707, 17757, 17761, 17771, 17879, 17913, 17973, 18110, 18119, + 18837, 18918, 19054, 19062, 19122, 19251, 19406, 19662, 19693, 19704, + 19798, 19981, 20006, 20018, 20024, 20025, 20029, 20033, 20098, 20102, + 20142, 20160, 20172, 20196, 20320, 20352, 20358, 20363, 20398, 20411, + 20415, 20482, 20523, 20602, 20633, 20687, 20698, 20711, 20800, 20805, + 20813, 20820, 20836, 20839, 20840, 20841, 20845, 20855, 20864, 20877, + 20882, 20885, 20887, 20900, 20908, 20917, 20919, 20937, 20940, 20956, + 20958, 20981, 20995, 20999, 21015, 21033, 21050, 21051, 21062, 21106, + 21111, 21129, 21147, 21155, 21171, 21191, 21193, 21202, 21214, 21220, + 21237, 21242, 21253, 21254, 21271, 21311, 21321, 21329, 21338, 21363, + 21365, 21373, 21375, 21443, 21450, 21471, 21477, 21483, 21489, 21510, + 21519, 21533, 21560, 21570, 21576, 21608, 21662, 21666, 21693, 21750, + 21776, 21843, 21845, 21859, 21892, 21895, 21913, 21917, 21931, 21939, + 21952, 21954, 21986, 22022, 22097, 22120, 22132, 22265, 22294, 22295, + 22411, 22478, 22516, 22541, 22577, 22578, 22592, 22618, 22622, 22696, + 22700, 22707, 22744, 22751, 22766, 22770, 22775, 22790, 22810, 22818, + 22852, 22856, 22865, 22868, 22882, 22899, 23000, 23020, 23067, 23079, + 23138, 23142, 23221, 23304, 23336, 23358, 23429, 23491, 23512, 23527, + 23534, 23539, 23551, 23558, 23586, 23615, 23648, 23650, 23652, 23653, + 23662, 23693, 23744, 23833, 23875, 23888, 23915, 23918, 23932, 23986, + 23994, 24033, 24034, 24061, 24104, 24125, 24169, 24180, 24230, 24240, + 24243, 24246, 24265, 24266, 24274, 24275, 24281, 24300, 24318, 24324, + 24354, 24403, 24418, 24425, 24427, 24459, 24474, 24489, 24493, 24525, + 24535, 24565, 24569, 24594, 24604, 24693, 24705, 24724, 24775, 24792, + 24801, 24840, 24900, 24904, 24908, 24910, 24928, 24936, 24954, 24974, + 24976, 24996, 25007, 25010, 25054, 25074, 25078, 25088, 25104, 25115, + 25134, 25140, 25181, 25265, 25289, 25295, 25299, 25300, 25340, 25342, + 25405, 25424, 25448, 25467, 25475, 25504, 25513, 25540, 25541, 25572, + 25628, 25634, 25682, 25705, 25719, 25726, 25754, 25757, 25796, 25935, + 25942, 25964, 25976, 26009, 26053, 26082, 26083, 26131, 26185, 26228, + 26248, 26257, 26268, 26292, 26310, 26356, 26360, 26368, 26391, 26395, + 26401, 26446, 26451, 26454, 26462, 26491, 26501, 26519, 26611, 26618, + 26647, 26655, 26706, 26753, 26757, 26766, 26792, 26900, 26946, 27043, + 27114, 27138, 27155, 27304, 27347, 27355, 27396, 27425, 27476, 27506, + 27511, 27513, 27551, 27566, 27578, 27579, 27726, 27751, 27784, 27839, + 27852, 27853, 27877, 27926, 27931, 27934, 27956, 27966, 27969, 28009, + 28010, 28023, 28024, 28037, 28107, 28122, 28138, 28153, 28186, 28207, + 28270, 28316, 28346, 28359, 28363, 28369, 28379, 28431, 28450, 28451, + 28526, 28614, 28651, 28670, 28699, 28702, 28729, 28746, 28784, 28791, + 28797, 28825, 28845, 28872, 28889, 28997, 29001, 29038, 29084, 29134, + 29136, 29200, 29211, 29224, 29227, 29237, 29264, 29282, 29312, 29333, + 29359, 29376, 29436, 29482, 29557, 29562, 29575, 29579, 29605, 29618, + 29662, 29702, 29705, 29730, 29767, 29788, 29801, 29809, 29829, 29833, + 29848, 29898, 29958, 29988, 30011, 30014, 30041, 30053, 30064, 30178, + 30224, 30237, 30239, 30274, 30313, 30410, 30427, 30439, 30452, 30465, + 30494, 30495, 30528, 30538, 30603, 30631, 30798, 30827, 30860, 30865, + 30922, 30924, 30971, 31018, 31036, 31038, 31048, 31049, 31056, 31062, + 31069, 31070, 31077, 31103, 31117, 31118, 31119, 31150, 31178, 31211, + 31260, 31296, 31306, 31311, 31361, 31409, 31435, 31470, 31520, 31680, + 31686, 31689, 31806, 31840, 31867, 31890, 31934, 31954, 31958, 31971, + 31975, 31976, 32000, 32016, 32034, 32047, 32091, 32099, 32160, 32190, + 32199, 32244, 32258, 32265, 32311, 32321, 32325, 32574, 32626, 32633, + 32634, 32645, 32661, 32666, 32701, 32762, 32769, 32773, 32838, 32864, + 32879, 32880, 32894, 32907, 32941, 32946, 33027, 33086, 33240, 33256, + 33261, 33281, 33284, 33304, 33391, 33401, 33419, 33425, 33437, 33457, + 33459, 33469, 33509, 33510, 33565, 33571, 33590, 33618, 33619, 33635, + 33709, 33725, 33737, 33738, 33740, 33756, 33767, 33775, 33777, 33853, + 33865, 33879, 34030, 34033, 34035, 34044, 34070, 34148, 34253, 34298, + 34310, 34322, 34349, 34367, 34384, 34396, 34407, 34409, 34440, 34473, + 34530, 34574, 34600, 34667, 34681, 34694, 34746, 34785, 34817, 34847, + 34892, 34912, 34915, 35010, 35023, 35031, 35038, 35041, 35064, 35066, + 35088, 35137, 35172, 35206, 35211, 35222, 35488, 35498, 35519, 35531, + 35538, 35542, 35565, 35576, 35582, 35585, 35641, 35672, 35712, 35722, + 35912, 35925, 36011, 36033, 36034, 36040, 36051, 36104, 36123, 36215, + 36284, 36299, 36335, 36336, 36554, 36564, 36646, 36650, 36664, 36667, + 36706, 36766, 36784, 36790, 36899, 36920, 36978, 36988, 37007, 37012, + 37070, 37086, 37105, 37117, 37137, 37147, 37226, 37273, 37300, 37324, + 37327, 37329, 37428, 37432, 37494, 37500, 37591, 37592, 37636, 37706, + 37881, 37909, 38283, 38317, 38327, 38446, 38475, 38477, 38517, 38520, + 38524, 38534, 38563, 38583, 38584, 38595, 38626, 38627, 38646, 38647, + 38691, 38706, 38728, 38742, 38875, 38880, 38911, 38923, 38936, 38953, + 38971, 39006, 39138, 39151, 39164, 39208, 39209, 39335, 39362, 39409, + 39422, 39530, 39698, 39791, 40000, 40023, 40189, 40295, 40372, 40442, + 40478, 40575, 40599, 40607, 40635, 40654, 40697, 40702, 40709, 40719, + 40726, 40763, 40771, 40845, 40846, 40860, 63744, 63745, 63746, 63747, + 63748, 63749, 63750, 63751, 63752, 63753, 63754, 63755, 63756, 63757, + 63758, 63759, 63760, 63761, 63762, 63763, 63764, 63765, 63766, 63767, + 63768, 63769, 63770, 63771, 63772, 63773, 63774, 63775, 63776, 63777, + 63778, 63779, 63780, 63781, 63782, 63783, 63784, 63785, 63786, 63787, + 63788, 63789, 63790, 63791, 63792, 63793, 63794, 63795, 63796, 63797, + 63798, 63799, 63800, 63801, 63802, 63803, 63804, 63805, 63806, 63807, + 63808, 63809, 63810, 63811, 63812, 63813, 63814, 63815, 63816, 63817, + 63818, 63819, 63820, 63821, 63822, 63823, 63824, 63825, 63826, 63827, + 63828, 63829, 63830, 63831, 63832, 63833, 63834, 63835, 63836, 63837, + 63838, 63839, 63840, 63841, 63842, 63843, 63844, 63845, 63846, 63847, + 63848, 63849, 63850, 63851, 63852, 63853, 63854, 63855, 63856, 63857, + 63858, 63859, 63860, 63861, 63862, 63863, 63864, 63865, 63866, 63867, + 63868, 63869, 63870, 63871, 63872, 63873, 63874, 63875, 63876, 63877, + 63878, 63879, 63880, 63881, 63882, 63883, 63884, 63885, 63886, 63887, + 63888, 63889, 63890, 63891, 63892, 63893, 63894, 63895, 63896, 63897, + 63898, 63899, 63900, 63901, 63902, 63903, 63904, 63905, 63906, 63907, + 63908, 63909, 63910, 63911, 63912, 63913, 63914, 63915, 63916, 63917, + 63918, 63919, 63920, 63921, 63922, 63923, 63924, 63925, 63926, 63927, + 63928, 63929, 63930, 63931, 63932, 63933, 63934, 63935, 63936, 63937, + 63938, 63939, 63940, 63941, 63942, 63943, 63944, 63945, 63946, 63947, + 63948, 63949, 63950, 63951, 63952, 63953, 63954, 63955, 63956, 63957, + 63958, 63959, 63960, 63961, 63962, 63963, 63964, 63965, 63966, 63967, + 63968, 63969, 63970, 63971, 63972, 63973, 63974, 63975, 63976, 63977, + 63978, 63979, 63980, 63981, 63982, 63983, 63984, 63985, 63986, 63987, + 63988, 63989, 63990, 63991, 63992, 63993, 63994, 63995, 63996, 63997, + 63998, 63999, 64000, 64001, 64002, 64003, 64004, 64005, 64006, 64007, + 64008, 64009, 64010, 64011, 64012, 64013, 64016, 64018, 64021, 64022, + 64023, 64024, 64025, 64026, 64027, 64028, 64029, 64030, 64032, 64034, + 64037, 64038, 64042, 64043, 64044, 64045, 64046, 64047, 64048, 64049, + 64050, 64051, 64052, 64053, 64054, 64055, 64056, 64057, 64058, 64059, + 64060, 64061, 64062, 64063, 64064, 64065, 64066, 64067, 64068, 64069, + 64070, 64071, 64072, 64073, 64074, 64075, 64076, 64077, 64078, 64079, + 64080, 64081, 64082, 64083, 64084, 64085, 64086, 64087, 64088, 64089, + 64090, 64091, 64092, 64093, 64094, 64095, 64096, 64097, 64098, 64099, + 64100, 64101, 64102, 64103, 64104, 64105, 64106, 64107, 64108, 64109, + 64112, 64113, 64114, 64115, 64116, 64117, 64118, 64119, 64120, 64121, + 64122, 64123, 64124, 64125, 64126, 64127, 64128, 64129, 64130, 64131, + 64132, 64133, 64134, 64135, 64136, 64137, 64138, 64139, 64140, 64141, + 64142, 64143, 64144, 64145, 64146, 64147, 64148, 64149, 64150, 64151, + 64152, 64153, 64154, 64155, 64156, 64157, 64158, 64159, 64160, 64161, + 64162, 64163, 64164, 64165, 64166, 64167, 64168, 64169, 64170, 64171, + 64172, 64173, 64174, 64175, 64176, 64177, 64178, 64179, 64180, 64181, + 64182, 64183, 64184, 64185, 64186, 64187, 64188, 64189, 64190, 64191, + 64192, 64193, 64194, 64195, 64196, 64197, 64198, 64199, 64200, 64201, + 64202, 64203, 64204, 64205, 64206, 64207, 64208, 64209, 64210, 64211, + 64212, 64213, 64214, 64215, 64216, 64217, 64285, 64287, 64298, 64299, + 64300, 64301, 64302, 64303, 64304, 64305, 64306, 64307, 64308, 64309, + 64310, 64312, 64313, 64314, 64315, 64316, 64318, 64320, 64321, 64323, + 64324, 64326, 64327, 64328, 64329, 64330, 64331, 64332, 64333, 64334, + 69785, 69786, 69787, 69788, 69797, 69803, 69818, 69927, 69934, 69935, + 69937, 69938, 119127, 119128, 119134, 119135, 119136, 119137, 119138, + 119139, 119140, 119141, 119150, 119151, 119152, 119153, 119154, + 119225, 119226, 119227, 119228, 119229, 119230, 119231, 119232, + 131362, 132380, 132389, 132427, 132666, 133124, 133342, 133676, + 133987, 136420, 136872, 136938, 137672, 138008, 138507, 138724, + 138726, 139651, 139679, 140081, 141012, 141380, 141386, 142092, + 142321, 143370, 144056, 144223, 144275, 144284, 144323, 144341, + 144493, 145059, 145575, 146061, 146170, 146620, 146718, 147153, + 147294, 147342, 148067, 148206, 148395, 149000, 149301, 149524, + 150582, 150674, 151457, 151480, 151620, 151794, 151795, 151833, + 151859, 152137, 152605, 153126, 153242, 153285, 153980, 154279, + 154539, 154752, 154832, 155526, 156122, 156200, 156231, 156377, + 156478, 156890, 156963, 157096, 157607, 157621, 158524, 158774, + 158933, 159083, 159532, 159665, 159954, 160714, 161383, 161966, + 162150, 162984, 163539, 163631, 165330, 165357, 165678, 166906, + 167287, 168261, 168415, 168474, 168970, 169110, 169398, 170800, + 172238, 172293, 172558, 172689, 172946, 173568, 194560, 194561, + 194562, 194563, 194564, 194565, 194566, 194567, 194568, 194569, + 194570, 194571, 194572, 194573, 194574, 194575, 194576, 194577, + 194578, 194579, 194580, 194581, 194582, 194583, 194584, 194585, + 194586, 194587, 194588, 194589, 194590, 194591, 194592, 194593, + 194594, 194595, 194596, 194597, 194598, 194599, 194600, 194601, + 194602, 194603, 194604, 194605, 194606, 194607, 194608, 194609, + 194610, 194611, 194612, 194613, 194614, 194615, 194616, 194617, + 194618, 194619, 194620, 194621, 194622, 194623, 194624, 194625, + 194626, 194627, 194628, 194629, 194630, 194631, 194632, 194633, + 194634, 194635, 194636, 194637, 194638, 194639, 194640, 194641, + 194642, 194643, 194644, 194645, 194646, 194647, 194648, 194649, + 194650, 194651, 194652, 194653, 194654, 194655, 194656, 194657, + 194658, 194659, 194660, 194661, 194662, 194663, 194664, 194665, + 194666, 194667, 194668, 194669, 194670, 194671, 194672, 194673, + 194674, 194675, 194676, 194677, 194678, 194679, 194680, 194681, + 194682, 194683, 194684, 194685, 194686, 194687, 194688, 194689, + 194690, 194691, 194692, 194693, 194694, 194695, 194696, 194697, + 194698, 194699, 194700, 194701, 194702, 194703, 194704, 194705, + 194706, 194707, 194708, 194709, 194710, 194711, 194712, 194713, + 194714, 194715, 194716, 194717, 194718, 194719, 194720, 194721, + 194722, 194723, 194724, 194725, 194726, 194727, 194728, 194729, + 194730, 194731, 194732, 194733, 194734, 194735, 194736, 194737, + 194738, 194739, 194740, 194741, 194742, 194743, 194744, 194745, + 194746, 194747, 194748, 194749, 194750, 194751, 194752, 194753, + 194754, 194755, 194756, 194757, 194758, 194759, 194760, 194761, + 194762, 194763, 194764, 194765, 194766, 194767, 194768, 194769, + 194770, 194771, 194772, 194773, 194774, 194775, 194776, 194777, + 194778, 194779, 194780, 194781, 194782, 194783, 194784, 194785, + 194786, 194787, 194788, 194789, 194790, 194791, 194792, 194793, + 194794, 194795, 194796, 194797, 194798, 194799, 194800, 194801, + 194802, 194803, 194804, 194805, 194806, 194807, 194808, 194809, + 194810, 194811, 194812, 194813, 194814, 194815, 194816, 194817, + 194818, 194819, 194820, 194821, 194822, 194823, 194824, 194825, + 194826, 194827, 194828, 194829, 194830, 194831, 194832, 194833, + 194834, 194835, 194836, 194837, 194838, 194839, 194840, 194841, + 194842, 194843, 194844, 194845, 194846, 194847, 194848, 194849, + 194850, 194851, 194852, 194853, 194854, 194855, 194856, 194857, + 194858, 194859, 194860, 194861, 194862, 194863, 194864, 194865, + 194866, 194867, 194868, 194869, 194870, 194871, 194872, 194873, + 194874, 194875, 194876, 194877, 194878, 194879, 194880, 194881, + 194882, 194883, 194884, 194885, 194886, 194887, 194888, 194889, + 194890, 194891, 194892, 194893, 194894, 194895, 194896, 194897, + 194898, 194899, 194900, 194901, 194902, 194903, 194904, 194905, + 194906, 194907, 194908, 194909, 194910, 194911, 194912, 194913, + 194914, 194915, 194916, 194917, 194918, 194919, 194920, 194921, + 194922, 194923, 194924, 194925, 194926, 194927, 194928, 194929, + 194930, 194931, 194932, 194933, 194934, 194935, 194936, 194937, + 194938, 194939, 194940, 194941, 194942, 194943, 194944, 194945, + 194946, 194947, 194948, 194949, 194950, 194951, 194952, 194953, + 194954, 194955, 194956, 194957, 194958, 194959, 194960, 194961, + 194962, 194963, 194964, 194965, 194966, 194967, 194968, 194969, + 194970, 194971, 194972, 194973, 194974, 194975, 194976, 194977, + 194978, 194979, 194980, 194981, 194982, 194983, 194984, 194985, + 194986, 194987, 194988, 194989, 194990, 194991, 194992, 194993, + 194994, 194995, 194996, 194997, 194998, 194999, 195000, 195001, + 195002, 195003, 195004, 195005, 195006, 195007, 195008, 195009, + 195010, 195011, 195012, 195013, 195014, 195015, 195016, 195017, + 195018, 195019, 195020, 195021, 195022, 195023, 195024, 195025, + 195026, 195027, 195028, 195029, 195030, 195031, 195032, 195033, + 195034, 195035, 195036, 195037, 195038, 195039, 195040, 195041, + 195042, 195043, 195044, 195045, 195046, 195047, 195048, 195049, + 195050, 195051, 195052, 195053, 195054, 195055, 195056, 195057, + 195058, 195059, 195060, 195061, 195062, 195063, 195064, 195065, + 195066, 195067, 195068, 195069, 195070, 195071, 195072, 195073, + 195074, 195075, 195076, 195077, 195078, 195079, 195080, 195081, + 195082, 195083, 195084, 195085, 195086, 195087, 195088, 195089, + 195090, 195091, 195092, 195093, 195094, 195095, 195096, 195097, + 195098, 195099, 195100, 195101 +}; + +static const uint16_t comp_seq[] = { + 33432, 663, 33114, 1208, 33114, 1202, 33114, 1209, 319, 59, 322, 62, + 330, 230, 331, 273, 325, 303, 341, 120, 332, 275, 327, 845, 324, 118, + 338, 688, 321, 61, 336, 843, 326, 63, 320, 60, 323, 116, 33096, 64, + 345, 694, 325, 690, 33104, 692, 330, 128, 320, 122, 340, 66, 325, 126, + 33089, 124, 330, 130, 340, 704, 325, 698, 342, 706, 345, 702, 33104, + 700, 336, 867, 341, 138, 332, 279, 342, 712, 330, 140, 326, 70, 321, + 69, 324, 134, 322, 871, 344, 714, 323, 132, 331, 277, 325, 136, 319, + 67, 340, 305, 320, 68, 33095, 869, 34077, 1308, 321, 142, 330, 252, + 324, 144, 320, 263, 340, 148, 323, 720, 33093, 146, 336, 724, 330, + 301, 326, 726, 340, 728, 321, 150, 325, 722, 33111, 730, 330, 232, + 323, 154, 332, 283, 320, 72, 327, 883, 336, 885, 319, 71, 322, 152, + 331, 281, 324, 156, 321, 73, 325, 160, 326, 74, 344, 732, 33109, 158, + 33089, 161, 336, 738, 320, 736, 345, 740, 330, 254, 33108, 163, 336, + 742, 340, 167, 345, 746, 342, 748, 330, 169, 33088, 165, 34077, 1266, + 320, 171, 330, 175, 319, 265, 325, 756, 340, 173, 336, 758, 322, 75, + 342, 762, 33113, 760, 335, 225, 325, 311, 327, 889, 331, 285, 326, 80, + 323, 177, 321, 78, 341, 256, 319, 76, 320, 77, 330, 234, 336, 887, + 322, 79, 332, 287, 324, 179, 33097, 181, 320, 772, 33093, 774, 34077, + 1270, 345, 782, 325, 776, 330, 187, 340, 185, 331, 289, 336, 778, 320, + 183, 33100, 291, 325, 784, 321, 191, 330, 195, 320, 189, 340, 193, + 339, 297, 33104, 786, 342, 800, 330, 199, 325, 794, 339, 299, 345, + 798, 340, 197, 33104, 796, 323, 203, 320, 83, 337, 802, 344, 804, 329, + 209, 330, 236, 322, 201, 331, 293, 321, 84, 328, 207, 332, 295, 341, + 211, 326, 85, 335, 227, 324, 205, 319, 82, 336, 911, 327, 913, 33110, + 806, 336, 814, 33090, 812, 319, 816, 325, 822, 321, 213, 336, 824, + 326, 820, 33088, 818, 326, 828, 33093, 826, 325, 830, 326, 217, 327, + 929, 336, 927, 319, 925, 321, 215, 323, 315, 320, 86, 33090, 931, 320, + 218, 325, 220, 345, 836, 336, 834, 330, 222, 33089, 832, 34077, 1280, + 34077, 1282, 34077, 1284, 327, 846, 330, 231, 323, 117, 336, 844, 325, + 304, 331, 274, 324, 119, 319, 87, 332, 276, 321, 89, 338, 689, 326, + 91, 341, 121, 320, 88, 322, 90, 33096, 92, 336, 693, 345, 695, 33093, + 691, 325, 127, 340, 94, 321, 125, 320, 123, 33098, 129, 336, 701, 342, + 707, 340, 705, 325, 699, 345, 703, 33098, 131, 336, 868, 323, 133, + 330, 141, 332, 280, 342, 713, 326, 98, 324, 135, 321, 97, 319, 95, + 344, 715, 327, 870, 320, 96, 322, 872, 331, 278, 325, 137, 340, 306, + 33109, 139, 34077, 1290, 321, 143, 325, 147, 330, 253, 324, 145, 340, + 149, 323, 721, 33088, 264, 325, 723, 330, 302, 345, 838, 326, 727, + 321, 151, 340, 729, 336, 725, 33111, 731, 331, 282, 320, 100, 332, + 284, 327, 884, 336, 886, 322, 153, 326, 102, 324, 157, 330, 233, 341, + 159, 319, 99, 344, 733, 323, 155, 33089, 101, 330, 262, 33089, 162, + 345, 741, 330, 255, 320, 737, 340, 164, 33104, 739, 336, 743, 330, + 170, 340, 168, 345, 747, 342, 749, 33088, 166, 336, 755, 325, 753, + 33088, 751, 345, 761, 319, 266, 340, 174, 320, 172, 325, 757, 336, + 759, 342, 763, 330, 176, 33090, 103, 330, 235, 321, 106, 336, 888, + 326, 108, 341, 257, 327, 890, 325, 312, 319, 104, 322, 107, 323, 178, + 331, 286, 320, 105, 329, 182, 324, 180, 332, 288, 33103, 226, 325, + 775, 33088, 773, 1310, 1298, 34077, 1297, 330, 196, 336, 787, 325, + 785, 320, 190, 339, 298, 340, 194, 33089, 192, 326, 839, 336, 797, + 330, 200, 342, 801, 339, 300, 325, 795, 345, 799, 33108, 198, 335, + 228, 329, 210, 320, 111, 337, 803, 319, 110, 331, 294, 326, 113, 342, + 807, 341, 212, 322, 202, 344, 805, 324, 206, 332, 296, 330, 237, 327, + 914, 321, 112, 323, 204, 336, 912, 33096, 208, 322, 813, 33104, 815, + 320, 819, 321, 214, 325, 823, 328, 840, 336, 825, 326, 821, 33087, + 817, 1310, 1304, 34077, 1303, 325, 831, 323, 316, 319, 926, 326, 115, + 336, 928, 321, 216, 328, 841, 320, 114, 327, 930, 33090, 932, 345, + 837, 336, 835, 325, 221, 321, 833, 330, 223, 33088, 219, 1309, 1306, + 34078, 1307, 35430, 2657, 35430, 2659, 34077, 1312, 35430, 2661, + 34077, 1363, 319, 1149, 349, 1109, 33088, 355, 34077, 1315, 34077, + 1317, 34077, 1319, 34077, 1321, 34077, 1323, 34077, 1325, 34077, 1327, + 34077, 1329, 34077, 1331, 34077, 1333, 34077, 1335, 34077, 1337, 327, + 851, 322, 853, 320, 847, 33087, 849, 33091, 246, 33088, 267, 34077, + 1341, 33088, 696, 34077, 1343, 322, 879, 319, 875, 320, 873, 33095, + 877, 1310, 1346, 34077, 1345, 1310, 1349, 34077, 1348, 327, 895, 322, + 897, 319, 893, 33088, 891, 1309, 1351, 34078, 1352, 33091, 307, 1310, + 1355, 34077, 1354, 1309, 1357, 34078, 1358, 319, 244, 330, 242, 320, + 240, 33091, 238, 327, 852, 319, 850, 322, 854, 33088, 848, 33091, 247, + 33088, 268, 323, 251, 33088, 270, 33088, 697, 320, 874, 327, 878, 322, + 880, 33087, 876, 33088, 735, 34077, 1365, 34077, 1366, 34077, 1367, + 319, 894, 320, 892, 322, 898, 33095, 896, 320, 765, 326, 767, 33091, + 310, 33091, 308, 33088, 272, 320, 241, 323, 239, 319, 245, 33098, 243, + 34077, 1369, 320, 857, 319, 859, 322, 863, 33095, 861, 320, 858, 327, + 862, 322, 864, 33087, 860, 319, 708, 33088, 710, 320, 711, 33087, 709, + 33310, 535, 33310, 539, 35431, 2664, 35431, 2665, 33310, 541, 319, + 768, 33088, 770, 320, 771, 33087, 769, 33093, 788, 33093, 789, 33093, + 790, 33093, 791, 33088, 808, 33088, 809, 33094, 810, 33094, 811, + 33093, 842, 33114, 1174, 33114, 1175, 33114, 1176, 322, 907, 336, 909, + 327, 905, 319, 903, 33088, 901, 319, 904, 336, 910, 327, 906, 320, + 902, 33090, 908, 33093, 718, 320, 915, 319, 917, 327, 919, 322, 921, + 33104, 923, 319, 918, 336, 924, 320, 916, 327, 920, 33090, 922, 33098, + 260, 34077, 1264, 559, 558, 33323, 557, 336, 754, 325, 752, 33088, + 750, 33114, 1177, 33114, 1179, 33114, 1178, 34077, 1268, 33091, 258, + 33091, 259, 34077, 1272, 34077, 1274, 33114, 1184, 33114, 1186, 34077, + 1276, 34077, 1278, 33114, 1190, 33114, 1192, 33091, 248, 33091, 249, + 33092, 716, 33092, 717, 33091, 313, 33091, 314, 33114, 1194, 33114, + 1196, 33114, 1198, 34077, 1286, 33114, 1200, 33114, 1207, 34077, 1288, + 33114, 1204, 33114, 1210, 33114, 1211, 34077, 1292, 33114, 1214, + 33114, 1215, 33114, 1218, 33114, 1219, 33114, 1224, 33114, 1225, + 33114, 1248, 33114, 1249, 33114, 1228, 33114, 1229, 33114, 1232, + 33114, 1233, 33114, 1250, 33098, 261, 1310, 1295, 34077, 1294, 33114, + 1240, 33114, 1241, 33114, 1242, 33114, 1243, 332, 292, 330, 188, 345, + 783, 340, 186, 325, 777, 336, 779, 331, 290, 33088, 184, 33114, 1252, + 33114, 1253, 33114, 1254, 33114, 1255, 1309, 1300, 34078, 1301, 326, + 829, 33093, 827, 33445, 666, 33445, 668, 33445, 670, 33445, 672, + 33445, 674, 33445, 676, 33445, 679, 33445, 681, 33445, 684, 33445, + 685, 33445, 687, 585, 583, 584, 581, 33347, 582, 319, 1104, 323, 1103, + 324, 1102, 334, 942, 352, 1106, 320, 356, 33101, 941, 33364, 589, 320, + 358, 319, 1115, 334, 956, 33101, 955, 352, 1119, 334, 970, 320, 359, + 319, 1117, 33101, 969, 319, 1131, 326, 373, 333, 985, 323, 1130, 324, + 1129, 320, 360, 33102, 986, 319, 1157, 334, 1000, 320, 361, 33101, + 999, 33102, 1148, 324, 1144, 326, 374, 320, 362, 319, 1146, 334, 1013, + 33091, 1145, 352, 1161, 334, 1026, 319, 1159, 320, 363, 33101, 1025, + 33120, 1099, 33120, 1112, 320, 375, 334, 934, 323, 1096, 352, 1098, + 349, 1100, 333, 933, 324, 1095, 33087, 1033, 320, 376, 334, 950, 319, + 1035, 33101, 949, 319, 1037, 334, 962, 320, 377, 333, 961, 352, 1111, + 33117, 1113, 333, 977, 323, 1124, 326, 388, 320, 378, 349, 1127, 334, + 978, 324, 1123, 33087, 1039, 319, 1041, 334, 994, 320, 390, 33101, + 993, 333, 1140, 33102, 1141, 319, 1043, 333, 1005, 320, 391, 326, 389, + 324, 1136, 334, 1006, 323, 1137, 33117, 1142, 590, 593, 33364, 595, + 33358, 594, 320, 392, 352, 1153, 349, 1155, 333, 1017, 319, 1045, + 33102, 1018, 320, 364, 319, 1125, 33117, 1128, 320, 379, 319, 1138, + 33117, 1143, 33120, 1154, 326, 395, 33088, 394, 33093, 719, 33094, + 400, 324, 444, 33094, 446, 33088, 398, 319, 396, 324, 448, 33094, 397, + 326, 454, 33092, 442, 33094, 456, 324, 410, 319, 402, 326, 460, 33091, + 458, 33088, 401, 33094, 462, 326, 472, 323, 470, 324, 403, 33097, 474, + 33094, 476, 33094, 478, 33094, 468, 324, 445, 33094, 447, 33088, 432, + 319, 430, 324, 449, 33094, 431, 326, 455, 33092, 443, 33094, 457, 324, + 423, 326, 461, 323, 459, 33087, 436, 33088, 435, 33094, 463, 323, 471, + 329, 475, 324, 437, 33094, 473, 33367, 598, 33094, 477, 33094, 479, + 33094, 469, 33094, 434, 33099, 440, 33099, 441, 33120, 1092, 34077, + 1339, 320, 269, 33091, 250, 33376, 601, 609, 605, 602, 606, 33376, + 604, 33376, 607, 33094, 452, 33094, 453, 33088, 734, 33094, 466, + 33094, 467, 323, 309, 320, 764, 33094, 766, 33088, 271, 610, 613, + 33384, 615, 33378, 614, 34077, 1364, 624, 623, 617, 620, 33386, 621, + 33385, 622, 521, 514, 520, 512, 33287, 511, 33091, 744, 33091, 745, + 33288, 513, 33288, 515, 33091, 780, 33091, 781, 33114, 1188, 33093, + 792, 33093, 793, 324, 865, 33089, 855, 324, 866, 33089, 856, 33089, + 881, 33089, 882, 33288, 524, 33089, 899, 33089, 900, 33288, 526, + 33288, 522, 320, 937, 319, 935, 352, 1047, 33117, 939, 320, 938, 319, + 936, 352, 1048, 33117, 940, 33120, 1049, 33120, 1050, 33120, 1051, + 33120, 1052, 33120, 1053, 33120, 1054, 349, 947, 319, 943, 320, 945, + 33120, 1055, 320, 946, 319, 944, 352, 1056, 33117, 948, 33120, 1057, + 33120, 1058, 33120, 1059, 33120, 1060, 33120, 1061, 33120, 1062, 320, + 953, 33087, 951, 319, 952, 33088, 954, 320, 959, 33087, 957, 319, 958, + 33088, 960, 319, 963, 320, 965, 349, 967, 33120, 1063, 352, 1064, 319, + 964, 320, 966, 33117, 968, 33120, 1065, 33120, 1066, 33120, 1067, + 33120, 1068, 33120, 1069, 33120, 1070, 352, 1071, 320, 973, 319, 971, + 33117, 975, 320, 974, 319, 972, 352, 1072, 33117, 976, 33120, 1073, + 33120, 1074, 33120, 1075, 33120, 1076, 33120, 1077, 33120, 1078, 319, + 979, 320, 981, 33117, 983, 320, 982, 319, 980, 33117, 984, 319, 987, + 320, 989, 33117, 991, 320, 990, 319, 988, 33117, 992, 320, 997, 33087, + 995, 319, 996, 33088, 998, 320, 1003, 33087, 1001, 319, 1002, 33088, + 1004, 319, 1007, 320, 1009, 33117, 1011, 320, 1010, 319, 1008, 33117, + 1012, 320, 1015, 319, 1014, 33117, 1016, 349, 1023, 319, 1019, 352, + 1079, 33088, 1021, 320, 1022, 319, 1020, 352, 1080, 33117, 1024, + 33120, 1081, 33120, 1082, 33120, 1083, 33120, 1084, 33120, 1085, + 33120, 1086, 352, 1087, 320, 1029, 319, 1027, 33117, 1031, 352, 1088, + 319, 1028, 320, 1030, 33117, 1032, 33120, 1089, 33120, 1090, 33120, + 1091, 33114, 1251, 33120, 1093, 33120, 1094, 33120, 1097, 33120, 1110, + 33120, 1152, 33120, 1101, 320, 1121, 319, 1120, 33117, 1122, 33120, + 1114, 33120, 1156, 319, 1133, 320, 1134, 33117, 1135 +}; + +static const uint16_t decomp_seq[] = { + 0, 1166, 1167, 2783, 2784, 1989, 2075, 2064, 5, 319, 5, 320, 5, 321, + 5, 322, 5, 326, 5, 328, 7, 340, 9, 319, 9, 320, 9, 321, 9, 326, 13, + 319, 13, 320, 13, 321, 13, 326, 18, 322, 19, 319, 19, 320, 19, 321, + 19, 322, 19, 326, 24, 319, 24, 320, 24, 321, 24, 326, 28, 320, 31, + 319, 31, 320, 31, 321, 31, 322, 31, 326, 31, 328, 33, 340, 35, 319, + 35, 320, 35, 321, 35, 326, 39, 319, 39, 320, 39, 321, 39, 326, 44, + 322, 45, 319, 45, 320, 45, 321, 45, 322, 45, 326, 50, 319, 50, 320, + 50, 321, 50, 326, 54, 320, 54, 326, 5, 323, 31, 323, 5, 324, 31, 324, + 5, 341, 31, 341, 7, 320, 33, 320, 7, 321, 33, 321, 7, 325, 33, 325, 7, + 330, 33, 330, 8, 330, 34, 330, 9, 323, 35, 323, 9, 324, 35, 324, 9, + 325, 35, 325, 9, 341, 35, 341, 9, 330, 35, 330, 11, 321, 37, 321, 11, + 324, 37, 324, 11, 325, 37, 325, 11, 340, 37, 340, 12, 321, 38, 321, + 372, 13, 322, 39, 322, 13, 323, 39, 323, 13, 324, 39, 324, 13, 341, + 39, 341, 13, 325, 14, 321, 40, 321, 15, 340, 41, 340, 16, 320, 42, + 320, 16, 340, 42, 340, 16, 330, 42, 330, 18, 320, 44, 320, 18, 340, + 44, 340, 18, 330, 44, 330, 19, 323, 45, 323, 19, 324, 45, 324, 19, + 329, 45, 329, 21, 320, 47, 320, 21, 340, 47, 340, 21, 330, 47, 330, + 22, 320, 48, 320, 22, 321, 48, 321, 22, 340, 48, 340, 22, 330, 48, + 330, 23, 340, 49, 340, 23, 330, 49, 330, 24, 322, 50, 322, 24, 323, + 50, 323, 24, 324, 50, 324, 24, 328, 50, 328, 24, 329, 50, 329, 24, + 341, 50, 341, 26, 321, 52, 321, 28, 321, 54, 321, 28, 326, 29, 320, + 55, 320, 29, 325, 55, 325, 29, 330, 55, 330, 1171, 346, 1172, 346, 19, + 335, 45, 335, 1173, 346, 24, 335, 50, 335, 2000, 5, 330, 31, 330, 13, + 330, 39, 330, 19, 330, 45, 330, 24, 330, 50, 330, 24, 326, 323, 50, + 326, 323, 24, 326, 320, 50, 326, 320, 24, 326, 330, 50, 326, 330, 24, + 326, 319, 50, 326, 319, 5, 326, 323, 31, 326, 323, 5, 325, 323, 31, + 325, 323, 65, 323, 93, 323, 11, 330, 37, 330, 15, 330, 41, 330, 19, + 341, 45, 341, 19, 341, 323, 45, 341, 323, 229, 330, 317, 330, 40, 330, + 11, 320, 37, 320, 18, 319, 44, 319, 5, 328, 320, 31, 328, 320, 65, + 320, 93, 320, 81, 320, 109, 320, 5, 331, 31, 331, 5, 332, 31, 332, 9, + 331, 35, 331, 9, 332, 35, 332, 13, 331, 39, 331, 13, 332, 39, 332, 19, + 331, 45, 331, 19, 332, 45, 332, 21, 331, 47, 331, 21, 332, 47, 332, + 24, 331, 50, 331, 24, 332, 50, 332, 22, 339, 48, 339, 23, 339, 49, + 339, 12, 330, 38, 330, 1189, 346, 1191, 346, 9, 340, 35, 340, 19, 326, + 323, 45, 326, 323, 19, 322, 323, 45, 322, 323, 19, 325, 45, 325, 19, + 325, 323, 45, 325, 323, 28, 323, 54, 323, 1193, 346, 1195, 346, 1197, + 346, 1199, 346, 3, 346, 1203, 346, 1201, 346, 2, 346, 4, 346, 1205, + 346, 1206, 346, 1212, 346, 1213, 346, 1216, 346, 1217, 346, 1220, 346, + 1221, 346, 1226, 346, 1227, 346, 1230, 346, 1231, 346, 1993, 1236, + 346, 1237, 346, 1238, 346, 1239, 346, 2790, 1222, 346, 1223, 346, + 1234, 346, 1235, 346, 1244, 346, 1245, 346, 1246, 346, 1247, 346, + 1260, 1261, 333, 498, 484, 318, 1, 501, 484, 56, 320, 365, 320, 58, + 366, 320, 367, 320, 368, 320, 369, 320, 371, 320, 372, 320, 383, 326, + 320, 503, 484, 368, 326, 371, 326, 380, 320, 381, 320, 382, 320, 383, + 320, 386, 326, 320, 384, 320, 386, 320, 387, 320, 1418, 393, 320, 393, + 326, 406, 319, 406, 326, 405, 320, 399, 326, 411, 320, 409, 319, 413, + 324, 409, 324, 1982, 422, 324, 419, 319, 419, 326, 418, 320, 433, 326, + 424, 320, 422, 319, 426, 324, 1419, 438, 331, 439, 331, 1990, 407, + 324, 420, 324, 404, 324, 417, 324, 404, 326, 417, 326, 406, 324, 419, + 324, 450, 326, 451, 326, 407, 326, 420, 326, 408, 326, 421, 326, 409, + 323, 422, 323, 409, 326, 422, 326, 412, 326, 425, 326, 464, 326, 465, + 326, 416, 326, 429, 326, 413, 323, 426, 323, 413, 326, 426, 326, 413, + 329, 426, 329, 414, 326, 427, 326, 415, 326, 428, 326, 1977, 516, 519, + 516, 520, 517, 520, 516, 521, 518, 520, 1420, 527, 520, 523, 520, 525, + 520, 1992, 534, 542, 538, 542, 540, 542, 528, 542, 529, 542, 530, 542, + 531, 542, 532, 542, 533, 542, 536, 542, 537, 542, 556, 555, 556, 559, + 551, 554, 552, 554, 553, 554, 567, 571, 570, 571, 2776, 563, 571, 564, + 571, 565, 571, 566, 571, 1180, 346, 1182, 346, 1181, 346, 1259, 346, + 580, 584, 580, 579, 580, 585, 576, 578, 577, 578, 588, 596, 591, 590, + 592, 590, 591, 596, 1183, 346, 1185, 346, 597, 599, 1187, 346, 600, + 608, 603, 608, 603, 609, 603, 602, 603, 602, 608, 611, 610, 612, 610, + 611, 616, 619, 617, 619, 618, 619, 618, 617, 619, 624, 626, 660, 628, + 660, 630, 660, 632, 660, 634, 660, 625, 659, 637, 638, 637, 640, 657, + 644, 658, 644, 637, 644, 647, 660, 649, 660, 651, 660, 653, 660, 655, + 660, 646, 659, 1892, 1895, 1406, 662, 664, 1897, 1263, 1309, 1265, + 1309, 1267, 1309, 1269, 1309, 1271, 1309, 1273, 1309, 1275, 1309, + 1277, 1309, 1279, 1309, 1281, 1309, 1283, 1309, 1285, 1309, 1287, + 1309, 1289, 1309, 1291, 1309, 1293, 1309, 1293, 1310, 1296, 1309, + 1296, 1310, 1299, 1309, 1299, 1310, 1302, 1309, 1302, 1310, 1305, + 1309, 1305, 1310, 1262, 1309, 2753, 2656, 2662, 2658, 2662, 1311, + 1309, 2660, 2662, 1314, 1309, 1316, 1309, 1318, 1309, 1320, 1309, + 1322, 1309, 1324, 1309, 1326, 1309, 1328, 1309, 1330, 1309, 1332, + 1309, 1334, 1309, 1336, 1309, 1338, 1309, 1340, 1309, 1342, 1309, + 1344, 1309, 1344, 1310, 1347, 1309, 1347, 1310, 1350, 1309, 1350, + 1310, 1353, 1309, 1353, 1310, 1356, 1309, 1356, 1310, 1903, 1313, + 1309, 1359, 1309, 1360, 1309, 1361, 1309, 1362, 1309, 1368, 1309, + 1407, 2666, 2663, 2667, 2663, 1906, 2668, 2677, 2669, 2677, 2669, + 2677, 2678, 2669, 2677, 2679, 2669, 2677, 2680, 2669, 2677, 2681, + 2669, 2677, 2682, 1907, 1408, 2756, 2683, 2677, 2684, 2677, 2683, + 2677, 2678, 2684, 2677, 2678, 2683, 2677, 2679, 2684, 2677, 2679, + 1913, 1409, 1917, 1915, 1918, 2758, 1923, 1898, 1410, 1926, 1928, + 1932, 1411, 1899, 2760, 2761, 1412, 2762, 1936, 2763, 1938, 1941, + 1943, 2764, 2754, 2765, 1945, 2766, 1947, 2718, 1413, 1951, 1952, + 1415, 1953, 1588, 2767, 2768, 2719, 2720, 1773, 1777, 1774, 1775, + 1778, 2794, 1957, 1779, 2729, 1772, 1785, 1786, 1958, 1394, 1790, + 1789, 2730, 1783, 2067, 1796, 2731, 2732, 1797, 1802, 1416, 1801, + 1800, 1395, 1803, 1806, 1963, 1805, 1808, 2693, 1811, 2755, 2733, + 1962, 1814, 2735, 1819, 1821, 1822, 1964, 2736, 1824, 1825, 2737, + 2738, 1500, 1831, 1833, 1396, 1834, 1397, 1965, 1840, 1841, 1843, + 1844, 1966, 1847, 1398, 1849, 2739, 1851, 1967, 2740, 1854, 2709, + 1856, 2741, 1969, 2742, 2743, 1399, 1971, 1400, 1864, 2769, 2745, + 2744, 2746, 2747, 1866, 1968, 1867, 1869, 1402, 1870, 1970, 1403, + 1404, 2749, 1872, 1874, 1975, 1877, 1405, 2750, 1885, 2751, 1976, + 2752, 1442, 1440, 1443, 2691, 1450, 1454, 1455, 1457, 1459, 1460, + 1463, 1461, 1370, 2695, 1466, 1467, 1468, 1473, 2692, 1371, 1469, + 1475, 2694, 1478, 1479, 1448, 1480, 1481, 2789, 1487, 1488, 1373, + 1493, 1494, 1495, 1496, 1374, 1501, 1502, 1505, 1507, 1508, 1509, + 1510, 1512, 1513, 1514, 1515, 1517, 1518, 2698, 1804, 1520, 1521, + 2699, 1523, 1524, 1525, 1532, 1528, 1530, 1531, 1533, 1535, 1536, + 1537, 1539, 1540, 1542, 1544, 1545, 1547, 1554, 1549, 1555, 1550, + 1552, 1489, 1570, 1557, 1558, 1559, 1556, 1561, 1560, 1566, 2700, + 1571, 1572, 1573, 1574, 1575, 1580, 2701, 2702, 1583, 1584, 1585, + 1582, 1587, 1375, 1376, 1589, 1591, 2703, 1593, 1594, 1595, 1597, + 2704, 1598, 1599, 1637, 1600, 1377, 1602, 1606, 1608, 1607, 2706, + 1610, 2707, 1613, 1612, 1614, 1617, 1618, 1378, 1619, 1620, 1621, + 1622, 1379, 2708, 1380, 1625, 1626, 1627, 1629, 2799, 1634, 2710, + 1636, 1381, 2717, 2759, 1638, 1640, 1382, 1642, 1645, 1646, 1648, + 1652, 1384, 1383, 1653, 2711, 1654, 1659, 1660, 1661, 1664, 1665, + 1669, 1667, 1668, 1670, 1671, 1672, 1674, 1675, 1678, 1679, 1683, + 1687, 2714, 1686, 1684, 1688, 1690, 1695, 2715, 1697, 1694, 1692, + 1385, 1699, 1701, 1703, 1700, 1386, 1705, 1707, 2716, 1712, 1722, + 1714, 1389, 1717, 1388, 1387, 1476, 1477, 1723, 1718, 1950, 1414, + 1724, 1725, 1726, 1730, 1728, 2721, 1390, 1735, 1732, 1738, 1740, + 2723, 1741, 1737, 1743, 1391, 1744, 1745, 1746, 1749, 2724, 1751, + 1392, 1753, 2725, 1754, 1393, 1755, 1758, 1760, 1761, 2726, 2705, + 2727, 1762, 2728, 1765, 1767, 1763, 1769, 2046, 1721, 2060, 2051, + 1791, 1439, 1522, 2161, 1578, 2087, 1541, 1577, 1860, 1937, 1999, + 2012, 2024, 2074, 1747, 1770, 1810, 1836, 1985, 2082, 2135, 1444, + 1516, 1752, 1818, 1998, 2146, 1611, 1798, 1994, 2028, 1680, 1954, + 2015, 1776, 1828, 2076, 1452, 1482, 1504, 1704, 1750, 1817, 1863, + 1942, 1996, 2001, 2058, 2117, 2139, 2145, 1889, 1924, 1978, 2094, + 2147, 2037, 1569, 1635, 1909, 1948, 1823, 1876, 2050, 2115, 1568, + 1603, 1748, 1781, 1793, 1921, 1930, 2102, 1503, 1949, 1485, 1484, + 1896, 1925, 1984, 2104, 2044, 1681, 2040, 1441, 1649, 1832, 1878, + 1456, 1643, 1437, 1766, 1708, 1920, 1519, 1564, 1865, 1986, 2033, + 2068, 1764, 1685, 1691, 1853, 1446, 1471, 1483, 1739, 1916, 1960, + 2036, 2086, 1506, 1529, 1581, 1633, 1710, 1799, 1879, 2099, 2137, + 2148, 2151, 1498, 1720, 1756, 2066, 1623, 1666, 1673, 1702, 1795, + 1812, 1845, 1894, 1927, 1946, 2062, 1988, 2070, 2095, 1490, 1499, + 1534, 1809, 2019, 1628, 1647, 1689, 1759, 1908, 1830, 1449, 1553, + 1616, 1650, 1835, 1842, 1939, 1944, 2088, 2114, 2118, 2124, 1453, + 1893, 2084, 2110, 1656, 1445, 1462, 1596, 1601, 1709, 1815, 1859, + 1991, 2073, 2159, 1716, 2101, 1497, 1731, 1734, 1787, 1838, 1852, + 1873, 1919, 2127, 1472, 1676, 2105, 1458, 1609, 1782, 2063, 1641, + 1658, 1736, 2107, 1491, 1526, 1605, 1713, 1727, 1742, 1768, 1837, + 1855, 1935, 2020, 2023, 2085, 2112, 1511, 1788, 1527, 1816, 1846, + 1995, 2108, 2141, 2149, 1733, 1780, 1955, 1902, 1904, 1911, 1827, + 1807, 2043, 1447, 1972, 1492, 1624, 1682, 1914, 1592, 1771, 1719, + 2065, 2016, 2103, 2030, 1631, 1464, 1546, 1434, 2773, 1563, 1435, + 1715, 2797, 2798, 1486, 1829, 1861, 1880, 1887, 1888, 2119, 1912, + 1940, 1997, 2774, 2039, 2071, 2079, 2775, 2129, 2130, 2131, 2144, + 2077, 2109, 1543, 1551, 1562, 1565, 1604, 1663, 1711, 1784, 1794, + 1813, 1820, 1839, 1875, 1881, 1883, 1882, 1884, 1886, 1890, 1891, + 1900, 1905, 1929, 1931, 1934, 1956, 1961, 1987, 2026, 2031, 2041, + 2042, 2052, 2053, 2069, 2113, 2122, 2126, 1651, 2734, 1959, 2009, + 1438, 1470, 1451, 1465, 1474, 1538, 1548, 1567, 1576, 1579, 1586, + 1590, 1630, 1632, 1639, 1644, 1655, 1657, 1662, 1677, 1693, 1696, + 1698, 1706, 1729, 1757, 1792, 1871, 1826, 1848, 1850, 1857, 1858, + 1862, 1868, 1901, 1910, 1922, 1933, 1973, 1983, 2010, 2027, 2029, + 2034, 2035, 2038, 2045, 2072, 2083, 2090, 2106, 2120, 2123, 2138, + 2713, 2712, 2722, 1401, 2748, 2757, 2781, 2158, 2160, 2032, 2047, + 2780, 2048, 2049, 2054, 665, 677, 667, 677, 2002, 669, 677, 2055, 671, + 677, 673, 677, 2782, 675, 677, 2696, 496, 480, 510, 481, 2056, 2003, + 2059, 508, 486, 508, 487, 508, 484, 486, 508, 484, 487, 488, 481, 488, + 482, 488, 484, 489, 484, 490, 484, 491, 484, 492, 484, 493, 484, 494, + 484, 495, 484, 496, 484, 497, 484, 678, 677, 499, 484, 680, 677, 500, + 484, 682, 677, 683, 677, 686, 677, 504, 484, 2005, 505, 484, 506, 484, + 507, 484, 509, 484, 493, 483, 489, 485, 498, 485, 504, 485, 2078, + 2080, 2785, 2004, 2081, 2089, 2092, 2093, 2091, 2007, 2096, 2097, + 2786, 2098, 1426, 1974, 2006, 2100, 2787, 1427, 2771, 2111, 1615, + 2116, 2788, 2772, 1428, 1429, 2008, 2121, 2791, 1430, 2792, 2125, + 2793, 2128, 1431, 2011, 2132, 2133, 2134, 2136, 1432, 1979, 1421, + 2061, 2140, 2142, 1433, 2013, 2143, 2795, 2796, 2014, 2150, 1436, + 2152, 1422, 2153, 2154, 2155, 2156, 2157, 2017, 2800, 1980, 2018, + 2777, 2697, 2021, 2022, 1423, 1981, 2025, 1372, 2778, 2057, 2779, + 1424, 2770, 1425, 5, 338, 31, 338, 6, 325, 32, 325, 6, 336, 32, 336, + 6, 345, 32, 345, 7, 340, 320, 33, 340, 320, 8, 325, 34, 325, 8, 336, + 34, 336, 8, 345, 34, 345, 8, 340, 34, 340, 8, 342, 34, 342, 9, 323, + 319, 35, 323, 319, 9, 323, 320, 35, 323, 320, 9, 342, 35, 342, 9, 344, + 35, 344, 9, 340, 324, 35, 340, 324, 10, 325, 36, 325, 11, 323, 37, + 323, 12, 325, 38, 325, 12, 336, 38, 336, 12, 326, 38, 326, 12, 340, + 38, 340, 12, 343, 38, 343, 13, 344, 39, 344, 13, 326, 320, 39, 326, + 320, 15, 320, 41, 320, 15, 336, 41, 336, 15, 345, 41, 345, 16, 336, + 42, 336, 16, 336, 323, 42, 336, 323, 16, 345, 42, 345, 16, 342, 42, + 342, 17, 320, 43, 320, 17, 325, 43, 325, 17, 336, 43, 336, 18, 325, + 44, 325, 18, 336, 44, 336, 18, 345, 44, 345, 18, 342, 44, 342, 19, + 322, 320, 45, 322, 320, 19, 322, 326, 45, 322, 326, 19, 323, 319, 45, + 323, 319, 19, 323, 320, 45, 323, 320, 20, 320, 46, 320, 20, 325, 46, + 325, 21, 325, 47, 325, 21, 336, 47, 336, 21, 336, 323, 47, 336, 323, + 21, 345, 47, 345, 22, 325, 48, 325, 22, 336, 48, 336, 22, 320, 325, + 48, 320, 325, 22, 330, 325, 48, 330, 325, 22, 336, 325, 48, 336, 325, + 23, 325, 49, 325, 23, 336, 49, 336, 23, 345, 49, 345, 23, 342, 49, + 342, 24, 337, 50, 337, 24, 344, 50, 344, 24, 342, 50, 342, 24, 322, + 320, 50, 322, 320, 24, 323, 326, 50, 323, 326, 25, 322, 51, 322, 25, + 336, 51, 336, 26, 319, 52, 319, 26, 320, 52, 320, 26, 326, 52, 326, + 26, 325, 52, 325, 26, 336, 52, 336, 27, 325, 53, 325, 27, 326, 53, + 326, 28, 325, 54, 325, 29, 321, 55, 321, 29, 336, 55, 336, 29, 345, + 55, 345, 38, 345, 49, 326, 52, 328, 54, 328, 224, 325, 1417, 5, 336, + 31, 336, 5, 327, 31, 327, 5, 321, 320, 31, 321, 320, 5, 321, 319, 31, + 321, 319, 5, 321, 327, 31, 321, 327, 5, 321, 322, 31, 321, 322, 5, + 336, 321, 31, 336, 321, 5, 324, 320, 31, 324, 320, 5, 324, 319, 31, + 324, 319, 5, 324, 327, 31, 324, 327, 5, 324, 322, 31, 324, 322, 5, + 336, 324, 31, 336, 324, 9, 336, 35, 336, 9, 327, 35, 327, 9, 322, 35, + 322, 9, 321, 320, 35, 321, 320, 9, 321, 319, 35, 321, 319, 9, 321, + 327, 35, 321, 327, 9, 321, 322, 35, 321, 322, 9, 336, 321, 35, 336, + 321, 13, 327, 39, 327, 13, 336, 39, 336, 19, 336, 45, 336, 19, 327, + 45, 327, 19, 321, 320, 45, 321, 320, 19, 321, 319, 45, 321, 319, 19, + 321, 327, 45, 321, 327, 19, 321, 322, 45, 321, 322, 19, 336, 321, 45, + 336, 321, 19, 335, 320, 45, 335, 320, 19, 335, 319, 45, 335, 319, 19, + 335, 327, 45, 335, 327, 19, 335, 322, 45, 335, 322, 19, 335, 336, 45, + 335, 336, 24, 336, 50, 336, 24, 327, 50, 327, 24, 335, 320, 50, 335, + 320, 24, 335, 319, 50, 335, 319, 24, 335, 327, 50, 335, 327, 24, 335, + 322, 50, 335, 322, 24, 335, 336, 50, 335, 336, 28, 319, 54, 319, 28, + 336, 54, 336, 28, 327, 54, 327, 28, 322, 54, 322, 380, 333, 380, 334, + 380, 333, 319, 380, 334, 319, 380, 333, 320, 380, 334, 320, 380, 333, + 349, 380, 334, 349, 365, 333, 365, 334, 365, 333, 319, 365, 334, 319, + 365, 333, 320, 365, 334, 320, 365, 333, 349, 365, 334, 349, 381, 333, + 381, 334, 381, 333, 319, 381, 334, 319, 381, 333, 320, 381, 334, 320, + 366, 333, 366, 334, 366, 333, 319, 366, 334, 319, 366, 333, 320, 366, + 334, 320, 382, 333, 382, 334, 382, 333, 319, 382, 334, 319, 382, 333, + 320, 382, 334, 320, 382, 333, 349, 382, 334, 349, 367, 333, 367, 334, + 367, 333, 319, 367, 334, 319, 367, 333, 320, 367, 334, 320, 367, 333, + 349, 367, 334, 349, 383, 333, 383, 334, 383, 333, 319, 383, 334, 319, + 383, 333, 320, 383, 334, 320, 383, 333, 349, 383, 334, 349, 368, 333, + 368, 334, 368, 333, 319, 368, 334, 319, 368, 333, 320, 368, 334, 320, + 368, 333, 349, 368, 334, 349, 384, 333, 384, 334, 384, 333, 319, 384, + 334, 319, 384, 333, 320, 384, 334, 320, 369, 333, 369, 334, 369, 333, + 319, 369, 334, 319, 369, 333, 320, 369, 334, 320, 386, 333, 386, 334, + 386, 333, 319, 386, 334, 319, 386, 333, 320, 386, 334, 320, 386, 333, + 349, 386, 334, 349, 371, 334, 371, 334, 319, 371, 334, 320, 371, 334, + 349, 387, 333, 387, 334, 387, 333, 319, 387, 334, 319, 387, 333, 320, + 387, 334, 320, 387, 333, 349, 387, 334, 349, 372, 333, 372, 334, 372, + 333, 319, 372, 334, 319, 372, 333, 320, 372, 334, 320, 372, 333, 349, + 372, 334, 349, 380, 319, 381, 319, 382, 319, 383, 319, 384, 319, 386, + 319, 387, 319, 380, 333, 352, 380, 334, 352, 380, 333, 319, 352, 380, + 334, 319, 352, 380, 333, 320, 352, 380, 334, 320, 352, 380, 333, 349, + 352, 380, 334, 349, 352, 365, 333, 352, 365, 334, 352, 365, 333, 319, + 352, 365, 334, 319, 352, 365, 333, 320, 352, 365, 334, 320, 352, 365, + 333, 349, 352, 365, 334, 349, 352, 382, 333, 352, 382, 334, 352, 382, + 333, 319, 352, 382, 334, 319, 352, 382, 333, 320, 352, 382, 334, 320, + 352, 382, 333, 349, 352, 382, 334, 349, 352, 367, 333, 352, 367, 334, + 352, 367, 333, 319, 352, 367, 334, 319, 352, 367, 333, 320, 352, 367, + 334, 320, 352, 367, 333, 349, 352, 367, 334, 349, 352, 387, 333, 352, + 387, 334, 352, 387, 333, 319, 352, 387, 334, 319, 352, 387, 333, 320, + 352, 387, 334, 320, 352, 387, 333, 349, 352, 387, 334, 349, 352, 372, + 333, 352, 372, 334, 352, 372, 333, 319, 352, 372, 334, 319, 352, 372, + 333, 320, 352, 372, 334, 320, 352, 372, 333, 349, 352, 372, 334, 349, + 352, 380, 324, 380, 323, 380, 319, 352, 380, 352, 380, 320, 352, 502, + 484, 380, 349, 380, 349, 352, 365, 324, 365, 323, 365, 319, 365, 352, + 56, 349, 382, 319, 352, 382, 352, 382, 320, 352, 382, 349, 382, 349, + 352, 366, 319, 367, 319, 367, 352, 1108, 319, 1108, 320, 1108, 349, + 383, 324, 383, 323, 383, 326, 319, 383, 349, 383, 326, 349, 368, 324, + 368, 323, 368, 319, 1163, 319, 1163, 320, 1163, 349, 386, 324, 386, + 323, 386, 326, 319, 385, 333, 385, 334, 386, 349, 386, 326, 349, 371, + 324, 371, 323, 371, 319, 370, 334, 56, 319, 30, 387, 319, 352, 387, + 352, 387, 320, 352, 387, 349, 387, 349, 352, 369, 319, 372, 319, 372, + 352, 57 +}; + +static const uint8_t decomp_idx_t1[] = { + 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, + 0, 0, 13, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19, 0, + 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0, 0, 0, 0, 27, 28, + 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, + 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 0, 0, 0, 41, 0, 42, 43, 44, 45, 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 63, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 66, 67, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 69, + 70, 71, 72, 73, 74, 75, 76 +}; + +static const uint16_t decomp_idx_t2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16392, 16394, + 16396, 16398, 16400, 16402, 0, 16404, 16406, 16408, 16410, 16412, + 16414, 16416, 16418, 16420, 0, 16422, 16424, 16426, 16428, 16430, + 16432, 0, 0, 16434, 16436, 16438, 16440, 16442, 0, 0, 16444, 16446, + 16448, 16450, 16452, 16454, 0, 16456, 16458, 16460, 16462, 16464, + 16466, 16468, 16470, 16472, 0, 16474, 16476, 16478, 16480, 16482, + 16484, 0, 0, 16486, 16488, 16490, 16492, 16494, 0, 16496, 16498, + 16500, 16502, 16504, 16506, 16508, 16510, 16512, 16514, 16516, 16518, + 16520, 16522, 16524, 16526, 16528, 0, 0, 16530, 16532, 16534, 16536, + 16538, 16540, 16542, 16544, 16546, 16548, 16550, 16552, 16554, 16556, + 16558, 16560, 16562, 16564, 16566, 16568, 0, 0, 16571, 16573, 16575, + 16577, 16579, 16581, 16583, 16585, 16587, 0, 0, 0, 16589, 16591, + 16593, 16595, 0, 16597, 16599, 16601, 16603, 16605, 16607, 0, 0, 0, 0, + 16609, 16611, 16613, 16615, 16617, 16619, 0, 0, 0, 16621, 16623, + 16625, 16627, 16629, 16631, 0, 0, 16633, 16635, 16637, 16639, 16641, + 16643, 16645, 16647, 16649, 16651, 16653, 16655, 16657, 16659, 16661, + 16663, 16665, 16667, 0, 0, 16669, 16671, 16673, 16675, 16677, 16679, + 16681, 16683, 16685, 16687, 16689, 16691, 16693, 16695, 16697, 16699, + 16701, 16703, 16705, 16707, 16709, 16711, 16713, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 16719, 16721, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16725, + 16727, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16730, 16732, 16734, 16736, 16738, 16740, 16742, + 16744, 33130, 33133, 33136, 33139, 33142, 33145, 33148, 33151, 0, + 33154, 33157, 33160, 33163, 16782, 16784, 0, 0, 16786, 16788, 16790, + 16792, 16794, 16796, 33182, 33185, 16804, 16806, 16808, 0, 0, 0, + 16810, 16812, 0, 0, 16814, 16816, 33202, 33205, 16824, 16826, 16828, + 16830, 16832, 16834, 16836, 16838, 16840, 16842, 16844, 16846, 16848, + 16850, 16852, 16854, 16856, 16858, 16860, 16862, 16864, 16866, 16868, + 16870, 16872, 16874, 16876, 16878, 16880, 16882, 16884, 16886, 0, 0, + 16888, 16890, 0, 0, 0, 0, 0, 0, 16776, 16779, 16896, 16898, 33284, + 33287, 33290, 33293, 16912, 16914, 33300, 33303, 16922, 16924, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 11, 0, 612, 16753, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 615, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0, 0, 17003, 17005, 623, 17008, 17010, + 17012, 0, 17014, 0, 17016, 17018, 33404, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17025, 17027, 17029, + 17031, 17033, 17035, 33421, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17020, 17037, 17040, 17042, 17044, 0, + 0, 0, 0, 17047, 17049, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17051, 17053, 0, 17055, 0, 0, 0, 17057, 0, 0, 0, 0, 17059, + 17061, 17063, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17065, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 17068, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17070, 17072, 0, 17074, 0, 0, 0, 17076, 0, 0, 0, 0, 17078, + 17080, 17082, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17085, 17087, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17090, 17092, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17094, 17096, 17098, 17100, 0, 0, + 17102, 17104, 0, 0, 17106, 17108, 17110, 17112, 17114, 17116, 0, 0, + 17118, 17120, 17122, 17124, 17126, 17128, 0, 0, 17130, 17132, 17134, + 17136, 17138, 17140, 17142, 17144, 17146, 17148, 17150, 17152, 0, 0, + 17154, 17156, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17159, + 17161, 17163, 17165, 17167, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17170, 0, 17172, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17177, 0, 0, 0, 0, 0, 0, 0, 17179, 0, 0, 17181, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17183, 17185, 17187, 17189, 17191, 17193, + 17195, 17197, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 17199, 17201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17203, + 17205, 0, 17207, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17209, 0, 0, + 17211, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17214, 17216, 17218, 0, 0, + 17220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17230, 0, + 0, 17232, 17234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17236, + 17238, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17242, 17244, + 17246, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17252, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17256, 0, 0, 0, 0, 0, 0, 17258, 17260, 0, 17262, 33648, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17267, 17269, 17271, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17273, 0, 17275, 33661, 17280, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17282, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17284, 0, 0, 0, 0, + 17286, 0, 0, 0, 0, 17288, 0, 0, 0, 0, 17290, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 17292, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17294, 0, 17296, 17298, + 0, 17300, 0, 0, 0, 0, 0, 0, 0, 0, 17302, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 17304, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17306, 0, 0, 0, + 0, 17308, 0, 0, 0, 0, 17310, 0, 0, 0, 0, 17312, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17314, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17319, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18275, 0, 18277, 0, + 18280, 0, 18283, 0, 18285, 0, 0, 0, 18288, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 18332, 0, 18336, 0, 0, 18340, 18342, 0, 18344, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18446, 18448, 18450, 18452, + 18454, 18456, 18458, 18460, 34846, 34849, 18468, 18470, 18472, 18474, + 18476, 18478, 18480, 18482, 18484, 18486, 34872, 34875, 34878, 34881, + 18500, 18502, 18504, 18506, 34892, 34895, 18514, 18516, 18518, 18520, + 18522, 18524, 18526, 18528, 18530, 18532, 18534, 18536, 18538, 18540, + 18542, 18544, 34930, 34933, 18552, 18554, 18556, 18558, 18560, 18562, + 18564, 18566, 34952, 34955, 18574, 18576, 18578, 18580, 18582, 18584, + 18586, 18588, 18590, 18592, 18594, 18596, 18598, 18600, 18602, 18604, + 18606, 18608, 34994, 34997, 35000, 35003, 35006, 35009, 35012, 35015, + 18634, 18636, 18638, 18640, 18642, 18644, 18646, 18648, 35034, 35037, + 18656, 18658, 18660, 18662, 18664, 18666, 35052, 35055, 35058, 35061, + 35064, 35067, 18686, 18688, 18690, 18692, 18694, 18696, 18698, 18700, + 18702, 18704, 18706, 18708, 18710, 18712, 35098, 35101, 35104, 35107, + 18726, 18728, 18730, 18732, 18734, 18736, 18738, 18740, 18742, 18744, + 18746, 18748, 18750, 18752, 18754, 18756, 18758, 18760, 18762, 18764, + 18766, 18768, 18770, 18772, 18774, 18776, 18778, 18780, 18782, 18784, + 0, 18786, 0, 0, 0, 0, 18789, 18791, 18793, 18795, 35181, 35184, 35187, + 35190, 35193, 35196, 35199, 35202, 35205, 35208, 35211, 35214, 35217, + 35220, 35223, 35226, 35229, 35232, 35235, 35238, 18857, 18859, 18861, + 18863, 18865, 18867, 35253, 35256, 35259, 35262, 35265, 35268, 35271, + 35274, 35277, 35280, 18899, 18901, 18903, 18905, 18907, 18909, 18911, + 18913, 35299, 35302, 35305, 35308, 35311, 35314, 35317, 35320, 35323, + 35326, 35329, 35332, 35335, 35338, 35341, 35344, 35347, 35350, 35353, + 35356, 18975, 18977, 18979, 18981, 35367, 35370, 35373, 35376, 35379, + 35382, 35385, 35388, 35391, 35394, 19013, 19015, 19017, 19019, 19021, + 19023, 19025, 19027, 0, 0, 0, 0, 0, 0, 19029, 19031, 35417, 35420, + 35423, 35426, 35429, 35432, 19051, 19053, 35439, 35442, 35445, 35448, + 35451, 35454, 19073, 19075, 35461, 35464, 35467, 35470, 0, 0, 19089, + 19091, 35477, 35480, 35483, 35486, 0, 0, 19105, 19107, 35493, 35496, + 35499, 35502, 35505, 35508, 19127, 19129, 35515, 35518, 35521, 35524, + 35527, 35530, 19149, 19151, 35537, 35540, 35543, 35546, 35549, 35552, + 19171, 19173, 35559, 35562, 35565, 35568, 35571, 35574, 19193, 19195, + 35581, 35584, 35587, 35590, 0, 0, 19209, 19211, 35597, 35600, 35603, + 35606, 0, 0, 19225, 19227, 35613, 35616, 35619, 35622, 35625, 35628, + 0, 19247, 0, 35633, 0, 35636, 0, 35639, 19258, 19260, 35646, 35649, + 35652, 35655, 35658, 35661, 19280, 19282, 35668, 35671, 35674, 35677, + 35680, 35683, 19302, 17029, 19304, 17031, 19306, 17033, 19308, 17035, + 19310, 17040, 19312, 17042, 19314, 17044, 0, 0, 35700, 35703, 52090, + 52094, 52098, 52102, 52106, 52110, 35730, 35733, 52120, 52124, 52128, + 52132, 52136, 52140, 35760, 35763, 52150, 52154, 52158, 52162, 52166, + 52170, 35790, 35793, 52180, 52184, 52188, 52192, 52196, 52200, 35820, + 35823, 52210, 52214, 52218, 52222, 52226, 52230, 35850, 35853, 52240, + 52244, 52248, 52252, 52256, 52260, 19496, 19498, 35884, 19503, 35889, + 0, 19510, 35896, 19515, 19517, 19519, 17005, 19521, 0, 636, 0, 0, + 19523, 35909, 19528, 35914, 0, 19533, 35919, 19538, 17008, 19540, + 17010, 19542, 19544, 19546, 19548, 19550, 19552, 35938, 33404, 0, 0, + 19557, 35943, 19562, 19564, 19566, 17012, 0, 19568, 19570, 19572, + 19574, 19576, 35962, 33421, 19581, 19583, 19585, 35971, 19590, 19592, + 19594, 17016, 19596, 19598, 17003, 3216, 0, 0, 35985, 19604, 35990, 0, + 19609, 35995, 19614, 17014, 19616, 17018, 19618, 3236, 0, 0, 1, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 186, 0, 0, 0, 209, 16402, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16715, 16717, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16723, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 17222, 17224, 17226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17248, 0, 0, 0, 0, 17250, 0, 0, + 17254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16892, 0, 16894, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16926, 0, 0, 16928, 0, 0, 16930, 0, + 16932, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16934, 0, 16936, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16938, 16940, 16942, + 16944, 16946, 0, 0, 16948, 16950, 0, 0, 16952, 16954, 0, 0, 0, 0, 0, + 0, 16956, 16958, 0, 0, 16960, 16962, 0, 0, 16964, 16966, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 16969, 16971, 16973, 16975, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16978, 16980, + 16982, 16984, 0, 0, 0, 0, 0, 0, 16986, 16988, 16990, 16992, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 610, 611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17228, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17322, 0, + 17324, 0, 17326, 0, 17328, 0, 17330, 0, 17332, 0, 17334, 0, 17336, 0, + 17338, 0, 17340, 0, 17342, 0, 17344, 0, 0, 17346, 0, 17348, 0, 17350, + 0, 0, 0, 0, 0, 0, 17352, 17354, 0, 17356, 17358, 0, 17360, 17362, 0, + 17364, 17366, 0, 17368, 17370, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17372, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17379, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17383, 0, 17385, 0, 17387, 0, + 17389, 0, 17391, 0, 17393, 0, 17395, 0, 17397, 0, 17399, 0, 17401, 0, + 17403, 0, 17405, 0, 0, 17407, 0, 17409, 0, 17411, 0, 0, 0, 0, 0, 0, + 17413, 17415, 0, 17417, 17419, 0, 17421, 17423, 0, 17425, 17427, 0, + 17429, 17431, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17434, 0, 0, 17436, 17438, 17440, 17442, 0, 0, 0, 17444, 0, + 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1505, 1506, 1507, + 1508, 1509, 1419, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, + 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, + 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1388, 1458, 1536, 1537, + 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, + 1549, 1550, 1551, 1552, 1241, 1553, 1554, 1555, 1556, 1557, 1558, + 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, + 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, + 1581, 1582, 1583, 1584, 1516, 1585, 1586, 1357, 1587, 1588, 1214, + 1293, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, + 1599, 1600, 1487, 1601, 1602, 1603, 1231, 1604, 1605, 1606, 1607, + 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, + 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, + 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, + 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1600, 1648, 1649, 1650, + 1651, 1652, 1653, 1654, 1655, 1357, 1656, 1657, 1658, 1659, 1660, + 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, + 1672, 1673, 1674, 1675, 1516, 1676, 1677, 1678, 1679, 1680, 1681, + 1682, 1683, 1684, 1685, 1148, 1686, 1687, 1688, 1689, 1690, 1691, + 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1588, + 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, + 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, + 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, + 1735, 1736, 1737, 1327, 1738, 1739, 1740, 1741, 1742, 1743, 1744, + 1745, 1746, 1747, 1748, 1749, 1750, 0, 0, 1753, 0, 1755, 0, 0, 1758, + 1759, 1760, 1761, 1762, 1763, 932, 1764, 1765, 1766, 0, 1767, 0, 1769, + 0, 0, 1770, 1771, 0, 0, 0, 1773, 1774, 1775, 1776, 1777, 1778, 1255, + 1260, 1264, 1288, 1289, 1295, 1779, 1323, 1780, 1781, 1782, 1783, + 1366, 1406, 1784, 1413, 1418, 1442, 1785, 1449, 1468, 1147, 1786, + 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1246, 1796, + 1797, 1798, 937, 1799, 1800, 1637, 1801, 1802, 1803, 1128, 1804, 1805, + 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1770, 1814, + 1815, 1816, 1817, 1818, 1819, 0, 0, 1821, 1277, 1822, 1823, 1824, + 1825, 1287, 1290, 1779, 1826, 1318, 1827, 1753, 1828, 1829, 1830, + 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1411, 1838, 1413, 1839, + 1418, 1840, 1841, 1842, 1843, 1844, 1755, 1458, 1459, 1845, 1846, + 1487, 1148, 1847, 1160, 1787, 1171, 1788, 1848, 1187, 1849, 1759, + 1204, 1850, 1851, 1852, 1853, 1760, 1854, 1224, 1233, 1855, 1243, + 1856, 1800, 1857, 1858, 1637, 1859, 1128, 1860, 1861, 1862, 1863, + 1864, 1808, 1865, 1769, 1866, 1809, 1585, 1867, 1810, 1868, 1812, 7, + 1869, 1870, 1871, 1872, 1814, 1764, 1873, 1815, 1874, 1816, 1875, + 1505, 1876, 1877, 1878, 1473, 1879, 1234, 1880, 1881, 1882, 1883, + 1884, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 18291, 0, 18293, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18298, 18300, 34686, + 34689, 18308, 18310, 18312, 18314, 18316, 18318, 18320, 18322, 18324, + 0, 18326, 18328, 18330, 16997, 18334, 0, 18338, 0, 17001, 19508, 0, + 17023, 18346, 0, 18349, 18351, 18353, 18302, 18355, 18357, 18359, + 18361, 18363, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17375, 0, 17377, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 17381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 17447, 17449, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 17452, 17454, 33840, 33843, 33846, 33849, + 33852, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17474, 17476, + 33862, 33865, 33868, 33871, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, + 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, + 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, + 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, + 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1299, 1299, 1300, 1301, + 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, + 1313, 1314, 1315, 1316, 1317, 1317, 1318, 1319, 1320, 1321, 1322, + 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, + 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, + 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1353, 1354, + 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, + 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, + 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, + 1388, 1389, 1390, 1391, 1391, 1152, 1392, 1392, 1393, 1394, 1395, + 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, + 1407, 1408, 1409, 1410, 1411, 1410, 1412, 1413, 1414, 1415, 1416, + 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, + 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, + 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, + 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, + 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, + 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, + 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, + 1494, 1495, 1496, 1497, 1146, 1147, 1148, 1149, 1150, 1153, 1154, + 1155, 1156, 1157, 1159, 1160, 1161, 1162, 1163, 1165, 1166, 1167, + 1168, 1169, 1171, 1172, 1173, 1174, 1175, 1177, 1178, 1179, 1180, + 1182, 1184, 1185, 1186, 1187, 1188, 1190, 1191, 1192, 1193, 1194, + 1196, 1197, 1198, 1199, 1200, 1200, 1202, 1203, 1204, 1205, 1207, + 1208, 1209, 1210, 1211, 1213, 1214, 1215, 1216, 1217, 1219, 1220, + 1221, 1223, 1224, 1226, 1227, 1228, 1229, 1230, 1232, 1232, 1233, + 1234, 1235, 1237, 1238, 1239, 1240, 1241, 1243, 1244, 1245, 1246, + 1247, 1249, 932, 933, 934, 937, 1113, 1119, 990, 1130, 1130, 1049, + 1062, 1181, 1067, 1087, 1088, 1089, 1106, 1107, 1108, 1109, 1110, + 1111, 1112, 1114, 1115, 1116, 1117, 1118, 1120, 1121, 1122, 1123, + 1124, 1125, 1126, 1127, 1128, 1129, 1131, 1132, 1133, 1134, 1135, + 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1152, + 1158, 1164, 1170, 1176, 1183, 1189, 1195, 1201, 1206, 1212, 1218, + 1225, 1231, 1236, 1242, 1248, 1222, 774, 683, 1806, 1996, 2024, 2046, + 2053, 2060, 2006, 2001, 2404, 5, 705, 792, 829, 584, 1752, 662, 700, + 1768, 1772, 785, 345, 1548, 1895, 1912, 1964, 1984, 1990, 1997, 1862, + 2009, 1820, 2018, 2025, 2030, 2034, 2038, 2044, 2047, 2048, 2050, + 2051, 2052, 2054, 2055, 2056, 2058, 2059, 2061, 1885, 1867, 1868, + 1886, 1887, 1888, 1889, 1890, 1898, 1903, 1906, 2057, 1911, 1913, + 2049, 2026, 7, 3, 4, 6, 1981, 1982, 1983, 1985, 1986, 1987, 1988, + 1989, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2002, 2003, + 2004, 2005, 593, 2007, 2008, 2010, 2011, 2012, 2013, 1874, 1874, 2014, + 2015, 2016, 2017, 2019, 2020, 2021, 2022, 2023, 1151, 1875, 2027, + 2028, 2029, 1751, 2031, 2032, 1754, 2033, 1756, 1757, 2035, 2036, + 2037, 2039, 2040, 2041, 2042, 2043, 2045 +}; + +int32_t decomp_idx(int32_t codepoint) { + if (codepoint >= 195102) return 0; + return decomp_idx_t2[(decomp_idx_t1[codepoint >> 6] << 6) + (codepoint & 63)]; +} +static const uint8_t comp_idx_t1[] = { + 0, 1, 2, 3, 0, 4, 5, 6, 7, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 0, 13, 0, + 0, 0, 0, 0, 0, 0, 14, 15, 16, 0, 17, 18, 19, 20, 0, 0, 21, 22, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 28, 0, 29, 0, 30, 0, 0, 0, 31, 0, 0, 32, 33, 0, 0, 0, 34, 0, + 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 40, 41, + 0, 42, 43, 0, 44, 45, 46, 47, 0, 48, 49, 50, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 51, 0, 52, 0, 53, 54, 55, 56, 57, 58, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 66, 0, 0, 0, 67 +}; + +static const uint16_t comp_idx_t2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 4, 20, 23, + 28, 34, 502, 52, 59, 66, 81, 82, 87, 517, 94, 103, 119, 0, 122, 130, + 137, 144, 163, 165, 171, 173, 182, 0, 0, 0, 0, 0, 0, 191, 207, 210, + 215, 221, 701, 239, 246, 254, 268, 270, 275, 281, 284, 293, 309, 0, + 571, 313, 320, 328, 347, 349, 585, 358, 368, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 381, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 396, 0, 400, 401, 753, 403, 0, 0, 405, 0, 0, + 0, 0, 762, 0, 0, 0, 0, 413, 765, 419, 0, 768, 0, 0, 0, 424, 0, 0, 0, + 0, 0, 428, 0, 432, 433, 434, 436, 0, 0, 437, 0, 0, 0, 0, 441, 0, 0, 0, + 0, 445, 449, 452, 0, 453, 0, 0, 0, 454, 0, 0, 0, 0, 0, 459, 463, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 467, 469, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 476, 478, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, 0, 0, 0, 0, 482, 483, 0, 0, 0, 0, 0, + 0, 484, 485, 486, 487, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 488, 492, 497, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 503, + 508, 0, 0, 0, 0, 0, 0, 513, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 524, 525, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 534, 535, 536, 537, 0, 0, 0, 0, 538, + 539, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 564, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 601, 0, 0, + 0, 609, 0, 613, 0, 618, 0, 0, 0, 0, 0, 625, 0, 629, 0, 0, 0, 630, 0, + 0, 0, 636, 0, 0, 641, 0, 642, 0, 0, 643, 0, 0, 0, 651, 0, 655, 0, 661, + 0, 0, 0, 0, 0, 669, 0, 673, 0, 0, 0, 675, 0, 0, 0, 686, 692, 695, 0, + 0, 698, 0, 0, 0, 699, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 702, 0, 0, 0, 0, 0, 0, 0, 0, 0, 703, 0, 0, 705, 0, 706, 709, + 711, 712, 0, 716, 0, 0, 0, 717, 0, 0, 0, 0, 718, 0, 0, 0, 722, 0, 0, + 0, 723, 0, 724, 0, 0, 725, 0, 0, 727, 0, 728, 731, 733, 734, 0, 738, + 0, 0, 0, 739, 0, 0, 0, 0, 740, 0, 0, 0, 745, 0, 0, 0, 746, 0, 747, 0, + 0, 0, 0, 0, 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 749, 750, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 760, 761, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 763, 764, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 782, 0, 783, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 795, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 798, 0, 0, 799, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 471, 0, 0, 0, 0, 0, 0, + 0, 472, 0, 0, 475, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 598, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 608, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 683, 685, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 744, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 755, 0, 0, 0, 0, 0, 0, 756, 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 769, + 771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 773, 0, 0, 776, 0, 0, 0, 0, 0, 0, 0, 0, 587, 0, 588, 0, + 589, 0, 590, 0, 591, 0, 0, 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 593, 0, 594, 0, 595, 596, 0, 0, 597, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 780, + 781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 784, 785, 0, 0, 0, 0, 0, 0, 787, + 788, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 789, 791, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 793, 794, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 796, 797, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 800, 804, 808, 809, 810, 811, 812, 813, 814, 818, 822, + 823, 824, 825, 826, 827, 828, 830, 0, 0, 0, 0, 0, 0, 832, 834, 0, 0, + 0, 0, 0, 0, 836, 840, 844, 845, 846, 847, 848, 849, 850, 854, 858, + 859, 860, 861, 862, 863, 864, 867, 0, 0, 0, 0, 0, 0, 870, 873, 0, 0, + 0, 0, 0, 0, 876, 878, 0, 0, 0, 0, 0, 0, 880, 882, 0, 0, 0, 0, 0, 0, + 884, 887, 0, 0, 0, 0, 0, 0, 0, 890, 0, 0, 0, 0, 0, 0, 893, 897, 901, + 902, 903, 904, 905, 906, 907, 911, 915, 916, 917, 751, 919, 920, 921, + 0, 0, 0, 922, 0, 0, 0, 0, 0, 0, 0, 923, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 924, 0, 0, 0, 0, 0, 0, 0, + 0, 925, 0, 0, 0, 0, 0, 0, 928, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 929, 0, 0, 0, 0, 0, 0, 0, 930, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 489, 0, 490, 0, 491, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 520, 0, 521, 0, 522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 528, 0, 0, 0, 0, 529, 0, 0, 786, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 532, 0, 533, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, + 541, 0, 542, 0, 0, 544, 0, 0, 0, 0, 545, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, 548, 549, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 551, 552, 0, 0, 553, 554, 0, 0, 555, 556, 557, 558, 0, + 0, 0, 0, 559, 560, 0, 0, 561, 562, 0, 0, 0, 0, 0, 0, 0, 0, 0, 563, + 918, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 567, 0, 0, 0, 0, 0, + 568, 569, 0, 570, 0, 0, 0, 0, 0, 0, 579, 580, 581, 582, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 514, 0, 93, 0, 523, + 0, 121, 0, 526, 0, 527, 0, 530, 0, 531, 0, 188, 0, 189, 0, 190, 0, + 543, 0, 0, 546, 0, 238, 0, 550, 0, 0, 0, 0, 0, 0, 565, 0, 0, 311, 0, + 0, 583, 0, 0, 356, 0, 0, 374, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 378, 0, 0, + 0, 0, 0, 0, 0, 0, 380, 0, 0, 0, 0, 384, 0, 385, 0, 386, 0, 387, 0, + 388, 0, 389, 0, 390, 0, 391, 0, 392, 0, 393, 0, 394, 0, 395, 0, 0, + 752, 0, 402, 0, 404, 0, 0, 0, 0, 0, 0, 409, 0, 0, 411, 0, 0, 417, 0, + 0, 420, 0, 0, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 772, 442, 443, 444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 458, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 376, 0, 377, 0, 0, 0, 0, 0, 0, 0, 0, 0, 379, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 473, 474 +}; + +int32_t comp_idx(int32_t codepoint) { + if (codepoint >= 69939) return 0; + return comp_idx_t2[(comp_idx_t1[codepoint >> 5] << 5) + (codepoint & 31)]; +} +static const uint8_t ccc_t1[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, + 5, 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 0, 14, 15, 16, 15, 17, 15, 17, + 15, 17, 15, 17, 0, 17, 0, 18, 15, 17, 0, 17, 0, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 32, 0, 0, 33, 0, 34, 0, 0, + 0, 35, 36, 0, 0, 37, 38, 39, 40, 41, 0, 0, 42, 0, 0, 0, 43, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 46, 0, 47, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 53, + 0, 0, 54, 55, 56, 57, 58, 0, 0, 59, 60, 0, 0, 0, 61, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 53, 66, 0, 67, 0, 0, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 0, 0, 71 +}; + +static const uint8_t ccc_t2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 232, 220, 220, 220, 220, 232, 216, 220, 220, 220, + 220, 220, 202, 202, 220, 220, 220, 220, 202, 202, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 1, 1, 1, 1, 1, 220, 220, 220, 220, + 230, 230, 230, 230, 230, 230, 230, 230, 240, 230, 220, 220, 220, 230, + 230, 230, 220, 220, 0, 230, 230, 230, 220, 220, 220, 220, 230, 232, + 220, 220, 230, 233, 234, 234, 233, 234, 234, 233, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 220, 230, 230, 230, 230, 220, 230, 230, 230, 222, 220, 230, 230, 230, + 230, 230, 230, 220, 220, 220, 220, 220, 220, 230, 230, 220, 230, 230, + 222, 228, 230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, + 0, 23, 0, 24, 25, 0, 230, 220, 0, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, + 230, 230, 230, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 230, + 230, 220, 220, 230, 230, 230, 230, 230, 220, 230, 230, 220, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, 0, 230, 230, 230, + 230, 220, 230, 0, 0, 230, 230, 0, 220, 230, 230, 220, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, 230, 220, + 230, 230, 220, 220, 220, 230, 220, 220, 230, 220, 230, 230, 230, 220, + 230, 220, 230, 220, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, + 230, 230, 230, 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, + 230, 230, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 230, 230, + 230, 0, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 220, 230, + 230, 220, 230, 230, 230, 220, 220, 220, 27, 28, 29, 230, 230, 230, + 220, 230, 230, 220, 220, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 9, 0, 0, 0, 230, 220, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 84, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 103, 103, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, + 107, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 118, 118, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 122, 122, 122, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 220, 0, 216, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 129, 130, 0, 132, 0, 0, 0, 0, 0, 130, 130, 130, 130, 0, 0, + 130, 0, 230, 230, 9, 0, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 222, + 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, + 0, 0, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 220, 230, + 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230, 230, 230, 0, 1, 220, 220, 220, 220, 220, 230, 230, 220, 220, 220, + 220, 230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 220, 230, 230, 230, + 230, 230, 230, 230, 220, 230, 230, 234, 214, 220, 202, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 233, 220, 230, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 230, 230, 1, 1, 230, 230, 230, 230, 1, 1, 1, 230, 230, + 0, 0, 0, 0, 230, 0, 0, 0, 1, 1, 230, 220, 230, 1, 1, 220, 220, 220, + 220, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, + 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 218, + 228, 232, 222, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 0, + 0, 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 220, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, 230, + 230, 220, 0, 0, 230, 230, 0, 0, 0, 0, 0, 230, 230, 0, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 230, 230, 230, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 220, 0, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 230, 1, 220, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 216, 216, 1, 1, 1, + 0, 0, 0, 226, 216, 216, 216, 216, 216, 0, 0, 0, 0, 0, 0, 0, 0, 220, + 220, 220, 220, 220, 220, 220, 220, 0, 0, 230, 230, 230, 230, 230, 220, + 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 230, 230, 230 +}; + +int32_t ccc(int32_t codepoint) { + if (codepoint >= 119365) return 0; + return ccc_t2[(ccc_t1[codepoint >> 6] << 6) + (codepoint & 63)]; +} +static const int32_t lowercase_offset_values[] = { + 0, 32, 1, -199, -121, 210, 206, 205, 79, 202, 203, 207, 211, 209, 213, + 214, 218, 217, 219, 2, -97, -56, -130, 10795, -163, 10792, -195, 69, + 71, 38, 37, 64, 63, 8, -60, -7, 80, 15, 48, 7264, -7615, -8, -74, -9, + -86, -100, -112, -128, -126, -7517, -8383, -8262, 28, 16, 26, -10743, + -3814, -10727, -10780, -10749, -10783, -10782, -10815, -35332, -42280, + -42308, 40 +}; + +static const uint8_t lowercase_offset_t1[] = { + 0, 1, 0, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, + 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 20, 21, 20, 22, 23, 24, 25, 0, 0, 0, 0, 26, + 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 30, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, + 20, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 34, 35, 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40 +}; + +static const uint8_t lowercase_offset_t2[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 4, 2, 0, 2, 0, 2, 0, 0, 0, 5, + 2, 0, 2, 0, 6, 2, 0, 7, 7, 2, 0, 0, 8, 9, 10, 2, 0, 7, 11, 0, 12, 13, + 2, 0, 0, 0, 12, 14, 0, 15, 2, 0, 2, 0, 2, 0, 16, 2, 0, 16, 0, 0, 2, 0, + 16, 2, 0, 17, 17, 2, 0, 2, 0, 18, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 19, 2, 0, 19, 2, 0, 19, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, + 19, 2, 0, 2, 0, 20, 21, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 22, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 23, 2, 0, 24, 25, 0, 0, 2, 0, 26, 27, 28, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 30, 30, 30, 0, 31, 0, 32, 32, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 0, 0, 0, 0, 34, 0, 0, 2, 0, 35, 2, 0, 0, 22, 22, 22, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 37, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 0, 39, + 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, + 0, 0, 0, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, + 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, + 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 41, 0, 41, 0, 41, 0, 41, 0, 0, 0, 0, 0, 0, 0, + 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, + 0, 0, 0, 0, 0, 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, + 0, 0, 41, 41, 41, 41, 41, 41, 41, 41, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, + 42, 42, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 43, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 41, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 41, 41, 46, 46, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, + 48, 48, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, + 0, 0, 0, 50, 51, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 55, 56, 57, 0, + 0, 2, 0, 2, 0, 2, 0, 58, 59, 60, 61, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 62, 62, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 63, + 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 2, 0, 64, 0, 0, 2, 0, 2, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 65, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66 +}; + +int32_t lowercase_offset(int32_t codepoint) { + int offset_index; + if (codepoint >= 66600) return 0; + offset_index = lowercase_offset_t2[(lowercase_offset_t1[codepoint >> 6] << 6) + (codepoint & 63)]; + return lowercase_offset_values[offset_index]; +} diff --git a/src/Datadog.Trace.ClrProfiler.Native/module_metadata.h b/src/Datadog.Trace.ClrProfiler.Native/module_metadata.h new file mode 100644 index 0000000000..4f50e973bf --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/module_metadata.h @@ -0,0 +1,111 @@ +#ifndef DD_CLR_PROFILER_MODULE_METADATA_H_ +#define DD_CLR_PROFILER_MODULE_METADATA_H_ + +#include +#include +#include + +#include "clr_helpers.h" +#include "com_ptr.h" +#include "integration.h" +#include "string.h" + +namespace trace { + +class ModuleMetadata { + private: + std::unordered_map wrapper_refs{}; + std::unordered_map wrapper_parent_type{}; + std::unordered_set failed_wrapper_keys{}; + + public: + const ComPtr metadata_import{}; + const ComPtr metadata_emit{}; + const ComPtr assembly_import{}; + const ComPtr assembly_emit{}; + WSTRING assemblyName = ""_W; + AppDomainID app_domain_id; + GUID module_version_id; + std::vector integrations = {}; + + ModuleMetadata(ComPtr metadata_import, + ComPtr metadata_emit, + ComPtr assembly_import, + ComPtr assembly_emit, + WSTRING assembly_name, + AppDomainID app_domain_id, + GUID module_version_id, + std::vector integrations) + : metadata_import(metadata_import), + metadata_emit(metadata_emit), + assembly_import(assembly_import), + assembly_emit(assembly_emit), + assemblyName(assembly_name), + app_domain_id(app_domain_id), + module_version_id(module_version_id), + integrations(integrations) {} + + bool TryGetWrapperMemberRef(const WSTRING& keyIn, + mdMemberRef& valueOut) const { + const auto search = wrapper_refs.find(keyIn); + + if (search != wrapper_refs.end()) { + valueOut = search->second; + return true; + } + + return false; + } + + bool TryGetWrapperParentTypeRef(const WSTRING& keyIn, + mdTypeRef& valueOut) const { + const auto search = wrapper_parent_type.find(keyIn); + + if (search != wrapper_parent_type.end()) { + valueOut = search->second; + return true; + } + + return false; + } + + bool IsFailedWrapperMemberKey(const WSTRING& key) const { + const auto search = failed_wrapper_keys.find(key); + + if (search != failed_wrapper_keys.end()) { + return true; + } + + return false; + } + + void SetWrapperMemberRef(const WSTRING& keyIn, const mdMemberRef valueIn) { + wrapper_refs[keyIn] = valueIn; + } + + void SetWrapperParentTypeRef(const WSTRING& keyIn, const mdTypeRef valueIn) { + wrapper_parent_type[keyIn] = valueIn; + } + + void SetFailedWrapperMemberKey(const WSTRING& key) { + failed_wrapper_keys.insert(key); + } + + inline std::vector GetMethodReplacementsForCaller( + const trace::FunctionInfo& caller) { + std::vector enabled; + for (auto& i : integrations) { + if ((i.replacement.caller_method.type_name.empty() || + i.replacement.caller_method.type_name == caller.type.name) && + (i.replacement.caller_method.method_name.empty() || + i.replacement.caller_method.method_name == caller.name)) { + enabled.push_back(i.replacement); + } + } + return enabled; + } +}; + +} // namespace trace + +#endif // DD_CLR_PROFILER_MODULE_METADATA_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/packages.config b/src/Datadog.Trace.ClrProfiler.Native/packages.config new file mode 100644 index 0000000000..5452db3bab --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Native/pal.h b/src/Datadog.Trace.ClrProfiler.Native/pal.h new file mode 100644 index 0000000000..074fc69f97 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/pal.h @@ -0,0 +1,75 @@ +#ifndef DD_CLR_PROFILER_PAL_H_ +#define DD_CLR_PROFILER_PAL_H_ + +#ifdef _WIN32 + +#include +#include +#include "windows.h" + +#else + +#include +#include + +#endif + +#include "environment_variables.h" +#include "string.h" // NOLINT +#include "util.h" + +namespace trace { + +inline WSTRING DatadogLogFilePath() { + WSTRING path = GetEnvironmentValue(environment::log_path); + + if (path.length() > 0) { + return path; + } + +#ifdef _WIN32 + char* p_program_data; + size_t length; + const errno_t result = _dupenv_s(&p_program_data, &length, "PROGRAMDATA"); + std::string program_data; + + if (SUCCEEDED(result) && p_program_data != nullptr && length > 0) { + program_data = std::string(p_program_data); + } else { + program_data = R"(C:\ProgramData)"; + } + + return ToWSTRING(program_data + + R"(\Datadog .NET Tracer\logs\dotnet-profiler.log)"); +#else + return "/var/log/datadog/dotnet/dotnet-profiler.log"_W; +#endif +} + +inline WSTRING GetCurrentProcessName() { +#ifdef _WIN32 + const DWORD length = 260; + WCHAR buffer[length]{}; + + const DWORD len = GetModuleFileName(nullptr, buffer, length); + const WSTRING current_process_path(buffer); + return std::filesystem::path(current_process_path).filename(); +#else + std::fstream comm("/proc/self/comm"); + std::string name; + std::getline(comm, name); + return ToWSTRING(name); +#endif +} + +inline int GetPID() { +#ifdef _WIN32 + return _getpid(); +#else + return getpid(); +#endif +} + +} // namespace trace + +#endif // DD_CLR_PROFILER_PAL_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/resource.h b/src/Datadog.Trace.ClrProfiler.Native/resource.h new file mode 100644 index 0000000000..2e4ce6b77d --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/resource.h @@ -0,0 +1,18 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc +#define NETCOREAPP20_MANAGED_ENTRYPOINT_DLL 401 +#define NETCOREAPP20_MANAGED_ENTRYPOINT_SYMBOLS 402 +#define NET45_MANAGED_ENTRYPOINT_DLL 403 +#define NET45_MANAGED_ENTRYPOINT_SYMBOLS 404 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.cpp b/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.cpp new file mode 100644 index 0000000000..cb8731377f --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.cpp @@ -0,0 +1,266 @@ +#include "sig_helpers.h" + +namespace trace { + +bool ParseNumber(PCCOR_SIGNATURE* p_sig, ULONG* number) { + ULONG result = CorSigUncompressData(*p_sig, number); + if (result == -1) { + return false; + } + + *p_sig += result; + return true; +} + +bool ParseTypeDefOrRefEncoded(PCCOR_SIGNATURE* p_sig) { + mdToken type_token; + ULONG result; + result = CorSigUncompressToken(*p_sig, &type_token); + if (result == -1) { + return false; + } + + *p_sig += result; + return true; +} + +bool ParseCustomMod(PCCOR_SIGNATURE* p_sig) { + if (**p_sig == ELEMENT_TYPE_CMOD_OPT || **p_sig == ELEMENT_TYPE_CMOD_REQD) { + *p_sig += 1; + return ParseTypeDefOrRefEncoded(p_sig); + } + + return false; +} + +bool ParseOptionalCustomMods(PCCOR_SIGNATURE* p_sig) { + while (true) { + switch (**p_sig) { + case ELEMENT_TYPE_CMOD_OPT: + case ELEMENT_TYPE_CMOD_REQD: + if (!ParseCustomMod(p_sig)) { + return false; + } + break; + default: + return true; + } + } + + return false; +} + +bool ParseRetType(PCCOR_SIGNATURE* p_sig) { + if (!ParseOptionalCustomMods(p_sig)) { + return false; + } + + if (**p_sig == ELEMENT_TYPE_TYPEDBYREF || + **p_sig == ELEMENT_TYPE_VOID) { + *p_sig += 1; + return true; + } + + if (**p_sig == ELEMENT_TYPE_BYREF) { + *p_sig += 1; + } + + return ParseType(p_sig); +} + +bool ParseParam(PCCOR_SIGNATURE* p_sig) { + if (!ParseOptionalCustomMods(p_sig)) { + return false; + } + + if (**p_sig == ELEMENT_TYPE_TYPEDBYREF) { + *p_sig += 1; + return true; + } + + if (**p_sig == ELEMENT_TYPE_BYREF) { + *p_sig += 1; + } + + return ParseType(p_sig); +} + +bool ParseMethod(PCCOR_SIGNATURE* p_sig) { + // Format: [[HASTHIS] [EXPLICITTHIS]] (DEFAULT|VARARG|GENERIC GenParamCount) + // ParamCount RetType Param* [SENTINEL Param+] + if (**p_sig == IMAGE_CEE_CS_CALLCONV_GENERIC) { + *p_sig += 1; + + ULONG generic_count = 0; + if (!ParseNumber(p_sig, &generic_count)) { + return false; + } + } + + ULONG param_count = 0; + if (!ParseNumber(p_sig, ¶m_count)) { + return false; + } + + if (!ParseRetType(p_sig)) { + return false; + } + + bool sentinel_found = false; + for (ULONG i = 0; i < param_count; i++) { + if (**p_sig == ELEMENT_TYPE_SENTINEL) { + if (sentinel_found) { + return false; + } + + sentinel_found = true; + *p_sig += 1; + } + + + if (!ParseParam(p_sig)) { + return false; + } + } + + return true; +} + +bool ParseArrayShape(PCCOR_SIGNATURE* p_sig) { + // Format: Rank NumSizes Size* NumLoBounds LoBound* + ULONG rank = 0, numsizes = 0, size = 0; + if (!ParseNumber(p_sig, &rank) || !ParseNumber(p_sig, &numsizes)) { + return false; + } + + for (ULONG i = 0; i < numsizes; i++) { + if (!ParseNumber(p_sig, &size)) { + return false; + } + } + + if (!ParseNumber(p_sig, &numsizes)) { + return false; + } + + for (ULONG i = 0; i < numsizes; i++) { + if (!ParseNumber(p_sig, &size)) { + return false; + } + } + + return true; +} + +// Returns whether or not the Type signature at the given address could be parsed. +// If successful, the input pointer will point to the next byte following the Type signature. +// If not, the input pointer may point to invalid data. +bool ParseType(PCCOR_SIGNATURE* p_sig) { + /* + Format = BOOLEAN | CHAR | I1 | U1 | U2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U | STRING | OBJECT + | VALUETYPE TypeDefOrRefEncoded + | CLASS TypeDefOrRefEncoded + | PTR CustomMod* VOID + | PTR CustomMod* Type + | FNPTR MethodDefSig + | FNPTR MethodRefSig + | ARRAY Type ArrayShape + | SZARRAY CustomMod* Type + | GENERICINST (CLASS | VALUETYPE) TypeDefOrRefEncoded GenArgCount Type * + | VAR Number + | MVAR Number + */ + + const auto cor_element_type = CorElementType(**p_sig); + ULONG number = 0; + *p_sig += 1; + + switch (cor_element_type) { + case ELEMENT_TYPE_VOID: + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_STRING: + case ELEMENT_TYPE_OBJECT: + return true; + + case ELEMENT_TYPE_PTR: + // Format: PTR CustomMod* VOID + // Format: PTR CustomMod* Type + if (!ParseOptionalCustomMods(p_sig)) { + return false; + } + + if (**p_sig == ELEMENT_TYPE_VOID) { + *p_sig += 1; + return true; + } else { + return ParseType(p_sig); + } + + case ELEMENT_TYPE_VALUETYPE: + case ELEMENT_TYPE_CLASS: + // Format: CLASS TypeDefOrRefEncoded + // Format: VALUETYPE TypeDefOrRefEncoded + return ParseTypeDefOrRefEncoded(p_sig); + + case ELEMENT_TYPE_FNPTR: + // Format: FNPTR MethodDefSig + // Format: FNPTR MethodRefSig + return ParseMethod(p_sig); + + case ELEMENT_TYPE_ARRAY: + // Format: ARRAY Type ArrayShape + if (!ParseType(p_sig)) { + return false; + } + return ParseArrayShape(p_sig); + + case ELEMENT_TYPE_SZARRAY: + // Format: SZARRAY CustomMod* Type + if (!ParseOptionalCustomMods(p_sig)) { + return false; + } + return ParseType(p_sig); + + case ELEMENT_TYPE_GENERICINST: + if (**p_sig != ELEMENT_TYPE_VALUETYPE && **p_sig != ELEMENT_TYPE_CLASS) { + return false; + } + + *p_sig += 1; + if (!ParseTypeDefOrRefEncoded(p_sig)) { + return false; + } + + if (!ParseNumber(p_sig, &number)) { + return false; + } + + for (ULONG i = 0; i < number; i++) { + if (!ParseType(p_sig)) { + return false; + } + } + return true; + + case ELEMENT_TYPE_VAR: + case ELEMENT_TYPE_MVAR: + // Format: VAR Number + // Format: MVAR Number + return ParseNumber(p_sig, &number); + + default: + return false; + } +} +} \ No newline at end of file diff --git a/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.h b/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.h new file mode 100644 index 0000000000..483ab98548 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/sig_helpers.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace trace { + +bool ParseType(PCCOR_SIGNATURE* p_sig); + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/string.cpp b/src/Datadog.Trace.ClrProfiler.Native/string.cpp new file mode 100644 index 0000000000..ff9370e4bc --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/string.cpp @@ -0,0 +1,35 @@ +#include "string.h" +#include "miniutf.hpp" + +namespace trace { + +std::string ToString(const std::string& str) { return str; } +std::string ToString(const char* str) { return std::string(str); } +std::string ToString(const uint64_t i) { + std::stringstream ss; + ss << i; + return ss.str(); +} +std::string ToString(const WSTRING& wstr) { + std::u16string ustr(reinterpret_cast(wstr.c_str())); + return miniutf::to_utf8(ustr); +} + +WSTRING ToWSTRING(const std::string& str) { + auto ustr = miniutf::to_utf16(str); + return WSTRING(reinterpret_cast(ustr.c_str())); +} + +WSTRING ToWSTRING(const uint64_t i) { + const auto ustr = ToString(i); + return ToWSTRING(ustr); +} + +WCHAR operator"" _W(const char c) { return WCHAR(c); } + +WSTRING operator"" _W(const char* arr, size_t size) { + std::string str(arr, size); + return ToWSTRING(str); +} + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/string.h b/src/Datadog.Trace.ClrProfiler.Native/string.h new file mode 100644 index 0000000000..a45f4f954e --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/string.h @@ -0,0 +1,26 @@ +#ifndef DD_CLR_PROFILER_STRING_H_ +#define DD_CLR_PROFILER_STRING_H_ + +#include +#include +#include + +namespace trace { + +typedef std::basic_string WSTRING; +typedef std::basic_stringstream WSTRINGSTREAM; + +std::string ToString(const std::string& str); +std::string ToString(const char* str); +std::string ToString(const uint64_t i); +std::string ToString(const WSTRING& wstr); + +WSTRING ToWSTRING(const std::string& str); +WSTRING ToWSTRING(const uint64_t i); + +WCHAR operator"" _W(const char c); +WSTRING operator"" _W(const char* arr, size_t size); + +} // namespace trace + +#endif // DD_CLR_PROFILER_STRING_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/util.cpp b/src/Datadog.Trace.ClrProfiler.Native/util.cpp new file mode 100644 index 0000000000..6aa5dd0751 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/util.cpp @@ -0,0 +1,85 @@ +#include "util.h" + +#include +#include +#include +#include +#include +#include "miniutf.hpp" +#include "pal.h" + +namespace trace { + +template +void Split(const WSTRING &s, wchar_t delim, Out result) { + size_t lpos = 0; + for (size_t i = 0; i < s.length(); i++) { + if (s[i] == delim) { + *(result++) = s.substr(lpos, (i - lpos)); + lpos = i + 1; + } + } + *(result++) = s.substr(lpos); +} + +std::vector Split(const WSTRING &s, wchar_t delim) { + std::vector elems; + Split(s, delim, std::back_inserter(elems)); + return elems; +} + +WSTRING Trim(const WSTRING &str) { + if (str.length() == 0) { + return ""_W; + } + + WSTRING trimmed = str; + + auto lpos = trimmed.find_first_not_of(" \t"_W); + if (lpos != WSTRING::npos && lpos > 0) { + trimmed = trimmed.substr(lpos); + } + + auto rpos = trimmed.find_last_not_of(" \t"_W); + if (rpos != WSTRING::npos) { + trimmed = trimmed.substr(0, rpos + 1); + } + + return trimmed; +} + +WSTRING GetEnvironmentValue(const WSTRING &name) { +#ifdef _WIN32 + const size_t max_buf_size = 4096; + WSTRING buf(max_buf_size, 0); + auto len = + GetEnvironmentVariable(name.data(), buf.data(), (DWORD)(buf.size())); + return Trim(buf.substr(0, len)); +#else + auto cstr = std::getenv(ToString(name).c_str()); + if (cstr == nullptr) { + return ""_W; + } + std::string str(cstr); + auto wstr = ToWSTRING(str); + return Trim(wstr); +#endif +} + +std::vector GetEnvironmentValues(const WSTRING &name, + const wchar_t delim) { + std::vector values; + for (auto s : Split(GetEnvironmentValue(name), delim)) { + s = Trim(s); + if (!s.empty()) { + values.push_back(s); + } + } + return values; +} + +std::vector GetEnvironmentValues(const WSTRING &name) { + return GetEnvironmentValues(name, L';'); +} + +} // namespace trace diff --git a/src/Datadog.Trace.ClrProfiler.Native/util.h b/src/Datadog.Trace.ClrProfiler.Native/util.h new file mode 100644 index 0000000000..c57c3ce844 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/util.h @@ -0,0 +1,41 @@ +#ifndef DD_CLR_PROFILER_UTIL_H_ +#define DD_CLR_PROFILER_UTIL_H_ + +#include +#include +#include +#include + +#include "string.h" + +namespace trace { + +template +void Split(const WSTRING &s, wchar_t delim, Out result); + +// Split splits a string by the given delimiter. +std::vector Split(const WSTRING &s, wchar_t delim); + +// Trim removes space from the beginning and end of a string. +WSTRING Trim(const WSTRING &str); + +// GetEnvironmentValue returns the environment variable value for the given +// name. Space is trimmed. +WSTRING GetEnvironmentValue(const WSTRING &name); + +// GetEnvironmentValues returns environment variable values for the given name +// split by the delimiter. Space is trimmed and empty values are ignored. +std::vector GetEnvironmentValues(const WSTRING &name, + const wchar_t delim); + +// GetEnvironmentValues calls GetEnvironmentValues with a semicolon delimiter. +std::vector GetEnvironmentValues(const WSTRING &name); + +template +bool Contains(const Container &items, + const typename Container::value_type &value) { + return std::find(items.begin(), items.end(), value) != items.end(); +} +} // namespace trace + +#endif // DD_CLR_PROFILER_UTIL_H_ diff --git a/src/Datadog.Trace.ClrProfiler.Native/version.h b/src/Datadog.Trace.ClrProfiler.Native/version.h new file mode 100644 index 0000000000..be5d0d9743 --- /dev/null +++ b/src/Datadog.Trace.ClrProfiler.Native/version.h @@ -0,0 +1,3 @@ +#pragma once + +constexpr auto PROFILER_VERSION = "1.19.1"; diff --git a/src/Datadog.Trace.OpenTracing/AssemblyInfo.cs b/src/Datadog.Trace.OpenTracing/AssemblyInfo.cs new file mode 100644 index 0000000000..37841736d2 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/AssemblyInfo.cs @@ -0,0 +1,5 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Datadog.Trace.OpenTracing.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.OpenTracing.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/src/Datadog.Trace.OpenTracing/Datadog.Trace.OpenTracing.csproj b/src/Datadog.Trace.OpenTracing/Datadog.Trace.OpenTracing.csproj new file mode 100644 index 0000000000..076648731b --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/Datadog.Trace.OpenTracing.csproj @@ -0,0 +1,24 @@ + + + + + 1.19.1 + Datadog APM - OpenTracing + Provides OpenTracing support for Datadog APM + $(PackageTags);OpenTracing + + + + + + + + + + + + + + + + diff --git a/src/Datadog.Trace.OpenTracing/DatadogTags.cs b/src/Datadog.Trace.OpenTracing/DatadogTags.cs new file mode 100644 index 0000000000..577a20ce4b --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/DatadogTags.cs @@ -0,0 +1,28 @@ +namespace Datadog.Trace.OpenTracing +{ + /// + /// This set of tags is used by the OpenTracing compatible tracer to set DataDog specific fields. + /// + public static class DatadogTags + { + /// + /// This tag sets the service name + /// + public const string ServiceName = "service.name"; + + /// + /// This tag sets the service version + /// + public const string ServiceVersion = "service.version"; + + /// + /// This tag sets resource name + /// + public const string ResourceName = "resource.name"; + + /// + /// This tag sets the span type + /// + public const string SpanType = "span.type"; + } +} diff --git a/src/Datadog.Trace.OpenTracing/HttpHeadersCodec.cs b/src/Datadog.Trace.OpenTracing/HttpHeadersCodec.cs new file mode 100644 index 0000000000..2a5528c793 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/HttpHeadersCodec.cs @@ -0,0 +1,50 @@ +using System; +using System.Globalization; +using Datadog.Trace.Headers; +using OpenTracing.Propagation; + +namespace Datadog.Trace.OpenTracing +{ + internal class HttpHeadersCodec : ICodec + { + private static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; + + public global::OpenTracing.ISpanContext Extract(object carrier) + { + var map = carrier as ITextMap; + + if (map == null) + { + throw new ArgumentException("Carrier should have type ITextMap", nameof(carrier)); + } + + IHeadersCollection headers = new TextMapHeadersCollection(map); + var propagationContext = SpanContextPropagator.Instance.Extract(headers); + return new OpenTracingSpanContext(propagationContext); + } + + public void Inject(global::OpenTracing.ISpanContext context, object carrier) + { + var map = carrier as ITextMap; + + if (map == null) + { + throw new ArgumentException("Carrier should have type ITextMap", nameof(carrier)); + } + + IHeadersCollection headers = new TextMapHeadersCollection(map); + + if (context is OpenTracingSpanContext otSpanContext && otSpanContext.Context is SpanContext ddSpanContext) + { + // this is a Datadog context + SpanContextPropagator.Instance.Inject(ddSpanContext, headers); + } + else + { + // any other OpenTracing.ISpanContext + headers.Set(HttpHeaderNames.TraceId, context.TraceId.ToString(InvariantCulture)); + headers.Set(HttpHeaderNames.ParentId, context.SpanId.ToString(InvariantCulture)); + } + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/ICodec.cs b/src/Datadog.Trace.OpenTracing/ICodec.cs new file mode 100644 index 0000000000..f9fe83bc93 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/ICodec.cs @@ -0,0 +1,9 @@ +namespace Datadog.Trace.OpenTracing +{ + internal interface ICodec + { + void Inject(global::OpenTracing.ISpanContext spanContext, object carrier); + + global::OpenTracing.ISpanContext Extract(object carrier); + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingHttpHeadersCarrier.cs b/src/Datadog.Trace.OpenTracing/OpenTracingHttpHeadersCarrier.cs new file mode 100644 index 0000000000..a08464eb8e --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingHttpHeadersCarrier.cs @@ -0,0 +1,79 @@ +using System.Collections; +using System.Collections.Generic; +using System.Net.Http.Headers; +using OpenTracing.Propagation; + +namespace Datadog.Trace.OpenTracing +{ + /// + /// This class wraps a to implement the interface + /// to enable injecting context propagation headers on outgoing http requests. + /// + /// + public class OpenTracingHttpHeadersCarrier : ITextMap + { + private HttpHeaders _headers; + + /// + /// Initializes a new instance of the class. + /// + /// The to wrap. + public OpenTracingHttpHeadersCarrier(HttpHeaders headers) + { + _headers = headers; + } + + /// + /// Returns the key's value from the underlying source, or null if the key doesn't exist. + /// + /// The key for which a value should be returned. + /// The key's value + public string Get(string key) + { + _headers.TryGetValues(key, out IEnumerable values); + if (values == null) + { + return null; + } + + // Comma appears to be the right separator to join several values for the same header name + // source: https://stackoverflow.com/a/3097052 + return string.Join(",", values); + } + + /// + /// Returns all key:value pairs from the underlying source. + /// Note that for some Formats, the iterator may include entries that + /// were never injected by a Tracer implementation (e.g., unrelated HTTP headers). + /// + /// All key value pairs + public IEnumerator> GetEnumerator() + { + foreach (KeyValuePair> header in _headers) + { + yield return new KeyValuePair(header.Key, header.Value == null ? null : string.Join(",", header.Value)); + } + } + + /// + /// Returns an enumerator that iterates through the header collection. + /// + /// An System.Collections.IEnumerator object that can be used to iterate through the header collection. + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + /// + /// Adds a key:value pair into the underlying source. If the source already contains the key, the value will be overwritten. + /// + /// A string, possibly with constraints dictated by the particular Format this is paired with. + /// A String, possibly with constraints dictated by the particular Format this is paired with. + public void Set(string key, string value) + { + // We remove all the existing values for that key before adding the new one to have a "set" behavior + _headers.Remove(key); + _headers.Add(key, value); + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingSpan.cs b/src/Datadog.Trace.OpenTracing/OpenTracingSpan.cs new file mode 100644 index 0000000000..3be5bf0f88 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingSpan.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using OpenTracing; +using OpenTracing.Tag; + +namespace Datadog.Trace.OpenTracing +{ + internal class OpenTracingSpan : ISpan + { + internal OpenTracingSpan(Span span) + { + Span = span; + Context = new OpenTracingSpanContext(span.Context); + } + + public OpenTracingSpanContext Context { get; } + + global::OpenTracing.ISpanContext ISpan.Context => Context; + + internal Span Span { get; } + + // TODO lucas: inline this in a separate commit, it will modify a lot of files + // This is only exposed for tests + internal Span DDSpan => Span; + + internal string OperationName => Span.OperationName; + + internal TimeSpan Duration => Span.Duration; + + public string GetBaggageItem(string key) => null; + + public ISpan Log(DateTimeOffset timestamp, IEnumerable> fields) => this; + + public ISpan Log(string eventName) => this; + + public ISpan Log(DateTimeOffset timestamp, string eventName) => this; + + public ISpan Log(IEnumerable> fields) => this; + + public ISpan SetBaggageItem(string key, string value) => this; + + public ISpan SetOperationName(string operationName) + { + Span.OperationName = operationName; + return this; + } + + public string GetTag(string key) + { + return Span.GetTag(key); + } + + public ISpan SetTag(string key, bool value) + { + return SetTag(key, value.ToString()); + } + + public ISpan SetTag(string key, double value) + { + return SetTag(key, value.ToString(CultureInfo.InvariantCulture)); + } + + public ISpan SetTag(string key, int value) + { + return SetTag(key, value.ToString(CultureInfo.InvariantCulture)); + } + + public ISpan SetTag(BooleanTag tag, bool value) + { + return SetTag(tag.Key, value); + } + + public ISpan SetTag(IntOrStringTag tag, string value) + { + return SetTag(tag.Key, value); + } + + public ISpan SetTag(IntTag tag, int value) + { + return SetTag(tag.Key, value); + } + + public ISpan SetTag(StringTag tag, string value) + { + return SetTag(tag.Key, value); + } + + public ISpan SetTag(string key, string value) + { + // TODO:bertrand do we want this behavior on the Span object too ? + + switch (key) + { + case DatadogTags.ResourceName: + Span.ResourceName = value; + return this; + case DatadogTags.SpanType: + Span.Type = value; + return this; + case DatadogTags.ServiceName: + Span.ServiceName = value; + return this; + case DatadogTags.ServiceVersion: + Span.SetTag(Tags.Version, value); + break; // Continue to set the requested tag + } + + if (key == global::OpenTracing.Tag.Tags.Error.Key) + { + Span.Error = value == bool.TrueString; + return this; + } + + Span.SetTag(key, value); + return this; + } + + public void Finish() + { + Span.Finish(); + } + + public void Finish(DateTimeOffset finishTimestamp) + { + Span.Finish(finishTimestamp); + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingSpanBuilder.cs b/src/Datadog.Trace.OpenTracing/OpenTracingSpanBuilder.cs new file mode 100644 index 0000000000..e1ad2d4f03 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingSpanBuilder.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using Datadog.Trace.Logging; +using OpenTracing; +using OpenTracing.Tag; + +namespace Datadog.Trace.OpenTracing +{ + internal class OpenTracingSpanBuilder : ISpanBuilder + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly OpenTracingTracer _tracer; + private readonly object _lock = new object(); + private readonly string _operationName; + private global::OpenTracing.ISpanContext _parent; + private DateTimeOffset? _start; + private Dictionary _tags; + private string _serviceName; + private bool _ignoreActiveSpan; + + internal OpenTracingSpanBuilder(OpenTracingTracer tracer, string operationName) + { + _tracer = tracer; + _operationName = operationName; + } + + public ISpanBuilder AddReference(string referenceType, global::OpenTracing.ISpanContext referencedContext) + { + lock (_lock) + { + if (referenceType == References.ChildOf) + { + _parent = referencedContext; + return this; + } + } + + Log.Debug("ISpanBuilder.AddReference is not implemented for other references than ChildOf by Datadog.Trace"); + return this; + } + + public ISpanBuilder AsChildOf(ISpan parent) + { + lock (_lock) + { + _parent = parent.Context; + return this; + } + } + + public ISpanBuilder AsChildOf(global::OpenTracing.ISpanContext parent) + { + lock (_lock) + { + _parent = parent; + return this; + } + } + + public ISpanBuilder IgnoreActiveSpan() + { + _ignoreActiveSpan = true; + return this; + } + + public ISpan Start() + { + lock (_lock) + { + ISpanContext parentContext = GetParentContext(); + Span ddSpan = _tracer.DatadogTracer.StartSpan(_operationName, parentContext, _serviceName, _start, _ignoreActiveSpan); + var otSpan = new OpenTracingSpan(ddSpan); + + if (_tags != null) + { + foreach (var pair in _tags) + { + otSpan.SetTag(pair.Key, pair.Value); + } + } + + return otSpan; + } + } + + public IScope StartActive() + { + return StartActive(finishSpanOnDispose: true); + } + + public IScope StartActive(bool finishSpanOnDispose) + { + var span = Start(); + return _tracer.ScopeManager.Activate(span, finishSpanOnDispose); + } + + public ISpanBuilder WithStartTimestamp(DateTimeOffset startTimestamp) + { + lock (_lock) + { + _start = startTimestamp; + return this; + } + } + + public ISpanBuilder WithTag(string key, bool value) + { + return WithTag(key, value.ToString()); + } + + public ISpanBuilder WithTag(string key, double value) + { + return WithTag(key, value.ToString(CultureInfo.InvariantCulture)); + } + + public ISpanBuilder WithTag(string key, int value) + { + return WithTag(key, value.ToString(CultureInfo.InvariantCulture)); + } + + public ISpanBuilder WithTag(BooleanTag tag, bool value) + { + return WithTag(tag.Key, value); + } + + public ISpanBuilder WithTag(IntOrStringTag tag, string value) + { + return WithTag(tag.Key, value); + } + + public ISpanBuilder WithTag(IntTag tag, int value) + { + return WithTag(tag.Key, value.ToString(CultureInfo.InvariantCulture)); + } + + public ISpanBuilder WithTag(StringTag tag, string value) + { + return WithTag(tag.Key, value); + } + + public ISpanBuilder WithTag(string key, string value) + { + lock (_lock) + { + if (key == DatadogTags.ServiceName) + { + _serviceName = value; + return this; + } + + if (_tags == null) + { + _tags = new Dictionary(); + } + + _tags[key] = value; + return this; + } + } + + private ISpanContext GetParentContext() + { + var openTracingSpanContext = _parent as OpenTracingSpanContext; + var parentContext = openTracingSpanContext?.Context; + + if (parentContext == null && !_ignoreActiveSpan) + { + // if parent was not set explicitly, default to active span as parent (unless disabled) + return _tracer.ActiveSpan?.Span.Context; + } + + return parentContext; + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingSpanContext.cs b/src/Datadog.Trace.OpenTracing/OpenTracingSpanContext.cs new file mode 100644 index 0000000000..4105b68bfc --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingSpanContext.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.OpenTracing +{ + internal class OpenTracingSpanContext : global::OpenTracing.ISpanContext + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + public OpenTracingSpanContext(ISpanContext context) + { + Context = context; + } + + public string TraceId => Context.TraceId.ToString(CultureInfo.InvariantCulture); + + public string SpanId => Context.SpanId.ToString(CultureInfo.InvariantCulture); + + internal ISpanContext Context { get; } + + public IEnumerable> GetBaggageItems() + { + return Enumerable.Empty>(); + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingTracer.cs b/src/Datadog.Trace.OpenTracing/OpenTracingTracer.cs new file mode 100644 index 0000000000..980ef89dfd --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingTracer.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Logging; +using OpenTracing; +using OpenTracing.Propagation; + +namespace Datadog.Trace.OpenTracing +{ + internal class OpenTracingTracer : ITracer + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly Dictionary _codecs; + + public OpenTracingTracer(IDatadogTracer datadogTracer) + : this(datadogTracer, new global::OpenTracing.Util.AsyncLocalScopeManager()) + { + } + + public OpenTracingTracer(IDatadogTracer datadogTracer, global::OpenTracing.IScopeManager scopeManager) + { + DatadogTracer = datadogTracer; + DefaultServiceName = datadogTracer.DefaultServiceName; + ScopeManager = scopeManager; + _codecs = new Dictionary + { + { BuiltinFormats.HttpHeaders.ToString(), new HttpHeadersCodec() }, + { BuiltinFormats.TextMap.ToString(), new HttpHeadersCodec() } // the HttpHeadersCodec can support an unconstrained ITextMap + }; + } + + public IDatadogTracer DatadogTracer { get; } + + public string DefaultServiceName { get; } + + public global::OpenTracing.IScopeManager ScopeManager { get; } + + public OpenTracingSpan ActiveSpan => (OpenTracingSpan)ScopeManager.Active?.Span; + + ISpan ITracer.ActiveSpan => ScopeManager.Active?.Span; + + public ISpanBuilder BuildSpan(string operationName) + { + return new OpenTracingSpanBuilder(this, operationName); + } + + public global::OpenTracing.ISpanContext Extract(IFormat format, TCarrier carrier) + { + _codecs.TryGetValue(format.ToString(), out ICodec codec); + + if (codec != null) + { + return codec.Extract(carrier); + } + + throw new NotSupportedException($"Tracer.Extract is not implemented for {format} by Datadog.Trace"); + } + + public void Inject(global::OpenTracing.ISpanContext spanContext, IFormat format, TCarrier carrier) + { + _codecs.TryGetValue(format.ToString(), out ICodec codec); + + if (codec != null) + { + codec.Inject(spanContext, carrier); + } + else + { + throw new NotSupportedException($"Tracer.Inject is not implemented for {format} by Datadog.Trace"); + } + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/OpenTracingTracerFactory.cs b/src/Datadog.Trace.OpenTracing/OpenTracingTracerFactory.cs new file mode 100644 index 0000000000..02a669aa61 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/OpenTracingTracerFactory.cs @@ -0,0 +1,40 @@ +using System; +using System.Net.Http; +using OpenTracing; + +namespace Datadog.Trace.OpenTracing +{ + /// + /// This class contains factory methods to instantiate an OpenTracing compatible tracer that sends data to DataDog + /// + public static class OpenTracingTracerFactory + { + /// + /// Create a new Datadog compatible ITracer implementation with the given parameters + /// + /// The agent endpoint where the traces will be sent (default is http://localhost:8126). + /// Default name of the service (default is the name of the executing assembly). + /// Turns on all debug logging (this may have an impact on application performance). + /// A Datadog compatible ITracer implementation + public static ITracer CreateTracer(Uri agentEndpoint = null, string defaultServiceName = null, bool isDebugEnabled = false) + { + return CreateTracer(agentEndpoint, defaultServiceName, null, isDebugEnabled); + } + + /// + /// Create a new Datadog compatible ITracer implementation using an existing Datadog Tracer instance + /// + /// Existing Datadog Tracer instance + /// A Datadog compatible ITracer implementation + public static ITracer WrapTracer(Tracer tracer) + { + return new OpenTracingTracer(tracer); + } + + internal static OpenTracingTracer CreateTracer(Uri agentEndpoint, string defaultServiceName, DelegatingHandler delegatingHandler, bool isDebugEnabled) + { + var tracer = Tracer.Create(agentEndpoint, defaultServiceName, isDebugEnabled); + return new OpenTracingTracer(tracer); + } + } +} diff --git a/src/Datadog.Trace.OpenTracing/TextMapHeadersCollection.cs b/src/Datadog.Trace.OpenTracing/TextMapHeadersCollection.cs new file mode 100644 index 0000000000..1b76660d26 --- /dev/null +++ b/src/Datadog.Trace.OpenTracing/TextMapHeadersCollection.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Headers; +using OpenTracing.Propagation; + +namespace Datadog.Trace.OpenTracing +{ + internal class TextMapHeadersCollection : IHeadersCollection + { + private readonly ITextMap _textMap; + + public TextMapHeadersCollection(ITextMap textMap) + { + _textMap = textMap; + } + + public IEnumerable GetValues(string name) + { + foreach (var pair in _textMap) + { + if (string.Equals(pair.Key, name, StringComparison.OrdinalIgnoreCase)) + { + yield return pair.Value; + } + } + } + + public void Set(string name, string value) + { + _textMap.Set(name, value); + } + + public void Add(string name, string value) + { + throw new NotImplementedException(); + } + + public void Remove(string name) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Datadog.Trace/Abstractions/IScope.cs b/src/Datadog.Trace/Abstractions/IScope.cs new file mode 100644 index 0000000000..9da4cac992 --- /dev/null +++ b/src/Datadog.Trace/Abstractions/IScope.cs @@ -0,0 +1,9 @@ +using System; + +namespace Datadog.Trace.Abstractions +{ + internal interface IScope : IDisposable + { + ISpan Span { get; } + } +} diff --git a/src/Datadog.Trace/Abstractions/ISpan.cs b/src/Datadog.Trace/Abstractions/ISpan.cs new file mode 100644 index 0000000000..0a5a4b7a91 --- /dev/null +++ b/src/Datadog.Trace/Abstractions/ISpan.cs @@ -0,0 +1,22 @@ +using System; + +namespace Datadog.Trace.Abstractions +{ + internal interface ISpan + { + string ResourceName { get; set; } + + string Type { get; set; } + + /// + /// Gets or sets a value indicating whether this span represents an error. + /// + bool Error { get; set; } + + ISpan SetTag(string key, string value); + + string GetTag(string key); + + void SetException(Exception exception); + } +} diff --git a/src/Datadog.Trace/Agent/AgentWriter.cs b/src/Datadog.Trace/Agent/AgentWriter.cs new file mode 100644 index 0000000000..37d032a3da --- /dev/null +++ b/src/Datadog.Trace/Agent/AgentWriter.cs @@ -0,0 +1,132 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.StatsdClient; + +namespace Datadog.Trace.Agent +{ + internal class AgentWriter : IAgentWriter + { + private const int TraceBufferSize = 1000; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly AgentWriterBuffer _tracesBuffer = new AgentWriterBuffer(TraceBufferSize); + private readonly IStatsd _statsd; + private readonly Task _flushTask; + private readonly TaskCompletionSource _processExit = new TaskCompletionSource(); + + private IApi _api; + + public AgentWriter(IApi api, IStatsd statsd) + : this(api, statsd, automaticFlush: true) + { + } + + internal AgentWriter(IApi api, IStatsd statsd, bool automaticFlush) + { + _api = api; + _statsd = statsd; + + _flushTask = automaticFlush ? Task.Run(FlushTracesTaskLoopAsync) : Task.FromResult(true); + } + + public void OverrideApi(IApi api) + { + _api = api; + } + + public Task Ping() + { + return _api.SendTracesAsync(new Span[0][]); + } + + public void WriteTrace(Span[] trace) + { + var success = _tracesBuffer.Push(trace); + + if (!success) + { + Log.Debug("Trace buffer is full. Dropping a trace from the buffer."); + } + + if (_statsd != null) + { + _statsd.AppendIncrementCount(TracerMetricNames.Queue.EnqueuedTraces); + _statsd.AppendIncrementCount(TracerMetricNames.Queue.EnqueuedSpans, trace.Length); + + if (!success) + { + _statsd.AppendIncrementCount(TracerMetricNames.Queue.DroppedTraces); + _statsd.AppendIncrementCount(TracerMetricNames.Queue.DroppedSpans, trace.Length); + } + + _statsd.Send(); + } + } + + public async Task FlushAndCloseAsync() + { + if (!_processExit.TrySetResult(true)) + { + return; + } + + await Task.WhenAny(_flushTask, Task.Delay(TimeSpan.FromSeconds(20))) + .ConfigureAwait(false); + + if (!_flushTask.IsCompleted) + { + Log.Warning("Could not flush all traces before process exit"); + } + } + + public async Task FlushTracesAsync() + { + var traces = _tracesBuffer.Pop(); + + if (_statsd != null) + { + var spanCount = traces.Sum(t => t.Length); + + _statsd.AppendIncrementCount(TracerMetricNames.Queue.DequeuedTraces, traces.Length); + _statsd.AppendIncrementCount(TracerMetricNames.Queue.DequeuedSpans, spanCount); + _statsd.AppendSetGauge(TracerMetricNames.Queue.MaxTraces, TraceBufferSize); + _statsd.Send(); + } + + if (traces.Length > 0) + { + await _api.SendTracesAsync(traces).ConfigureAwait(false); + } + } + + private async Task FlushTracesTaskLoopAsync() + { + while (true) + { + try + { + await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(1)), _processExit.Task) + .ConfigureAwait(false); + + if (_processExit.Task.IsCompleted) + { + await FlushTracesAsync().ConfigureAwait(false); + return; + } + else + { + await FlushTracesAsync().ConfigureAwait(false); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "An unhandled error occurred during the flushing task"); + } + } + } + } +} diff --git a/src/Datadog.Trace/Agent/AgentWriterBuffer.cs b/src/Datadog.Trace/Agent/AgentWriterBuffer.cs new file mode 100644 index 0000000000..0ac299a041 --- /dev/null +++ b/src/Datadog.Trace/Agent/AgentWriterBuffer.cs @@ -0,0 +1,53 @@ +using System; + +namespace Datadog.Trace.Agent +{ + internal class AgentWriterBuffer + { + private readonly Random _random = new Random(); + private readonly T[] _items; + + private int _count; + + public AgentWriterBuffer(int maxSize) + { + _items = new T[maxSize]; + } + + public bool Push(T item) + { + lock (_items) + { + if (_count < _items.Length) + { + _items[_count++] = item; + return true; + } + else + { + // drop a random trace. + // note that Random.Next() is NOT thread-safe, + // but we are running this inside a lock + _items[_random.Next(_items.Length)] = item; + return false; + } + } + } + + public T[] Pop() + { + lock (_items) + { + // copy items from buffer into new array + var result = new T[_count]; + Array.Copy(_items, result, _count); + + // clear buffer + Array.Clear(_items, 0, _items.Length); + _count = 0; + + return result; + } + } + } +} diff --git a/src/Datadog.Trace/Agent/Api.cs b/src/Datadog.Trace/Agent/Api.cs new file mode 100644 index 0000000000..df45002fe6 --- /dev/null +++ b/src/Datadog.Trace/Agent/Api.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.Net.Sockets; +using System.Threading.Tasks; +using Datadog.Trace.Agent.MessagePack; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.Logging; +using Datadog.Trace.PlatformHelpers; +using Datadog.Trace.Vendors.StatsdClient; +using Newtonsoft.Json; + +namespace Datadog.Trace.Agent +{ + internal class Api : IApi + { + private const string TracesPath = "/v0.4/traces"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly IApiRequestFactory _apiRequestFactory; + private readonly IStatsd _statsd; + private readonly Uri _tracesEndpoint; + private readonly FormatterResolverWrapper _formatterResolver = new FormatterResolverWrapper(SpanFormatterResolver.Instance); + private readonly string _containerId; + private readonly FrameworkDescription _frameworkDescription; + + public Api(Uri baseEndpoint, IApiRequestFactory apiRequestFactory, IStatsd statsd) + { + Log.Debug("Creating new Api"); + + _tracesEndpoint = new Uri(baseEndpoint, TracesPath); + _statsd = statsd; + _containerId = ContainerMetadata.GetContainerId(); + _apiRequestFactory = apiRequestFactory ?? new ApiWebRequestFactory(); + + // report runtime details + try + { + _frameworkDescription = FrameworkDescription.Create(); + + if (_frameworkDescription != null) + { + Log.Information(_frameworkDescription.ToString()); + } + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting framework description"); + } + } + + public async Task SendTracesAsync(Span[][] traces) + { + // retry up to 5 times with exponential back-off + var retryLimit = 5; + var retryCount = 1; + var sleepDuration = 100; // in milliseconds + var traceIds = GetUniqueTraceIds(traces); + + while (true) + { + var request = _apiRequestFactory.Create(_tracesEndpoint); + + // Set additional headers + request.AddHeader(AgentHttpHeaderNames.TraceCount, traceIds.Count.ToString()); + if (_frameworkDescription != null) + { + request.AddHeader(AgentHttpHeaderNames.LanguageInterpreter, _frameworkDescription.Name); + request.AddHeader(AgentHttpHeaderNames.LanguageVersion, _frameworkDescription.ProductVersion); + } + + if (_containerId != null) + { + request.AddHeader(AgentHttpHeaderNames.ContainerId, _containerId); + } + + bool success = false; + Exception exception = null; + + try + { + success = await SendTracesAsync(traces, request).ConfigureAwait(false); + } + catch (Exception ex) + { +#if DEBUG + if (ex.InnerException is InvalidOperationException ioe) + { + Log.Error(ex, "An error occurred while sending traces to the agent at {0}", _tracesEndpoint); + return false; + } +#endif + exception = ex; + } + + // Error handling block + if (!success) + { + bool isSocketException = false; + + if (exception?.InnerException is SocketException se) + { + isSocketException = true; + Log.Error(se, "Unable to communicate with the trace agent at {0}", _tracesEndpoint); + TracingProcessManager.TryForceTraceAgentRefresh(); + } + + if (retryCount >= retryLimit) + { + // stop retrying + Log.Error(exception, "An error occurred while sending traces to the agent at {0}", _tracesEndpoint); + return false; + } + + // retry + await Task.Delay(sleepDuration).ConfigureAwait(false); + retryCount++; + sleepDuration *= 2; + + if (isSocketException) + { + // Ensure we have the most recent port before trying again + TracingProcessManager.TraceAgentMetadata.ForcePortFileRead(); + } + + continue; + } + + _statsd?.Send(); + return true; + } + } + + private static HashSet GetUniqueTraceIds(Span[][] traces) + { + var uniqueTraceIds = new HashSet(); + + foreach (var trace in traces) + { + foreach (var span in trace) + { + uniqueTraceIds.Add(span.TraceId); + } + } + + return uniqueTraceIds; + } + + private async Task SendTracesAsync(Span[][] traces, IApiRequest request) + { + IApiResponse response = null; + + try + { + try + { + _statsd?.AppendIncrementCount(TracerMetricNames.Api.Requests); + response = await request.PostAsync(traces, _formatterResolver).ConfigureAwait(false); + } + catch + { + // count only network/infrastructure errors, not valid responses with error status codes + // (which are handled below) + _statsd?.AppendIncrementCount(TracerMetricNames.Api.Errors); + throw; + } + + if (_statsd != null) + { + // don't bother creating the tags array if trace metrics are disabled + string[] tags = { $"status:{response.StatusCode}" }; + + // count every response, grouped by status code + _statsd.AppendIncrementCount(TracerMetricNames.Api.Responses, tags: tags); + } + + // Attempt a retry if the status code is not SUCCESS + if (response.StatusCode < 200 || response.StatusCode >= 300) + { + return false; + } + + try + { + if (response.ContentLength > 0 && Tracer.Instance.Sampler != null) + { + var responseContent = await response.ReadAsStringAsync().ConfigureAwait(false); + var apiResponse = JsonConvert.DeserializeObject(responseContent); + Tracer.Instance.Sampler.SetDefaultSampleRates(apiResponse?.RateByService); + } + } + catch (Exception ex) + { + Log.Error(ex, "Traces sent successfully to the Agent at {0}, but an error occurred deserializing the response.", _tracesEndpoint); + } + } + finally + { + response?.Dispose(); + } + + return true; + } + + internal class ApiResponse + { + [JsonProperty("rate_by_service")] + public Dictionary RateByService { get; set; } + } + } +} diff --git a/src/Datadog.Trace/Agent/ApiWebRequest.cs b/src/Datadog.Trace/Agent/ApiWebRequest.cs new file mode 100644 index 0000000000..788bddfd9c --- /dev/null +++ b/src/Datadog.Trace/Agent/ApiWebRequest.cs @@ -0,0 +1,52 @@ +using System.Net; +using System.Threading.Tasks; +using Datadog.Trace.Agent.MessagePack; +using Datadog.Trace.Vendors.MessagePack; + +namespace Datadog.Trace.Agent +{ + internal class ApiWebRequest : IApiRequest + { + private readonly HttpWebRequest _request; + + public ApiWebRequest(HttpWebRequest request) + { + _request = request; + + // Default headers + _request.Headers.Add(AgentHttpHeaderNames.Language, ".NET"); + _request.Headers.Add(AgentHttpHeaderNames.TracerVersion, TracerConstants.AssemblyVersion); + + // don't add automatic instrumentation to requests from this HttpClient + _request.Headers.Add(HttpHeaderNames.TracingEnabled, "false"); + } + + public void AddHeader(string name, string value) + { + _request.Headers.Add(name, value); + } + + public async Task PostAsync(Span[][] traces, FormatterResolverWrapper formatterResolver) + { + _request.Method = "POST"; + + _request.ContentType = "application/msgpack"; + using (var requestStream = await _request.GetRequestStreamAsync().ConfigureAwait(false)) + { + await MessagePackSerializer.SerializeAsync(requestStream, traces, formatterResolver).ConfigureAwait(false); + } + + try + { + var httpWebResponse = (HttpWebResponse)await _request.GetResponseAsync().ConfigureAwait(false); + return new ApiWebResponse(httpWebResponse); + } + catch (WebException exception) + when (exception.Status == WebExceptionStatus.ProtocolError && exception.Response != null) + { + // If the exception is caused by an error status code, ignore it and let the caller handle the result + return new ApiWebResponse((HttpWebResponse)exception.Response); + } + } + } +} diff --git a/src/Datadog.Trace/Agent/ApiWebRequestFactory.cs b/src/Datadog.Trace/Agent/ApiWebRequestFactory.cs new file mode 100644 index 0000000000..89eddacab6 --- /dev/null +++ b/src/Datadog.Trace/Agent/ApiWebRequestFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Net; + +namespace Datadog.Trace.Agent +{ + internal class ApiWebRequestFactory : IApiRequestFactory + { + public IApiRequest Create(Uri endpoint) + { + return new ApiWebRequest(WebRequest.CreateHttp(endpoint)); + } + } +} diff --git a/src/Datadog.Trace/Agent/ApiWebResponse.cs b/src/Datadog.Trace/Agent/ApiWebResponse.cs new file mode 100644 index 0000000000..93c1092871 --- /dev/null +++ b/src/Datadog.Trace/Agent/ApiWebResponse.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace Datadog.Trace.Agent +{ + internal class ApiWebResponse : IApiResponse, IDisposable + { + private readonly HttpWebResponse _response; + + public ApiWebResponse(HttpWebResponse response) + { + _response = response; + } + + public int StatusCode => (int)_response.StatusCode; + + public long ContentLength => _response.ContentLength; + + public async Task ReadAsStringAsync() + { + using (var responseStream = _response.GetResponseStream()) + { + var reader = new StreamReader(responseStream); + return await reader.ReadToEndAsync().ConfigureAwait(false); + } + } + + public void Dispose() + { + _response?.Dispose(); + } + } +} diff --git a/src/Datadog.Trace/Agent/IAgentWriter.cs b/src/Datadog.Trace/Agent/IAgentWriter.cs new file mode 100644 index 0000000000..f498572e61 --- /dev/null +++ b/src/Datadog.Trace/Agent/IAgentWriter.cs @@ -0,0 +1,17 @@ +using System.Threading.Tasks; + +namespace Datadog.Trace.Agent +{ + internal interface IAgentWriter + { + void WriteTrace(Span[] trace); + + Task Ping(); + + Task FlushTracesAsync(); + + Task FlushAndCloseAsync(); + + void OverrideApi(IApi api); + } +} diff --git a/src/Datadog.Trace/Agent/IApi.cs b/src/Datadog.Trace/Agent/IApi.cs new file mode 100644 index 0000000000..a6972667f3 --- /dev/null +++ b/src/Datadog.Trace/Agent/IApi.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Datadog.Trace.Agent +{ + internal interface IApi + { + Task SendTracesAsync(Span[][] traces); + } +} diff --git a/src/Datadog.Trace/Agent/IApiRequest.cs b/src/Datadog.Trace/Agent/IApiRequest.cs new file mode 100644 index 0000000000..850c45282e --- /dev/null +++ b/src/Datadog.Trace/Agent/IApiRequest.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Datadog.Trace.Agent.MessagePack; +using Datadog.Trace.Headers; + +namespace Datadog.Trace.Agent +{ + internal interface IApiRequest + { + void AddHeader(string name, string value); + + Task PostAsync(Span[][] traces, FormatterResolverWrapper formatterResolver); + } +} diff --git a/src/Datadog.Trace/Agent/IApiRequestFactory.cs b/src/Datadog.Trace/Agent/IApiRequestFactory.cs new file mode 100644 index 0000000000..7933cf9aaa --- /dev/null +++ b/src/Datadog.Trace/Agent/IApiRequestFactory.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Datadog.Trace.Agent +{ + internal interface IApiRequestFactory + { + IApiRequest Create(Uri endpoint); + } +} diff --git a/src/Datadog.Trace/Agent/IApiResponse.cs b/src/Datadog.Trace/Agent/IApiResponse.cs new file mode 100644 index 0000000000..60fc9c108c --- /dev/null +++ b/src/Datadog.Trace/Agent/IApiResponse.cs @@ -0,0 +1,14 @@ +using System; +using System.Threading.Tasks; + +namespace Datadog.Trace.Agent +{ + internal interface IApiResponse : IDisposable + { + int StatusCode { get; } + + long ContentLength { get; } + + Task ReadAsStringAsync(); + } +} diff --git a/src/Datadog.Trace/Agent/MessagePack/FormatterResolverWrapper.cs b/src/Datadog.Trace/Agent/MessagePack/FormatterResolverWrapper.cs new file mode 100644 index 0000000000..fc9c366cb2 --- /dev/null +++ b/src/Datadog.Trace/Agent/MessagePack/FormatterResolverWrapper.cs @@ -0,0 +1,20 @@ +using Datadog.Trace.Vendors.MessagePack; +using Datadog.Trace.Vendors.MessagePack.Formatters; + +namespace Datadog.Trace.Agent.MessagePack +{ + internal struct FormatterResolverWrapper : IFormatterResolver + { + private readonly IFormatterResolver _resolver; + + public FormatterResolverWrapper(IFormatterResolver resolver) + { + _resolver = resolver; + } + + public IMessagePackFormatter GetFormatter() + { + return _resolver.GetFormatter(); + } + } +} diff --git a/src/Datadog.Trace/Agent/MessagePack/SpanFormatterResolver.cs b/src/Datadog.Trace/Agent/MessagePack/SpanFormatterResolver.cs new file mode 100644 index 0000000000..7107c878e6 --- /dev/null +++ b/src/Datadog.Trace/Agent/MessagePack/SpanFormatterResolver.cs @@ -0,0 +1,27 @@ +using Datadog.Trace.Vendors.MessagePack; +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Resolvers; + +namespace Datadog.Trace.Agent.MessagePack +{ + internal class SpanFormatterResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new SpanFormatterResolver(); + + private static readonly IMessagePackFormatter Formatter = new SpanMessagePackFormatter(); + + private SpanFormatterResolver() + { + } + + public IMessagePackFormatter GetFormatter() + { + if (typeof(T) == typeof(Span)) + { + return (IMessagePackFormatter)Formatter; + } + + return StandardResolver.Instance.GetFormatter(); + } + } +} diff --git a/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs b/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs new file mode 100644 index 0000000000..20a3834c4f --- /dev/null +++ b/src/Datadog.Trace/Agent/MessagePack/SpanMessagePackFormatter.cs @@ -0,0 +1,108 @@ +using System; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Vendors.MessagePack; +using Datadog.Trace.Vendors.MessagePack.Formatters; + +namespace Datadog.Trace.Agent.MessagePack +{ + internal class SpanMessagePackFormatter : IMessagePackFormatter + { + public int Serialize(ref byte[] bytes, int offset, Span value, IFormatterResolver formatterResolver) + { + // First, pack array length (or map length). + // It should be the number of members of the object to be serialized. + var len = 8; + + if (value.Context.ParentId != null) + { + len++; + } + + if (value.Error) + { + len++; + } + + if (value.Tags != null) + { + len++; + } + + if (value.Metrics != null) + { + len++; + } + + int originalOffset = offset; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, len); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "trace_id"); + offset += MessagePackBinary.WriteUInt64(ref bytes, offset, value.Context.TraceId); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "span_id"); + offset += MessagePackBinary.WriteUInt64(ref bytes, offset, value.Context.SpanId); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "name"); + offset += MessagePackBinary.WriteString(ref bytes, offset, value.OperationName); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "resource"); + offset += MessagePackBinary.WriteString(ref bytes, offset, value.ResourceName); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "service"); + offset += MessagePackBinary.WriteString(ref bytes, offset, value.ServiceName); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "type"); + offset += MessagePackBinary.WriteString(ref bytes, offset, value.Type); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "start"); + offset += MessagePackBinary.WriteInt64(ref bytes, offset, value.StartTime.ToUnixTimeNanoseconds()); + + offset += MessagePackBinary.WriteString(ref bytes, offset, "duration"); + offset += MessagePackBinary.WriteInt64(ref bytes, offset, value.Duration.ToNanoseconds()); + + if (value.Context.ParentId != null) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, "parent_id"); + offset += MessagePackBinary.WriteUInt64(ref bytes, offset, (ulong)value.Context.ParentId); + } + + if (value.Error) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, "error"); + offset += MessagePackBinary.WriteByte(ref bytes, offset, 1); + } + + if (value.Tags != null) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, "meta"); + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Tags.Count); + + foreach (var pair in value.Tags) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, pair.Key); + offset += MessagePackBinary.WriteString(ref bytes, offset, pair.Value); + } + } + + if (value.Metrics != null) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, "metrics"); + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Metrics.Count); + + foreach (var pair in value.Metrics) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, pair.Key); + offset += MessagePackBinary.WriteDouble(ref bytes, offset, pair.Value); + } + } + + return offset - originalOffset; + } + + public Span Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Datadog.Trace/AgentHttpHeaderNames.cs b/src/Datadog.Trace/AgentHttpHeaderNames.cs new file mode 100644 index 0000000000..4d8dea1761 --- /dev/null +++ b/src/Datadog.Trace/AgentHttpHeaderNames.cs @@ -0,0 +1,41 @@ +using System.Runtime.InteropServices; + +namespace Datadog.Trace +{ + /// + /// Names of HTTP headers that can be used when sending traces to the Trace Agent. + /// + internal static class AgentHttpHeaderNames + { + /// + /// The language-specific tracer that generated this span. + /// Always ".NET" for the .NET Tracer. + /// + public const string Language = "Datadog-Meta-Lang"; + + /// + /// The interpreter for the given language, e.g. ".NET Framework" or ".NET Core". + /// + public const string LanguageInterpreter = "Datadog-Meta-Lang-Interpreter"; + + /// + /// The interpreter version for the given language, e.g. "4.7.2" for .NET Framework or "2.1" for .NET Core. + /// + public const string LanguageVersion = "Datadog-Meta-Lang-Version"; + + /// + /// The version of the tracer that generated this span. + /// + public const string TracerVersion = "Datadog-Meta-Tracer-Version"; + + /// + /// The number of unique traces per request. + /// + public const string TraceCount = "X-Datadog-Trace-Count"; + + /// + /// The id of the container where the traced application is running. + /// + public const string ContainerId = "Datadog-Container-ID"; + } +} diff --git a/src/Datadog.Trace/AssemblyInfo.cs b/src/Datadog.Trace/AssemblyInfo.cs new file mode 100644 index 0000000000..d68a8e6126 --- /dev/null +++ b/src/Datadog.Trace/AssemblyInfo.cs @@ -0,0 +1,16 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.Managed, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.TestHelpers, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.OpenTracing, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.OpenTracing.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.OpenTracing.IntegrationTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.AspNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +[assembly: InternalsVisibleTo("Datadog.Trace.ClrProfiler.Managed.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.MSBuild, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Datadog.Trace.BenchmarkDotNet, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] +[assembly: InternalsVisibleTo("Benchmarks.Trace, PublicKey=002400000480000094000000060200000024000052534131000400000100010025b855c8bc41b1d47e777fc247392999ca6f553cdb030fac8e3bd010171ded9982540d988553935f44f7dd58cb4b17fbb92653d5c2dc5112696886665b317c6f92795bf64beab2405c501c8a30cb1b31b1541ed66e27d9823169ec2815b00ceeeecc8d5a1bf43db67d2961a3e9bea1397f043ec07491709649252f5565b756c5")] diff --git a/src/Datadog.Trace/AsyncLocalCompat.cs b/src/Datadog.Trace/AsyncLocalCompat.cs new file mode 100644 index 0000000000..8b4cc84b7f --- /dev/null +++ b/src/Datadog.Trace/AsyncLocalCompat.cs @@ -0,0 +1,50 @@ +namespace Datadog.Trace +{ +#if NET45 + using System; + using System.Runtime.Remoting; + using System.Runtime.Remoting.Messaging; + + internal class AsyncLocalCompat + { + private readonly string _name = "__Datadog_Scope_Current__" + Guid.NewGuid(); + + public T Get() + { + var handle = CallContext.LogicalGetData(_name) as ObjectHandle; + + return handle == null + ? default(T) + : (T)handle.Unwrap(); + } + + public void Set(T value) + { + if (CallContext.LogicalGetData(_name) is IDisposable oldHandle) + { + oldHandle.Dispose(); + } + + CallContext.LogicalSetData(_name, new DisposableObjectHandle(value)); + } + } + +#else + using System.Threading; + + internal class AsyncLocalCompat + { + private readonly AsyncLocal _asyncLocal = new AsyncLocal(); + + public T Get() + { + return _asyncLocal.Value; + } + + public void Set(T value) + { + _asyncLocal.Value = value; + } + } +#endif +} diff --git a/src/Datadog.Trace/AsyncLocalScopeManager.cs b/src/Datadog.Trace/AsyncLocalScopeManager.cs new file mode 100644 index 0000000000..2633e60c40 --- /dev/null +++ b/src/Datadog.Trace/AsyncLocalScopeManager.cs @@ -0,0 +1,23 @@ +using System; +using Datadog.Trace.Logging; + +namespace Datadog.Trace +{ + internal class AsyncLocalScopeManager : ScopeManagerBase + { + private readonly AsyncLocalCompat _activeScope = new AsyncLocalCompat(); + + public override Scope Active + { + get + { + return _activeScope.Get(); + } + + protected set + { + _activeScope.Set(value); + } + } + } +} diff --git a/src/Datadog.Trace/Configuration/CompositeConfigurationSource.cs b/src/Datadog.Trace/Configuration/CompositeConfigurationSource.cs new file mode 100644 index 0000000000..9baf8be4df --- /dev/null +++ b/src/Datadog.Trace/Configuration/CompositeConfigurationSource.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +namespace Datadog.Trace.Configuration +{ + /// + /// Represents one or more configuration sources. + /// + public class CompositeConfigurationSource : IConfigurationSource, IEnumerable + { + private readonly List _sources = new List(); + + /// + /// Adds a new configuration source to this instance. + /// + /// The configuration source to add. + public void Add(IConfigurationSource source) + { + if (source == null) { throw new ArgumentNullException(nameof(source)); } + + _sources.Add(source); + } + + /// + /// Inserts an element into the at the specified index. + /// + /// The zero-based index at which should be inserted. + /// The configuration source to insert. + public void Insert(int index, IConfigurationSource item) + { + if (item == null) { throw new ArgumentNullException(nameof(item)); } + + _sources.Insert(index, item); + } + + /// + /// Gets the value of the first setting found with + /// the specified key from the current list of configuration sources. + /// Sources are queried in the order in which they were added. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + public string GetString(string key) + { + return _sources.Select(source => source.GetString(key)) + .FirstOrDefault(value => value != null); + } + + /// + /// Gets the value of the first setting found with + /// the specified key from the current list of configuration sources. + /// Sources are queried in the order in which they were added. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + public int? GetInt32(string key) + { + return _sources.Select(source => source.GetInt32(key)) + .FirstOrDefault(value => value != null); + } + + /// + /// Gets the value of the first setting found with + /// the specified key from the current list of configuration sources. + /// Sources are queried in the order in which they were added. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + public double? GetDouble(string key) + { + return _sources.Select(source => source.GetDouble(key)) + .FirstOrDefault(value => value != null); + } + + /// + /// Gets the value of the first setting found with + /// the specified key from the current list of configuration sources. + /// Sources are queried in the order in which they were added. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + public bool? GetBool(string key) + { + return _sources.Select(source => source.GetBool(key)) + .FirstOrDefault(value => value != null); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return _sources.GetEnumerator(); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return _sources.GetEnumerator(); + } + + /// + public IDictionary GetDictionary(string key) + { + return _sources.Select(source => source.GetDictionary(key)) + .FirstOrDefault(value => value != null); + } + } +} diff --git a/src/Datadog.Trace/Configuration/ConfigurationKeys.cs b/src/Datadog.Trace/Configuration/ConfigurationKeys.cs new file mode 100644 index 0000000000..af45a21abb --- /dev/null +++ b/src/Datadog.Trace/Configuration/ConfigurationKeys.cs @@ -0,0 +1,251 @@ +namespace Datadog.Trace.Configuration +{ + /// + /// String constants for standard Datadog configuration keys. + /// + public static class ConfigurationKeys + { + /// + /// Configuration key for the path to the configuration file. + /// Can only be set with an environment variable + /// or in the app.config/web.config file. + /// + public const string ConfigurationFileName = "DD_TRACE_CONFIG_FILE"; + + /// + /// Configuration key for the application's environment. Sets the "env" tag on every . + /// + /// + public const string Environment = "DD_ENV"; + + /// + /// Configuration key for the application's default service name. + /// Used as the service name for top-level spans, + /// and used to determine service name of some child spans. + /// + /// + public const string ServiceName = "DD_SERVICE"; + + /// + /// Configuration key for the application's version. Sets the "version" tag on every . + /// + /// + public const string ServiceVersion = "DD_VERSION"; + + /// + /// Configuration key for enabling or disabling the Tracer. + /// Default is value is true (enabled). + /// + /// + public const string TraceEnabled = "DD_TRACE_ENABLED"; + + /// + /// Configuration key for enabling or disabling the Tracer's debug mode. + /// Default is value is false (disabled). + /// + /// + public const string DebugEnabled = "DD_TRACE_DEBUG"; + + /// + /// Configuration key for a list of integrations to disable. All other integrations remain enabled. + /// Default is empty (all integrations are enabled). + /// Supports multiple values separated with semi-colons. + /// + /// + public const string DisabledIntegrations = "DD_DISABLED_INTEGRATIONS"; + + /// + /// Configuration key for the Agent host where the Tracer can send traces. + /// Overriden by if present. + /// Default value is "localhost". + /// + /// + public const string AgentHost = "DD_AGENT_HOST"; + + /// + /// Configuration key for the Agent port where the Tracer can send traces. + /// Default value is 8126. + /// + /// + public const string AgentPort = "DD_TRACE_AGENT_PORT"; + + /// + /// Sibling setting for . + /// Used to force a specific port binding for the Trace Agent. + /// Default value is 8126. + /// + /// + public const string TraceAgentPortKey = "DD_APM_RECEIVER_PORT"; + + /// + /// Configuration key for the Agent URL where the Tracer can send traces. + /// Overrides values in and if present. + /// Default value is "http://localhost:8126". + /// + /// + public const string AgentUri = "DD_TRACE_AGENT_URL"; + + /// + /// Configuration key for enabling or disabling default Analytics. + /// + /// + public const string GlobalAnalyticsEnabled = "DD_TRACE_ANALYTICS_ENABLED"; + + /// + /// Configuration key for a list of tags to be applied globally to spans. + /// + /// + public const string GlobalTags = "DD_TAGS"; + + /// + /// Configuration key for a map of header keys to tag names. + /// Automatically apply header values as tags on traces. + /// + /// + public const string HeaderTags = "DD_TRACE_HEADER_TAGS"; + + /// + /// Configuration key for enabling or disabling the automatic injection + /// of correlation identifiers into the logging context. + /// + /// + public const string LogsInjectionEnabled = "DD_LOGS_INJECTION"; + + /// + /// Configuration key for setting the number of traces allowed + /// to be submitted per second. + /// + /// + public const string MaxTracesSubmittedPerSecond = "DD_MAX_TRACES_PER_SECOND"; + + /// + /// Configuration key for enabling or disabling the diagnostic log at startup + /// + /// + public const string StartupDiagnosticLogEnabled = "DD_TRACE_STARTUP_LOGS"; + + /// + /// Configuration key for setting custom sampling rules based on regular expressions. + /// Semi-colon separated list of sampling rules. + /// The rule is matched in order of specification. The first match in a list is used. + /// + /// Per entry: + /// The item "sample_rate" is required in decimal format. + /// The item "service" is optional in regular expression format, to match on service name. + /// The item "name" is optional in regular expression format, to match on operation name. + /// + /// To give a rate of 50% to any traces in a service starting with the text "cart": + /// '[{"sample_rate":0.5, "service":"cart.*"}]' + /// + /// To give a rate of 20% to any traces which have an operation name of "http.request": + /// '[{"sample_rate":0.2, "name":"http.request"}]' + /// + /// To give a rate of 100% to any traces within a service named "background" and with an operation name of "sql.query": + /// '[{"sample_rate":1.0, "service":"background", "name":"sql.query"}] + /// + /// To give a rate of 10% to all traces + /// '[{"sample_rate":0.1}]' + /// + /// To configure multiple rules, separate by semi-colon and order from most specific to least specific: + /// '[{"sample_rate":0.5, "service":"cart.*"}, {"sample_rate":0.2, "name":"http.request"}, {"sample_rate":1.0, "service":"background", "name":"sql.query"}, {"sample_rate":0.1}]' + /// + /// If no rules are specified, or none match, default internal sampling logic will be used. + /// + /// + public const string CustomSamplingRules = "DD_TRACE_SAMPLING_RULES"; + + /// + /// Configuration key for setting the global rate for the sampler. + /// + public const string GlobalSamplingRate = "DD_TRACE_SAMPLE_RATE"; + + /// + /// Configuration key for the DogStatsd port where the Tracer can send metrics. + /// Default value is 8125. + /// + public const string DogStatsdPort = "DD_DOGSTATSD_PORT"; + + /// + /// Configuration key for enabling or disabling internal metrics sent to DogStatsD. + /// Default value is false (disabled). + /// + public const string TracerMetricsEnabled = "DD_TRACE_METRICS_ENABLED"; + + /// + /// Configuration key for setting the approximate maximum size, + /// in bytes, for Tracer log files. + /// Default value is 10 MB. + /// + public const string MaxLogFileSize = "DD_MAX_LOGFILE_SIZE"; + + /// + /// Configuration key for setting the path to the profiler log file. + /// Default value is "%ProgramData%"\Datadog .NET Tracer\logs\dotnet-profiler.log" on Windows + /// or "/var/log/datadog/dotnet/dotnet-profiler.log" on Linux. + /// + public const string ProfilerLogPath = "DD_TRACE_LOG_PATH"; + + /// + /// Configuration key for when a standalone instance of the Trace Agent needs to be started. + /// + public const string TraceAgentPath = "DD_TRACE_AGENT_PATH"; + + /// + /// Configuration key for arguments to pass to the Trace Agent process. + /// + public const string TraceAgentArgs = "DD_TRACE_AGENT_ARGS"; + + /// + /// Configuration key for when a standalone instance of DogStatsD needs to be started. + /// + public const string DogStatsDPath = "DD_DOGSTATSD_PATH"; + + /// + /// Configuration key for arguments to pass to the DogStatsD process. + /// + public const string DogStatsDArgs = "DD_DOGSTATSD_ARGS"; + + /// + /// Configuration key for enabling or disabling the use of . + /// Default value is true (enabled). + /// + public const string DiagnosticSourceEnabled = "DD_DIAGNOSTIC_SOURCE_ENABLED"; + + /// + /// String format patterns used to match integration-specific configuration keys. + /// + public static class Integrations + { + /// + /// Configuration key pattern for enabling or disabling an integration. + /// + public const string Enabled = "DD_TRACE_{0}_ENABLED"; + + /// + /// Configuration key pattern for enabling or disabling Analytics in an integration. + /// + public const string AnalyticsEnabled = "DD_TRACE_{0}_ANALYTICS_ENABLED"; + + /// + /// Configuration key pattern for setting Analytics sampling rate in an integration. + /// + public const string AnalyticsSampleRate = "DD_TRACE_{0}_ANALYTICS_SAMPLE_RATE"; + } + + /// + /// String constants for debug configuration keys. + /// + internal static class Debug + { + /// + /// Configuration key for forcing the automatic instrumentation to only use the mdToken method lookup mechanism. + /// + public const string ForceMdTokenLookup = "DD_TRACE_DEBUG_LOOKUP_MDTOKEN"; + + /// + /// Configuration key for forcing the automatic instrumentation to only use the fallback method lookup mechanism. + /// + public const string ForceFallbackLookup = "DD_TRACE_DEBUG_LOOKUP_FALLBACK"; + } + } +} diff --git a/src/Datadog.Trace/Configuration/EnvironmentConfigurationSource.cs b/src/Datadog.Trace/Configuration/EnvironmentConfigurationSource.cs new file mode 100644 index 0000000000..a818cae3cb --- /dev/null +++ b/src/Datadog.Trace/Configuration/EnvironmentConfigurationSource.cs @@ -0,0 +1,17 @@ +using Datadog.Trace.Util; + +namespace Datadog.Trace.Configuration +{ + /// + /// Represents a configuration source that + /// retrieves values from environment variables. + /// + public class EnvironmentConfigurationSource : StringConfigurationSource + { + /// + public override string GetString(string key) + { + return EnvironmentHelpers.GetEnvironmentVariable(key); + } + } +} diff --git a/src/Datadog.Trace/Configuration/GlobalSettings.cs b/src/Datadog.Trace/Configuration/GlobalSettings.cs new file mode 100644 index 0000000000..16e4fe4918 --- /dev/null +++ b/src/Datadog.Trace/Configuration/GlobalSettings.cs @@ -0,0 +1,127 @@ +using System.IO; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Configuration +{ + /// + /// Contains global datadog settings. + /// + public class GlobalSettings + { + /// + /// Initializes a new instance of the class with default values. + /// + internal GlobalSettings() + : this(null) + { + } + + /// + /// Initializes a new instance of the class + /// using the specified to initialize values. + /// + /// The to use when retrieving configuration values. + internal GlobalSettings(IConfigurationSource source) + { + DebugEnabled = source?.GetBool(ConfigurationKeys.DebugEnabled) ?? + // default value + false; + } + + /// + /// Gets a value indicating whether debug mode is enabled. + /// Default is false. + /// Set in code via + /// + /// + public bool DebugEnabled { get; private set; } + + /// + /// Gets or sets the global settings instance. + /// + internal static GlobalSettings Source { get; set; } = FromDefaultSources(); + + /// + /// Set whether debug mode is enabled. + /// Affects the level of logs written to file. + /// + /// Whether debug is enabled. + public static void SetDebugEnabled(bool enabled) + { + Source.DebugEnabled = enabled; + + if (enabled) + { + DatadogLogging.SetLogLevel(LogEventLevel.Verbose); + } + else + { + DatadogLogging.UseDefaultLevel(); + } + } + + /// + /// Used to refresh global settings when environment variables or config sources change. + /// This is not necessary if changes are set via code, only environment. + /// + public static void Reload() + { + Source = FromDefaultSources(); + } + + /// + /// Create a populated from the default sources + /// returned by . + /// + /// A populated from the default sources. + public static GlobalSettings FromDefaultSources() + { + var source = CreateDefaultConfigurationSource(); + return new GlobalSettings(source); + } + + /// + /// Creates a by combining environment variables, + /// AppSettings where available, and a local datadog.json file, if present. + /// + /// A new instance. + internal static CompositeConfigurationSource CreateDefaultConfigurationSource() + { + // env > AppSettings > datadog.json + var configurationSource = new CompositeConfigurationSource + { + new EnvironmentConfigurationSource(), + +#if !NETSTANDARD2_0 + // on .NET Framework only, also read from app.config/web.config + new NameValueConfigurationSource(System.Configuration.ConfigurationManager.AppSettings) +#endif + }; + + string currentDirectory = System.Environment.CurrentDirectory; + +#if !NETSTANDARD2_0 + // on .NET Framework only, use application's root folder + // as default path when looking for datadog.json + if (System.Web.Hosting.HostingEnvironment.IsHosted) + { + currentDirectory = System.Web.Hosting.HostingEnvironment.MapPath("~"); + } +#endif + + // if environment variable is not set, look for default file name in the current directory + var configurationFileName = configurationSource.GetString(ConfigurationKeys.ConfigurationFileName) ?? + configurationSource.GetString("DD_DOTNET_TRACER_CONFIG_FILE") ?? + Path.Combine(currentDirectory, "datadog.json"); + + if (Path.GetExtension(configurationFileName).ToUpperInvariant() == ".JSON" && + File.Exists(configurationFileName)) + { + configurationSource.Add(JsonConfigurationSource.FromFile(configurationFileName)); + } + + return configurationSource; + } + } +} diff --git a/src/Datadog.Trace/Configuration/IConfigurationSource.cs b/src/Datadog.Trace/Configuration/IConfigurationSource.cs new file mode 100644 index 0000000000..d3e46e8712 --- /dev/null +++ b/src/Datadog.Trace/Configuration/IConfigurationSource.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; + +namespace Datadog.Trace.Configuration +{ + /// + /// A source of configuration settings, identifiable by a string key. + /// + public interface IConfigurationSource + { + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + string GetString(string key); + + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + int? GetInt32(string key); + + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + double? GetDouble(string key); + + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + bool? GetBool(string key); + + /// + /// Gets the value of + /// the setting with the specified key. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + IDictionary GetDictionary(string key); + } +} diff --git a/src/Datadog.Trace/Configuration/IntegrationSettings.cs b/src/Datadog.Trace/Configuration/IntegrationSettings.cs new file mode 100644 index 0000000000..d01e0a5f4e --- /dev/null +++ b/src/Datadog.Trace/Configuration/IntegrationSettings.cs @@ -0,0 +1,59 @@ +using System; + +namespace Datadog.Trace.Configuration +{ + /// + /// Contains integration-specific settings. + /// + public class IntegrationSettings + { + /// + /// Initializes a new instance of the class. + /// + /// The integration name. + /// The to use when retrieving configuration values. + public IntegrationSettings(string integrationName, IConfigurationSource source) + { + IntegrationName = integrationName ?? throw new ArgumentNullException(nameof(integrationName)); + + if (source == null) + { + return; + } + + Enabled = source.GetBool(string.Format(ConfigurationKeys.Integrations.Enabled, integrationName)) ?? + source.GetBool(string.Format("DD_{0}_ENABLED", integrationName)); + + AnalyticsEnabled = source.GetBool(string.Format(ConfigurationKeys.Integrations.AnalyticsEnabled, integrationName)) ?? + source.GetBool(string.Format("DD_{0}_ANALYTICS_ENABLED", integrationName)); + + AnalyticsSampleRate = source.GetDouble(string.Format(ConfigurationKeys.Integrations.AnalyticsSampleRate, integrationName)) ?? + source.GetDouble(string.Format("DD_{0}_ANALYTICS_SAMPLE_RATE", integrationName)) ?? + // default value + 1.0; + } + + /// + /// Gets the name of the integration. Used to retrieve integration-specific settings. + /// + public string IntegrationName { get; } + + /// + /// Gets or sets a value indicating whether + /// this integration is enabled. + /// + public bool? Enabled { get; set; } + + /// + /// Gets or sets a value indicating whether + /// Analytics are enabled for this integration. + /// + public bool? AnalyticsEnabled { get; set; } + + /// + /// Gets or sets a value between 0 and 1 (inclusive) + /// that determines the sampling rate for this integration. + /// + public double AnalyticsSampleRate { get; set; } + } +} diff --git a/src/Datadog.Trace/Configuration/IntegrationSettingsCollection.cs b/src/Datadog.Trace/Configuration/IntegrationSettingsCollection.cs new file mode 100644 index 0000000000..7b348595a1 --- /dev/null +++ b/src/Datadog.Trace/Configuration/IntegrationSettingsCollection.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Concurrent; + +namespace Datadog.Trace.Configuration +{ + /// + /// A collection of instances, referenced by name. + /// + public class IntegrationSettingsCollection + { + private readonly IConfigurationSource _source; + private readonly ConcurrentDictionary _settings; + private readonly Func _valueFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The to use when retrieving configuration values. + public IntegrationSettingsCollection(IConfigurationSource source) + { + _source = source; + _settings = new ConcurrentDictionary(); + _valueFactory = name => new IntegrationSettings(name, _source); + } + + /// + /// Gets the for the specified integration. + /// + /// The name of the integration. + /// The integration-specific settings for the specified integration. + public IntegrationSettings this[string integrationName] => + _settings.GetOrAdd(integrationName, _valueFactory); + } +} diff --git a/src/Datadog.Trace/Configuration/JsonConfigurationSource.cs b/src/Datadog.Trace/Configuration/JsonConfigurationSource.cs new file mode 100644 index 0000000000..94c8a6c185 --- /dev/null +++ b/src/Datadog.Trace/Configuration/JsonConfigurationSource.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Datadog.Trace.Configuration +{ + /// + /// Represents a configuration source that retrieves + /// values from the provided JSON string. + /// + public class JsonConfigurationSource : IConfigurationSource + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(JsonConfigurationSource)); + + private readonly JObject _configuration; + + /// + /// Initializes a new instance of the + /// class with the specified JSON string. + /// + /// A JSON string that contains configuration values. + public JsonConfigurationSource(string json) + { + _configuration = (JObject)JsonConvert.DeserializeObject(json); + } + + /// + /// Creates a new instance + /// by loading the JSON string from the specified file. + /// + /// A JSON file that contains configuration values. + /// The newly created configuration source. + public static JsonConfigurationSource FromFile(string filename) + { + string json = File.ReadAllText(filename); + return new JsonConfigurationSource(json); + } + + /// + /// Gets the value of + /// the setting with the specified key. + /// Supports JPath. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + string IConfigurationSource.GetString(string key) + { + return GetValue(key); + } + + /// + /// Gets the value of + /// the setting with the specified key. + /// Supports JPath. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + int? IConfigurationSource.GetInt32(string key) + { + return GetValue(key); + } + + /// + /// Gets the value of + /// the setting with the specified key. + /// Supports JPath. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + double? IConfigurationSource.GetDouble(string key) + { + return GetValue(key); + } + + /// + /// Gets the value of + /// the setting with the specified key. + /// Supports JPath. + /// + /// The key that identifies the setting. + /// The value of the setting, or null if not found. + bool? IConfigurationSource.GetBool(string key) + { + return GetValue(key); + } + + /// + /// Gets the value of the setting with the specified key and converts it into type . + /// Supports JPath. + /// + /// The type to convert the setting value into. + /// The key that identifies the setting. + /// The value of the setting, or the default value of T if not found. + public T GetValue(string key) + { + JToken token = _configuration.SelectToken(key, errorWhenNoMatch: false); + + return token == null + ? default + : token.Value(); + } + + /// + /// Gets a containing all of the values. + /// + /// + /// Example JSON where `globalTags` is the configuration key. + /// { + /// "globalTags": { + /// "name1": "value1", + /// "name2": "value2" + /// } + /// } + /// + /// The key that identifies the setting. + /// containing all of the key-value pairs. + /// Thrown if the configuration value is not a valid JSON string." + public IDictionary GetDictionary(string key) + { + var token = _configuration.SelectToken(key, errorWhenNoMatch: false); + if (token == null) + { + return null; + } + + if (token.Type == JTokenType.Object) + { + try + { + var dictionary = token + ?.ToObject>(); + return dictionary; + } + catch (Exception e) + { + Log.Error(e, "Unable to parse configuration value for {0} as key-value pairs of strings.", key); + return null; + } + } + + return StringConfigurationSource.ParseCustomKeyValues(token.ToString()); + } + } +} diff --git a/src/Datadog.Trace/Configuration/NameValueConfigurationSource.cs b/src/Datadog.Trace/Configuration/NameValueConfigurationSource.cs new file mode 100644 index 0000000000..c81259f785 --- /dev/null +++ b/src/Datadog.Trace/Configuration/NameValueConfigurationSource.cs @@ -0,0 +1,29 @@ +using System.Collections.Specialized; + +namespace Datadog.Trace.Configuration +{ + /// + /// Represents a configuration source that retrieves + /// values from the provided . + /// + public class NameValueConfigurationSource : StringConfigurationSource + { + private readonly NameValueCollection _nameValueCollection; + + /// + /// Initializes a new instance of the class + /// that wraps the specified . + /// + /// The collection that will be wrapped by this configuration source. + public NameValueConfigurationSource(NameValueCollection nameValueCollection) + { + _nameValueCollection = nameValueCollection; + } + + /// + public override string GetString(string key) + { + return _nameValueCollection[key]; + } + } +} diff --git a/src/Datadog.Trace/Configuration/StringConfigurationSource.cs b/src/Datadog.Trace/Configuration/StringConfigurationSource.cs new file mode 100644 index 0000000000..9a4c809671 --- /dev/null +++ b/src/Datadog.Trace/Configuration/StringConfigurationSource.cs @@ -0,0 +1,94 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using Datadog.Trace.ExtensionMethods; + +namespace Datadog.Trace.Configuration +{ + /// + /// A base implementation + /// for string-only configuration sources. + /// + public abstract class StringConfigurationSource : IConfigurationSource + { + /// + /// Returns a from parsing + /// . + /// + /// A string containing key-value pairs which are comma-separated, and for which the key and value are colon-separated. + /// of key value pairs. + public static IDictionary ParseCustomKeyValues(string data) + { + var dictionary = new ConcurrentDictionary(); + + // A null return value means the key was not present, + // and CompositeConfigurationSource depends on this behavior + // (it returns the first non-null value it finds). + if (data == null) + { + return null; + } + + if (string.IsNullOrWhiteSpace(data)) + { + return dictionary; + } + + var entries = data.Split(','); + + foreach (var e in entries) + { + var kv = e.Split(':'); + if (kv.Length != 2) + { + continue; + } + + var key = kv[0]; + var value = kv[1]; + dictionary[key] = value; + } + + return dictionary; + } + + /// + public abstract string GetString(string key); + + /// + public virtual int? GetInt32(string key) + { + string value = GetString(key); + + return int.TryParse(value, out int result) + ? result + : (int?)null; + } + + /// + public double? GetDouble(string key) + { + string value = GetString(key); + + return double.TryParse(value, out double result) + ? result + : (double?)null; + } + + /// + public virtual bool? GetBool(string key) + { + var value = GetString(key); + return value?.ToBoolean(); + } + + /// + /// Gets a from parsing + /// + /// The key + /// containing all of the key-value pairs. + public IDictionary GetDictionary(string key) + { + return ParseCustomKeyValues(GetString(key)); + } + } +} diff --git a/src/Datadog.Trace/Configuration/TracerSettings.cs b/src/Datadog.Trace/Configuration/TracerSettings.cs new file mode 100644 index 0000000000..32fa33d7c4 --- /dev/null +++ b/src/Datadog.Trace/Configuration/TracerSettings.cs @@ -0,0 +1,320 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Sampling; +using Datadog.Trace.Util; + +namespace Datadog.Trace.Configuration +{ + /// + /// Contains Tracer settings. + /// + public class TracerSettings + { + /// + /// The default host value for . + /// + public const string DefaultAgentHost = "localhost"; + + /// + /// The default port value for . + /// + public const int DefaultAgentPort = 8126; + + /// + /// Initializes a new instance of the class with default values. + /// + public TracerSettings() + : this(null) + { + } + + /// + /// Initializes a new instance of the class + /// using the specified to initialize values. + /// + /// The to use when retrieving configuration values. + public TracerSettings(IConfigurationSource source) + { + Environment = source?.GetString(ConfigurationKeys.Environment); + + ServiceName = source?.GetString(ConfigurationKeys.ServiceName) ?? + // backwards compatibility for names used in the past + source?.GetString("DD_SERVICE_NAME"); + + ServiceVersion = source?.GetString(ConfigurationKeys.ServiceVersion); + + TraceEnabled = source?.GetBool(ConfigurationKeys.TraceEnabled) ?? + // default value + true; + + var disabledIntegrationNames = source?.GetString(ConfigurationKeys.DisabledIntegrations) + ?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries) ?? + Enumerable.Empty(); + + DisabledIntegrationNames = new HashSet(disabledIntegrationNames, StringComparer.OrdinalIgnoreCase); + + var agentHost = source?.GetString(ConfigurationKeys.AgentHost) ?? + // backwards compatibility for names used in the past + source?.GetString("DD_TRACE_AGENT_HOSTNAME") ?? + source?.GetString("DATADOG_TRACE_AGENT_HOSTNAME") ?? + // default value + DefaultAgentHost; + + var agentPort = source?.GetInt32(ConfigurationKeys.AgentPort) ?? + // backwards compatibility for names used in the past + source?.GetInt32("DATADOG_TRACE_AGENT_PORT") ?? + // default value + DefaultAgentPort; + + var agentUri = source?.GetString(ConfigurationKeys.AgentUri) ?? + // default value + $"http://{agentHost}:{agentPort}"; + + AgentUri = new Uri(agentUri); + + AnalyticsEnabled = source?.GetBool(ConfigurationKeys.GlobalAnalyticsEnabled) ?? + // default value + false; + + LogsInjectionEnabled = source?.GetBool(ConfigurationKeys.LogsInjectionEnabled) ?? + // default value + false; + + var maxTracesPerSecond = source?.GetInt32(ConfigurationKeys.MaxTracesSubmittedPerSecond); + + if (maxTracesPerSecond != null) + { + // Ensure our flag for the rate limiter is enabled + RuleBasedSampler.OptInTracingWithoutLimits(); + } + else + { + maxTracesPerSecond = 100; // default + } + + MaxTracesSubmittedPerSecond = maxTracesPerSecond.Value; + + Integrations = new IntegrationSettingsCollection(source); + + GlobalTags = source?.GetDictionary(ConfigurationKeys.GlobalTags) ?? + // backwards compatibility for names used in the past + source?.GetDictionary("DD_TRACE_GLOBAL_TAGS") ?? + // default value (empty) + new ConcurrentDictionary(); + + // Filter out tags with empty keys or empty values, and trim whitespace + GlobalTags = GlobalTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value)) + .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); + + HeaderTags = source?.GetDictionary(ConfigurationKeys.HeaderTags) ?? + // default value (empty) + new ConcurrentDictionary(); + + // Filter out tags with empty keys or empty values, and trim whitespace + HeaderTags = HeaderTags.Where(kvp => !string.IsNullOrEmpty(kvp.Key) && !string.IsNullOrEmpty(kvp.Value)) + .ToDictionary(kvp => kvp.Key.Trim(), kvp => kvp.Value.Trim()); + + DogStatsdPort = source?.GetInt32(ConfigurationKeys.DogStatsdPort) ?? + // default value + 8125; + + TracerMetricsEnabled = source?.GetBool(ConfigurationKeys.TracerMetricsEnabled) ?? + // default value + false; + + CustomSamplingRules = source?.GetString(ConfigurationKeys.CustomSamplingRules); + + GlobalSamplingRate = source?.GetDouble(ConfigurationKeys.GlobalSamplingRate); + + DiagnosticSourceEnabled = source?.GetBool(ConfigurationKeys.DiagnosticSourceEnabled) ?? + // default value + true; + + StartupDiagnosticLogEnabled = source?.GetBool(ConfigurationKeys.StartupDiagnosticLogEnabled) ?? + // default value + true; + } + + /// + /// Gets or sets the default environment name applied to all spans. + /// + /// + public string Environment { get; set; } + + /// + /// Gets or sets the service name applied to top-level spans and used to build derived service names. + /// + /// + public string ServiceName { get; set; } + + /// + /// Gets or sets the version tag applied to all spans. + /// + /// + public string ServiceVersion { get; set; } + + /// + /// Gets or sets a value indicating whether tracing is enabled. + /// Default is true. + /// + /// + public bool TraceEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether debug is enabled for a tracer. + /// This property is obsolete. Manage the debug setting through GlobalSettings. + /// + /// + [Obsolete] + public bool DebugEnabled { get; set; } + + /// + /// Gets or sets the names of disabled integrations. + /// + /// + public HashSet DisabledIntegrationNames { get; set; } + + /// + /// Gets or sets the Uri where the Tracer can connect to the Agent. + /// Default is "http://localhost:8126". + /// + /// + /// + /// + public Uri AgentUri { get; set; } + + /// + /// Gets or sets a value indicating whether default Analytics are enabled. + /// Settings this value is a shortcut for setting + /// on some predetermined integrations. + /// See the documentation for more details. + /// + /// + public bool AnalyticsEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether correlation identifiers are + /// automatically injected into the logging context. + /// Default is false. + /// + /// + public bool LogsInjectionEnabled { get; set; } + + /// + /// Gets or sets a value indicating the maximum number of traces set to AutoKeep (p1) per second. + /// Default is 100. + /// + /// + public int MaxTracesSubmittedPerSecond { get; set; } + + /// + /// Gets or sets a value indicating custom sampling rules. + /// + /// + public string CustomSamplingRules { get; set; } + + /// + /// Gets or sets a value indicating a global rate for sampling. + /// + /// + public double? GlobalSamplingRate { get; set; } + + /// + /// Gets a collection of keyed by integration name. + /// + public IntegrationSettingsCollection Integrations { get; } + + /// + /// Gets or sets the global tags, which are applied to all s. + /// + public IDictionary GlobalTags { get; set; } + + /// + /// Gets or sets the map of header keys to tag names, which are applied to the root of incoming requests. + /// + public IDictionary HeaderTags { get; set; } + + /// + /// Gets or sets the port where the DogStatsd server is listening for connections. + /// Default is 8125. + /// + /// + public int DogStatsdPort { get; set; } + + /// + /// Gets or sets a value indicating whether internal metrics + /// are enabled and sent to DogStatsd. + /// + public bool TracerMetricsEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the use + /// of is enabled. + /// + public bool DiagnosticSourceEnabled { get; set; } + + /// + /// Gets or sets a value indicating whether the diagnostic log at startup is enabled + /// + public bool StartupDiagnosticLogEnabled { get; set; } + + /// + /// Create a populated from the default sources + /// returned by . + /// + /// A populated from the default sources. + public static TracerSettings FromDefaultSources() + { + var source = CreateDefaultConfigurationSource(); + return new TracerSettings(source); + } + + /// + /// Creates a by combining environment variables, + /// AppSettings where available, and a local datadog.json file, if present. + /// + /// A new instance. + public static CompositeConfigurationSource CreateDefaultConfigurationSource() + { + return GlobalSettings.CreateDefaultConfigurationSource(); + } + + internal bool IsIntegrationEnabled(string name) + { + if (TraceEnabled && !DomainMetadata.ShouldAvoidAppDomain()) + { + bool disabled = Integrations[name].Enabled == false || DisabledIntegrationNames.Contains(name); + return !disabled; + } + + return false; + } + + internal bool IsOptInIntegrationEnabled(string name) + { + if (TraceEnabled && !DomainMetadata.ShouldAvoidAppDomain()) + { + var disabled = Integrations[name].Enabled != true || DisabledIntegrationNames.Contains(name); + return !disabled; + } + + return false; + } + + internal double? GetIntegrationAnalyticsSampleRate(string name, bool enabledWithGlobalSetting) + { + var integrationSettings = Integrations[name]; + var analyticsEnabled = integrationSettings.AnalyticsEnabled ?? (enabledWithGlobalSetting && AnalyticsEnabled); + return analyticsEnabled ? integrationSettings.AnalyticsSampleRate : (double?)null; + } + + internal bool IsNetStandardFeatureFlagEnabled() + { + var value = EnvironmentHelpers.GetEnvironmentVariable("DD_TRACE_NETSTANDARD_ENABLED", string.Empty); + + return value == "1" || value == "true"; + } + } +} diff --git a/src/Datadog.Trace/CorrelationIdentifier.cs b/src/Datadog.Trace/CorrelationIdentifier.cs new file mode 100644 index 0000000000..167b2f8522 --- /dev/null +++ b/src/Datadog.Trace/CorrelationIdentifier.cs @@ -0,0 +1,73 @@ +using System; + +namespace Datadog.Trace +{ + /// + /// An API to access identifying values of the service and the active span + /// + public static class CorrelationIdentifier + { + internal static readonly string ServiceKey = "dd.service"; + internal static readonly string VersionKey = "dd.version"; + internal static readonly string EnvKey = "dd.env"; + internal static readonly string TraceIdKey = "dd.trace_id"; + internal static readonly string SpanIdKey = "dd.span_id"; + + /// + /// Gets the name of the service + /// + public static string Service + { + get + { + return Tracer.Instance.DefaultServiceName ?? string.Empty; + } + } + + /// + /// Gets the version of the service + /// + public static string Version + { + get + { + return Tracer.Instance.Settings.ServiceVersion ?? string.Empty; + } + } + + /// + /// Gets the environment name of the service + /// + public static string Env + { + get + { + return Tracer.Instance.Settings.Environment ?? string.Empty; + } + } + + /// + /// Gets the id of the active trace. + /// + /// The id of the active trace. If there is no active trace, returns zero. + public static ulong TraceId + { + get + { + return Tracer.Instance.ActiveScope?.Span?.TraceId ?? 0; + } + } + + /// + /// Gets the id of the active span. + /// + /// The id of the active span. If there is no active span, returns zero. + public static ulong SpanId + { + get + { + return Tracer.Instance.ActiveScope?.Span?.SpanId ?? 0; + } + } + } +} diff --git a/src/Datadog.Trace/Datadog.Trace.csproj b/src/Datadog.Trace/Datadog.Trace.csproj new file mode 100644 index 0000000000..0a78395af0 --- /dev/null +++ b/src/Datadog.Trace/Datadog.Trace.csproj @@ -0,0 +1,57 @@ + + + + + 1.19.1 + Datadog APM + Manual instrumentation library for Datadog APM + + + + + + + + + + + + + + + + + + + + + + + $(DefineConstants);REMOTING;HASHTABLE + + + + $(DefineConstants);ASYNCLOCAL;HASHTABLE + + + + $(DefineConstants);ASYNCLOCAL;HASHTABLE + + + + + + + + $(DefineConstants);ATOMIC_APPEND;HRESULTS + + + + $(DefineConstants);OS_MUTEX + + + \ No newline at end of file diff --git a/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticObserver.cs b/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticObserver.cs new file mode 100644 index 0000000000..0c0c3e5c17 --- /dev/null +++ b/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticObserver.cs @@ -0,0 +1,290 @@ +#if NETSTANDARD +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Abstractions; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Headers; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; +using Datadog.Trace.Vendors.Serilog.Events; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Abstractions; + +namespace Datadog.Trace.DiagnosticListeners +{ + /// + /// Instruments ASP.NET Core. + /// + /// Unfortunately, ASP.NET Core only uses one instance + /// for everything so we also only create one observer to ensure best performance. + /// + /// Hosting events: https://github.com/dotnet/aspnetcore/blob/master/src/Hosting/Hosting/src/Internal/HostingApplicationDiagnostics.cs + /// + internal sealed class AspNetCoreDiagnosticObserver : DiagnosticObserver + { + public const string IntegrationName = "AspNetCore"; + + private const string DiagnosticListenerName = "Microsoft.AspNetCore"; + private const string ComponentName = "aspnet_core"; + private const string HttpRequestInOperationName = "aspnet_core.request"; + private const string NoHostSpecified = "UNKNOWN_HOST"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private static readonly PropertyFetcher HttpRequestInStartHttpContextFetcher = new PropertyFetcher("HttpContext"); + private static readonly PropertyFetcher HttpRequestInStopHttpContextFetcher = new PropertyFetcher("HttpContext"); + private static readonly PropertyFetcher UnhandledExceptionHttpContextFetcher = new PropertyFetcher("HttpContext"); + private static readonly PropertyFetcher UnhandledExceptionExceptionFetcher = new PropertyFetcher("Exception"); + private static readonly PropertyFetcher BeforeActionHttpContextFetcher = new PropertyFetcher("httpContext"); + private static readonly PropertyFetcher BeforeActionActionDescriptorFetcher = new PropertyFetcher("actionDescriptor"); + + private readonly IDatadogTracer _tracer; + private readonly AspNetCoreDiagnosticOptions _options; + private readonly bool _isLogLevelDebugEnabled = Log.IsEnabled(LogEventLevel.Debug); + + public AspNetCoreDiagnosticObserver(IDatadogTracer tracer, AspNetCoreDiagnosticOptions options) + : base(tracer) + { + _tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + _options = options ?? throw new ArgumentNullException(nameof(options)); + } + + protected override string ListenerName => DiagnosticListenerName; + + protected override void OnNext(string eventName, object arg) + { + switch (eventName) + { + case "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start": + OnHostingHttpRequestInStart(arg); + break; + + case "Microsoft.AspNetCore.Mvc.BeforeAction": + OnMvcBeforeAction(arg); + break; + + case "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop": + OnHostingHttpRequestInStop(arg); + break; + + case "Microsoft.AspNetCore.Hosting.UnhandledException": + case "Microsoft.AspNetCore.Diagnostics.UnhandledException": + OnHostingUnhandledException(arg); + break; + } + } + + private static string GetUrl(HttpRequest request) + { + if (request.Host.HasValue) + { + return $"{request.Scheme}://{request.Host.Value}{request.PathBase.Value}{request.Path.Value}"; + } + + // HTTP 1.0 requests are not required to provide a Host to be valid + // Since this is just for display, we can provide a string that is + // not an actual Uri with only the fields that are specified. + // request.GetDisplayUrl(), used above, will throw an exception + // if request.Host is null. + return $"{request.Scheme}://{NoHostSpecified}{request.PathBase.Value}{request.Path.Value}"; + } + + private static SpanContext ExtractPropagatedContext(HttpRequest request) + { + try + { + // extract propagation details from http headers + var requestHeaders = request.Headers; + + if (requestHeaders != null) + { + return SpanContextPropagator.Instance.Extract(new HeadersCollectionAdapter(requestHeaders)); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error extracting propagated HTTP headers."); + } + + return null; + } + + private static IEnumerable> ExtractHeaderTags(HttpRequest request, IDatadogTracer tracer) + { + try + { + // extract propagation details from http headers + var requestHeaders = request.Headers; + + if (requestHeaders != null) + { + return SpanContextPropagator.Instance.ExtractHeaderTags(new HeadersCollectionAdapter(requestHeaders), tracer.Settings.HeaderTags); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error extracting propagated HTTP headers."); + } + + return Enumerable.Empty>(); + } + + private bool ShouldIgnore(HttpContext httpContext) + { + foreach (Func ignore in _options.IgnorePatterns) + { + if (ignore(httpContext)) + { + return true; + } + } + + return false; + } + + private void OnHostingHttpRequestInStart(object arg) + { + var httpContext = HttpRequestInStartHttpContextFetcher.Fetch(arg); + + if (ShouldIgnore(httpContext)) + { + if (_isLogLevelDebugEnabled) + { + Log.Debug("Ignoring request"); + } + } + else + { + HttpRequest request = httpContext.Request; + string host = request.Host.Value; + string httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN"; + string url = GetUrl(request); + + string resourceUrl = UriHelpers.GetRelativeUrl(new Uri(url), tryRemoveIds: true) + .ToLowerInvariant(); + + string resourceName = $"{httpMethod} {resourceUrl}"; + + SpanContext propagatedContext = ExtractPropagatedContext(request); + var tagsFromHeaders = ExtractHeaderTags(request, _tracer); + + Span span = _tracer.StartSpan(HttpRequestInOperationName, propagatedContext) + .SetTag(Tags.InstrumentationName, ComponentName); + + span.DecorateWebServerSpan(resourceName, httpMethod, host, url, tagsFromHeaders); + + // set analytics sample rate if enabled + var analyticsSampleRate = _tracer.Settings.GetIntegrationAnalyticsSampleRate(IntegrationName, enabledWithGlobalSetting: true); + span.SetMetric(Tags.Analytics, analyticsSampleRate); + + Scope scope = _tracer.ActivateSpan(span); + + _options.OnRequest?.Invoke(scope.Span, httpContext); + } + } + + private void OnMvcBeforeAction(object arg) + { + var httpContext = BeforeActionHttpContextFetcher.Fetch(arg); + + if (ShouldIgnore(httpContext)) + { + if (_isLogLevelDebugEnabled) + { + Log.Debug("Ignoring request"); + } + } + else + { + Span span = _tracer.ScopeManager.Active?.Span; + + if (span != null) + { + // NOTE: This event is the start of the action pipeline. The action has been selected, the route + // has been selected but no filters have run and model binding hasn't occured. + var actionDescriptor = BeforeActionActionDescriptorFetcher.Fetch(arg); + HttpRequest request = httpContext.Request; + + string httpMethod = request.Method?.ToUpperInvariant() ?? "UNKNOWN"; + string controllerName = actionDescriptor.RouteValues["controller"]; + string actionName = actionDescriptor.RouteValues["action"]; + string routeTemplate = actionDescriptor.AttributeRouteInfo?.Template ?? $"{controllerName}/{actionName}"; + string resourceName = $"{httpMethod} {routeTemplate}"; + + // override the parent's resource name with the MVC route template + span.ResourceName = resourceName; + } + } + } + + private void OnHostingHttpRequestInStop(object arg) + { + IScope scope = _tracer.ScopeManager.Active; + + if (scope != null) + { + var httpContext = HttpRequestInStopHttpContextFetcher.Fetch(arg); + scope.Span.SetTag(Tags.HttpStatusCode, httpContext.Response.StatusCode.ToString()); + + if (httpContext.Response.StatusCode / 100 == 5) + { + // 5xx codes are server-side errors + scope.Span.Error = true; + } + + scope.Dispose(); + } + } + + private void OnHostingUnhandledException(object arg) + { + ISpan span = _tracer.ScopeManager.Active?.Span; + + if (span != null) + { + var exception = UnhandledExceptionExceptionFetcher.Fetch(arg); + var httpContext = UnhandledExceptionHttpContextFetcher.Fetch(arg); + + span.SetException(exception); + _options.OnError?.Invoke(span, exception, httpContext); + } + } + + private readonly struct HeadersCollectionAdapter : IHeadersCollection + { + private readonly IHeaderDictionary _headers; + + public HeadersCollectionAdapter(IHeaderDictionary headers) + { + _headers = headers; + } + + public IEnumerable GetValues(string name) + { + if (_headers.TryGetValue(name, out var values)) + { + return values.ToArray(); + } + + return Enumerable.Empty(); + } + + public void Set(string name, string value) + { + throw new NotImplementedException(); + } + + public void Add(string name, string value) + { + throw new NotImplementedException(); + } + + public void Remove(string name) + { + throw new NotImplementedException(); + } + } + } +} +#endif diff --git a/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticOptions.cs b/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticOptions.cs new file mode 100644 index 0000000000..96c60e82ab --- /dev/null +++ b/src/Datadog.Trace/DiagnosticListeners/AspNetCoreDiagnosticOptions.cs @@ -0,0 +1,42 @@ +#if NETSTANDARD +using System; +using System.Collections.Generic; +using Datadog.Trace.Abstractions; +using Microsoft.AspNetCore.Http; + +namespace Datadog.Trace.DiagnosticListeners +{ + internal class AspNetCoreDiagnosticOptions + { + private List> _ignorePatterns; + + /// + /// Gets a list of delegates that define whether or not a given request should be ignored. + /// + public List> IgnorePatterns + { + get + { + if (_ignorePatterns == null) + { + _ignorePatterns = new List>(); + } + + return _ignorePatterns; + } + } + + /// + /// Gets or sets a delegate that allows + /// the modification of the created span. + /// + public Action OnRequest { get; set; } + + /// + /// Gets or sets a delegate that allows + /// the modification of the created span when error occurs. + /// + public Action OnError { get; set; } + } +} +#endif diff --git a/src/Datadog.Trace/DiagnosticListeners/DiagnosticManager.cs b/src/Datadog.Trace/DiagnosticListeners/DiagnosticManager.cs new file mode 100644 index 0000000000..56454167bd --- /dev/null +++ b/src/Datadog.Trace/DiagnosticListeners/DiagnosticManager.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.DiagnosticListeners +{ + internal sealed class DiagnosticManager : IDiagnosticManager, IObserver, IDisposable + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly IEnumerable _diagnosticObservers; + private readonly List _subscriptions = new List(); + private IDisposable _allListenersSubscription; + + public DiagnosticManager(IEnumerable diagnosticSubscribers) + { + if (diagnosticSubscribers == null) + { + throw new ArgumentNullException(nameof(diagnosticSubscribers)); + } + + _diagnosticObservers = diagnosticSubscribers.Where(x => x.IsSubscriberEnabled()); + } + + public bool IsRunning => _allListenersSubscription != null; + + public void Start() + { + if (_allListenersSubscription == null) + { + Log.Verbose("Starting AllListeners subscription"); + _allListenersSubscription = DiagnosticListener.AllListeners.Subscribe(this); + } + } + + void IObserver.OnCompleted() + { + } + + void IObserver.OnError(Exception error) + { + } + + void IObserver.OnNext(DiagnosticListener listener) + { + foreach (var subscriber in _diagnosticObservers) + { + IDisposable subscription = subscriber.SubscribeIfMatch(listener); + + if (subscription != null) + { + if (Log.IsEnabled(LogEventLevel.Verbose)) + { + Log.Verbose( + "Subscriber '{0}' returned subscription for '{1}'", + subscriber.GetType().Name, + listener.Name); + } + + _subscriptions.Add(subscription); + } + } + } + + public void Stop() + { + if (_allListenersSubscription != null) + { + if (Log.IsEnabled(LogEventLevel.Verbose)) + { + Log.Verbose("Stopping AllListeners subscription"); + } + + _allListenersSubscription.Dispose(); + _allListenersSubscription = null; + + foreach (var subscription in _subscriptions) + { + subscription.Dispose(); + } + + _subscriptions.Clear(); + } + } + + public void Dispose() + { + Stop(); + } + } +} diff --git a/src/Datadog.Trace/DiagnosticListeners/DiagnosticObserver.cs b/src/Datadog.Trace/DiagnosticListeners/DiagnosticObserver.cs new file mode 100644 index 0000000000..383351b00a --- /dev/null +++ b/src/Datadog.Trace/DiagnosticListeners/DiagnosticObserver.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.DiagnosticListeners +{ + internal abstract class DiagnosticObserver : IObserver> + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + protected DiagnosticObserver(IDatadogTracer tracer) + { + Tracer = tracer ?? throw new ArgumentNullException(nameof(tracer)); + } + + protected IDatadogTracer Tracer { get; } + + /// + /// Gets the name of the that should be instrumented. + /// + /// The name of the that should be instrumented. + protected abstract string ListenerName { get; } + + public virtual bool IsSubscriberEnabled() + { + return true; + } + + public virtual IDisposable SubscribeIfMatch(DiagnosticListener diagnosticListener) + { + if (diagnosticListener.Name == ListenerName) + { + return diagnosticListener.Subscribe(this, IsEventEnabled); + } + + return null; + } + + void IObserver>.OnCompleted() + { + } + + void IObserver>.OnError(Exception error) + { + } + + void IObserver>.OnNext(KeyValuePair value) + { + try + { + OnNext(value.Key, value.Value); + } + catch (Exception ex) + { + Log.Error(ex, "Event Exception: {0}", value.Key); + } + } + + protected virtual bool IsEventEnabled(string eventName) + { + return true; + } + + protected abstract void OnNext(string eventName, object arg); + } +} diff --git a/src/Datadog.Trace/DiagnosticListeners/IDiagnosticManager.cs b/src/Datadog.Trace/DiagnosticListeners/IDiagnosticManager.cs new file mode 100644 index 0000000000..ec3a9bb691 --- /dev/null +++ b/src/Datadog.Trace/DiagnosticListeners/IDiagnosticManager.cs @@ -0,0 +1,9 @@ +namespace Datadog.Trace.DiagnosticListeners +{ + internal interface IDiagnosticManager + { + void Start(); + + void Stop(); + } +} diff --git a/src/Datadog.Trace/DisposableObjectHandle.cs b/src/Datadog.Trace/DisposableObjectHandle.cs new file mode 100644 index 0000000000..a85be7a600 --- /dev/null +++ b/src/Datadog.Trace/DisposableObjectHandle.cs @@ -0,0 +1,52 @@ +#if NET45 +using System; +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; + +namespace Datadog.Trace +{ + // Create a wrapper around ObjectHandle to enable a Sponsor for + // objects stored in the CallContext until the host AppDomain + // no longer needs them. + // This issue was raised in the Serilog library here: https://github.com/serilog/serilog/issues/987 + // This solution was borrowed from the corresponding fix in the following PR: https://github.com/serilog/serilog/pull/992 + internal sealed class DisposableObjectHandle : ObjectHandle, IDisposable + { + private static readonly ISponsor LifeTimeSponsor = new ClientSponsor(); + + private bool _disposed; + + public DisposableObjectHandle(object o) + : base(o) + { + } + + public override object InitializeLifetimeService() + { + var lease = (ILease)base.InitializeLifetimeService(); + lease?.Register(LifeTimeSponsor); + return lease; + } + + public void Dispose() => Dispose(true); + + private void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + if (GetLifetimeService() is ILease lease) + { + lease.Unregister(LifeTimeSponsor); + } + } + + _disposed = true; + } + } +} +#endif diff --git a/src/Datadog.Trace/DogStatsd/NoOpStatsd.cs b/src/Datadog.Trace/DogStatsd/NoOpStatsd.cs new file mode 100644 index 0000000000..6a33bcf0a6 --- /dev/null +++ b/src/Datadog.Trace/DogStatsd/NoOpStatsd.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Concurrent; +using Datadog.Trace.Vendors.StatsdClient; + +namespace Datadog.Trace.DogStatsd +{ + internal class NoOpStatsd : IStatsd + { + public ConcurrentBag Commands { get; } + + public void Send(string name, T value, double sampleRate, params string[] tags) + where TCommandType : Statsd.Metric + { + // no-op + } + + public void Add(string name, T value, double sampleRate, params string[] tags) + where TCommandType : Statsd.Metric + { + // no-op + } + + public void Send(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] tags, bool truncateIfTooLong = false) + { + // no-op + } + + public void Add(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] tags, bool truncateIfTooLong = false) + { + // no-op + } + + public void Send(string command) + { + // no-op + } + + public void Send() + { + // no-op + } + + public void Add(Action actionToTime, string statName, double sampleRate, params string[] tags) + { + // no-op + } + + public void Send(Action actionToTime, string statName, double sampleRate, params string[] tags) + { + // no-op + } + + public void Add(string name, int status, int? timestamp, string hostname, string[] tags, string serviceCheckMessage, bool truncateIfTooLong) + { + // no-op + } + + public void Send(string name, int status, int? timestamp, string hostname, string[] tags, string serviceCheckMessage, bool truncateIfTooLong) + { + // no-op + } + } +} diff --git a/src/Datadog.Trace/DogStatsd/StatsdExtensions.cs b/src/Datadog.Trace/DogStatsd/StatsdExtensions.cs new file mode 100644 index 0000000000..c0ebff2039 --- /dev/null +++ b/src/Datadog.Trace/DogStatsd/StatsdExtensions.cs @@ -0,0 +1,53 @@ +using System; +using System.Linq; +using Datadog.Trace.Vendors.StatsdClient; + +namespace Datadog.Trace.DogStatsd +{ + internal static class StatsdExtensions + { + public static void AppendIncrementCount(this IStatsd statsd, string name, int value = 1, double sampleRate = 1, string[] tags = null) + { + statsd?.Add(name, value, sampleRate, tags); + } + + public static void AppendSetGauge(this IStatsd statsd, string name, int value, double sampleRate = 1, string[] tags = null) + { + statsd?.Add(name, value, sampleRate, tags); + } + + public static void AppendException(this IStatsd statsd, Exception exception, string source, string message, string[] tags = null) + { + if (statsd != null) + { + string[] exceptionTags = + { + $"source:{source}", + $"message:{message}", + $"exception-type:{exception.GetType().FullName}", + $"exception-message:{exception.Message}", + }; + + string[] allTags = exceptionTags.Concat(tags ?? Enumerable.Empty()).ToArray(); + + statsd.Add(TracerMetricNames.Health.Exceptions, value: 1, sampleRate: 1, allTags); + } + } + + public static void AppendWarning(this IStatsd statsd, string source, string message, string[] tags = null) + { + if (statsd != null) + { + string[] warningTags = + { + $"source:{source}", + $"message:{message}" + }; + + string[] allTags = warningTags.Concat(tags ?? Enumerable.Empty()).ToArray(); + + statsd.Add(TracerMetricNames.Health.Warnings, value: 1, sampleRate: 1, allTags); + } + } + } +} diff --git a/src/Datadog.Trace/DogStatsd/TracerMetricNames.cs b/src/Datadog.Trace/DogStatsd/TracerMetricNames.cs new file mode 100644 index 0000000000..021e2b49f3 --- /dev/null +++ b/src/Datadog.Trace/DogStatsd/TracerMetricNames.cs @@ -0,0 +1,94 @@ +namespace Datadog.Trace.DogStatsd +{ + internal static class TracerMetricNames + { + public static class Api + { + /// + /// Count: Total number of API requests made + /// + public const string Requests = "datadog.tracer.api.requests"; + + /// + /// Count: Count of API responses. + /// This metric has an additional tag of "status: {code}" to group the responses by the HTTP response code. + /// This is different from in that this is all HTTP responses + /// regardless of status code, and is exceptions raised from making an API call. + /// + public const string Responses = "datadog.tracer.api.responses"; + + /// + /// Count: Total number of exceptions raised by API calls. + /// This is different from receiving a 4xx or 5xx response. + /// It is a "timeout error" or something from making the API call. + /// + public const string Errors = "datadog.tracer.api.errors"; + } + + public static class Queue + { + /// + /// Count: Total number of traces pushed into the queue (does not include traces dropped due to a full queue) + /// + public const string EnqueuedTraces = "datadog.tracer.queue.enqueued_traces"; + + /// + /// Count: Total number of spans pushed into the queue (does not include traces dropped due to a full queue) + /// + public const string EnqueuedSpans = "datadog.tracer.queue.enqueued_spans"; + + /// + /// Count: Total size in bytes of traces pushed into the queue (does not include traces dropped due to a full queue) + /// + public const string EnqueuedBytes = "datadog.tracer.queue.enqueued_bytes"; + + /// + /// Count: Total number of traces dropped due to a full queue + /// + public const string DroppedTraces = "datadog.tracer.queue.dropped_traces"; + + /// + /// Count: Total number of spans dropped due to a full queue + /// + public const string DroppedSpans = "datadog.tracer.queue.dropped_spans"; + + /// + /// Count: Number of traces pulled from the queue for flushing + /// + public const string DequeuedTraces = "datadog.tracer.queue.dequeued_traces"; + + /// + /// Count: Total number of spans pulled from the queue for flushing + /// + public const string DequeuedSpans = "datadog.tracer.queue.dequeued_spans"; + + /// + /// Count: Size in bytes of traces pulled from the queue for flushing + /// + public const string DequeuedBytes = "datadog.tracer.queue.dequeued_bytes"; + + /// + /// Gauge: The maximum number of traces buffered by the background writer (this is static at 1k for now) + /// + public const string MaxTraces = "datadog.tracer.queue.max_traces"; + } + + public static class Health + { + /// + /// Gauge: Set to 1 by each Tracer instance. + /// + public const string Heartbeat = "datadog.tracer.heartbeat"; + + /// + /// Count: The number of exceptions thrown by the Tracer. + /// + public const string Exceptions = "datadog.tracer.health.exceptions"; + + /// + /// Count: The number of warnings generated by the Tracer. + /// + public const string Warnings = "datadog.tracer.health.warnings"; + } + } +} diff --git a/src/Datadog.Trace/ExtensionMethods/DictionaryExtensions.cs b/src/Datadog.Trace/ExtensionMethods/DictionaryExtensions.cs new file mode 100644 index 0000000000..8456a77b10 --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/DictionaryExtensions.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Datadog.Trace.ExtensionMethods +{ + internal static class DictionaryExtensions + { + public static TValue GetValueOrDefault(this IDictionary dictionary, TKey key) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + return dictionary.TryGetValue(key, out var value) + ? value + : default; + } + + public static TValue GetValueOrDefault(this IDictionary dictionary, object key) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + return dictionary.TryGetValue(key, out TValue value) + ? value + : default; + } + + public static bool TryGetValue(this IDictionary dictionary, object key, out TValue value) + { + if (dictionary == null) + { + throw new ArgumentNullException(nameof(dictionary)); + } + + object valueObj; + + try + { + // per its contract, IDictionary.Item[] should return null instead of throwing an exception + // if a key is not found, but let's use try/catch to be defensive against misbehaving implementations + valueObj = dictionary[key]; + } + catch + { + valueObj = null; + } + + switch (valueObj) + { + case TValue valueTyped: + value = valueTyped; + return true; + case IConvertible convertible: + value = (TValue)convertible.ToType(typeof(TValue), provider: null); + return true; + default: + value = default; + return false; + } + } + } +} diff --git a/src/Datadog.Trace/ExtensionMethods/NameValueCollectionExtensions.cs b/src/Datadog.Trace/ExtensionMethods/NameValueCollectionExtensions.cs new file mode 100644 index 0000000000..09d65fade0 --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/NameValueCollectionExtensions.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Specialized; +using Datadog.Trace.Headers; + +namespace Datadog.Trace.ExtensionMethods +{ + /// + /// Extension methods for objects. + /// + internal static class NameValueCollectionExtensions + { + /// + /// Provides an implementation that wraps the specified . + /// + /// The name/value collection to wrap. + /// An object that implements . + public static IHeadersCollection Wrap(this NameValueCollection collection) + { + if (collection == null) + { + throw new ArgumentNullException(nameof(collection)); + } + + return new NameValueHeadersCollection(collection); + } + } +} diff --git a/src/Datadog.Trace/ExtensionMethods/SpanExtensions.cs b/src/Datadog.Trace/ExtensionMethods/SpanExtensions.cs new file mode 100644 index 0000000000..f696b82515 --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/SpanExtensions.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using Datadog.Trace.Util; + +namespace Datadog.Trace.ExtensionMethods +{ + /// + /// Extension methods for the class. + /// + public static class SpanExtensions + { + /// + /// Sets the sampling priority for the trace that contains the specified . + /// + /// A span that belongs to the trace. + /// The new sampling priority for the trace. + public static void SetTraceSamplingPriority(this Span span, SamplingPriority samplingPriority) + { + if (span == null) { throw new ArgumentNullException(nameof(span)); } + + if (span.Context.TraceContext != null) + { + span.Context.TraceContext.SamplingPriority = samplingPriority; + } + } + + /// + /// Adds standard tags to a span with values taken from the specified . + /// + /// The span to add the tags to. + /// The db command to get tags values from. + public static void AddTagsFromDbCommand(this Span span, IDbCommand command) + { + span.ResourceName = command.CommandText; + span.Type = SpanTypes.Sql; + + var tags = DbCommandCache.GetTagsFromDbCommand(command); + + foreach (var pair in tags) + { + span.SetTag(pair.Key, pair.Value); + } + } + + internal static void DecorateWebServerSpan( + this Span span, + string resourceName, + string method, + string host, + string httpUrl, + IEnumerable> tags) + { + span.Type = SpanTypes.Web; + span.ResourceName = resourceName?.Trim(); + span.SetTag(Tags.SpanKind, SpanKinds.Server); + span.SetTag(Tags.HttpMethod, method); + span.SetTag(Tags.HttpRequestHeadersHost, host); + span.SetTag(Tags.HttpUrl, httpUrl); + span.SetTag(Tags.Language, TracerConstants.Language); + + foreach (KeyValuePair kvp in tags) + { + span.SetTag(kvp.Key, kvp.Value); + } + } + + internal static void SetServerStatusCode(this Span span, int statusCode) + { + span.SetTag(Tags.HttpStatusCode, statusCode.ToString()); + + // 5xx codes are server-side errors + if (statusCode / 100 == 5) + { + span.Error = true; + } + } + } +} diff --git a/src/Datadog.Trace/ExtensionMethods/StringExtensions.cs b/src/Datadog.Trace/ExtensionMethods/StringExtensions.cs new file mode 100644 index 0000000000..e1ae55fdb4 --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/StringExtensions.cs @@ -0,0 +1,68 @@ +using System; + +namespace Datadog.Trace.ExtensionMethods +{ + internal static class StringExtensions + { + /// + /// Removes the trailing occurrence of a substring from the current string. + /// + /// The original string. + /// The string to remove from the end of . + /// One of the enumeration values that determines how this string and are compared. + /// A new string with removed from the end, if found. Otherwise, . + public static string TrimEnd(this string value, string suffix, StringComparison comparisonType) + { + if (value == null) { throw new ArgumentNullException(nameof(value)); } + + return !string.IsNullOrEmpty(suffix) && value.EndsWith(suffix, comparisonType) + ? value.Substring(0, value.Length - suffix.Length) + : value; + } + + /// + /// Converts a into a by comparing it to commonly used values + /// such as "True", "yes", "T", "Y", or "1" for true and "False", "no", "F", "N", or "0" for false. Case-insensitive. + /// Defaults to null if string is not recognized. + /// + /// The string to convert. + /// true or false if is one of the accepted values; null otherwise. + public static bool? ToBoolean(this string value) + { + if (value == null) { throw new ArgumentNullException(nameof(value)); } + + if (value.Length == 1) + { + if (value[0] == 'T' || value[0] == 't' || + value[0] == 'Y' || value[0] == 'y' || + value[0] == '1') + { + return true; + } + + if (value[0] == 'F' || value[0] == 'f' || + value[0] == 'N' || value[0] == 'n' || + value[0] == '0') + { + return false; + } + + return null; + } + + if (string.Equals(value, "TRUE", StringComparison.OrdinalIgnoreCase) || + string.Equals(value, "YES", StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (string.Equals(value, "FALSE", StringComparison.OrdinalIgnoreCase) || + string.Equals(value, "NO", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/ExtensionMethods/TimeExtensions.cs b/src/Datadog.Trace/ExtensionMethods/TimeExtensions.cs new file mode 100644 index 0000000000..ccc3af631e --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/TimeExtensions.cs @@ -0,0 +1,22 @@ +using System; + +namespace Datadog.Trace.ExtensionMethods +{ + internal static class TimeExtensions + { + /// + /// Returns the number of nanoseconds that have elapsed since 1970-01-01T00:00:00.000Z. + /// + /// The value to get the number of elapsed nanoseconds for. + /// The number of nanoseconds that have elapsed since 1970-01-01T00:00:00.000Z. + public static long ToUnixTimeNanoseconds(this DateTimeOffset dateTimeOffset) + { + return (dateTimeOffset.Ticks - TimeConstants.UnixEpochInTicks) * TimeConstants.NanoSecondsPerTick; + } + + public static long ToNanoseconds(this TimeSpan ts) + { + return ts.Ticks * TimeConstants.NanoSecondsPerTick; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/ExtensionMethods/WebHeadersExtensions.cs b/src/Datadog.Trace/ExtensionMethods/WebHeadersExtensions.cs new file mode 100644 index 0000000000..7280f3cac6 --- /dev/null +++ b/src/Datadog.Trace/ExtensionMethods/WebHeadersExtensions.cs @@ -0,0 +1,31 @@ +#if !NETSTANDARD2_0 + +using System; +using System.Net; +using Datadog.Trace.Headers; + +namespace Datadog.Trace.ExtensionMethods +{ + /// + /// Extension methods for objects. + /// + internal static class WebHeadersExtensions + { + /// + /// Provides an implementation that wraps the specified . + /// + /// The Web headers to wrap. + /// An object that implements . + public static IHeadersCollection Wrap(this WebHeaderCollection headers) + { + if (headers == null) + { + throw new ArgumentNullException(nameof(headers)); + } + + return new WebHeadersCollection(headers); + } + } +} + +#endif diff --git a/src/Datadog.Trace/FrameworkDescription.NetCore.cs b/src/Datadog.Trace/FrameworkDescription.NetCore.cs new file mode 100644 index 0000000000..df80ec0c5b --- /dev/null +++ b/src/Datadog.Trace/FrameworkDescription.NetCore.cs @@ -0,0 +1,99 @@ +#if !NETFRAMEWORK +using System; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using Datadog.Trace.Logging; + +namespace Datadog.Trace +{ + internal partial class FrameworkDescription + { + public static FrameworkDescription Create() + { + string frameworkName = null; + string osPlatform = null; + + try + { + // RuntimeInformation.FrameworkDescription returns a string like ".NET Framework 4.7.2" or ".NET Core 2.1", + // we want to return everything before the last space + string frameworkDescription = RuntimeInformation.FrameworkDescription; + int index = frameworkDescription.LastIndexOf(' '); + frameworkName = frameworkDescription.Substring(0, index).Trim(); + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting framework name from RuntimeInformation"); + } + + if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) + { + osPlatform = "Windows"; + } + else if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux)) + { + osPlatform = "Linux"; + } + else if (RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.OSX)) + { + osPlatform = "MacOS"; + } + + return new FrameworkDescription( + frameworkName ?? "unknown", + GetNetCoreOrNetFrameworkVersion() ?? "unknown", + osPlatform ?? "unknown", + RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant(), + RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant()); + } + + private static string GetNetCoreOrNetFrameworkVersion() + { + string productVersion = null; + + if (Environment.Version.Major == 3 || Environment.Version.Major >= 5) + { + // Environment.Version returns "4.x" in .NET Core 2.x, + // but it is correct since .NET Core 3.0.0 + productVersion = Environment.Version.ToString(); + } + + if (productVersion == null) + { + try + { + // try to get product version from assembly path + Match match = Regex.Match( + RootAssembly.CodeBase, + @"/[^/]*microsoft\.netcore\.app/(\d+\.\d+\.\d+[^/]*)/", + RegexOptions.IgnoreCase); + + if (match.Success && match.Groups.Count > 0 && match.Groups[1].Success) + { + productVersion = match.Groups[1].Value; + } + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting .NET Core version from assembly path"); + } + } + + if (productVersion == null) + { + // if we fail to extract version from assembly path, + // fall back to the [AssemblyInformationalVersion] or [AssemblyFileVersion] + productVersion = GetVersionFromAssemblyAttributes(); + } + + if (productVersion == null) + { + // at this point, everything else has failed (this is probably the same as [AssemblyFileVersion] above) + productVersion = Environment.Version.ToString(); + } + + return productVersion; + } + } +} +#endif diff --git a/src/Datadog.Trace/FrameworkDescription.NetFramework.cs b/src/Datadog.Trace/FrameworkDescription.NetFramework.cs new file mode 100644 index 0000000000..9435bb45e8 --- /dev/null +++ b/src/Datadog.Trace/FrameworkDescription.NetFramework.cs @@ -0,0 +1,65 @@ +#if NETFRAMEWORK +using System; +using System.Linq; +using Datadog.Trace.Logging; +using Microsoft.Win32; + +namespace Datadog.Trace +{ + internal partial class FrameworkDescription + { + public static FrameworkDescription Create() + { + // .NET Framework + return new FrameworkDescription( + ".NET Framework", + GetNetFrameworkVersion() ?? "unknown", + "Windows", + Environment.Is64BitOperatingSystem ? "x64" : "x86", + Environment.Is64BitProcess ? "x64" : "x86"); + } + + private static string GetNetFrameworkVersion() + { + string productVersion = null; + + try + { + object registryValue; + + using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default)) + using (var subKey = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\")) + { + registryValue = subKey?.GetValue("Release"); + } + + if (registryValue is int release) + { + // find the known version on the list with the largest release number + // that is lower than or equal to the release number in the Windows Registry + productVersion = DotNetFrameworkVersionMapping.FirstOrDefault(t => release >= t.Item1)?.Item2; + } + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting .NET Framework version from Windows Registry"); + } + + if (productVersion == null) + { + // if we fail to extract version from assembly path, + // fall back to the [AssemblyInformationalVersion] or [AssemblyFileVersion] + productVersion = GetVersionFromAssemblyAttributes(); + } + + if (productVersion == null) + { + // at this point, everything else has failed (this is probably the same as [AssemblyFileVersion] above) + productVersion = Environment.Version.ToString(); + } + + return productVersion; + } + } +} +#endif diff --git a/src/Datadog.Trace/FrameworkDescription.cs b/src/Datadog.Trace/FrameworkDescription.cs new file mode 100644 index 0000000000..e47272e747 --- /dev/null +++ b/src/Datadog.Trace/FrameworkDescription.cs @@ -0,0 +1,98 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using Datadog.Trace.Logging; +using Microsoft.Win32; + +namespace Datadog.Trace +{ + internal partial class FrameworkDescription + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(FrameworkDescription)); + + private static readonly Assembly RootAssembly = typeof(object).Assembly; + + private static readonly Tuple[] DotNetFrameworkVersionMapping = + { + // known min value for each framework version + Tuple.Create(528040, "4.8"), + Tuple.Create(461808, "4.7.2"), + Tuple.Create(461308, "4.7.1"), + Tuple.Create(460798, "4.7"), + Tuple.Create(394802, "4.6.2"), + Tuple.Create(394254, "4.6.1"), + Tuple.Create(393295, "4.6"), + Tuple.Create(379893, "4.5.2"), + Tuple.Create(378675, "4.5.1"), + Tuple.Create(378389, "4.5"), + }; + + private FrameworkDescription( + string name, + string productVersion, + string osPlatform, + string osArchitecture, + string processArchitecture) + { + Name = name; + ProductVersion = productVersion; + OSPlatform = osPlatform; + OSArchitecture = osArchitecture; + ProcessArchitecture = processArchitecture; + } + + public string Name { get; } + + public string ProductVersion { get; } + + public string OSPlatform { get; } + + public string OSArchitecture { get; } + + public string ProcessArchitecture { get; } + + public override string ToString() + { + // examples: + // .NET Framework 4.8 x86 on Windows x64 + // .NET Core 3.0.0 x64 on Linux x64 + return $"{Name} {ProductVersion} {ProcessArchitecture} on {OSPlatform} {OSArchitecture}"; + } + + private static string GetVersionFromAssemblyAttributes() + { + string productVersion = null; + + try + { + // if we fail to extract version from assembly path, fall back to the [AssemblyInformationalVersion], + var informationalVersionAttribute = (AssemblyInformationalVersionAttribute)RootAssembly.GetCustomAttribute(typeof(AssemblyInformationalVersionAttribute)); + + // split remove the commit hash from pre-release versions + productVersion = informationalVersionAttribute?.InformationalVersion?.Split('+')[0]; + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting framework version from [AssemblyInformationalVersion]"); + } + + if (productVersion == null) + { + try + { + // and if that fails, try [AssemblyFileVersion] + var fileVersionAttribute = (AssemblyFileVersionAttribute)RootAssembly.GetCustomAttribute(typeof(AssemblyFileVersionAttribute)); + productVersion = fileVersionAttribute?.Version; + } + catch (Exception e) + { + Log.SafeLogError(e, "Error getting framework version from [AssemblyFileVersion]"); + } + } + + return productVersion; + } + } +} diff --git a/src/Datadog.Trace/Headers/DictionaryHeadersCollection.cs b/src/Datadog.Trace/Headers/DictionaryHeadersCollection.cs new file mode 100644 index 0000000000..a9c509a2ba --- /dev/null +++ b/src/Datadog.Trace/Headers/DictionaryHeadersCollection.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Datadog.Trace.Headers +{ + internal class DictionaryHeadersCollection : IHeadersCollection + { + private readonly IDictionary> _headers; + + public DictionaryHeadersCollection() + { + _headers = new Dictionary>(StringComparer.OrdinalIgnoreCase); + } + + public DictionaryHeadersCollection(int capacity) + { + _headers = new Dictionary>(capacity, StringComparer.OrdinalIgnoreCase); + } + + public DictionaryHeadersCollection(IDictionary> dictionary) + { + _headers = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); + } + + public IEnumerable GetValues(string name) + { + return _headers.TryGetValue(name, out var values) + ? values + : Enumerable.Empty(); + } + + public void Set(string name, string value) + { + _headers.Remove(name); + _headers.Add(name, new List { value }); + } + + public void Add(string name, string value) + { + Add(name, new[] { value }); + } + + public void Add(string name, IEnumerable values) + { + if (!_headers.TryGetValue(name, out var list)) + { + list = new List(); + _headers[name] = list; + } + + foreach (var value in values) + { + list.Add(value); + } + } + + public void Remove(string name) + { + _headers.Remove(name); + } + } +} diff --git a/src/Datadog.Trace/Headers/IHeadersCollection.cs b/src/Datadog.Trace/Headers/IHeadersCollection.cs new file mode 100644 index 0000000000..29ce7558a5 --- /dev/null +++ b/src/Datadog.Trace/Headers/IHeadersCollection.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace Datadog.Trace.Headers +{ + /// + /// Specified a common interface that can be used to manipulate collections of headers. + /// + internal interface IHeadersCollection + { + /// + /// Returns all header values for a specified header stored in the collection. + /// + /// The specified header to return values for. + /// Zero or more header strings. + IEnumerable GetValues(string name); + + /// + /// Sets the value of an entry in the collection, replacing any previous values. + /// + /// The header to add to the collection. + /// The content of the header. + void Set(string name, string value); + + /// + /// Adds the specified header and its value into the collection. + /// + /// The header to add to the collection. + /// The content of the header. + void Add(string name, string value); + + /// + /// Removes the specified header from the collection. + /// + /// The name of the header to remove from the collection. + void Remove(string name); + } +} diff --git a/src/Datadog.Trace/Headers/NameValueHeadersCollection.cs b/src/Datadog.Trace/Headers/NameValueHeadersCollection.cs new file mode 100644 index 0000000000..ea5e2b5d0c --- /dev/null +++ b/src/Datadog.Trace/Headers/NameValueHeadersCollection.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; + +namespace Datadog.Trace.Headers +{ + internal class NameValueHeadersCollection : IHeadersCollection + { + private readonly NameValueCollection _headers; + + public NameValueHeadersCollection(NameValueCollection headers) + { + _headers = headers ?? throw new ArgumentNullException(nameof(headers)); + } + + public IEnumerable GetValues(string name) + { + return _headers.GetValues(name) ?? Enumerable.Empty(); + } + + public void Set(string name, string value) + { + _headers.Set(name, value); + } + + public void Add(string name, string value) + { + _headers.Add(name, value); + } + + public void Remove(string name) + { + _headers.Remove(name); + } + } +} diff --git a/src/Datadog.Trace/Headers/WebHeadersCollection.cs b/src/Datadog.Trace/Headers/WebHeadersCollection.cs new file mode 100644 index 0000000000..01ec0d104b --- /dev/null +++ b/src/Datadog.Trace/Headers/WebHeadersCollection.cs @@ -0,0 +1,33 @@ +#if !NETSTANDARD2_0 + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace Datadog.Trace.Headers +{ + internal class WebHeadersCollection : IHeadersCollection + { + private readonly WebHeaderCollection _headers; + + public WebHeadersCollection(WebHeaderCollection headers) + { + _headers = headers ?? throw new ArgumentNullException(nameof(headers)); + } + + public IEnumerable GetValues(string name) + => _headers.GetValues(name) ?? Enumerable.Empty(); + + public void Set(string name, string value) + => _headers.Set(name, value); + + public void Add(string name, string value) + => _headers.Add(name, value); + + public void Remove(string name) + => _headers.Remove(name); + } +} + +#endif diff --git a/src/Datadog.Trace/HttpHeaderNames.cs b/src/Datadog.Trace/HttpHeaderNames.cs new file mode 100644 index 0000000000..efafe61075 --- /dev/null +++ b/src/Datadog.Trace/HttpHeaderNames.cs @@ -0,0 +1,34 @@ +namespace Datadog.Trace +{ + /// + /// Names of HTTP headers that can be used tracing inbound or outbound HTTP requests. + /// + public static class HttpHeaderNames + { + /// + /// ID of a distributed trace. + /// + public const string TraceId = "x-datadog-trace-id"; + + /// + /// ID of the parent span in a distributed trace. + /// + public const string ParentId = "x-datadog-parent-id"; + + /// + /// Setting used to determine whether a trace should be sampled or not. + /// + public const string SamplingPriority = "x-datadog-sampling-priority"; + + /// + /// If header is set to "false", tracing is disabled for that http request. + /// Tracing is enabled by default. + /// + public const string TracingEnabled = "x-datadog-tracing-enabled"; + + /// + /// Origin of the distributed trace. + /// + public const string Origin = "x-datadog-origin"; + } +} diff --git a/src/Datadog.Trace/IDatadogTracer.cs b/src/Datadog.Trace/IDatadogTracer.cs new file mode 100644 index 0000000000..a4935cb894 --- /dev/null +++ b/src/Datadog.Trace/IDatadogTracer.cs @@ -0,0 +1,40 @@ +using System; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; + +namespace Datadog.Trace +{ + internal interface IDatadogTracer + { + string DefaultServiceName { get; } + + IScopeManager ScopeManager { get; } + + ISampler Sampler { get; } + + TracerSettings Settings { get; } + + Span StartSpan(string operationName); + + Span StartSpan(string operationName, ISpanContext parent); + + Span StartSpan(string operationName, ISpanContext parent, string serviceName, DateTimeOffset? startTime, bool ignoreActiveScope); + + void Write(Span[] span); + + /// + /// Make a span the active span and return its new scope. + /// + /// The span to activate. + /// A Scope object wrapping this span. + Scope ActivateSpan(Span span); + + /// + /// Make a span the active span and return its new scope. + /// + /// The span to activate. + /// Determines whether closing the returned scope will also finish the span. + /// A Scope object wrapping this span. + Scope ActivateSpan(Span span, bool finishOnClose); + } +} diff --git a/src/Datadog.Trace/IScopeManager.cs b/src/Datadog.Trace/IScopeManager.cs new file mode 100644 index 0000000000..7f6c9c82b4 --- /dev/null +++ b/src/Datadog.Trace/IScopeManager.cs @@ -0,0 +1,26 @@ +using System; + +namespace Datadog.Trace +{ + /// + /// Interface for managing a scope. + /// + internal interface IScopeManager + { + event EventHandler SpanOpened; + + event EventHandler SpanActivated; + + event EventHandler SpanDeactivated; + + event EventHandler SpanClosed; + + event EventHandler TraceEnded; + + Scope Active { get; } + + Scope Activate(Span span, bool finishOnClose); + + void Close(Scope scope); + } +} diff --git a/src/Datadog.Trace/ISpanContext.cs b/src/Datadog.Trace/ISpanContext.cs new file mode 100644 index 0000000000..51243a244c --- /dev/null +++ b/src/Datadog.Trace/ISpanContext.cs @@ -0,0 +1,23 @@ +namespace Datadog.Trace +{ + /// + /// Span context interface. + /// + public interface ISpanContext + { + /// + /// Gets the trace identifier. + /// + ulong TraceId { get; } + + /// + /// Gets the span identifier. + /// + ulong SpanId { get; } + + /// + /// Gets the service name to propagate to child spans. + /// + string ServiceName { get; } + } +} diff --git a/src/Datadog.Trace/ITraceContext.cs b/src/Datadog.Trace/ITraceContext.cs new file mode 100644 index 0000000000..2ec11f861f --- /dev/null +++ b/src/Datadog.Trace/ITraceContext.cs @@ -0,0 +1,21 @@ +using System; + +namespace Datadog.Trace +{ + internal interface ITraceContext + { + DateTimeOffset UtcNow { get; } + + SamplingPriority? SamplingPriority { get; set; } + + Span RootSpan { get; } + + void AddSpan(Span span); + + void CloseSpan(Span span); + + void LockSamplingPriority(); + + TimeSpan ElapsedSince(DateTimeOffset date); + } +} diff --git a/src/Datadog.Trace/Logging/DatadogLogging.cs b/src/Datadog.Trace/Logging/DatadogLogging.cs new file mode 100644 index 0000000000..59ff568a19 --- /dev/null +++ b/src/Datadog.Trace/Logging/DatadogLogging.cs @@ -0,0 +1,183 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using Datadog.Trace.Configuration; +using Datadog.Trace.Util; +using Datadog.Trace.Vendors.Serilog; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Sinks.File; + +namespace Datadog.Trace.Logging +{ + internal static class DatadogLogging + { + private static readonly long? MaxLogFileSize = 10 * 1024 * 1024; + private static readonly LoggingLevelSwitch LoggingLevelSwitch = new LoggingLevelSwitch(LogEventLevel.Information); + private static readonly ILogger SharedLogger = null; + + static DatadogLogging() + { + // No-op for if we fail to construct the file logger + SharedLogger = + new LoggerConfiguration() + .WriteTo.Sink() + .CreateLogger(); + try + { + if (GlobalSettings.Source.DebugEnabled) + { + LoggingLevelSwitch.MinimumLevel = LogEventLevel.Verbose; + } + + var maxLogSizeVar = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.MaxLogFileSize); + if (long.TryParse(maxLogSizeVar, out var maxLogSize)) + { + // No verbose or debug logs + MaxLogFileSize = maxLogSize; + } + + string logDirectory = null; + try + { + logDirectory = GetLogDirectory(); + } + catch + { + // Do nothing when an exception is thrown for attempting to access the filesystem + } + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (logDirectory == null) + { + return; + } + + // Ends in a dash because of the date postfix + var managedLogPath = Path.Combine(logDirectory, $"dotnet-tracer-{DomainMetadata.ProcessName}-.log"); + + var loggerConfiguration = + new LoggerConfiguration() + .Enrich.FromLogContext() + .MinimumLevel.ControlledBy(LoggingLevelSwitch) + .WriteTo.File( + managedLogPath, + outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}{Properties}{NewLine}", + rollingInterval: RollingInterval.Day, + rollOnFileSizeLimit: true, + fileSizeLimitBytes: MaxLogFileSize); + + try + { + loggerConfiguration.Enrich.WithProperty("MachineName", DomainMetadata.MachineName); + loggerConfiguration.Enrich.WithProperty("Process", $"[{DomainMetadata.ProcessId} {DomainMetadata.ProcessName}]"); + loggerConfiguration.Enrich.WithProperty("AppDomain", $"[{DomainMetadata.AppDomainId} {DomainMetadata.AppDomainName}]"); + loggerConfiguration.Enrich.WithProperty("TracerVersion", TracerConstants.AssemblyVersion); + } + catch + { + // At all costs, make sure the logger works when possible. + } + + SharedLogger = loggerConfiguration.CreateLogger(); + } + catch + { + // Don't let this exception bubble up as this logger is for debugging and is non-critical + } + } + + public static ILogger GetLogger(Type classType) + { + // Tells us which types are loaded, when, and how often. + SharedLogger.Debug($"Logger retrieved for: {classType.AssemblyQualifiedName}"); + return SharedLogger; + } + + public static ILogger For() + { + return GetLogger(typeof(T)); + } + + public static void SafeLogError(this ILogger logger, Exception ex, string message, params object[] args) + { + try + { + logger.Error(ex, message, args); + } + catch + { + try + { + message = string.Format(message, args); + Console.Error.WriteLine($"{message} {ex}"); + } + catch + { + // ignore + } + } + } + + internal static void SetLogLevel(LogEventLevel logLevel) + { + LoggingLevelSwitch.MinimumLevel = logLevel; + } + + internal static void UseDefaultLevel() + { + SetLogLevel(LogEventLevel.Information); + } + + private static string GetLogDirectory() + { + var nativeLogFile = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.ProfilerLogPath); + string logDirectory = null; + + if (!string.IsNullOrEmpty(nativeLogFile)) + { + logDirectory = Path.GetDirectoryName(nativeLogFile); + } + + // This entire block may throw a SecurityException if not granted the System.Security.Permissions.FileIOPermission + // because of the following API calls + // - Directory.Exists + // - Environment.GetFolderPath + // - Path.GetTempPath + if (logDirectory == null) + { +#if NETFRAMEWORK + logDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Datadog .NET Tracer", "logs"); +#else + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + logDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Datadog .NET Tracer", "logs"); + } + else + { + // Linux + logDirectory = "/var/log/datadog/dotnet"; + } +#endif + } + + if (!Directory.Exists(logDirectory)) + { + try + { + Directory.CreateDirectory(logDirectory); + } + catch + { + // Unable to create the directory meaning that the user + // will have to create it on their own. + // Last effort at writing logs + logDirectory = Path.GetTempPath(); + } + } + + return logDirectory; + } + } +} diff --git a/src/Datadog.Trace/Logging/LibLogScopeEventSubscriber.cs b/src/Datadog.Trace/Logging/LibLogScopeEventSubscriber.cs new file mode 100644 index 0000000000..397a885544 --- /dev/null +++ b/src/Datadog.Trace/Logging/LibLogScopeEventSubscriber.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using Datadog.Trace.Logging.LogProviders; + +namespace Datadog.Trace.Logging +{ + /// + /// Subscriber to ScopeManager events that sets/unsets correlation identifier + /// properties in the application's logging context. + /// + internal class LibLogScopeEventSubscriber : IDisposable + { + private const int _numPropertiesSetOnSpanEvent = 5; + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(LibLogScopeEventSubscriber)); + private readonly IScopeManager _scopeManager; + private readonly string _defaultServiceName; + private readonly string _version; + private readonly string _env; + private readonly ILogProvider _logProvider; + + // Each mapped context sets a key-value pair into the logging context + // Disposing the returned context unsets the key-value pair + // Keep a stack to retain the history of our correlation identifier properties + // (the stack is particularly important for Serilog, see below). + // + // IMPORTANT: Serilog -- The logging contexts (throughout the entire application) + // are maintained in a stack, as opposed to a map, and must be closed + // in reverse-order of opening. When operating on the stack-based model, + // it is only valid to add the properties once and unset them once. + private readonly ConcurrentStack _contextDisposalStack = new ConcurrentStack(); + + private bool _safeToAddToMdc = true; + + // IMPORTANT: For all logging frameworks, do not set any default values for + // "dd.trace_id" and "dd.span_id" when initializing the subscriber + // because the Tracer may be initialized at a time when it is not safe + // to add properties logging context of the underlying logging framework. + // + // Failure to abide by this can cause a SerializationException when + // control is passed from one AppDomain to another where the originating + // AppDomain used a logging framework that stored logging context properties + // inside the System.Runtime.Remoting.Messaging.CallContext structure + // but the target AppDomain is unable to de-serialize the object -- + // this can easily happen if the target AppDomain cannot find/load the + // logging framework assemblies. + public LibLogScopeEventSubscriber(IScopeManager scopeManager, string defaultServiceName, string version, string env) + { + _scopeManager = scopeManager; + _defaultServiceName = defaultServiceName; + _version = version; + _env = env; + + try + { + _logProvider = LogProvider.CurrentLogProvider ?? LogProvider.ResolveLogProvider(); + if (_logProvider is SerilogLogProvider) + { + // Do not set default values for Serilog because it is unsafe to set + // except at the application startup, but this would require auto-instrumentation + _scopeManager.SpanOpened += StackOnSpanOpened; + _scopeManager.SpanClosed += StackOnSpanClosed; + } + else + { + _scopeManager.SpanActivated += MapOnSpanActivated; + _scopeManager.TraceEnded += MapOnTraceEnded; + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Could not successfully start the LibLogScopeEventSubscriber. There was an issue resolving the application logger."); + } + } + + public void StackOnSpanOpened(object sender, SpanEventArgs spanEventArgs) + { + SetCorrelationIdentifierContext(_defaultServiceName, _version, _env, spanEventArgs.Span.TraceId, spanEventArgs.Span.SpanId); + } + + public void StackOnSpanClosed(object sender, SpanEventArgs spanEventArgs) + { + RemoveLastCorrelationIdentifierContext(); + } + + public void MapOnSpanActivated(object sender, SpanEventArgs spanEventArgs) + { + RemoveAllCorrelationIdentifierContexts(); + SetCorrelationIdentifierContext(_defaultServiceName, _version, _env, spanEventArgs.Span.TraceId, spanEventArgs.Span.SpanId); + } + + public void MapOnTraceEnded(object sender, SpanEventArgs spanEventArgs) + { + RemoveAllCorrelationIdentifierContexts(); + SetDefaultValues(); + } + + public void Dispose() + { + if (_logProvider is SerilogLogProvider) + { + _scopeManager.SpanOpened -= StackOnSpanOpened; + _scopeManager.SpanClosed -= StackOnSpanClosed; + } + else + { + _scopeManager.SpanActivated -= MapOnSpanActivated; + _scopeManager.TraceEnded -= MapOnTraceEnded; + } + + RemoveAllCorrelationIdentifierContexts(); + } + + private void SetDefaultValues() + { + SetCorrelationIdentifierContext(_defaultServiceName, _version, _env, 0, 0); + } + + private void RemoveLastCorrelationIdentifierContext() + { + // TODO: Debug logs + for (int i = 0; i < _numPropertiesSetOnSpanEvent; i++) + { + if (_contextDisposalStack.TryPop(out var ctxDisposable)) + { + ctxDisposable.Dispose(); + } + else + { + // There is nothing left to pop so do nothing. + // Though we are in a strange circumstance if we did not balance + // the stack properly + Debug.Fail($"{nameof(RemoveLastCorrelationIdentifierContext)} call failed. Too few items on the context stack."); + } + } + } + + private void RemoveAllCorrelationIdentifierContexts() + { + // TODO: Debug logs + while (_contextDisposalStack.TryPop(out IDisposable ctxDisposable)) + { + ctxDisposable.Dispose(); + } + } + + private void SetCorrelationIdentifierContext(string service, string version, string env, ulong traceId, ulong spanId) + { + if (!_safeToAddToMdc) + { + return; + } + + try + { + // TODO: Debug logs + _contextDisposalStack.Push( + LogProvider.OpenMappedContext( + CorrelationIdentifier.ServiceKey, service, destructure: false)); + _contextDisposalStack.Push( + LogProvider.OpenMappedContext( + CorrelationIdentifier.VersionKey, version, destructure: false)); + _contextDisposalStack.Push( + LogProvider.OpenMappedContext( + CorrelationIdentifier.EnvKey, env, destructure: false)); + _contextDisposalStack.Push( + LogProvider.OpenMappedContext( + CorrelationIdentifier.TraceIdKey, traceId.ToString(), destructure: false)); + _contextDisposalStack.Push( + LogProvider.OpenMappedContext( + CorrelationIdentifier.SpanIdKey, spanId.ToString(), destructure: false)); + } + catch (Exception) + { + _safeToAddToMdc = false; + RemoveAllCorrelationIdentifierContexts(); + } + } + } +} diff --git a/src/Datadog.Trace/Logging/LoggingExtensions.cs b/src/Datadog.Trace/Logging/LoggingExtensions.cs new file mode 100644 index 0000000000..5041edbe64 --- /dev/null +++ b/src/Datadog.Trace/Logging/LoggingExtensions.cs @@ -0,0 +1,13 @@ +using System; + +namespace Datadog.Trace.Logging +{ + internal static partial class LibLogExtensions + { + public static bool ErrorExceptionForFilter(this ILog logger, string message, Exception exception, params object[] formatParams) + { + logger.ErrorException(message, exception, formatParams); + return false; + } + } +} diff --git a/src/Datadog.Trace/Metrics.cs b/src/Datadog.Trace/Metrics.cs new file mode 100644 index 0000000000..e18f9f35af --- /dev/null +++ b/src/Datadog.Trace/Metrics.cs @@ -0,0 +1,25 @@ +namespace Datadog.Trace +{ + internal static class Metrics + { + public const string SamplingPriority = "_sampling_priority_v1"; + + /// + /// To be set when the agent determines the sampling rate for a trace + /// Read: Agent Priority Sample Rate + /// + public const string SamplingAgentDecision = "_dd.agent_psr"; + + /// + /// To be set when a sampling rule is applied to a trace + /// Read: Sampling Rule Priority Sample Rate + /// + public const string SamplingRuleDecision = "_dd.rule_psr"; + + /// + /// To be set when a rate limiter is applied to a trace. + /// Read: Rate Limiter Priority Sample Rate + /// + public const string SamplingLimitDecision = "_dd.limit_psr"; + } +} diff --git a/src/Datadog.Trace/PlatformHelpers/AzureAppservices.cs b/src/Datadog.Trace/PlatformHelpers/AzureAppservices.cs new file mode 100644 index 0000000000..b5283e022e --- /dev/null +++ b/src/Datadog.Trace/PlatformHelpers/AzureAppservices.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace.PlatformHelpers +{ + internal class AzureAppServices + { + /// + /// Configuration key which is used as a flag to tell us whether we are running in the context of Azure App Services. + /// + internal static readonly string AzureAppServicesContextKey = "DD_AZURE_APP_SERVICES"; + + /// + /// Example: 8c56d827-5f07-45ce-8f2b-6c5001db5c6f+apm-dotnet-EastUSwebspace + /// Format: {subscriptionId}+{planResourceGroup}-{hostedInRegion} + /// + internal static readonly string WebsiteOwnerNameKey = "WEBSITE_OWNER_NAME"; + + /// + /// This is the name of the resource group the site instance is assigned to. + /// + internal static readonly string ResourceGroupKey = "WEBSITE_RESOURCE_GROUP"; + + /// + /// This is the unique name of the website instance within azure app services. + /// + internal static readonly string SiteNameKey = "WEBSITE_DEPLOYMENT_ID"; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(AzureAppServices)); + + static AzureAppServices() + { + Metadata = new AzureAppServices(EnvironmentHelpers.GetEnvironmentVariables()); + } + + public AzureAppServices(IDictionary environmentVariables) + { + IsRelevant = GetVariableIfExists(AzureAppServicesContextKey, environmentVariables)?.ToBoolean() ?? false; + if (IsRelevant) + { + SubscriptionId = GetSubscriptionId(environmentVariables); + ResourceGroup = GetVariableIfExists(ResourceGroupKey, environmentVariables); + SiteName = GetVariableIfExists(SiteNameKey, environmentVariables); + ResourceId = CompileResourceId(); + } + } + + public static AzureAppServices Metadata { get; set; } + + public bool IsRelevant { get; } + + public string SubscriptionId { get; } + + public string ResourceGroup { get; } + + public string SiteName { get; } + + public string ResourceId { get; } + + private string CompileResourceId() + { + string resourceId = null; + + try + { + var success = true; + if (SubscriptionId == null) + { + success = false; + Log.Warning("Could not successfully retrieve the subscription ID from variable: {0}", WebsiteOwnerNameKey); + } + + if (SiteName == null) + { + success = false; + Log.Warning("Could not successfully retrieve the deployment ID from variable: {0}", SiteNameKey); + } + + if (ResourceGroup == null) + { + success = false; + Log.Warning("Could not successfully retrieve the resource group name from variable: {0}", ResourceGroupKey); + } + + if (success) + { + resourceId = $"/subscriptions/{SubscriptionId}/resourcegroups/{ResourceGroup}/providers/microsoft.web/sites/{SiteName}".ToLowerInvariant(); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Could not successfully setup the resource id for azure app services."); + } + + return resourceId; + } + + private string GetSubscriptionId(IDictionary environmentVariables) + { + try + { + var websiteOwner = GetVariableIfExists(WebsiteOwnerNameKey, environmentVariables); + if (!string.IsNullOrWhiteSpace(websiteOwner)) + { + var plusSplit = websiteOwner.Split('+'); + if (plusSplit.Length > 0 && !string.IsNullOrWhiteSpace(plusSplit[0])) + { + return plusSplit[0]; + } + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Could not successfully retrieve the subscription id for azure app services."); + } + + return null; + } + + private string GetVariableIfExists(string key, IDictionary environmentVariables) + { + if (environmentVariables.Contains(key)) + { + return environmentVariables[key]?.ToString(); + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/PlatformHelpers/ContainerMetadata.cs b/src/Datadog.Trace/PlatformHelpers/ContainerMetadata.cs new file mode 100644 index 0000000000..8e2cb63f99 --- /dev/null +++ b/src/Datadog.Trace/PlatformHelpers/ContainerMetadata.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using System.Threading; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.PlatformHelpers +{ + /// + /// Utility class with methods to interact with container hosts. + /// + internal static class ContainerMetadata + { + private const string ControlGroupsFilePath = "/proc/self/cgroup"; + + private const string ContainerIdRegex = @"^(?:\d+):(?:[^:]*):/?(?:.+/)([0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}|[0-9a-f]{64}(?:\.scope)?)$"; + + private static readonly Lazy ContainerId = new Lazy(GetContainerIdInternal, LazyThreadSafetyMode.ExecutionAndPublication); + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ContainerMetadata)); + + /// + /// Gets the id of the container executing the code. + /// Return null if code is not executing inside a supported container. + /// + /// The container id or null. + public static string GetContainerId() + { + return ContainerId.Value; + } + + /// + /// Uses regular expression to try to extract a container id from the specified string. + /// + /// Lines of text from a cgroup file. + /// The container id if found; otherwise, null. + public static string ParseCgroupLines(IEnumerable lines) + { + return lines.Select(ParseCgroupLine) + .FirstOrDefault(id => !string.IsNullOrWhiteSpace(id)); + } + + /// + /// Uses regular expression to try to extract a container id from the specified string. + /// + /// A single line from a cgroup file. + /// The container id if found; otherwise, null. + public static string ParseCgroupLine(string line) + { + var lineMatch = Regex.Match(line, ContainerIdRegex); + + return lineMatch.Success + ? lineMatch.Groups[1].Value + : null; + } + + private static string GetContainerIdInternal() + { + try + { + var isLinux = string.Equals(FrameworkDescription.Create().OSPlatform, "Linux", StringComparison.OrdinalIgnoreCase); + + if (isLinux && + File.Exists(ControlGroupsFilePath)) + { + var lines = File.ReadLines(ControlGroupsFilePath); + return ParseCgroupLines(lines); + } + } + catch (Exception ex) + { + Log.Warning("Error reading cgroup file. Will not report container id.", ex); + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/Sampling/CustomSamplingRule.cs b/src/Datadog.Trace/Sampling/CustomSamplingRule.cs new file mode 100644 index 0000000000..7bc29f59b2 --- /dev/null +++ b/src/Datadog.Trace/Sampling/CustomSamplingRule.cs @@ -0,0 +1,155 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Datadog.Trace.Logging; +using Newtonsoft.Json; + +namespace Datadog.Trace.Sampling +{ + internal class CustomSamplingRule : ISamplingRule + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + private static readonly TimeSpan RegexTimeout = TimeSpan.FromSeconds(1); + + private readonly float _samplingRate; + private readonly string _serviceNameRegex; + private readonly string _operationNameRegex; + + private bool _hasPoisonedRegex = false; + + public CustomSamplingRule( + float rate, + string ruleName, + string serviceNameRegex, + string operationNameRegex) + { + _samplingRate = rate; + _serviceNameRegex = WrapWithLineCharacters(serviceNameRegex); + _operationNameRegex = WrapWithLineCharacters(operationNameRegex); + RuleName = ruleName; + } + + public string RuleName { get; } + + /// + /// Gets or sets the priority of the rule. + /// Configuration rules will default to 1 as a priority and rely on order of specification. + /// + public int Priority { get; protected set; } = 1; + + public static IEnumerable BuildFromConfigurationString(string configuration) + { + try + { + if (!string.IsNullOrEmpty(configuration)) + { + var index = 0; + var rules = JsonConvert.DeserializeObject>(configuration); + return rules.Select( + r => + { + index++; // Used to create a readable rule name if one is not specified + return new CustomSamplingRule(r.SampleRate, r.RuleName ?? $"config-rule-{index}", r.Service, r.OperationName); + }); + } + } + catch (Exception ex) + { + Log.Error(ex, "Unable to parse custom sampling rules"); + } + + return Enumerable.Empty(); + } + + public bool IsMatch(Span span) + { + if (_hasPoisonedRegex) + { + return false; + } + + if (DoesNotMatch(input: span.ServiceName, pattern: _serviceNameRegex)) + { + return false; + } + + if (DoesNotMatch(input: span.OperationName, pattern: _operationNameRegex)) + { + return false; + } + + return true; + } + + public float GetSamplingRate(Span span) + { + span.SetMetric(Metrics.SamplingRuleDecision, _samplingRate); + return _samplingRate; + } + + private static string WrapWithLineCharacters(string regex) + { + if (regex == null) + { + return regex; + } + + if (!regex.StartsWith("^")) + { + regex = "^" + regex; + } + + if (!regex.EndsWith("$")) + { + regex = regex + "$"; + } + + return regex; + } + + private bool DoesNotMatch(string input, string pattern) + { + try + { + if (pattern != null && + !Regex.IsMatch( + input: input, + pattern: pattern, + options: RegexOptions.None, + matchTimeout: RegexTimeout)) + { + return true; + } + } + catch (RegexMatchTimeoutException timeoutEx) + { + _hasPoisonedRegex = true; + Log.Error( + timeoutEx, + "Timeout when trying to match against {0} on {1}.", + input, + pattern); + } + + return false; + } + + [Serializable] + private class CustomRuleConfig + { + [JsonProperty(PropertyName = "rule_name")] + public string RuleName { get; set; } + + [JsonRequired] + [JsonProperty(PropertyName = "sample_rate")] + public float SampleRate { get; set; } + + [JsonProperty(PropertyName = "name")] + public string OperationName { get; set; } + + [JsonProperty(PropertyName = "service")] + public string Service { get; set; } + } + } +} diff --git a/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs b/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs new file mode 100644 index 0000000000..57443fe0fd --- /dev/null +++ b/src/Datadog.Trace/Sampling/DefaultSamplingRule.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.Sampling +{ + internal class DefaultSamplingRule : ISamplingRule + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private static Dictionary _sampleRates = new Dictionary(); + + public string RuleName => "default-rule"; + + /// + /// Gets the lowest possible priority + /// + public int Priority => int.MinValue; + + public bool IsMatch(Span span) + { + return true; + } + + public float GetSamplingRate(Span span) + { + Log.Debug("Using the default sampling logic"); + + var env = span.GetTag(Tags.Env); + var service = span.ServiceName; + + var key = $"service:{service},env:{env}"; + + if (_sampleRates.TryGetValue(key, out var sampleRate)) + { + span.SetMetric(Metrics.SamplingAgentDecision, sampleRate); + return sampleRate; + } + + Log.Debug("Could not establish sample rate for trace {0}", span.TraceId); + + return 1; + } + + public void SetDefaultSampleRates(IEnumerable> sampleRates) + { + // to avoid locking if writers and readers can access the dictionary at the same time, + // build the new dictionary first, then replace the old one + var rates = new Dictionary(StringComparer.OrdinalIgnoreCase); + + if (sampleRates != null) + { + foreach (var pair in sampleRates) + { + rates.Add(pair.Key, pair.Value); + } + } + + _sampleRates = rates; + } + } +} diff --git a/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs b/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs new file mode 100644 index 0000000000..89539210b5 --- /dev/null +++ b/src/Datadog.Trace/Sampling/GlobalSamplingRule.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.Sampling +{ + internal class GlobalSamplingRule : ISamplingRule + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly float _globalRate; + + public GlobalSamplingRule(float rate) + { + _globalRate = rate; + } + + public string RuleName => "global-rate-rule"; + + /// + /// Gets the priority which is one beneath custom rules. + /// + public int Priority => 0; + + public bool IsMatch(Span span) + { + return true; + } + + public float GetSamplingRate(Span span) + { + Log.Debug("Using the global sampling rate: {0}", _globalRate); + span.SetMetric(Metrics.SamplingRuleDecision, _globalRate); + return _globalRate; + } + } +} diff --git a/src/Datadog.Trace/Sampling/IRateLimiter.cs b/src/Datadog.Trace/Sampling/IRateLimiter.cs new file mode 100644 index 0000000000..eec006be64 --- /dev/null +++ b/src/Datadog.Trace/Sampling/IRateLimiter.cs @@ -0,0 +1,9 @@ +namespace Datadog.Trace.Sampling +{ + internal interface IRateLimiter + { + bool Allowed(Span span); + + float GetEffectiveRate(); + } +} diff --git a/src/Datadog.Trace/Sampling/ISampler.cs b/src/Datadog.Trace/Sampling/ISampler.cs new file mode 100644 index 0000000000..571e3d9ef2 --- /dev/null +++ b/src/Datadog.Trace/Sampling/ISampler.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Datadog.Trace.Sampling +{ + internal interface ISampler + { + void SetDefaultSampleRates(IEnumerable> sampleRates); + + SamplingPriority GetSamplingPriority(Span span); + + void RegisterRule(ISamplingRule rule); + } +} diff --git a/src/Datadog.Trace/Sampling/ISamplingRule.cs b/src/Datadog.Trace/Sampling/ISamplingRule.cs new file mode 100644 index 0000000000..858982faa1 --- /dev/null +++ b/src/Datadog.Trace/Sampling/ISamplingRule.cs @@ -0,0 +1,21 @@ +namespace Datadog.Trace.Sampling +{ + internal interface ISamplingRule + { + /// + /// Gets the rule name. + /// Used for debugging purposes mostly. + /// + string RuleName { get; } + + /// + /// Gets the priority. + /// Higher number means higher priority. + /// + int Priority { get; } + + bool IsMatch(Span span); + + float GetSamplingRate(Span span); + } +} diff --git a/src/Datadog.Trace/Sampling/RateLimiter.cs b/src/Datadog.Trace/Sampling/RateLimiter.cs new file mode 100644 index 0000000000..ca9c47b242 --- /dev/null +++ b/src/Datadog.Trace/Sampling/RateLimiter.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.Sampling +{ + internal class RateLimiter : IRateLimiter + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly ConcurrentQueue _intervalQueue = new ConcurrentQueue(); + + private readonly int _maxTracesPerInterval; + private readonly int _intervalMilliseconds; + private readonly TimeSpan _interval; + + private DateTime _windowBegin; + + private int _refreshing; + + private int _windowChecks = 0; + private int _windowAllowed = 0; + + private int _previousWindowChecks = 0; + private int _previousWindowAllowed = 0; + + public RateLimiter(int? maxTracesPerInterval) + { + _maxTracesPerInterval = maxTracesPerInterval ?? 100; + _intervalMilliseconds = 1_000; + _interval = TimeSpan.FromMilliseconds(_intervalMilliseconds); + _windowBegin = DateTime.UtcNow; + } + + public bool Allowed(Span span) + { + try + { + if (_maxTracesPerInterval == 0) + { + // Rate limit of 0 blocks everything + return false; + } + + if (_maxTracesPerInterval < 0) + { + // Negative rate limit disables rate limiting + return true; + } + + WaitForRefresh(); + + // This must happen after the wait, because we check for window statistics, modifying this number + Interlocked.Increment(ref _windowChecks); + + var count = _intervalQueue.Count; + + if (count >= _maxTracesPerInterval) + { + Log.Debug("Dropping trace id {0} with count of {1} for last {2}ms.", span.TraceId, count, _intervalMilliseconds); + return false; + } + + _intervalQueue.Enqueue(DateTime.UtcNow); + Interlocked.Increment(ref _windowAllowed); + + return true; + } + finally + { + // Always set the sample rate metric whether it was allowed or not + // DEV: Setting this allows us to properly compute metrics and debug the + // various sample rates that are getting applied to this span + span.SetMetric(Metrics.SamplingLimitDecision, GetEffectiveRate()); + } + } + + public float GetEffectiveRate() + { + if (_maxTracesPerInterval == 0) + { + // Rate limit of 0 blocks everything + return 0; + } + + if (_maxTracesPerInterval < 0) + { + // Negative rate limit disables rate limiting + return 1; + } + + var totalChecksForLastTwoWindows = _windowChecks + _previousWindowChecks; + + if (totalChecksForLastTwoWindows == 0) + { + // no checks, effectively 100%. don't divide by zero + return 1; + } + + // Current window + previous window to prevent burst-iness and low new window numbers from skewing the rate + return (_windowAllowed + _previousWindowAllowed) / (float)totalChecksForLastTwoWindows; + } + + private void WaitForRefresh() + { + int refreshInProgress = 0; + + try + { + refreshInProgress = Interlocked.CompareExchange(ref _refreshing, 1, 0); + + if (refreshInProgress != 0) + { + // A refresh is already in progress + return; + } + + var now = DateTime.UtcNow; + + var timeSinceWindowStart = (now - _windowBegin).TotalMilliseconds; + + if (timeSinceWindowStart >= _intervalMilliseconds) + { + // statistical window has passed, shift the counts + _previousWindowAllowed = _windowAllowed; + _previousWindowChecks = _windowChecks; + _windowAllowed = 0; + _windowChecks = 0; + _windowBegin = now; + } + + while (_intervalQueue.TryPeek(out var time) && now.Subtract(time) > _interval) + { + _intervalQueue.TryDequeue(out _); + } + } + finally + { + if (refreshInProgress == 0) + { + // If refreshing is 0, it means that this thread acquired the lock + // Releasing it before leaving + // Note: a full fence might not be needed here, but better safe than sorry + Interlocked.Exchange(ref _refreshing, 0); + } + } + } + } +} diff --git a/src/Datadog.Trace/Sampling/RuleBasedSampler.cs b/src/Datadog.Trace/Sampling/RuleBasedSampler.cs new file mode 100644 index 0000000000..72fd467835 --- /dev/null +++ b/src/Datadog.Trace/Sampling/RuleBasedSampler.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using Datadog.Trace.Logging; + +namespace Datadog.Trace.Sampling +{ + internal class RuleBasedSampler : ISampler + { + private const ulong KnuthFactor = 1_111_111_111_111_111_111; + + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + private static bool _tracingWithoutLimitsEnabled = false; + + private readonly IRateLimiter _limiter; + private readonly DefaultSamplingRule _defaultRule = new DefaultSamplingRule(); + private readonly List _rules = new List(); + + public RuleBasedSampler(IRateLimiter limiter) + { + _limiter = limiter ?? new RateLimiter(null); + RegisterRule(_defaultRule); + } + + public static void OptInTracingWithoutLimits() + { + _tracingWithoutLimitsEnabled = true; + } + + public void SetDefaultSampleRates(IEnumerable> sampleRates) + { + _defaultRule.SetDefaultSampleRates(sampleRates); + } + + public SamplingPriority GetSamplingPriority(Span span) + { + var traceId = span.TraceId; + + if (_rules.Count > 0) + { + foreach (var rule in _rules) + { + if (rule.IsMatch(span)) + { + var sampleRate = rule.GetSamplingRate(span); + + Log.Debug( + "Matched on rule {0}. Applying rate of {1} to trace id {2}", + rule.RuleName, + sampleRate, + traceId); + + return GetSamplingPriority(span, sampleRate); + } + } + } + + Log.Debug("No rules matched for trace {0}", traceId); + + return SamplingPriority.AutoKeep; + } + + /// + /// Will insert a rule according to how high the Priority field is set. + /// If the priority is equal to other rules, the new rule will be the last in that priority group. + /// + /// The new rule being registered. + public void RegisterRule(ISamplingRule rule) + { + OptInTracingWithoutLimits(); + + for (var i = 0; i < _rules.Count; i++) + { + if (_rules[i].Priority < rule.Priority) + { + _rules.Insert(i, rule); + return; + } + } + + // No items or this is the last priority + _rules.Add(rule); + } + + private SamplingPriority GetSamplingPriority(Span span, float rate) + { + var sample = ((span.TraceId * KnuthFactor) % TracerConstants.MaxTraceId) <= (rate * TracerConstants.MaxTraceId); + var priority = SamplingPriority.AutoReject; + + if (sample) + { + if (_tracingWithoutLimitsEnabled) + { + if (_limiter.Allowed(span)) + { + priority = SamplingPriority.AutoKeep; + } + } + else + { + priority = SamplingPriority.AutoKeep; + } + } + + return priority; + } + } +} diff --git a/src/Datadog.Trace/SamplingPriority.cs b/src/Datadog.Trace/SamplingPriority.cs new file mode 100644 index 0000000000..d2fd647729 --- /dev/null +++ b/src/Datadog.Trace/SamplingPriority.cs @@ -0,0 +1,28 @@ +namespace Datadog.Trace +{ + /// + /// A traces sampling priority determines whether is should be kept and stored. + /// + public enum SamplingPriority + { + /// + /// Explicitly ask the backend to not store a trace. + /// + UserReject = -1, + + /// + /// Used by the built-in sampler to inform the backend that a trace should be rejected and not stored. + /// + AutoReject = 0, + + /// + /// Used by the built-in sampler to inform the backend that a trace should be kept and stored. + /// + AutoKeep = 1, + + /// + /// Explicitly ask the backend to keep a trace. + /// + UserKeep = 2 + } +} diff --git a/src/Datadog.Trace/Scope.cs b/src/Datadog.Trace/Scope.cs new file mode 100644 index 0000000000..50763cb038 --- /dev/null +++ b/src/Datadog.Trace/Scope.cs @@ -0,0 +1,66 @@ +using Datadog.Trace.Abstractions; + +namespace Datadog.Trace +{ + /// + /// A scope is a handle used to manage the concept of an active span. + /// Meaning that at a given time at most one span is considered active and + /// all newly created spans that are not created with the ignoreActiveSpan + /// parameter will be automatically children of the active span. + /// + public class Scope : IScope + { + private readonly IScopeManager _scopeManager; + private readonly bool _finishOnClose; + + internal Scope(Scope parent, Span span, IScopeManager scopeManager, bool finishOnClose) + { + Parent = parent; + Span = span; + _scopeManager = scopeManager; + _finishOnClose = finishOnClose; + } + + /// + /// Gets the active span wrapped in this scope + /// + public Span Span { get; } + + /// + /// Gets the active span wrapped in this scope + /// Proxy to Span without concrete return value + /// + ISpan IScope.Span => Span; + + internal Scope Parent { get; } + + /// + /// Closes the current scope and makes its parent scope active + /// + public void Close() + { + _scopeManager.Close(this); + + if (_finishOnClose) + { + Span.Finish(); + } + } + + /// + /// Closes the current scope and makes its parent scope active + /// + public void Dispose() + { + try + { + Close(); + } + catch + { + // Ignore disposal exceptions here... + // TODO: Log? only in test/debug? How should Close() concerns be handled (i.e. independent?) + } + } + } +} diff --git a/src/Datadog.Trace/ScopeManagerBase.cs b/src/Datadog.Trace/ScopeManagerBase.cs new file mode 100644 index 0000000000..c6504f4923 --- /dev/null +++ b/src/Datadog.Trace/ScopeManagerBase.cs @@ -0,0 +1,72 @@ +using System; +using Datadog.Trace.Logging; + +namespace Datadog.Trace +{ + internal abstract class ScopeManagerBase : IScopeManager + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.GetLogger(typeof(ScopeManagerBase)); + + public event EventHandler SpanOpened; + + public event EventHandler SpanActivated; + + public event EventHandler SpanDeactivated; + + public event EventHandler SpanClosed; + + public event EventHandler TraceEnded; + + public abstract Scope Active { get; protected set; } + + public Scope Activate(Span span, bool finishOnClose) + { + var newParent = Active; + var scope = new Scope(newParent, span, this, finishOnClose); + var scopeOpenedArgs = new SpanEventArgs(span); + + SpanOpened?.Invoke(this, scopeOpenedArgs); + + Active = scope; + + if (newParent != null) + { + SpanDeactivated?.Invoke(this, new SpanEventArgs(newParent.Span)); + } + + SpanActivated?.Invoke(this, scopeOpenedArgs); + + return scope; + } + + public void Close(Scope scope) + { + var current = Active; + var isRootSpan = scope.Parent == null; + + if (current == null || current != scope) + { + // This is not the current scope for this context, bail out + SpanClosed?.Invoke(this, new SpanEventArgs(scope.Span)); + return; + } + + // if the scope that was just closed was the active scope, + // set its parent as the new active scope + Active = scope.Parent; + SpanDeactivated?.Invoke(this, new SpanEventArgs(scope.Span)); + + if (!isRootSpan) + { + SpanActivated?.Invoke(this, new SpanEventArgs(scope.Parent.Span)); + } + + SpanClosed?.Invoke(this, new SpanEventArgs(scope.Span)); + + if (isRootSpan) + { + TraceEnded?.Invoke(this, new SpanEventArgs(scope.Span)); + } + } + } +} diff --git a/src/Datadog.Trace/Span.cs b/src/Datadog.Trace/Span.cs new file mode 100644 index 0000000000..4440b1d117 --- /dev/null +++ b/src/Datadog.Trace/Span.cs @@ -0,0 +1,420 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using Datadog.Trace.Abstractions; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace +{ + /// + /// A Span represents a logical unit of work in the system. It may be + /// related to other spans by parent/children relationships. The span + /// tracks the duration of an operation as well as associated metadata in + /// the form of a resource name, a service name, and user defined tags. + /// + public class Span : IDisposable, ISpan + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + private static readonly bool IsLogLevelDebugEnabled = Log.IsEnabled(LogEventLevel.Debug); + + private readonly object _lock = new object(); + private readonly object _tagsLock = new object(); + private readonly object _metricLock = new object(); + + internal Span(SpanContext context, DateTimeOffset? start) + { + Context = context; + ServiceName = context.ServiceName; + StartTime = start ?? Context.TraceContext.UtcNow; + + Log.Debug( + "Span started: [s_id: {0}, p_id: {1}, t_id: {2}]", + SpanId, + Context.ParentId, + TraceId); + } + + /// + /// Gets or sets operation name + /// + public string OperationName { get; set; } + + /// + /// Gets or sets the resource name + /// + public string ResourceName { get; set; } + + /// + /// Gets or sets the type of request this span represents (ex: web, db). + /// Not to be confused with span kind. + /// + /// + public string Type { get; set; } + + /// + /// Gets or sets a value indicating whether this span represents an error + /// + public bool Error { get; set; } + + /// + /// Gets or sets the service name. + /// + public string ServiceName + { + get => Context.ServiceName; + set => Context.ServiceName = value; + } + + /// + /// Gets the trace's unique identifier. + /// + public ulong TraceId => Context.TraceId; + + /// + /// Gets the span's unique identifier. + /// + public ulong SpanId => Context.SpanId; + + internal SpanContext Context { get; } + + internal DateTimeOffset StartTime { get; private set; } + + internal TimeSpan Duration { get; private set; } + + internal Dictionary Tags { get; private set; } + + internal Dictionary Metrics { get; private set; } + + internal bool IsFinished { get; private set; } + + internal bool IsRootSpan => Context?.TraceContext?.RootSpan == this; + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + var sb = new StringBuilder(); + sb.AppendLine($"TraceId: {Context.TraceId}"); + sb.AppendLine($"ParentId: {Context.ParentId}"); + sb.AppendLine($"SpanId: {Context.SpanId}"); + sb.AppendLine($"ServiceName: {ServiceName}"); + sb.AppendLine($"OperationName: {OperationName}"); + sb.AppendLine($"Resource: {ResourceName}"); + sb.AppendLine($"Type: {Type}"); + sb.AppendLine($"Start: {StartTime}"); + sb.AppendLine($"Duration: {Duration}"); + sb.AppendLine($"Error: {Error}"); + sb.AppendLine("Meta:"); + + if (Tags?.Count > 0) + { + // lock because we're iterating the collection, not reading a single value + lock (_tagsLock) + { + foreach (var kv in Tags) + { + sb.Append($"\t{kv.Key}:{kv.Value}"); + } + } + } + + sb.AppendLine("Metrics:"); + + if (Metrics?.Count > 0) + { + // lock because we're iterating the collection, not reading a single value + lock (_metricLock) + { + foreach (var kv in Metrics) + { + sb.Append($"\t{kv.Key}:{kv.Value}"); + } + } + } + + return sb.ToString(); + } + + /// + /// Add a the specified tag to this span. + /// + /// The tag's key. + /// The tag's value. + /// This span to allow method chaining. + public Span SetTag(string key, string value) + { + if (IsFinished) + { + Log.Debug("SetTag should not be called after the span was closed"); + return this; + } + + // some tags have special meaning + switch (key) + { + case Trace.Tags.SamplingPriority: + if (Enum.TryParse(value, out SamplingPriority samplingPriority) && + Enum.IsDefined(typeof(SamplingPriority), samplingPriority)) + { + // allow setting the sampling priority via a tag + Context.TraceContext.SamplingPriority = samplingPriority; + } + + break; +#pragma warning disable CS0618 // Type or member is obsolete + case Trace.Tags.ForceKeep: + case Trace.Tags.ManualKeep: + if (value.ToBoolean() ?? false) + { + // user-friendly tag to set UserKeep priority + Context.TraceContext.SamplingPriority = SamplingPriority.UserKeep; + } + + break; + case Trace.Tags.ForceDrop: + case Trace.Tags.ManualDrop: + if (value.ToBoolean() ?? false) + { + // user-friendly tag to set UserReject priority + Context.TraceContext.SamplingPriority = SamplingPriority.UserReject; + } + + break; +#pragma warning restore CS0618 // Type or member is obsolete + case Trace.Tags.Analytics: + // value is a string and can represent a bool ("true") or a double ("0.5"), + // so try to parse both. + // note that "1" and "0" can parse as either type, + // but they mean the same thing in this case, so it's fine. + bool? boolean = value.ToBoolean(); + + if (boolean == true) + { + // always sample + SetMetric(Trace.Tags.Analytics, 1.0); + } + else if (boolean == false) + { + // never sample + SetMetric(Trace.Tags.Analytics, 0.0); + } + else if (double.TryParse( + value, + NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, + CultureInfo.InvariantCulture, + out double analyticsSampleRate)) + { + // use specified sample rate + SetMetric(Trace.Tags.Analytics, analyticsSampleRate); + } + else + { + Log.Warning("Value {0} has incorrect format for tag {1}", value, Trace.Tags.Analytics); + } + + break; + default: + if (value == null) + { + if (Tags != null) + { + // lock when modifying the collection + lock (_tagsLock) + { + // Agent doesn't accept null tag values, + // remove them instead + Tags.Remove(key); + } + } + } + else + { + // lock when modifying the collection + lock (_tagsLock) + { + if (Tags == null) + { + // defer instantiation until needed to + // avoid unnecessary allocations per span + Tags = new Dictionary(); + } + + // if not a special tag, just add it to the tag bag + Tags[key] = value; + } + } + + break; + } + + return this; + } + + /// + /// Add a the specified tag to this span. + /// + /// The tag's key. + /// The tag's value. + /// This span to allow method chaining. + ISpan ISpan.SetTag(string key, string value) + => SetTag(key, value); + + /// + /// Record the end time of the span and flushes it to the backend. + /// After the span has been finished all modifications will be ignored. + /// + public void Finish() + { + Finish(Context.TraceContext.ElapsedSince(StartTime)); + } + + /// + /// Explicitly set the end time of the span and flushes it to the backend. + /// After the span has been finished all modifications will be ignored. + /// + /// Explicit value for the end time of the Span + public void Finish(DateTimeOffset finishTimestamp) + { + Finish(finishTimestamp - StartTime); + } + + /// + /// Record the end time of the span and flushes it to the backend. + /// After the span has been finished all modifications will be ignored. + /// + public void Dispose() + { + Finish(); + } + + /// + /// Add the StackTrace and other exception metadata to the span + /// + /// The exception. + public void SetException(Exception exception) + { + Error = true; + + if (exception != null) + { + // for AggregateException, use the first inner exception until we can support multiple errors. + // there will be only one error in most cases, and even if there are more and we lose + // the other ones, it's still better than the generic "one or more errors occurred" message. + if (exception is AggregateException aggregateException && aggregateException.InnerExceptions.Count > 0) + { + exception = aggregateException.InnerExceptions[0]; + } + + SetTag(Trace.Tags.ErrorMsg, exception.Message); + SetTag(Trace.Tags.ErrorStack, exception.ToString()); + SetTag(Trace.Tags.ErrorType, exception.GetType().ToString()); + } + } + + /// + /// Gets the value (or default/null if the key is not a valid tag) of a tag with the key value passed + /// + /// The tag's key + /// The value for the tag with the key specified, or null if the tag does not exist + public string GetTag(string key) + { + switch (key) + { + case Trace.Tags.SamplingPriority: + return ((int?)(Context.TraceContext?.SamplingPriority ?? Context.SamplingPriority))?.ToString(); + default: + // no need to lock on single reads + return Tags != null && Tags.TryGetValue(key, out var value) ? value : null; + } + } + + internal void Finish(TimeSpan duration) + { + var shouldCloseSpan = false; + lock (_lock) + { + ResourceName ??= OperationName; + + if (!IsFinished) + { + Duration = duration; + if (Duration < TimeSpan.Zero) + { + Duration = TimeSpan.Zero; + } + + IsFinished = true; + shouldCloseSpan = true; + } + } + + if (shouldCloseSpan) + { + Context.TraceContext.CloseSpan(this); + + if (IsLogLevelDebugEnabled) + { + Log.Debug( + "Span closed: [s_id: {0}, p_id: {1}, t_id: {2}] for (Service: {3}, Resource: {4}, Operation: {5}, Tags: [{6}])", + SpanId, + Context.ParentId, + TraceId, + ServiceName, + ResourceName, + OperationName, + Tags == null ? string.Empty : string.Join(",", Tags.Keys)); + } + } + } + + internal double? GetMetric(string key) + { + // no need to lock on single reads + return Metrics != null && Metrics.TryGetValue(key, out double value) ? value : default; + } + + internal Span SetMetric(string key, double? value) + { + if (value == null) + { + if (Metrics != null) + { + // lock when modifying the collection + lock (_metricLock) + { + Metrics.Remove(key); + } + } + } + else + { + // lock when modifying the collection + lock (_metricLock) + { + if (Metrics == null) + { + // defer instantiation until needed to + // avoid unnecessary allocations per span + Metrics = new Dictionary(); + } + + Metrics[key] = value.Value; + } + } + + return this; + } + + internal void ResetStartTime() + { + StartTime = Context.TraceContext.UtcNow; + } + } +} diff --git a/src/Datadog.Trace/SpanContext.cs b/src/Datadog.Trace/SpanContext.cs new file mode 100644 index 0000000000..d1ab10acc3 --- /dev/null +++ b/src/Datadog.Trace/SpanContext.cs @@ -0,0 +1,118 @@ +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; + +namespace Datadog.Trace +{ + /// + /// The SpanContext contains all the information needed to express relationships between spans inside or outside the process boundaries. + /// + public class SpanContext : ISpanContext + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + /// + /// Initializes a new instance of the class + /// from a propagated context. will be null + /// since this is a root context locally. + /// + /// The propagated trace id. + /// The propagated span id. + /// The propagated sampling priority. + /// The service name to propagate to child spans. + public SpanContext(ulong? traceId, ulong spanId, SamplingPriority? samplingPriority = null, string serviceName = null) + : this(traceId, serviceName) + { + SpanId = spanId; + SamplingPriority = samplingPriority; + } + + /// + /// Initializes a new instance of the class + /// from a propagated context. will be null + /// since this is a root context locally. + /// + /// The propagated trace id. + /// The propagated span id. + /// The propagated sampling priority. + /// The service name to propagate to child spans. + /// The propagated origin of the trace. + internal SpanContext(ulong? traceId, ulong spanId, SamplingPriority? samplingPriority, string serviceName, string origin) + : this(traceId, serviceName) + { + SpanId = spanId; + SamplingPriority = samplingPriority; + Origin = origin; + } + + /// + /// Initializes a new instance of the class + /// that is the child of the specified parent context. + /// + /// The parent context. + /// The trace context. + /// The service name to propagate to child spans. + internal SpanContext(ISpanContext parent, ITraceContext traceContext, string serviceName) + : this(parent?.TraceId, serviceName) + { + SpanId = SpanIdGenerator.CreateNew(); + Parent = parent; + TraceContext = traceContext; + if (parent is SpanContext spanContext) + { + Origin = spanContext.Origin; + } + } + + private SpanContext(ulong? traceId, string serviceName) + { + TraceId = traceId > 0 + ? traceId.Value + : SpanIdGenerator.CreateNew(); + + ServiceName = serviceName; + } + + /// + /// Gets the parent context. + /// + public ISpanContext Parent { get; } + + /// + /// Gets the trace id + /// + public ulong TraceId { get; } + + /// + /// Gets the span id of the parent span + /// + public ulong? ParentId => Parent?.SpanId; + + /// + /// Gets the span id + /// + public ulong SpanId { get; } + + /// + /// Gets or sets the service name to propagate to child spans. + /// + public string ServiceName { get; set; } + + /// + /// Gets the origin of the trace + /// + internal string Origin { get; } + + /// + /// Gets the trace context. + /// Returns null for contexts created from incoming propagated context. + /// + internal ITraceContext TraceContext { get; } + + /// + /// Gets the sampling priority for contexts created from incoming propagated context. + /// Returns null for local contexts. + /// + internal SamplingPriority? SamplingPriority { get; } + } +} diff --git a/src/Datadog.Trace/SpanContextPropagator.cs b/src/Datadog.Trace/SpanContextPropagator.cs new file mode 100644 index 0000000000..8476297e43 --- /dev/null +++ b/src/Datadog.Trace/SpanContextPropagator.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using Datadog.Trace.Headers; +using Datadog.Trace.Logging; + +namespace Datadog.Trace +{ + internal class SpanContextPropagator + { + private const NumberStyles NumberStyles = System.Globalization.NumberStyles.Integer; + + private static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private static readonly int[] SamplingPriorities; + + static SpanContextPropagator() + { + SamplingPriorities = Enum.GetValues(typeof(SamplingPriority)).Cast().ToArray(); + } + + private SpanContextPropagator() + { + } + + public static SpanContextPropagator Instance { get; } = new SpanContextPropagator(); + + /// + /// Propagates the specified context by adding new headers to a . + /// This locks the sampling priority for . + /// + /// A value that will be propagated into . + /// A to add new headers to. + /// Type of header collection + public void Inject(SpanContext context, T headers) + where T : IHeadersCollection + { + if (context == null) { throw new ArgumentNullException(nameof(context)); } + + if (headers == null) { throw new ArgumentNullException(nameof(headers)); } + + // lock sampling priority when span propagates. + context.TraceContext?.LockSamplingPriority(); + + headers.Set(HttpHeaderNames.TraceId, context.TraceId.ToString(InvariantCulture)); + headers.Set(HttpHeaderNames.ParentId, context.SpanId.ToString(InvariantCulture)); + + // avoid writing origin header if not set, keeping the previous behavior. + if (context.Origin != null) + { + headers.Set(HttpHeaderNames.Origin, context.Origin); + } + + var samplingPriority = (int?)(context.TraceContext?.SamplingPriority ?? context.SamplingPriority); + + headers.Set( + HttpHeaderNames.SamplingPriority, + samplingPriority?.ToString(InvariantCulture)); + } + + /// + /// Extracts a from the values found in the specified headers. + /// + /// The headers that contain the values to be extracted. + /// Type of header collection + /// A new that contains the values obtained from . + public SpanContext Extract(T headers) + where T : IHeadersCollection + { + if (headers == null) + { + throw new ArgumentNullException(nameof(headers)); + } + + var traceId = ParseUInt64(headers, HttpHeaderNames.TraceId); + + if (traceId == 0) + { + // a valid traceId is required to use distributed tracing + return null; + } + + var parentId = ParseUInt64(headers, HttpHeaderNames.ParentId); + var samplingPriority = ParseSamplingPriority(headers, HttpHeaderNames.SamplingPriority); + var origin = ParseString(headers, HttpHeaderNames.Origin); + + return new SpanContext(traceId, parentId, samplingPriority, null, origin); + } + + public IEnumerable> ExtractHeaderTags(T headers, IEnumerable> headerToTagMap) + where T : IHeadersCollection + { + var tagsFromHeaders = new Dictionary(); + + foreach (KeyValuePair headerNameToTagName in headerToTagMap) + { + string headerValue = ParseString(headers, headerNameToTagName.Key); + if (headerValue != null) + { + tagsFromHeaders.Add(headerNameToTagName.Value, headerValue); + } + } + + return tagsFromHeaders; + } + + private static ulong ParseUInt64(T headers, string headerName) + where T : IHeadersCollection + { + var headerValues = headers.GetValues(headerName); + + bool hasValue = false; + + foreach (string headerValue in headerValues) + { + if (ulong.TryParse(headerValue, NumberStyles, InvariantCulture, out var result)) + { + return result; + } + + hasValue = true; + } + + if (hasValue) + { + Log.Information("Could not parse {0} headers: {1}", headerName, string.Join(",", headerValues)); + } + + return 0; + } + + private static SamplingPriority? ParseSamplingPriority(T headers, string headerName) + where T : IHeadersCollection + { + var headerValues = headers.GetValues(headerName); + + bool hasValue = false; + + foreach (string headerValue in headerValues) + { + if (int.TryParse(headerValue, out var result)) + { + foreach (var validValue in SamplingPriorities) + { + if (validValue == result) + { + return (SamplingPriority)result; + } + } + } + + hasValue = true; + } + + if (hasValue) + { + Log.Information( + "Could not parse {0} headers: {1}", + headerName, + string.Join(",", headerValues)); + } + + return default; + } + + private static string ParseString(IHeadersCollection headers, string headerName) + { + var headerValues = headers.GetValues(headerName); + + foreach (string headerValue in headerValues) + { + if (!string.IsNullOrEmpty(headerValue)) + { + return headerValue; + } + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/SpanEventArgs.cs b/src/Datadog.Trace/SpanEventArgs.cs new file mode 100644 index 0000000000..86696ad2b9 --- /dev/null +++ b/src/Datadog.Trace/SpanEventArgs.cs @@ -0,0 +1,19 @@ +using System; + +namespace Datadog.Trace +{ + /// + /// EventArgs for a Span + /// + internal class SpanEventArgs : EventArgs + { + /// + /// Initializes a new instance of the class. + /// Creates a new using + /// + /// The used to initialize the object. + public SpanEventArgs(Span span) => Span = span; + + internal Span Span { get; } + } +} diff --git a/src/Datadog.Trace/SpanKinds.cs b/src/Datadog.Trace/SpanKinds.cs new file mode 100644 index 0000000000..453302781c --- /dev/null +++ b/src/Datadog.Trace/SpanKinds.cs @@ -0,0 +1,34 @@ +namespace Datadog.Trace +{ + /// + /// A set of standard span kinds that can be used by integrations. + /// Not to be confused with span types. + /// + /// + public static class SpanKinds + { + /// + /// A span generated by the client in a client/server architecture. + /// + /// + public const string Client = "client"; + + /// + /// A span generated by the server in a client/server architecture. + /// + /// + public const string Server = "server"; + + /// + /// A span generated by the producer in a producer/consumer architecture. + /// + /// + public const string Producer = "producer"; + + /// + /// A span generated by the consumer in a producer/consumer architecture. + /// + /// + public const string Consumer = "consumer"; + } +} diff --git a/src/Datadog.Trace/SpanTypes.cs b/src/Datadog.Trace/SpanTypes.cs new file mode 100644 index 0000000000..30651f3af2 --- /dev/null +++ b/src/Datadog.Trace/SpanTypes.cs @@ -0,0 +1,60 @@ +namespace Datadog.Trace +{ + /// + /// A set of standard span types that can be used by integrations. + /// Not to be confused with span kinds. + /// + /// + public static class SpanTypes + { + /// + /// The span type for a Redis client integration. + /// + public const string Redis = "redis"; + + /// + /// The span type for a SQL client integration. + /// + public const string Sql = "sql"; + + /// + /// The span type for a web framework integration (incoming HTTP requests). + /// + public const string Web = "web"; + + /// + /// The span type for a MongoDB integration. + /// + public const string MongoDb = "mongodb"; + + /// + /// The span type for an outgoing HTTP integration. + /// + public const string Http = "http"; + + /// + /// The span type for a GraphQL integration. + /// + public const string GraphQL = "graphql"; + + /// + /// The span type for a custom integration. + /// + public const string Custom = "custom"; + + /// + /// The span type for a Test instegration. + /// + public const string Test = "test"; + + /// + /// The span type for a Benchmark integration. + /// + public const string Benchmark = "benchmark"; + + /// + /// The span type for msbuild integration. + /// + public const string Build = "build"; + } +} diff --git a/src/Datadog.Trace/Tags.cs b/src/Datadog.Trace/Tags.cs new file mode 100644 index 0000000000..aad96dd1f8 --- /dev/null +++ b/src/Datadog.Trace/Tags.cs @@ -0,0 +1,214 @@ +using System; + +namespace Datadog.Trace +{ + /// + /// Standard span tags used by integrations. + /// + public static class Tags + { + /// + /// The environment of the profiled service. + /// + public const string Env = "env"; + + /// + /// The version of the profiled service. + /// + public const string Version = "version"; + + /// + /// The name of the integration that generated the span. + /// Use OpenTracing tag "component" + /// + public const string InstrumentationName = "component"; + + /// + /// The name of the method that was instrumented to generate the span. + /// + public const string InstrumentedMethod = "instrumented.method"; + + /// + /// The kind of span (e.g. client, server). Not to be confused with . + /// + /// + public const string SpanKind = "span.kind"; + + /// + /// The URL of an HTTP request + /// + public const string HttpUrl = "http.url"; + + /// + /// The method of an HTTP request + /// + public const string HttpMethod = "http.method"; + + /// + /// The host of an HTTP request + /// + public const string HttpRequestHeadersHost = "http.request.headers.host"; + + /// + /// The status code of an HTTP response + /// + public const string HttpStatusCode = "http.status_code"; + + /// + /// The error message of an exception + /// + public const string ErrorMsg = "error.msg"; + + /// + /// The type of an exception + /// + public const string ErrorType = "error.type"; + + /// + /// The stack trace of an exception + /// + public const string ErrorStack = "error.stack"; + + /// + /// The type of database (e.g. mssql, mysql) + /// + public const string DbType = "db.type"; + + /// + /// The user used to sign into a database + /// + public const string DbUser = "db.user"; + + /// + /// The name of the database. + /// + public const string DbName = "db.name"; + + /// + /// The query text + /// + public const string SqlQuery = "sql.query"; + + /// + /// The number of rows returned by a query + /// + public const string SqlRows = "sql.rows"; + + /// + /// The ASP.NET routing template. + /// + public const string AspNetRoute = "aspnet.route"; + + /// + /// The MVC or Web API controller name. + /// + public const string AspNetController = "aspnet.controller"; + + /// + /// The MVC or Web API action name. + /// + public const string AspNetAction = "aspnet.action"; + + /// + /// The hostname of a outgoing server connection. + /// + public const string OutHost = "out.host"; + + /// + /// The port of a outgoing server connection. + /// + public const string OutPort = "out.port"; + + /// + /// The raw command sent to Redis. + /// + public const string RedisRawCommand = "redis.raw_command"; + + /// + /// A MongoDB query. + /// + public const string MongoDbQuery = "mongodb.query"; + + /// + /// A MongoDB collection name. + /// + public const string MongoDbCollection = "mongodb.collection"; + + /// + /// The operation name of the GraphQL request. + /// + public const string GraphQLOperationName = "graphql.operation.name"; + + /// + /// The operation type of the GraphQL request. + /// + public const string GraphQLOperationType = "graphql.operation.type"; + + /// + /// The source defining the GraphQL request. + /// + public const string GraphQLSource = "graphql.source"; + + /// + /// The sampling priority for the entire trace. + /// + public const string SamplingPriority = "sampling.priority"; + + /// + /// Obsolete. Use . + /// + [Obsolete("This field will be removed in futures versions of this library. Use ManualKeep instead.")] + public const string ForceKeep = "force.keep"; + + /// + /// Obsolete. Use . + /// + [Obsolete("This field will be removed in futures versions of this library. Use ManualDrop instead.")] + public const string ForceDrop = "force.drop"; + + /// + /// A user-friendly tag that sets the sampling priority to . + /// + public const string ManualKeep = "manual.keep"; + + /// + /// A user-friendly tag that sets the sampling priority to . + /// + public const string ManualDrop = "manual.drop"; + + /// + /// Configures Trace Analytics. + /// + public const string Analytics = "_dd1.sr.eausr"; + + /// + /// Language tag, applied to root spans that are .NET runtime (e.g., ASP.NET) + /// + public const string Language = "language"; + + /// + /// The resource id of the site instance in azure app services where the traced application is running. + /// + public const string AzureAppServicesResourceId = "aas.resource.id"; + + /// + /// The resource group of the site instance in azure app services where the traced application is running. + /// + public const string AzureAppServicesResourceGroup = "aas.resource.group"; + + /// + /// The site name of the site instance in azure app services where the traced application is running. + /// + public const string AzureAppServicesSiteName = "aas.site.name"; + + /// + /// The subscription id of the site instance in azure app services where the traced application is running. + /// + public const string AzureAppServicesSubscriptionId = "aas.subscription.id"; + + /// + /// Configures the origin of the trace + /// + public const string Origin = "_dd.origin"; + } +} diff --git a/src/Datadog.Trace/TimeConstants.cs b/src/Datadog.Trace/TimeConstants.cs new file mode 100644 index 0000000000..7eb220a432 --- /dev/null +++ b/src/Datadog.Trace/TimeConstants.cs @@ -0,0 +1,11 @@ +using System; + +namespace Datadog.Trace +{ + internal static class TimeConstants + { + public const long NanoSecondsPerTick = 1000000 / TimeSpan.TicksPerMillisecond; + + public const long UnixEpochInTicks = 621355968000000000; // = DateTimeOffset.FromUnixTimeMilliseconds(0).Ticks + } +} diff --git a/src/Datadog.Trace/TraceContext.cs b/src/Datadog.Trace/TraceContext.cs new file mode 100644 index 0000000000..3a288ed78c --- /dev/null +++ b/src/Datadog.Trace/TraceContext.cs @@ -0,0 +1,156 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Datadog.Trace.Logging; +using Datadog.Trace.PlatformHelpers; +using Datadog.Trace.Util; + +namespace Datadog.Trace +{ + internal class TraceContext : ITraceContext + { + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + private readonly DateTimeOffset _utcStart = DateTimeOffset.UtcNow; + private readonly long _timestamp = Stopwatch.GetTimestamp(); + private readonly List _spans = new List(); + + private int _openSpans; + private SamplingPriority? _samplingPriority; + private bool _samplingPriorityLocked; + + public TraceContext(IDatadogTracer tracer) + { + Tracer = tracer; + } + + public Span RootSpan { get; private set; } + + public DateTimeOffset UtcNow => _utcStart.Add(Elapsed); + + public IDatadogTracer Tracer { get; } + + /// + /// Gets or sets sampling priority. + /// Once the sampling priority is locked with , + /// further attempts to set this are ignored. + /// + public SamplingPriority? SamplingPriority + { + get => _samplingPriority; + set + { + if (!_samplingPriorityLocked) + { + _samplingPriority = value; + } + } + } + + private TimeSpan Elapsed => StopwatchHelpers.GetElapsed(Stopwatch.GetTimestamp() - _timestamp); + + public void AddSpan(Span span) + { + lock (_spans) + { + if (RootSpan == null) + { + // first span added is the root span + RootSpan = span; + DecorateRootSpan(span); + + if (_samplingPriority == null) + { + if (span.Context.Parent is SpanContext context && context.SamplingPriority != null) + { + // this is a root span created from a propagated context that contains a sampling priority. + // lock sampling priority when a span is started from a propagated trace. + _samplingPriority = context.SamplingPriority; + LockSamplingPriority(); + } + else + { + // this is a local root span (i.e. not propagated). + // determine an initial sampling priority for this trace, but don't lock it yet + _samplingPriority = + Tracer.Sampler?.GetSamplingPriority(RootSpan); + } + } + } + + _spans.Add(span); + _openSpans++; + } + } + + public void CloseSpan(Span span) + { + if (span == RootSpan) + { + // lock sampling priority and set metric when root span finishes + LockSamplingPriority(); + + if (_samplingPriority == null) + { + Log.Warning("Cannot set span metric for sampling priority before it has been set."); + } + else + { + span.SetMetric(Metrics.SamplingPriority, (int)_samplingPriority); + } + } + + Span[] spansToWrite = null; + + lock (_spans) + { + _openSpans--; + + if (_openSpans == 0) + { + spansToWrite = _spans.ToArray(); + _spans.Clear(); + } + } + + if (spansToWrite != null) + { + Tracer.Write(spansToWrite); + } + } + + public void LockSamplingPriority() + { + if (_samplingPriority == null) + { + Log.Warning("Cannot lock sampling priority before it has been set."); + } + else + { + _samplingPriorityLocked = true; + } + } + + public TimeSpan ElapsedSince(DateTimeOffset date) + { + return Elapsed + (_utcStart - date); + } + + private void DecorateRootSpan(Span span) + { + if (AzureAppServices.Metadata?.IsRelevant ?? false) + { + span.SetTag(Tags.AzureAppServicesSiteName, AzureAppServices.Metadata.SiteName); + span.SetTag(Tags.AzureAppServicesResourceGroup, AzureAppServices.Metadata.ResourceGroup); + span.SetTag(Tags.AzureAppServicesSubscriptionId, AzureAppServices.Metadata.SubscriptionId); + span.SetTag(Tags.AzureAppServicesResourceId, AzureAppServices.Metadata.ResourceId); + } + + // set the origin tag to the root span of each trace/subtrace + if (span.Context.Origin != null) + { + span.SetTag(Tags.Origin, span.Context.Origin); + } + } + } +} diff --git a/src/Datadog.Trace/Tracer.cs b/src/Datadog.Trace/Tracer.cs new file mode 100644 index 0000000000..c27e3025cc --- /dev/null +++ b/src/Datadog.Trace/Tracer.cs @@ -0,0 +1,675 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.DiagnosticListeners; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.Logging; +using Datadog.Trace.Sampling; +using Datadog.Trace.Vendors.StatsdClient; +using Newtonsoft.Json; + +namespace Datadog.Trace +{ + /// + /// The tracer is responsible for creating spans and flushing them to the Datadog agent + /// + public class Tracer : IDatadogTracer + { + private const string UnknownServiceName = "UnknownService"; + private static readonly Vendors.Serilog.ILogger Log = DatadogLogging.For(); + + /// + /// The number of Tracer instances that have been created and not yet destroyed. + /// This is used in the heartbeat metrics to estimate the number of + /// "live" Tracers that could potentially be sending traces to the Agent. + /// + private static int _liveTracerCount; + + /// + /// Indicates whether we're initializing a tracer for the first time + /// + private static int _firstInitialization = 1; + + private readonly IScopeManager _scopeManager; + private readonly Timer _heartbeatTimer; + + private IAgentWriter _agentWriter; + + static Tracer() + { + TracingProcessManager.Initialize(); + // create the default global Tracer + Instance = new Tracer(); + } + + /// + /// Initializes a new instance of the class with default settings. + /// + public Tracer() + : this(settings: null, agentWriter: null, sampler: null, scopeManager: null, statsd: null) + { + } + + /// + /// Initializes a new instance of the + /// class using the specified . + /// + /// + /// A instance with the desired settings, + /// or null to use the default configuration sources. + /// + public Tracer(TracerSettings settings) + : this(settings, agentWriter: null, sampler: null, scopeManager: null, statsd: null) + { + } + + internal Tracer(TracerSettings settings, IAgentWriter agentWriter, ISampler sampler, IScopeManager scopeManager, IStatsd statsd) + { + // update the count of Tracer instances + Interlocked.Increment(ref _liveTracerCount); + + Settings = settings ?? TracerSettings.FromDefaultSources(); + + // if not configured, try to determine an appropriate service name + DefaultServiceName = Settings.ServiceName ?? + GetApplicationName() ?? + UnknownServiceName; + + // only set DogStatsdClient if tracer metrics are enabled + if (Settings.TracerMetricsEnabled) + { + // Run this first in case the port override is ready + TracingProcessManager.SubscribeToDogStatsDPortOverride( + port => + { + Log.Debug("Attempting to override dogstatsd port with {0}", port); + Statsd = CreateDogStatsdClient(Settings, DefaultServiceName, port); + }); + + Statsd = statsd ?? CreateDogStatsdClient(Settings, DefaultServiceName, Settings.DogStatsdPort); + } + + // Run this first in case the port override is ready + TracingProcessManager.SubscribeToTraceAgentPortOverride( + port => + { + Log.Debug("Attempting to override trace agent port with {0}", port); + var builder = new UriBuilder(Settings.AgentUri) { Port = port }; + var baseEndpoint = builder.Uri; + IApi overridingApiClient = new Api(baseEndpoint, apiRequestFactory: null, Statsd); + if (_agentWriter == null) + { + _agentWriter = _agentWriter ?? new AgentWriter(overridingApiClient, Statsd); + } + else + { + _agentWriter.OverrideApi(overridingApiClient); + } + }); + + // fall back to default implementations of each dependency if not provided + _agentWriter = agentWriter ?? new AgentWriter(new Api(Settings.AgentUri, apiRequestFactory: null, Statsd), Statsd); + + _scopeManager = scopeManager ?? new AsyncLocalScopeManager(); + Sampler = sampler ?? new RuleBasedSampler(new RateLimiter(Settings.MaxTracesSubmittedPerSecond)); + + if (!string.IsNullOrWhiteSpace(Settings.CustomSamplingRules)) + { + // User has opted in, ensure rate limiter is used + RuleBasedSampler.OptInTracingWithoutLimits(); + + foreach (var rule in CustomSamplingRule.BuildFromConfigurationString(Settings.CustomSamplingRules)) + { + Sampler.RegisterRule(rule); + } + } + + if (Settings.GlobalSamplingRate != null) + { + var globalRate = (float)Settings.GlobalSamplingRate; + + if (globalRate < 0f || globalRate > 1f) + { + Log.Warning("{0} configuration of {1} is out of range", ConfigurationKeys.GlobalSamplingRate, Settings.GlobalSamplingRate); + } + else + { + Sampler.RegisterRule(new GlobalSamplingRule(globalRate)); + } + } + + // Register callbacks to make sure we flush the traces before exiting + AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; + AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload; + AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; + Console.CancelKeyPress += Console_CancelKeyPress; + + // start the heartbeat loop + _heartbeatTimer = new Timer(HeartbeatCallback, state: null, dueTime: TimeSpan.Zero, period: TimeSpan.FromMinutes(1)); + + // If configured, add/remove the correlation identifiers into the + // LibLog logging context when a scope is activated/closed + if (Settings.LogsInjectionEnabled) + { + InitializeLibLogScopeEventSubscriber(_scopeManager, DefaultServiceName, Settings.ServiceVersion, Settings.Environment); + } + + if (Interlocked.Exchange(ref _firstInitialization, 0) == 1 && Settings.StartupDiagnosticLogEnabled) + { + _ = WriteDiagnosticLog(); + } + } + + /// + /// Finalizes an instance of the class. + /// + ~Tracer() + { + // update the count of Tracer instances + Interlocked.Decrement(ref _liveTracerCount); + } + + /// + /// Gets or sets the global tracer object + /// + public static Tracer Instance { get; set; } + + /// + /// Gets the active scope + /// + public Scope ActiveScope => _scopeManager.Active; + + /// + /// Gets the default service name for traces where a service name is not specified. + /// + public string DefaultServiceName { get; } + + /// + /// Gets this tracer's settings. + /// + public TracerSettings Settings { get; } + + /// + /// Gets the tracer's scope manager, which determines which span is currently active, if any. + /// + IScopeManager IDatadogTracer.ScopeManager => _scopeManager; + + /// + /// Gets the instance used by this instance. + /// + ISampler IDatadogTracer.Sampler => Sampler; + + internal IDiagnosticManager DiagnosticManager { get; set; } + + internal ISampler Sampler { get; } + + internal IStatsd Statsd { get; private set; } + + /// + /// Create a new Tracer with the given parameters + /// + /// The agent endpoint where the traces will be sent (default is http://localhost:8126). + /// Default name of the service (default is the name of the executing assembly). + /// Turns on all debug logging (this may have an impact on application performance). + /// The newly created tracer + public static Tracer Create(Uri agentEndpoint = null, string defaultServiceName = null, bool isDebugEnabled = false) + { + // Keep supporting this older public method by creating a TracerConfiguration + // from default sources, overwriting the specified settings, and passing that to the constructor. + var configuration = TracerSettings.FromDefaultSources(); + GlobalSettings.SetDebugEnabled(isDebugEnabled); + + if (agentEndpoint != null) + { + configuration.AgentUri = agentEndpoint; + } + + if (defaultServiceName != null) + { + configuration.ServiceName = defaultServiceName; + } + + return new Tracer(configuration); + } + + /// + /// Make a span the active span and return its new scope. + /// + /// The span to activate. + /// A Scope object wrapping this span. + Scope IDatadogTracer.ActivateSpan(Span span) + { + return ActivateSpan(span); + } + + /// + /// Make a span the active span and return its new scope. + /// + /// The span to activate. + /// Determines whether closing the returned scope will also finish the span. + /// A Scope object wrapping this span. + public Scope ActivateSpan(Span span, bool finishOnClose = true) + { + return _scopeManager.Activate(span, finishOnClose); + } + + /// + /// This is a shortcut for + /// and , it creates a new span with the given parameters and makes it active. + /// + /// The span's operation name + /// The span's parent + /// The span's service name + /// An explicit start time for that span + /// If set the span will not be a child of the currently active span + /// If set to false, closing the returned scope will not close the enclosed span + /// A scope wrapping the newly created span + public Scope StartActive(string operationName, ISpanContext parent = null, string serviceName = null, DateTimeOffset? startTime = null, bool ignoreActiveScope = false, bool finishOnClose = true) + { + var span = StartSpan(operationName, parent, serviceName, startTime, ignoreActiveScope); + return _scopeManager.Activate(span, finishOnClose); + } + + /// + /// Creates a new with the specified parameters. + /// + /// The span's operation name + /// The newly created span + Span IDatadogTracer.StartSpan(string operationName) + { + return StartSpan(operationName); + } + + /// + /// Creates a new with the specified parameters. + /// + /// The span's operation name + /// The span's parent + /// The newly created span + Span IDatadogTracer.StartSpan(string operationName, ISpanContext parent) + { + return StartSpan(operationName, parent); + } + + /// + /// Creates a new with the specified parameters. + /// + /// The span's operation name + /// The span's parent + /// The span's service name + /// An explicit start time for that span + /// If set the span will not be a child of the currently active span + /// The newly created span + public Span StartSpan(string operationName, ISpanContext parent = null, string serviceName = null, DateTimeOffset? startTime = null, bool ignoreActiveScope = false) + { + if (parent == null && !ignoreActiveScope) + { + parent = _scopeManager.Active?.Span?.Context; + } + + ITraceContext traceContext; + + // try to get the trace context (from local spans) or + // sampling priority (from propagated spans), + // otherwise start a new trace context + if (parent is SpanContext parentSpanContext) + { + traceContext = parentSpanContext.TraceContext ?? + new TraceContext(this) + { + SamplingPriority = parentSpanContext.SamplingPriority + }; + } + else + { + traceContext = new TraceContext(this); + } + + var finalServiceName = serviceName ?? parent?.ServiceName ?? DefaultServiceName; + var spanContext = new SpanContext(parent, traceContext, finalServiceName); + + var span = new Span(spanContext, startTime) + { + OperationName = operationName, + }; + + // Apply any global tags + if (Settings.GlobalTags.Count > 0) + { + foreach (var entry in Settings.GlobalTags) + { + span.SetTag(entry.Key, entry.Value); + } + } + + // automatically add the "env" tag if defined, taking precedence over an "env" tag set from a global tag + var env = Settings.Environment; + if (!string.IsNullOrWhiteSpace(env)) + { + span.SetTag(Tags.Env, env); + } + + // automatically add the "version" tag if defined, taking precedence over an "version" tag set from a global tag + var version = Settings.ServiceVersion; + if (!string.IsNullOrWhiteSpace(version) && string.Equals(finalServiceName, DefaultServiceName)) + { + span.SetTag(Tags.Version, version); + } + + traceContext.AddSpan(span); + return span; + } + + /// + /// Writes the specified collection to the agent writer. + /// + /// The collection to write. + void IDatadogTracer.Write(Span[] trace) + { + if (Settings.TraceEnabled) + { + _agentWriter.WriteTrace(trace); + } + } + + internal Task FlushAsync() + { + return _agentWriter.FlushTracesAsync(); + } + + internal void StartDiagnosticObservers() + { + // instead of adding a hard dependency on DiagnosticSource, + // check if it is available before trying to use it + var type = Type.GetType("System.Diagnostics.DiagnosticSource, System.Diagnostics.DiagnosticSource", throwOnError: false); + + if (type == null) + { + Log.Warning("DiagnosticSource type could not be loaded. Disabling diagnostic observers."); + } + else + { + // don't call this method unless the necessary types are available + StartDiagnosticObserversInternal(); + } + } + + internal void StartDiagnosticObserversInternal() + { + DiagnosticManager?.Stop(); + + var observers = new List(); + +#if NETSTANDARD + if (Settings.IsIntegrationEnabled(AspNetCoreDiagnosticObserver.IntegrationName)) + { + Log.Debug("Adding AspNetCoreDiagnosticObserver"); + + var aspNetCoreDiagnosticOptions = new AspNetCoreDiagnosticOptions(); + observers.Add(new AspNetCoreDiagnosticObserver(this, aspNetCoreDiagnosticOptions)); + } +#endif + + if (observers.Count == 0) + { + Log.Debug("DiagnosticManager not started, zero observers added."); + } + else + { + Log.Debug("Starting DiagnosticManager with {0} observers.", observers.Count); + + var diagnosticManager = new DiagnosticManager(observers); + diagnosticManager.Start(); + DiagnosticManager = diagnosticManager; + } + } + + internal async Task WriteDiagnosticLog() + { + string agentError = null; + + try + { + var success = await _agentWriter.Ping().ConfigureAwait(false); + + if (!success) + { + agentError = "An error occurred while sending traces to the agent"; + } + } + catch (Exception ex) + { + agentError = ex.Message; + } + + try + { + var frameworkDescription = FrameworkDescription.Create(); + + var stringWriter = new StringWriter(); + + using (var writer = new JsonTextWriter(stringWriter)) + { + writer.WriteStartObject(); + + writer.WritePropertyName("date"); + writer.WriteValue(DateTime.Now); + + writer.WritePropertyName("os_name"); + writer.WriteValue(frameworkDescription.OSPlatform); + + writer.WritePropertyName("os_version"); + writer.WriteValue(Environment.OSVersion.ToString()); + + writer.WritePropertyName("version"); + writer.WriteValue(typeof(Tracer).Assembly.GetName().Version.ToString()); + + writer.WritePropertyName("platform"); + writer.WriteValue(frameworkDescription.ProcessArchitecture); + + writer.WritePropertyName("lang"); + writer.WriteValue(frameworkDescription.Name); + + writer.WritePropertyName("lang_version"); + writer.WriteValue(frameworkDescription.ProductVersion); + + writer.WritePropertyName("env"); + writer.WriteValue(Settings.Environment); + + writer.WritePropertyName("enabled"); + writer.WriteValue(Settings.TraceEnabled); + + writer.WritePropertyName("service"); + writer.WriteValue(DefaultServiceName); + + writer.WritePropertyName("agent_url"); + writer.WriteValue(Settings.AgentUri); + + writer.WritePropertyName("debug"); + writer.WriteValue(GlobalSettings.Source.DebugEnabled); + + writer.WritePropertyName("analytics_enabled"); + writer.WriteValue(Settings.AnalyticsEnabled); + + writer.WritePropertyName("sample_rate"); + writer.WriteValue(Settings.GlobalSamplingRate); + + writer.WritePropertyName("sampling_rules"); + writer.WriteValue(Settings.CustomSamplingRules); + + writer.WritePropertyName("tags"); + + writer.WriteStartArray(); + + foreach (var entry in Settings.GlobalTags) + { + writer.WriteValue(string.Concat(entry.Key, ":", entry.Value)); + } + + writer.WriteEndArray(); + + writer.WritePropertyName("log_injection_enabled"); + writer.WriteValue(Settings.LogsInjectionEnabled); + + writer.WritePropertyName("runtime_metrics_enabled"); + writer.WriteValue(Settings.TracerMetricsEnabled); + + writer.WritePropertyName("disabled_integrations"); + writer.WriteStartArray(); + + foreach (var integration in Settings.DisabledIntegrationNames) + { + writer.WriteValue(integration); + } + + writer.WriteEndArray(); + + writer.WritePropertyName("netstandard_enabled"); + writer.WriteValue(Settings.IsNetStandardFeatureFlagEnabled()); + + writer.WritePropertyName("agent_reachable"); + writer.WriteValue(agentError == null); + + writer.WritePropertyName("agent_error"); + writer.WriteValue(agentError ?? string.Empty); + + writer.WriteEndObject(); + } + + Log.Information("DATADOG TRACER CONFIGURATION - {0}", stringWriter.ToString()); + } + catch (Exception ex) + { + Log.Warning(ex, "DATADOG TRACER DIAGNOSTICS - Error fetching configuration"); + } + } + + /// + /// Gets an "application name" for the executing application by looking at + /// the hosted app name (.NET Framework on IIS only), assembly name, and process name. + /// + /// The default service name. + private static string GetApplicationName() + { + try + { +#if !NETSTANDARD2_0 + // System.Web.dll is only available on .NET Framework + if (System.Web.Hosting.HostingEnvironment.IsHosted) + { + // if this app is an ASP.NET application, return "SiteName/ApplicationVirtualPath". + // note that ApplicationVirtualPath includes a leading slash. + return (System.Web.Hosting.HostingEnvironment.SiteName + System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath).TrimEnd('/'); + } +#endif + + return Assembly.GetEntryAssembly()?.GetName().Name ?? + Process.GetCurrentProcess().ProcessName; + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error creating default service name."); + return null; + } + } + + private static IStatsd CreateDogStatsdClient(TracerSettings settings, string serviceName, int port) + { + try + { + var frameworkDescription = FrameworkDescription.Create(); + + var constantTags = new List + { + "lang:.NET", + $"lang_interpreter:{frameworkDescription.Name}", + $"lang_version:{frameworkDescription.ProductVersion}", + $"tracer_version:{TracerConstants.AssemblyVersion}", + $"service:{serviceName}" + }; + + if (settings.Environment != null) + { + constantTags.Add($"env:{settings.Environment}"); + } + + if (settings.ServiceVersion != null) + { + constantTags.Add($"version:{settings.ServiceVersion}"); + } + + var statsdUdp = new StatsdUDP(settings.AgentUri.DnsSafeHost, port, StatsdConfig.DefaultStatsdMaxUDPPacketSize); + return new Statsd(statsdUdp, new RandomGenerator(), new StopWatchFactory(), prefix: string.Empty, constantTags.ToArray()); + } + catch (Exception ex) + { + Log.SafeLogError(ex, $"Unable to instantiate {nameof(Statsd)} client."); + return new NoOpStatsd(); + } + } + + private void InitializeLibLogScopeEventSubscriber(IScopeManager scopeManager, string defaultServiceName, string version, string env) + { + new LibLogScopeEventSubscriber(scopeManager, defaultServiceName, version ?? string.Empty, env ?? string.Empty); + } + + private void CurrentDomain_ProcessExit(object sender, EventArgs e) + { + RunShutdownTasks(); + } + + private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) + { + RunShutdownTasks(); + } + + private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) + { + RunShutdownTasks(); + } + + private void CurrentDomain_DomainUnload(object sender, EventArgs e) + { + RunShutdownTasks(); + } + + private void RunShutdownTasks() + { + try + { + _agentWriter.FlushAndCloseAsync().Wait(); + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error flushing traces on shutdown."); + } + + try + { + TracingProcessManager.StopProcesses(); + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error stopping sub processes on shutdown."); + } + } + + private void HeartbeatCallback(object state) + { + if (Statsd != null) + { + // use the count of Tracer instances as the heartbeat value + // to estimate the number of "live" Tracers than can potentially + // send traces to the Agent + Statsd.AppendSetGauge(TracerMetricNames.Health.Heartbeat, _liveTracerCount); + Statsd.Send(); + } + } + } +} diff --git a/src/Datadog.Trace/TracerConstants.cs b/src/Datadog.Trace/TracerConstants.cs new file mode 100644 index 0000000000..401ee70c76 --- /dev/null +++ b/src/Datadog.Trace/TracerConstants.cs @@ -0,0 +1,14 @@ +namespace Datadog.Trace +{ + internal static class TracerConstants + { + public const string Language = "dotnet"; + + /// + /// 2^63-1 + /// + public const ulong MaxTraceId = 9_223_372_036_854_775_807; + + public static readonly string AssemblyVersion = typeof(Tracer).Assembly.GetName().Version.ToString(); + } +} diff --git a/src/Datadog.Trace/TracingProcessManager.cs b/src/Datadog.Trace/TracingProcessManager.cs new file mode 100644 index 0000000000..a37a0443ad --- /dev/null +++ b/src/Datadog.Trace/TracingProcessManager.cs @@ -0,0 +1,667 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.Configuration; +using Datadog.Trace.Logging; +using Datadog.Trace.Util; +using Datadog.Trace.Vendors.Serilog; +using Datadog.Trace.Vendors.StatsdClient; + +namespace Datadog.Trace +{ + /// + /// This class is used to manage agent processes in contexts where the user can not, such as Azure App Services. + /// + internal class TracingProcessManager + { + internal static readonly int KeepAliveInterval = 120_000; + internal static readonly int ExceptionRetryInterval = 1_000; + + internal static readonly ProcessMetadata TraceAgentMetadata = new ProcessMetadata + { + Name = "datadog-trace-agent", + ProcessPath = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TraceAgentPath), + ProcessArguments = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.TraceAgentArgs), + RefreshPortVars = () => + { + var portString = TraceAgentMetadata.Port?.ToString(CultureInfo.InvariantCulture); + Environment.SetEnvironmentVariable(ConfigurationKeys.AgentPort, portString); + Environment.SetEnvironmentVariable(ConfigurationKeys.TraceAgentPortKey, portString); + } + }; + + internal static readonly ProcessMetadata DogStatsDMetadata = new ProcessMetadata + { + Name = "dogstatsd", + ProcessPath = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.DogStatsDPath), + ProcessArguments = EnvironmentHelpers.GetEnvironmentVariable(ConfigurationKeys.DogStatsDArgs), + RefreshPortVars = () => + { + var portString = DogStatsDMetadata.Port?.ToString(CultureInfo.InvariantCulture); + Environment.SetEnvironmentVariable(StatsdConfig.DD_DOGSTATSD_PORT_ENV_VAR, portString); + } + }; + + private static readonly List Processes = new List() + { + TraceAgentMetadata, + DogStatsDMetadata + }; + + private static readonly ILogger Log = DatadogLogging.For(); + + private static CancellationTokenSource _cancellationTokenSource; + private static bool _isProcessManager; + + public static void TryForceTraceAgentRefresh() + { + try + { + if (string.IsNullOrEmpty(TraceAgentMetadata.DirectoryPath)) + { + Log.Debug("This is not a context where we manage agent processes."); + return; + } + + Log.Warning("Attempting to force a child process refresh."); + InitializePortManagerClaimFiles(TraceAgentMetadata.DirectoryPath); + + if (!_isProcessManager) + { + Log.Debug("This process is not responsible for managing agent processes."); + return; + } + + if (Processes.All(p => p.HasAttemptedStartup)) + { + Log.Debug("Forcing a full refresh on agent processes."); + StopProcesses(); + + _cancellationTokenSource = new CancellationTokenSource(); + + Log.Debug("Starting child processes."); + StartProcesses(); + } + else + { + Log.Debug("This process has not had a chance to initialize agent processes."); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error when forcing a trace agent process refresh."); + } + } + + public static void SubscribeToTraceAgentPortOverride(Action subscriber) + { + TraceAgentMetadata.PortSubscribers.Add(subscriber); + + if (TraceAgentMetadata.Port != null) + { + subscriber(TraceAgentMetadata.Port.Value); + } + } + + public static void SubscribeToDogStatsDPortOverride(Action subscriber) + { + DogStatsDMetadata.PortSubscribers.Add(subscriber); + + if (DogStatsDMetadata.Port != null) + { + subscriber(DogStatsDMetadata.Port.Value); + } + } + + public static void StopProcesses() + { + _cancellationTokenSource?.Cancel(); + + if (_isProcessManager) + { + foreach (var metadata in Processes) + { + try + { + SafelyKillProcess(metadata); + metadata.Dispose(); + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error when cancelling process {0}.", metadata.Name); + } + } + } + } + + public static void Initialize() + { + try + { + if (string.IsNullOrWhiteSpace(TraceAgentMetadata.ProcessPath)) + { + return; + } + + if (DomainMetadata.ShouldAvoidAppDomain()) + { + Log.Information("Skipping process manager initialization for AppDomain: {0}", DomainMetadata.AppDomainName); + return; + } + + if (!Directory.Exists(TraceAgentMetadata.DirectoryPath)) + { + Log.Warning("Directory for trace agent does not exist: {0}", TraceAgentMetadata.DirectoryPath); + return; + } + + InitializePortManagerClaimFiles(TraceAgentMetadata.DirectoryPath); + _cancellationTokenSource = new CancellationTokenSource(); + + if (_isProcessManager) + { + Log.Debug("Starting child processes from process {0}, AppDomain {1}.", DomainMetadata.ProcessName, DomainMetadata.AppDomainName); + StartProcesses(); + } + + Log.Debug("Initializing sub process port file watchers."); + foreach (var instance in Processes) + { + instance.InitializePortFileWatcher(); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error when attempting to initialize process manager."); + } + } + + private static void InitializePortManagerClaimFiles(string traceAgentDirectory) + { + var portManagerDirectory = Path.Combine(traceAgentDirectory, "port-manager"); + + if (!Directory.Exists(portManagerDirectory)) + { + Directory.CreateDirectory(portManagerDirectory); + } + + var fileClaim = + Path.Combine( + portManagerDirectory, + string.Format(CultureInfo.InvariantCulture, "{0}_{1}", DomainMetadata.ProcessId, DomainMetadata.AppDomainId)); + + var portManagerFiles = Directory.GetFiles(portManagerDirectory); + if (portManagerFiles.Length > 0) + { + int? GetProcessIdFromFileName(string fullPath) + { + var fileName = Path.GetFileNameWithoutExtension(fullPath); + if (int.TryParse(fileName?.Split('_')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out var pid)) + { + return pid; + } + + return null; + } + + foreach (var portManagerFileName in portManagerFiles) + { + try + { + var claimPid = GetProcessIdFromFileName(portManagerFileName); + var isActive = false; + + try + { + if (claimPid != null) + { + using (Process.GetProcessById(claimPid.Value)) + { + isActive = true; + } + } + } + finally + { + if (!isActive) + { + File.Delete(portManagerFileName); + } + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error when cleaning port claims."); + } + } + } + + var remainingFiles = Directory.GetFiles(portManagerDirectory); + if (remainingFiles.Length == 0) + { + File.WriteAllText(fileClaim, DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)); + _isProcessManager = true; + } + } + + private static void StartProcesses() + { + foreach (var metadata in Processes) + { + if (!string.IsNullOrWhiteSpace(metadata.ProcessPath)) + { + if (!metadata.IsBeingManaged) + { + metadata.KeepAliveTask = StartProcessWithKeepAlive(metadata); + } + } + else + { + Log.Debug("There is no path configured for {0}.", metadata.Name); + } + } + } + + private static void SafelyKillProcess(ProcessMetadata metadata) + { + try + { + if (_isProcessManager) + { + metadata.SafelyForceKill(); + } + } + catch (Exception ex) + { + Log.Error(ex, "Failed to verify halt of the {0} process.", metadata.Name); + } + } + + private static Task StartProcessWithKeepAlive(ProcessMetadata metadata) + { + const int circuitBreakerMax = 3; + var path = metadata.ProcessPath; + Log.Debug("Starting keep alive for {0}.", path); + + return Task.Run( + async () => + { + try + { + metadata.IsBeingManaged = true; + var sequentialFailures = 0; + + while (true) + { + if (_cancellationTokenSource.Token.IsCancellationRequested) + { + Log.Debug("Shutdown triggered for keep alive {0}.", path); + return; + } + + try + { + metadata.IsFaulted = false; + + if (metadata.ProgramIsRunning()) + { + Log.Debug("{0} is already running.", path); + continue; + } + + var startInfo = new ProcessStartInfo { FileName = path }; + + if (!string.IsNullOrWhiteSpace(metadata.ProcessArguments)) + { + startInfo.Arguments = metadata.ProcessArguments; + } + + Log.Debug("Starting {0}.", path); + GrabFreePortForInstance(metadata); + metadata.Process = Process.Start(startInfo); + + await Task.Delay(150, _cancellationTokenSource.Token); + + if (metadata.Process == null || metadata.Process.HasExited) + { + Log.Error("{0} has failed to start.", path); + sequentialFailures++; + } + else + { + Log.Debug("Successfully started {0}.", path); + sequentialFailures = 0; + metadata.AlertSubscribers(); + Log.Debug("Finished calling port subscribers for {0}.", metadata.Name); + } + } + catch (Exception ex) + { + metadata.IsFaulted = true; + Log.Error(ex, "Exception when trying to start an instance of {0}.", path); + sequentialFailures++; + } + finally + { + metadata.HasAttemptedStartup = true; + // Delay for a reasonable amount of time before we check to see if the process is alive again. + if (metadata.IsFaulted) + { + // Quicker retry in these cases + await Task.Delay(ExceptionRetryInterval, _cancellationTokenSource.Token); + } + else + { + await Task.Delay(KeepAliveInterval, _cancellationTokenSource.Token); + } + } + + if (sequentialFailures >= circuitBreakerMax) + { + Log.Error("Circuit breaker triggered for {0}. Max failed retries reached ({1}).", path, sequentialFailures); + break; + } + } + } + finally + { + Log.Debug("Keep alive is dropping for {0}.", path); + metadata.IsBeingManaged = false; + } + }, + _cancellationTokenSource.Token); + } + + private static string ReadSingleLineNoLock(string file) + { + using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + using (var sr = new StreamReader(fs)) + { + return sr.ReadLine(); + } + } + } + + private static int? GetFreeTcpPort() + { + TcpListener tcpListener = null; + try + { + tcpListener = new TcpListener(IPAddress.Loopback, 0); + tcpListener.Start(); + var port = ((IPEndPoint)tcpListener.LocalEndpoint).Port; + return port; + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error trying to get a free port."); + return null; + } + finally + { + tcpListener?.Stop(); + } + } + + private static void GrabFreePortForInstance(ProcessMetadata instance) + { + instance.Port = GetFreeTcpPort(); + if (instance.Port == null) + { + throw new Exception($"Unable to secure a port for {instance.Name}"); + } + + instance.RefreshPortVars(); + Log.Debug("Attempting to use port {0} for the {1}.", instance.Port, instance.Name); + + if (instance.PortFilePath != null) + { + File.WriteAllText(instance.PortFilePath, instance.Port.Value.ToString(CultureInfo.InvariantCulture)); + } + } + + internal class ProcessMetadata : IDisposable + { + private string _processPath; + private FileSystemWatcher _portFileWatcher; + + public string Name { get; set; } + + public Process Process { get; set; } + + public Task KeepAliveTask { get; set; } + + /// + /// Gets or sets a value indicating whether this is being managed by active keep alive tasks. + /// + public bool IsBeingManaged { get; set; } + + /// + /// Gets or sets a value indicating whether the last attempt at running this process faulted. + /// + public bool IsFaulted { get; set; } + + /// + /// Gets or sets a value indicating whether the process has ever been tried. + /// + public bool HasAttemptedStartup { get; set; } + + public string PortFilePath { get; private set; } + + public string ProcessPath + { + get => _processPath; + set + { + _processPath = value; + DirectoryPath = Path.GetDirectoryName(_processPath); + PortFilePath = !string.IsNullOrWhiteSpace(_processPath) ? $"{_processPath}.port" : null; + } + } + + public string DirectoryPath { get; private set; } + + public string ProcessArguments { get; set; } + + public Action RefreshPortVars { get; set; } + + public int? Port { get; set; } + + public ConcurrentBag> PortSubscribers { get; } = new ConcurrentBag>(); + + public void AlertSubscribers() + { + if (Port != null) + { + foreach (var portSubscriber in PortSubscribers) + { + portSubscriber(Port.Value); + } + } + } + + public void Dispose() + { + try + { + _portFileWatcher?.Dispose(); + Process?.Dispose(); + KeepAliveTask?.Dispose(); + + if (_isProcessManager) + { + // Do our best to give new instances a fresh slate + File.Delete(PortFilePath); + } + } + catch (Exception ex) + { + Log.SafeLogError(ex, "Error when disposing of process manager resources."); + } + } + + public void InitializePortFileWatcher() + { + if (File.Exists(PortFilePath)) + { + Log.Debug("Port file already exists."); + ReadPortAndAlertSubscribers(); + } + + _portFileWatcher = new FileSystemWatcher + { + NotifyFilter = NotifyFilters.LastAccess + | NotifyFilters.LastWrite + | NotifyFilters.FileName + | NotifyFilters.CreationTime + | NotifyFilters.Size, + Path = Path.GetDirectoryName(PortFilePath), + Filter = Path.GetFileName(PortFilePath) + }; + + _portFileWatcher.Created += OnPortFileChanged; + _portFileWatcher.Changed += OnPortFileChanged; + _portFileWatcher.Deleted += OnPortFileDeleted; + _portFileWatcher.EnableRaisingEvents = true; + } + + public void ForcePortFileRead() + { + if (KeepAliveTask == null) + { + // There is nothing to accomplish, ports are not dynamic + return; + } + + ReadPortAndAlertSubscribers(); + } + + public void SafelyForceKill() + { + try + { + var fileName = Path.GetFileNameWithoutExtension(ProcessPath); + var processesByName = Process.GetProcessesByName(fileName); + foreach (var process in processesByName) + { + try + { + process.Kill(); + } + finally + { + process.Dispose(); + } + } + } + catch (Exception ex) + { + try + { + Log.Error(ex, "Error when force killing process {0}.", ProcessPath); + } + catch + { + // ignore, to be safe + } + } + } + + public bool ProgramIsRunning() + { + try + { + if (string.IsNullOrWhiteSpace(ProcessPath)) + { + return false; + } + + // fileName will match either TraceAgentMetadata.Name or DogStatsDMetadata.Name + var fileName = Path.GetFileNameWithoutExtension(ProcessPath); + var processesByName = Process.GetProcessesByName(fileName); + + if (processesByName?.Length > 0) + { + // We enforce a unique enough naming within contexts where we would use child processes + return true; + } + + Log.Debug("Program [{0}] is no longer running", ProcessPath); + + return false; + } + catch (Exception ex) + { + try + { + Log.Error(ex, "Error when checking for running program {0}.", ProcessPath); + } + catch + { + // ignore, to be safe + } + + return false; + } + } + + private void OnPortFileChanged(object source, FileSystemEventArgs e) + { + Log.Debug("Port file has changed."); + ReadPortAndAlertSubscribers(); + } + + private void OnPortFileDeleted(object source, FileSystemEventArgs e) + { + // For if some process or user decides to delete the port file, we have some evidence of what happened + Log.Error("The port file ({0}) has been deleted.", e.FullPath); + } + + private void ReadPortAndAlertSubscribers() + { + var retries = 3; + + while (retries-- > 0) + { + try + { + var portFile = PortFilePath; + var portText = ReadSingleLineNoLock(portFile); + if (int.TryParse(portText, NumberStyles.Any, CultureInfo.InvariantCulture, out var portValue)) + { + if (Port == portValue) + { + // nothing to do, let's not cause churn + return; + } + + Port = portValue; + Log.Debug("Retrieved port {0} from {1}.", portValue, PortFilePath); + RefreshPortVars(); + } + else + { + Log.Error("The port file ({0}) is malformed: {1}", PortFilePath, portText); + } + + AlertSubscribers(); + } + catch (Exception ex) + { + Log.Error(ex, "Error when alerting subscribers for {0}", Name); + Thread.Sleep(5); // Wait just a tiny bit just to let the file come unlocked + } + } + } + } + } +} diff --git a/src/Datadog.Trace/Util/DbCommandCache.cs b/src/Datadog.Trace/Util/DbCommandCache.cs new file mode 100644 index 0000000000..4d8569ad49 --- /dev/null +++ b/src/Datadog.Trace/Util/DbCommandCache.cs @@ -0,0 +1,104 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Threading; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog; + +namespace Datadog.Trace.Util +{ + internal static class DbCommandCache + { + internal const int MaxConnectionStrings = 100; + + private static readonly ILogger Log = DatadogLogging.GetLogger(typeof(DbCommandCache)); + + private static ConcurrentDictionary[]> _cache + = new ConcurrentDictionary[]>(); + + /// + /// Gets or sets the underlying cache, to be used for unit tests + /// + internal static ConcurrentDictionary[]> Cache + { + get + { + return _cache; + } + + set + { + _cache = value; + } + } + + public static KeyValuePair[] GetTagsFromDbCommand(IDbCommand command) + { + var connectionString = command.Connection.ConnectionString; + var cache = _cache; + + if (cache != null) + { + if (cache.TryGetValue(connectionString, out var tags)) + { + // Fast path: it's expected that most calls will end up in this branch + return tags; + } + + if (cache.Count <= MaxConnectionStrings) + { + // Populating the cache. This path should be hit only during application warmup + // ReSharper disable once ConvertClosureToMethodGroup -- Lambdas are cached by the compiler + return cache.GetOrAdd(connectionString, cs => ExtractTagsFromConnectionString(cs)); + } + + // The assumption "connection strings are a finite set" was wrong, disabling the cache + // Use atomic operation to log only once + if (Interlocked.Exchange(ref _cache, null) != null) + { + Log.Information($"More than {MaxConnectionStrings} different connection strings were used, disabling cache"); + } + } + + // Fallback: too many different connection string, there might be a random part in them + // Stop using the cache to prevent memory leaks + return ExtractTagsFromConnectionString(connectionString); + } + + private static KeyValuePair[] ExtractTagsFromConnectionString(string connectionString) + { + // Parse the connection string + var builder = new DbConnectionStringBuilder { ConnectionString = connectionString }; + + return new[] + { + new KeyValuePair( + Tags.DbName, + GetConnectionStringValue(builder, "Database", "Initial Catalog", "InitialCatalog")), + + new KeyValuePair( + Tags.DbUser, + GetConnectionStringValue(builder, "User ID", "UserID")), + + new KeyValuePair( + Tags.OutHost, + GetConnectionStringValue(builder, "Server", "Data Source", "DataSource", "Network Address", "NetworkAddress", "Address", "Addr", "Host")) + }; + } + + private static string GetConnectionStringValue(DbConnectionStringBuilder builder, params string[] names) + { + foreach (string name in names) + { + if (builder.TryGetValue(name, out object valueObj) && + valueObj is string value) + { + return value; + } + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/Util/DomainMetadata.cs b/src/Datadog.Trace/Util/DomainMetadata.cs new file mode 100644 index 0000000000..8cd4c4bde8 --- /dev/null +++ b/src/Datadog.Trace/Util/DomainMetadata.cs @@ -0,0 +1,127 @@ +using System; +using System.Diagnostics; + +namespace Datadog.Trace.Util +{ + /// + /// Dedicated helper class for consistently referencing Process and AppDomain information. + /// + internal static class DomainMetadata + { + private const string UnknownName = "unknown"; + private static Process _currentProcess; + private static bool _processDataPoisoned; + private static bool _domainDataPoisoned; + private static bool? _isAppInsightsAppDomain; + + static DomainMetadata() + { + TrySetProcess(); + } + + public static string ProcessName + { + get + { + try + { + return !_processDataPoisoned ? _currentProcess.ProcessName : UnknownName; + } + catch + { + _processDataPoisoned = true; + return UnknownName; + } + } + } + + public static string MachineName + { + get + { + try + { + return !_processDataPoisoned ? _currentProcess.MachineName : UnknownName; + } + catch + { + _processDataPoisoned = true; + return UnknownName; + } + } + } + + public static int ProcessId + { + get + { + try + { + return !_processDataPoisoned ? _currentProcess.Id : -1; + } + catch + { + _processDataPoisoned = true; + return -1; + } + } + } + + public static string AppDomainName + { + get + { + try + { + return !_domainDataPoisoned ? AppDomain.CurrentDomain.FriendlyName : UnknownName; + } + catch + { + _domainDataPoisoned = true; + return UnknownName; + } + } + } + + public static int AppDomainId + { + get + { + try + { + return !_domainDataPoisoned ? AppDomain.CurrentDomain.Id : -1; + } + catch + { + _domainDataPoisoned = true; + return -1; + } + } + } + + public static bool ShouldAvoidAppDomain() + { + if (_isAppInsightsAppDomain == null) + { + _isAppInsightsAppDomain = AppDomainName.IndexOf("ApplicationInsights", StringComparison.OrdinalIgnoreCase) >= 0; + } + + return _isAppInsightsAppDomain.Value; + } + + private static void TrySetProcess() + { + try + { + if (!_processDataPoisoned && _currentProcess == null) + { + _currentProcess = Process.GetCurrentProcess(); + } + } + catch + { + _processDataPoisoned = true; + } + } + } +} diff --git a/src/Datadog.Trace/Util/EnvironmentHelpers.cs b/src/Datadog.Trace/Util/EnvironmentHelpers.cs new file mode 100644 index 0000000000..21826e2ef7 --- /dev/null +++ b/src/Datadog.Trace/Util/EnvironmentHelpers.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections; +using Datadog.Trace.Logging; +using Datadog.Trace.Vendors.Serilog; + +namespace Datadog.Trace.Util +{ + /// + /// Helpers to access environment variables + /// + internal static class EnvironmentHelpers + { + private static readonly ILogger Logger = DatadogLogging.GetLogger(typeof(EnvironmentHelpers)); + + /// + /// Safe wrapper around Environment.GetEnvironmentVariable + /// + /// Name of the environment variable to fetch + /// Value to return in case of error + /// The value of the environment variable, or the default value if an error occured + public static string GetEnvironmentVariable(string key, string defaultValue = null) + { + try + { + return Environment.GetEnvironmentVariable(key); + } + catch (Exception ex) + { + Logger.Warning(ex, "Error while reading environment variable {0}", key); + } + + return defaultValue; + } + + /// + /// Safe wrapper around Environment.GetEnvironmentVariables + /// + /// A dictionary that contains all environment variables, or en empty dictionary if an error occured + public static IDictionary GetEnvironmentVariables() + { + try + { + return Environment.GetEnvironmentVariables(); + } + catch (Exception ex) + { + Logger.Warning(ex, "Error while reading environment variables"); + } + + return null; + } + } +} diff --git a/src/Datadog.Trace/Util/PropertyFetcher.cs b/src/Datadog.Trace/Util/PropertyFetcher.cs new file mode 100644 index 0000000000..0b8329c615 --- /dev/null +++ b/src/Datadog.Trace/Util/PropertyFetcher.cs @@ -0,0 +1,112 @@ +// From https://github.com/dotnet/runtime/blob/master/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs + +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.Util +{ + internal class PropertyFetcher + { + private readonly string _propertyName; + private Type _expectedType; + private object _fetchForExpectedType; + + /// + /// Initializes a new instance of the class. + /// + /// The name of the property that this instance will fetch. + public PropertyFetcher(string propertyName) + { + _propertyName = propertyName; + } + + /// + /// Gets the value of the property on the specified object. + /// + /// Type of the result. + /// The object that contains the property. + /// The value of the property on the specified object. + public T Fetch(object obj) + { + return Fetch(obj, obj.GetType()); + } + + /// + /// Gets the value of the property on the specified object. + /// + /// Type of the result. + /// The object that contains the property. + /// Type of the object + /// The value of the property on the specified object. + public T Fetch(object obj, Type objType) + { + if (objType != _expectedType) + { + var propertyInfo = objType.GetProperty(_propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase); + _fetchForExpectedType = PropertyFetch.FetcherForProperty(propertyInfo); + _expectedType = objType; + } + + return ((PropertyFetch)_fetchForExpectedType).Fetch(obj); + } + + /// + /// PropertyFetch is a helper class. It takes a PropertyInfo and then knows how + /// to efficiently fetch that property from a .NET object (See Fetch method). + /// It hides some slightly complex generic code. + /// + /// Return type of the property. + private class PropertyFetch + { + private readonly Func _propertyFetch; + + private PropertyFetch() + { + _propertyFetch = _ => default; + } + + private PropertyFetch(PropertyInfo propertyInfo) + { + // Generate lambda: arg => (T)((TObject)arg).get_property(); + var param = Expression.Parameter(typeof(object), "arg"); // arg => + var cast = Expression.Convert(param, propertyInfo.DeclaringType); // (TObject)arg + var propertyFetch = Expression.Property(cast, propertyInfo); // get_property() + var castResult = Expression.Convert(propertyFetch, typeof(T)); // (T)result + + // Generate the actual lambda + var lambda = Expression.Lambda(typeof(Func), castResult, param); + + // Compile it for faster access + _propertyFetch = (Func)lambda.Compile(); + } + + /// + /// Create a property fetcher from a .NET Reflection class that + /// represents a property of a particular type. + /// + /// The property that this instance will fetch. + /// The new property fetcher. + public static PropertyFetch FetcherForProperty(PropertyInfo propertyInfo) + { + if (propertyInfo == null) + { + // returns null on any fetch. + return new PropertyFetch(); + } + + return new PropertyFetch(propertyInfo); + } + + /// + /// Gets the value of the property on the specified object. + /// + /// The object that contains the property. + /// The value of the property on the specified object. + public T Fetch(object obj) + { + return _propertyFetch(obj); + } + } + } +} diff --git a/src/Datadog.Trace/Util/SpanIdGenerator.cs b/src/Datadog.Trace/Util/SpanIdGenerator.cs new file mode 100644 index 0000000000..423f6e501f --- /dev/null +++ b/src/Datadog.Trace/Util/SpanIdGenerator.cs @@ -0,0 +1,58 @@ +using System; + +namespace Datadog.Trace.Util +{ + internal class SpanIdGenerator + { +#if !NETSTANDARD + private static readonly Random GlobalSeedGenerator = new Random(); +#endif + + [ThreadStatic] + private static Random _threadRandom; + + public static ulong CreateNew() + { + Random random = GetRandom(); + + long high = random.Next(int.MinValue, int.MaxValue); + long low = random.Next(int.MinValue, int.MaxValue); + + // Concatenate both values, and truncate the 32 top bits from low + var value = high << 32 | (low & 0xFFFFFFFF); + + return (ulong)value & 0x7FFFFFFFFFFFFFFF; + } + + private static Random GetRandom() + { + Random random = _threadRandom; + + if (random == null) + { +#if NETSTANDARD + random = new Random(); +#else + // On .NET Framework, the clock is used to seed the new random instances. + // Resolution is too low, so if many threads are created at the same time, + // some could end up using the same seed. + // Instead, use a shared random instance to generate the seed. + // The same approach was used for System.Random on .NET Core: + // https://docs.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netcore-3.1 + int seed; + + lock (GlobalSeedGenerator) + { + seed = GlobalSeedGenerator.Next(); + } + + random = new Random(seed); +#endif + + _threadRandom = random; + } + + return random; + } + } +} diff --git a/src/Datadog.Trace/Util/StopwatchHelpers.cs b/src/Datadog.Trace/Util/StopwatchHelpers.cs new file mode 100644 index 0000000000..5a424ea01c --- /dev/null +++ b/src/Datadog.Trace/Util/StopwatchHelpers.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Datadog.Trace.Util +{ + internal class StopwatchHelpers + { + private static readonly double DateTimeTickFrequency = 10000000.0 / Stopwatch.Frequency; + + public static TimeSpan GetElapsed(long stopwatchTicks) + { + var ticks = (long)(stopwatchTicks * DateTimeTickFrequency); + + return new TimeSpan(ticks); + } + } +} diff --git a/src/Datadog.Trace/Util/UriHelpers.cs b/src/Datadog.Trace/Util/UriHelpers.cs new file mode 100644 index 0000000000..97e1bdf5cb --- /dev/null +++ b/src/Datadog.Trace/Util/UriHelpers.cs @@ -0,0 +1,84 @@ +using System; +using System.Text; + +namespace Datadog.Trace.Util +{ + internal static class UriHelpers + { + public const string UrlIdPlaceholder = "?"; + + public static string CleanUri(Uri uri, bool removeScheme, bool tryRemoveIds) + { + var path = GetRelativeUrl(uri, tryRemoveIds); + + if (removeScheme) + { + // keep only host and path. + // remove scheme, userinfo, query, and fragment. + return $"{uri.Authority}{path}"; + } + + // keep only scheme, authority, and path. + // remove userinfo, query, and fragment. + return $"{uri.Scheme}{Uri.SchemeDelimiter}{uri.Authority}{path}"; + } + + public static string GetRelativeUrl(Uri uri, bool tryRemoveIds) + { + // try to remove segments that look like ids + string path = tryRemoveIds + ? CleanUriSegment(uri.AbsolutePath) + : uri.AbsolutePath; + return path; + } + + public static string CleanUriSegment(string absolutePath) + { + if (string.IsNullOrWhiteSpace(absolutePath)) + { + return absolutePath; + } + + // Sanitized url will be at worse as long as the original + var sb = new StringBuilder(absolutePath.Length); + + int previousIndex = 0; + int index = 0; + + while (index != -1) + { + index = absolutePath.IndexOf('/', previousIndex); + + string segment; + + if (index == -1) + { + // Last segment + segment = absolutePath.Substring(previousIndex); + } + else + { + segment = absolutePath.Substring(previousIndex, index - previousIndex); + } + + // replace path segments that look like numbers or guid + segment = long.TryParse(segment, out _) || + Guid.TryParseExact(segment, "N", out _) || + Guid.TryParseExact(segment, "D", out _) + ? UrlIdPlaceholder + : segment; + + sb.Append(segment); + + if (index != -1) + { + sb.Append("/"); + } + + previousIndex = index + 1; + } + + return sb.ToString(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Attributes.cs b/src/Datadog.Trace/Vendors/MessagePack/Attributes.cs new file mode 100644 index 0000000000..3c9932611d --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Attributes.cs @@ -0,0 +1,79 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)] + internal class MessagePackObjectAttribute : Attribute + { + public bool KeyAsPropertyName { get; private set; } + + public MessagePackObjectAttribute(bool keyAsPropertyName = false) + { + this.KeyAsPropertyName = keyAsPropertyName; + } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + internal class KeyAttribute : Attribute + { + public int? IntKey { get; private set; } + public string StringKey { get; private set; } + + public KeyAttribute(int x) + { + this.IntKey = x; + } + + public KeyAttribute(string x) + { + this.StringKey = x; + } + } + + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] + internal class IgnoreMemberAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = true, Inherited = false)] + internal class UnionAttribute : Attribute + { + public int Key { get; private set; } + public Type SubType { get; private set; } + + public UnionAttribute(int key, Type subType) + { + this.Key = key; + this.SubType = subType; + } + } + + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = true)] + internal class SerializationConstructorAttribute : Attribute + { + + } + + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] + internal class MessagePackFormatterAttribute : Attribute + { + public Type FormatterType { get; private set; } + public object[] Arguments { get; private set; } + + public MessagePackFormatterAttribute(Type formatterType) + { + this.FormatterType = formatterType; + } + + public MessagePackFormatterAttribute(Type formatterType, params object[] arguments) + { + this.FormatterType = formatterType; + this.Arguments = arguments; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/BitOperations.cs b/src/Datadog.Trace/Vendors/MessagePack/BitOperations.cs new file mode 100644 index 0000000000..89d6e70245 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/BitOperations.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +#if !NETCOREAPP + +using System.Runtime.CompilerServices; + +// Some routines inspired by the Stanford Bit Twiddling Hacks by Sean Eron Anderson: +// http://graphics.stanford.edu/~seander/bithacks.html + +namespace System.Numerics +{ + /// + /// Utility methods for intrinsic bit-twiddling operations. + /// The methods use hardware intrinsics when available on the underlying platform, + /// otherwise they use optimized software fallbacks. + /// + internal static class BitOperations + { + /// + /// Rotates the specified value left by the specified number of bits. + /// Similar in behavior to the x86 instruction ROL. + /// + /// The value to rotate. + /// The number of bits to rotate by. + /// Any value outside the range [0..31] is treated as congruent mod 32. + /// The rotated value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint RotateLeft(uint value, int offset) + => (value << offset) | (value >> (32 - offset)); + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/MessagePack/FloatBits.cs b/src/Datadog.Trace/Vendors/MessagePack/FloatBits.cs new file mode 100644 index 0000000000..cb07b3529b --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/FloatBits.cs @@ -0,0 +1,122 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Runtime.InteropServices; + +namespace Datadog.Trace.Vendors.MessagePack +{ + // safe accessor of Single/Double's underlying byte. + // This code is borrowed from MsgPack-Cli https://github.com/msgpack/msgpack-cli + + [StructLayout(LayoutKind.Explicit)] + internal struct Float32Bits + { + [FieldOffset(0)] + public readonly float Value; + + [FieldOffset(0)] + public readonly Byte Byte0; + + [FieldOffset(1)] + public readonly Byte Byte1; + + [FieldOffset(2)] + public readonly Byte Byte2; + + [FieldOffset(3)] + public readonly Byte Byte3; + + public Float32Bits(float value) + { + this = default(Float32Bits); + this.Value = value; + } + + public Float32Bits(byte[] bigEndianBytes, int offset) + { + this = default(Float32Bits); + + if (BitConverter.IsLittleEndian) + { + this.Byte0 = bigEndianBytes[offset + 3]; + this.Byte1 = bigEndianBytes[offset + 2]; + this.Byte2 = bigEndianBytes[offset + 1]; + this.Byte3 = bigEndianBytes[offset]; + } + else + { + this.Byte0 = bigEndianBytes[offset]; + this.Byte1 = bigEndianBytes[offset + 1]; + this.Byte2 = bigEndianBytes[offset + 2]; + this.Byte3 = bigEndianBytes[offset + 3]; + } + } + } + + [StructLayout(LayoutKind.Explicit)] + internal struct Float64Bits + { + [FieldOffset(0)] + public readonly double Value; + + [FieldOffset(0)] + public readonly Byte Byte0; + + [FieldOffset(1)] + public readonly Byte Byte1; + + [FieldOffset(2)] + public readonly Byte Byte2; + + [FieldOffset(3)] + public readonly Byte Byte3; + + [FieldOffset(4)] + public readonly Byte Byte4; + + [FieldOffset(5)] + public readonly Byte Byte5; + + [FieldOffset(6)] + public readonly Byte Byte6; + + [FieldOffset(7)] + public readonly Byte Byte7; + + public Float64Bits(double value) + { + this = default(Float64Bits); + this.Value = value; + } + + public Float64Bits(byte[] bigEndianBytes, int offset) + { + this = default(Float64Bits); + + if (BitConverter.IsLittleEndian) + { + this.Byte0 = bigEndianBytes[offset + 7]; + this.Byte1 = bigEndianBytes[offset + 6]; + this.Byte2 = bigEndianBytes[offset + 5]; + this.Byte3 = bigEndianBytes[offset + 4]; + this.Byte4 = bigEndianBytes[offset + 3]; + this.Byte5 = bigEndianBytes[offset + 2]; + this.Byte6 = bigEndianBytes[offset + 1]; + this.Byte7 = bigEndianBytes[offset]; + } + else + { + this.Byte0 = bigEndianBytes[offset]; + this.Byte1 = bigEndianBytes[offset + 1]; + this.Byte2 = bigEndianBytes[offset + 2]; + this.Byte3 = bigEndianBytes[offset + 3]; + this.Byte4 = bigEndianBytes[offset + 4]; + this.Byte5 = bigEndianBytes[offset + 5]; + this.Byte6 = bigEndianBytes[offset + 6]; + this.Byte7 = bigEndianBytes[offset + 7]; + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionFormatter.cs new file mode 100644 index 0000000000..a6fa362a49 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionFormatter.cs @@ -0,0 +1,1103 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +#if NETSTANDARD || NETFRAMEWORK +using System.Collections.Concurrent; +#endif + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class ArrayFormatter : IMessagePackFormatter + { + public int Serialize(ref byte[] bytes, int offset, T[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + + for (int i = 0; i < value.Length; i++) + { + offset += formatter.Serialize(ref bytes, offset, value[i], formatterResolver); + } + + return offset - startOffset; + } + } + + public T[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new T[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ByteArraySegmentFormatter : IMessagePackFormatter> + { + public static readonly ByteArraySegmentFormatter Instance = new ByteArraySegmentFormatter(); + + ByteArraySegmentFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, ArraySegment value, IFormatterResolver formatterResolver) + { + if (value.Array == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteBytes(ref bytes, offset, value.Array, value.Offset, value.Count); + } + } + + public ArraySegment Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(ArraySegment); + } + else + { + // use ReadBytesSegment? But currently straem api uses memory pool so can't save arraysegment... + var binary = MessagePackBinary.ReadBytes(bytes, offset, out readSize); + return new ArraySegment(binary, 0, binary.Length); + } + } + } + + internal sealed class ArraySegmentFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, ArraySegment value, IFormatterResolver formatterResolver) + { + if (value.Array == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Count); + + var array = value.Array; + for (int i = 0; i < value.Count; i++) + { + var item = array[value.Offset + i]; + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + } + + public ArraySegment Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(ArraySegment); + } + else + { + var array = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + return new ArraySegment(array, 0, array.Length); + } + } + } + + // List is popular format, should avoid abstraction. + internal sealed class ListFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, List value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var c = value.Count; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, c); + + for (int i = 0; i < c; i++) + { + offset += formatter.Serialize(ref bytes, offset, value[i], formatterResolver); + } + + return offset - startOffset; + } + } + + public List Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var list = new List(len); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < len; i++) + { + list.Add(formatter.Deserialize(bytes, offset, formatterResolver, out readSize)); + offset += readSize; + } + } + + readSize = offset - startOffset; + return list; + } + } + } + + internal abstract class CollectionFormatterBase : IMessagePackFormatter + where TCollection : IEnumerable + where TEnumerator : IEnumerator + { + public int Serialize(ref byte[] bytes, int offset, TCollection value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + // Optimize iteration(array is fastest) + var array = value as TElement[]; + if (array != null) + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, array.Length); + + foreach (var item in array) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + // knows count or not. + var seqCount = GetCount(value); + if (seqCount != null) + { + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, seqCount.Value); + + // Unity's foreach struct enumerator causes boxing so iterate manually. + var e = GetSourceEnumerator(value); + try + { + while (e.MoveNext()) + { +#if NETSTANDARD || NETFRAMEWORK + offset += formatter.Serialize(ref bytes, offset, e.Current, formatterResolver); +#else + offset += formatter.Serialize(ref bytes, (int)offset, (TElement)e.Current, (IFormatterResolver)formatterResolver); +#endif + } + } + finally + { + e.Dispose(); + } + + return offset - startOffset; + } + else + { + // write message first -> open header space -> write header + var writeStarOffset = offset; + + var count = 0; + var moveCount = 0; + + // count = 16 <= 65535, header len is "3" so choose default space. + offset += 3; + + var e = GetSourceEnumerator(value); + try + { + while (e.MoveNext()) + { + count++; +#if NETSTANDARD || NETFRAMEWORK + var writeSize = formatter.Serialize(ref bytes, offset, e.Current, formatterResolver); +#else + var writeSize = formatter.Serialize(ref bytes, (int)offset, (TElement)e.Current, (IFormatterResolver)formatterResolver); +#endif + moveCount += writeSize; + offset += writeSize; + } + } + finally + { + e.Dispose(); + } + + var headerLength = MessagePackBinary.GetArrayHeaderLength(count); + if (headerLength != 3) + { + if (headerLength == 1) offset -= 2; // 1 + else offset += 2; // 5 + + MessagePackBinary.EnsureCapacity(ref bytes, offset, headerLength); + Buffer.BlockCopy(bytes, writeStarOffset + 3, bytes, writeStarOffset + headerLength, moveCount); + } + MessagePackBinary.WriteArrayHeader(ref bytes, writeStarOffset, count); + + return offset - startOffset; + } + } + } + } + + public TCollection Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(TCollection); + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var list = Create(len); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < len; i++) + { + Add(list, i, formatter.Deserialize(bytes, offset, formatterResolver, out readSize)); + offset += readSize; + } + } + + readSize = offset - startOffset; + + return Complete(list); + } + } + + // abstraction for serialize + protected virtual int? GetCount(TCollection sequence) + { + var collection = sequence as ICollection; + if (collection != null) + { + return collection.Count; + } +#if NETSTANDARD || NETFRAMEWORK + else + { + var c2 = sequence as IReadOnlyCollection; + if (c2 != null) + { + return c2.Count; + } + } +#endif + + return null; + } + + // Some collections can use struct iterator, this is optimization path + protected abstract TEnumerator GetSourceEnumerator(TCollection source); + + // abstraction for deserialize + protected abstract TIntermediate Create(int count); + protected abstract void Add(TIntermediate collection, int index, TElement value); + protected abstract TCollection Complete(TIntermediate intermediateCollection); + } + + internal abstract class CollectionFormatterBase : CollectionFormatterBase, TCollection> + where TCollection : IEnumerable + { + protected override IEnumerator GetSourceEnumerator(TCollection source) + { + return source.GetEnumerator(); + } + } + + internal abstract class CollectionFormatterBase : CollectionFormatterBase + where TCollection : IEnumerable + { + protected sealed override TCollection Complete(TCollection intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class GenericCollectionFormatter : CollectionFormatterBase + where TCollection : ICollection, new() + { + protected override TCollection Create(int count) + { + return new TCollection(); + } + + protected override void Add(TCollection collection, int index, TElement value) + { + collection.Add(value); + } + } + + internal sealed class LinkedListFormatter : CollectionFormatterBase, LinkedList.Enumerator, LinkedList> + { + protected override void Add(LinkedList collection, int index, T value) + { + collection.AddLast(value); + } + + protected override LinkedList Complete(LinkedList intermediateCollection) + { + return intermediateCollection; + } + + protected override LinkedList Create(int count) + { + return new LinkedList(); + } + + protected override LinkedList.Enumerator GetSourceEnumerator(LinkedList source) + { + return source.GetEnumerator(); + } + } + + internal sealed class QeueueFormatter : CollectionFormatterBase, Queue.Enumerator, Queue> + { + protected override int? GetCount(Queue sequence) + { + return sequence.Count; + } + + protected override void Add(Queue collection, int index, T value) + { + collection.Enqueue(value); + } + + protected override Queue Create(int count) + { + return new Queue(count); + } + + protected override Queue.Enumerator GetSourceEnumerator(Queue source) + { + return source.GetEnumerator(); + } + + protected override Queue Complete(Queue intermediateCollection) + { + return intermediateCollection; + } + } + + // should deserialize reverse order. + internal sealed class StackFormatter : CollectionFormatterBase.Enumerator, Stack> + { + protected override int? GetCount(Stack sequence) + { + return sequence.Count; + } + + protected override void Add(T[] collection, int index, T value) + { + // add reverse + collection[collection.Length - 1 - index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override Stack.Enumerator GetSourceEnumerator(Stack source) + { + return source.GetEnumerator(); + } + + protected override Stack Complete(T[] intermediateCollection) + { + return new Stack(intermediateCollection); + } + } + + internal sealed class HashSetFormatter : CollectionFormatterBase, HashSet.Enumerator, HashSet> + { + protected override int? GetCount(HashSet sequence) + { + return sequence.Count; + } + + protected override void Add(HashSet collection, int index, T value) + { + collection.Add(value); + } + + protected override HashSet Complete(HashSet intermediateCollection) + { + return intermediateCollection; + } + + protected override HashSet Create(int count) + { + return new HashSet(MessagePackSecurity.Active.GetEqualityComparer()); + } + + protected override HashSet.Enumerator GetSourceEnumerator(HashSet source) + { + return source.GetEnumerator(); + } + } + + internal sealed class ReadOnlyCollectionFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override ReadOnlyCollection Complete(T[] intermediateCollection) + { + return new ReadOnlyCollection(intermediateCollection); + } + + protected override T[] Create(int count) + { + return new T[count]; + } + } + + internal sealed class InterfaceListFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override IList Complete(T[] intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class InterfaceCollectionFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override ICollection Complete(T[] intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class InterfaceEnumerableFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override IEnumerable Complete(T[] intermediateCollection) + { + return intermediateCollection; + } + } + + // [Key, [Array]] + internal sealed class InterfaceGroupingFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, IGrouping value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 2); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Key, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify>().Serialize(ref bytes, offset, value, formatterResolver); + return offset - startOffset; + } + } + + public IGrouping Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + if (count != 2) throw new InvalidOperationException("Invalid Grouping format."); + + using (MessagePackSecurity.DepthStep()) + { + var key = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + var value = formatterResolver.GetFormatterWithVerify>().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Grouping(key, value); + } + } + } + } + + internal sealed class InterfaceLookupFormatter : CollectionFormatterBase, Dictionary>, ILookup> + { + protected override void Add(Dictionary> collection, int index, IGrouping value) + { + collection.Add(value.Key, value); + } + + protected override ILookup Complete(Dictionary> intermediateCollection) + { + return new Lookup(intermediateCollection); + } + + protected override Dictionary> Create(int count) + { + return new Dictionary>(count); + } + } + + class Grouping : IGrouping + { + readonly TKey key; + readonly IEnumerable elements; + + public Grouping(TKey key, IEnumerable elements) + { + this.key = key; + this.elements = elements; + } + + public TKey Key + { + get + { + return key; + } + } + + public IEnumerator GetEnumerator() + { + return elements.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return elements.GetEnumerator(); + } + } + + class Lookup : ILookup + { + readonly Dictionary> groupings; + + public Lookup(Dictionary> groupings) + { + this.groupings = groupings; + } + + public IEnumerable this[TKey key] + { + get + { + return groupings[key]; + } + } + + public int Count + { + get + { + return groupings.Count; + } + } + + public bool Contains(TKey key) + { + return groupings.ContainsKey(key); + } + + public IEnumerator> GetEnumerator() + { + return groupings.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return groupings.Values.GetEnumerator(); + } + } + + // NonGenerics + + internal sealed class NonGenericListFormatter : IMessagePackFormatter + where T : class, IList, new() + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Count); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(T); + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var list = new T(); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < count; i++) + { + list.Add(formatter.Deserialize(bytes, offset, formatterResolver, out readSize)); + offset += readSize; + } + } + + readSize = offset - startOffset; + return list; + } + } + + internal sealed class NonGenericInterfaceListFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new NonGenericInterfaceListFormatter(); + + NonGenericInterfaceListFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, IList value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Count); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + + public IList Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(IList); + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var list = new object[count]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < count; i++) + { + list[i] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return list; + } + } + + internal sealed class NonGenericDictionaryFormatter : IMessagePackFormatter + where T : class, IDictionary, new() + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Count); + foreach (DictionaryEntry item in value) + { + offset += formatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += formatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + + return offset - startOffset; + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + var count = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = CollectionHelpers.CreateHashCollection(count, MessagePackSecurity.Active.GetEqualityComparer()); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < count; i++) + { + var key = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var value = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + dict.Add(key, value); + } + } + + readSize = offset - startOffset; + return dict; + } + } + + internal sealed class NonGenericInterfaceDictionaryFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new NonGenericInterfaceDictionaryFormatter(); + + NonGenericInterfaceDictionaryFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, IDictionary value, IFormatterResolver formatterResolver) + { + if (value == null) + { + MessagePackBinary.WriteNil(ref bytes, offset); + return 1; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, value.Count); + foreach (DictionaryEntry item in value) + { + offset += formatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += formatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + + return offset - startOffset; + } + + public IDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + + var formatter = formatterResolver.GetFormatterWithVerify(); + var startOffset = offset; + + var count = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = new Dictionary(count, MessagePackSecurity.Active.GetEqualityComparer()); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < count; i++) + { + var key = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var value = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + dict.Add(key, value); + } + } + + readSize = offset - startOffset; + return dict; + } + } + +#if NETSTANDARD || NETFRAMEWORK + + internal sealed class ObservableCollectionFormatter : CollectionFormatterBase> + { + protected override void Add(ObservableCollection collection, int index, T value) + { + collection.Add(value); + } + + protected override ObservableCollection Create(int count) + { + return new ObservableCollection(); + } + } + + internal sealed class ReadOnlyObservableCollectionFormatter : CollectionFormatterBase, ReadOnlyObservableCollection> + { + protected override void Add(ObservableCollection collection, int index, T value) + { + collection.Add(value); + } + + protected override ObservableCollection Create(int count) + { + return new ObservableCollection(); + } + + protected override ReadOnlyObservableCollection Complete(ObservableCollection intermediateCollection) + { + return new ReadOnlyObservableCollection(intermediateCollection); + } + } + + internal sealed class InterfaceReadOnlyListFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override IReadOnlyList Complete(T[] intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class InterfaceReadOnlyCollectionFormatter : CollectionFormatterBase> + { + protected override void Add(T[] collection, int index, T value) + { + collection[index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override IReadOnlyCollection Complete(T[] intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class InterfaceSetFormatter : CollectionFormatterBase, ISet> + { + protected override void Add(HashSet collection, int index, T value) + { + collection.Add(value); + } + + protected override ISet Complete(HashSet intermediateCollection) + { + return intermediateCollection; + } + + protected override HashSet Create(int count) + { + return new HashSet(MessagePackSecurity.Active.GetEqualityComparer()); + } + } + + internal sealed class ConcurrentBagFormatter : CollectionFormatterBase> + { + protected override int? GetCount(ConcurrentBag sequence) + { + return sequence.Count; + } + + protected override void Add(ConcurrentBag collection, int index, T value) + { + collection.Add(value); + } + + protected override ConcurrentBag Create(int count) + { + return new ConcurrentBag(); + } + } + + internal sealed class ConcurrentQueueFormatter : CollectionFormatterBase> + { + protected override int? GetCount(ConcurrentQueue sequence) + { + return sequence.Count; + } + + protected override void Add(ConcurrentQueue collection, int index, T value) + { + collection.Enqueue(value); + } + + protected override ConcurrentQueue Create(int count) + { + return new ConcurrentQueue(); + } + } + + internal sealed class ConcurrentStackFormatter : CollectionFormatterBase> + { + protected override int? GetCount(ConcurrentStack sequence) + { + return sequence.Count; + } + + protected override void Add(T[] collection, int index, T value) + { + // add reverse + collection[collection.Length - 1 - index] = value; + } + + protected override T[] Create(int count) + { + return new T[count]; + } + + protected override ConcurrentStack Complete(T[] intermediateCollection) + { + return new ConcurrentStack(intermediateCollection); + } + } + +#endif +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionHelpers`2.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionHelpers`2.cs new file mode 100644 index 0000000000..8f78c24f17 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/CollectionHelpers`2.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + /// + /// Provides general helpers for creating collections (including dictionaries). + /// + /// The concrete type of collection to create. + /// The type of equality comparer that we would hope to pass into the collection's constructor. + internal static class CollectionHelpers + where TCollection : new() + { + /// + /// The delegate that will create the collection, if the typical (int count, IEqualityComparer{T} equalityComparer) constructor was found. + /// + private static Func collectionCreator; + + /// + /// Initializes static members of the class. + /// + /// + /// Initializes a delegate that is optimized to create a collection of a given size and using the given equality comparer, if possible. + /// + static CollectionHelpers() + { + var ctor = typeof(TCollection).GetTypeInfo().GetConstructor(new Type[] { typeof(int), typeof(TEqualityComparer) }); + if (ctor != null) + { + ParameterExpression param1 = Expression.Parameter(typeof(int), "count"); + ParameterExpression param2 = Expression.Parameter(typeof(TEqualityComparer), "equalityComparer"); + NewExpression body = Expression.New(ctor, param1, param2); + collectionCreator = Expression.Lambda>(body, param1, param2).Compile(); + } + } + + /// + /// Initializes a new instance of the collection. + /// + /// The number of elements the collection should be prepared to receive. + /// The equality comparer to initialize the collection with. + /// The newly initialized collection. + /// + /// Use of the and are a best effort. + /// If we can't find a constructor on the collection in the expected shape, we'll just instantiate the collection with its default constructor. + /// + internal static TCollection CreateHashCollection(int count, TEqualityComparer equalityComparer) => collectionCreator != null ? collectionCreator.Invoke(count, equalityComparer) : new TCollection(); + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/DictionaryFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/DictionaryFormatter.cs new file mode 100644 index 0000000000..1d7452e740 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/DictionaryFormatter.cs @@ -0,0 +1,457 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +#if NETSTANDARD || NETFRAMEWORK +using System.Collections.Concurrent; +#endif + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ +#if NETSTANDARD || NETFRAMEWORK + + // unfortunately, can't use IDictionary because supports IReadOnlyDictionary. + internal abstract class DictionaryFormatterBase : IMessagePackFormatter + where TDictionary : IEnumerable> + where TEnumerator : IEnumerator> + { + public int Serialize(ref byte[] bytes, int offset, TDictionary value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var keyFormatter = formatterResolver.GetFormatterWithVerify(); + var valueFormatter = formatterResolver.GetFormatterWithVerify(); + + int count; + { + var col = value as ICollection>; + if (col != null) + { + count = col.Count; + } + else + { + var col2 = value as IReadOnlyCollection>; + if (col2 != null) + { + count = col2.Count; + } + else + { + throw new InvalidOperationException("DictionaryFormatterBase's TDictionary supports only ICollection or IReadOnlyCollection"); + } + } + } + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, count); + + var e = GetSourceEnumerator(value); + try + { + while (e.MoveNext()) + { + var item = e.Current; + offset += keyFormatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += valueFormatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + } + finally + { + e.Dispose(); + } + + return offset - startOffset; + } + } + + public TDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(TDictionary); + } + else + { + var startOffset = offset; + var keyFormatter = formatterResolver.GetFormatterWithVerify(); + var valueFormatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = Create(len); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < len; i++) + { + var key = keyFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + var value = valueFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + Add(dict, i, key, value); + } + } + + readSize = offset - startOffset; + + return Complete(dict); + } + } + + // abstraction for serialize + + // Some collections can use struct iterator, this is optimization path + protected abstract TEnumerator GetSourceEnumerator(TDictionary source); + + // abstraction for deserialize + protected abstract TIntermediate Create(int count); + protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value); + protected abstract TDictionary Complete(TIntermediate intermediateCollection); + } + + internal abstract class DictionaryFormatterBase : DictionaryFormatterBase>, TDictionary> + where TDictionary : IEnumerable> + { + protected override IEnumerator> GetSourceEnumerator(TDictionary source) + { + return source.GetEnumerator(); + } + } + + internal abstract class DictionaryFormatterBase : DictionaryFormatterBase + where TDictionary : IDictionary + { + protected override TDictionary Complete(TDictionary intermediateCollection) + { + return intermediateCollection; + } + } + + + internal sealed class DictionaryFormatter : DictionaryFormatterBase, Dictionary.Enumerator, Dictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override Dictionary Complete(Dictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count, MessagePackSecurity.Active.GetEqualityComparer()); + } + + protected override Dictionary.Enumerator GetSourceEnumerator(Dictionary source) + { + return source.GetEnumerator(); + } + } + + internal sealed class GenericDictionaryFormatter : DictionaryFormatterBase + where TDictionary : IDictionary, new() + { + protected override void Add(TDictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override TDictionary Create(int count) + { + return CollectionHelpers>.CreateHashCollection(count, MessagePackSecurity.Active.GetEqualityComparer()); + } + } + + internal sealed class InterfaceDictionaryFormatter : DictionaryFormatterBase, IDictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count, MessagePackSecurity.Active.GetEqualityComparer()); + } + + protected override IDictionary Complete(Dictionary intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class SortedListFormatter : DictionaryFormatterBase> + { + protected override void Add(SortedList collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override SortedList Create(int count) + { + return new SortedList(count); + } + } + + internal sealed class SortedDictionaryFormatter : DictionaryFormatterBase, SortedDictionary.Enumerator, SortedDictionary> + { + protected override void Add(SortedDictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override SortedDictionary Complete(SortedDictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override SortedDictionary Create(int count) + { + return new SortedDictionary(); + } + + protected override SortedDictionary.Enumerator GetSourceEnumerator(SortedDictionary source) + { + return source.GetEnumerator(); + } + } + + internal sealed class ReadOnlyDictionaryFormatter : DictionaryFormatterBase, ReadOnlyDictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override ReadOnlyDictionary Complete(Dictionary intermediateCollection) + { + return new ReadOnlyDictionary(intermediateCollection); + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count, MessagePackSecurity.Active.GetEqualityComparer()); + } + } + + internal sealed class InterfaceReadOnlyDictionaryFormatter : DictionaryFormatterBase, IReadOnlyDictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override IReadOnlyDictionary Complete(Dictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count, MessagePackSecurity.Active.GetEqualityComparer()); + } + } + + internal sealed class ConcurrentDictionaryFormatter : DictionaryFormatterBase> + { + protected override void Add(ConcurrentDictionary collection, int index, TKey key, TValue value) + { + collection.TryAdd(key, value); + } + + protected override ConcurrentDictionary Create(int count) + { + // concurrent dictionary can't access defaultConcurrecyLevel so does not use count overload. + return new ConcurrentDictionary(MessagePackSecurity.Active.GetEqualityComparer()); + } + } + +#else + + internal abstract class DictionaryFormatterBase : IMessagePackFormatter + where TDictionary : IDictionary + { + public int Serialize(ref byte[] bytes, int offset, TDictionary value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var keyFormatter = formatterResolver.GetFormatterWithVerify(); + var valueFormatter = formatterResolver.GetFormatterWithVerify(); + + var count = value.Count; + + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, count); + + var e = value.GetEnumerator(); + try + { + while (e.MoveNext()) + { + var item = e.Current; + offset += keyFormatter.Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += valueFormatter.Serialize(ref bytes, offset, item.Value, formatterResolver); + } + } + finally + { + e.Dispose(); + } + + return offset - startOffset; + } + } + + public TDictionary Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return default(TDictionary); + } + else + { + var startOffset = offset; + var keyFormatter = formatterResolver.GetFormatterWithVerify(); + var valueFormatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + + var dict = Create(len); + for (int i = 0; i < len; i++) + { + var key = keyFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + var value = valueFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + Add(dict, i, key, value); + } + readSize = offset - startOffset; + + return Complete(dict); + } + } + + // abstraction for deserialize + protected abstract TIntermediate Create(int count); + protected abstract void Add(TIntermediate collection, int index, TKey key, TValue value); + protected abstract TDictionary Complete(TIntermediate intermediateCollection); + } + + internal sealed class DictionaryFormatter : DictionaryFormatterBase, Dictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override Dictionary Complete(Dictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count); + } + } + + internal sealed class GenericDictionaryFormatter : DictionaryFormatterBase + where TDictionary : IDictionary, new() + { + protected override void Add(TDictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override TDictionary Complete(TDictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override TDictionary Create(int count) + { + return new TDictionary(); + } + } + + internal sealed class InterfaceDictionaryFormatter : DictionaryFormatterBase, IDictionary> + { + protected override void Add(Dictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override Dictionary Create(int count) + { + return new Dictionary(count); + } + + protected override IDictionary Complete(Dictionary intermediateCollection) + { + return intermediateCollection; + } + } + + internal sealed class SortedListFormatter : DictionaryFormatterBase, SortedList> + { + protected override void Add(SortedList collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override SortedList Complete(SortedList intermediateCollection) + { + return intermediateCollection; + } + + protected override SortedList Create(int count) + { + return new SortedList(count); + } + } + + internal sealed class SortedDictionaryFormatter : DictionaryFormatterBase, SortedDictionary> + { + protected override void Add(SortedDictionary collection, int index, TKey key, TValue value) + { + collection.Add(key, value); + } + + protected override SortedDictionary Complete(SortedDictionary intermediateCollection) + { + return intermediateCollection; + } + + protected override SortedDictionary Create(int count) + { + return new SortedDictionary(); + } + } + +#endif + +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/DynamicObjectTypeFallbackFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/DynamicObjectTypeFallbackFormatter.cs new file mode 100644 index 0000000000..f5bb36f013 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/DynamicObjectTypeFallbackFormatter.cs @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if NETSTANDARD || NETFRAMEWORK + +using Datadog.Trace.Vendors.MessagePack.Resolvers; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class DynamicObjectTypeFallbackFormatter : IMessagePackFormatter + { + delegate int SerializeMethod(object dynamicFormatter, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver); + + readonly MessagePack.Internal.ThreadsafeTypeKeyHashTable> serializers = new Internal.ThreadsafeTypeKeyHashTable>(); + + readonly IFormatterResolver[] innerResolvers; + + public DynamicObjectTypeFallbackFormatter(params IFormatterResolver[] innerResolvers) + { + this.innerResolvers = innerResolvers; + } + + public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + var type = value.GetType(); + var ti = type.GetTypeInfo(); + + if (type == typeof(object)) + { + // serialize to empty map + return MessagePackBinary.WriteMapHeader(ref bytes, offset, 0); + } + + KeyValuePair formatterAndDelegate; + if (!serializers.TryGetValue(type, out formatterAndDelegate)) + { + lock (serializers) + { + if (!serializers.TryGetValue(type, out formatterAndDelegate)) + { + object formatter = null; + foreach (var innerResolver in innerResolvers) + { + formatter = innerResolver.GetFormatterDynamic(type); + if (formatter != null) break; + } + if (formatter == null) + { + throw new FormatterNotRegisteredException(type.FullName + " is not registered in this resolver. resolvers:" + string.Join(", ", innerResolvers.Select(x => x.GetType().Name).ToArray())); + } + + var t = type; + { + var formatterType = typeof(IMessagePackFormatter<>).MakeGenericType(t); + var param0 = Expression.Parameter(typeof(object), "formatter"); + var param1 = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes"); + var param2 = Expression.Parameter(typeof(int), "offset"); + var param3 = Expression.Parameter(typeof(object), "value"); + var param4 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var serializeMethodInfo = formatterType.GetRuntimeMethod("Serialize", new[] { typeof(byte[]).MakeByRefType(), typeof(int), t, typeof(IFormatterResolver) }); + + var body = Expression.Call( + Expression.Convert(param0, formatterType), + serializeMethodInfo, + param1, + param2, + ti.IsValueType ? Expression.Unbox(param3, t) : Expression.Convert(param3, t), + param4); + + var lambda = Expression.Lambda(body, param0, param1, param2, param3, param4).Compile(); + + formatterAndDelegate = new KeyValuePair(formatter, lambda); + } + + serializers.TryAdd(t, formatterAndDelegate); + } + } + } + + return formatterAndDelegate.Value(formatterAndDelegate.Key, ref bytes, offset, value, formatterResolver); + } + + public object Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return PrimitiveObjectFormatter.Instance.Deserialize(bytes, offset, formatterResolver, out readSize); + } + } +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/EnumAsStringFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/EnumAsStringFormatter.cs new file mode 100644 index 0000000000..4aceb9e766 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/EnumAsStringFormatter.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + // Note:This implemenataion is 'not' fastest, should more improve. + internal sealed class EnumAsStringFormatter : IMessagePackFormatter + { + readonly Dictionary nameValueMapping; + readonly Dictionary valueNameMapping; + + public EnumAsStringFormatter() + { + var names = Enum.GetNames(typeof(T)); + var values = Enum.GetValues(typeof(T)); + + nameValueMapping = new Dictionary(names.Length); + valueNameMapping = new Dictionary(names.Length); + + for (int i = 0; i < names.Length; i++) + { + nameValueMapping[names[i]] = (T)values.GetValue(i); + valueNameMapping[(T)values.GetValue(i)] = names[i]; + } + } + + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + string name; + if (!valueNameMapping.TryGetValue(value, out name)) + { + name = value.ToString(); // fallback for flags etc, But Enum.ToString is too slow. + } + + return MessagePackBinary.WriteString(ref bytes, offset, name); + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var name = MessagePackBinary.ReadString(bytes, offset, out readSize); + + T value; + if (!nameValueMapping.TryGetValue(name, out value)) + { + value = (T)Enum.Parse(typeof(T), name); // Enum.Parse is too slow + } + return value; + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.cs new file mode 100644 index 0000000000..7bf7133a25 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.cs @@ -0,0 +1,833 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class ForceInt16BlockFormatter : IMessagePackFormatter + { + public static readonly ForceInt16BlockFormatter Instance = new ForceInt16BlockFormatter(); + + ForceInt16BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int16 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt16ForceInt16Block(ref bytes, offset, value); + } + + public Int16 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt16(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceInt16BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceInt16BlockFormatter Instance = new NullableForceInt16BlockFormatter(); + + NullableForceInt16BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int16? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt16ForceInt16Block(ref bytes, offset, value.Value); + } + } + + public Int16? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt16(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceInt16BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceInt16BlockArrayFormatter Instance = new ForceInt16BlockArrayFormatter(); + + ForceInt16BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int16[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt16ForceInt16Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int16[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int16[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt16(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceInt32BlockFormatter : IMessagePackFormatter + { + public static readonly ForceInt32BlockFormatter Instance = new ForceInt32BlockFormatter(); + + ForceInt32BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int32 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, offset, value); + } + + public Int32 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt32(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceInt32BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceInt32BlockFormatter Instance = new NullableForceInt32BlockFormatter(); + + NullableForceInt32BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int32? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, offset, value.Value); + } + } + + public Int32? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt32(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceInt32BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceInt32BlockArrayFormatter Instance = new ForceInt32BlockArrayFormatter(); + + ForceInt32BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int32[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int32[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int32[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceInt64BlockFormatter : IMessagePackFormatter + { + public static readonly ForceInt64BlockFormatter Instance = new ForceInt64BlockFormatter(); + + ForceInt64BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int64 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt64ForceInt64Block(ref bytes, offset, value); + } + + public Int64 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt64(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceInt64BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceInt64BlockFormatter Instance = new NullableForceInt64BlockFormatter(); + + NullableForceInt64BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int64? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt64ForceInt64Block(ref bytes, offset, value.Value); + } + } + + public Int64? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt64(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceInt64BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceInt64BlockArrayFormatter Instance = new ForceInt64BlockArrayFormatter(); + + ForceInt64BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int64[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt64ForceInt64Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int64[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int64[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt64(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceUInt16BlockFormatter : IMessagePackFormatter + { + public static readonly ForceUInt16BlockFormatter Instance = new ForceUInt16BlockFormatter(); + + ForceUInt16BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt16 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt16ForceUInt16Block(ref bytes, offset, value); + } + + public UInt16 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceUInt16BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceUInt16BlockFormatter Instance = new NullableForceUInt16BlockFormatter(); + + NullableForceUInt16BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt16? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt16ForceUInt16Block(ref bytes, offset, value.Value); + } + } + + public UInt16? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceUInt16BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceUInt16BlockArrayFormatter Instance = new ForceUInt16BlockArrayFormatter(); + + ForceUInt16BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt16[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt16ForceUInt16Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt16[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt16[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceUInt32BlockFormatter : IMessagePackFormatter + { + public static readonly ForceUInt32BlockFormatter Instance = new ForceUInt32BlockFormatter(); + + ForceUInt32BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt32 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt32ForceUInt32Block(ref bytes, offset, value); + } + + public UInt32 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceUInt32BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceUInt32BlockFormatter Instance = new NullableForceUInt32BlockFormatter(); + + NullableForceUInt32BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt32? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt32ForceUInt32Block(ref bytes, offset, value.Value); + } + } + + public UInt32? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceUInt32BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceUInt32BlockArrayFormatter Instance = new ForceUInt32BlockArrayFormatter(); + + ForceUInt32BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt32[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt32ForceUInt32Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt32[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt32[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceUInt64BlockFormatter : IMessagePackFormatter + { + public static readonly ForceUInt64BlockFormatter Instance = new ForceUInt64BlockFormatter(); + + ForceUInt64BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt64 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt64ForceUInt64Block(ref bytes, offset, value); + } + + public UInt64 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceUInt64BlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceUInt64BlockFormatter Instance = new NullableForceUInt64BlockFormatter(); + + NullableForceUInt64BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt64? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt64ForceUInt64Block(ref bytes, offset, value.Value); + } + } + + public UInt64? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceUInt64BlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceUInt64BlockArrayFormatter Instance = new ForceUInt64BlockArrayFormatter(); + + ForceUInt64BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt64[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt64ForceUInt64Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt64[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt64[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ForceByteBlockFormatter : IMessagePackFormatter + { + public static readonly ForceByteBlockFormatter Instance = new ForceByteBlockFormatter(); + + ForceByteBlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Byte value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteByteForceByteBlock(ref bytes, offset, value); + } + + public Byte Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadByte(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceByteBlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceByteBlockFormatter Instance = new NullableForceByteBlockFormatter(); + + NullableForceByteBlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Byte? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteByteForceByteBlock(ref bytes, offset, value.Value); + } + } + + public Byte? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadByte(bytes, offset, out readSize); + } + } + } + + + internal sealed class ForceSByteBlockFormatter : IMessagePackFormatter + { + public static readonly ForceSByteBlockFormatter Instance = new ForceSByteBlockFormatter(); + + ForceSByteBlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, SByte value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteSByteForceSByteBlock(ref bytes, offset, value); + } + + public SByte Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + } + } + + internal sealed class NullableForceSByteBlockFormatter : IMessagePackFormatter + { + public static readonly NullableForceSByteBlockFormatter Instance = new NullableForceSByteBlockFormatter(); + + NullableForceSByteBlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, SByte? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteSByteForceSByteBlock(ref bytes, offset, value.Value); + } + } + + public SByte? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + } + } + } + + internal sealed class ForceSByteBlockArrayFormatter : IMessagePackFormatter + { + public static readonly ForceSByteBlockArrayFormatter Instance = new ForceSByteBlockArrayFormatter(); + + ForceSByteBlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, SByte[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteSByteForceSByteBlock(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public SByte[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new SByte[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadSByte(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.tt b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.tt new file mode 100644 index 0000000000..9931f35613 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ForceSizePrimitiveFormatter.tt @@ -0,0 +1,138 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var types = new[] + { + typeof(Int16), + typeof(Int32), + typeof(Int64), + typeof(UInt16), + typeof(UInt32), + typeof(UInt64), + typeof(byte), + typeof(sbyte), + }; +#> +using System; + +namespace MessagePack.Formatters +{ +<# foreach(var t in types) { #> + public sealed class Force<#= t.Name #>BlockFormatter : IMessagePackFormatter<<#= t.Name #>> + { + public static readonly Force<#= t.Name #>BlockFormatter Instance = new Force<#= t.Name #>BlockFormatter(); + + Force<#= t.Name #>BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #> value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.Write<#= t.Name #>Force<#= t.Name #>Block(ref bytes, offset, value); + } + + public <#= t.Name #> Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + } + } + + public sealed class NullableForce<#= t.Name #>BlockFormatter : IMessagePackFormatter<<#= t.Name #>?> + { + public static readonly NullableForce<#= t.Name #>BlockFormatter Instance = new NullableForce<#= t.Name #>BlockFormatter(); + + NullableForce<#= t.Name #>BlockFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #>? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.Write<#= t.Name #>Force<#= t.Name #>Block(ref bytes, offset, value.Value); + } + } + + public <#= t.Name #>? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + } + } + } + +<# if(t.Name != "Byte") { #> + public sealed class Force<#= t.Name #>BlockArrayFormatter : IMessagePackFormatter<<#= t.Name #>[]> + { + public static readonly Force<#= t.Name #>BlockArrayFormatter Instance = new Force<#= t.Name #>BlockArrayFormatter(); + + Force<#= t.Name #>BlockArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #>[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.Write<#= t.Name #>Force<#= t.Name #>Block(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public <#= t.Name #>[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new <#= t.Name #>[len]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } +<# } #> + +<# } #> +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/IMessagePackFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/IMessagePackFormatter.cs new file mode 100644 index 0000000000..95711e1887 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/IMessagePackFormatter.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + // marker + internal interface IMessagePackFormatter + { + + } + + internal interface IMessagePackFormatter : IMessagePackFormatter + { + int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver); + T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize); + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/IgnoreFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/IgnoreFormatter.cs new file mode 100644 index 0000000000..12c99741bb --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/IgnoreFormatter.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class IgnoreFormatter : IMessagePackFormatter + { + public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + readSize = MessagePackBinary.ReadNextBlock(bytes, offset); + return default(T); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/MultiDimentionalArrayFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/MultiDimentionalArrayFormatter.cs new file mode 100644 index 0000000000..ff316fad6d --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/MultiDimentionalArrayFormatter.cs @@ -0,0 +1,307 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + // multi dimentional array serialize to [i, j, [seq]] + + internal sealed class TwoDimentionalArrayFormatter : IMessagePackFormatter + { + const int ArrayLength = 3; + + public int Serialize(ref byte[] bytes, int offset, T[,] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var i = value.GetLength(0); + var j = value.GetLength(1); + + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, ArrayLength); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, i); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, j); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + } + + public T[,] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + if (len != ArrayLength) throw new InvalidOperationException("Invalid T[,] format"); + + var iLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var jLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var maxLen = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var array = new T[iLength, jLength]; + + var i = 0; + var j = -1; + using (MessagePackSecurity.DepthStep()) + { + for (int loop = 0; loop < maxLen; loop++) + { + if (j < jLength - 1) + { + j++; + } + else + { + j = 0; + i++; + } + + array[i, j] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ThreeDimentionalArrayFormatter : IMessagePackFormatter + { + const int ArrayLength = 4; + + public int Serialize(ref byte[] bytes, int offset, T[,,] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var i = value.GetLength(0); + var j = value.GetLength(1); + var k = value.GetLength(2); + + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, ArrayLength); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, i); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, j); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, k); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + } + + public T[,,] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + if (len != ArrayLength) throw new InvalidOperationException("Invalid T[,,] format"); + + var iLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var jLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var kLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var maxLen = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var array = new T[iLength, jLength, kLength]; + + var i = 0; + var j = 0; + var k = -1; + using (MessagePackSecurity.DepthStep()) + { + for (int loop = 0; loop < maxLen; loop++) + { + if (k < kLength - 1) + { + k++; + } + else if (j < jLength - 1) + { + k = 0; + j++; + } + else + { + k = 0; + j = 0; + i++; + } + + array[i, j, k] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class FourDimentionalArrayFormatter : IMessagePackFormatter + { + const int ArrayLength = 5; + + public int Serialize(ref byte[] bytes, int offset, T[,,,] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var i = value.GetLength(0); + var j = value.GetLength(1); + var k = value.GetLength(2); + var l = value.GetLength(3); + + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, ArrayLength); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, i); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, j); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, k); + offset += MessagePackBinary.WriteInt32(ref bytes, offset, l); + + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + foreach (var item in value) + { + offset += formatter.Serialize(ref bytes, offset, item, formatterResolver); + } + + return offset - startOffset; + } + } + + public T[,,,] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var formatter = formatterResolver.GetFormatterWithVerify(); + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + if (len != ArrayLength) throw new InvalidOperationException("Invalid T[,,,] format"); + + var iLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var jLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var kLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var lLength = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var maxLen = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var array = new T[iLength, jLength, kLength, lLength]; + + var i = 0; + var j = 0; + var k = 0; + var l = -1; + using (MessagePackSecurity.DepthStep()) + { + for (int loop = 0; loop < maxLen; loop++) + { + if (l < lLength - 1) + { + l++; + } + else if (k < kLength - 1) + { + l = 0; + k++; + } + else if (j < jLength - 1) + { + l = 0; + k = 0; + j++; + } + else + { + l = 0; + k = 0; + j = 0; + i++; + } + + array[i, j, k, l] = formatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/NullableFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/NullableFormatter.cs new file mode 100644 index 0000000000..caae603c66 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/NullableFormatter.cs @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class NullableFormatter : IMessagePackFormatter + where T : struct + { + public int Serialize(ref byte[] bytes, int offset, T? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Value, formatterResolver); + } + } + + public T? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + } + } + } + + internal sealed class StaticNullableFormatter : IMessagePackFormatter + where T : struct + { + readonly IMessagePackFormatter underlyingFormatter; + + public StaticNullableFormatter(IMessagePackFormatter underlyingFormatter) + { + this.underlyingFormatter = underlyingFormatter; + } + + public int Serialize(ref byte[] bytes, int offset, T? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return underlyingFormatter.Serialize(ref bytes, offset, value.Value, formatterResolver); + } + } + + public T? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return underlyingFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + } + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/OldSpecFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/OldSpecFormatter.cs new file mode 100644 index 0000000000..1e4a8269b1 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/OldSpecFormatter.cs @@ -0,0 +1,264 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + /// + /// Serialize by .NET native DateTime binary format. + /// + internal sealed class NativeDateTimeFormatter : IMessagePackFormatter + { + public static readonly NativeDateTimeFormatter Instance = new NativeDateTimeFormatter(); + + public int Serialize(ref byte[] bytes, int offset, DateTime value, IFormatterResolver formatterResolver) + { + var dateData = value.ToBinary(); + return MessagePackBinary.WriteInt64(ref bytes, offset, dateData); + } + + public DateTime Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.GetMessagePackType(bytes, offset) == MessagePackType.Extension) + { + return DateTimeFormatter.Instance.Deserialize(bytes, offset, formatterResolver, out readSize); + } + + var dateData = MessagePackBinary.ReadInt64(bytes, offset, out readSize); + return DateTime.FromBinary(dateData); + } + } + + internal sealed class NativeDateTimeArrayFormatter : IMessagePackFormatter + { + public static readonly NativeDateTimeArrayFormatter Instance = new NativeDateTimeArrayFormatter(); + + public int Serialize(ref byte[] bytes, int offset, DateTime[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt64(ref bytes, offset, value[i].ToBinary()); + } + + return offset - startOffset; + } + } + + public DateTime[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new DateTime[len]; + for (int i = 0; i < array.Length; i++) + { + var dateData = MessagePackBinary.ReadInt64(bytes, offset, out readSize); + array[i] = DateTime.FromBinary(dateData); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + // Old-Spec + // bin 8, bin 16, bin 32, str 8, str 16, str 32 -> fixraw or raw 16 or raw 32 + // fixraw -> fixstr, raw16 -> str16, raw32 -> str32 + // https://github.com/msgpack/msgpack/blob/master/spec-old.md + + /// + /// Old-MessagePack spec's string formatter. + /// + internal sealed class OldSpecStringFormatter : IMessagePackFormatter + { + public static readonly OldSpecStringFormatter Instance = new OldSpecStringFormatter(); + + // Old spec does not exists str 8 format. + public int Serialize(ref byte[] bytes, int offset, string value, IFormatterResolver formatterResolver) + { + if (value == null) return MessagePackBinary.WriteNil(ref bytes, offset); + + MessagePackBinary.EnsureCapacity(ref bytes, offset, StringEncoding.UTF8.GetMaxByteCount(value.Length) + 5); + + int useOffset; + if (value.Length <= MessagePackRange.MaxFixStringLength) + { + useOffset = 1; + } + else if (value.Length <= ushort.MaxValue) + { + useOffset = 3; + } + else + { + useOffset = 5; + } + + // skip length area + var writeBeginOffset = offset + useOffset; + var byteCount = StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, writeBeginOffset); + + // move body and write prefix + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + if (useOffset != 1) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 1, byteCount); + } + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + return byteCount + 1; + } + else if (byteCount <= ushort.MaxValue) + { + if (useOffset != 3) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 3, byteCount); + } + + bytes[offset] = MessagePackCode.Str16; + bytes[offset + 1] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 2] = unchecked((byte)byteCount); + return byteCount + 3; + } + else + { + if (useOffset != 5) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 5, byteCount); + } + + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + return byteCount + 5; + } + } + + public string Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadString(bytes, offset, out readSize); + } + } + + /// + /// Old-MessagePack spec's binary formatter. + /// + internal sealed class OldSpecBinaryFormatter : IMessagePackFormatter + { + public static readonly OldSpecBinaryFormatter Instance = new OldSpecBinaryFormatter(); + + public int Serialize(ref byte[] bytes, int offset, byte[] value, IFormatterResolver formatterResolver) + { + if (value == null) return MessagePackBinary.WriteNil(ref bytes, offset); + + var byteCount = value.Length; + + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, byteCount + 1); + + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + Buffer.BlockCopy(value, 0, bytes, offset + 1, byteCount); + return byteCount + 1; + } + else if (byteCount <= ushort.MaxValue) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, byteCount + 3); + + bytes[offset] = MessagePackCode.Str16; + bytes[offset + 1] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 2] = unchecked((byte)byteCount); + Buffer.BlockCopy(value, 0, bytes, offset + 3, byteCount); + return byteCount + 3; + } + else + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, byteCount + 5); + + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + Buffer.BlockCopy(value, 0, bytes, offset + 5, byteCount); + return byteCount + 5; + } + } + + public byte[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var type = MessagePackBinary.GetMessagePackType(bytes, offset); + if (type == MessagePackType.Nil) + { + readSize = 1; + return null; + } + else if (type == MessagePackType.Binary) + { + return MessagePackBinary.ReadBytes(bytes, offset, out readSize); + } + else if (type == MessagePackType.String) + { + var code = bytes[offset]; + unchecked + { + if (MessagePackCode.MinFixStr <= code && code <= MessagePackCode.MaxFixStr) + { + var length = bytes[offset] & 0x1F; + readSize = length + 1; + var result = new byte[length]; + Buffer.BlockCopy(bytes, offset + 1, result, 0, result.Length); + return result; + } + else if (code == MessagePackCode.Str8) + { + var length = (int)bytes[offset + 1]; + readSize = length + 2; + var result = new byte[length]; + Buffer.BlockCopy(bytes, offset + 2, result, 0, result.Length); + return result; + } + else if (code == MessagePackCode.Str16) + { + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + readSize = length + 3; + var result = new byte[length]; + Buffer.BlockCopy(bytes, offset + 3, result, 0, result.Length); + return result; + } + else if (code == MessagePackCode.Str32) + { + var length = (int)((uint)(bytes[offset + 1] << 24) | (uint)(bytes[offset + 2] << 16) | (uint)(bytes[offset + 3] << 8) | (uint)bytes[offset + 4]); + readSize = length + 5; + var result = new byte[length]; + Buffer.BlockCopy(bytes, offset + 5, result, 0, result.Length); + return result; + } + } + } + + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.cs new file mode 100644 index 0000000000..d1f8937675 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.cs @@ -0,0 +1,1335 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class Int16Formatter : IMessagePackFormatter + { + public static readonly Int16Formatter Instance = new Int16Formatter(); + + Int16Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int16 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt16(ref bytes, offset, value); + } + + public Int16 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt16(bytes, offset, out readSize); + } + } + + internal sealed class NullableInt16Formatter : IMessagePackFormatter + { + public static readonly NullableInt16Formatter Instance = new NullableInt16Formatter(); + + NullableInt16Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int16? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt16(ref bytes, offset, value.Value); + } + } + + public Int16? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt16(bytes, offset, out readSize); + } + } + } + + internal sealed class Int16ArrayFormatter : IMessagePackFormatter + { + public static readonly Int16ArrayFormatter Instance = new Int16ArrayFormatter(); + + Int16ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int16[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt16(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int16[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int16[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt16(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class Int32Formatter : IMessagePackFormatter + { + public static readonly Int32Formatter Instance = new Int32Formatter(); + + Int32Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int32 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt32(ref bytes, offset, value); + } + + public Int32 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt32(bytes, offset, out readSize); + } + } + + internal sealed class NullableInt32Formatter : IMessagePackFormatter + { + public static readonly NullableInt32Formatter Instance = new NullableInt32Formatter(); + + NullableInt32Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int32? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt32(ref bytes, offset, value.Value); + } + } + + public Int32? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt32(bytes, offset, out readSize); + } + } + } + + internal sealed class Int32ArrayFormatter : IMessagePackFormatter + { + public static readonly Int32ArrayFormatter Instance = new Int32ArrayFormatter(); + + Int32ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int32[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt32(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int32[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int32[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class Int64Formatter : IMessagePackFormatter + { + public static readonly Int64Formatter Instance = new Int64Formatter(); + + Int64Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int64 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt64(ref bytes, offset, value); + } + + public Int64 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadInt64(bytes, offset, out readSize); + } + } + + internal sealed class NullableInt64Formatter : IMessagePackFormatter + { + public static readonly NullableInt64Formatter Instance = new NullableInt64Formatter(); + + NullableInt64Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Int64? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteInt64(ref bytes, offset, value.Value); + } + } + + public Int64? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadInt64(bytes, offset, out readSize); + } + } + } + + internal sealed class Int64ArrayFormatter : IMessagePackFormatter + { + public static readonly Int64ArrayFormatter Instance = new Int64ArrayFormatter(); + + Int64ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Int64[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteInt64(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Int64[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Int64[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadInt64(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class UInt16Formatter : IMessagePackFormatter + { + public static readonly UInt16Formatter Instance = new UInt16Formatter(); + + UInt16Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt16 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt16(ref bytes, offset, value); + } + + public UInt16 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + } + } + + internal sealed class NullableUInt16Formatter : IMessagePackFormatter + { + public static readonly NullableUInt16Formatter Instance = new NullableUInt16Formatter(); + + NullableUInt16Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt16? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt16(ref bytes, offset, value.Value); + } + } + + public UInt16? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + } + } + } + + internal sealed class UInt16ArrayFormatter : IMessagePackFormatter + { + public static readonly UInt16ArrayFormatter Instance = new UInt16ArrayFormatter(); + + UInt16ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt16[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt16(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt16[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt16[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class UInt32Formatter : IMessagePackFormatter + { + public static readonly UInt32Formatter Instance = new UInt32Formatter(); + + UInt32Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt32 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt32(ref bytes, offset, value); + } + + public UInt32 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + } + } + + internal sealed class NullableUInt32Formatter : IMessagePackFormatter + { + public static readonly NullableUInt32Formatter Instance = new NullableUInt32Formatter(); + + NullableUInt32Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt32? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt32(ref bytes, offset, value.Value); + } + } + + public UInt32? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + } + } + } + + internal sealed class UInt32ArrayFormatter : IMessagePackFormatter + { + public static readonly UInt32ArrayFormatter Instance = new UInt32ArrayFormatter(); + + UInt32ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt32[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt32(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt32[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt32[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class UInt64Formatter : IMessagePackFormatter + { + public static readonly UInt64Formatter Instance = new UInt64Formatter(); + + UInt64Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt64 value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteUInt64(ref bytes, offset, value); + } + + public UInt64 Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + } + } + + internal sealed class NullableUInt64Formatter : IMessagePackFormatter + { + public static readonly NullableUInt64Formatter Instance = new NullableUInt64Formatter(); + + NullableUInt64Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, UInt64? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteUInt64(ref bytes, offset, value.Value); + } + } + + public UInt64? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + } + } + } + + internal sealed class UInt64ArrayFormatter : IMessagePackFormatter + { + public static readonly UInt64ArrayFormatter Instance = new UInt64ArrayFormatter(); + + UInt64ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, UInt64[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteUInt64(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public UInt64[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new UInt64[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class SingleFormatter : IMessagePackFormatter + { + public static readonly SingleFormatter Instance = new SingleFormatter(); + + SingleFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Single value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteSingle(ref bytes, offset, value); + } + + public Single Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadSingle(bytes, offset, out readSize); + } + } + + internal sealed class NullableSingleFormatter : IMessagePackFormatter + { + public static readonly NullableSingleFormatter Instance = new NullableSingleFormatter(); + + NullableSingleFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Single? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteSingle(ref bytes, offset, value.Value); + } + } + + public Single? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadSingle(bytes, offset, out readSize); + } + } + } + + internal sealed class SingleArrayFormatter : IMessagePackFormatter + { + public static readonly SingleArrayFormatter Instance = new SingleArrayFormatter(); + + SingleArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Single[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteSingle(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Single[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Single[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadSingle(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class DoubleFormatter : IMessagePackFormatter + { + public static readonly DoubleFormatter Instance = new DoubleFormatter(); + + DoubleFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Double value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteDouble(ref bytes, offset, value); + } + + public Double Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadDouble(bytes, offset, out readSize); + } + } + + internal sealed class NullableDoubleFormatter : IMessagePackFormatter + { + public static readonly NullableDoubleFormatter Instance = new NullableDoubleFormatter(); + + NullableDoubleFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Double? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteDouble(ref bytes, offset, value.Value); + } + } + + public Double? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadDouble(bytes, offset, out readSize); + } + } + } + + internal sealed class DoubleArrayFormatter : IMessagePackFormatter + { + public static readonly DoubleArrayFormatter Instance = new DoubleArrayFormatter(); + + DoubleArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Double[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteDouble(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Double[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Double[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadDouble(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class BooleanFormatter : IMessagePackFormatter + { + public static readonly BooleanFormatter Instance = new BooleanFormatter(); + + BooleanFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Boolean value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteBoolean(ref bytes, offset, value); + } + + public Boolean Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadBoolean(bytes, offset, out readSize); + } + } + + internal sealed class NullableBooleanFormatter : IMessagePackFormatter + { + public static readonly NullableBooleanFormatter Instance = new NullableBooleanFormatter(); + + NullableBooleanFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Boolean? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteBoolean(ref bytes, offset, value.Value); + } + } + + public Boolean? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadBoolean(bytes, offset, out readSize); + } + } + } + + internal sealed class BooleanArrayFormatter : IMessagePackFormatter + { + public static readonly BooleanArrayFormatter Instance = new BooleanArrayFormatter(); + + BooleanArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Boolean[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteBoolean(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Boolean[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Boolean[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadBoolean(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class ByteFormatter : IMessagePackFormatter + { + public static readonly ByteFormatter Instance = new ByteFormatter(); + + ByteFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Byte value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteByte(ref bytes, offset, value); + } + + public Byte Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadByte(bytes, offset, out readSize); + } + } + + internal sealed class NullableByteFormatter : IMessagePackFormatter + { + public static readonly NullableByteFormatter Instance = new NullableByteFormatter(); + + NullableByteFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Byte? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteByte(ref bytes, offset, value.Value); + } + } + + public Byte? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadByte(bytes, offset, out readSize); + } + } + } + + + internal sealed class SByteFormatter : IMessagePackFormatter + { + public static readonly SByteFormatter Instance = new SByteFormatter(); + + SByteFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, SByte value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteSByte(ref bytes, offset, value); + } + + public SByte Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + } + } + + internal sealed class NullableSByteFormatter : IMessagePackFormatter + { + public static readonly NullableSByteFormatter Instance = new NullableSByteFormatter(); + + NullableSByteFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, SByte? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteSByte(ref bytes, offset, value.Value); + } + } + + public SByte? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + } + } + } + + internal sealed class SByteArrayFormatter : IMessagePackFormatter + { + public static readonly SByteArrayFormatter Instance = new SByteArrayFormatter(); + + SByteArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, SByte[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteSByte(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public SByte[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new SByte[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadSByte(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class CharFormatter : IMessagePackFormatter + { + public static readonly CharFormatter Instance = new CharFormatter(); + + CharFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Char value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteChar(ref bytes, offset, value); + } + + public Char Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadChar(bytes, offset, out readSize); + } + } + + internal sealed class NullableCharFormatter : IMessagePackFormatter + { + public static readonly NullableCharFormatter Instance = new NullableCharFormatter(); + + NullableCharFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, Char? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteChar(ref bytes, offset, value.Value); + } + } + + public Char? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadChar(bytes, offset, out readSize); + } + } + } + + internal sealed class CharArrayFormatter : IMessagePackFormatter + { + public static readonly CharArrayFormatter Instance = new CharArrayFormatter(); + + CharArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Char[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteChar(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public Char[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new Char[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadChar(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class DateTimeFormatter : IMessagePackFormatter + { + public static readonly DateTimeFormatter Instance = new DateTimeFormatter(); + + DateTimeFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, DateTime value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteDateTime(ref bytes, offset, value); + } + + public DateTime Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + } + } + + internal sealed class NullableDateTimeFormatter : IMessagePackFormatter + { + public static readonly NullableDateTimeFormatter Instance = new NullableDateTimeFormatter(); + + NullableDateTimeFormatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, DateTime? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteDateTime(ref bytes, offset, value.Value); + } + } + + public DateTime? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + } + } + } + + internal sealed class DateTimeArrayFormatter : IMessagePackFormatter + { + public static readonly DateTimeArrayFormatter Instance = new DateTimeArrayFormatter(); + + DateTimeArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, DateTime[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteDateTime(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public DateTime[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new DateTime[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.tt b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.tt new file mode 100644 index 0000000000..67a1e756ad --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveFormatter.tt @@ -0,0 +1,139 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var types = new[] + { + typeof(Int16), + typeof(Int32), + typeof(Int64), + typeof(UInt16), + typeof(UInt32), + typeof(UInt64), + typeof(Single), + typeof(Double), + typeof(bool), + typeof(byte), + typeof(sbyte), + typeof(char), + typeof(DateTime) + }; +#> +using System; + +namespace MessagePack.Formatters +{ +<# foreach(var t in types) { #> + public sealed class <#= t.Name #>Formatter : IMessagePackFormatter<<#= t.Name #>> + { + public static readonly <#= t.Name #>Formatter Instance = new <#= t.Name #>Formatter(); + + <#= t.Name #>Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #> value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.Write<#= t.Name #>(ref bytes, offset, value); + } + + public <#= t.Name #> Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + } + } + + public sealed class Nullable<#= t.Name #>Formatter : IMessagePackFormatter<<#= t.Name #>?> + { + public static readonly Nullable<#= t.Name #>Formatter Instance = new Nullable<#= t.Name #>Formatter(); + + Nullable<#= t.Name #>Formatter() + { + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #>? value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.Write<#= t.Name #>(ref bytes, offset, value.Value); + } + } + + public <#= t.Name #>? Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + } + } + } + +<# if(t.Name != "Byte") { #> + public sealed class <#= t.Name #>ArrayFormatter : IMessagePackFormatter<<#= t.Name #>[]> + { + public static readonly <#= t.Name #>ArrayFormatter Instance = new <#= t.Name #>ArrayFormatter(); + + <#= t.Name #>ArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, <#= t.Name #>[] value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.Write<#= t.Name #>(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public <#= t.Name #>[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new <#= t.Name #>[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.Read<#= t.Name #>(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } +<# } #> + +<# } #> +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveObjectFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveObjectFormatter.cs new file mode 100644 index 0000000000..bfbf6b39c2 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/PrimitiveObjectFormatter.cs @@ -0,0 +1,257 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Reflection; +using System.Collections.Generic; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal sealed class PrimitiveObjectFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new PrimitiveObjectFormatter(); + + static readonly Dictionary typeToJumpCode = new Dictionary() + { + // When adding types whose size exceeds 32-bits, add support in MessagePackSecurity.GetHashCollisionResistantEqualityComparer() + { typeof(Boolean), 0 }, + { typeof(Char), 1 }, + { typeof(SByte), 2 }, + { typeof(Byte), 3 }, + { typeof(Int16), 4 }, + { typeof(UInt16), 5 }, + { typeof(Int32), 6 }, + { typeof(UInt32), 7 }, + { typeof(Int64), 8 }, + { typeof(UInt64),9 }, + { typeof(Single), 10 }, + { typeof(Double), 11 }, + { typeof(DateTime), 12 }, + { typeof(string), 13 }, + { typeof(byte[]), 14 } + }; + + PrimitiveObjectFormatter() + { + + } + +#if !UNITY_WSA + + public static bool IsSupportedType(Type type, TypeInfo typeInfo, object value) + { + if (value == null) return true; + if (typeToJumpCode.ContainsKey(type)) return true; + if (typeInfo.IsEnum) return true; + + if (value is System.Collections.IDictionary) return true; + if (value is System.Collections.ICollection) return true; + + return false; + } + +#endif + + public int Serialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + var t = value.GetType(); + + int code; + if (typeToJumpCode.TryGetValue(t, out code)) + { + switch (code) + { + case 0: + return MessagePackBinary.WriteBoolean(ref bytes, offset, (bool)value); + case 1: + return MessagePackBinary.WriteChar(ref bytes, offset, (char)value); + case 2: + return MessagePackBinary.WriteSByteForceSByteBlock(ref bytes, offset, (sbyte)value); + case 3: + return MessagePackBinary.WriteByteForceByteBlock(ref bytes, offset, (byte)value); + case 4: + return MessagePackBinary.WriteInt16ForceInt16Block(ref bytes, offset, (Int16)value); + case 5: + return MessagePackBinary.WriteUInt16ForceUInt16Block(ref bytes, offset, (UInt16)value); + case 6: + return MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, offset, (Int32)value); + case 7: + return MessagePackBinary.WriteUInt32ForceUInt32Block(ref bytes, offset, (UInt32)value); + case 8: + return MessagePackBinary.WriteInt64ForceInt64Block(ref bytes, offset, (Int64)value); + case 9: + return MessagePackBinary.WriteUInt64ForceUInt64Block(ref bytes, offset, (UInt64)value); + case 10: + return MessagePackBinary.WriteSingle(ref bytes, offset, (Single)value); + case 11: + return MessagePackBinary.WriteDouble(ref bytes, offset, (double)value); + case 12: + return MessagePackBinary.WriteDateTime(ref bytes, offset, (DateTime)value); + case 13: + return MessagePackBinary.WriteString(ref bytes, offset, (string)value); + case 14: + return MessagePackBinary.WriteBytes(ref bytes, offset, (byte[])value); + default: + throw new InvalidOperationException("Not supported primitive object resolver. type:" + t.Name); + } + } + else + { +#if UNITY_WSA && !NETFX_CORE + if (t.IsEnum) +#else + if (t.GetTypeInfo().IsEnum) +#endif + { + var underlyingType = Enum.GetUnderlyingType(t); + var code2 = typeToJumpCode[underlyingType]; + switch (code2) + { + case 2: + return MessagePackBinary.WriteSByteForceSByteBlock(ref bytes, offset, (sbyte)value); + case 3: + return MessagePackBinary.WriteByteForceByteBlock(ref bytes, offset, (byte)value); + case 4: + return MessagePackBinary.WriteInt16ForceInt16Block(ref bytes, offset, (Int16)value); + case 5: + return MessagePackBinary.WriteUInt16ForceUInt16Block(ref bytes, offset, (UInt16)value); + case 6: + return MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, offset, (Int32)value); + case 7: + return MessagePackBinary.WriteUInt32ForceUInt32Block(ref bytes, offset, (UInt32)value); + case 8: + return MessagePackBinary.WriteInt64ForceInt64Block(ref bytes, offset, (Int64)value); + case 9: + return MessagePackBinary.WriteUInt64ForceUInt64Block(ref bytes, offset, (UInt64)value); + default: + break; + } + } + else if (value is System.Collections.IDictionary) // check IDictionary first + { + var d = value as System.Collections.IDictionary; + var startOffset = offset; + offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, d.Count); + foreach (System.Collections.DictionaryEntry item in d) + { + offset += Serialize(ref bytes, offset, item.Key, formatterResolver); + offset += Serialize(ref bytes, offset, item.Value, formatterResolver); + } + return offset - startOffset; + } + else if (value is System.Collections.ICollection) + { + var c = value as System.Collections.ICollection; + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, c.Count); + foreach (var item in c) + { + offset += Serialize(ref bytes, offset, item, formatterResolver); + } + return offset - startOffset; + } + } + + throw new InvalidOperationException("Not supported primitive object resolver. type:" + t.Name); + } + + public object Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var type = MessagePackBinary.GetMessagePackType(bytes, offset); + switch (type) + { + case MessagePackType.Integer: + var code = bytes[offset]; + if (MessagePackCode.MinNegativeFixInt <= code && code <= MessagePackCode.MaxNegativeFixInt) return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + else if (MessagePackCode.MinFixInt <= code && code <= MessagePackCode.MaxFixInt) return MessagePackBinary.ReadByte(bytes, offset, out readSize); + else if (code == MessagePackCode.Int8) return MessagePackBinary.ReadSByte(bytes, offset, out readSize); + else if (code == MessagePackCode.Int16) return MessagePackBinary.ReadInt16(bytes, offset, out readSize); + else if (code == MessagePackCode.Int32) return MessagePackBinary.ReadInt32(bytes, offset, out readSize); + else if (code == MessagePackCode.Int64) return MessagePackBinary.ReadInt64(bytes, offset, out readSize); + else if (code == MessagePackCode.UInt8) return MessagePackBinary.ReadByte(bytes, offset, out readSize); + else if (code == MessagePackCode.UInt16) return MessagePackBinary.ReadUInt16(bytes, offset, out readSize); + else if (code == MessagePackCode.UInt32) return MessagePackBinary.ReadUInt32(bytes, offset, out readSize); + else if (code == MessagePackCode.UInt64) return MessagePackBinary.ReadUInt64(bytes, offset, out readSize); + throw new InvalidOperationException("Invalid primitive bytes."); + case MessagePackType.Boolean: + return MessagePackBinary.ReadBoolean(bytes, offset, out readSize); + case MessagePackType.Float: + if (MessagePackCode.Float32 == bytes[offset]) + { + return MessagePackBinary.ReadSingle(bytes, offset, out readSize); + } + else + { + return MessagePackBinary.ReadDouble(bytes, offset, out readSize); + } + case MessagePackType.String: + return MessagePackBinary.ReadString(bytes, offset, out readSize); + case MessagePackType.Binary: + return MessagePackBinary.ReadBytes(bytes, offset, out readSize); + case MessagePackType.Extension: + var ext = MessagePackBinary.ReadExtensionFormatHeader(bytes, offset, out readSize); + if (ext.TypeCode == ReservedMessagePackExtensionTypeCode.DateTime) + { + return MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + } + throw new InvalidOperationException("Invalid primitive bytes."); + case MessagePackType.Array: + { + var length = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + var startOffset = offset; + offset += readSize; + + var objectFormatter = formatterResolver.GetFormatter(); + var array = new object[length]; + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < length; i++) + { + array[i] = objectFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + } + } + + readSize = offset - startOffset; + return array; + } + case MessagePackType.Map: + { + var length = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + var startOffset = offset; + offset += readSize; + + var objectFormatter = formatterResolver.GetFormatter(); + var hash = new Dictionary(length, MessagePackSecurity.Active.GetEqualityComparer()); + using (MessagePackSecurity.DepthStep()) + { + for (int i = 0; i < length; i++) + { + var key = objectFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + var value = objectFormatter.Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + hash.Add(key, value); + } + } + + readSize = offset - startOffset; + return hash; + } + case MessagePackType.Nil: + readSize = 1; + return null; + default: + throw new InvalidOperationException("Invalid primitive bytes."); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/StandardClassLibraryFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/StandardClassLibraryFormatter.cs new file mode 100644 index 0000000000..17407f6ef3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/StandardClassLibraryFormatter.cs @@ -0,0 +1,574 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Text; + +#if NETSTANDARD || NETFRAMEWORK +using System.Threading.Tasks; +#endif + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + // NET40 -> BigInteger, Complex, Tuple + + // byte[] is special. represents bin type. + internal sealed class ByteArrayFormatter : IMessagePackFormatter + { + public static readonly ByteArrayFormatter Instance = new ByteArrayFormatter(); + + ByteArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, byte[] value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteBytes(ref bytes, offset, value); + } + + public byte[] Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return MessagePackBinary.ReadBytes(bytes, offset, out readSize); + } + } + + internal sealed class NullableStringFormatter : IMessagePackFormatter + { + public static readonly NullableStringFormatter Instance = new NullableStringFormatter(); + + NullableStringFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, String value, IFormatterResolver typeResolver) + { + return MessagePackBinary.WriteString(ref bytes, offset, value); + } + + public String Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize) + { + return MessagePackBinary.ReadString(bytes, offset, out readSize); + } + } + + internal sealed class NullableStringArrayFormatter : IMessagePackFormatter + { + public static readonly NullableStringArrayFormatter Instance = new NullableStringArrayFormatter(); + + NullableStringArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, String[] value, IFormatterResolver typeResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, value.Length); + for (int i = 0; i < value.Length; i++) + { + offset += MessagePackBinary.WriteString(ref bytes, offset, value[i]); + } + + return offset - startOffset; + } + } + + public String[] Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + var array = new String[len]; + for (int i = 0; i < array.Length; i++) + { + array[i] = MessagePackBinary.ReadString(bytes, offset, out readSize); + offset += readSize; + } + readSize = offset - startOffset; + return array; + } + } + } + + internal sealed class DecimalFormatter : IMessagePackFormatter + { + public static readonly DecimalFormatter Instance = new DecimalFormatter(); + + DecimalFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, decimal value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteString(ref bytes, offset, value.ToString(CultureInfo.InvariantCulture)); + } + + public decimal Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return decimal.Parse(MessagePackBinary.ReadString(bytes, offset, out readSize), CultureInfo.InvariantCulture); + } + } + + internal sealed class TimeSpanFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new TimeSpanFormatter(); + + TimeSpanFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, TimeSpan value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteInt64(ref bytes, offset, value.Ticks); + } + + public TimeSpan Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return new TimeSpan(MessagePackBinary.ReadInt64(bytes, offset, out readSize)); + } + } + + internal sealed class DateTimeOffsetFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new DateTimeOffsetFormatter(); + + DateTimeOffsetFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, DateTimeOffset value, IFormatterResolver formatterResolver) + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 2); + offset += MessagePackBinary.WriteDateTime(ref bytes, offset, new DateTime(value.Ticks, DateTimeKind.Utc)); // current ticks as is + offset += MessagePackBinary.WriteInt16(ref bytes, offset, (short)value.Offset.TotalMinutes); // offset is normalized in minutes + return offset - startOffset; + } + + public DateTimeOffset Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + if (count != 2) throw new InvalidOperationException("Invalid DateTimeOffset format."); + + var utc = MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + offset += readSize; + + var dtOffsetMinutes = MessagePackBinary.ReadInt16(bytes, offset, out readSize); + offset += readSize; + + readSize = offset - startOffset; + + return new DateTimeOffset(utc.Ticks, TimeSpan.FromMinutes(dtOffsetMinutes)); + } + } + + internal sealed class GuidFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new GuidFormatter(); + + + GuidFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Guid value, IFormatterResolver formatterResolver) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 38); + + bytes[offset] = MessagePackCode.Str8; + bytes[offset + 1] = unchecked((byte)36); + new GuidBits(ref value).Write(bytes, offset + 2); + return 38; + } + + public Guid Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var segment = MessagePackBinary.ReadStringSegment(bytes, offset, out readSize); + return new GuidBits(segment).Value; + } + } + + internal sealed class UriFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new UriFormatter(); + + + UriFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Uri value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteString(ref bytes, offset, value.ToString()); + } + } + + public Uri Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return new Uri(MessagePackBinary.ReadString(bytes, offset, out readSize), UriKind.RelativeOrAbsolute); + } + } + } + + internal sealed class VersionFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new VersionFormatter(); + + VersionFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Version value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteString(ref bytes, offset, value.ToString()); + } + } + + public Version Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return new Version(MessagePackBinary.ReadString(bytes, offset, out readSize)); + } + } + } + + internal sealed class KeyValuePairFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, KeyValuePair value, IFormatterResolver formatterResolver) + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 2); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Key, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Value, formatterResolver); + return offset - startOffset; + } + + public KeyValuePair Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + if (count != 2) throw new InvalidOperationException("Invalid KeyValuePair format."); + + using (MessagePackSecurity.DepthStep()) + { + var key = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + var value = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new KeyValuePair(key, value); + } + } + } + + internal sealed class StringBuilderFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new StringBuilderFormatter(); + + StringBuilderFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, StringBuilder value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return MessagePackBinary.WriteString(ref bytes, offset, value.ToString()); + } + } + + public StringBuilder Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + return new StringBuilder(MessagePackBinary.ReadString(bytes, offset, out readSize)); + } + } + } + + internal sealed class BitArrayFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new BitArrayFormatter(); + + BitArrayFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, BitArray value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + var len = value.Length; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, len); + for (int i = 0; i < len; i++) + { + offset += MessagePackBinary.WriteBoolean(ref bytes, offset, value.Get(i)); + } + + return offset - startOffset; + } + } + + public BitArray Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + + var len = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + var array = new BitArray(len); + for (int i = 0; i < len; i++) + { + array[i] = MessagePackBinary.ReadBoolean(bytes, offset, out readSize); + offset += readSize; + } + + readSize = offset - startOffset; + return array; + } + } + } + +#if NETSTANDARD || NETFRAMEWORK + + internal sealed class BigIntegerFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new BigIntegerFormatter(); + + BigIntegerFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, System.Numerics.BigInteger value, IFormatterResolver formatterResolver) + { + return MessagePackBinary.WriteBytes(ref bytes, offset, value.ToByteArray()); + } + + public System.Numerics.BigInteger Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + return new System.Numerics.BigInteger(MessagePackBinary.ReadBytes(bytes, offset, out readSize)); + } + } + + internal sealed class ComplexFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new ComplexFormatter(); + + ComplexFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, System.Numerics.Complex value, IFormatterResolver formatterResolver) + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 2); + offset += MessagePackBinary.WriteDouble(ref bytes, offset, value.Real); + offset += MessagePackBinary.WriteDouble(ref bytes, offset, value.Imaginary); + return offset - startOffset; + } + + public System.Numerics.Complex Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + + if (count != 2) throw new InvalidOperationException("Invalid Complex format."); + + var real = MessagePackBinary.ReadDouble(bytes, offset, out readSize); + offset += readSize; + + var imaginary = MessagePackBinary.ReadDouble(bytes, offset, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new System.Numerics.Complex(real, imaginary); + } + } + + internal sealed class LazyFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Lazy value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + return formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Value, formatterResolver); + } + } + + public Lazy Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + using (MessagePackSecurity.DepthStep()) + { + // deserialize immediately(no delay, because capture byte[] causes memory leak) + var v = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + return new Lazy(() => v); + } + } + } + } + + internal sealed class TaskUnitFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new TaskUnitFormatter(); + static readonly Task CompletedTask = Task.FromResult(null); + + TaskUnitFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Task value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + value.Wait(); // wait...! + return MessagePackBinary.WriteNil(ref bytes, offset); + } + } + + public Task Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (!MessagePackBinary.IsNil(bytes, offset)) + { + throw new InvalidOperationException("Invalid input"); + } + else + { + readSize = 1; + return CompletedTask; + } + } + } + + internal sealed class TaskValueFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Task value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + // value.Result -> wait...! + return formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Result, formatterResolver); + } + } + + public Task Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var v = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + return Task.FromResult(v); + } + } + } + +#endif +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.cs b/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.cs new file mode 100644 index 0000000000..21f2f5e51c --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.cs @@ -0,0 +1,457 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if NETSTANDARD || NETFRAMEWORK + +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 1); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 1) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 2); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 2) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 3); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 3) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 4); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item4, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 4) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item4 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3, item4); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 5); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item4, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item5, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 5) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item4 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item5 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3, item4, item5); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 6); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item4, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item5, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item6, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 6) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item4 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item5 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item6 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3, item4, item5, item6); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 7); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item4, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item5, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item6, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item7, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 7) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item4 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item5 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item6 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item7 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3, item4, item5, item6, item7); + } + } + } + } + + + internal sealed class TupleFormatter : IMessagePackFormatter> + { + public int Serialize(ref byte[] bytes, int offset, Tuple value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, 8); + + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item1, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item2, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item3, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item4, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item5, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item6, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Item7, formatterResolver); + offset += formatterResolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value.Rest, formatterResolver); + + return offset - startOffset; + } + } + + public Tuple Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != 8) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + var item1 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item2 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item3 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item4 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item5 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item6 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item7 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + var item8 = formatterResolver.GetFormatterWithVerify().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; + + readSize = offset - startOffset; + return new Tuple(item1, item2, item3, item4, item5, item6, item7, item8); + } + } + } + } + +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.tt b/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.tt new file mode 100644 index 0000000000..e6c3c3c6ae --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/TupleFormatter.tt @@ -0,0 +1,71 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +#if NETSTANDARD || NETFRAMEWORK + +using System; + +namespace MessagePack.Formatters +{ +<# for(var i = 1; i <= 8; i++) { + Func toT = x => "T" + ((x == 8) ? "Rest" : x.ToString()); + Func toItem = x => ((x == 8) ? "Rest" : "Item" + x); + var ts = string.Join(", ", Enumerable.Range(1, i).Select(x => toT(x))); + var t = "Tuple<" + ts + ">"; +#> + + public sealed class TupleFormatter<<#= ts #>> : IMessagePackFormatter<<#= t #>> + { + public int Serialize(ref byte[] bytes, int offset, <#= t #> value, IFormatterResolver formatterResolver) + { + if (value == null) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + else + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, <#= i #>); + +<# for(var j = 1; j <= i; j++) { #> + offset += formatterResolver.GetFormatterWithVerify<<#= toT(j) #>>().Serialize(ref bytes, offset, value.<#= toItem(j) #>, formatterResolver); +<# } #> + + return offset - startOffset; + } + } + + public <#= t #> Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + readSize = 1; + return null; + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != <#= i #>) throw new InvalidOperationException("Invalid Tuple count"); + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { +<# for(var j = 1; j <= i; j++) { #> + var item<#= j #> = formatterResolver.GetFormatterWithVerify<<#= toT(j) #>>().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; +<# } #> + + readSize = offset - startOffset; + return new Tuple<<#= ts #>>(<#= string.Join(", ", Enumerable.Range(1, i).Select(x => "item" + x)) #>); + } + } + } + } + +<# } #> +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Formatters/ValueTupleFormatter.tt b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ValueTupleFormatter.tt new file mode 100644 index 0000000000..73ef261a76 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Formatters/ValueTupleFormatter.tt @@ -0,0 +1,62 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +#if NETSTANDARD || NETFRAMEWORK +using System; + +namespace MessagePack.Formatters +{ +<# for(var i = 1; i <= 8; i++) { + Func toT = x => "T" + ((x == 8) ? "Rest" : x.ToString()); + Func toItem = x => ((x == 8) ? "Rest" : "Item" + x); + var ts = string.Join(", ", Enumerable.Range(1, i).Select(x => toT(x))); + var t = "ValueTuple<" + ts + ">"; +#> + + public sealed class ValueTupleFormatter<<#= ts #>> : IMessagePackFormatter<<#= t #>><#= (t.Contains("TRest") ? " where TRest : struct" : "") #> + { + public int Serialize(ref byte[] bytes, int offset, <#= t #> value, IFormatterResolver formatterResolver) + { + var startOffset = offset; + offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, <#= i #>); + +<# for(var j = 1; j <= i; j++) { #> + offset += formatterResolver.GetFormatterWithVerify<<#= toT(j) #>>().Serialize(ref bytes, offset, value.<#= toItem(j) #>, formatterResolver); +<# } #> + + return offset - startOffset; + } + + public <#= t #> Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + { + if (MessagePackBinary.IsNil(bytes, offset)) + { + throw new InvalidOperationException("Data is Nil, ValueTuple can not be null."); + } + else + { + var startOffset = offset; + var count = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + if (count != <#= i #>) throw new InvalidOperationException("Invalid ValueTuple count"); + offset += readSize; + + using (MessagePackSecurity.DepthStep()) + { +<# for(var j = 1; j <= i; j++) { #> + var item<#= j #> = formatterResolver.GetFormatterWithVerify<<#= toT(j) #>>().Deserialize(bytes, offset, formatterResolver, out readSize); + offset += readSize; +<# } #> + + readSize = offset - startOffset; + return new ValueTuple<<#= ts #>>(<#= string.Join(", ", Enumerable.Range(1, i).Select(x => "item" + x)) #>); + } + } + } + } + +<# } #> +} +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/HashCode.cs b/src/Datadog.Trace/Vendors/MessagePack/HashCode.cs new file mode 100644 index 0000000000..b20fc80762 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/HashCode.cs @@ -0,0 +1,485 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// + +/* + +The xxHash32 implementation is based on the code published by Yann Collet: +https://raw.githubusercontent.com/Cyan4973/xxHash/5c174cfa4e45a42f94082dc0d4539b39696afea1/xxhash.c + + xxHash - Fast Hash algorithm + Copyright (C) 2012-2016, Yann Collet + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + + You can contact the author at : + - xxHash homepage: http://www.xxhash.com + - xxHash source repository : https://github.com/Cyan4973/xxHash + +*/ + +#if !NETCOREAPP + +using System.Collections.Generic; +using System.ComponentModel; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; + +namespace System +{ + // xxHash32 is used for the hash code. + // https://github.com/Cyan4973/xxHash + + internal struct HashCode + { + private static readonly uint s_seed = GenerateGlobalSeed(); + + private const uint Prime1 = 2654435761U; + private const uint Prime2 = 2246822519U; + private const uint Prime3 = 3266489917U; + private const uint Prime4 = 668265263U; + private const uint Prime5 = 374761393U; + + private uint _v1, _v2, _v3, _v4; + private uint _queue1, _queue2, _queue3; + private uint _length; + + private static uint GenerateGlobalSeed() + { + var bytes = new byte[4]; + using (var rng = RandomNumberGenerator.Create()) + { + rng.GetBytes(bytes); + } + + return BitConverter.ToUInt32(bytes, 0); + } + + public static int Combine(T1 value1) + { + unchecked + { + // Provide a way of diffusing bits from something with a limited + // input hash space. For example, many enums only have a few + // possible hashes, only using the bottom few bits of the code. Some + // collections are built on the assumption that hashes are spread + // over a larger space, so diffusing the bits may help the + // collection work more efficiently. + + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 4; + + hash = QueueRound(hash, hc1); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 8; + + hash = QueueRound(hash, hc1); + hash = QueueRound(hash, hc2); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + + uint hash = MixEmptyState(); + hash += 12; + + hash = QueueRound(hash, hc1); + hash = QueueRound(hash, hc2); + hash = QueueRound(hash, hc3); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 16; + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 20; + + hash = QueueRound(hash, hc5); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 24; + + hash = QueueRound(hash, hc5); + hash = QueueRound(hash, hc6); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + uint hc7 = (uint)(value7?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + uint hash = MixState(v1, v2, v3, v4); + hash += 28; + + hash = QueueRound(hash, hc5); + hash = QueueRound(hash, hc6); + hash = QueueRound(hash, hc7); + + hash = MixFinal(hash); + return (int)hash; + } + } + + public static int Combine(T1 value1, T2 value2, T3 value3, T4 value4, T5 value5, T6 value6, T7 value7, T8 value8) + { + unchecked + { + uint hc1 = (uint)(value1?.GetHashCode() ?? 0); + uint hc2 = (uint)(value2?.GetHashCode() ?? 0); + uint hc3 = (uint)(value3?.GetHashCode() ?? 0); + uint hc4 = (uint)(value4?.GetHashCode() ?? 0); + uint hc5 = (uint)(value5?.GetHashCode() ?? 0); + uint hc6 = (uint)(value6?.GetHashCode() ?? 0); + uint hc7 = (uint)(value7?.GetHashCode() ?? 0); + uint hc8 = (uint)(value8?.GetHashCode() ?? 0); + + Initialize(out uint v1, out uint v2, out uint v3, out uint v4); + + v1 = Round(v1, hc1); + v2 = Round(v2, hc2); + v3 = Round(v3, hc3); + v4 = Round(v4, hc4); + + v1 = Round(v1, hc5); + v2 = Round(v2, hc6); + v3 = Round(v3, hc7); + v4 = Round(v4, hc8); + + uint hash = MixState(v1, v2, v3, v4); + hash += 32; + + hash = MixFinal(hash); + return (int)hash; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) + { + unchecked + { + v1 = s_seed + Prime1 + Prime2; + v2 = s_seed + Prime2; + v3 = s_seed; + v4 = s_seed - Prime1; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint Round(uint hash, uint input) + { + unchecked + { + return BitOperations.RotateLeft(hash + input * Prime2, 13) * Prime1; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint QueueRound(uint hash, uint queuedValue) + { + unchecked + { + return BitOperations.RotateLeft(hash + queuedValue * Prime3, 17) * Prime4; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixState(uint v1, uint v2, uint v3, uint v4) + { + unchecked + { + return BitOperations.RotateLeft(v1, 1) + BitOperations.RotateLeft(v2, 7) + BitOperations.RotateLeft(v3, 12) + BitOperations.RotateLeft(v4, 18); + } + } + + private static uint MixEmptyState() + { + unchecked + { + return s_seed + Prime5; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static uint MixFinal(uint hash) + { + unchecked + { + hash ^= hash >> 15; + hash *= Prime2; + hash ^= hash >> 13; + hash *= Prime3; + hash ^= hash >> 16; + return hash; + } + } + + public void Add(T value) + { + Add(value?.GetHashCode() ?? 0); + } + + public void Add(T value, IEqualityComparer comparer) + { + Add(comparer != null ? comparer.GetHashCode(value) : (value?.GetHashCode() ?? 0)); + } + + private void Add(int value) + { + unchecked + { + // The original xxHash works as follows: + // 0. Initialize immediately. We can't do this in a struct (no + // default ctor). + // 1. Accumulate blocks of length 16 (4 uints) into 4 accumulators. + // 2. Accumulate remaining blocks of length 4 (1 uint) into the + // hash. + // 3. Accumulate remaining blocks of length 1 into the hash. + + // There is no need for #3 as this type only accepts ints. _queue1, + // _queue2 and _queue3 are basically a buffer so that when + // ToHashCode is called we can execute #2 correctly. + + // We need to initialize the xxHash32 state (_v1 to _v4) lazily (see + // #0) nd the last place that can be done if you look at the + // original code is just before the first block of 16 bytes is mixed + // in. The xxHash32 state is never used for streams containing fewer + // than 16 bytes. + + // To see what's really going on here, have a look at the Combine + // methods. + + uint val = (uint)value; + + // Storing the value of _length locally shaves of quite a few bytes + // in the resulting machine code. + uint previousLength = _length++; + uint position = previousLength % 4; + + // Switch can't be inlined. + + if (position == 0) + _queue1 = val; + else if (position == 1) + _queue2 = val; + else if (position == 2) + _queue3 = val; + else // position == 3 + { + if (previousLength == 3) + Initialize(out _v1, out _v2, out _v3, out _v4); + + _v1 = Round(_v1, _queue1); + _v2 = Round(_v2, _queue2); + _v3 = Round(_v3, _queue3); + _v4 = Round(_v4, val); + } + } + } + + public int ToHashCode() + { + unchecked + { + // Storing the value of _length locally shaves of quite a few bytes + // in the resulting machine code. + uint length = _length; + + // position refers to the *next* queue position in this method, so + // position == 1 means that _queue1 is populated; _queue2 would have + // been populated on the next call to Add. + uint position = length % 4; + + // If the length is less than 4, _v1 to _v4 don't contain anything + // yet. xxHash32 treats this differently. + + uint hash = length < 4 ? MixEmptyState() : MixState(_v1, _v2, _v3, _v4); + + // _length is incremented once per Add(Int32) and is therefore 4 + // times too small (xxHash length is in bytes, not ints). + + hash += length * 4; + + // Mix what remains in the queue + + // Switch can't be inlined right now, so use as few branches as + // possible by manually excluding impossible scenarios (position > 1 + // is always false if position is not > 0). + if (position > 0) + { + hash = QueueRound(hash, _queue1); + if (position > 1) + { + hash = QueueRound(hash, _queue2); + if (position > 2) + hash = QueueRound(hash, _queue3); + } + } + + hash = MixFinal(hash); + return (int)hash; + } + } + +#pragma warning disable 0809 + // Obsolete member 'memberA' overrides non-obsolete member 'memberB'. + // Disallowing GetHashCode and Equals is by design + + // * We decided to not override GetHashCode() to produce the hash code + // as this would be weird, both naming-wise as well as from a + // behavioral standpoint (GetHashCode() should return the object's + // hash code, not the one being computed). + + // * Even though ToHashCode() can be called safely multiple times on + // this implementation, it is not part of the contract. If the + // implementation has to change in the future we don't want to worry + // about people who might have incorrectly used this type. + + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes. Use ToHashCode to retrieve the computed hash code.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => throw new NotSupportedException(); + + [Obsolete("HashCode is a mutable struct and should not be compared with other HashCodes.", error: true)] + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => throw new NotSupportedException(); +#pragma warning restore 0809 + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/MessagePack/IFormatterResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/IFormatterResolver.cs new file mode 100644 index 0000000000..229976103a --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/IFormatterResolver.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ + +using Datadog.Trace.Vendors.MessagePack.Formatters; +using System; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack +{ + internal interface IFormatterResolver + { + IMessagePackFormatter GetFormatter(); + } + + internal static class FormatterResolverExtensions + { + public static IMessagePackFormatter GetFormatterWithVerify(this IFormatterResolver resolver) + { + IMessagePackFormatter formatter; + try + { + formatter = resolver.GetFormatter(); + } + catch (TypeInitializationException ex) + { +#if NETSTANDARD || NETFRAMEWORK + // The fact that we're using static constructors to initialize this is an internal detail. + // Rethrow the inner exception if there is one. + // Do it carefully so as to not stomp on the original callstack. + System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex.InnerException ?? ex).Throw(); + throw new InvalidOperationException("Unreachable"); // keep the compiler happy +#else + var data = ex.Data; // suppress warning about not using `ex` + throw; +#endif + } + + if (formatter == null) + { + throw new FormatterNotRegisteredException(typeof(T).FullName + " is not registered in this resolver. resolver:" + resolver.GetType().Name); + } + + return formatter; + } + +#if !UNITY_WSA + + public static object GetFormatterDynamic(this IFormatterResolver resolver, Type type) + { + var methodInfo = typeof(IFormatterResolver).GetRuntimeMethod("GetFormatter", Type.EmptyTypes); + + var formatter = methodInfo.MakeGenericMethod(type).Invoke(resolver, null); + return formatter; + } + +#endif + } + + internal class FormatterNotRegisteredException : Exception + { + public FormatterNotRegisteredException(string message) : base(message) + { + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/IMessagePackSerializationCallbackReceiver.cs b/src/Datadog.Trace/Vendors/MessagePack/IMessagePackSerializationCallbackReceiver.cs new file mode 100644 index 0000000000..4b9b07f1a6 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/IMessagePackSerializationCallbackReceiver.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + internal interface IMessagePackSerializationCallbackReceiver + { + void OnBeforeSerialize(); + void OnAfterDeserialize(); + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ArrayPool.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ArrayPool.cs new file mode 100644 index 0000000000..c921752b0f --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ArrayPool.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal sealed class BufferPool : ArrayPool + { + public static readonly BufferPool Default = new BufferPool(65535); + + public BufferPool(int bufferLength) + : base(bufferLength) + { + } + } + + internal class ArrayPool + { + readonly int bufferLength; + readonly object gate; + int index; + T[][] buffers; + + public ArrayPool(int bufferLength) + { + this.bufferLength = bufferLength; + this.buffers = new T[4][]; + this.gate = new object(); + } + + public T[] Rent() + { + lock (gate) + { + if (index >= buffers.Length) + { + Array.Resize(ref buffers, buffers.Length * 2); + } + + if (buffers[index] == null) + { + buffers[index] = new T[bufferLength]; + } + + var buffer = buffers[index]; + buffers[index] = null; + index++; + + return buffer; + } + } + + public void Return(T[] array) + { + if (array.Length != bufferLength) + { + throw new InvalidOperationException("return buffer is not from pool"); + } + + lock (gate) + { + if (index != 0) + { + buffers[--index] = array; + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayComparer.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayComparer.cs new file mode 100644 index 0000000000..697c229fb1 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayComparer.cs @@ -0,0 +1,143 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class ByteArrayComparer + { +#if ENABLE_UNSAFE_MSGPACK + +#if NETSTANDARD || NETFRAMEWORK + + static readonly bool Is32Bit = (IntPtr.Size == 4); + + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] + public static int GetHashCode(byte[] bytes, int offset, int count) + { + if (Is32Bit) + { + return unchecked((int)FarmHash.Hash32(bytes, offset, count)); + } + else + { + return unchecked((int)FarmHash.Hash64(bytes, offset, count)); + } + } + +#endif + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static unsafe bool Equals(byte[] xs, int xsOffset, int xsCount, byte[] ys) + { + return Equals(xs, xsOffset, xsCount, ys, 0, ys.Length); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static unsafe bool Equals(byte[] xs, int xsOffset, int xsCount, byte[] ys, int ysOffset, int ysCount) + { + if (xs == null || ys == null || xsCount != ysCount) + { + return false; + } + + fixed (byte* p1 = &xs[xsOffset]) + fixed (byte* p2 = &ys[ysOffset]) + { + switch (xsCount) + { + case 0: + return true; + case 1: + return *p1 == *p2; + case 2: + return *(short*)p1 == *(short*)p2; + case 3: + if (*(byte*)p1 != *(byte*)p2) return false; + return *(short*)(p1 + 1) == *(short*)(p2 + 1); + case 4: + return *(int*)p1 == *(int*)p2; + case 5: + if (*(byte*)p1 != *(byte*)p2) return false; + return *(int*)(p1 + 1) == *(int*)(p2 + 1); + case 6: + if (*(short*)p1 != *(short*)p2) return false; + return *(int*)(p1 + 2) == *(int*)(p2 + 2); + case 7: + if (*(byte*)p1 != *(byte*)p2) return false; + if (*(short*)(p1 + 1) != *(short*)(p2 + 1)) return false; + return *(int*)(p1 + 3) == *(int*)(p2 + 3); + default: + { + var x1 = p1; + var x2 = p2; + + byte* xEnd = p1 + xsCount - 8; + byte* yEnd = p2 + ysCount - 8; + + while (x1 < xEnd) + { + if (*(long*)x1 != *(long*)x2) + { + return false; + } + + x1 += 8; + x2 += 8; + } + + return *(long*)xEnd == *(long*)yEnd; + } + } + } + } + +#else +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool Equals(byte[] xs, int xsOffset, int xsCount, byte[] ys) + { + if (xs == null || ys == null || xsCount != ys.Length) + { + return false; + } + + for (int i = 0; i < ys.Length; i++) + { + if (xs[xsOffset++] != ys[i]) return false; + } + + return true; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool Equals(byte[] xs, int xsOffset, int xsCount, byte[] ys, int ysOffset, int ysCount) + { + if (xs == null || ys == null || xsCount != ysCount) + { + return false; + } + + for (int i = 0; i < xsCount; i++) + { + if (xs[xsOffset++] != ys[ysOffset++]) return false; + } + + return true; + } + +#endif + + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayStringHashTable.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayStringHashTable.cs new file mode 100644 index 0000000000..aa5e096b0c --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ByteArrayStringHashTable.cs @@ -0,0 +1,196 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + // like ArraySegment hashtable. + // Add is safe for construction phase only and requires capacity(does not do rehash) + // and specialized for internal use(nongenerics, TValue is int) + + // internal, but code generator requires this class + internal class ByteArrayStringHashTable : IEnumerable> + { + readonly Entry[][] buckets; // immutable array(faster than linkedlist) + readonly ulong indexFor; + + public ByteArrayStringHashTable(int capacity) + : this(capacity, 0.42f) // default: 0.75f -> 0.42f + { + } + + public ByteArrayStringHashTable(int capacity, float loadFactor) + { + var tableSize = CalculateCapacity(capacity, loadFactor); + this.buckets = new Entry[tableSize][]; + this.indexFor = (ulong)buckets.Length - 1; + } + + public void Add(string key, int value) + { + if (!TryAddInternal(Encoding.UTF8.GetBytes(key), value)) + { + throw new ArgumentException("Key was already exists. Key:" + key); + } + } + + public void Add(byte[] key, int value) + { + if (!TryAddInternal(key, value)) + { + throw new ArgumentException("Key was already exists. Key:" + key); + } + } + + bool TryAddInternal(byte[] key, int value) + { + var h = ByteArrayGetHashCode(key, 0, key.Length); + var entry = new Entry { Key = key, Value = value }; + + var array = buckets[h & (indexFor)]; + if (array == null) + { + buckets[h & (indexFor)] = new[] { entry }; + } + else + { + // check duplicate + for (int i = 0; i < array.Length; i++) + { + var e = array[i].Key; + if (ByteArrayComparer.Equals(key, 0, key.Length, e)) + { + return false; + } + } + + var newArray = new Entry[array.Length + 1]; + Array.Copy(array, newArray, array.Length); + array = newArray; + array[array.Length - 1] = entry; + buckets[h & (indexFor)] = array; + } + + return true; + } + + public bool TryGetValue(ArraySegment key, out int value) + { + var table = buckets; + var hash = ByteArrayGetHashCode(key.Array, key.Offset, key.Count); + var entry = table[hash & indexFor]; + + if (entry == null) goto NOT_FOUND; + + { +#if NETSTANDARD || NETFRAMEWORK + ref var v = ref entry[0]; +#else + var v = entry[0]; +#endif + if (ByteArrayComparer.Equals(key.Array, key.Offset, key.Count, v.Key)) + { + value = v.Value; + return true; + } + } + + for (int i = 1; i < entry.Length; i++) + { +#if NETSTANDARD || NETFRAMEWORK + ref var v = ref entry[i]; +#else + var v = entry[i]; +#endif + if (ByteArrayComparer.Equals(key.Array, key.Offset, key.Count, v.Key)) + { + value = v.Value; + return true; + } + } + + NOT_FOUND: + value = default(int); + return false; + } + +#if NETSTANDARD || NETFRAMEWORK + static readonly bool Is32Bit = (IntPtr.Size == 4); +#endif + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + static ulong ByteArrayGetHashCode(byte[] x, int offset, int count) + { + // FNV1-1a 32bit https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function + uint hash = 0; + if (x != null) + { + var max = offset + count; + + hash = 2166136261; + for (int i = offset; i < max; i++) + { + hash = unchecked((x[i] ^ hash) * 16777619); + } + } + + return (ulong)hash; + } + + static int CalculateCapacity(int collectionSize, float loadFactor) + { + var initialCapacity = (int)(((float)collectionSize) / loadFactor); + var capacity = 1; + while (capacity < initialCapacity) + { + capacity <<= 1; + } + + if (capacity < 8) + { + return 8; + } + + return capacity; + } + + // only for Debug use + public IEnumerator> GetEnumerator() + { + var b = this.buckets; + + foreach (var item in b) + { + if (item == null) continue; + foreach (var item2 in item) + { + yield return new KeyValuePair(Encoding.UTF8.GetString(item2.Key), item2.Value); + } + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + struct Entry + { + public byte[] Key; + public int Value; + + // for debugging + public override string ToString() + { + return "(" + Encoding.UTF8.GetString(Key) + ", " + Value + ")"; + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ExpressionUtility.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ExpressionUtility.cs new file mode 100644 index 0000000000..fec99c955f --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ExpressionUtility.cs @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class ExpressionUtility + { + // Method + + static MethodInfo GetMethodInfoCore(LambdaExpression expression) + { + if (expression == null) + { + throw new ArgumentNullException("expression"); + } + + return (expression.Body as MethodCallExpression).Method; + } + + /// + /// Get MethodInfo from Expression for Static(with result) method. + /// + public static MethodInfo GetMethodInfo(Expression> expression) + { + return GetMethodInfoCore(expression); + } + + /// + /// Get MethodInfo from Expression for Static(void) method. + /// + public static MethodInfo GetMethodInfo(Expression expression) + { + return GetMethodInfoCore(expression); + } + + /// + /// Get MethodInfo from Expression for Instance(with result) method. + /// + public static MethodInfo GetMethodInfo(Expression> expression) + { + return GetMethodInfoCore(expression); + } + + /// + /// Get MethodInfo from Expression for Instance(void) method. + /// + public static MethodInfo GetMethodInfo(Expression> expression) + { + return GetMethodInfoCore(expression); + } + + // WithArgument(for ref, out) helper + + /// + /// Get MethodInfo from Expression for Instance(with result) method. + /// + public static MethodInfo GetMethodInfo(Expression> expression) + { + return GetMethodInfoCore(expression); + } + + // Property + + static MemberInfo GetMemberInfoCore(Expression source) + { + if (source == null) + { + throw new ArgumentNullException("source"); + } + + var memberExpression = source.Body as MemberExpression; + return memberExpression.Member; + } + + public static PropertyInfo GetPropertyInfo(Expression> expression) + { + return GetMemberInfoCore(expression) as PropertyInfo; + } + + // Field + + public static FieldInfo GetFieldInfo(Expression> expression) + { + return GetMemberInfoCore(expression) as FieldInfo; + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/GuidBits.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/GuidBits.cs new file mode 100644 index 0000000000..2de0d00bd7 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/GuidBits.cs @@ -0,0 +1,376 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Runtime.InteropServices; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + [StructLayout(LayoutKind.Explicit, Pack = 1)] + internal struct GuidBits + { + [FieldOffset(0)] + public readonly Guid Value; + + [FieldOffset(0)] + public readonly byte Byte0; + [FieldOffset(1)] + public readonly byte Byte1; + [FieldOffset(2)] + public readonly byte Byte2; + [FieldOffset(3)] + public readonly byte Byte3; + [FieldOffset(4)] + public readonly byte Byte4; + [FieldOffset(5)] + public readonly byte Byte5; + [FieldOffset(6)] + public readonly byte Byte6; + [FieldOffset(7)] + public readonly byte Byte7; + [FieldOffset(8)] + public readonly byte Byte8; + [FieldOffset(9)] + public readonly byte Byte9; + [FieldOffset(10)] + public readonly byte Byte10; + [FieldOffset(11)] + public readonly byte Byte11; + [FieldOffset(12)] + public readonly byte Byte12; + [FieldOffset(13)] + public readonly byte Byte13; + [FieldOffset(14)] + public readonly byte Byte14; + [FieldOffset(15)] + public readonly byte Byte15; + + // string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[0])) + static byte[] byteToHexStringHigh = new byte[256] { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102 }; + + // string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[1])) + static byte[] byteToHexStringLow = new byte[256] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102 }; + + public GuidBits(ref Guid value) + { + this = default(GuidBits); + this.Value = value; + } + + // 4-pattern, lower/upper and '-' or no + public GuidBits(ArraySegment utf8string) + { + this = default(GuidBits); + + var array = utf8string.Array; + var offset = utf8string.Offset; + + // 32 + if (utf8string.Count == 32) + { + if (BitConverter.IsLittleEndian) + { + this.Byte0 = Parse(array, offset + 6); + this.Byte1 = Parse(array, offset + 4); + this.Byte2 = Parse(array, offset + 2); + this.Byte3 = Parse(array, offset + 0); + + this.Byte4 = Parse(array, offset + 10); + this.Byte5 = Parse(array, offset + 8); + + this.Byte6 = Parse(array, offset + 14); + this.Byte7 = Parse(array, offset + 12); + } + else + { + this.Byte0 = Parse(array, offset + 0); + this.Byte1 = Parse(array, offset + 2); + this.Byte2 = Parse(array, offset + 4); + this.Byte3 = Parse(array, offset + 6); + + this.Byte4 = Parse(array, offset + 8); + this.Byte5 = Parse(array, offset + 10); + + this.Byte6 = Parse(array, offset + 12); + this.Byte7 = Parse(array, offset + 14); + } + this.Byte8 = Parse(array, offset + 16); + this.Byte9 = Parse(array, offset + 18); + + this.Byte10 = Parse(array, offset + 20); + this.Byte11 = Parse(array, offset + 22); + this.Byte12 = Parse(array, offset + 24); + this.Byte13 = Parse(array, offset + 26); + this.Byte14 = Parse(array, offset + 28); + this.Byte15 = Parse(array, offset + 30); + return; + } + else if (utf8string.Count == 36) + { + // '-' => 45 + if (BitConverter.IsLittleEndian) + { + this.Byte0 = Parse(array, offset + 6); + this.Byte1 = Parse(array, offset + 4); + this.Byte2 = Parse(array, offset + 2); + this.Byte3 = Parse(array, offset + 0); + + if (array[offset + 8] != '-') goto ERROR; + + this.Byte4 = Parse(array, offset + 11); + this.Byte5 = Parse(array, offset + 9); + + if (array[offset + 13] != '-') goto ERROR; + + this.Byte6 = Parse(array, offset + 16); + this.Byte7 = Parse(array, offset + 14); + } + else + { + this.Byte0 = Parse(array, offset + 0); + this.Byte1 = Parse(array, offset + 2); + this.Byte2 = Parse(array, offset + 4); + this.Byte3 = Parse(array, offset + 6); + + if (array[offset + 8] != '-') goto ERROR; + + this.Byte4 = Parse(array, offset + 9); + this.Byte5 = Parse(array, offset + 11); + + if (array[offset + 13] != '-') goto ERROR; + + this.Byte6 = Parse(array, offset + 14); + this.Byte7 = Parse(array, offset + 16); + } + + if (array[offset + 18] != '-') goto ERROR; + + this.Byte8 = Parse(array, offset + 19); + this.Byte9 = Parse(array, offset + 21); + + if (array[offset + 23] != '-') goto ERROR; + + this.Byte10 = Parse(array, offset + 24); + this.Byte11 = Parse(array, offset + 26); + this.Byte12 = Parse(array, offset + 28); + this.Byte13 = Parse(array, offset + 30); + this.Byte14 = Parse(array, offset + 32); + this.Byte15 = Parse(array, offset + 34); + return; + } + + ERROR: + throw new ArgumentException("Invalid Guid Pattern."); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + static byte Parse(byte[] bytes, int highOffset) + { + return unchecked((byte)(SwitchParse(bytes[highOffset]) * 16 + SwitchParse(bytes[highOffset + 1]))); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + static byte SwitchParse(byte b) + { + // '0'(48) ~ '9'(57) => -48 + // 'A'(65) ~ 'F'(70) => -55 + // 'a'(97) ~ 'f'(102) => -87 + switch (b) + { + case 48: + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + return unchecked((byte)((b - 48))); + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: + return unchecked((byte)((b - 55))); + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: + return unchecked((byte)((b - 87))); + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case 32: + case 33: + case 34: + case 35: + case 36: + case 37: + case 38: + case 39: + case 40: + case 41: + case 42: + case 43: + case 44: + case 45: + case 46: + case 47: + case 58: + case 59: + case 60: + case 61: + case 62: + case 63: + case 64: + case 71: + case 72: + case 73: + case 74: + case 75: + case 76: + case 77: + case 78: + case 79: + case 80: + case 81: + case 82: + case 83: + case 84: + case 85: + case 86: + case 87: + case 88: + case 89: + case 90: + case 91: + case 92: + case 93: + case 94: + case 95: + case 96: + default: + throw new ArgumentException("Invalid Guid Pattern."); + } + } + + // 4(x2) - 2(x2) - 2(x2) - 2(x2) - 6(x2) + public void Write(byte[] buffer, int offset) + { + if (BitConverter.IsLittleEndian) + { + // int(_a) + buffer[offset + 6] = byteToHexStringHigh[Byte0]; + buffer[offset + 7] = byteToHexStringLow[Byte0]; + buffer[offset + 4] = byteToHexStringHigh[Byte1]; + buffer[offset + 5] = byteToHexStringLow[Byte1]; + buffer[offset + 2] = byteToHexStringHigh[Byte2]; + buffer[offset + 3] = byteToHexStringLow[Byte2]; + buffer[offset + 0] = byteToHexStringHigh[Byte3]; + buffer[offset + 1] = byteToHexStringLow[Byte3]; + + buffer[offset + 8] = (byte)'-'; + + // short(_b) + buffer[offset + 11] = byteToHexStringHigh[Byte4]; + buffer[offset + 12] = byteToHexStringLow[Byte4]; + buffer[offset + 9] = byteToHexStringHigh[Byte5]; + buffer[offset + 10] = byteToHexStringLow[Byte5]; + + buffer[offset + 13] = (byte)'-'; + + // short(_c) + buffer[offset + 16] = byteToHexStringHigh[Byte6]; + buffer[offset + 17] = byteToHexStringLow[Byte6]; + buffer[offset + 14] = byteToHexStringHigh[Byte7]; + buffer[offset + 15] = byteToHexStringLow[Byte7]; + } + else + { + buffer[offset + 0] = byteToHexStringHigh[Byte0]; + buffer[offset + 1] = byteToHexStringLow[Byte0]; + buffer[offset + 2] = byteToHexStringHigh[Byte1]; + buffer[offset + 3] = byteToHexStringLow[Byte1]; + buffer[offset + 4] = byteToHexStringHigh[Byte2]; + buffer[offset + 5] = byteToHexStringLow[Byte2]; + buffer[offset + 6] = byteToHexStringHigh[Byte3]; + buffer[offset + 7] = byteToHexStringLow[Byte3]; + + buffer[offset + 8] = (byte)'-'; + + buffer[offset + 9] = byteToHexStringHigh[Byte4]; + buffer[offset + 10] = byteToHexStringLow[Byte4]; + buffer[offset + 11] = byteToHexStringHigh[Byte5]; + buffer[offset + 12] = byteToHexStringLow[Byte5]; + + buffer[offset + 13] = (byte)'-'; + + buffer[offset + 14] = byteToHexStringHigh[Byte6]; + buffer[offset + 15] = byteToHexStringLow[Byte6]; + buffer[offset + 16] = byteToHexStringHigh[Byte7]; + buffer[offset + 17] = byteToHexStringLow[Byte7]; + } + + buffer[offset + 18] = (byte)'-'; + + buffer[offset + 19] = byteToHexStringHigh[Byte8]; + buffer[offset + 20] = byteToHexStringLow[Byte8]; + buffer[offset + 21] = byteToHexStringHigh[Byte9]; + buffer[offset + 22] = byteToHexStringLow[Byte9]; + + buffer[offset + 23] = (byte)'-'; + + buffer[offset + 24] = byteToHexStringHigh[Byte10]; + buffer[offset + 25] = byteToHexStringLow[Byte10]; + buffer[offset + 26] = byteToHexStringHigh[Byte11]; + buffer[offset + 27] = byteToHexStringLow[Byte11]; + buffer[offset + 28] = byteToHexStringHigh[Byte12]; + buffer[offset + 29] = byteToHexStringLow[Byte12]; + buffer[offset + 30] = byteToHexStringHigh[Byte13]; + buffer[offset + 31] = byteToHexStringLow[Byte13]; + buffer[offset + 32] = byteToHexStringHigh[Byte14]; + buffer[offset + 33] = byteToHexStringLow[Byte14]; + buffer[offset + 34] = byteToHexStringHigh[Byte15]; + buffer[offset + 35] = byteToHexStringLow[Byte15]; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ReflectionExtensions.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ReflectionExtensions.cs new file mode 100644 index 0000000000..4583914dba --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ReflectionExtensions.cs @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if !UNITY_WSA + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class ReflectionExtensions + { + public static bool IsNullable(this System.Reflection.TypeInfo type) + { + return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Nullable<>); + } + + public static bool IsPublic(this System.Reflection.TypeInfo type) + { + return type.IsPublic; + } + + public static bool IsAnonymous(this System.Reflection.TypeInfo type) + { + return type.GetCustomAttribute() != null + && type.IsGenericType && type.Name.Contains("AnonymousType") + && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$")) + && (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic; + } + + public static bool IsIndexer(this System.Reflection.PropertyInfo propertyInfo) + { + return propertyInfo.GetIndexParameters().Length > 0; + } + +#if NETSTANDARD || NETFRAMEWORK + + public static bool IsConstructedGenericType(this System.Reflection.TypeInfo type) + { + return type.AsType().IsConstructedGenericType; + } + + public static MethodInfo GetGetMethod(this PropertyInfo propInfo) + { + return propInfo.GetMethod; + } + + public static MethodInfo GetSetMethod(this PropertyInfo propInfo) + { + return propInfo.SetMethod; + } + +#endif + } +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/ThreadsafeTypeKeyHashTable.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/ThreadsafeTypeKeyHashTable.cs new file mode 100644 index 0000000000..1b19cdeeec --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/ThreadsafeTypeKeyHashTable.cs @@ -0,0 +1,236 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + // Safe for multiple-read, single-write. + internal class ThreadsafeTypeKeyHashTable + { + Entry[] buckets; + int size; // only use in writer lock + + readonly object writerLock = new object(); + readonly float loadFactor; + + // IEqualityComparer.Equals is overhead if key only Type, don't use it. + // readonly IEqualityComparer comparer; + + public ThreadsafeTypeKeyHashTable(int capacity = 4, float loadFactor = 0.75f) + { + var tableSize = CalculateCapacity(capacity, loadFactor); + this.buckets = new Entry[tableSize]; + this.loadFactor = loadFactor; + } + + public bool TryAdd(Type key, TValue value) + { + return TryAdd(key, _ => value); // create lambda capture + } + + public bool TryAdd(Type key, Func valueFactory) + { + TValue _; + return TryAddInternal(key, valueFactory, out _); + } + + bool TryAddInternal(Type key, Func valueFactory, out TValue resultingValue) + { + lock (writerLock) + { + var nextCapacity = CalculateCapacity(size + 1, loadFactor); + + if (buckets.Length < nextCapacity) + { + // rehash + var nextBucket = new Entry[nextCapacity]; + for (int i = 0; i < buckets.Length; i++) + { + var e = buckets[i]; + while (e != null) + { + var newEntry = new Entry { Key = e.Key, Value = e.Value, Hash = e.Hash }; + AddToBuckets(nextBucket, key, newEntry, null, out resultingValue); + e = e.Next; + } + } + + // add entry(if failed to add, only do resize) + var successAdd = AddToBuckets(nextBucket, key, null, valueFactory, out resultingValue); + + // replace field(threadsafe for read) + VolatileWrite(ref buckets, nextBucket); + + if (successAdd) size++; + return successAdd; + } + else + { + // add entry(insert last is thread safe for read) + var successAdd = AddToBuckets(buckets, key, null, valueFactory, out resultingValue); + if (successAdd) size++; + return successAdd; + } + } + } + + bool AddToBuckets(Entry[] buckets, Type newKey, Entry newEntryOrNull, Func valueFactory, out TValue resultingValue) + { + var h = (newEntryOrNull != null) ? newEntryOrNull.Hash : newKey.GetHashCode(); + if (buckets[h & (buckets.Length - 1)] == null) + { + if (newEntryOrNull != null) + { + resultingValue = newEntryOrNull.Value; + VolatileWrite(ref buckets[h & (buckets.Length - 1)], newEntryOrNull); + } + else + { + resultingValue = valueFactory(newKey); + VolatileWrite(ref buckets[h & (buckets.Length - 1)], new Entry { Key = newKey, Value = resultingValue, Hash = h }); + } + } + else + { + var searchLastEntry = buckets[h & (buckets.Length - 1)]; + while (true) + { + if (searchLastEntry.Key == newKey) + { + resultingValue = searchLastEntry.Value; + return false; + } + + if (searchLastEntry.Next == null) + { + if (newEntryOrNull != null) + { + resultingValue = newEntryOrNull.Value; + VolatileWrite(ref searchLastEntry.Next, newEntryOrNull); + } + else + { + resultingValue = valueFactory(newKey); + VolatileWrite(ref searchLastEntry.Next, new Entry { Key = newKey, Value = resultingValue, Hash = h }); + } + break; + } + searchLastEntry = searchLastEntry.Next; + } + } + + return true; + } + + public bool TryGetValue(Type key, out TValue value) + { + var table = buckets; + var hash = key.GetHashCode(); + var entry = table[hash & table.Length - 1]; + + if (entry == null) goto NOT_FOUND; + + if (entry.Key == key) + { + value = entry.Value; + return true; + } + + var next = entry.Next; + while (next != null) + { + if (next.Key == key) + { + value = next.Value; + return true; + } + next = next.Next; + } + + NOT_FOUND: + value = default(TValue); + return false; + } + + public TValue GetOrAdd(Type key, Func valueFactory) + { + TValue v; + if (TryGetValue(key, out v)) + { + return v; + } + + TryAddInternal(key, valueFactory, out v); + return v; + } + + static int CalculateCapacity(int collectionSize, float loadFactor) + { + var initialCapacity = (int)(((float)collectionSize) / loadFactor); + var capacity = 1; + while (capacity < initialCapacity) + { + capacity <<= 1; + } + + if (capacity < 8) + { + return 8; + } + + return capacity; + } + + static void VolatileWrite(ref Entry location, Entry value) + { +#if NETSTANDARD || NETFRAMEWORK + System.Threading.Volatile.Write(ref location, value); +#elif UNITY_WSA || NET_4_6 + System.Threading.Volatile.Write(ref location, value); +#else + System.Threading.Thread.MemoryBarrier(); + location = value; +#endif + } + + static void VolatileWrite(ref Entry[] location, Entry[] value) + { +#if NETSTANDARD || NETFRAMEWORK + System.Threading.Volatile.Write(ref location, value); +#elif UNITY_WSA || NET_4_6 + System.Threading.Volatile.Write(ref location, value); +#else + System.Threading.Thread.MemoryBarrier(); + location = value; +#endif + } + + class Entry + { + public Type Key; + public TValue Value; + public int Hash; + public Entry Next; + + // debug only + public override string ToString() + { + return Key + "(" + Count() + ")"; + } + + int Count() + { + var count = 1; + var n = this; + while (n.Next != null) + { + count++; + n = n.Next; + } + return count; + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/TinyJsonReader.cs b/src/Datadog.Trace/Vendors/MessagePack/Internal/TinyJsonReader.cs new file mode 100644 index 0000000000..5287e12591 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/TinyJsonReader.cs @@ -0,0 +1,359 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Globalization; +using System.IO; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + // simple, tiny JSON reader for MessagePackSerializer.FromJson. + // this is simple, compact and enough fast but not optimized extremely. + + internal enum TinyJsonToken + { + None, + StartObject, // { + EndObject, // } + StartArray, // [ + EndArray, // ] + Number, // -0~9 + String, // "___" + True, // true + False, // false + Null, // null + } + + internal enum ValueType : byte + { + Null, + True, + False, + Double, + Long, + ULong, + Decimal, + String + } + + internal class TinyJsonException : Exception + { + public TinyJsonException(string message) : base(message) + { + + } + } + + internal class TinyJsonReader : IDisposable + { + readonly TextReader reader; + readonly bool disposeInnerReader; + StringBuilder reusableBuilder; + + public TinyJsonToken TokenType { get; private set; } + public ValueType ValueType { get; private set; } + public double DoubleValue { get; private set; } + public long LongValue { get; private set; } + public ulong ULongValue { get; private set; } + public decimal DecimalValue { get; private set; } + public string StringValue { get; private set; } + + public TinyJsonReader(TextReader reader, bool disposeInnerReader = true) + { + this.reader = reader; + this.disposeInnerReader = disposeInnerReader; + } + + public bool Read() + { + ReadNextToken(); + ReadValue(); + return TokenType != TinyJsonToken.None; + } + + public void Dispose() + { + if (reader != null && disposeInnerReader) + { + reader.Dispose(); + } + TokenType = TinyJsonToken.None; + ValueType = ValueType.Null; + } + + void SkipWhiteSpace() + { + var c = reader.Peek(); + while (c != -1 && Char.IsWhiteSpace((char)c)) + { + reader.Read(); + c = reader.Peek(); + } + } + + char ReadChar() + { + return (char)reader.Read(); + } + + static bool IsWordBreak(char c) + { + switch (c) + { + case ' ': + case '{': + case '}': + case '[': + case ']': + case ',': + case ':': + case '\"': + return true; + default: + return false; + } + } + + void ReadNextToken() + { + SkipWhiteSpace(); + + var intChar = reader.Peek(); + if (intChar == -1) + { + TokenType = TinyJsonToken.None; + return; + } + + var c = (char)intChar; + switch (c) + { + case '{': + TokenType = TinyJsonToken.StartObject; + return; + case '}': + TokenType = TinyJsonToken.EndObject; + return; + case '[': + TokenType = TinyJsonToken.StartArray; + return; + case ']': + TokenType = TinyJsonToken.EndArray; + return; + case '"': + TokenType = TinyJsonToken.String; + return; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + TokenType = TinyJsonToken.Number; + return; + case 't': + TokenType = TinyJsonToken.True; + return; + case 'f': + TokenType = TinyJsonToken.False; + return; + case 'n': + TokenType = TinyJsonToken.Null; + return; + case ',': + case ':': + reader.Read(); + ReadNextToken(); + return; + default: + throw new TinyJsonException("Invalid String:" + c); + } + } + + void ReadValue() + { + ValueType = ValueType.Null; + + switch (TokenType) + { + case TinyJsonToken.None: + break; + case TinyJsonToken.StartObject: + case TinyJsonToken.EndObject: + case TinyJsonToken.StartArray: + case TinyJsonToken.EndArray: + reader.Read(); + break; + case TinyJsonToken.Number: + ReadNumber(); + break; + case TinyJsonToken.String: + ReadString(); + break; + case TinyJsonToken.True: + if (ReadChar() != 't') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'r') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'u') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'e') throw new TinyJsonException("Invalid Token"); + ValueType = ValueType.True; + break; + case TinyJsonToken.False: + if (ReadChar() != 'f') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'a') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 's') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'e') throw new TinyJsonException("Invalid Token"); + ValueType = ValueType.False; + break; + case TinyJsonToken.Null: + if (ReadChar() != 'n') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'u') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token"); + if (ReadChar() != 'l') throw new TinyJsonException("Invalid Token"); + ValueType = ValueType.Null; + break; + default: + throw new ArgumentException("InvalidTokenState:" + TokenType); + } + } + + void ReadNumber() + { + StringBuilder numberWord; + if (reusableBuilder == null) + { + reusableBuilder = new StringBuilder(); + numberWord = reusableBuilder; + } + else + { + numberWord = reusableBuilder; + numberWord.Length = 0; // Clear + } + + var isDouble = false; + var intChar = reader.Peek(); + while (intChar != -1 && !IsWordBreak((char)intChar)) + { + var c = ReadChar(); + numberWord.Append(c); + if (c == '.' || c == 'e' || c == 'E') isDouble = true; + intChar = reader.Peek(); + } + + var number = numberWord.ToString(); + if (isDouble) + { + double parsedDouble; + Double.TryParse(number, NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands | NumberStyles.AllowExponent, System.Globalization.CultureInfo.InvariantCulture, out parsedDouble); + ValueType = ValueType.Double; + DoubleValue = parsedDouble; + } + else + { + long parsedInt; + if (Int64.TryParse(number, NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out parsedInt)) + { + ValueType = ValueType.Long; + LongValue = parsedInt; + return; + } + + ulong parsedULong; + if (ulong.TryParse(number, NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out parsedULong)) + { + ValueType = ValueType.ULong; + ULongValue = parsedULong; + return; + } + + Decimal parsedDecimal; + if (decimal.TryParse(number, NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture, out parsedDecimal)) + { + ValueType = ValueType.Decimal; + DecimalValue = parsedDecimal; + return; + } + } + } + + void ReadString() + { + reader.Read(); // skip ["] + + StringBuilder sb; + if (reusableBuilder == null) + { + reusableBuilder = new StringBuilder(); + sb = reusableBuilder; + } + else + { + sb = reusableBuilder; + sb.Length = 0; // Clear + } + + while (true) + { + if (reader.Peek() == -1) throw new TinyJsonException("Invalid Json String"); + + var c = ReadChar(); + switch (c) + { + case '"': // endtoken + goto END; + case '\\': // escape character + if (reader.Peek() == -1) throw new TinyJsonException("Invalid Json String"); + + c = ReadChar(); + switch (c) + { + case '"': + case '\\': + case '/': + sb.Append(c); + break; + case 'b': + sb.Append('\b'); + break; + case 'f': + sb.Append('\f'); + break; + case 'n': + sb.Append('\n'); + break; + case 'r': + sb.Append('\r'); + break; + case 't': + sb.Append('\t'); + break; + case 'u': + var hex = new char[4]; + hex[0] = ReadChar(); + hex[1] = ReadChar(); + hex[2] = ReadChar(); + hex[3] = ReadChar(); + sb.Append((char)Convert.ToInt32(new string(hex), 16)); + break; + } + break; + default: // string + sb.Append(c); + break; + } + } + + END: + ValueType = ValueType.String; + StringValue = sb.ToString(); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Internal/UnsafeMemory.tt b/src/Datadog.Trace/Vendors/MessagePack/Internal/UnsafeMemory.tt new file mode 100644 index 0000000000..cc5037998f --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Internal/UnsafeMemory.tt @@ -0,0 +1,67 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var Max = 31; +#> +#if NETSTANDARD || NETFRAMEWORK + +using System.Runtime.CompilerServices; + +namespace MessagePack.Internal +{ + public static partial class UnsafeMemory32 + { +<# for(var i = 4; i <= Max; i++) { #> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe int WriteRaw<#= i #>(ref byte[] dst, int dstOffset, byte[] src) + { + MessagePackBinary.EnsureCapacity(ref dst, dstOffset, src.Length); + + fixed (byte* pSrc = &src[0]) + fixed (byte* pDst = &dst[dstOffset]) + { +<# for(var j = 0; j < (i / 4); j++) { #> + *(int*)(pDst + <#= (4 * j) #>) = *(int*)(pSrc + <#= (4 * j) #>); +<# } #> +<# if(i % 4 != 0) { #> + *(int*)(pDst + <#= i - 4 #>) = *(int*)(pSrc + <#= (i - 4) #>); +<# } #> + } + + return src.Length; + } + +<# } #> + } + + public static partial class UnsafeMemory64 + { +<# for(var i = 8; i <= Max; i++) { #> + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe int WriteRaw<#= i #>(ref byte[] dst, int dstOffset, byte[] src) + { + MessagePackBinary.EnsureCapacity(ref dst, dstOffset, src.Length); + + fixed (byte* pSrc = &src[0]) + fixed (byte* pDst = &dst[dstOffset]) + { +<# for(var j = 0; j < (i / 8); j++) { #> + *(long*)(pDst + <#= (8 * j) #>) = *(long*)(pSrc + <#= (8 * j) #>); +<# } #> +<# if(i % 8 != 0) { #> + *(long*)(pDst + <#= i - 8 #>) = *(long*)(pSrc + <#= (i - 8) #>); +<# } #> + } + + return src.Length; + } + +<# } #> + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Helper.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Helper.cs new file mode 100644 index 0000000000..6041c02c43 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Helper.cs @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + // use 'Safe' code for Unity because in IL2CPP gots strange behaviour. + + public static int Encode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength) + { + if (IntPtr.Size == 4) + { + return LZ4Codec.Encode32Safe(input, inputOffset, inputLength, output, outputOffset, outputLength); + } + else + { + return LZ4Codec.Encode64Safe(input, inputOffset, inputLength, output, outputOffset, outputLength); + } + } + + public static int Decode(byte[] input, int inputOffset, int inputLength, byte[] output, int outputOffset, int outputLength) + { + if (IntPtr.Size == 4) + { + return LZ4Codec.Decode32Safe(input, inputOffset, inputLength, output, outputOffset, outputLength); + } + else + { + return LZ4Codec.Decode64Safe(input, inputOffset, inputLength, output, outputOffset, outputLength); + } + } + + internal static class HashTablePool + { + [ThreadStatic] + static ushort[] ushortPool; + + [ThreadStatic] + static uint[] uintPool; + + [ThreadStatic] + static int[] intPool; + + public static ushort[] GetUShortHashTablePool() + { + if (ushortPool == null) + { + ushortPool = new ushort[HASH64K_TABLESIZE]; + } + else + { + Array.Clear(ushortPool, 0, ushortPool.Length); + } + return ushortPool; + } + + public static uint[] GetUIntHashTablePool() + { + if (uintPool == null) + { + uintPool = new uint[HASH_TABLESIZE]; + } + else + { + Array.Clear(uintPool, 0, uintPool.Length); + } + return uintPool; + } + + public static int[] GetIntHashTablePool() + { + if (intPool == null) + { + intPool = new int[HASH_TABLESIZE]; + } + else + { + Array.Clear(intPool, 0, intPool.Length); + } + return intPool; + } + } + } +} + diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe.cs new file mode 100644 index 0000000000..9f9464bf0a --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe.cs @@ -0,0 +1,441 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#region license + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +using System; +using System.Diagnostics; + +// ReSharper disable CheckNamespace +// ReSharper disable InconsistentNaming + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + /// Safe LZ4 codec. + internal static partial class LZ4Codec + { + #region Helper + + // ReSharper disable UnusedParameter.Local + + [Conditional("DEBUG")] + private static void Assert(bool condition, string errorMessage) + { + if (!condition) throw new ArgumentException(errorMessage); + Debug.Assert(condition, errorMessage); + } + + // ReSharper restore UnusedParameter.Local + + #endregion + + #region Byte manipulation + + // ReSharper disable RedundantCast + + internal static void Poke2(byte[] buffer, int offset, ushort value) + { + buffer[offset] = (byte)value; + buffer[offset + 1] = (byte)(value >> 8); + } + + internal static ushort Peek2(byte[] buffer, int offset) + { + // NOTE: It's faster than BitConverter.ToUInt16 (suprised? me too) + return (ushort)(((uint)buffer[offset]) | ((uint)buffer[offset + 1] << 8)); + } + + internal static uint Peek4(byte[] buffer, int offset) + { + // NOTE: It's faster than BitConverter.ToUInt32 (suprised? me too) + return + ((uint)buffer[offset]) | + ((uint)buffer[offset + 1] << 8) | + ((uint)buffer[offset + 2] << 16) | + ((uint)buffer[offset + 3] << 24); + } + + private static uint Xor4(byte[] buffer, int offset1, int offset2) + { + // return Peek4(buffer, offset1) ^ Peek4(buffer, offset2); + var value1 = + ((uint)buffer[offset1]) | + ((uint)buffer[offset1 + 1] << 8) | + ((uint)buffer[offset1 + 2] << 16) | + ((uint)buffer[offset1 + 3] << 24); + var value2 = + ((uint)buffer[offset2]) | + ((uint)buffer[offset2 + 1] << 8) | + ((uint)buffer[offset2 + 2] << 16) | + ((uint)buffer[offset2 + 3] << 24); + return value1 ^ value2; + } + + private static ulong Xor8(byte[] buffer, int offset1, int offset2) + { + // return Peek8(buffer, offset1) ^ Peek8(buffer, offset2); + var value1 = + ((ulong)buffer[offset1]) | + ((ulong)buffer[offset1 + 1] << 8) | + ((ulong)buffer[offset1 + 2] << 16) | + ((ulong)buffer[offset1 + 3] << 24) | + ((ulong)buffer[offset1 + 4] << 32) | + ((ulong)buffer[offset1 + 5] << 40) | + ((ulong)buffer[offset1 + 6] << 48) | + ((ulong)buffer[offset1 + 7] << 56); + var value2 = + ((ulong)buffer[offset2]) | + ((ulong)buffer[offset2 + 1] << 8) | + ((ulong)buffer[offset2 + 2] << 16) | + ((ulong)buffer[offset2 + 3] << 24) | + ((ulong)buffer[offset2 + 4] << 32) | + ((ulong)buffer[offset2 + 5] << 40) | + ((ulong)buffer[offset2 + 6] << 48) | + ((ulong)buffer[offset2 + 7] << 56); + return value1 ^ value2; + } + + private static bool Equal2(byte[] buffer, int offset1, int offset2) + { + // return Peek2(buffer, offset1) == Peek2(buffer, offset2); + if (buffer[offset1] != buffer[offset2]) return false; + return buffer[offset1 + 1] == buffer[offset2 + 1]; + } + + private static bool Equal4(byte[] buffer, int offset1, int offset2) + { + // return Peek4(buffer, offset1) == Peek4(buffer, offset2); + if (buffer[offset1] != buffer[offset2]) return false; + if (buffer[offset1 + 1] != buffer[offset2 + 1]) return false; + if (buffer[offset1 + 2] != buffer[offset2 + 2]) return false; + return buffer[offset1 + 3] == buffer[offset2 + 3]; + } + + // ReSharper restore RedundantCast + + #endregion + + #region Byte block copy + + private static void Copy4(byte[] buf, int src, int dst) + { + Assert(dst > src, "Copying backwards is not implemented"); + buf[dst + 3] = buf[src + 3]; + buf[dst + 2] = buf[src + 2]; + buf[dst + 1] = buf[src + 1]; + buf[dst] = buf[src]; + } + + private static void Copy8(byte[] buf, int src, int dst) + { + Assert(dst > src, "Copying backwards is not implemented"); + buf[dst + 7] = buf[src + 7]; + buf[dst + 6] = buf[src + 6]; + buf[dst + 5] = buf[src + 5]; + buf[dst + 4] = buf[src + 4]; + buf[dst + 3] = buf[src + 3]; + buf[dst + 2] = buf[src + 2]; + buf[dst + 1] = buf[src + 1]; + buf[dst] = buf[src]; + } + + private static void BlockCopy(byte[] src, int src_0, byte[] dst, int dst_0, int len) + { + Assert(src != dst, "BlockCopy does not handle copying to the same buffer"); + + if (len >= BLOCK_COPY_LIMIT) + { + Buffer.BlockCopy(src, src_0, dst, dst_0, len); + } + else + { + while (len >= 8) + { + dst[dst_0] = src[src_0]; + dst[dst_0 + 1] = src[src_0 + 1]; + dst[dst_0 + 2] = src[src_0 + 2]; + dst[dst_0 + 3] = src[src_0 + 3]; + dst[dst_0 + 4] = src[src_0 + 4]; + dst[dst_0 + 5] = src[src_0 + 5]; + dst[dst_0 + 6] = src[src_0 + 6]; + dst[dst_0 + 7] = src[src_0 + 7]; + len -= 8; + src_0 += 8; + dst_0 += 8; + } + + while (len >= 4) + { + dst[dst_0] = src[src_0]; + dst[dst_0 + 1] = src[src_0 + 1]; + dst[dst_0 + 2] = src[src_0 + 2]; + dst[dst_0 + 3] = src[src_0 + 3]; + len -= 4; + src_0 += 4; + dst_0 += 4; + } + + while (len-- > 0) + { + dst[dst_0++] = src[src_0++]; + } + } + } + + private static int WildCopy(byte[] src, int src_0, byte[] dst, int dst_0, int dst_end) + { + var len = dst_end - dst_0; + + Assert(src != dst, "BlockCopy does not handle copying to the same buffer"); + Assert(len > 0, "Length have to be greater than 0"); + + if (len >= BLOCK_COPY_LIMIT) + { + Buffer.BlockCopy(src, src_0, dst, dst_0, len); + } + else + { + // apparently (tested) this is an overkill + // it seems to be faster without this 8-byte loop + //while (len >= 8) + //{ + // dst[dst_0] = src[src_0]; + // dst[dst_0 + 1] = src[src_0 + 1]; + // dst[dst_0 + 2] = src[src_0 + 2]; + // dst[dst_0 + 3] = src[src_0 + 3]; + // dst[dst_0 + 4] = src[src_0 + 4]; + // dst[dst_0 + 5] = src[src_0 + 5]; + // dst[dst_0 + 6] = src[src_0 + 6]; + // dst[dst_0 + 7] = src[src_0 + 7]; + // len -= 8; src_0 += 8; dst_0 += 8; + //} + + while (len >= 4) + { + dst[dst_0] = src[src_0]; + dst[dst_0 + 1] = src[src_0 + 1]; + dst[dst_0 + 2] = src[src_0 + 2]; + dst[dst_0 + 3] = src[src_0 + 3]; + len -= 4; + src_0 += 4; + dst_0 += 4; + } + + while (len-- > 0) + { + dst[dst_0++] = src[src_0++]; + } + } + + return len; + } + + private static int SecureCopy(byte[] buffer, int src, int dst, int dst_end) + { + var diff = dst - src; + var length = dst_end - dst; + var len = length; + + Assert(diff >= 4, "Target must be at least 4 bytes further than source"); + Assert(BLOCK_COPY_LIMIT > 4, "This method requires BLOCK_COPY_LIMIT > 4"); + Assert(len > 0, "Length have to be greater than 0"); + + if (diff >= BLOCK_COPY_LIMIT) + { + if (diff >= length) + { + Buffer.BlockCopy(buffer, src, buffer, dst, length); + return length; // done + } + + do + { + Buffer.BlockCopy(buffer, src, buffer, dst, diff); + src += diff; + dst += diff; + len -= diff; + } while (len >= diff); + } + + // apparently (tested) this is an overkill + // it seems to be faster without this 8-byte loop + //while (len >= 8) + //{ + // buffer[dst] = buffer[src]; + // buffer[dst + 1] = buffer[src + 1]; + // buffer[dst + 2] = buffer[src + 2]; + // buffer[dst + 3] = buffer[src + 3]; + // buffer[dst + 4] = buffer[src + 4]; + // buffer[dst + 5] = buffer[src + 5]; + // buffer[dst + 6] = buffer[src + 6]; + // buffer[dst + 7] = buffer[src + 7]; + // dst += 8; src += 8; len -= 8; + //} + + while (len >= 4) + { + buffer[dst] = buffer[src]; + buffer[dst + 1] = buffer[src + 1]; + buffer[dst + 2] = buffer[src + 2]; + buffer[dst + 3] = buffer[src + 3]; + dst += 4; + src += 4; + len -= 4; + } + + while (len-- > 0) + { + buffer[dst++] = buffer[src++]; + } + + return length; // done + } + + #endregion + + /// Encodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static int Encode32Safe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength); + if (outputLength == 0) return 0; + + if (inputLength < LZ4_64KLIMIT) + { + var hashTable = HashTablePool.GetUShortHashTablePool(); + return LZ4_compress64kCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength); + } + else + { + var hashTable = HashTablePool.GetIntHashTablePool(); + return LZ4_compressCtx_safe32(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength); + } + } + + /// Encodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static int Encode64Safe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength); + if (outputLength == 0) return 0; + + if (inputLength < LZ4_64KLIMIT) + { + var hashTable = HashTablePool.GetUShortHashTablePool(); + return LZ4_compress64kCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength); + } + else + { + var hashTable = HashTablePool.GetIntHashTablePool(); + return LZ4_compressCtx_safe64(hashTable, input, output, inputOffset, outputOffset, inputLength, outputLength); + } + } + + /// Decodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static int Decode32Safe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + var length = LZ4_uncompress_safe32(input, output, inputOffset, outputOffset, outputLength); + if (length != inputLength) + throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given."); + return outputLength; + } + + /// Decodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static int Decode64Safe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments( + input, inputOffset, inputLength, + output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + var length = LZ4_uncompress_safe64(input, output, inputOffset, outputOffset, outputLength); + if (length != inputLength) + throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given."); + return outputLength; + } + } +} + +// ReSharper restore InconsistentNaming +// ReSharper restore CheckNamespace \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe32.Dirty.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe32.Dirty.cs new file mode 100644 index 0000000000..6bb877da04 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe32.Dirty.cs @@ -0,0 +1,669 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#region LZ4 original + +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2012, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + + You can contact the author at : + - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + - LZ4 source repository : http://code.google.com/p/lz4/ +*/ + +#endregion + +#region LZ4 port + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +// ReSharper disable CheckNamespace +// ReSharper disable InconsistentNaming +// ReSharper disable TooWideLocalVariableScope +// ReSharper disable JoinDeclarationAndInitializer +// ReSharper disable RedundantIfElseBlock + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + #region LZ4_compressCtx + + private static int LZ4_compressCtx_safe32( + int[] hash_table, + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int src_len, + int dst_maxlen) + { + unchecked + { + var debruijn32 = DEBRUIJN_TABLE_32; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + var src_base = src_0; + var src_anchor = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst_0; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + hash_table[(((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST)] = (src_p - src_base); + src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + int src_ref; + int dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (src_p - src_base); + } while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p))); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + var len = length - RUN_MASK; + dst[dst_token] = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + dst[dst_p++] = 255; + len -= 255; + } while (len > 254); + dst[dst_p++] = (byte)len; + BlockCopy(src, src_anchor, dst, dst_p, length); + dst_p += length; + goto _next_match; + } + else + dst[dst_p++] = (byte)len; + } + else + { + dst[dst_token] = (byte)(length << ML_BITS); + } + + // Copy Literals + if (length > 0) + { + _i = dst_p + length; + WildCopy(src, src_anchor, dst, dst_p, _i); + dst_p = _i; + } + + _next_match: + // Encode Offset + Poke2(dst, dst_p, (ushort)(src_p - src_ref)); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch already verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (int)Xor4(src, src_ref, src_p); + if (diff == 0) + { + src_p += STEPSIZE_32; + src_ref += STEPSIZE_32; + continue; + } + src_p += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++; + + _endCount: + // Encode MatchLength + length = (src_p - src_anchor); + + if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (length >= ML_MASK) + { + dst[dst_token] += ML_MASK; + length -= ML_MASK; + for (; length > 509; length -= 510) + { + dst[dst_p++] = 255; + dst[dst_p++] = 255; + } + if (length > 254) + { + length -= 255; + dst[dst_p++] = 255; + } + dst[dst_p++] = (byte)length; + } + else + { + dst[dst_token] += (byte)length; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH_ADJUST)] = (src_p - 2 - src_base); + + // Test next position + + h = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (src_p - src_base); + + if ((src_ref > src_p - (MAX_DISTANCE + 1)) && (Equal4(src, src_ref, src_p))) + { + dst_token = dst_p++; + dst[dst_token] = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + } + + _last_literals: + // Encode Last Literals + { + var lastRun = (src_end - src_anchor); + + if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0; + + if (lastRun >= RUN_MASK) + { + dst[dst_p++] = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255; + dst[dst_p++] = (byte)lastRun; + } + else dst[dst_p++] = (byte)(lastRun << ML_BITS); + BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor); + dst_p += src_end - src_anchor; + } + + // End + return ((dst_p) - dst_0); + } + } + + #endregion + + #region LZ4_compress64kCtx + + private static int LZ4_compress64kCtx_safe32( + ushort[] hash_table, + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int src_len, + int dst_maxlen) + { + unchecked + { + var debruijn32 = DEBRUIJN_TABLE_32; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + var src_anchor = src_p; + var src_base = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst_0; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int len, length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + int src_ref; + int dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + } while (!Equal4(src, src_ref, src_p)); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + len = length - RUN_MASK; + dst[dst_token] = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + dst[dst_p++] = 255; + len -= 255; + } while (len > 254); + dst[dst_p++] = (byte)len; + BlockCopy(src, src_anchor, dst, dst_p, length); + dst_p += length; + goto _next_match; + } + else + { + dst[dst_p++] = (byte)len; + } + } + else + { + dst[dst_token] = (byte)(length << ML_BITS); + } + + // Copy Literals + if (length > 0) + { + _i = dst_p + length; + WildCopy(src, src_anchor, dst, dst_p, _i); + dst_p = _i; + } + + _next_match: + // Encode Offset + Poke2(dst, dst_p, (ushort)(src_p - src_ref)); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (int)Xor4(src, src_ref, src_p); + if (diff == 0) + { + src_p += STEPSIZE_32; + src_ref += STEPSIZE_32; + continue; + } + src_p += debruijn32[((uint)((diff) & -(diff)) * 0x077CB531u) >> 27]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++; + + _endCount: + + // Encode MatchLength + len = (src_p - src_anchor); + + if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (len >= ML_MASK) + { + dst[dst_token] += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) + { + dst[dst_p++] = 255; + dst[dst_p++] = 255; + } + if (len > 254) + { + len -= 255; + dst[dst_p++] = 255; + } + dst[dst_p++] = (byte)len; + } + else + { + dst[dst_token] += (byte)len; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base); + + // Test next position + + h = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + + if (Equal4(src, src_ref, src_p)) + { + dst_token = dst_p++; + dst[dst_token] = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + } + + _last_literals: + // Encode Last Literals + var lastRun = (src_end - src_anchor); + if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0; + if (lastRun >= RUN_MASK) + { + dst[dst_p++] = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255; + dst[dst_p++] = (byte)lastRun; + } + else + { + dst[dst_p++] = (byte)(lastRun << ML_BITS); + } + BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor); + dst_p += src_end - src_anchor; + + // End + return ((dst_p) - dst_0); + } + } + + #endregion + + #region LZ4_uncompress + + private static int LZ4_uncompress_safe32( + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int dst_len) + { + unchecked + { + var dec32table = DECODER_TABLE_32; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + int dst_ref; + + var dst_p = dst_0; + var dst_end = dst_p + dst_len; + int dst_cpy; + + var dst_LASTLITERALS = dst_end - LASTLITERALS; + var dst_COPYLENGTH = dst_end - COPYLENGTH; + var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_32 - 4); + + byte token; + + // Main Loop + while (true) + { + int length; + + // get runlength + token = src[src_p++]; + if ((length = (token >> ML_BITS)) == RUN_MASK) + { + int len; + for (; (len = src[src_p++]) == 255; length += 255) + { + /* do nothing */ + } + length += len; + } + + // copy literals + dst_cpy = dst_p + length; + + if (dst_cpy > dst_COPYLENGTH) + { + if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals + BlockCopy(src, src_p, dst, dst_p, length); + src_p += length; + break; // EOF + } + if (dst_p < dst_cpy) + { + _i = WildCopy(src, src_p, dst, dst_p, dst_cpy); + src_p += _i; + dst_p += _i; + } + src_p -= (dst_p - dst_cpy); + dst_p = dst_cpy; + + // get offset + dst_ref = (dst_cpy) - Peek2(src, src_p); + src_p += 2; + if (dst_ref < dst_0) goto _output_error; // Error : offset outside destination buffer + + // get matchlength + if ((length = (token & ML_MASK)) == ML_MASK) + { + for (; src[src_p] == 255; length += 255) src_p++; + length += src[src_p++]; + } + + // copy repeated sequence + if ((dst_p - dst_ref) < STEPSIZE_32) + { + const int dec64 = 0; + dst[dst_p + 0] = dst[dst_ref + 0]; + dst[dst_p + 1] = dst[dst_ref + 1]; + dst[dst_p + 2] = dst[dst_ref + 2]; + dst[dst_p + 3] = dst[dst_ref + 3]; + dst_p += 4; + dst_ref += 4; + dst_ref -= dec32table[dst_p - dst_ref]; + Copy4(dst, dst_ref, dst_p); + dst_p += STEPSIZE_32 - 4; + dst_ref -= dec64; + } + else + { + Copy4(dst, dst_ref, dst_p); + dst_p += 4; + dst_ref += 4; + } + dst_cpy = dst_p + length - (STEPSIZE_32 - 4); + + if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4) + { + if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals + if (dst_p < dst_COPYLENGTH) + { + _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH); + dst_ref += _i; + dst_p += _i; + } + + while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++]; + dst_p = dst_cpy; + continue; + } + + if (dst_p < dst_cpy) + { + SecureCopy(dst, dst_ref, dst_p, dst_cpy); + } + dst_p = dst_cpy; // correction + } + + // end of decoding + return ((src_p) - src_0); + + // write overflow error detected + _output_error: + return (-((src_p) - src_0)); + } + } + + #endregion + } +} + +// ReSharper restore RedundantIfElseBlock +// ReSharper restore JoinDeclarationAndInitializer +// ReSharper restore TooWideLocalVariableScope +// ReSharper restore InconsistentNaming +// ReSharper restore CheckNamespace \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe64.Dirty.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe64.Dirty.cs new file mode 100644 index 0000000000..de75db4f17 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Safe64.Dirty.cs @@ -0,0 +1,682 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#region LZ4 original + +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2012, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + + You can contact the author at : + - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + - LZ4 source repository : http://code.google.com/p/lz4/ +*/ + +#endregion + +#region LZ4 port + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +// ReSharper disable CheckNamespace +// ReSharper disable InconsistentNaming +// ReSharper disable TooWideLocalVariableScope +// ReSharper disable JoinDeclarationAndInitializer +// ReSharper disable RedundantIfElseBlock + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + #region LZ4_compressCtx + + private static int LZ4_compressCtx_safe64( + int[] hash_table, + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int src_len, + int dst_maxlen) + { + unchecked + { + var debruijn64 = DEBRUIJN_TABLE_64; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + var src_base = src_0; + var src_anchor = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst_0; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_3 = src_LASTLITERALS - 3; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + hash_table[(((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST)] = (src_p - src_base); + src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + int src_ref; + int dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (src_p - src_base); + } while ((src_ref < src_p - MAX_DISTANCE) || (!Equal4(src, src_ref, src_p))); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + var len = length - RUN_MASK; + dst[dst_token] = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + dst[dst_p++] = 255; + len -= 255; + } while (len > 254); + dst[dst_p++] = (byte)len; + BlockCopy(src, src_anchor, dst, dst_p, length); + dst_p += length; + goto _next_match; + } + else + dst[dst_p++] = (byte)len; + } + else + { + dst[dst_token] = (byte)(length << ML_BITS); + } + + // Copy Literals + if (length > 0) + { + _i = dst_p + length; + WildCopy(src, src_anchor, dst, dst_p, _i); + dst_p = _i; + } + + _next_match: + // Encode Offset + Poke2(dst, dst_p, (ushort)(src_p - src_ref)); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch already verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (long)Xor8(src, src_ref, src_p); + if (diff == 0) + { + src_p += STEPSIZE_64; + src_ref += STEPSIZE_64; + continue; + } + src_p += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_3) && (Equal4(src, src_ref, src_p))) + { + src_p += 4; + src_ref += 4; + } + if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++; + + _endCount: + // Encode MatchLength + length = (src_p - src_anchor); + + if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (length >= ML_MASK) + { + dst[dst_token] += ML_MASK; + length -= ML_MASK; + for (; length > 509; length -= 510) + { + dst[dst_p++] = 255; + dst[dst_p++] = 255; + } + if (length > 254) + { + length -= 255; + dst[dst_p++] = 255; + } + dst[dst_p++] = (byte)length; + } + else + { + dst[dst_token] += (byte)length; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH_ADJUST)] = (src_p - 2 - src_base); + + // Test next position + + h = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (src_p - src_base); + + if ((src_ref > src_p - (MAX_DISTANCE + 1)) && (Equal4(src, src_ref, src_p))) + { + dst_token = dst_p++; + dst[dst_token] = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH_ADJUST); + } + + _last_literals: + // Encode Last Literals + { + var lastRun = (src_end - src_anchor); + + if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0; + + if (lastRun >= RUN_MASK) + { + dst[dst_p++] = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255; + dst[dst_p++] = (byte)lastRun; + } + else dst[dst_p++] = (byte)(lastRun << ML_BITS); + BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor); + dst_p += src_end - src_anchor; + } + + // End + return (dst_p - dst_0); + } + } + + #endregion + + #region LZ4_compress64kCtx + + private static int LZ4_compress64kCtx_safe64( + ushort[] hash_table, + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int src_len, + int dst_maxlen) + { + unchecked + { + var debruijn64 = DEBRUIJN_TABLE_64; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + var src_anchor = src_p; + var src_base = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst_0; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_3 = src_LASTLITERALS - 3; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int len, length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + int src_ref; + int dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = (((Peek4(src, src_p_fwd)) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + } while (!Equal4(src, src_ref, src_p)); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src_0) && (src[src_p - 1] == src[src_ref - 1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + len = length - RUN_MASK; + dst[dst_token] = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + dst[dst_p++] = 255; + len -= 255; + } while (len > 254); + dst[dst_p++] = (byte)len; + BlockCopy(src, src_anchor, dst, dst_p, length); + dst_p += length; + goto _next_match; + } + else + dst[dst_p++] = (byte)len; + } + else + { + dst[dst_token] = (byte)(length << ML_BITS); + } + + // Copy Literals + if (length > 0) /*?*/ + { + _i = dst_p + length; + WildCopy(src, src_anchor, dst, dst_p, _i); + dst_p = _i; + } + + _next_match: + // Encode Offset + Poke2(dst, dst_p, (ushort)(src_p - src_ref)); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (long)Xor8(src, src_ref, src_p); + if (diff == 0) + { + src_p += STEPSIZE_64; + src_ref += STEPSIZE_64; + continue; + } + src_p += debruijn64[((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL) >> 58]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_3) && (Equal4(src, src_ref, src_p))) + { + src_p += 4; + src_ref += 4; + } + if ((src_p < src_LASTLITERALS_1) && (Equal2(src, src_ref, src_p))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (src[src_ref] == src[src_p])) src_p++; + + _endCount: + + // Encode MatchLength + len = (src_p - src_anchor); + + if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (len >= ML_MASK) + { + dst[dst_token] += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) + { + dst[dst_p++] = 255; + dst[dst_p++] = 255; + } + if (len > 254) + { + len -= 255; + dst[dst_p++] = 255; + } + dst[dst_p++] = (byte)len; + } + else + { + dst[dst_token] += (byte)len; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[(((Peek4(src, src_p - 2)) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base); + + // Test next position + + h = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + + if (Equal4(src, src_ref, src_p)) + { + dst_token = dst_p++; + dst[dst_token] = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = (((Peek4(src, src_p)) * 2654435761u) >> HASH64K_ADJUST); + } + + _last_literals: + // Encode Last Literals + { + var lastRun = (src_end - src_anchor); + if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0; + if (lastRun >= RUN_MASK) + { + dst[dst_p++] = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) dst[dst_p++] = 255; + dst[dst_p++] = (byte)lastRun; + } + else dst[dst_p++] = (byte)(lastRun << ML_BITS); + BlockCopy(src, src_anchor, dst, dst_p, src_end - src_anchor); + dst_p += src_end - src_anchor; + } + + // End + return (dst_p - dst_0); + } + } + + #endregion + + #region LZ4_uncompress + + private static int LZ4_uncompress_safe64( + byte[] src, + byte[] dst, + int src_0, + int dst_0, + int dst_len) + { + unchecked + { + var dec32table = DECODER_TABLE_32; + var dec64table = DECODER_TABLE_64; + int _i; + + // ---- preprocessed source start here ---- + // r93 + var src_p = src_0; + int dst_ref; + + var dst_p = dst_0; + var dst_end = dst_p + dst_len; + int dst_cpy; + + var dst_LASTLITERALS = dst_end - LASTLITERALS; + var dst_COPYLENGTH = dst_end - COPYLENGTH; + var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_64 - 4); + + uint token; + + // Main Loop + while (true) + { + int length; + + // get runlength + token = src[src_p++]; + if ((length = (byte)(token >> ML_BITS)) == RUN_MASK) + { + int len; + for (; (len = src[src_p++]) == 255; length += 255) + { + /* do nothing */ + } + length += len; + } + + // copy literals + dst_cpy = dst_p + length; + + if (dst_cpy > dst_COPYLENGTH) + { + if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals + BlockCopy(src, src_p, dst, dst_p, length); + src_p += length; + break; // EOF + } + if (dst_p < dst_cpy) /*?*/ + { + _i = WildCopy(src, src_p, dst, dst_p, dst_cpy); + src_p += _i; + dst_p += _i; + } + src_p -= (dst_p - dst_cpy); + dst_p = dst_cpy; + + // get offset + dst_ref = (dst_cpy) - Peek2(src, src_p); + src_p += 2; + if (dst_ref < dst_0) goto _output_error; // Error : offset outside destination buffer + + // get matchlength + if ((length = (byte)(token & ML_MASK)) == ML_MASK) + { + for (; src[src_p] == 255; length += 255) src_p++; + length += src[src_p++]; + } + + // copy repeated sequence + if ((dst_p - dst_ref) < STEPSIZE_64) + { + var dec64 = dec64table[dst_p - dst_ref]; + + dst[dst_p + 0] = dst[dst_ref + 0]; + dst[dst_p + 1] = dst[dst_ref + 1]; + dst[dst_p + 2] = dst[dst_ref + 2]; + dst[dst_p + 3] = dst[dst_ref + 3]; + dst_p += 4; + dst_ref += 4; + dst_ref -= dec32table[dst_p - dst_ref]; + Copy4(dst, dst_ref, dst_p); + dst_p += STEPSIZE_64 - 4; + dst_ref -= dec64; + } + else + { + Copy8(dst, dst_ref, dst_p); + dst_p += 8; + dst_ref += 8; + } + dst_cpy = dst_p + length - (STEPSIZE_64 - 4); + + if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4) + { + if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals + if (dst_p < dst_COPYLENGTH) + { + _i = SecureCopy(dst, dst_ref, dst_p, dst_COPYLENGTH); + dst_ref += _i; + dst_p += _i; + } + + while (dst_p < dst_cpy) dst[dst_p++] = dst[dst_ref++]; + dst_p = dst_cpy; + continue; + } + + if (dst_p < dst_cpy) + { + SecureCopy(dst, dst_ref, dst_p, dst_cpy); + } + dst_p = dst_cpy; // correction + } + + // end of decoding + return ((src_p) - src_0); + + _output_error: + // write overflow error detected + return (-((src_p) - src_0)); + } + } + + #endregion + } +} + +// ReSharper restore RedundantIfElseBlock +// ReSharper restore JoinDeclarationAndInitializer +// ReSharper restore TooWideLocalVariableScope +// ReSharper restore InconsistentNaming +// ReSharper restore CheckNamespace \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe.cs new file mode 100644 index 0000000000..e18c35f82a --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe.cs @@ -0,0 +1,226 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if ENABLE_UNSAFE_MSGPACK + +#region license + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +using System; + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + /// Unsafe LZ4 codec. + internal static partial class LZ4Codec + { + /// Copies block of memory. + /// The source. + /// The destination. + /// The length (in bytes). + private static unsafe void BlockCopy(byte* src, byte* dst, int len) + { + while (len >= 8) + { + *(ulong*)dst = *(ulong*)src; + dst += 8; + src += 8; + len -= 8; + } + if (len >= 4) + { + *(uint*)dst = *(uint*)src; + dst += 4; + src += 4; + len -= 4; + } + if (len >= 2) + { + *(ushort*)dst = *(ushort*)src; + dst += 2; + src += 2; + len -= 2; + } + if (len >= 1) + { + *dst = *src; /* d++; s++; l--; */ + } + } + + /// Encodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static unsafe int Encode32Unsafe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments(input, inputOffset, inputLength, output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + fixed (byte* inputPtr = &input[inputOffset]) + fixed (byte* outputPtr = &output[outputOffset]) + { + if (inputLength < LZ4_64KLIMIT) + { + var uHashTable = HashTablePool.GetUShortHashTablePool(); + fixed (ushort* hash1 = &uHashTable[0]) + { + return LZ4_compress64kCtx_32(hash1, inputPtr, outputPtr, inputLength, outputLength); + } + } + else + { + var bHashTable = HashTablePool.GetUIntHashTablePool(); + fixed (uint* hash2 = &bHashTable[0]) + { + return LZ4_compressCtx_32(hash2, inputPtr, outputPtr, inputLength, outputLength); + } + } + } + } + + /// Decodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static unsafe int Decode32Unsafe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments( + input, inputOffset, inputLength, + output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + fixed (byte* inputPtr = &input[inputOffset]) + fixed (byte* outputPtr = &output[outputOffset]) + { + var length = LZ4_uncompress_32(inputPtr, outputPtr, outputLength); + if (length != inputLength) + throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given."); + return outputLength; + } + } + + /// Encodes the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static unsafe int Encode64Unsafe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments( + input, inputOffset, inputLength, + output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + fixed (byte* inputPtr = &input[inputOffset]) + fixed (byte* outputPtr = &output[outputOffset]) + { + if (inputLength < LZ4_64KLIMIT) + { + var uHashTable = HashTablePool.GetUShortHashTablePool(); + fixed (ushort* h1 = &uHashTable[0]) + { + return LZ4_compress64kCtx_64(h1, inputPtr, outputPtr, inputLength, outputLength); + } + } + else + { + var uiHashTable = HashTablePool.GetUIntHashTablePool(); + fixed (uint* h2 = &uiHashTable[0]) + { + return LZ4_compressCtx_64(h2, inputPtr, outputPtr, inputLength, outputLength); + } + } + } + } + + /// Decode64s the specified input. + /// The input. + /// The input offset. + /// Length of the input. + /// The output. + /// The output offset. + /// Length of the output. + /// Number of bytes written. + public static unsafe int Decode64Unsafe( + byte[] input, + int inputOffset, + int inputLength, + byte[] output, + int outputOffset, + int outputLength) + { + CheckArguments( + input, inputOffset, inputLength, + output, outputOffset, outputLength); + + if (outputLength == 0) return 0; + + fixed (byte* inputPtr = &input[inputOffset]) + fixed (byte* outputPtr = &output[outputOffset]) + { + var length = LZ4_uncompress_64(inputPtr, outputPtr, outputLength); + if (length != inputLength) + throw new ArgumentException("LZ4 block is corrupted, or invalid length has been given."); + return outputLength; + } + } + } +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe32.Dirty.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe32.Dirty.cs new file mode 100644 index 0000000000..a54811ee82 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe32.Dirty.cs @@ -0,0 +1,684 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if ENABLE_UNSAFE_MSGPACK + +#region LZ4 original + +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2012, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + + You can contact the author at : + - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + - LZ4 source repository : http://code.google.com/p/lz4/ +*/ + +#endregion + +#region LZ4 port + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +// ReSharper disable InconsistentNaming +// ReSharper disable TooWideLocalVariableScope +// ReSharper disable JoinDeclarationAndInitializer + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + #region LZ4_compressCtx_32 + + private static unsafe int LZ4_compressCtx_32( + uint* hash_table, + byte* src, + byte* dst, + int src_len, + int dst_maxlen) + { + unchecked + { + byte* _p; + + fixed (int* debruijn32 = &DEBRUIJN_TABLE_32[0]) + { + // r93 + var src_p = src; + var src_base = src_p; + var src_anchor = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + hash_table[((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST)] = (uint)(src_p - src_base); + src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + byte* xxx_ref; + byte* xxx_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = ((((*(uint*)(src_p_fwd))) * 2654435761u) >> HASH_ADJUST); + xxx_ref = src_base + hash_table[h]; + hash_table[h] = (uint)(src_p - src_base); + } while ((xxx_ref < src_p - MAX_DISTANCE) || ((*(uint*)(xxx_ref)) != (*(uint*)(src_p)))); + + // Catch up + while ((src_p > src_anchor) && (xxx_ref > src) && (src_p[-1] == xxx_ref[-1])) + { + src_p--; + xxx_ref--; + } + + // Encode Literal length + length = (int)(src_p - src_anchor); + xxx_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + var len = length - RUN_MASK; + *xxx_token = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + *dst_p++ = 255; + len -= 255; + } while (len > 254); + *dst_p++ = (byte)len; + BlockCopy(src_anchor, dst_p, (length)); + dst_p += length; + goto _next_match; + } + *dst_p++ = (byte)len; + } + else + { + *xxx_token = (byte)(length << ML_BITS); + } + + // Copy Literals + _p = dst_p + (length); + do + { + *(uint*)dst_p = *(uint*)src_anchor; + dst_p += 4; + src_anchor += 4; + *(uint*)dst_p = *(uint*)src_anchor; + dst_p += 4; + src_anchor += 4; + } while (dst_p < _p); + dst_p = _p; + + _next_match: + + // Encode Offset + *(ushort*)dst_p = (ushort)(src_p - xxx_ref); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + xxx_ref += MINMATCH; // MinMatch already verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (*(int*)(xxx_ref)) ^ (*(int*)(src_p)); + if (diff == 0) + { + src_p += STEPSIZE_32; + xxx_ref += STEPSIZE_32; + continue; + } + src_p += debruijn32[(((uint)((diff) & -(diff)) * 0x077CB531u)) >> 27]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)(xxx_ref)) == (*(ushort*)(src_p)))) + { + src_p += 2; + xxx_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (*xxx_ref == *src_p)) src_p++; + + _endCount: + + // Encode MatchLength + length = (int)(src_p - src_anchor); + + if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (length >= ML_MASK) + { + *xxx_token += ML_MASK; + length -= ML_MASK; + for (; length > 509; length -= 510) + { + *dst_p++ = 255; + *dst_p++ = 255; + } + if (length > 254) + { + length -= 255; + *dst_p++ = 255; + } + *dst_p++ = (byte)length; + } + else + { + *xxx_token += (byte)length; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[((((*(uint*)(src_p - 2))) * 2654435761u) >> HASH_ADJUST)] = (uint)(src_p - 2 - src_base); + + // Test next position + + h = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + xxx_ref = src_base + hash_table[h]; + hash_table[h] = (uint)(src_p - src_base); + + if ((xxx_ref > src_p - (MAX_DISTANCE + 1)) && ((*(uint*)(xxx_ref)) == (*(uint*)(src_p)))) + { + xxx_token = dst_p++; + *xxx_token = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + } + + _last_literals: + + // Encode Last Literals + { + var lastRun = (int)(src_end - src_anchor); + + if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0; + + if (lastRun >= RUN_MASK) + { + *dst_p++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) *dst_p++ = 255; + *dst_p++ = (byte)lastRun; + } + else *dst_p++ = (byte)(lastRun << ML_BITS); + BlockCopy(src_anchor, dst_p, (int)(src_end - src_anchor)); + dst_p += src_end - src_anchor; + } + + // End + return (int)((dst_p) - dst); + } + } + } + + #endregion + + #region LZ4_compress64kCtx_32 + + private static unsafe int LZ4_compress64kCtx_32( + ushort* hash_table, + byte* src, + byte* dst, + int src_len, + int dst_maxlen) + { + unchecked + { + byte* _p; + fixed (int* debruijn32 = &DEBRUIJN_TABLE_32[0]) + { + // r93 + var src_p = src; + var src_anchor = src_p; + var src_base = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_32 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int len, length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + byte* xxx_ref; + byte* xxx_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = ((((*(uint*)(src_p_fwd))) * 2654435761u) >> HASH64K_ADJUST); + xxx_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + } while ((*(uint*)(xxx_ref)) != (*(uint*)(src_p))); + + // Catch up + while ((src_p > src_anchor) && (xxx_ref > src) && (src_p[-1] == xxx_ref[-1])) + { + src_p--; + xxx_ref--; + } + + // Encode Literal length + length = (int)(src_p - src_anchor); + xxx_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + len = length - RUN_MASK; + *xxx_token = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + *dst_p++ = 255; + len -= 255; + } while (len > 254); + *dst_p++ = (byte)len; + BlockCopy(src_anchor, dst_p, (length)); + dst_p += length; + goto _next_match; + } + *dst_p++ = (byte)len; + } + else + { + *xxx_token = (byte)(length << ML_BITS); + } + + // Copy Literals + _p = dst_p + (length); + do + { + *(uint*)dst_p = *(uint*)src_anchor; + dst_p += 4; + src_anchor += 4; + *(uint*)dst_p = *(uint*)src_anchor; + dst_p += 4; + src_anchor += 4; + } while (dst_p < _p); + dst_p = _p; + + _next_match: + + // Encode Offset + *(ushort*)dst_p = (ushort)(src_p - xxx_ref); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + xxx_ref += MINMATCH; // MinMatch verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (*(int*)(xxx_ref)) ^ (*(int*)(src_p)); + if (diff == 0) + { + src_p += STEPSIZE_32; + xxx_ref += STEPSIZE_32; + continue; + } + src_p += debruijn32[(((uint)((diff) & -(diff)) * 0x077CB531u)) >> 27]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)(xxx_ref)) == (*(ushort*)(src_p)))) + { + src_p += 2; + xxx_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (*xxx_ref == *src_p)) src_p++; + + _endCount: + + // Encode MatchLength + len = (int)(src_p - src_anchor); + + if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (len >= ML_MASK) + { + *xxx_token += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) + { + *dst_p++ = 255; + *dst_p++ = 255; + } + if (len > 254) + { + len -= 255; + *dst_p++ = 255; + } + *dst_p++ = (byte)len; + } + else *xxx_token += (byte)len; + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[((((*(uint*)(src_p - 2))) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base); + + // Test next position + + h = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + xxx_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + + if ((*(uint*)(xxx_ref)) == (*(uint*)(src_p))) + { + xxx_token = dst_p++; + *xxx_token = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + } + + _last_literals: + + // Encode Last Literals + { + var lastRun = (int)(src_end - src_anchor); + if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0; + if (lastRun >= RUN_MASK) + { + *dst_p++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) *dst_p++ = 255; + *dst_p++ = (byte)lastRun; + } + else *dst_p++ = (byte)(lastRun << ML_BITS); + BlockCopy(src_anchor, dst_p, (int)(src_end - src_anchor)); + dst_p += src_end - src_anchor; + } + + // End + return (int)((dst_p) - dst); + } + } + } + + #endregion + + #region LZ4_uncompress_32 + + private static unsafe int LZ4_uncompress_32( + byte* src, + byte* dst, + int dst_len) + { + unchecked + { + fixed (int* dec32table = &DECODER_TABLE_32[0]) + { + // r93 + var src_p = src; + byte* xxx_ref; + + var dst_p = dst; + var dst_end = dst_p + dst_len; + byte* dst_cpy; + + var dst_LASTLITERALS = dst_end - LASTLITERALS; + var dst_COPYLENGTH = dst_end - COPYLENGTH; + var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_32 - 4); + + uint xxx_token; + + // Main Loop + while (true) + { + int length; + + // get runlength + xxx_token = *src_p++; + if ((length = (int)(xxx_token >> ML_BITS)) == RUN_MASK) + { + int len; + for (; (len = *src_p++) == 255; length += 255) + { + /* do nothing */ + } + length += len; + } + + // copy literals + dst_cpy = dst_p + length; + + if (dst_cpy > dst_COPYLENGTH) + { + if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals + BlockCopy(src_p, dst_p, (length)); + src_p += length; + break; // EOF + } + do + { + *(uint*)dst_p = *(uint*)src_p; + dst_p += 4; + src_p += 4; + *(uint*)dst_p = *(uint*)src_p; + dst_p += 4; + src_p += 4; + } while (dst_p < dst_cpy); + src_p -= (dst_p - dst_cpy); + dst_p = dst_cpy; + + // get offset + xxx_ref = (dst_cpy) - (*(ushort*)(src_p)); + src_p += 2; + if (xxx_ref < dst) goto _output_error; // Error : offset outside destination buffer + + // get matchlength + if ((length = (int)(xxx_token & ML_MASK)) == ML_MASK) + { + for (; *src_p == 255; length += 255) src_p++; + length += *src_p++; + } + + // copy repeated sequence + if ((dst_p - xxx_ref) < STEPSIZE_32) + { + const int dec64 = 0; + + dst_p[0] = xxx_ref[0]; + dst_p[1] = xxx_ref[1]; + dst_p[2] = xxx_ref[2]; + dst_p[3] = xxx_ref[3]; + dst_p += 4; + xxx_ref += 4; + xxx_ref -= dec32table[dst_p - xxx_ref]; + (*(uint*)(dst_p)) = (*(uint*)(xxx_ref)); + dst_p += STEPSIZE_32 - 4; + xxx_ref -= dec64; + } + else + { + *(uint*)dst_p = *(uint*)xxx_ref; + dst_p += 4; + xxx_ref += 4; + } + dst_cpy = dst_p + length - (STEPSIZE_32 - 4); + + if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4) + { + if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals + { + do + { + *(uint*)dst_p = *(uint*)xxx_ref; + dst_p += 4; + xxx_ref += 4; + *(uint*)dst_p = *(uint*)xxx_ref; + dst_p += 4; + xxx_ref += 4; + } while (dst_p < dst_COPYLENGTH); + } + + while (dst_p < dst_cpy) *dst_p++ = *xxx_ref++; + dst_p = dst_cpy; + continue; + } + + do + { + *(uint*)dst_p = *(uint*)xxx_ref; + dst_p += 4; + xxx_ref += 4; + *(uint*)dst_p = *(uint*)xxx_ref; + dst_p += 4; + xxx_ref += 4; + } while (dst_p < dst_cpy); + dst_p = dst_cpy; // correction + } + + // end of decoding + return (int)((src_p) - src); + + // write overflow error detected + _output_error: + return (int)(-((src_p) - src)); + } + } + } + + #endregion + } +} + +// ReSharper restore JoinDeclarationAndInitializer +// ReSharper restore TooWideLocalVariableScope +// ReSharper restore InconsistentNaming + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe64.Dirty.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe64.Dirty.cs new file mode 100644 index 0000000000..387e61467d --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.Unsafe64.Dirty.cs @@ -0,0 +1,686 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if ENABLE_UNSAFE_MSGPACK + +#region LZ4 original + +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2012, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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 COPYRIGHT HOLDERS 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 COPYRIGHT + OWNER 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. + + You can contact the author at : + - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + - LZ4 source repository : http://code.google.com/p/lz4/ +*/ + +#endregion + +#region LZ4 port + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +// ReSharper disable InconsistentNaming +// ReSharper disable TooWideLocalVariableScope +// ReSharper disable JoinDeclarationAndInitializer + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + #region LZ4_compressCtx_64 + + private static unsafe int LZ4_compressCtx_64( + uint* hash_table, + byte* src, + byte* dst, + int src_len, + int dst_maxlen) + { + unchecked + { + byte* _p; + + fixed (int* debruijn64 = &DEBRUIJN_TABLE_64[0]) + { + // r93 + var src_p = src; + var src_base = src_p; + var src_anchor = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_3 = src_LASTLITERALS - 3; + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int length; + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + hash_table[((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST)] = (uint)(src_p - src_base); + src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + byte* src_ref; + byte* dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = ((((*(uint*)(src_p_fwd))) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (uint)(src_p - src_base); + } while ((src_ref < src_p - MAX_DISTANCE) || ((*(uint*)(src_ref)) != (*(uint*)(src_p)))); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src) && (src_p[-1] == src_ref[-1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (int)(src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + var len = length - RUN_MASK; + *dst_token = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + *dst_p++ = 255; + len -= 255; + } while (len > 254); + *dst_p++ = (byte)len; + BlockCopy(src_anchor, dst_p, (length)); + dst_p += length; + goto _next_match; + } + *dst_p++ = (byte)len; + } + else + { + *dst_token = (byte)(length << ML_BITS); + } + + // Copy Literals + _p = dst_p + (length); + { + do + { + *(ulong*)dst_p = *(ulong*)src_anchor; + dst_p += 8; + src_anchor += 8; + } while (dst_p < _p); + } + dst_p = _p; + + _next_match: + + // Encode Offset + *(ushort*)dst_p = (ushort)(src_p - src_ref); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch already verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (*(long*)(src_ref)) ^ (*(long*)(src_p)); + if (diff == 0) + { + src_p += STEPSIZE_64; + src_ref += STEPSIZE_64; + continue; + } + src_p += debruijn64[(((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL)) >> 58]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_3) && ((*(uint*)(src_ref)) == (*(uint*)(src_p)))) + { + src_p += 4; + src_ref += 4; + } + if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)(src_ref)) == (*(ushort*)(src_p)))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (*src_ref == *src_p)) src_p++; + + _endCount: + + // Encode MatchLength + length = (int)(src_p - src_anchor); + + if (dst_p + (length >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (length >= ML_MASK) + { + *dst_token += ML_MASK; + length -= ML_MASK; + for (; length > 509; length -= 510) + { + *dst_p++ = 255; + *dst_p++ = 255; + } + if (length > 254) + { + length -= 255; + *dst_p++ = 255; + } + *dst_p++ = (byte)length; + } + else + { + *dst_token += (byte)length; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[((((*(uint*)(src_p - 2))) * 2654435761u) >> HASH_ADJUST)] = (uint)(src_p - 2 - src_base); + + // Test next position + + h = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (uint)(src_p - src_base); + + if ((src_ref > src_p - (MAX_DISTANCE + 1)) && ((*(uint*)(src_ref)) == (*(uint*)(src_p)))) + { + dst_token = dst_p++; + *dst_token = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH_ADJUST); + } + + _last_literals: + + // Encode Last Literals + var lastRun = (int)(src_end - src_anchor); + if (dst_p + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > dst_end) return 0; + if (lastRun >= RUN_MASK) + { + *dst_p++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) *dst_p++ = 255; + *dst_p++ = (byte)lastRun; + } + else *dst_p++ = (byte)(lastRun << ML_BITS); + BlockCopy(src_anchor, dst_p, (int)(src_end - src_anchor)); + dst_p += src_end - src_anchor; + + // End + return (int)(dst_p - dst); + } + } + } + + #endregion + + #region LZ4_compress64kCtx_64 + + private static unsafe int LZ4_compress64kCtx_64( + ushort* hash_table, + byte* src, + byte* dst, + int src_len, + int dst_maxlen) + { + unchecked + { + byte* _p; + + fixed (int* debruijn64 = &DEBRUIJN_TABLE_64[0]) + { + // r93 + var src_p = src; + var src_anchor = src_p; + var src_base = src_p; + var src_end = src_p + src_len; + var src_mflimit = src_end - MFLIMIT; + + var dst_p = dst; + var dst_end = dst_p + dst_maxlen; + + var src_LASTLITERALS = src_end - LASTLITERALS; + var src_LASTLITERALS_1 = src_LASTLITERALS - 1; + + var src_LASTLITERALS_3 = src_LASTLITERALS - 3; + + var src_LASTLITERALS_STEPSIZE_1 = src_LASTLITERALS - (STEPSIZE_64 - 1); + var dst_LASTLITERALS_1 = dst_end - (1 + LASTLITERALS); + var dst_LASTLITERALS_3 = dst_end - (2 + 1 + LASTLITERALS); + + int len, length; + + uint h, h_fwd; + + // Init + if (src_len < MINLENGTH) goto _last_literals; + + // First Byte + src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + + // Main Loop + while (true) + { + var findMatchAttempts = (1 << SKIPSTRENGTH) + 3; + var src_p_fwd = src_p; + byte* src_ref; + byte* dst_token; + + // Find a match + do + { + h = h_fwd; + var step = findMatchAttempts++ >> SKIPSTRENGTH; + src_p = src_p_fwd; + src_p_fwd = src_p + step; + + if (src_p_fwd > src_mflimit) goto _last_literals; + + h_fwd = ((((*(uint*)(src_p_fwd))) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + } while ((*(uint*)(src_ref)) != (*(uint*)(src_p))); + + // Catch up + while ((src_p > src_anchor) && (src_ref > src) && (src_p[-1] == src_ref[-1])) + { + src_p--; + src_ref--; + } + + // Encode Literal length + length = (int)(src_p - src_anchor); + dst_token = dst_p++; + + if (dst_p + length + (length >> 8) > dst_LASTLITERALS_3) return 0; // Check output limit + + if (length >= RUN_MASK) + { + len = length - RUN_MASK; + *dst_token = (RUN_MASK << ML_BITS); + if (len > 254) + { + do + { + *dst_p++ = 255; + len -= 255; + } while (len > 254); + *dst_p++ = (byte)len; + BlockCopy(src_anchor, dst_p, (length)); + dst_p += length; + goto _next_match; + } + *dst_p++ = (byte)len; + } + else + { + *dst_token = (byte)(length << ML_BITS); + } + + // Copy Literals + { + _p = dst_p + (length); + { + do + { + *(ulong*)dst_p = *(ulong*)src_anchor; + dst_p += 8; + src_anchor += 8; + } while (dst_p < _p); + } + dst_p = _p; + } + + _next_match: + + // Encode Offset + *(ushort*)dst_p = (ushort)(src_p - src_ref); + dst_p += 2; + + // Start Counting + src_p += MINMATCH; + src_ref += MINMATCH; // MinMatch verified + src_anchor = src_p; + + while (src_p < src_LASTLITERALS_STEPSIZE_1) + { + var diff = (*(long*)(src_ref)) ^ (*(long*)(src_p)); + if (diff == 0) + { + src_p += STEPSIZE_64; + src_ref += STEPSIZE_64; + continue; + } + src_p += debruijn64[(((ulong)((diff) & -(diff)) * 0x0218A392CDABBD3FL)) >> 58]; + goto _endCount; + } + + if ((src_p < src_LASTLITERALS_3) && ((*(uint*)(src_ref)) == (*(uint*)(src_p)))) + { + src_p += 4; + src_ref += 4; + } + if ((src_p < src_LASTLITERALS_1) && ((*(ushort*)(src_ref)) == (*(ushort*)(src_p)))) + { + src_p += 2; + src_ref += 2; + } + if ((src_p < src_LASTLITERALS) && (*src_ref == *src_p)) src_p++; + + _endCount: + + // Encode MatchLength + len = (int)(src_p - src_anchor); + + if (dst_p + (len >> 8) > dst_LASTLITERALS_1) return 0; // Check output limit + + if (len >= ML_MASK) + { + *dst_token += ML_MASK; + len -= ML_MASK; + for (; len > 509; len -= 510) + { + *dst_p++ = 255; + *dst_p++ = 255; + } + if (len > 254) + { + len -= 255; + *dst_p++ = 255; + } + *dst_p++ = (byte)len; + } + else + { + *dst_token += (byte)len; + } + + // Test end of chunk + if (src_p > src_mflimit) + { + src_anchor = src_p; + break; + } + + // Fill table + hash_table[((((*(uint*)(src_p - 2))) * 2654435761u) >> HASH64K_ADJUST)] = (ushort)(src_p - 2 - src_base); + + // Test next position + + h = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + src_ref = src_base + hash_table[h]; + hash_table[h] = (ushort)(src_p - src_base); + + if ((*(uint*)(src_ref)) == (*(uint*)(src_p))) + { + dst_token = dst_p++; + *dst_token = 0; + goto _next_match; + } + + // Prepare next loop + src_anchor = src_p++; + h_fwd = ((((*(uint*)(src_p))) * 2654435761u) >> HASH64K_ADJUST); + } + + _last_literals: + + // Encode Last Literals + var lastRun = (int)(src_end - src_anchor); + if (dst_p + lastRun + 1 + (lastRun - RUN_MASK + 255) / 255 > dst_end) return 0; + if (lastRun >= RUN_MASK) + { + *dst_p++ = (RUN_MASK << ML_BITS); + lastRun -= RUN_MASK; + for (; lastRun > 254; lastRun -= 255) *dst_p++ = 255; + *dst_p++ = (byte)lastRun; + } + else *dst_p++ = (byte)(lastRun << ML_BITS); + BlockCopy(src_anchor, dst_p, (int)(src_end - src_anchor)); + dst_p += src_end - src_anchor; + + // End + return (int)(dst_p - dst); + } + } + } + + #endregion + + #region LZ4_uncompress_64 + + private static unsafe int LZ4_uncompress_64( + byte* src, + byte* dst, + int dst_len) + { + unchecked + { + fixed (int* dec32table = &DECODER_TABLE_32[0]) + fixed (int* dec64table = &DECODER_TABLE_64[0]) + { + // r93 + var src_p = src; + byte* dst_ref; + + var dst_p = dst; + var dst_end = dst_p + dst_len; + byte* dst_cpy; + + var dst_LASTLITERALS = dst_end - LASTLITERALS; + var dst_COPYLENGTH = dst_end - COPYLENGTH; + var dst_COPYLENGTH_STEPSIZE_4 = dst_end - COPYLENGTH - (STEPSIZE_64 - 4); + + byte token; + + // Main Loop + while (true) + { + int length; + + // get runlength + token = *src_p++; + if ((length = (token >> ML_BITS)) == RUN_MASK) + { + int len; + for (; (len = *src_p++) == 255; length += 255) + { + /* do nothing */ + } + length += len; + } + + // copy literals + dst_cpy = dst_p + length; + + if (dst_cpy > dst_COPYLENGTH) + { + if (dst_cpy != dst_end) goto _output_error; // Error : not enough place for another match (min 4) + 5 literals + BlockCopy(src_p, dst_p, (length)); + src_p += length; + break; // EOF + } + do + { + *(ulong*)dst_p = *(ulong*)src_p; + dst_p += 8; + src_p += 8; + } while (dst_p < dst_cpy); + src_p -= (dst_p - dst_cpy); + dst_p = dst_cpy; + + // get offset + dst_ref = (dst_cpy) - (*(ushort*)(src_p)); + src_p += 2; + if (dst_ref < dst) goto _output_error; // Error : offset outside destination buffer + + // get matchlength + if ((length = (token & ML_MASK)) == ML_MASK) + { + for (; *src_p == 255; length += 255) src_p++; + length += *src_p++; + } + + // copy repeated sequence + if ((dst_p - dst_ref) < STEPSIZE_64) + { + var dec64 = dec64table[dst_p - dst_ref]; + + dst_p[0] = dst_ref[0]; + dst_p[1] = dst_ref[1]; + dst_p[2] = dst_ref[2]; + dst_p[3] = dst_ref[3]; + dst_p += 4; + dst_ref += 4; + dst_ref -= dec32table[dst_p - dst_ref]; + (*(uint*)(dst_p)) = (*(uint*)(dst_ref)); + dst_p += STEPSIZE_64 - 4; + dst_ref -= dec64; + } + else + { + *(ulong*)dst_p = *(ulong*)dst_ref; + dst_p += 8; + dst_ref += 8; + } + dst_cpy = dst_p + length - (STEPSIZE_64 - 4); + + if (dst_cpy > dst_COPYLENGTH_STEPSIZE_4) + { + if (dst_cpy > dst_LASTLITERALS) goto _output_error; // Error : last 5 bytes must be literals + while (dst_p < dst_COPYLENGTH) + { + *(ulong*)dst_p = *(ulong*)dst_ref; + dst_p += 8; + dst_ref += 8; + } + + while (dst_p < dst_cpy) *dst_p++ = *dst_ref++; + dst_p = dst_cpy; + continue; + } + + { + do + { + *(ulong*)dst_p = *(ulong*)dst_ref; + dst_p += 8; + dst_ref += 8; + } while (dst_p < dst_cpy); + } + dst_p = dst_cpy; // correction + } + + // end of decoding + return (int)((src_p) - src); + + // write overflow error detected + _output_error: + return (int)(-((src_p) - src)); + } + } + } + + #endregion + } +} + +// ReSharper restore JoinDeclarationAndInitializer +// ReSharper restore TooWideLocalVariableScope +// ReSharper restore InconsistentNaming + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.cs new file mode 100644 index 0000000000..58daa19694 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/Codec/LZ4Codec.cs @@ -0,0 +1,162 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#region license + +/* +Copyright (c) 2013, Milosz Krajewski +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions + and the following disclaimer. + +* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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. +*/ + +#endregion + +using System; + +// ReSharper disable InconsistentNaming + +namespace Datadog.Trace.Vendors.MessagePack.LZ4 +{ + internal static partial class LZ4Codec + { + #region configuration + + /// + /// Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + /// Increasing memory usage improves compression ratio + /// Reduced memory usage can improve speed, due to cache effect + /// Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + /// + private const int MEMORY_USAGE = 12; // modified use 12. + + /// + /// Decreasing this value will make the algorithm skip faster data segments considered "incompressible" + /// This may decrease compression ratio dramatically, but will be faster on incompressible data + /// Increasing this value will make the algorithm search more before declaring a segment "incompressible" + /// This could improve compression a bit, but will be slower on incompressible data + /// The default value (6) is recommended + /// + private const int NOTCOMPRESSIBLE_DETECTIONLEVEL = 6; + + #endregion + + #region consts + + private const int MINMATCH = 4; + +#pragma warning disable 162, 429 + // ReSharper disable once UnreachableCode + private const int SKIPSTRENGTH = + NOTCOMPRESSIBLE_DETECTIONLEVEL > 2 + ? NOTCOMPRESSIBLE_DETECTIONLEVEL + : 2; +#pragma warning restore 162, 429 + + private const int COPYLENGTH = 8; + private const int LASTLITERALS = 5; + private const int MFLIMIT = COPYLENGTH + MINMATCH; + private const int MINLENGTH = MFLIMIT + 1; + private const int MAXD_LOG = 16; + private const int MAXD = 1 << MAXD_LOG; + private const int MAXD_MASK = MAXD - 1; + private const int MAX_DISTANCE = (1 << MAXD_LOG) - 1; + private const int ML_BITS = 4; + private const int ML_MASK = (1 << ML_BITS) - 1; + private const int RUN_BITS = 8 - ML_BITS; + private const int RUN_MASK = (1 << RUN_BITS) - 1; + private const int STEPSIZE_64 = 8; + private const int STEPSIZE_32 = 4; + + private const int LZ4_64KLIMIT = (1 << 16) + (MFLIMIT - 1); + + private const int HASH_LOG = MEMORY_USAGE - 2; + private const int HASH_TABLESIZE = 1 << HASH_LOG; + private const int HASH_ADJUST = (MINMATCH * 8) - HASH_LOG; + + private const int HASH64K_LOG = HASH_LOG + 1; + private const int HASH64K_TABLESIZE = 1 << HASH64K_LOG; + private const int HASH64K_ADJUST = (MINMATCH * 8) - HASH64K_LOG; + + private const int HASHHC_LOG = MAXD_LOG - 1; + private const int HASHHC_TABLESIZE = 1 << HASHHC_LOG; + private const int HASHHC_ADJUST = (MINMATCH * 8) - HASHHC_LOG; + //private const int HASHHC_MASK = HASHHC_TABLESIZE - 1; + + private static readonly int[] DECODER_TABLE_32 = { 0, 3, 2, 3, 0, 0, 0, 0 }; + private static readonly int[] DECODER_TABLE_64 = { 0, 0, 0, -1, 0, 1, 2, 3 }; + + private static readonly int[] DEBRUIJN_TABLE_32 = { + 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, + 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 + }; + + private static readonly int[] DEBRUIJN_TABLE_64 = { + 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, + 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, + 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, + 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 + }; + + private const int MAX_NB_ATTEMPTS = 256; + private const int OPTIMAL_ML = (ML_MASK - 1) + MINMATCH; + + private const int BLOCK_COPY_LIMIT = 16; + + #endregion + + #region internal interface (common) + + /// Gets maximum the length of the output. + /// Length of the input. + /// Maximum number of bytes needed for compressed buffer. + public static int MaximumOutputLength(int inputLength) + { + return inputLength + (inputLength / 255) + 16; + } + + #endregion + + #region internal interface (common) + + internal static void CheckArguments( + byte[] input, int inputOffset, int inputLength, + byte[] output, int outputOffset, int outputLength) + { + if (inputLength == 0) + { + outputLength = 0; + return; + } + + if (input == null) throw new ArgumentNullException("input"); + if ((uint)inputOffset > (uint)input.Length) throw new ArgumentOutOfRangeException("inputOffset"); + if ((uint)inputLength > (uint)input.Length - (uint)inputOffset) throw new ArgumentOutOfRangeException("inputLength"); + + if (output == null) throw new ArgumentNullException("output"); + if ((uint)outputOffset > (uint)output.Length) throw new ArgumentOutOfRangeException("outputOffset"); + if ((uint)outputLength > (uint)output.Length - (uint)outputOffset) throw new ArgumentOutOfRangeException("outputLength"); + } + + #endregion + } +} + +// ReSharper restore InconsistentNaming diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.JSON.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.JSON.cs new file mode 100644 index 0000000000..a043e3c7a3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.JSON.cs @@ -0,0 +1,263 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using Datadog.Trace.Vendors.MessagePack.LZ4; +using System; +using System.Globalization; +using System.IO; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + // JSON API + internal static partial class LZ4MessagePackSerializer + { + /// + /// Dump to JSON string. + /// + public static string ToJson(T obj) + { + return ToJson(Serialize(obj)); + } + + /// + /// Dump to JSON string. + /// + public static string ToJson(T obj, IFormatterResolver resolver) + { + return ToJson(Serialize(obj, resolver)); + } + + /// + /// Dump message-pack binary to JSON string. + /// + public static string ToJson(byte[] bytes) + { + if (bytes == null || bytes.Length == 0) return ""; + + int readSize; + if (MessagePackBinary.GetMessagePackType(bytes, 0) == MessagePackType.Extension) + { + var header = MessagePackBinary.ReadExtensionFormatHeader(bytes, 0, out readSize); + if (header.TypeCode == ExtensionTypeCode) + { + // decode lz4 + var offset = readSize; + var length = MessagePackBinary.ReadInt32(bytes, offset, out readSize); + offset += readSize; + + var buffer = LZ4MemoryPool.GetBuffer(); + if (buffer.Length < length) + { + buffer = new byte[length]; + } + + // LZ4 Decode + LZ4Codec.Decode(bytes, offset, bytes.Length - offset, buffer, 0, length); + + bytes = buffer; // use LZ4 bytes + } + } + + var sb = new StringBuilder(); + ToJsonCore(bytes, 0, sb); + return sb.ToString(); + } + + public static byte[] FromJson(string str) + { + using (var sr = new StringReader(str)) + { + return FromJson(sr); + } + } + + /// + /// From Json String to LZ4MessagePack binary + /// + public static byte[] FromJson(TextReader reader) + { + var buffer = MessagePackSerializer.FromJsonUnsafe(reader); // offset is guranteed from 0 + return LZ4MessagePackSerializer.ToLZ4Binary(buffer); + } + + static int ToJsonCore(byte[] bytes, int offset, StringBuilder builder) + { + var readSize = 0; + var type = MessagePackBinary.GetMessagePackType(bytes, offset); + switch (type) + { + case MessagePackType.Integer: + var code = bytes[offset]; + if (MessagePackCode.MinNegativeFixInt <= code && code <= MessagePackCode.MaxNegativeFixInt) builder.Append(MessagePackBinary.ReadSByte(bytes, offset, out readSize)); + else if (MessagePackCode.MinFixInt <= code && code <= MessagePackCode.MaxFixInt) builder.Append(MessagePackBinary.ReadByte(bytes, offset, out readSize)); + else if (code == MessagePackCode.Int8) builder.Append(MessagePackBinary.ReadSByte(bytes, offset, out readSize)); + else if (code == MessagePackCode.Int16) builder.Append(MessagePackBinary.ReadInt16(bytes, offset, out readSize)); + else if (code == MessagePackCode.Int32) builder.Append(MessagePackBinary.ReadInt32(bytes, offset, out readSize)); + else if (code == MessagePackCode.Int64) builder.Append(MessagePackBinary.ReadInt64(bytes, offset, out readSize)); + else if (code == MessagePackCode.UInt8) builder.Append(MessagePackBinary.ReadByte(bytes, offset, out readSize)); + else if (code == MessagePackCode.UInt16) builder.Append(MessagePackBinary.ReadUInt16(bytes, offset, out readSize)); + else if (code == MessagePackCode.UInt32) builder.Append(MessagePackBinary.ReadUInt32(bytes, offset, out readSize)); + else if (code == MessagePackCode.UInt64) builder.Append(MessagePackBinary.ReadUInt64(bytes, offset, out readSize)); + break; + case MessagePackType.Boolean: + builder.Append(MessagePackBinary.ReadBoolean(bytes, offset, out readSize) ? "true" : "false"); + break; + case MessagePackType.Float: + var floatCode = bytes[offset]; + if (floatCode == MessagePackCode.Float32) + { + builder.Append(MessagePackBinary.ReadSingle(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + } + else + { + builder.Append(MessagePackBinary.ReadDouble(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + } + break; + case MessagePackType.String: + WriteJsonString(MessagePackBinary.ReadString(bytes, offset, out readSize), builder); + break; + case MessagePackType.Binary: + builder.Append("\"" + Convert.ToBase64String(MessagePackBinary.ReadBytes(bytes, offset, out readSize)) + "\""); + break; + case MessagePackType.Array: + { + var length = MessagePackBinary.ReadArrayHeaderRaw(bytes, offset, out readSize); + var totalReadSize = readSize; + offset += readSize; + builder.Append("["); + for (int i = 0; i < length; i++) + { + readSize = ToJsonCore(bytes, offset, builder); + offset += readSize; + totalReadSize += readSize; + + if (i != length - 1) + { + builder.Append(","); + } + } + builder.Append("]"); + + return totalReadSize; + } + case MessagePackType.Map: + { + var length = MessagePackBinary.ReadMapHeaderRaw(bytes, offset, out readSize); + var totalReadSize = readSize; + offset += readSize; + builder.Append("{"); + for (int i = 0; i < length; i++) + { + // write key + { + var keyType = MessagePackBinary.GetMessagePackType(bytes, offset); + if (keyType == MessagePackType.String || keyType == MessagePackType.Binary) + { + readSize = ToJsonCore(bytes, offset, builder); + } + else + { + builder.Append("\""); + readSize = ToJsonCore(bytes, offset, builder); + builder.Append("\""); + } + offset += readSize; + totalReadSize += readSize; + } + + builder.Append(":"); + + // write body + { + readSize = ToJsonCore(bytes, offset, builder); + offset += readSize; + totalReadSize += readSize; + } + + if (i != length - 1) + { + builder.Append(","); + } + } + builder.Append("}"); + + return totalReadSize; + } + case MessagePackType.Extension: + var extHeader = MessagePackBinary.ReadExtensionFormatHeader(bytes, offset, out readSize); + if (extHeader.TypeCode == ReservedMessagePackExtensionTypeCode.DateTime) + { + var dt = MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + builder.Append("\""); + builder.Append(dt.ToString("o", CultureInfo.InvariantCulture)); + builder.Append("\""); + } + else + { + var ext = MessagePackBinary.ReadExtensionFormat(bytes, offset, out readSize); + builder.Append("["); + builder.Append(ext.TypeCode); + builder.Append(","); + builder.Append("\""); + builder.Append(Convert.ToBase64String(ext.Data)); + builder.Append("\""); + builder.Append("]"); + } + break; + case MessagePackType.Unknown: + case MessagePackType.Nil: + default: + readSize = 1; + builder.Append("null"); + break; + } + + return readSize; + } + + // escape string + static void WriteJsonString(string value, StringBuilder builder) + { + builder.Append('\"'); + + var len = value.Length; + for (int i = 0; i < len; i++) + { + var c = value[i]; + switch (c) + { + case '"': + builder.Append("\\\""); + break; + case '\\': + builder.Append("\\\\"); + break; + case '\b': + builder.Append("\\b"); + break; + case '\f': + builder.Append("\\f"); + break; + case '\n': + builder.Append("\\n"); + break; + case '\r': + builder.Append("\\r"); + break; + case '\t': + builder.Append("\\t"); + break; + default: + builder.Append(c); + break; + } + } + + builder.Append('\"'); + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.NonGeneric.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.NonGeneric.cs new file mode 100644 index 0000000000..8fd42741f0 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.NonGeneric.cs @@ -0,0 +1,281 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if NETSTANDARD || NETFRAMEWORK + +using System; +using System.Linq; +using System.Reflection; +using System.IO; +using System.Linq.Expressions; + +namespace Datadog.Trace.Vendors.MessagePack +{ + internal static partial class LZ4MessagePackSerializer + { + internal static class NonGeneric + { + static readonly Func CreateCompiledMethods; + static readonly MessagePack.Internal.ThreadsafeTypeKeyHashTable serializes = new MessagePack.Internal.ThreadsafeTypeKeyHashTable(capacity: 64); + + + static NonGeneric() + { + CreateCompiledMethods = t => new CompiledMethods(t); + } + + public static byte[] Serialize(Type type, object obj) + { + return GetOrAdd(type).serialize1.Invoke(obj); + } + + public static byte[] Serialize(Type type, object obj, IFormatterResolver resolver) + { + return GetOrAdd(type).serialize2.Invoke(obj, resolver); + } + + public static void Serialize(Type type, Stream stream, object obj) + { + GetOrAdd(type).serialize3.Invoke(stream, obj); + } + + public static void Serialize(Type type, Stream stream, object obj, IFormatterResolver resolver) + { + GetOrAdd(type).serialize4.Invoke(stream, obj, resolver); + } + + public static object Deserialize(Type type, byte[] bytes) + { + return GetOrAdd(type).deserialize1.Invoke(bytes); + } + + public static object Deserialize(Type type, byte[] bytes, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize2.Invoke(bytes, resolver); + } + + public static object Deserialize(Type type, Stream stream) + { + return GetOrAdd(type).deserialize3.Invoke(stream); + } + + public static object Deserialize(Type type, Stream stream, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize4.Invoke(stream, resolver); + } + + public static object Deserialize(Type type, Stream stream, bool readStrict) + { + return GetOrAdd(type).deserialize5.Invoke(stream, readStrict); + } + + public static object Deserialize(Type type, Stream stream, IFormatterResolver resolver, bool readStrict) + { + return GetOrAdd(type).deserialize6.Invoke(stream, resolver, readStrict); + } + + public static object Deserialize(Type type, ArraySegment bytes) + { + return GetOrAdd(type).deserialize7.Invoke(bytes); + } + + public static object Deserialize(Type type, ArraySegment bytes, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize8.Invoke(bytes, resolver); + } + + static CompiledMethods GetOrAdd(Type type) + { + return serializes.GetOrAdd(type, CreateCompiledMethods); + } + + class CompiledMethods + { + public readonly Func serialize1; + public readonly Func serialize2; + public readonly Action serialize3; + public readonly Action serialize4; + + public readonly Func deserialize1; + public readonly Func deserialize2; + public readonly Func deserialize3; + public readonly Func deserialize4; + public readonly Func deserialize5; + public readonly Func deserialize6; + + public readonly Func, object> deserialize7; + public readonly Func, IFormatterResolver, object> deserialize8; + + public CompiledMethods(Type type) + { + var ti = type.GetTypeInfo(); + { + // public static byte[] Serialize(T obj) + var serialize = GetMethod(type, new Type[] { null }); + + var param1 = Expression.Parameter(typeof(object), "obj"); + var body = Expression.Call(serialize, ti.IsValueType + ? Expression.Unbox(param1, type) + : Expression.Convert(param1, type)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.serialize1 = lambda; + } + { + // public static byte[] Serialize(T obj, IFormatterResolver resolver) + var serialize = GetMethod(type, new Type[] { null, typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(object), "obj"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var body = Expression.Call(serialize, ti.IsValueType + ? Expression.Unbox(param1, type) + : Expression.Convert(param1, type), param2); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.serialize2 = lambda; + } + { + // public static void Serialize(Stream stream, T obj) + var serialize = GetMethod(type, new Type[] { typeof(Stream), null }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(object), "obj"); + + var body = Expression.Call(serialize, param1, ti.IsValueType + ? Expression.Unbox(param2, type) + : Expression.Convert(param2, type)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.serialize3 = lambda; + } + { + // public static void Serialize(Stream stream, T obj, IFormatterResolver resolver) + var serialize = GetMethod(type, new Type[] { typeof(Stream), null, typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(object), "obj"); + var param3 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var body = Expression.Call(serialize, param1, ti.IsValueType + ? Expression.Unbox(param2, type) + : Expression.Convert(param2, type), param3); + var lambda = Expression.Lambda>(body, param1, param2, param3).Compile(); + + this.serialize4 = lambda; + } + + { + // public static T Deserialize(byte[] bytes) + var deserialize = GetMethod(type, new Type[] { typeof(byte[]) }); + + var param1 = Expression.Parameter(typeof(byte[]), "bytes"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.deserialize1 = lambda; + } + { + // public static T Deserialize(byte[] bytes, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(byte[]), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(byte[]), "bytes"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize2 = lambda; + } + { + // public static T Deserialize(Stream stream) + var deserialize = GetMethod(type, new Type[] { typeof(Stream) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.deserialize3 = lambda; + } + { + // public static T Deserialize(Stream stream, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize4 = lambda; + } + { + // public static T Deserialize(Stream stream, bool readStrict) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(bool) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(bool), "readStrict"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize5 = lambda; + } + { + // public static T Deserialize(Stream stream, IFormatterResolver resolver, bool readStrict) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(IFormatterResolver), typeof(bool) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var param3 = Expression.Parameter(typeof(bool), "readStrict"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2, param3), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2, param3).Compile(); + + this.deserialize6 = lambda; + } + + { + // public static T Deserialize(ArraySegment bytes) + var deserialize = GetMethod(type, new Type[] { typeof(ArraySegment) }); + + var param1 = Expression.Parameter(typeof(ArraySegment), "bytes"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda, object>>(body, param1).Compile(); + + this.deserialize7 = lambda; + } + { + // public static T Deserialize(ArraySegment bytes, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(ArraySegment), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(ArraySegment), "bytes"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda, IFormatterResolver, object>>(body, param1, param2).Compile(); + + this.deserialize8 = lambda; + } + } + + // null is generic type marker. + static MethodInfo GetMethod(Type type, Type[] parameters) + { + return typeof(LZ4MessagePackSerializer).GetRuntimeMethods().Where(x => + { + if (!(x.Name == "Serialize" || x.Name == "Deserialize")) return false; + var ps = x.GetParameters(); + if (ps.Length != parameters.Length) return false; + for (int i = 0; i < ps.Length; i++) + { + if (parameters[i] == null && ps[i].ParameterType.IsGenericParameter) continue; + if (ps[i].ParameterType != parameters[i]) return false; + } + return true; + }) + .Single() + .MakeGenericMethod(type); + } + } + } + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.cs b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.cs new file mode 100644 index 0000000000..f01d14505b --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/LZ4/LZ4MessagePackSerializer.cs @@ -0,0 +1,365 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.IO; +using Datadog.Trace.Vendors.MessagePack.LZ4; + +namespace Datadog.Trace.Vendors.MessagePack +{ + /// + /// LZ4 Compressed special serializer. + /// + internal static partial class LZ4MessagePackSerializer + { + public const sbyte ExtensionTypeCode = 99; + + public const int NotCompressionSize = 64; + + /// + /// Serialize to binary with default resolver. + /// + public static byte[] Serialize(T obj) + { + return Serialize(obj, null); + } + + /// + /// Serialize to binary with specified resolver. + /// + public static byte[] Serialize(T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = MessagePackSerializer.DefaultResolver; + var buffer = SerializeCore(obj, resolver); + + return MessagePackBinary.FastCloneWithResize(buffer.Array, buffer.Count); + } + + /// + /// Serialize to stream. + /// + public static void Serialize(Stream stream, T obj) + { + Serialize(stream, obj, null); + } + + /// + /// Serialize to stream with specified resolver. + /// + public static void Serialize(Stream stream, T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = MessagePackSerializer.DefaultResolver; + var buffer = SerializeCore(obj, resolver); + + stream.Write(buffer.Array, 0, buffer.Count); + } + + public static int SerializeToBlock(ref byte[] bytes, int offset, T obj, IFormatterResolver resolver) + { + var serializedData = MessagePackSerializer.SerializeUnsafe(obj, resolver); + + if (serializedData.Count < NotCompressionSize) + { + // can't write direct, shoganai... + MessagePackBinary.EnsureCapacity(ref bytes, offset, serializedData.Count); + Buffer.BlockCopy(serializedData.Array, serializedData.Offset, bytes, offset, serializedData.Count); + return serializedData.Count; + } + else + { + var maxOutCount = LZ4Codec.MaximumOutputLength(serializedData.Count); + + MessagePackBinary.EnsureCapacity(ref bytes, offset, 6 + 5 + maxOutCount); // (ext header size + fixed length size) + + // acquire ext header position + var extHeaderOffset = offset; + offset += (6 + 5); + + // write body + var lz4Length = LZ4Codec.Encode(serializedData.Array, serializedData.Offset, serializedData.Count, bytes, offset, bytes.Length - offset); + + // write extension header(always 6 bytes) + extHeaderOffset += MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref bytes, extHeaderOffset, (sbyte)ExtensionTypeCode, lz4Length + 5); + + // write length(always 5 bytes) + MessagePackBinary.WriteInt32ForceInt32Block(ref bytes, extHeaderOffset, serializedData.Count); + + return 6 + 5 + lz4Length; + } + } + + public static byte[] ToLZ4Binary(ArraySegment messagePackBinary) + { + var buffer = ToLZ4BinaryCore(messagePackBinary); + return MessagePackBinary.FastCloneWithResize(buffer.Array, buffer.Count); + } + + static ArraySegment SerializeCore(T obj, IFormatterResolver resolver) + { + var serializedData = MessagePackSerializer.SerializeUnsafe(obj, resolver); + return ToLZ4BinaryCore(serializedData); + } + + static ArraySegment ToLZ4BinaryCore(ArraySegment serializedData) + { + if (serializedData.Count < NotCompressionSize) + { + return serializedData; + } + else + { + var offset = 0; + var buffer = LZ4MemoryPool.GetBuffer(); + var maxOutCount = LZ4Codec.MaximumOutputLength(serializedData.Count); + if (buffer.Length < 6 + 5 + maxOutCount) // (ext header size + fixed length size) + { + buffer = new byte[6 + 5 + maxOutCount]; + } + + // acquire ext header position + var extHeaderOffset = offset; + offset += (6 + 5); + + // write body + var lz4Length = LZ4Codec.Encode(serializedData.Array, serializedData.Offset, serializedData.Count, buffer, offset, buffer.Length - offset); + + // write extension header(always 6 bytes) + extHeaderOffset += MessagePackBinary.WriteExtensionFormatHeaderForceExt32Block(ref buffer, extHeaderOffset, (sbyte)ExtensionTypeCode, lz4Length + 5); + + // write length(always 5 bytes) + MessagePackBinary.WriteInt32ForceInt32Block(ref buffer, extHeaderOffset, serializedData.Count); + + return new ArraySegment(buffer, 0, 6 + 5 + lz4Length); + } + } + + public static T Deserialize(byte[] bytes) + { + return Deserialize(bytes, null); + } + + public static T Deserialize(byte[] bytes, IFormatterResolver resolver) + { + return DeserializeCore(new ArraySegment(bytes, 0, bytes.Length), resolver); + } + + public static T Deserialize(ArraySegment bytes) + { + return DeserializeCore(bytes, null); + } + + public static T Deserialize(ArraySegment bytes, IFormatterResolver resolver) + { + return DeserializeCore(bytes, resolver); + } + + public static T Deserialize(Stream stream) + { + return Deserialize(stream, null); + } + + public static T Deserialize(Stream stream, IFormatterResolver resolver) + { + return Deserialize(stream, resolver, false); + } + + public static T Deserialize(Stream stream, bool readStrict) + { + return Deserialize(stream, MessagePackSerializer.DefaultResolver, readStrict); + } + + public static T Deserialize(Stream stream, IFormatterResolver resolver, bool readStrict) + { + if (!readStrict) + { + var buffer = MessagePack.Internal.InternalMemoryPool.GetBuffer(); // use MessagePackSerializer.Pool! + var len = FillFromStream(stream, ref buffer); + return DeserializeCore(new ArraySegment(buffer, 0, len), resolver); + } + else + { + int blockSize; + var bytes = MessagePackBinary.ReadMessageBlockFromStreamUnsafe(stream, false, out blockSize); + return DeserializeCore(new ArraySegment(bytes, 0, blockSize), resolver); + } + } + + public static byte[] Decode(Stream stream, bool readStrict = false) + { + if (!readStrict) + { + var buffer = MessagePack.Internal.InternalMemoryPool.GetBuffer(); // use MessagePackSerializer.Pool! + var len = FillFromStream(stream, ref buffer); + return Decode(new ArraySegment(buffer, 0, len)); + } + else + { + int blockSize; + var bytes = MessagePackBinary.ReadMessageBlockFromStreamUnsafe(stream, false, out blockSize); + return Decode(new ArraySegment(bytes, 0, blockSize)); + } + } + + public static byte[] Decode(byte[] bytes) + { + return Decode(new ArraySegment(bytes, 0, bytes.Length)); + } + + public static byte[] Decode(ArraySegment bytes) + { + int readSize; + if (MessagePackBinary.GetMessagePackType(bytes.Array, bytes.Offset) == MessagePackType.Extension) + { + var header = MessagePackBinary.ReadExtensionFormatHeader(bytes.Array, bytes.Offset, out readSize); + if (header.TypeCode == ExtensionTypeCode) + { + // decode lz4 + var offset = bytes.Offset + readSize; + var length = MessagePackBinary.ReadInt32(bytes.Array, offset, out readSize); + offset += readSize; + + var buffer = new byte[length]; // use new buffer. + + // LZ4 Decode + var len = bytes.Count + bytes.Offset - offset; + LZ4Codec.Decode(bytes.Array, offset, len, buffer, 0, length); + + return buffer; + } + } + + if (bytes.Offset == 0 && bytes.Array.Length == bytes.Count) + { + // return same reference + return bytes.Array; + } + else + { + var result = new byte[bytes.Count]; + Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); + return result; + } + } + + + /// + /// Get the war memory pool byte[]. The result can not share across thread and can not hold and can not call LZ4Deserialize before use it. + /// + public static byte[] DecodeUnsafe(byte[] bytes) + { + return DecodeUnsafe(new ArraySegment(bytes, 0, bytes.Length)); + } + + /// + /// Get the war memory pool byte[]. The result can not share across thread and can not hold and can not call LZ4Deserialize before use it. + /// + public static byte[] DecodeUnsafe(ArraySegment bytes) + { + int readSize; + if (MessagePackBinary.GetMessagePackType(bytes.Array, bytes.Offset) == MessagePackType.Extension) + { + var header = MessagePackBinary.ReadExtensionFormatHeader(bytes.Array, bytes.Offset, out readSize); + if (header.TypeCode == ExtensionTypeCode) + { + // decode lz4 + var offset = bytes.Offset + readSize; + var length = MessagePackBinary.ReadInt32(bytes.Array, offset, out readSize); + offset += readSize; + + var buffer = LZ4MemoryPool.GetBuffer(); // use LZ4 Pool(Unsafe) + if (buffer.Length < length) + { + buffer = new byte[length]; + } + + // LZ4 Decode + var len = bytes.Count + bytes.Offset - offset; + LZ4Codec.Decode(bytes.Array, offset, len, buffer, 0, length); + + return buffer; // return pooled bytes. + } + } + + if (bytes.Offset == 0 && bytes.Array.Length == bytes.Count) + { + // return same reference + return bytes.Array; + } + else + { + var result = new byte[bytes.Count]; + Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); + return result; + } + } + + static T DeserializeCore(ArraySegment bytes, IFormatterResolver resolver) + { + if (resolver == null) resolver = MessagePackSerializer.DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + int readSize; + if (MessagePackBinary.GetMessagePackType(bytes.Array, bytes.Offset) == MessagePackType.Extension) + { + var header = MessagePackBinary.ReadExtensionFormatHeader(bytes.Array, bytes.Offset, out readSize); + if (header.TypeCode == ExtensionTypeCode) + { + // decode lz4 + var offset = bytes.Offset + readSize; + var length = MessagePackBinary.ReadInt32(bytes.Array, offset, out readSize); + offset += readSize; + + var buffer = LZ4MemoryPool.GetBuffer(); // use LZ4 Pool + if (buffer.Length < length) + { + buffer = new byte[length]; + } + + // LZ4 Decode + var len = bytes.Count + bytes.Offset - offset; + LZ4Codec.Decode(bytes.Array, offset, len, buffer, 0, length); + + return formatter.Deserialize(buffer, 0, resolver, out readSize); + } + } + + return formatter.Deserialize(bytes.Array, bytes.Offset, resolver, out readSize); + } + + static int FillFromStream(Stream input, ref byte[] buffer) + { + int length = 0; + int read; + while ((read = input.Read(buffer, length, buffer.Length - length)) > 0) + { + length += read; + if (length == buffer.Length) + { + MessagePackBinary.FastResize(ref buffer, length * 2); + } + } + + return length; + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class LZ4MemoryPool + { + [ThreadStatic] + static byte[] lz4buffer = null; + + public static byte[] GetBuffer() + { + if (lz4buffer == null) + { + lz4buffer = new byte[LZ4.LZ4Codec.MaximumOutputLength(65536)]; + } + return lz4buffer; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePack.csproj.txt b/src/Datadog.Trace/Vendors/MessagePack/MessagePack.csproj.txt new file mode 100644 index 0000000000..fceb5f41e3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePack.csproj.txt @@ -0,0 +1,98 @@ + + + + netstandard1.6;netstandard2.0;net45;net47 + $(NoWarn);CS0649 + True + $(DefineConstants);ENABLE_UNSAFE_MSGPACK + True + + true + MessagePack for C# + Extremely Fast MessagePack(MsgPack) Serializer for C#(.NET, .NET Core, Unity, Xamarin). + MsgPack;MessagePack;Serialization;Formatter;Serializer;Unity;Xamarin + MessagePack + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ForceSizePrimitiveFormatter.cs + TextTemplatingFileGenerator + + + TextTemplatingFileGenerator + PrimitiveFormatter.cs + + + TextTemplatingFileGenerator + TupleFormatter.cs + + + TextTemplatingFileGenerator + ValueTupleFormatter.cs + + + UnsafeMemory.cs + TextTemplatingFileGenerator + + + + + + True + True + ForceSizePrimitiveFormatter.tt + + + True + True + PrimitiveFormatter.tt + + + True + True + TupleFormatter.tt + + + True + True + ValueTupleFormatter.tt + + + UnsafeMemory.tt + True + True + + + + + + + diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackBinary.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackBinary.cs new file mode 100644 index 0000000000..887a28e45e --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackBinary.cs @@ -0,0 +1,5929 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Decoders; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.IO; + +namespace Datadog.Trace.Vendors.MessagePack +{ + /// + /// Encode/Decode Utility of MessagePack Spec. + /// https://github.com/msgpack/msgpack/blob/master/spec.md + /// + internal static partial class MessagePackBinary + { + const int MaxSize = 256; // [0] ~ [255] + const int ArrayMaxSize = 0x7FFFFFC7; // https://msdn.microsoft.com/en-us/library/system.array + + static readonly IMapHeaderDecoder[] mapHeaderDecoders = new IMapHeaderDecoder[MaxSize]; + static readonly IArrayHeaderDecoder[] arrayHeaderDecoders = new IArrayHeaderDecoder[MaxSize]; + static readonly IBooleanDecoder[] booleanDecoders = new IBooleanDecoder[MaxSize]; + static readonly IByteDecoder[] byteDecoders = new IByteDecoder[MaxSize]; + static readonly IBytesDecoder[] bytesDecoders = new IBytesDecoder[MaxSize]; + static readonly IBytesSegmentDecoder[] bytesSegmentDecoders = new IBytesSegmentDecoder[MaxSize]; + static readonly ISByteDecoder[] sbyteDecoders = new ISByteDecoder[MaxSize]; + static readonly ISingleDecoder[] singleDecoders = new ISingleDecoder[MaxSize]; + static readonly IDoubleDecoder[] doubleDecoders = new IDoubleDecoder[MaxSize]; + static readonly IInt16Decoder[] int16Decoders = new IInt16Decoder[MaxSize]; + static readonly IInt32Decoder[] int32Decoders = new IInt32Decoder[MaxSize]; + static readonly IInt64Decoder[] int64Decoders = new IInt64Decoder[MaxSize]; + static readonly IUInt16Decoder[] uint16Decoders = new IUInt16Decoder[MaxSize]; + static readonly IUInt32Decoder[] uint32Decoders = new IUInt32Decoder[MaxSize]; + static readonly IUInt64Decoder[] uint64Decoders = new IUInt64Decoder[MaxSize]; + static readonly IStringDecoder[] stringDecoders = new IStringDecoder[MaxSize]; + static readonly IStringSegmentDecoder[] stringSegmentDecoders = new IStringSegmentDecoder[MaxSize]; + static readonly IExtDecoder[] extDecoders = new IExtDecoder[MaxSize]; + static readonly IExtHeaderDecoder[] extHeaderDecoders = new IExtHeaderDecoder[MaxSize]; + static readonly IDateTimeDecoder[] dateTimeDecoders = new IDateTimeDecoder[MaxSize]; + static readonly IReadNextDecoder[] readNextDecoders = new IReadNextDecoder[MaxSize]; + + static MessagePackBinary() + { + // Init LookupTable. + for (int i = 0; i < MaxSize; i++) + { + mapHeaderDecoders[i] = Decoders.InvalidMapHeader.Instance; + arrayHeaderDecoders[i] = Decoders.InvalidArrayHeader.Instance; + booleanDecoders[i] = Decoders.InvalidBoolean.Instance; + byteDecoders[i] = Decoders.InvalidByte.Instance; + bytesDecoders[i] = Decoders.InvalidBytes.Instance; + bytesSegmentDecoders[i] = Decoders.InvalidBytesSegment.Instance; + sbyteDecoders[i] = Decoders.InvalidSByte.Instance; + singleDecoders[i] = Decoders.InvalidSingle.Instance; + doubleDecoders[i] = Decoders.InvalidDouble.Instance; + int16Decoders[i] = Decoders.InvalidInt16.Instance; + int32Decoders[i] = Decoders.InvalidInt32.Instance; + int64Decoders[i] = Decoders.InvalidInt64.Instance; + uint16Decoders[i] = Decoders.InvalidUInt16.Instance; + uint32Decoders[i] = Decoders.InvalidUInt32.Instance; + uint64Decoders[i] = Decoders.InvalidUInt64.Instance; + stringDecoders[i] = Decoders.InvalidString.Instance; + stringSegmentDecoders[i] = Decoders.InvalidStringSegment.Instance; + extDecoders[i] = Decoders.InvalidExt.Instance; + extHeaderDecoders[i] = Decoders.InvalidExtHeader.Instance; + dateTimeDecoders[i] = Decoders.InvalidDateTime.Instance; + } + + // Number + for (int i = MessagePackCode.MinNegativeFixInt; i <= MessagePackCode.MaxNegativeFixInt; i++) + { + sbyteDecoders[i] = Decoders.FixSByte.Instance; + int16Decoders[i] = Decoders.FixNegativeInt16.Instance; + int32Decoders[i] = Decoders.FixNegativeInt32.Instance; + int64Decoders[i] = Decoders.FixNegativeInt64.Instance; + singleDecoders[i] = Decoders.FixNegativeFloat.Instance; + doubleDecoders[i] = Decoders.FixNegativeDouble.Instance; + readNextDecoders[i] = Decoders.ReadNext1.Instance; + } + for (int i = MessagePackCode.MinFixInt; i <= MessagePackCode.MaxFixInt; i++) + { + byteDecoders[i] = Decoders.FixByte.Instance; + sbyteDecoders[i] = Decoders.FixSByte.Instance; + int16Decoders[i] = Decoders.FixInt16.Instance; + int32Decoders[i] = Decoders.FixInt32.Instance; + int64Decoders[i] = Decoders.FixInt64.Instance; + uint16Decoders[i] = Decoders.FixUInt16.Instance; + uint32Decoders[i] = Decoders.FixUInt32.Instance; + uint64Decoders[i] = Decoders.FixUInt64.Instance; + singleDecoders[i] = Decoders.FixFloat.Instance; + doubleDecoders[i] = Decoders.FixDouble.Instance; + readNextDecoders[i] = Decoders.ReadNext1.Instance; + } + + byteDecoders[MessagePackCode.UInt8] = Decoders.UInt8Byte.Instance; + sbyteDecoders[MessagePackCode.Int8] = Decoders.Int8SByte.Instance; + int16Decoders[MessagePackCode.UInt8] = Decoders.UInt8Int16.Instance; + int16Decoders[MessagePackCode.UInt16] = Decoders.UInt16Int16.Instance; + int16Decoders[MessagePackCode.Int8] = Decoders.Int8Int16.Instance; + int16Decoders[MessagePackCode.Int16] = Decoders.Int16Int16.Instance; + int32Decoders[MessagePackCode.UInt8] = Decoders.UInt8Int32.Instance; + int32Decoders[MessagePackCode.UInt16] = Decoders.UInt16Int32.Instance; + int32Decoders[MessagePackCode.UInt32] = Decoders.UInt32Int32.Instance; + int32Decoders[MessagePackCode.Int8] = Decoders.Int8Int32.Instance; + int32Decoders[MessagePackCode.Int16] = Decoders.Int16Int32.Instance; + int32Decoders[MessagePackCode.Int32] = Decoders.Int32Int32.Instance; + int64Decoders[MessagePackCode.UInt8] = Decoders.UInt8Int64.Instance; + int64Decoders[MessagePackCode.UInt16] = Decoders.UInt16Int64.Instance; + int64Decoders[MessagePackCode.UInt32] = Decoders.UInt32Int64.Instance; + int64Decoders[MessagePackCode.UInt64] = Decoders.UInt64Int64.Instance; + int64Decoders[MessagePackCode.Int8] = Decoders.Int8Int64.Instance; + int64Decoders[MessagePackCode.Int16] = Decoders.Int16Int64.Instance; + int64Decoders[MessagePackCode.Int32] = Decoders.Int32Int64.Instance; + int64Decoders[MessagePackCode.Int64] = Decoders.Int64Int64.Instance; + uint16Decoders[MessagePackCode.UInt8] = Decoders.UInt8UInt16.Instance; + uint16Decoders[MessagePackCode.UInt16] = Decoders.UInt16UInt16.Instance; + uint32Decoders[MessagePackCode.UInt8] = Decoders.UInt8UInt32.Instance; + uint32Decoders[MessagePackCode.UInt16] = Decoders.UInt16UInt32.Instance; + uint32Decoders[MessagePackCode.UInt32] = Decoders.UInt32UInt32.Instance; + uint64Decoders[MessagePackCode.UInt8] = Decoders.UInt8UInt64.Instance; + uint64Decoders[MessagePackCode.UInt16] = Decoders.UInt16UInt64.Instance; + uint64Decoders[MessagePackCode.UInt32] = Decoders.UInt32UInt64.Instance; + uint64Decoders[MessagePackCode.UInt64] = Decoders.UInt64UInt64.Instance; + + singleDecoders[MessagePackCode.Float32] = Decoders.Float32Single.Instance; + singleDecoders[MessagePackCode.Int8] = Decoders.Int8Single.Instance; + singleDecoders[MessagePackCode.Int16] = Decoders.Int16Single.Instance; + singleDecoders[MessagePackCode.Int32] = Decoders.Int32Single.Instance; + singleDecoders[MessagePackCode.Int64] = Decoders.Int64Single.Instance; + singleDecoders[MessagePackCode.UInt8] = Decoders.UInt8Single.Instance; + singleDecoders[MessagePackCode.UInt16] = Decoders.UInt16Single.Instance; + singleDecoders[MessagePackCode.UInt32] = Decoders.UInt32Single.Instance; + singleDecoders[MessagePackCode.UInt64] = Decoders.UInt64Single.Instance; + + doubleDecoders[MessagePackCode.Float32] = Decoders.Float32Double.Instance; + doubleDecoders[MessagePackCode.Float64] = Decoders.Float64Double.Instance; + doubleDecoders[MessagePackCode.Int8] = Decoders.Int8Double.Instance; + doubleDecoders[MessagePackCode.Int16] = Decoders.Int16Double.Instance; + doubleDecoders[MessagePackCode.Int32] = Decoders.Int32Double.Instance; + doubleDecoders[MessagePackCode.Int64] = Decoders.Int64Double.Instance; + doubleDecoders[MessagePackCode.UInt8] = Decoders.UInt8Double.Instance; + doubleDecoders[MessagePackCode.UInt16] = Decoders.UInt16Double.Instance; + doubleDecoders[MessagePackCode.UInt32] = Decoders.UInt32Double.Instance; + doubleDecoders[MessagePackCode.UInt64] = Decoders.UInt64Double.Instance; + + readNextDecoders[MessagePackCode.Int8] = Decoders.ReadNext2.Instance; + readNextDecoders[MessagePackCode.Int16] = Decoders.ReadNext3.Instance; + readNextDecoders[MessagePackCode.Int32] = Decoders.ReadNext5.Instance; + readNextDecoders[MessagePackCode.Int64] = Decoders.ReadNext9.Instance; + readNextDecoders[MessagePackCode.UInt8] = Decoders.ReadNext2.Instance; + readNextDecoders[MessagePackCode.UInt16] = Decoders.ReadNext3.Instance; + readNextDecoders[MessagePackCode.UInt32] = Decoders.ReadNext5.Instance; + readNextDecoders[MessagePackCode.UInt64] = Decoders.ReadNext9.Instance; + readNextDecoders[MessagePackCode.Float32] = Decoders.ReadNext5.Instance; + readNextDecoders[MessagePackCode.Float64] = Decoders.ReadNext9.Instance; + + // Map + for (int i = MessagePackCode.MinFixMap; i <= MessagePackCode.MaxFixMap; i++) + { + mapHeaderDecoders[i] = Decoders.FixMapHeader.Instance; + readNextDecoders[i] = Decoders.ReadNext1.Instance; + } + mapHeaderDecoders[MessagePackCode.Map16] = Decoders.Map16Header.Instance; + mapHeaderDecoders[MessagePackCode.Map32] = Decoders.Map32Header.Instance; + readNextDecoders[MessagePackCode.Map16] = Decoders.ReadNextMap.Instance; + readNextDecoders[MessagePackCode.Map32] = Decoders.ReadNextMap.Instance; + + // Array + for (int i = MessagePackCode.MinFixArray; i <= MessagePackCode.MaxFixArray; i++) + { + arrayHeaderDecoders[i] = Decoders.FixArrayHeader.Instance; + readNextDecoders[i] = Decoders.ReadNext1.Instance; + } + arrayHeaderDecoders[MessagePackCode.Array16] = Decoders.Array16Header.Instance; + arrayHeaderDecoders[MessagePackCode.Array32] = Decoders.Array32Header.Instance; + readNextDecoders[MessagePackCode.Array16] = Decoders.ReadNextArray.Instance; + readNextDecoders[MessagePackCode.Array32] = Decoders.ReadNextArray.Instance; + + // Str + for (int i = MessagePackCode.MinFixStr; i <= MessagePackCode.MaxFixStr; i++) + { + stringDecoders[i] = Decoders.FixString.Instance; + stringSegmentDecoders[i] = Decoders.FixStringSegment.Instance; + readNextDecoders[i] = Decoders.ReadNextFixStr.Instance; + } + + stringDecoders[MessagePackCode.Str8] = Decoders.Str8String.Instance; + stringDecoders[MessagePackCode.Str16] = Decoders.Str16String.Instance; + stringDecoders[MessagePackCode.Str32] = Decoders.Str32String.Instance; + stringSegmentDecoders[MessagePackCode.Str8] = Decoders.Str8StringSegment.Instance; + stringSegmentDecoders[MessagePackCode.Str16] = Decoders.Str16StringSegment.Instance; + stringSegmentDecoders[MessagePackCode.Str32] = Decoders.Str32StringSegment.Instance; + readNextDecoders[MessagePackCode.Str8] = Decoders.ReadNextStr8.Instance; + readNextDecoders[MessagePackCode.Str16] = Decoders.ReadNextStr16.Instance; + readNextDecoders[MessagePackCode.Str32] = Decoders.ReadNextStr32.Instance; + + // Others + stringDecoders[MessagePackCode.Nil] = Decoders.NilString.Instance; + stringSegmentDecoders[MessagePackCode.Nil] = Decoders.NilStringSegment.Instance; + bytesDecoders[MessagePackCode.Nil] = Decoders.NilBytes.Instance; + bytesSegmentDecoders[MessagePackCode.Nil] = Decoders.NilBytesSegment.Instance; + readNextDecoders[MessagePackCode.Nil] = Decoders.ReadNext1.Instance; + + booleanDecoders[MessagePackCode.False] = Decoders.False.Instance; + booleanDecoders[MessagePackCode.True] = Decoders.True.Instance; + readNextDecoders[MessagePackCode.False] = Decoders.ReadNext1.Instance; + readNextDecoders[MessagePackCode.True] = Decoders.ReadNext1.Instance; + + bytesDecoders[MessagePackCode.Bin8] = Decoders.Bin8Bytes.Instance; + bytesDecoders[MessagePackCode.Bin16] = Decoders.Bin16Bytes.Instance; + bytesDecoders[MessagePackCode.Bin32] = Decoders.Bin32Bytes.Instance; + bytesSegmentDecoders[MessagePackCode.Bin8] = Decoders.Bin8BytesSegment.Instance; + bytesSegmentDecoders[MessagePackCode.Bin16] = Decoders.Bin16BytesSegment.Instance; + bytesSegmentDecoders[MessagePackCode.Bin32] = Decoders.Bin32BytesSegment.Instance; + readNextDecoders[MessagePackCode.Bin8] = Decoders.ReadNextBin8.Instance; + readNextDecoders[MessagePackCode.Bin16] = Decoders.ReadNextBin16.Instance; + readNextDecoders[MessagePackCode.Bin32] = Decoders.ReadNextBin32.Instance; + + // Ext + extDecoders[MessagePackCode.FixExt1] = Decoders.FixExt1.Instance; + extDecoders[MessagePackCode.FixExt2] = Decoders.FixExt2.Instance; + extDecoders[MessagePackCode.FixExt4] = Decoders.FixExt4.Instance; + extDecoders[MessagePackCode.FixExt8] = Decoders.FixExt8.Instance; + extDecoders[MessagePackCode.FixExt16] = Decoders.FixExt16.Instance; + extDecoders[MessagePackCode.Ext8] = Decoders.Ext8.Instance; + extDecoders[MessagePackCode.Ext16] = Decoders.Ext16.Instance; + extDecoders[MessagePackCode.Ext32] = Decoders.Ext32.Instance; + + extHeaderDecoders[MessagePackCode.FixExt1] = Decoders.FixExt1Header.Instance; + extHeaderDecoders[MessagePackCode.FixExt2] = Decoders.FixExt2Header.Instance; + extHeaderDecoders[MessagePackCode.FixExt4] = Decoders.FixExt4Header.Instance; + extHeaderDecoders[MessagePackCode.FixExt8] = Decoders.FixExt8Header.Instance; + extHeaderDecoders[MessagePackCode.FixExt16] = Decoders.FixExt16Header.Instance; + extHeaderDecoders[MessagePackCode.Ext8] = Decoders.Ext8Header.Instance; + extHeaderDecoders[MessagePackCode.Ext16] = Decoders.Ext16Header.Instance; + extHeaderDecoders[MessagePackCode.Ext32] = Decoders.Ext32Header.Instance; + + + readNextDecoders[MessagePackCode.FixExt1] = Decoders.ReadNext3.Instance; + readNextDecoders[MessagePackCode.FixExt2] = Decoders.ReadNext4.Instance; + readNextDecoders[MessagePackCode.FixExt4] = Decoders.ReadNext6.Instance; + readNextDecoders[MessagePackCode.FixExt8] = Decoders.ReadNext10.Instance; + readNextDecoders[MessagePackCode.FixExt16] = Decoders.ReadNext18.Instance; + readNextDecoders[MessagePackCode.Ext8] = Decoders.ReadNextExt8.Instance; + readNextDecoders[MessagePackCode.Ext16] = Decoders.ReadNextExt16.Instance; + readNextDecoders[MessagePackCode.Ext32] = Decoders.ReadNextExt32.Instance; + + // DateTime + dateTimeDecoders[MessagePackCode.FixExt4] = Decoders.FixExt4DateTime.Instance; + dateTimeDecoders[MessagePackCode.FixExt8] = Decoders.FixExt8DateTime.Instance; + dateTimeDecoders[MessagePackCode.Ext8] = Decoders.Ext8DateTime.Instance; + } + + /// + /// A maximum allowable element count for any array or map allocated by this class + /// when reading from non-seekable streams. + /// The default is . + /// + /// + /// When reading from a byte array or seekable streams, the actual length + /// of the remaining buffer or stream is used to calculate a safe limit. + /// + public static int MaxArrayAllocationSize = int.MaxValue; + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static void EnsureCapacity(ref byte[] bytes, int offset, int appendLength) + { + var newLength = offset + appendLength; + + // If null(most case fisrt time) fill byte. + if (bytes == null) + { + bytes = new byte[newLength]; + return; + } + + // like MemoryStream.EnsureCapacity + var current = bytes.Length; + if (newLength > current) + { + int num = newLength; + if (num < 256) + { + num = 256; + FastResize(ref bytes, num); + return; + } + + if (current == ArrayMaxSize) + { + throw new InvalidOperationException("byte[] size reached maximum size of array(0x7FFFFFC7), can not write to single byte[]. Details: https://msdn.microsoft.com/en-us/library/system.array"); + } + + var newSize = unchecked((current * 2)); + if (newSize < 0) // overflow + { + num = ArrayMaxSize; + } + else + { + if (num < newSize) + { + num = newSize; + } + } + + FastResize(ref bytes, num); + } + } + + // Buffer.BlockCopy version of Array.Resize +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static void FastResize(ref byte[] array, int newSize) + { + if (newSize < 0) throw new ArgumentOutOfRangeException("newSize"); + + byte[] array2 = array; + if (array2 == null) + { + array = new byte[newSize]; + return; + } + + if (array2.Length != newSize) + { + byte[] array3 = new byte[newSize]; + Buffer.BlockCopy(array2, 0, array3, 0, (array2.Length > newSize) ? newSize : array2.Length); + array = array3; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static byte[] FastCloneWithResize(byte[] array, int newSize) + { + if (newSize < 0) throw new ArgumentOutOfRangeException("newSize"); + + byte[] array2 = array; + if (array2 == null) + { + array = new byte[newSize]; + return array; + } + + byte[] array3 = new byte[newSize]; + Buffer.BlockCopy(array2, 0, array3, 0, (array2.Length > newSize) ? newSize : array2.Length); + return array3; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static MessagePackType GetMessagePackType(byte[] bytes, int offset) + { + return MessagePackCode.ToMessagePackType(bytes[offset]); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadNext(byte[] bytes, int offset) + { + return readNextDecoders[bytes[offset]].Read(bytes, offset); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadNextBlock(byte[] bytes, int offset) + { + switch (GetMessagePackType(bytes, offset)) + { + case MessagePackType.Unknown: + case MessagePackType.Integer: + case MessagePackType.Nil: + case MessagePackType.Boolean: + case MessagePackType.Float: + case MessagePackType.String: + case MessagePackType.Binary: + case MessagePackType.Extension: + default: + return ReadNext(bytes, offset); + case MessagePackType.Array: + { + var startOffset = offset; + int readSize; + var header = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + for (int i = 0; i < header; i++) + { + offset += ReadNextBlock(bytes, offset); + } + return offset - startOffset; + } + case MessagePackType.Map: + { + var startOffset = offset; + int readSize; + var header = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + for (int i = 0; i < header; i++) + { + offset += ReadNextBlock(bytes, offset); // read key block + offset += ReadNextBlock(bytes, offset); // read value block + } + return offset - startOffset; + } + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteNil(ref byte[] bytes, int offset) + { + EnsureCapacity(ref bytes, offset, 1); + + bytes[offset] = MessagePackCode.Nil; + return 1; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static Nil ReadNil(byte[] bytes, int offset, out int readSize) + { + if (bytes[offset] == MessagePackCode.Nil) + { + readSize = 1; + return Nil.Default; + } + else + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool IsNil(byte[] bytes, int offset) + { + return bytes[offset] == MessagePackCode.Nil; + } + + public static int WriteRaw(ref byte[] bytes, int offset, byte[] rawMessagePackBlock) + { + EnsureCapacity(ref bytes, offset, rawMessagePackBlock.Length); + Buffer.BlockCopy(rawMessagePackBlock, 0, bytes, offset, rawMessagePackBlock.Length); + return rawMessagePackBlock.Length; + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackRange.MaxFixMapCount(15), can use this method. + /// + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedMapHeaderUnsafe(ref byte[] bytes, int offset, int count) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = (byte)(MessagePackCode.MinFixMap | count); + return 1; + } + + /// + /// Write map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeader(ref byte[] bytes, int offset, int count) + { + checked + { + return WriteMapHeader(ref bytes, offset, (uint)count); + } + } + + /// + /// Write map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeader(ref byte[] bytes, int offset, uint count) + { + if (count <= MessagePackRange.MaxFixMapCount) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = (byte)(MessagePackCode.MinFixMap | count); + return 1; + } + else if (count <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + unchecked + { + bytes[offset] = MessagePackCode.Map16; + bytes[offset + 1] = (byte)(count >> 8); + bytes[offset + 2] = (byte)(count); + } + return 3; + } + else + { + EnsureCapacity(ref bytes, offset, 5); + unchecked + { + bytes[offset] = MessagePackCode.Map32; + bytes[offset + 1] = (byte)(count >> 24); + bytes[offset + 2] = (byte)(count >> 16); + bytes[offset + 3] = (byte)(count >> 8); + bytes[offset + 4] = (byte)(count); + } + return 5; + } + } + + /// + /// Write map format header, always use map32 format(length is fixed, 5). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeaderForceMap32Block(ref byte[] bytes, int offset, uint count) + { + EnsureCapacity(ref bytes, offset, 5); + unchecked + { + bytes[offset] = MessagePackCode.Map32; + bytes[offset + 1] = (byte)(count >> 24); + bytes[offset + 2] = (byte)(count >> 16); + bytes[offset + 3] = (byte)(count >> 8); + bytes[offset + 4] = (byte)(count); + } + return 5; + } + + /// + /// Return map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadMapHeader(byte[] bytes, int offset, out int readSize) + { + checked + { + int count = (int)mapHeaderDecoders[bytes[offset]].Read(bytes, offset, out readSize); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + // We allow for each primitive to be the minimal 1 byte in size, and we have a key=value map, so that's 2 bytes. + if (count * 2 > bytes.Length - offset) + { + ThrowNotEnoughBytesException(); + } + + return count; + } + } + + /// + /// Return map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadMapHeaderRaw(byte[] bytes, int offset, out int readSize) + { + return ReadMapHeaderRaw(bytes, offset, checked((uint)(bytes.Length - offset)), out readSize); + } + + private static uint ReadMapHeaderRaw(byte[] bytes, int offset, uint remainingBytes, out int readSize) + { + uint count = mapHeaderDecoders[bytes[offset]].Read(bytes, offset, out readSize); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + // We allow for each primitive to be the minimal 1 byte in size, and we have a key=value map, so that's 2 bytes. + if (count * 2 > remainingBytes - readSize) + { + ThrowNotEnoughBytesException(); + } + + return count; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int GetArrayHeaderLength(int count) + { + if (count <= MessagePackRange.MaxFixArrayCount) + { + return 1; + } + else if (count <= ushort.MaxValue) + { + return 3; + } + else + { + return 5; + } + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackRange.MaxFixArrayCount(15), can use this method. + /// + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedArrayHeaderUnsafe(ref byte[] bytes, int offset, int count) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = (byte)(MessagePackCode.MinFixArray | count); + return 1; + } + + /// + /// Write array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeader(ref byte[] bytes, int offset, int count) + { + checked + { + return WriteArrayHeader(ref bytes, offset, (uint)count); + } + } + + /// + /// Write array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeader(ref byte[] bytes, int offset, uint count) + { + if (count <= MessagePackRange.MaxFixArrayCount) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = (byte)(MessagePackCode.MinFixArray | count); + return 1; + } + else if (count <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + unchecked + { + bytes[offset] = MessagePackCode.Array16; + bytes[offset + 1] = (byte)(count >> 8); + bytes[offset + 2] = (byte)(count); + } + return 3; + } + else + { + EnsureCapacity(ref bytes, offset, 5); + unchecked + { + bytes[offset] = MessagePackCode.Array32; + bytes[offset + 1] = (byte)(count >> 24); + bytes[offset + 2] = (byte)(count >> 16); + bytes[offset + 3] = (byte)(count >> 8); + bytes[offset + 4] = (byte)(count); + } + return 5; + } + } + + /// + /// Write array format header, always use array32 format(length is fixed, 5). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeaderForceArray32Block(ref byte[] bytes, int offset, uint count) + { + EnsureCapacity(ref bytes, offset, 5); + unchecked + { + bytes[offset] = MessagePackCode.Array32; + bytes[offset + 1] = (byte)(count >> 24); + bytes[offset + 2] = (byte)(count >> 16); + bytes[offset + 3] = (byte)(count >> 8); + bytes[offset + 4] = (byte)(count); + } + return 5; + } + + /// + /// Return array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadArrayHeader(byte[] bytes, int offset, out int readSize) + { + checked + { + int count = (int)arrayHeaderDecoders[bytes[offset]].Read(bytes, offset, out readSize); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + // We allow for each primitive to be the minimal 1 byte in size. + // Formatters that know each element is larger can double-check our work. + if (count > bytes.Length - offset) + { + ThrowNotEnoughBytesException(); + } + + return count; + } + } + + + /// + /// Return array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadArrayHeaderRaw(byte[] bytes, int offset, out int readSize) + { + return ReadArrayHeaderRaw(bytes, offset, checked((uint)(bytes.Length - offset)), out readSize); + } + + private static uint ReadArrayHeaderRaw(byte[] bytes, int offset, uint remainingBytes, out int readSize) + { + uint count = arrayHeaderDecoders[bytes[offset]].Read(bytes, offset, out readSize); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + // We allow for each primitive to be the minimal 1 byte in size. + // Formatters that know each element is larger can double-check our work. + if (count > remainingBytes - readSize) + { + ThrowNotEnoughBytesException(); + } + + return count; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBoolean(ref byte[] bytes, int offset, bool value) + { + EnsureCapacity(ref bytes, offset, 1); + + bytes[offset] = (value ? MessagePackCode.True : MessagePackCode.False); + return 1; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool ReadBoolean(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return booleanDecoders[bytes[offset]].Read(); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteByte(ref byte[] bytes, int offset, byte value) + { + if (value <= MessagePackCode.MaxFixInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = value; + return 1; + } + else + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = value; + return 2; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteByteForceByteBlock(ref byte[] bytes, int offset, byte value) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = value; + return 2; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static byte ReadByte(byte[] bytes, int offset, out int readSize) + { + return byteDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBytes(ref byte[] bytes, int offset, byte[] value) + { + if (value == null) + { + return WriteNil(ref bytes, offset); + } + else + { + return WriteBytes(ref bytes, offset, value, 0, value.Length); + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBytes(ref byte[] dest, int dstOffset, byte[] src, int srcOffset, int count) + { + if (src == null) + { + return WriteNil(ref dest, dstOffset); + } + + if (count <= byte.MaxValue) + { + var size = count + 2; + EnsureCapacity(ref dest, dstOffset, size); + + dest[dstOffset] = MessagePackCode.Bin8; + dest[dstOffset + 1] = (byte)count; + + Buffer.BlockCopy(src, srcOffset, dest, dstOffset + 2, count); + return size; + } + else if (count <= UInt16.MaxValue) + { + var size = count + 3; + EnsureCapacity(ref dest, dstOffset, size); + + unchecked + { + dest[dstOffset] = MessagePackCode.Bin16; + dest[dstOffset + 1] = (byte)(count >> 8); + dest[dstOffset + 2] = (byte)(count); + } + + Buffer.BlockCopy(src, srcOffset, dest, dstOffset + 3, count); + return size; + } + else + { + var size = count + 5; + EnsureCapacity(ref dest, dstOffset, size); + + unchecked + { + dest[dstOffset] = MessagePackCode.Bin32; + dest[dstOffset + 1] = (byte)(count >> 24); + dest[dstOffset + 2] = (byte)(count >> 16); + dest[dstOffset + 3] = (byte)(count >> 8); + dest[dstOffset + 4] = (byte)(count); + } + + Buffer.BlockCopy(src, srcOffset, dest, dstOffset + 5, count); + return size; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static byte[] ReadBytes(byte[] bytes, int offset, out int readSize) + { + return bytesDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ArraySegment ReadBytesSegment(byte[] bytes, int offset, out int readSize) + { + return bytesSegmentDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSByte(ref byte[] bytes, int offset, sbyte value) + { + if (value < MessagePackRange.MinFixNegativeInt) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.Int8; + bytes[offset + 1] = unchecked((byte)(value)); + return 2; + } + else + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSByteForceSByteBlock(ref byte[] bytes, int offset, sbyte value) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.Int8; + bytes[offset + 1] = unchecked((byte)(value)); + return 2; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static sbyte ReadSByte(byte[] bytes, int offset, out int readSize) + { + return sbyteDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSingle(ref byte[] bytes, int offset, float value) + { + EnsureCapacity(ref bytes, offset, 5); + + bytes[offset] = MessagePackCode.Float32; + + var num = new Float32Bits(value); + if (BitConverter.IsLittleEndian) + { + bytes[offset + 1] = num.Byte3; + bytes[offset + 2] = num.Byte2; + bytes[offset + 3] = num.Byte1; + bytes[offset + 4] = num.Byte0; + } + else + { + bytes[offset + 1] = num.Byte0; + bytes[offset + 2] = num.Byte1; + bytes[offset + 3] = num.Byte2; + bytes[offset + 4] = num.Byte3; + } + + return 5; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static float ReadSingle(byte[] bytes, int offset, out int readSize) + { + return singleDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteDouble(ref byte[] bytes, int offset, double value) + { + EnsureCapacity(ref bytes, offset, 9); + + bytes[offset] = MessagePackCode.Float64; + + var num = new Float64Bits(value); + if (BitConverter.IsLittleEndian) + { + bytes[offset + 1] = num.Byte7; + bytes[offset + 2] = num.Byte6; + bytes[offset + 3] = num.Byte5; + bytes[offset + 4] = num.Byte4; + bytes[offset + 5] = num.Byte3; + bytes[offset + 6] = num.Byte2; + bytes[offset + 7] = num.Byte1; + bytes[offset + 8] = num.Byte0; + } + else + { + bytes[offset + 1] = num.Byte0; + bytes[offset + 2] = num.Byte1; + bytes[offset + 3] = num.Byte2; + bytes[offset + 4] = num.Byte3; + bytes[offset + 5] = num.Byte4; + bytes[offset + 6] = num.Byte5; + bytes[offset + 7] = num.Byte6; + bytes[offset + 8] = num.Byte7; + } + + return 9; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static double ReadDouble(byte[] bytes, int offset, out int readSize) + { + return doubleDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt16(ref byte[] bytes, int offset, short value) + { + if (value >= 0) + { + // positive int(use uint) + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + } + else + { + // negative int(use int) + if (MessagePackRange.MinFixNegativeInt <= value) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (sbyte.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.Int8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.Int16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt16ForceInt16Block(ref byte[] bytes, int offset, short value) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.Int16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static short ReadInt16(byte[] bytes, int offset, out int readSize) + { + return int16Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackCode.MaxFixInt(127), can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WritePositiveFixedIntUnsafe(ref byte[] bytes, int offset, int value) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = (byte)value; + return 1; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt32(ref byte[] bytes, int offset, int value) + { + if (value >= 0) + { + // positive int(use uint) + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (value <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.UInt32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + } + else + { + // negative int(use int) + if (MessagePackRange.MinFixNegativeInt <= value) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (sbyte.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.Int8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (short.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.Int16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.Int32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + } + } + + /// + /// Acquire static message block(always 5 bytes). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt32ForceInt32Block(ref byte[] bytes, int offset, int value) + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.Int32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadInt32(byte[] bytes, int offset, out int readSize) + { + return int32Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt64(ref byte[] bytes, int offset, long value) + { + if (value >= 0) + { + // positive int(use uint) + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (value <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else if (value <= uint.MaxValue) + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.UInt32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + else + { + EnsureCapacity(ref bytes, offset, 9); + bytes[offset] = MessagePackCode.UInt64; + bytes[offset + 1] = unchecked((byte)(value >> 56)); + bytes[offset + 2] = unchecked((byte)(value >> 48)); + bytes[offset + 3] = unchecked((byte)(value >> 40)); + bytes[offset + 4] = unchecked((byte)(value >> 32)); + bytes[offset + 5] = unchecked((byte)(value >> 24)); + bytes[offset + 6] = unchecked((byte)(value >> 16)); + bytes[offset + 7] = unchecked((byte)(value >> 8)); + bytes[offset + 8] = unchecked((byte)value); + return 9; + } + } + else + { + // negative int(use int) + if (MessagePackRange.MinFixNegativeInt <= value) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (sbyte.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.Int8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (short.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.Int16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else if (int.MinValue <= value) + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.Int32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + else + { + EnsureCapacity(ref bytes, offset, 9); + bytes[offset] = MessagePackCode.Int64; + bytes[offset + 1] = unchecked((byte)(value >> 56)); + bytes[offset + 2] = unchecked((byte)(value >> 48)); + bytes[offset + 3] = unchecked((byte)(value >> 40)); + bytes[offset + 4] = unchecked((byte)(value >> 32)); + bytes[offset + 5] = unchecked((byte)(value >> 24)); + bytes[offset + 6] = unchecked((byte)(value >> 16)); + bytes[offset + 7] = unchecked((byte)(value >> 8)); + bytes[offset + 8] = unchecked((byte)value); + return 9; + } + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt64ForceInt64Block(ref byte[] bytes, int offset, long value) + { + EnsureCapacity(ref bytes, offset, 9); + bytes[offset] = MessagePackCode.Int64; + bytes[offset + 1] = unchecked((byte)(value >> 56)); + bytes[offset + 2] = unchecked((byte)(value >> 48)); + bytes[offset + 3] = unchecked((byte)(value >> 40)); + bytes[offset + 4] = unchecked((byte)(value >> 32)); + bytes[offset + 5] = unchecked((byte)(value >> 24)); + bytes[offset + 6] = unchecked((byte)(value >> 16)); + bytes[offset + 7] = unchecked((byte)(value >> 8)); + bytes[offset + 8] = unchecked((byte)value); + return 9; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static long ReadInt64(byte[] bytes, int offset, out int readSize) + { + return int64Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt16(ref byte[] bytes, int offset, ushort value) + { + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt16ForceUInt16Block(ref byte[] bytes, int offset, ushort value) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ushort ReadUInt16(byte[] bytes, int offset, out int readSize) + { + return uint16Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt32(ref byte[] bytes, int offset, uint value) + { + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (value <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.UInt32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt32ForceUInt32Block(ref byte[] bytes, int offset, uint value) + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.UInt32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadUInt32(byte[] bytes, int offset, out int readSize) + { + return uint32Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt64(ref byte[] bytes, int offset, ulong value) + { + if (value <= MessagePackRange.MaxFixPositiveInt) + { + EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = unchecked((byte)value); + return 1; + } + else if (value <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, 2); + bytes[offset] = MessagePackCode.UInt8; + bytes[offset + 1] = unchecked((byte)value); + return 2; + } + else if (value <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.UInt16; + bytes[offset + 1] = unchecked((byte)(value >> 8)); + bytes[offset + 2] = unchecked((byte)value); + return 3; + } + else if (value <= uint.MaxValue) + { + EnsureCapacity(ref bytes, offset, 5); + bytes[offset] = MessagePackCode.UInt32; + bytes[offset + 1] = unchecked((byte)(value >> 24)); + bytes[offset + 2] = unchecked((byte)(value >> 16)); + bytes[offset + 3] = unchecked((byte)(value >> 8)); + bytes[offset + 4] = unchecked((byte)value); + return 5; + } + else + { + EnsureCapacity(ref bytes, offset, 9); + bytes[offset] = MessagePackCode.UInt64; + bytes[offset + 1] = unchecked((byte)(value >> 56)); + bytes[offset + 2] = unchecked((byte)(value >> 48)); + bytes[offset + 3] = unchecked((byte)(value >> 40)); + bytes[offset + 4] = unchecked((byte)(value >> 32)); + bytes[offset + 5] = unchecked((byte)(value >> 24)); + bytes[offset + 6] = unchecked((byte)(value >> 16)); + bytes[offset + 7] = unchecked((byte)(value >> 8)); + bytes[offset + 8] = unchecked((byte)value); + return 9; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt64ForceUInt64Block(ref byte[] bytes, int offset, ulong value) + { + EnsureCapacity(ref bytes, offset, 9); + bytes[offset] = MessagePackCode.UInt64; + bytes[offset + 1] = unchecked((byte)(value >> 56)); + bytes[offset + 2] = unchecked((byte)(value >> 48)); + bytes[offset + 3] = unchecked((byte)(value >> 40)); + bytes[offset + 4] = unchecked((byte)(value >> 32)); + bytes[offset + 5] = unchecked((byte)(value >> 24)); + bytes[offset + 6] = unchecked((byte)(value >> 16)); + bytes[offset + 7] = unchecked((byte)(value >> 8)); + bytes[offset + 8] = unchecked((byte)value); + return 9; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ulong ReadUInt64(byte[] bytes, int offset, out int readSize) + { + return uint64Decoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteChar(ref byte[] bytes, int offset, char value) + { + return WriteUInt16(ref bytes, offset, (ushort)value); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static char ReadChar(byte[] bytes, int offset, out int readSize) + { + return (char)ReadUInt16(bytes, offset, out readSize); + } + + /// + /// Unsafe. If value is guranteed length is 0 ~ 31, can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedStringUnsafe(ref byte[] bytes, int offset, string value, int byteCount) + { + EnsureCapacity(ref bytes, offset, byteCount + 1); + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 1); + + return byteCount + 1; + } + + /// + /// Unsafe. If pre-calculated byteCount of target string, can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteStringUnsafe(ref byte[] bytes, int offset, string value, int byteCount) + { + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + EnsureCapacity(ref bytes, offset, byteCount + 1); + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 1); + return byteCount + 1; + } + else if (byteCount <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, byteCount + 2); + bytes[offset] = MessagePackCode.Str8; + bytes[offset + 1] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 2); + return byteCount + 2; + } + else if (byteCount <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, byteCount + 3); + bytes[offset] = MessagePackCode.Str16; + bytes[offset + 1] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 2] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 3); + return byteCount + 3; + } + else + { + EnsureCapacity(ref bytes, offset, byteCount + 5); + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 5); + return byteCount + 5; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteStringBytes(ref byte[] bytes, int offset, byte[] utf8stringBytes) + { + var byteCount = utf8stringBytes.Length; + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + EnsureCapacity(ref bytes, offset, byteCount + 1); + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + Buffer.BlockCopy(utf8stringBytes, 0, bytes, offset + 1, byteCount); + return byteCount + 1; + } + else if (byteCount <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, byteCount + 2); + bytes[offset] = MessagePackCode.Str8; + bytes[offset + 1] = unchecked((byte)byteCount); + Buffer.BlockCopy(utf8stringBytes, 0, bytes, offset + 2, byteCount); + return byteCount + 2; + } + else if (byteCount <= ushort.MaxValue) + { + EnsureCapacity(ref bytes, offset, byteCount + 3); + bytes[offset] = MessagePackCode.Str16; + bytes[offset + 1] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 2] = unchecked((byte)byteCount); + Buffer.BlockCopy(utf8stringBytes, 0, bytes, offset + 3, byteCount); + return byteCount + 3; + } + else + { + EnsureCapacity(ref bytes, offset, byteCount + 5); + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + Buffer.BlockCopy(utf8stringBytes, 0, bytes, offset + 5, byteCount); + return byteCount + 5; + } + } + + public static byte[] GetEncodedStringBytes(string value) + { + var byteCount = StringEncoding.UTF8.GetByteCount(value); + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + var bytes = new byte[byteCount + 1]; + bytes[0] = (byte)(MessagePackCode.MinFixStr | byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 1); + return bytes; + } + else if (byteCount <= byte.MaxValue) + { + var bytes = new byte[byteCount + 2]; + bytes[0] = MessagePackCode.Str8; + bytes[1] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 2); + return bytes; + } + else if (byteCount <= ushort.MaxValue) + { + var bytes = new byte[byteCount + 3]; + bytes[0] = MessagePackCode.Str16; + bytes[1] = unchecked((byte)(byteCount >> 8)); + bytes[2] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 3); + return bytes; + } + else + { + var bytes = new byte[byteCount + 5]; + bytes[0] = MessagePackCode.Str32; + bytes[1] = unchecked((byte)(byteCount >> 24)); + bytes[2] = unchecked((byte)(byteCount >> 16)); + bytes[3] = unchecked((byte)(byteCount >> 8)); + bytes[4] = unchecked((byte)byteCount); + StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, 5); + return bytes; + } + } + + public static int WriteString(ref byte[] bytes, int offset, string value) + { + if (value == null) return WriteNil(ref bytes, offset); + + // MaxByteCount -> WritePrefix -> GetBytes has some overheads of `MaxByteCount` + // solves heuristic length check + + // ensure buffer by MaxByteCount(faster than GetByteCount) + MessagePackBinary.EnsureCapacity(ref bytes, offset, StringEncoding.UTF8.GetMaxByteCount(value.Length) + 5); + + int useOffset; + if (value.Length <= MessagePackRange.MaxFixStringLength) + { + useOffset = 1; + } + else if (value.Length <= byte.MaxValue) + { + useOffset = 2; + } + else if (value.Length <= ushort.MaxValue) + { + useOffset = 3; + } + else + { + useOffset = 5; + } + + // skip length area + var writeBeginOffset = offset + useOffset; + var byteCount = StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, writeBeginOffset); + + // move body and write prefix + if (byteCount <= MessagePackRange.MaxFixStringLength) + { + if (useOffset != 1) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 1, byteCount); + } + bytes[offset] = (byte)(MessagePackCode.MinFixStr | byteCount); + return byteCount + 1; + } + else if (byteCount <= byte.MaxValue) + { + if (useOffset != 2) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 2, byteCount); + } + + bytes[offset] = MessagePackCode.Str8; + bytes[offset + 1] = unchecked((byte)byteCount); + return byteCount + 2; + } + else if (byteCount <= ushort.MaxValue) + { + if (useOffset != 3) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 3, byteCount); + } + + bytes[offset] = MessagePackCode.Str16; + bytes[offset + 1] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 2] = unchecked((byte)byteCount); + return byteCount + 3; + } + else + { + if (useOffset != 5) + { + Buffer.BlockCopy(bytes, writeBeginOffset, bytes, offset + 5, byteCount); + } + + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + return byteCount + 5; + } + } + + public static int WriteStringForceStr32Block(ref byte[] bytes, int offset, string value) + { + if (value == null) return WriteNil(ref bytes, offset); + + MessagePackBinary.EnsureCapacity(ref bytes, offset, StringEncoding.UTF8.GetMaxByteCount(value.Length) + 5); + + var byteCount = StringEncoding.UTF8.GetBytes(value, 0, value.Length, bytes, offset + 5); + + bytes[offset] = MessagePackCode.Str32; + bytes[offset + 1] = unchecked((byte)(byteCount >> 24)); + bytes[offset + 2] = unchecked((byte)(byteCount >> 16)); + bytes[offset + 3] = unchecked((byte)(byteCount >> 8)); + bytes[offset + 4] = unchecked((byte)byteCount); + return byteCount + 5; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static string ReadString(byte[] bytes, int offset, out int readSize) + { + return stringDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ArraySegment ReadStringSegment(byte[] bytes, int offset, out int readSize) + { + return stringSegmentDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormatHeader(ref byte[] bytes, int offset, sbyte typeCode, int dataLength) + { + switch (dataLength) + { + case 1: + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.FixExt1; + bytes[offset + 1] = unchecked((byte)typeCode); + return 2; + case 2: + EnsureCapacity(ref bytes, offset, 4); + bytes[offset] = MessagePackCode.FixExt2; + bytes[offset + 1] = unchecked((byte)typeCode); + return 2; + case 4: + EnsureCapacity(ref bytes, offset, 6); + bytes[offset] = MessagePackCode.FixExt4; + bytes[offset + 1] = unchecked((byte)typeCode); + return 2; + case 8: + EnsureCapacity(ref bytes, offset, 10); + bytes[offset] = MessagePackCode.FixExt8; + bytes[offset + 1] = unchecked((byte)typeCode); + return 2; + case 16: + EnsureCapacity(ref bytes, offset, 18); + bytes[offset] = MessagePackCode.FixExt16; + bytes[offset + 1] = unchecked((byte)typeCode); + return 2; + default: + unchecked + { + if (dataLength <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, dataLength + 3); + bytes[offset] = MessagePackCode.Ext8; + bytes[offset + 1] = unchecked((byte)(dataLength)); + bytes[offset + 2] = unchecked((byte)typeCode); + return 3; + } + else if (dataLength <= UInt16.MaxValue) + { + EnsureCapacity(ref bytes, offset, dataLength + 4); + bytes[offset] = MessagePackCode.Ext16; + bytes[offset + 1] = unchecked((byte)(dataLength >> 8)); + bytes[offset + 2] = unchecked((byte)(dataLength)); + bytes[offset + 3] = unchecked((byte)typeCode); + return 4; + } + else + { + EnsureCapacity(ref bytes, offset, dataLength + 6); + bytes[offset] = MessagePackCode.Ext32; + bytes[offset + 1] = unchecked((byte)(dataLength >> 24)); + bytes[offset + 2] = unchecked((byte)(dataLength >> 16)); + bytes[offset + 3] = unchecked((byte)(dataLength >> 8)); + bytes[offset + 4] = unchecked((byte)dataLength); + bytes[offset + 5] = unchecked((byte)typeCode); + return 6; + } + } + } + } + + /// + /// Write extension format header, always use ext32 format(length is fixed, 6). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormatHeaderForceExt32Block(ref byte[] bytes, int offset, sbyte typeCode, int dataLength) + { + EnsureCapacity(ref bytes, offset, dataLength + 6); + bytes[offset] = MessagePackCode.Ext32; + bytes[offset + 1] = unchecked((byte)(dataLength >> 24)); + bytes[offset + 2] = unchecked((byte)(dataLength >> 16)); + bytes[offset + 3] = unchecked((byte)(dataLength >> 8)); + bytes[offset + 4] = unchecked((byte)dataLength); + bytes[offset + 5] = unchecked((byte)typeCode); + return 6; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormat(ref byte[] bytes, int offset, sbyte typeCode, byte[] data) + { + var length = data.Length; + switch (length) + { + case 1: + EnsureCapacity(ref bytes, offset, 3); + bytes[offset] = MessagePackCode.FixExt1; + bytes[offset + 1] = unchecked((byte)typeCode); + bytes[offset + 2] = data[0]; + return 3; + case 2: + EnsureCapacity(ref bytes, offset, 4); + bytes[offset] = MessagePackCode.FixExt2; + bytes[offset + 1] = unchecked((byte)typeCode); + bytes[offset + 2] = data[0]; + bytes[offset + 3] = data[1]; + return 4; + case 4: + EnsureCapacity(ref bytes, offset, 6); + bytes[offset] = MessagePackCode.FixExt4; + bytes[offset + 1] = unchecked((byte)typeCode); + bytes[offset + 2] = data[0]; + bytes[offset + 3] = data[1]; + bytes[offset + 4] = data[2]; + bytes[offset + 5] = data[3]; + return 6; + case 8: + EnsureCapacity(ref bytes, offset, 10); + bytes[offset] = MessagePackCode.FixExt8; + bytes[offset + 1] = unchecked((byte)typeCode); + bytes[offset + 2] = data[0]; + bytes[offset + 3] = data[1]; + bytes[offset + 4] = data[2]; + bytes[offset + 5] = data[3]; + bytes[offset + 6] = data[4]; + bytes[offset + 7] = data[5]; + bytes[offset + 8] = data[6]; + bytes[offset + 9] = data[7]; + return 10; + case 16: + EnsureCapacity(ref bytes, offset, 18); + bytes[offset] = MessagePackCode.FixExt16; + bytes[offset + 1] = unchecked((byte)typeCode); + bytes[offset + 2] = data[0]; + bytes[offset + 3] = data[1]; + bytes[offset + 4] = data[2]; + bytes[offset + 5] = data[3]; + bytes[offset + 6] = data[4]; + bytes[offset + 7] = data[5]; + bytes[offset + 8] = data[6]; + bytes[offset + 9] = data[7]; + bytes[offset + 10] = data[8]; + bytes[offset + 11] = data[9]; + bytes[offset + 12] = data[10]; + bytes[offset + 13] = data[11]; + bytes[offset + 14] = data[12]; + bytes[offset + 15] = data[13]; + bytes[offset + 16] = data[14]; + bytes[offset + 17] = data[15]; + return 18; + default: + unchecked + { + if (data.Length <= byte.MaxValue) + { + EnsureCapacity(ref bytes, offset, length + 3); + bytes[offset] = MessagePackCode.Ext8; + bytes[offset + 1] = unchecked((byte)(length)); + bytes[offset + 2] = unchecked((byte)typeCode); + Buffer.BlockCopy(data, 0, bytes, offset + 3, length); + return length + 3; + } + else if (data.Length <= UInt16.MaxValue) + { + EnsureCapacity(ref bytes, offset, length + 4); + bytes[offset] = MessagePackCode.Ext16; + bytes[offset + 1] = unchecked((byte)(length >> 8)); + bytes[offset + 2] = unchecked((byte)(length)); + bytes[offset + 3] = unchecked((byte)typeCode); + Buffer.BlockCopy(data, 0, bytes, offset + 4, length); + return length + 4; + } + else + { + EnsureCapacity(ref bytes, offset, length + 6); + bytes[offset] = MessagePackCode.Ext32; + bytes[offset + 1] = unchecked((byte)(length >> 24)); + bytes[offset + 2] = unchecked((byte)(length >> 16)); + bytes[offset + 3] = unchecked((byte)(length >> 8)); + bytes[offset + 4] = unchecked((byte)length); + bytes[offset + 5] = unchecked((byte)typeCode); + Buffer.BlockCopy(data, 0, bytes, offset + 6, length); + return length + 6; + } + } + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ExtensionResult ReadExtensionFormat(byte[] bytes, int offset, out int readSize) + { + return extDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + + /// + /// return byte length of ExtensionFormat. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ExtensionHeader ReadExtensionFormatHeader(byte[] bytes, int offset, out int readSize) + { + return extHeaderDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int GetExtensionFormatHeaderLength(int dataLength) + { + switch (dataLength) + { + case 1: + case 2: + case 4: + case 8: + case 16: + return 2; + default: + if (dataLength <= byte.MaxValue) + { + return 3; + } + else if (dataLength <= UInt16.MaxValue) + { + return 4; + } + else + { + return 6; + } + } + } + + // Timestamp spec + // https://github.com/msgpack/msgpack/pull/209 + // FixExt4(-1) => seconds | [1970-01-01 00:00:00 UTC, 2106-02-07 06:28:16 UTC) range + // FixExt8(-1) => nanoseconds + seconds | [1970-01-01 00:00:00.000000000 UTC, 2514-05-30 01:53:04.000000000 UTC) range + // Ext8(12,-1) => nanoseconds + seconds | [-584554047284-02-23 16:59:44 UTC, 584554051223-11-09 07:00:16.000000000 UTC) range + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteDateTime(ref byte[] bytes, int offset, DateTime dateTime) + { + dateTime = dateTime.ToUniversalTime(); + + var secondsSinceBclEpoch = dateTime.Ticks / TimeSpan.TicksPerSecond; + var seconds = secondsSinceBclEpoch - DateTimeConstants.BclSecondsAtUnixEpoch; + var nanoseconds = (dateTime.Ticks % TimeSpan.TicksPerSecond) * DateTimeConstants.NanosecondsPerTick; + + // reference pseudo code. + /* + struct timespec { + long tv_sec; // seconds + long tv_nsec; // nanoseconds + } time; + if ((time.tv_sec >> 34) == 0) + { + uint64_t data64 = (time.tv_nsec << 34) | time.tv_sec; + if (data & 0xffffffff00000000L == 0) + { + // timestamp 32 + uint32_t data32 = data64; + serialize(0xd6, -1, data32) + } + else + { + // timestamp 64 + serialize(0xd7, -1, data64) + } + } + else + { + // timestamp 96 + serialize(0xc7, 12, -1, time.tv_nsec, time.tv_sec) + } + */ + + if ((seconds >> 34) == 0) + { + var data64 = unchecked((ulong)((nanoseconds << 34) | seconds)); + if ((data64 & 0xffffffff00000000L) == 0) + { + // timestamp 32(seconds in 32-bit unsigned int) + var data32 = (UInt32)data64; + EnsureCapacity(ref bytes, offset, 6); + bytes[offset] = MessagePackCode.FixExt4; + bytes[offset + 1] = unchecked((byte)ReservedMessagePackExtensionTypeCode.DateTime); + bytes[offset + 2] = unchecked((byte)(data32 >> 24)); + bytes[offset + 3] = unchecked((byte)(data32 >> 16)); + bytes[offset + 4] = unchecked((byte)(data32 >> 8)); + bytes[offset + 5] = unchecked((byte)data32); + return 6; + } + else + { + // timestamp 64(nanoseconds in 30-bit unsigned int | seconds in 34-bit unsigned int) + EnsureCapacity(ref bytes, offset, 10); + bytes[offset] = MessagePackCode.FixExt8; + bytes[offset + 1] = unchecked((byte)ReservedMessagePackExtensionTypeCode.DateTime); + bytes[offset + 2] = unchecked((byte)(data64 >> 56)); + bytes[offset + 3] = unchecked((byte)(data64 >> 48)); + bytes[offset + 4] = unchecked((byte)(data64 >> 40)); + bytes[offset + 5] = unchecked((byte)(data64 >> 32)); + bytes[offset + 6] = unchecked((byte)(data64 >> 24)); + bytes[offset + 7] = unchecked((byte)(data64 >> 16)); + bytes[offset + 8] = unchecked((byte)(data64 >> 8)); + bytes[offset + 9] = unchecked((byte)data64); + return 10; + } + } + else + { + // timestamp 96( nanoseconds in 32-bit unsigned int | seconds in 64-bit signed int ) + EnsureCapacity(ref bytes, offset, 15); + bytes[offset] = MessagePackCode.Ext8; + bytes[offset + 1] = (byte)12; + bytes[offset + 2] = unchecked((byte)ReservedMessagePackExtensionTypeCode.DateTime); + bytes[offset + 3] = unchecked((byte)(nanoseconds >> 24)); + bytes[offset + 4] = unchecked((byte)(nanoseconds >> 16)); + bytes[offset + 5] = unchecked((byte)(nanoseconds >> 8)); + bytes[offset + 6] = unchecked((byte)nanoseconds); + bytes[offset + 7] = unchecked((byte)(seconds >> 56)); + bytes[offset + 8] = unchecked((byte)(seconds >> 48)); + bytes[offset + 9] = unchecked((byte)(seconds >> 40)); + bytes[offset + 10] = unchecked((byte)(seconds >> 32)); + bytes[offset + 11] = unchecked((byte)(seconds >> 24)); + bytes[offset + 12] = unchecked((byte)(seconds >> 16)); + bytes[offset + 13] = unchecked((byte)(seconds >> 8)); + bytes[offset + 14] = unchecked((byte)seconds); + return 15; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static DateTime ReadDateTime(byte[] bytes, int offset, out int readSize) + { + return dateTimeDecoders[bytes[offset]].Read(bytes, offset, out readSize); + } + + /// + /// Throws an exception indicating that there aren't enough bytes remaining in the buffer to store + /// the promised data. + /// + internal static void ThrowNotEnoughBytesException() + { + throw new EndOfStreamException(); + } + } + + // Stream Overload + internal static partial class MessagePackBinary + { + static class StreamDecodeMemoryPool + { + [ThreadStatic] + static byte[] buffer = null; + + public static byte[] GetBuffer() + { + if (buffer == null) + { + buffer = new byte[65536]; + } + return buffer; + } + } + + static byte[] ReadMessageBlockFromStreamUnsafe(Stream stream) + { + int _; + return ReadMessageBlockFromStreamUnsafe(stream, false, out _); + } + + /// + /// Read MessageBlock, returns byte[] block is in MemoryPool so careful to use. + /// + public static byte[] ReadMessageBlockFromStreamUnsafe(Stream stream, bool readOnlySingleMessage, out int readSize) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + readSize = ReadMessageBlockFromStreamCore(stream, ref bytes, 0, readOnlySingleMessage); + return bytes; + } + + static int ReadMessageBlockFromStreamCore(Stream stream, ref byte[] bytes, int offset, bool readOnlySingleMessage) + { + var byteCode = stream.ReadByte(); + if (byteCode < 0 || byte.MaxValue < byteCode) + { + throw new InvalidOperationException("Invalid MessagePack code was detected, code:" + byteCode); + } + + var code = (byte)byteCode; + + MessagePackBinary.EnsureCapacity(ref bytes, offset, 1); + bytes[offset] = code; + + var type = MessagePackCode.ToMessagePackType(code); + switch (type) + { + case MessagePackType.Integer: + { + var readCount = 0; + if (MessagePackCode.MinNegativeFixInt <= code && code <= MessagePackCode.MaxNegativeFixInt) return 1; + else if (MessagePackCode.MinFixInt <= code && code <= MessagePackCode.MaxFixInt) return 1; + + switch (code) + { + case MessagePackCode.Int8: readCount = 1; break; + case MessagePackCode.Int16: readCount = 2; break; + case MessagePackCode.Int32: readCount = 4; break; + case MessagePackCode.Int64: readCount = 8; break; + case MessagePackCode.UInt8: readCount = 1; break; + case MessagePackCode.UInt16: readCount = 2; break; + case MessagePackCode.UInt32: readCount = 4; break; + case MessagePackCode.UInt64: readCount = 8; break; + default: throw new InvalidOperationException("Invalid Code"); + } + + MessagePackBinary.EnsureCapacity(ref bytes, offset, readCount + 1); + ReadFully(stream, bytes, offset + 1, readCount); + return readCount + 1; + } + case MessagePackType.Unknown: + case MessagePackType.Nil: + case MessagePackType.Boolean: + return 1; + case MessagePackType.Float: + if (code == MessagePackCode.Float32) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 5); + ReadFully(stream, bytes, offset + 1, 4); + return 5; + } + else + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 9); + ReadFully(stream, bytes, offset + 1, 8); + return 9; + } + case MessagePackType.String: + { + if (MessagePackCode.MinFixStr <= code && code <= MessagePackCode.MaxFixStr) + { + var length = bytes[offset] & 0x1F; + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 1 + length); + ReadFully(stream, bytes, offset + 1, length); + return length + 1; + } + + switch (code) + { + case MessagePackCode.Str8: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 2); + ReadFully(stream, bytes, offset + 1, 1); + var length = bytes[offset + 1]; + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 2 + length); + ReadFully(stream, bytes, offset + 2, length); + + return length + 2; + } + case MessagePackCode.Str16: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 3); + ReadFully(stream, bytes, offset + 1, 2); + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 3 + length); + ReadFully(stream, bytes, offset + 3, length); + + return length + 3; + } + case MessagePackCode.Str32: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 5); + ReadFully(stream, bytes, offset + 1, 4); + var length = (bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | (bytes[offset + 4]); + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 5 + length); + ReadFully(stream, bytes, offset + 5, length); + + return length + 5; + } + default: throw new InvalidOperationException("Invalid Code"); + } + } + case MessagePackType.Binary: + { + switch (code) + { + case MessagePackCode.Bin8: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 2); + ReadFully(stream, bytes, offset + 1, 1); + var length = bytes[offset + 1]; + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 2 + length); + ReadFully(stream, bytes, offset + 2, length); + + return length + 2; + } + case MessagePackCode.Bin16: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 3); + ReadFully(stream, bytes, offset + 1, 2); + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 3 + length); + ReadFully(stream, bytes, offset + 3, length); + + return length + 3; + } + case MessagePackCode.Bin32: + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, 5); + ReadFully(stream, bytes, offset + 1, 4); + var length = (bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | (bytes[offset + 4]); + + ThrowIfNotEnoughBytesRemaining(stream, length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 5 + length); + ReadFully(stream, bytes, offset + 5, length); + + return length + 5; + } + default: throw new InvalidOperationException("Invalid Code"); + } + } + case MessagePackType.Array: + { + var readHeaderSize = 0; + + if (MessagePackCode.MinFixArray <= code && code <= MessagePackCode.MaxFixArray) readHeaderSize = 0; + else if (code == MessagePackCode.Array16) readHeaderSize = 2; + else if (code == MessagePackCode.Array32) readHeaderSize = 4; + if (readHeaderSize != 0) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, readHeaderSize + 1); + ReadFully(stream, bytes, offset + 1, readHeaderSize); + } + + var startOffset = offset; + offset += (readHeaderSize + 1); + uint remainingBytes = stream.CanSeek ? (uint)(stream.Length - startOffset) : uint.MaxValue; + + int _; + var length = ReadArrayHeaderRaw(bytes, startOffset, remainingBytes, out _); + if (!readOnlySingleMessage) + { + for (int i = 0; i < length; i++) + { + offset += ReadMessageBlockFromStreamCore(stream, ref bytes, offset, readOnlySingleMessage); + } + } + + return offset - startOffset; + } + case MessagePackType.Map: + { + var readHeaderSize = 0; + + if (MessagePackCode.MinFixMap <= code && code <= MessagePackCode.MaxFixMap) readHeaderSize = 0; + else if (code == MessagePackCode.Map16) readHeaderSize = 2; + else if (code == MessagePackCode.Map32) readHeaderSize = 4; + if (readHeaderSize != 0) + { + MessagePackBinary.EnsureCapacity(ref bytes, offset, readHeaderSize + 1); + ReadFully(stream, bytes, offset + 1, readHeaderSize); + } + + var startOffset = offset; + offset += (readHeaderSize + 1); + uint remainingBytes = stream.CanSeek ? (uint)(stream.Length - startOffset) : uint.MaxValue; + + int _; + var length = ReadMapHeaderRaw(bytes, startOffset, remainingBytes, out _); + if (!readOnlySingleMessage) + { + for (int i = 0; i < length; i++) + { + offset += ReadMessageBlockFromStreamCore(stream, ref bytes, offset, readOnlySingleMessage); // key + offset += ReadMessageBlockFromStreamCore(stream, ref bytes, offset, readOnlySingleMessage); // value + } + } + + return offset - startOffset; + } + case MessagePackType.Extension: + { + var readHeaderSize = 0; + + switch (code) + { + case MessagePackCode.FixExt1: readHeaderSize = 1; break; + case MessagePackCode.FixExt2: readHeaderSize = 1; break; + case MessagePackCode.FixExt4: readHeaderSize = 1; break; + case MessagePackCode.FixExt8: readHeaderSize = 1; break; + case MessagePackCode.FixExt16: readHeaderSize = 1; break; + case MessagePackCode.Ext8: readHeaderSize = 2; break; + case MessagePackCode.Ext16: readHeaderSize = 3; break; + case MessagePackCode.Ext32: readHeaderSize = 5; break; + default: throw new InvalidOperationException("Invalid Code"); + } + + MessagePackBinary.EnsureCapacity(ref bytes, offset, readHeaderSize + 1); + ReadFully(stream, bytes, offset + 1, readHeaderSize); + + if (!readOnlySingleMessage) + { + int _; + var header = ReadExtensionFormatHeader(bytes, offset, out _); + + ThrowIfNotEnoughBytesRemaining(stream, (int)header.Length); + MessagePackBinary.EnsureCapacity(ref bytes, offset, 1 + readHeaderSize + (int)header.Length); + ReadFully(stream, bytes, offset + 1 + readHeaderSize, (int)header.Length); + + return 1 + readHeaderSize + (int)header.Length; + } + else + { + return readHeaderSize + 1; + } + } + default: throw new InvalidOperationException("Invalid Code"); + } + } + + private static void ThrowIfNotEnoughBytesRemaining(Stream stream, int length) + { + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + // For streams, we can only predict length when the streams are seekable. + int upperLimit = stream.CanSeek ? checked((int)(stream.Length - stream.Position)) : MaxArrayAllocationSize; + if (stream.CanSeek && length > upperLimit) + { + ThrowNotEnoughBytesException(); + } + } + + static void ReadFully(Stream stream, byte[] bytes, int offset, int readSize) + { + var nextLen = readSize; + while (nextLen != 0) + { + var len = stream.Read(bytes, offset, nextLen); + if (len == -1) return; + offset += len; + nextLen = nextLen - len; + } + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadNext(Stream stream) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + return ReadMessageBlockFromStreamCore(stream, ref bytes, 0, true); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadNextBlock(Stream stream) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + var offset = 0; + return ReadMessageBlockFromStreamCore(stream, ref bytes, offset, false); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteNil(Stream stream) + { + stream.WriteByte(MessagePackCode.Nil); + return 1; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static Nil ReadNil(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadNil(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool IsNil(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + + return bytes[offset] == MessagePackCode.Nil; + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackRange.MaxFixMapCount(15), can use this method. + /// + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedMapHeaderUnsafe(Stream stream, int count) + { + stream.WriteByte((byte)(MessagePackCode.MinFixMap | count)); + return 1; + } + + /// + /// Write map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeader(Stream stream, int count) + { + checked + { + return WriteMapHeader(stream, (uint)count); + } + } + + /// + /// Write map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeader(Stream stream, uint count) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteMapHeader(ref buffer, 0, count); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Write map format header, always use map32 format(length is fixed, 5). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteMapHeaderForceMap32Block(Stream stream, uint count) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteMapHeaderForceMap32Block(ref buffer, 0, count); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Return map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadMapHeader(Stream stream) + { + checked + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + ReadMessageBlockFromStreamCore(stream, ref bytes, 0, true); + int readSize; + return ReadMapHeader(bytes, 0, out readSize); + } + } + + /// + /// Return map count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadMapHeaderRaw(Stream stream) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + ReadMessageBlockFromStreamCore(stream, ref bytes, 0, true); + int readSize; + return ReadMapHeaderRaw(bytes, 0, out readSize); + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackRange.MaxFixArrayCount(15), can use this method. + /// + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedArrayHeaderUnsafe(Stream stream, int count) + { + stream.WriteByte((byte)(MessagePackCode.MinFixArray | count)); + return 1; + } + + /// + /// Write array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeader(Stream stream, int count) + { + checked + { + return WriteArrayHeader(stream, (uint)count); + } + } + + /// + /// Write array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeader(Stream stream, uint count) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteArrayHeader(ref buffer, 0, count); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Write array format header, always use array32 format(length is fixed, 5). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteArrayHeaderForceArray32Block(Stream stream, uint count) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteArrayHeaderForceArray32Block(ref buffer, 0, count); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Return array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadArrayHeader(Stream stream) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + ReadMessageBlockFromStreamCore(stream, ref bytes, 0, true); + int readSize; + return ReadArrayHeader(bytes, 0, out readSize); + } + + /// + /// Return array count. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadArrayHeaderRaw(Stream stream) + { + var bytes = StreamDecodeMemoryPool.GetBuffer(); + ReadMessageBlockFromStreamCore(stream, ref bytes, 0, true); + int readSize; + return ReadArrayHeaderRaw(bytes, 0, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBoolean(Stream stream, bool value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteBoolean(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static bool ReadBoolean(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadBoolean(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteByte(Stream stream, byte value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteByte(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteByteForceByteBlock(Stream stream, byte value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteByteForceByteBlock(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static byte ReadByte(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadByte(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBytes(Stream stream, byte[] value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteBytes(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteBytes(Stream stream, byte[] src, int srcOffset, int count) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteBytes(ref buffer, 0, src, srcOffset, count); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static byte[] ReadBytes(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadBytes(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSByte(Stream stream, sbyte value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteSByte(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSByteForceSByteBlock(Stream stream, sbyte value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteSByteForceSByteBlock(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static sbyte ReadSByte(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadSByte(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteSingle(Stream stream, float value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteSingle(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static float ReadSingle(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadSingle(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteDouble(Stream stream, double value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteDouble(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static double ReadDouble(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadDouble(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt16(Stream stream, short value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt16(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt16ForceInt16Block(Stream stream, short value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt16ForceInt16Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static short ReadInt16(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadInt16(bytes, offset, out readSize); + } + + /// + /// Unsafe. If value is guranteed 0 ~ MessagePackCode.MaxFixInt(127), can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WritePositiveFixedIntUnsafe(Stream stream, int value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WritePositiveFixedIntUnsafe(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt32(Stream stream, int value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt32(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Acquire static message block(always 5 bytes). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt32ForceInt32Block(Stream stream, int value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt32ForceInt32Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int ReadInt32(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadInt32(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt64(Stream stream, long value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt64(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteInt64ForceInt64Block(Stream stream, long value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteInt64ForceInt64Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static long ReadInt64(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadInt64(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt16(Stream stream, ushort value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt16(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt16ForceUInt16Block(Stream stream, ushort value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt16ForceUInt16Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ushort ReadUInt16(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadUInt16(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt32(Stream stream, uint value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt32(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt32ForceUInt32Block(Stream stream, uint value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt32ForceUInt32Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static uint ReadUInt32(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadUInt32(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt64(Stream stream, ulong value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt64(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteUInt64ForceUInt64Block(Stream stream, ulong value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteUInt64ForceUInt64Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ulong ReadUInt64(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadUInt64(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteChar(Stream stream, char value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteChar(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static char ReadChar(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadChar(bytes, offset, out readSize); + } + + /// + /// Unsafe. If value is guranteed length is 0 ~ 31, can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteFixedStringUnsafe(Stream stream, string value, int byteCount) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteFixedStringUnsafe(ref buffer, 0, value, byteCount); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Unsafe. If pre-calculated byteCount of target string, can use this method. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteStringUnsafe(Stream stream, string value, int byteCount) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteStringUnsafe(ref buffer, 0, value, byteCount); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteStringBytes(Stream stream, byte[] utf8stringBytes) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteStringBytes(ref buffer, 0, utf8stringBytes); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + public static int WriteString(Stream stream, string value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteString(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + public static int WriteStringForceStr32Block(Stream stream, string value) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteStringForceStr32Block(ref buffer, 0, value); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static string ReadString(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadString(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormatHeader(Stream stream, sbyte typeCode, int dataLength) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteExtensionFormatHeader(ref buffer, 0, typeCode, dataLength); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + + /// + /// Write extension format header, always use ext32 format(length is fixed, 6). + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormatHeaderForceExt32Block(Stream stream, sbyte typeCode, int dataLength) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteExtensionFormatHeaderForceExt32Block(ref buffer, 0, typeCode, dataLength); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteExtensionFormat(Stream stream, sbyte typeCode, byte[] data) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteExtensionFormat(ref buffer, 0, typeCode, data); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ExtensionResult ReadExtensionFormat(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadExtensionFormat(bytes, offset, out readSize); + } + + /// + /// return byte length of ExtensionFormat. + /// +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static ExtensionHeader ReadExtensionFormatHeader(Stream stream) + { + int readSize; + var bytes = ReadMessageBlockFromStreamUnsafe(stream, true, out readSize); + var offset = 0; + + return ReadExtensionFormatHeader(bytes, offset, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static int WriteDateTime(Stream stream, DateTime dateTime) + { + var buffer = StreamDecodeMemoryPool.GetBuffer(); + var writeCount = WriteDateTime(ref buffer, 0, dateTime); + stream.Write(buffer, 0, writeCount); + return writeCount; + } + +#if NETSTANDARD || NETFRAMEWORK + [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)] +#endif + public static DateTime ReadDateTime(Stream stream) + { + var bytes = ReadMessageBlockFromStreamUnsafe(stream); + var offset = 0; + int readSize; + + return ReadDateTime(bytes, offset, out readSize); + } + } + + internal struct ExtensionResult + { + public sbyte TypeCode { get; private set; } + public byte[] Data { get; private set; } + + public ExtensionResult(sbyte typeCode, byte[] data) + { + TypeCode = typeCode; + Data = data; + } + } + + internal struct ExtensionHeader + { + public sbyte TypeCode { get; private set; } + public uint Length { get; private set; } + + public ExtensionHeader(sbyte typeCode, uint length) + { + TypeCode = typeCode; + Length = length; + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class DateTimeConstants + { + internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + internal const long BclSecondsAtUnixEpoch = 62135596800; + internal const int NanosecondsPerTick = 100; + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Decoders +{ + internal interface IMapHeaderDecoder + { + uint Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixMapHeader : IMapHeaderDecoder + { + internal static readonly IMapHeaderDecoder Instance = new FixMapHeader(); + + FixMapHeader() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return (uint)(bytes[offset] & 0xF); + } + } + + internal sealed class Map16Header : IMapHeaderDecoder + { + internal static readonly IMapHeaderDecoder Instance = new Map16Header(); + + Map16Header() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (uint)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class Map32Header : IMapHeaderDecoder + { + internal static readonly IMapHeaderDecoder Instance = new Map32Header(); + + Map32Header() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (uint)((bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | bytes[offset + 4]); + } + } + } + + internal sealed class InvalidMapHeader : IMapHeaderDecoder + { + internal static readonly IMapHeaderDecoder Instance = new InvalidMapHeader(); + + InvalidMapHeader() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IArrayHeaderDecoder + { + uint Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixArrayHeader : IArrayHeaderDecoder + { + internal static readonly IArrayHeaderDecoder Instance = new FixArrayHeader(); + + FixArrayHeader() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return (uint)(bytes[offset] & 0xF); + } + } + + internal sealed class Array16Header : IArrayHeaderDecoder + { + internal static readonly IArrayHeaderDecoder Instance = new Array16Header(); + + Array16Header() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (uint)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class Array32Header : IArrayHeaderDecoder + { + internal static readonly IArrayHeaderDecoder Instance = new Array32Header(); + + Array32Header() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (uint)((bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | bytes[offset + 4]); + } + } + } + + internal sealed class InvalidArrayHeader : IArrayHeaderDecoder + { + internal static readonly IArrayHeaderDecoder Instance = new InvalidArrayHeader(); + + InvalidArrayHeader() + { + + } + + public uint Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IBooleanDecoder + { + bool Read(); + } + + internal sealed class True : IBooleanDecoder + { + internal static IBooleanDecoder Instance = new True(); + + True() { } + + public bool Read() + { + return true; + } + } + + internal sealed class False : IBooleanDecoder + { + internal static IBooleanDecoder Instance = new False(); + + False() { } + + public bool Read() + { + return false; + } + } + + internal sealed class InvalidBoolean : IBooleanDecoder + { + internal static IBooleanDecoder Instance = new InvalidBoolean(); + + InvalidBoolean() { } + + public bool Read() + { + throw new InvalidOperationException("code is invalid."); + } + } + + internal interface IByteDecoder + { + byte Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixByte : IByteDecoder + { + internal static readonly IByteDecoder Instance = new FixByte(); + + FixByte() + { + + } + + public byte Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return bytes[offset]; + } + } + + internal sealed class UInt8Byte : IByteDecoder + { + internal static readonly IByteDecoder Instance = new UInt8Byte(); + + UInt8Byte() + { + + } + + public byte Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return bytes[offset + 1]; + } + } + + internal sealed class InvalidByte : IByteDecoder + { + internal static readonly IByteDecoder Instance = new InvalidByte(); + + InvalidByte() + { + + } + + public byte Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IBytesDecoder + { + byte[] Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class NilBytes : IBytesDecoder + { + internal static readonly IBytesDecoder Instance = new NilBytes(); + + NilBytes() + { + + } + + public byte[] Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return null; + } + } + + internal sealed class Bin8Bytes : IBytesDecoder + { + internal static readonly IBytesDecoder Instance = new Bin8Bytes(); + + Bin8Bytes() + { + + } + + public byte[] Read(byte[] bytes, int offset, out int readSize) + { + var length = bytes[offset + 1]; + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var newBytes = new byte[length]; + Buffer.BlockCopy(bytes, offset + 2, newBytes, 0, length); + + readSize = length + 2; + return newBytes; + } + } + + internal sealed class Bin16Bytes : IBytesDecoder + { + internal static readonly IBytesDecoder Instance = new Bin16Bytes(); + + Bin16Bytes() + { + + } + + public byte[] Read(byte[] bytes, int offset, out int readSize) + { + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var newBytes = new byte[length]; + Buffer.BlockCopy(bytes, offset + 3, newBytes, 0, length); + + readSize = length + 3; + return newBytes; + } + } + + internal sealed class Bin32Bytes : IBytesDecoder + { + internal static readonly IBytesDecoder Instance = new Bin32Bytes(); + + Bin32Bytes() + { + + } + + public byte[] Read(byte[] bytes, int offset, out int readSize) + { + var length = (bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | (bytes[offset + 4]); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var newBytes = new byte[length]; + Buffer.BlockCopy(bytes, offset + 5, newBytes, 0, length); + + readSize = length + 5; + return newBytes; + } + } + + internal sealed class InvalidBytes : IBytesDecoder + { + internal static readonly IBytesDecoder Instance = new InvalidBytes(); + + InvalidBytes() + { + + } + + public byte[] Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IBytesSegmentDecoder + { + ArraySegment Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class NilBytesSegment : IBytesSegmentDecoder + { + internal static readonly IBytesSegmentDecoder Instance = new NilBytesSegment(); + + NilBytesSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return default(ArraySegment); + } + } + + internal sealed class Bin8BytesSegment : IBytesSegmentDecoder + { + internal static readonly IBytesSegmentDecoder Instance = new Bin8BytesSegment(); + + Bin8BytesSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + var length = bytes[offset + 1]; + + readSize = length + 2; + return new ArraySegment(bytes, offset + 2, length); + } + } + + internal sealed class Bin16BytesSegment : IBytesSegmentDecoder + { + internal static readonly IBytesSegmentDecoder Instance = new Bin16BytesSegment(); + + Bin16BytesSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + + readSize = length + 3; + return new ArraySegment(bytes, offset + 3, length); + } + } + + internal sealed class Bin32BytesSegment : IBytesSegmentDecoder + { + internal static readonly IBytesSegmentDecoder Instance = new Bin32BytesSegment(); + + Bin32BytesSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + var length = (bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | (bytes[offset + 4]); + readSize = length + 5; + return new ArraySegment(bytes, offset + 5, length); + } + } + + internal sealed class InvalidBytesSegment : IBytesSegmentDecoder + { + internal static readonly IBytesSegmentDecoder Instance = new InvalidBytesSegment(); + + InvalidBytesSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface ISByteDecoder + { + sbyte Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixSByte : ISByteDecoder + { + internal static readonly ISByteDecoder Instance = new FixSByte(); + + FixSByte() + { + + } + + public sbyte Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((sbyte)bytes[offset]); + } + } + + internal sealed class Int8SByte : ISByteDecoder + { + internal static readonly ISByteDecoder Instance = new Int8SByte(); + + Int8SByte() + { + + } + + public sbyte Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((sbyte)(bytes[offset + 1])); + } + } + + internal sealed class InvalidSByte : ISByteDecoder + { + internal static readonly ISByteDecoder Instance = new InvalidSByte(); + + InvalidSByte() + { + + } + + public sbyte Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface ISingleDecoder + { + float Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixNegativeFloat : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new FixNegativeFloat(); + + FixNegativeFloat() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return FixSByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class FixFloat : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new FixFloat(); + + FixFloat() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return FixByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int8Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new Int8Single(); + + Int8Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return Int8SByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int16Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new Int16Single(); + + Int16Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return Int16Int16.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int32Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new Int32Single(); + + Int32Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return Int32Int32.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int64Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new Int64Single(); + + Int64Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return Int64Int64.Instance.Read(bytes, offset, out readSize); + } + } + + + internal sealed class UInt8Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new UInt8Single(); + + UInt8Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return UInt8Byte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt16Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new UInt16Single(); + + UInt16Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return UInt16UInt16.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt32Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new UInt32Single(); + + UInt32Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return UInt32UInt32.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt64Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new UInt64Single(); + + UInt64Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + return UInt64UInt64.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Float32Single : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new Float32Single(); + + Float32Single() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + return new Float32Bits(bytes, offset + 1).Value; + } + } + + internal sealed class InvalidSingle : ISingleDecoder + { + internal static readonly ISingleDecoder Instance = new InvalidSingle(); + + InvalidSingle() + { + + } + + public Single Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IDoubleDecoder + { + double Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixNegativeDouble : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new FixNegativeDouble(); + + FixNegativeDouble() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return FixSByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class FixDouble : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new FixDouble(); + + FixDouble() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return FixByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int8Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Int8Double(); + + Int8Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return Int8SByte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int16Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Int16Double(); + + Int16Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return Int16Int16.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int32Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Int32Double(); + + Int32Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return Int32Int32.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Int64Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Int64Double(); + + Int64Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return Int64Int64.Instance.Read(bytes, offset, out readSize); + } + } + + + internal sealed class UInt8Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new UInt8Double(); + + UInt8Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return UInt8Byte.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt16Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new UInt16Double(); + + UInt16Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return UInt16UInt16.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt32Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new UInt32Double(); + + UInt32Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return UInt32UInt32.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class UInt64Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new UInt64Double(); + + UInt64Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + return UInt64UInt64.Instance.Read(bytes, offset, out readSize); + } + } + + internal sealed class Float32Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Float32Double(); + + Float32Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + return new Float32Bits(bytes, offset + 1).Value; + } + } + + internal sealed class Float64Double : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new Float64Double(); + + Float64Double() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + readSize = 9; + return new Float64Bits(bytes, offset + 1).Value; + } + } + + internal sealed class InvalidDouble : IDoubleDecoder + { + internal static readonly IDoubleDecoder Instance = new InvalidDouble(); + + InvalidDouble() + { + + } + + public Double Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IInt16Decoder + { + Int16 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixNegativeInt16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new FixNegativeInt16(); + + FixNegativeInt16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((short)(sbyte)bytes[offset]); + } + } + + internal sealed class FixInt16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new FixInt16(); + + FixInt16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((short)bytes[offset]); + } + } + + internal sealed class UInt8Int16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new UInt8Int16(); + + UInt8Int16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((short)(byte)(bytes[offset + 1])); + } + } + + internal sealed class UInt16Int16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new UInt16Int16(); + + UInt16Int16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + return checked((Int16)((bytes[offset + 1] << 8) + (bytes[offset + 2]))); + } + } + + internal sealed class Int8Int16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new Int8Int16(); + + Int8Int16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((short)(sbyte)(bytes[offset + 1])); + } + } + + internal sealed class Int16Int16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new Int16Int16(); + + Int16Int16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (short)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class InvalidInt16 : IInt16Decoder + { + internal static readonly IInt16Decoder Instance = new InvalidInt16(); + + InvalidInt16() + { + + } + + public Int16 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IInt32Decoder + { + Int32 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixNegativeInt32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new FixNegativeInt32(); + + FixNegativeInt32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((int)(sbyte)bytes[offset]); + } + } + + internal sealed class FixInt32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new FixInt32(); + + FixInt32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((int)bytes[offset]); + } + } + + internal sealed class UInt8Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new UInt8Int32(); + + UInt8Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((int)(byte)(bytes[offset + 1])); + } + } + internal sealed class UInt16Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new UInt16Int32(); + + UInt16Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + return (Int32)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + + internal sealed class UInt32Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new UInt32Int32(); + + UInt32Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + checked + { + return (Int32)((UInt32)(bytes[offset + 1] << 24) | (UInt32)(bytes[offset + 2] << 16) | (UInt32)(bytes[offset + 3] << 8) | (UInt32)bytes[offset + 4]); + } + } + } + + internal sealed class Int8Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new Int8Int32(); + + Int8Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((int)(sbyte)(bytes[offset + 1])); + } + } + + internal sealed class Int16Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new Int16Int32(); + + Int16Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (int)(short)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class Int32Int32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new Int32Int32(); + + Int32Int32() + { + + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (int)((bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | bytes[offset + 4]); + } + } + } + + internal sealed class InvalidInt32 : IInt32Decoder + { + internal static readonly IInt32Decoder Instance = new InvalidInt32(); + + InvalidInt32() + { + } + + public Int32 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IInt64Decoder + { + Int64 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixNegativeInt64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new FixNegativeInt64(); + + FixNegativeInt64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((long)(sbyte)bytes[offset]); + } + } + + internal sealed class FixInt64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new FixInt64(); + + FixInt64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((long)bytes[offset]); + } + } + + internal sealed class UInt8Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new UInt8Int64(); + + UInt8Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((int)(byte)(bytes[offset + 1])); + } + } + internal sealed class UInt16Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new UInt16Int64(); + + UInt16Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + return (Int64)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + + internal sealed class UInt32Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new UInt32Int64(); + + UInt32Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + return unchecked((Int64)((uint)(bytes[offset + 1] << 24) | ((uint)bytes[offset + 2] << 16) | ((uint)bytes[offset + 3] << 8) | (uint)bytes[offset + 4])); + } + } + + internal sealed class UInt64Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new UInt64Int64(); + + UInt64Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 9; + checked + { + return (Int64)bytes[offset + 1] << 56 | (Int64)bytes[offset + 2] << 48 | (Int64)bytes[offset + 3] << 40 | (Int64)bytes[offset + 4] << 32 + | (Int64)bytes[offset + 5] << 24 | (Int64)bytes[offset + 6] << 16 | (Int64)bytes[offset + 7] << 8 | (Int64)bytes[offset + 8]; + } + } + } + + + internal sealed class Int8Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new Int8Int64(); + + Int8Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((long)(sbyte)(bytes[offset + 1])); + } + } + + internal sealed class Int16Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new Int16Int64(); + + Int16Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (long)(short)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class Int32Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new Int32Int64(); + + Int32Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (long)((long)(bytes[offset + 1] << 24) + (long)(bytes[offset + 2] << 16) + (long)(bytes[offset + 3] << 8) + (long)bytes[offset + 4]); + } + } + } + + internal sealed class Int64Int64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new Int64Int64(); + + Int64Int64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 9; + unchecked + { + return (long)bytes[offset + 1] << 56 | (long)bytes[offset + 2] << 48 | (long)bytes[offset + 3] << 40 | (long)bytes[offset + 4] << 32 + | (long)bytes[offset + 5] << 24 | (long)bytes[offset + 6] << 16 | (long)bytes[offset + 7] << 8 | (long)bytes[offset + 8]; + } + } + } + + internal sealed class InvalidInt64 : IInt64Decoder + { + internal static readonly IInt64Decoder Instance = new InvalidInt64(); + + InvalidInt64() + { + + } + + public Int64 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IUInt16Decoder + { + UInt16 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixUInt16 : IUInt16Decoder + { + internal static readonly IUInt16Decoder Instance = new FixUInt16(); + + FixUInt16() + { + + } + + public UInt16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((UInt16)bytes[offset]); + } + } + + internal sealed class UInt8UInt16 : IUInt16Decoder + { + internal static readonly IUInt16Decoder Instance = new UInt8UInt16(); + + UInt8UInt16() + { + + } + + public UInt16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((UInt16)(bytes[offset + 1])); + } + } + + internal sealed class UInt16UInt16 : IUInt16Decoder + { + internal static readonly IUInt16Decoder Instance = new UInt16UInt16(); + + UInt16UInt16() + { + + } + + public UInt16 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (UInt16)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class InvalidUInt16 : IUInt16Decoder + { + internal static readonly IUInt16Decoder Instance = new InvalidUInt16(); + + InvalidUInt16() + { + + } + + public UInt16 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IUInt32Decoder + { + UInt32 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixUInt32 : IUInt32Decoder + { + internal static readonly IUInt32Decoder Instance = new FixUInt32(); + + FixUInt32() + { + + } + + public UInt32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((UInt32)bytes[offset]); + } + } + + internal sealed class UInt8UInt32 : IUInt32Decoder + { + internal static readonly IUInt32Decoder Instance = new UInt8UInt32(); + + UInt8UInt32() + { + + } + + public UInt32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((UInt32)(bytes[offset + 1])); + } + } + + internal sealed class UInt16UInt32 : IUInt32Decoder + { + internal static readonly IUInt32Decoder Instance = new UInt16UInt32(); + + UInt16UInt32() + { + + } + + public UInt32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (UInt32)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class UInt32UInt32 : IUInt32Decoder + { + internal static readonly IUInt32Decoder Instance = new UInt32UInt32(); + + UInt32UInt32() + { + + } + + public UInt32 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (UInt32)((UInt32)(bytes[offset + 1] << 24) | (UInt32)(bytes[offset + 2] << 16) | (UInt32)(bytes[offset + 3] << 8) | (UInt32)bytes[offset + 4]); + } + } + } + + internal sealed class InvalidUInt32 : IUInt32Decoder + { + internal static readonly IUInt32Decoder Instance = new InvalidUInt32(); + + InvalidUInt32() + { + + } + + public UInt32 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IUInt64Decoder + { + UInt64 Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixUInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new FixUInt64(); + + FixUInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return unchecked((UInt64)bytes[offset]); + } + } + + internal sealed class UInt8UInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new UInt8UInt64(); + + UInt8UInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + return unchecked((UInt64)(bytes[offset + 1])); + } + } + + internal sealed class UInt16UInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new UInt16UInt64(); + + UInt16UInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + unchecked + { + return (UInt64)((bytes[offset + 1] << 8) | (bytes[offset + 2])); + } + } + } + + internal sealed class UInt32UInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new UInt32UInt64(); + + UInt32UInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 5; + unchecked + { + return (UInt64)(((UInt64)bytes[offset + 1] << 24) + (ulong)(bytes[offset + 2] << 16) + (UInt64)(bytes[offset + 3] << 8) + (UInt64)bytes[offset + 4]); + } + } + } + + internal sealed class UInt64UInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new UInt64UInt64(); + + UInt64UInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + readSize = 9; + unchecked + { + return (UInt64)bytes[offset + 1] << 56 | (UInt64)bytes[offset + 2] << 48 | (UInt64)bytes[offset + 3] << 40 | (UInt64)bytes[offset + 4] << 32 + | (UInt64)bytes[offset + 5] << 24 | (UInt64)bytes[offset + 6] << 16 | (UInt64)bytes[offset + 7] << 8 | (UInt64)bytes[offset + 8]; + } + } + } + + internal sealed class InvalidUInt64 : IUInt64Decoder + { + internal static readonly IUInt64Decoder Instance = new InvalidUInt64(); + + InvalidUInt64() + { + + } + + public UInt64 Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IStringDecoder + { + String Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class NilString : IStringDecoder + { + internal static readonly IStringDecoder Instance = new NilString(); + + NilString() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return null; + } + } + + internal sealed class FixString : IStringDecoder + { + internal static readonly IStringDecoder Instance = new FixString(); + + FixString() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + var length = bytes[offset] & 0x1F; + readSize = length + 1; + return StringEncoding.UTF8.GetString(bytes, offset + 1, length); + } + } + + internal sealed class Str8String : IStringDecoder + { + internal static readonly IStringDecoder Instance = new Str8String(); + + Str8String() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + var length = (int)bytes[offset + 1]; + readSize = length + 2; + return StringEncoding.UTF8.GetString(bytes, offset + 2, length); + } + } + + internal sealed class Str16String : IStringDecoder + { + internal static readonly IStringDecoder Instance = new Str16String(); + + Str16String() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + readSize = length + 3; + return StringEncoding.UTF8.GetString(bytes, offset + 3, length); + } + } + } + + internal sealed class Str32String : IStringDecoder + { + internal static readonly IStringDecoder Instance = new Str32String(); + + Str32String() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (int)((uint)(bytes[offset + 1] << 24) | (uint)(bytes[offset + 2] << 16) | (uint)(bytes[offset + 3] << 8) | (uint)bytes[offset + 4]); + readSize = length + 5; + return StringEncoding.UTF8.GetString(bytes, offset + 5, length); + } + } + } + + internal sealed class InvalidString : IStringDecoder + { + internal static readonly IStringDecoder Instance = new InvalidString(); + + InvalidString() + { + + } + + public String Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IStringSegmentDecoder + { + ArraySegment Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class NilStringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new NilStringSegment(); + + NilStringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + readSize = 1; + return new ArraySegment(bytes, offset, 1); + } + } + + internal sealed class FixStringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new FixStringSegment(); + + FixStringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + var length = bytes[offset] & 0x1F; + readSize = length + 1; + return new ArraySegment(bytes, offset + 1, length); + } + } + + internal sealed class Str8StringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new Str8StringSegment(); + + Str8StringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + var length = (int)bytes[offset + 1]; + readSize = length + 2; + return new ArraySegment(bytes, offset + 2, length); + } + } + + internal sealed class Str16StringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new Str16StringSegment(); + + Str16StringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (bytes[offset + 1] << 8) + (bytes[offset + 2]); + readSize = length + 3; + return new ArraySegment(bytes, offset + 3, length); + } + } + } + + internal sealed class Str32StringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new Str32StringSegment(); + + Str32StringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (int)((uint)(bytes[offset + 1] << 24) | (uint)(bytes[offset + 2] << 16) | (uint)(bytes[offset + 3] << 8) | (uint)bytes[offset + 4]); + readSize = length + 5; + return new ArraySegment(bytes, offset + 5, length); + } + } + } + + internal sealed class InvalidStringSegment : IStringSegmentDecoder + { + internal static readonly IStringSegmentDecoder Instance = new InvalidStringSegment(); + + InvalidStringSegment() + { + + } + + public ArraySegment Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IExtDecoder + { + ExtensionResult Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixExt1 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new FixExt1(); + + FixExt1() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + readSize = 3; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + var body = new byte[1] { bytes[offset + 2] }; // make new bytes is overhead? + return new ExtensionResult(typeCode, body); + } + } + + internal sealed class FixExt2 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new FixExt2(); + + FixExt2() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + readSize = 4; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + var body = new byte[2] + { + bytes[offset + 2], + bytes[offset + 3], + }; + return new ExtensionResult(typeCode, body); + } + } + + internal sealed class FixExt4 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new FixExt4(); + + FixExt4() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + readSize = 6; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + var body = new byte[4] + { + bytes[offset + 2], + bytes[offset + 3], + bytes[offset + 4], + bytes[offset + 5], + }; + return new ExtensionResult(typeCode, body); + } + } + + internal sealed class FixExt8 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new FixExt8(); + + FixExt8() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + readSize = 10; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + var body = new byte[8] + { + bytes[offset + 2], + bytes[offset + 3], + bytes[offset + 4], + bytes[offset + 5], + bytes[offset + 6], + bytes[offset + 7], + bytes[offset + 8], + bytes[offset + 9], + }; + return new ExtensionResult(typeCode, body); + } + } + + internal sealed class FixExt16 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new FixExt16(); + + FixExt16() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + readSize = 18; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + var body = new byte[16] + { + bytes[offset + 2], + bytes[offset + 3], + bytes[offset + 4], + bytes[offset + 5], + bytes[offset + 6], + bytes[offset + 7], + bytes[offset + 8], + bytes[offset + 9], + bytes[offset + 10], + bytes[offset + 11], + bytes[offset + 12], + bytes[offset + 13], + bytes[offset + 14], + bytes[offset + 15], + bytes[offset + 16], + bytes[offset + 17] + }; + return new ExtensionResult(typeCode, body); + } + } + + internal sealed class Ext8 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new Ext8(); + + Ext8() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = bytes[offset + 1]; + var typeCode = unchecked((sbyte)bytes[offset + 2]); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var body = new byte[length]; + readSize = (int)length + 3; + Buffer.BlockCopy(bytes, offset + 3, body, 0, (int)length); + return new ExtensionResult(typeCode, body); + } + } + } + + internal sealed class Ext16 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new Ext16(); + + Ext16() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (int)((UInt16)(bytes[offset + 1] << 8) | (UInt16)bytes[offset + 2]); + var typeCode = unchecked((sbyte)bytes[offset + 3]); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var body = new byte[length]; + readSize = length + 4; + Buffer.BlockCopy(bytes, offset + 4, body, 0, (int)length); + return new ExtensionResult(typeCode, body); + } + } + } + + internal sealed class Ext32 : IExtDecoder + { + internal static readonly IExtDecoder Instance = new Ext32(); + + Ext32() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (UInt32)((UInt32)(bytes[offset + 1] << 24) | (UInt32)(bytes[offset + 2] << 16) | (UInt32)(bytes[offset + 3] << 8) | (UInt32)bytes[offset + 4]); + var typeCode = unchecked((sbyte)bytes[offset + 5]); + + // Protected against corrupted or mischievious data that may lead to allocating way too much memory. + if (length > bytes.Length - offset) + { + MessagePackBinary.ThrowNotEnoughBytesException(); + } + + var body = new byte[length]; + checked + { + readSize = (int)length + 6; + Buffer.BlockCopy(bytes, offset + 6, body, 0, (int)length); + } + return new ExtensionResult(typeCode, body); + } + } + } + + internal sealed class InvalidExt : IExtDecoder + { + internal static readonly IExtDecoder Instance = new InvalidExt(); + + InvalidExt() + { + + } + + public ExtensionResult Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + + + + + + internal interface IExtHeaderDecoder + { + ExtensionHeader Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixExt1Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new FixExt1Header(); + + FixExt1Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + return new ExtensionHeader(typeCode, 1); + } + } + + internal sealed class FixExt2Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new FixExt2Header(); + + FixExt2Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + return new ExtensionHeader(typeCode, 2); + } + } + + internal sealed class FixExt4Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new FixExt4Header(); + + FixExt4Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + return new ExtensionHeader(typeCode, 4); + } + } + + internal sealed class FixExt8Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new FixExt8Header(); + + FixExt8Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + return new ExtensionHeader(typeCode, 8); + } + } + + internal sealed class FixExt16Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new FixExt16Header(); + + FixExt16Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + readSize = 2; + var typeCode = unchecked((sbyte)bytes[offset + 1]); + return new ExtensionHeader(typeCode, 16); + } + } + + internal sealed class Ext8Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new Ext8Header(); + + Ext8Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = bytes[offset + 1]; + var typeCode = unchecked((sbyte)bytes[offset + 2]); + + readSize = 3; + return new ExtensionHeader(typeCode, length); + } + } + } + + internal sealed class Ext16Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new Ext16Header(); + + Ext16Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (UInt32)((UInt16)(bytes[offset + 1] << 8) | (UInt16)bytes[offset + 2]); + var typeCode = unchecked((sbyte)bytes[offset + 3]); + + readSize = 4; + return new ExtensionHeader(typeCode, length); + } + } + } + + internal sealed class Ext32Header : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new Ext32Header(); + + Ext32Header() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + unchecked + { + var length = (UInt32)((UInt32)(bytes[offset + 1] << 24) | (UInt32)(bytes[offset + 2] << 16) | (UInt32)(bytes[offset + 3] << 8) | (UInt32)bytes[offset + 4]); + var typeCode = unchecked((sbyte)bytes[offset + 5]); + + readSize = 6; + return new ExtensionHeader(typeCode, length); + } + } + } + + internal sealed class InvalidExtHeader : IExtHeaderDecoder + { + internal static readonly IExtHeaderDecoder Instance = new InvalidExtHeader(); + + InvalidExtHeader() + { + + } + + public ExtensionHeader Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IDateTimeDecoder + { + DateTime Read(byte[] bytes, int offset, out int readSize); + } + + internal sealed class FixExt4DateTime : IDateTimeDecoder + { + internal static readonly IDateTimeDecoder Instance = new FixExt4DateTime(); + + FixExt4DateTime() + { + + } + + public DateTime Read(byte[] bytes, int offset, out int readSize) + { + var typeCode = unchecked((sbyte)bytes[offset + 1]); + if (typeCode != ReservedMessagePackExtensionTypeCode.DateTime) + { + throw new InvalidOperationException(string.Format("typeCode is invalid. typeCode:{0}", typeCode)); + } + + unchecked + { + var seconds = (UInt32)((UInt32)(bytes[offset + 2] << 24) | (UInt32)(bytes[offset + 3] << 16) | (UInt32)(bytes[offset + 4] << 8) | (UInt32)bytes[offset + 5]); + + readSize = 6; + return DateTimeConstants.UnixEpoch.AddSeconds(seconds); + } + } + } + + internal sealed class FixExt8DateTime : IDateTimeDecoder + { + internal static readonly IDateTimeDecoder Instance = new FixExt8DateTime(); + + FixExt8DateTime() + { + + } + + public DateTime Read(byte[] bytes, int offset, out int readSize) + { + var typeCode = unchecked((sbyte)bytes[offset + 1]); + if (typeCode != ReservedMessagePackExtensionTypeCode.DateTime) + { + throw new InvalidOperationException(string.Format("typeCode is invalid. typeCode:{0}", typeCode)); + } + + var data64 = (UInt64)bytes[offset + 2] << 56 | (UInt64)bytes[offset + 3] << 48 | (UInt64)bytes[offset + 4] << 40 | (UInt64)bytes[offset + 5] << 32 + | (UInt64)bytes[offset + 6] << 24 | (UInt64)bytes[offset + 7] << 16 | (UInt64)bytes[offset + 8] << 8 | (UInt64)bytes[offset + 9]; + + var nanoseconds = (long)(data64 >> 34); + var seconds = data64 & 0x00000003ffffffffL; + + readSize = 10; + return DateTimeConstants.UnixEpoch.AddSeconds(seconds).AddTicks(nanoseconds / DateTimeConstants.NanosecondsPerTick); + } + } + + internal sealed class Ext8DateTime : IDateTimeDecoder + { + internal static readonly IDateTimeDecoder Instance = new Ext8DateTime(); + + Ext8DateTime() + { + + } + + public DateTime Read(byte[] bytes, int offset, out int readSize) + { + var length = checked((byte)bytes[offset + 1]); + var typeCode = unchecked((sbyte)bytes[offset + 2]); + if (length != 12 || typeCode != ReservedMessagePackExtensionTypeCode.DateTime) + { + throw new InvalidOperationException(string.Format("typeCode is invalid. typeCode:{0}", typeCode)); + } + + var nanoseconds = (UInt32)((UInt32)(bytes[offset + 3] << 24) | (UInt32)(bytes[offset + 4] << 16) | (UInt32)(bytes[offset + 5] << 8) | (UInt32)bytes[offset + 6]); + unchecked + { + var seconds = (long)bytes[offset + 7] << 56 | (long)bytes[offset + 8] << 48 | (long)bytes[offset + 9] << 40 | (long)bytes[offset + 10] << 32 + | (long)bytes[offset + 11] << 24 | (long)bytes[offset + 12] << 16 | (long)bytes[offset + 13] << 8 | (long)bytes[offset + 14]; + + readSize = 15; + return DateTimeConstants.UnixEpoch.AddSeconds(seconds).AddTicks(nanoseconds / DateTimeConstants.NanosecondsPerTick); + } + } + } + + internal sealed class InvalidDateTime : IDateTimeDecoder + { + internal static readonly IDateTimeDecoder Instance = new InvalidDateTime(); + + InvalidDateTime() + { + + } + + public DateTime Read(byte[] bytes, int offset, out int readSize) + { + throw new InvalidOperationException(string.Format("code is invalid. code:{0} format:{1}", bytes[offset], MessagePackCode.ToFormatName(bytes[offset]))); + } + } + + internal interface IReadNextDecoder + { + int Read(byte[] bytes, int offset); + } + + internal sealed class ReadNext1 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext1(); + ReadNext1() + { + + } + public int Read(byte[] bytes, int offset) { return 1; } + } + + internal sealed class ReadNext2 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext2(); + ReadNext2() + { + + } + public int Read(byte[] bytes, int offset) { return 2; } + + } + internal sealed class ReadNext3 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext3(); + ReadNext3() + { + + } + public int Read(byte[] bytes, int offset) { return 3; } + } + internal sealed class ReadNext4 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext4(); + ReadNext4() + { + + } + public int Read(byte[] bytes, int offset) { return 4; } + } + internal sealed class ReadNext5 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext5(); + ReadNext5() + { + + } + public int Read(byte[] bytes, int offset) { return 5; } + } + internal sealed class ReadNext6 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext6(); + ReadNext6() + { + + } + public int Read(byte[] bytes, int offset) { return 6; } + } + + internal sealed class ReadNext9 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext9(); + ReadNext9() + { + + } + public int Read(byte[] bytes, int offset) { return 9; } + } + internal sealed class ReadNext10 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext10(); + ReadNext10() + { + + } + public int Read(byte[] bytes, int offset) { return 10; } + } + internal sealed class ReadNext18 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNext18(); + ReadNext18() + { + + } + public int Read(byte[] bytes, int offset) { return 18; } + } + + internal sealed class ReadNextMap : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextMap(); + ReadNextMap() + { + + } + public int Read(byte[] bytes, int offset) + { + var startOffset = offset; + int readSize; + var length = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + offset += readSize; + for (int i = 0; i < length; i++) + { + offset += MessagePackBinary.ReadNext(bytes, offset); // key + offset += MessagePackBinary.ReadNext(bytes, offset); // value + } + return offset - startOffset; + } + } + + internal sealed class ReadNextArray : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextArray(); + ReadNextArray() + { + + } + public int Read(byte[] bytes, int offset) + { + var startOffset = offset; + int readSize; + var length = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + offset += readSize; + for (int i = 0; i < length; i++) + { + offset += MessagePackBinary.ReadNext(bytes, offset); + } + return offset - startOffset; + } + } + + internal sealed class ReadNextFixStr : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextFixStr(); + ReadNextFixStr() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = bytes[offset] & 0x1F; + return length + 1; + } + } + + internal sealed class ReadNextStr8 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextStr8(); + ReadNextStr8() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = (int)bytes[offset + 1]; + return length + 2; + } + } + + internal sealed class ReadNextStr16 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextStr16(); + ReadNextStr16() + { + + } + public int Read(byte[] bytes, int offset) + { + + var length = (bytes[offset + 1] << 8) | (bytes[offset + 2]); + return length + 3; + } + } + + internal sealed class ReadNextStr32 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextStr32(); + ReadNextStr32() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = (int)((uint)(bytes[offset + 1] << 24) | (uint)(bytes[offset + 2] << 16) | (uint)(bytes[offset + 3] << 8) | (uint)bytes[offset + 4]); + return length + 5; + } + } + + internal sealed class ReadNextBin8 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextBin8(); + ReadNextBin8() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = bytes[offset + 1]; + return length + 2; + } + } + + internal sealed class ReadNextBin16 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextBin16(); + ReadNextBin16() + { + + } + public int Read(byte[] bytes, int offset) + { + + var length = (bytes[offset + 1] << 8) | (bytes[offset + 2]); + return length + 3; + } + } + + internal sealed class ReadNextBin32 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextBin32(); + ReadNextBin32() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = (bytes[offset + 1] << 24) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 8) | (bytes[offset + 4]); + return length + 5; + } + } + + internal sealed class ReadNextExt8 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextExt8(); + ReadNextExt8() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = bytes[offset + 1]; + return (int)length + 3; + } + } + + internal sealed class ReadNextExt16 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextExt16(); + ReadNextExt16() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = (int)((UInt16)(bytes[offset + 1] << 8) | (UInt16)bytes[offset + 2]); + return length + 4; + } + } + + internal sealed class ReadNextExt32 : IReadNextDecoder + { + internal static readonly IReadNextDecoder Instance = new ReadNextExt32(); + ReadNextExt32() + { + + } + public int Read(byte[] bytes, int offset) + { + var length = (UInt32)((UInt32)(bytes[offset + 1] << 24) | (UInt32)(bytes[offset + 2] << 16) | (UInt32)(bytes[offset + 3] << 8) | (UInt32)bytes[offset + 4]); + return (int)length + 6; + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackCode.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackCode.cs new file mode 100644 index 0000000000..350135b66e --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackCode.cs @@ -0,0 +1,203 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + /// + /// https://github.com/msgpack/msgpack/blob/master/spec.md#serialization-type-to-format-conversion + /// + internal enum MessagePackType : byte + { + Unknown = 0, + + Integer = 1, + Nil = 2, + Boolean = 3, + Float = 4, + String = 5, + Binary = 6, + Array = 7, + Map = 8, + Extension = 9, + } + + /// + /// https://github.com/msgpack/msgpack/blob/master/spec.md#overview + /// + internal static class MessagePackCode + { + public const byte MinFixInt = 0x00; // 0 + public const byte MaxFixInt = 0x7f; // 127 + public const byte MinFixMap = 0x80; // 128 + public const byte MaxFixMap = 0x8f; // 143 + public const byte MinFixArray = 0x90; // 144 + public const byte MaxFixArray = 0x9f; // 159 + public const byte MinFixStr = 0xa0; // 160 + public const byte MaxFixStr = 0xbf; // 191 + public const byte Nil = 0xc0; + public const byte NeverUsed = 0xc1; + public const byte False = 0xc2; + public const byte True = 0xc3; + public const byte Bin8 = 0xc4; + public const byte Bin16 = 0xc5; + public const byte Bin32 = 0xc6; + public const byte Ext8 = 0xc7; + public const byte Ext16 = 0xc8; + public const byte Ext32 = 0xc9; + public const byte Float32 = 0xca; + public const byte Float64 = 0xcb; + public const byte UInt8 = 0xcc; + public const byte UInt16 = 0xcd; + public const byte UInt32 = 0xce; + public const byte UInt64 = 0xcf; + public const byte Int8 = 0xd0; + public const byte Int16 = 0xd1; + public const byte Int32 = 0xd2; + public const byte Int64 = 0xd3; + public const byte FixExt1 = 0xd4; + public const byte FixExt2 = 0xd5; + public const byte FixExt4 = 0xd6; + public const byte FixExt8 = 0xd7; + public const byte FixExt16 = 0xd8; + public const byte Str8 = 0xd9; + public const byte Str16 = 0xda; + public const byte Str32 = 0xdb; + public const byte Array16 = 0xdc; + public const byte Array32 = 0xdd; + public const byte Map16 = 0xde; + public const byte Map32 = 0xdf; + public const byte MinNegativeFixInt = 0xe0; // 224 + public const byte MaxNegativeFixInt = 0xff; // 255 + + static readonly MessagePackType[] typeLookupTable = new MessagePackType[256]; + static readonly string[] formatNameTable = new string[256]; + + static MessagePackCode() + { + // Init Lookup Table + for (int i = MinFixInt; i <= MaxFixInt; i++) + { + typeLookupTable[i] = MessagePackType.Integer; + formatNameTable[i] = "positive fixint"; + } + for (int i = MinFixMap; i <= MaxFixMap; i++) + { + typeLookupTable[i] = MessagePackType.Map; + formatNameTable[i] = "fixmap"; + } + for (int i = MinFixArray; i <= MaxFixArray; i++) + { + typeLookupTable[i] = MessagePackType.Array; + formatNameTable[i] = "fixarray"; + } + for (int i = MinFixStr; i <= MaxFixStr; i++) + { + typeLookupTable[i] = MessagePackType.String; + formatNameTable[i] = "fixstr"; + } + + typeLookupTable[Nil] = MessagePackType.Nil; + typeLookupTable[NeverUsed] = MessagePackType.Unknown; + typeLookupTable[False] = MessagePackType.Boolean; + typeLookupTable[True] = MessagePackType.Boolean; + typeLookupTable[Bin8] = MessagePackType.Binary; + typeLookupTable[Bin16] = MessagePackType.Binary; + typeLookupTable[Bin32] = MessagePackType.Binary; + typeLookupTable[Ext8] = MessagePackType.Extension; + typeLookupTable[Ext16] = MessagePackType.Extension; + typeLookupTable[Ext32] = MessagePackType.Extension; + typeLookupTable[Float32] = MessagePackType.Float; + typeLookupTable[Float64] = MessagePackType.Float; + typeLookupTable[UInt8] = MessagePackType.Integer; + typeLookupTable[UInt16] = MessagePackType.Integer; + typeLookupTable[UInt32] = MessagePackType.Integer; + typeLookupTable[UInt64] = MessagePackType.Integer; + typeLookupTable[Int8] = MessagePackType.Integer; + typeLookupTable[Int16] = MessagePackType.Integer; + typeLookupTable[Int32] = MessagePackType.Integer; + typeLookupTable[Int64] = MessagePackType.Integer; + typeLookupTable[FixExt1] = MessagePackType.Extension; + typeLookupTable[FixExt2] = MessagePackType.Extension; + typeLookupTable[FixExt4] = MessagePackType.Extension; + typeLookupTable[FixExt8] = MessagePackType.Extension; + typeLookupTable[FixExt16] = MessagePackType.Extension; + typeLookupTable[Str8] = MessagePackType.String; + typeLookupTable[Str16] = MessagePackType.String; + typeLookupTable[Str32] = MessagePackType.String; + typeLookupTable[Array16] = MessagePackType.Array; + typeLookupTable[Array32] = MessagePackType.Array; + typeLookupTable[Map16] = MessagePackType.Map; + typeLookupTable[Map32] = MessagePackType.Map; + + formatNameTable[Nil] = "nil"; + formatNameTable[NeverUsed] = "(never used)"; + formatNameTable[False] = "false"; + formatNameTable[True] = "true"; + formatNameTable[Bin8] = "bin 8"; + formatNameTable[Bin16] = "bin 16"; + formatNameTable[Bin32] = "bin 32"; + formatNameTable[Ext8] = "ext 8"; + formatNameTable[Ext16] = "ext 16"; + formatNameTable[Ext32] = "ext 32"; + formatNameTable[Float32] = "float 32"; + formatNameTable[Float64] = "float 64"; + formatNameTable[UInt8] = "uint 8"; + formatNameTable[UInt16] = "uint 16"; + formatNameTable[UInt32] = "uint 32"; + formatNameTable[UInt64] = "uint 64"; + formatNameTable[Int8] = "int 8"; + formatNameTable[Int16] = "int 16"; + formatNameTable[Int32] = "int 32"; + formatNameTable[Int64] = "int 64"; + formatNameTable[FixExt1] = "fixext 1"; + formatNameTable[FixExt2] = "fixext 2"; + formatNameTable[FixExt4] = "fixext 4"; + formatNameTable[FixExt8] = "fixext 8"; + formatNameTable[FixExt16] = "fixext 16"; + formatNameTable[Str8] = "str 8"; + formatNameTable[Str16] = "str 16"; + formatNameTable[Str32] = "str 32"; + formatNameTable[Array16] = "array 16"; + formatNameTable[Array32] = "array 32"; + formatNameTable[Map16] = "map 16"; + formatNameTable[Map32] = "map 32"; + + for (int i = MinNegativeFixInt; i <= MaxNegativeFixInt; i++) + { + typeLookupTable[i] = MessagePackType.Integer; + formatNameTable[i] = "negative fixint"; + } + } + + public static MessagePackType ToMessagePackType(byte code) + { + return typeLookupTable[code]; + } + + public static string ToFormatName(byte code) + { + return formatNameTable[code]; + } + } + + internal static class ReservedMessagePackExtensionTypeCode + { + public const sbyte DateTime = -1; + } + + internal static class MessagePackRange + { + public const int MinFixNegativeInt = -32; + public const int MaxFixNegativeInt = -1; + public const int MaxFixPositiveInt = 127; + public const int MinFixStringLength = 0; + public const int MaxFixStringLength = 31; + public const int MaxFixMapCount = 15; + public const int MaxFixArrayCount = 15; + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackSecurity.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSecurity.cs new file mode 100644 index 0000000000..0f993a84cb --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSecurity.cs @@ -0,0 +1,364 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; + +namespace Datadog.Trace.Vendors.MessagePack +{ + /// + /// Settings related to security, particularly relevant when deserializing data from untrusted sources. + /// + internal class MessagePackSecurity + { + /// + /// The thread-local value tracking recursion for an ongoing deserialization operation. + /// + private static readonly ThreadLocal ObjectGraphDepth = new ThreadLocal(); + + /// + /// Gets an instance preconfigured with settings that omit all protections. Useful for deserializing fully-trusted and valid msgpack sequences. + /// + public static readonly MessagePackSecurity TrustedData = new MessagePackSecurity(); + + /// + /// Gets an instance preconfigured with protections applied with reasonable settings for deserializing untrusted msgpack sequences. + /// + public static readonly MessagePackSecurity UntrustedData = new MessagePackSecurity + { + HashCollisionResistant = true, + MaximumObjectGraphDepth = 500, + }; + + /// + /// The instance that is active for all deserialization operations within this AppDomain or process. + /// + /// Defaults to . + public static MessagePackSecurity Active = TrustedData; + + private readonly ObjectFallbackEqualityComparer objectFallbackEqualityComparer; + + private MessagePackSecurity() + { + this.objectFallbackEqualityComparer = new ObjectFallbackEqualityComparer(this); + } + + /// + /// Initializes a new instance of the class + /// with properties copied from a provided template. + /// + /// The template to copy from. + protected MessagePackSecurity(MessagePackSecurity copyFrom) + { + if (copyFrom is null) + { + throw new ArgumentNullException(nameof(copyFrom)); + } + + this.HashCollisionResistant = copyFrom.HashCollisionResistant; + this.MaximumObjectGraphDepth = copyFrom.MaximumObjectGraphDepth; + } + + /// + /// Gets a value indicating whether data to be deserialized is untrusted and thus should not be allowed to create + /// dictionaries or other hash-based collections unless the hashed type has a hash collision resistant implementation available. + /// This can mitigate some denial of service attacks when deserializing untrusted code. + /// + /// + /// The value is false for and true for . + /// + public bool HashCollisionResistant { get; private set; } + + /// + /// Gets the maximum depth of an object graph that may be deserialized. + /// + /// + /// + /// This value can be reduced to avoid a stack overflow that would crash the process when deserializing a msgpack sequence designed to cause deep recursion. + /// A very short callstack on a thread with 1MB of total stack space might deserialize ~2000 nested arrays before crashing due to a stack overflow. + /// Since stack space occupied may vary by the kind of object deserialized, a conservative value for this property to defend against stack overflow attacks might be 500. + /// + /// + public int MaximumObjectGraphDepth { get; private set; } = int.MaxValue; + + /// + /// Gets a copy of these options with the property set to a new value. + /// + /// The new value for the property. + /// The new instance; or the original if the value is unchanged. + public MessagePackSecurity WithMaximumObjectGraphDepth(int maximumObjectGraphDepth) + { + if (this.MaximumObjectGraphDepth == maximumObjectGraphDepth) + { + return this; + } + + var clone = this.Clone(); + clone.MaximumObjectGraphDepth = maximumObjectGraphDepth; + return clone; + } + + /// + /// Gets a copy of these options with the property set to a new value. + /// + /// The new value for the property. + /// The new instance; or the original if the value is unchanged. + public MessagePackSecurity WithHashCollisionResistant(bool hashCollisionResistant) + { + if (this.HashCollisionResistant == hashCollisionResistant) + { + return this; + } + + var clone = this.Clone(); + clone.HashCollisionResistant = hashCollisionResistant; + return clone; + } + + /// + /// Gets an that is suitable to use with a hash-based collection. + /// + /// The type of key that will be hashed in the collection. + /// The to use. + /// + /// When is active, this will be a collision resistant instance which may reject certain key types. + /// When is not active, this will be . + /// + public IEqualityComparer GetEqualityComparer() + { + return this.HashCollisionResistant ? GetHashCollisionResistantEqualityComparer() : EqualityComparer.Default; + } + + /// + /// Gets an that is suitable to use with a hash-based collection. + /// + /// The to use. + /// + /// When is active, this will be a collision resistant instance which may reject certain key types. + /// When is not active, this will be . + /// + public IEqualityComparer GetEqualityComparer() + { + return this.HashCollisionResistant ? GetHashCollisionResistantEqualityComparer() : EqualityComparer.Default; + } + + /// + /// Returns a hash collision resistant equality comparer. + /// + /// The type of key that will be hashed in the collection. + /// A hash collision resistant equality comparer. + protected virtual IEqualityComparer GetHashCollisionResistantEqualityComparer() + { + // For anything 32-bits and under, our fallback base secure hasher is usually adequate since it makes the hash unpredictable. + // We should have special implementations for any value that is larger than 32-bits in order to make sure + // that all the data gets hashed securely rather than trivially and predictably compressed into 32-bits before being hashed. + // We also have to specially handle some 32-bit types (e.g. float) where multiple in-memory representations should hash to the same value. + // Any type supported by the PrimitiveObjectFormatter should be added here if supporting it as a key in a collection makes sense. + return + // 32-bits or smaller: + typeof(T) == typeof(bool) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(char) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(sbyte) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(byte) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(short) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(ushort) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(int) ? CollisionResistantHasher.Instance : + typeof(T) == typeof(uint) ? CollisionResistantHasher.Instance : + + // Larger than 32-bits (or otherwise require special handling): + typeof(T) == typeof(long) ? (IEqualityComparer)Int64EqualityComparer.Instance : + typeof(T) == typeof(ulong) ? (IEqualityComparer)UInt64EqualityComparer.Instance : + typeof(T) == typeof(string) ? (IEqualityComparer)StringEqualityComparer.Instance : + typeof(T) == typeof(object) ? (IEqualityComparer)this.objectFallbackEqualityComparer : + + // Any type we don't explicitly whitelist here shouldn't be allowed to use as the key in a hash-based collection since it isn't known to be hash resistant. + // This method can of course be overridden to add more hash collision resistant type support, or the deserializing party can indicate that the data is Trusted + // so that this method doesn't even get called. + throw new TypeAccessException($"No hash-resistant equality comparer available for type: {typeof(T)}"); + } + + /// + /// Should be called within the expression of a using statement around which a method + /// deserializes a sub-element. + /// + /// A value to be disposed of when deserializing the sub-element is complete. + /// Thrown when the depth of the object graph being deserialized exceeds . + /// + /// Rather than wrap the body of every method, + /// this should wrap *calls* to these methods. They need not appear in pure "thunk" methods that simply delegate the deserialization to another formatter. + /// In this way, we can avoid repeatedly incrementing and decrementing the counter when deserializing each element of a collection. + /// + public static ObjectGraphDepthStep DepthStep() + { + int max = Active.MaximumObjectGraphDepth; + if (max < int.MaxValue) + { + int current = ObjectGraphDepth.Value; + if (current >= max) + { + throw new InsufficientExecutionStackException($"This msgpack sequence has an object graph that exceeds the maximum depth allowed of {max}."); + } + + ObjectGraphDepth.Value = current + 1; + return new ObjectGraphDepthStep(true); + } + + return default; + } + + /// + /// Returns a hash collision resistant equality comparer. + /// + /// A hash collision resistant equality comparer. + protected virtual IEqualityComparer GetHashCollisionResistantEqualityComparer() => (IEqualityComparer)this.GetHashCollisionResistantEqualityComparer(); + + /// + /// Creates a new instance that is a copy of this one. + /// + /// + /// Derived types should override this method to instantiate their own derived type. + /// + protected virtual MessagePackSecurity Clone() => new MessagePackSecurity(this); + + /// + /// The struct returned from + /// that when disposed will decrement the object graph depth counter to reverse + /// the effect of the call to . + /// + internal struct ObjectGraphDepthStep : IDisposable + { + private readonly bool active; + + internal ObjectGraphDepthStep(bool active) + { + this.active = active; + } + + /// + public void Dispose() + { + if (this.active) + { + ObjectGraphDepth.Value--; + } + } + } + + /// + /// A hash collision resistant implementation of . + /// + /// The type of key that will be hashed. + private class CollisionResistantHasher : IEqualityComparer, IEqualityComparer + { + internal static readonly CollisionResistantHasher Instance = new CollisionResistantHasher(); + + public bool Equals(T x, T y) => EqualityComparer.Default.Equals(x, y); + + bool IEqualityComparer.Equals(object x, object y) => ((IEqualityComparer)EqualityComparer.Default).Equals(x, y); + + public int GetHashCode(object obj) => this.GetHashCode((T)obj); + + public virtual int GetHashCode(T value) => HashCode.Combine(value); + } + + /// + /// A special hash-resistent equality comparer that defers picking the actual implementation + /// till it can check the runtime type of each value to be hashed. + /// + private class ObjectFallbackEqualityComparer : IEqualityComparer, IEqualityComparer + { + private static readonly object[] EmptyObjectArray = new object[0]; + private static readonly MethodInfo GetHashCollisionResistantEqualityComparerOpenGenericMethod = typeof(MessagePackSecurity).GetTypeInfo().DeclaredMethods.Single(m => m.Name == nameof(MessagePackSecurity.GetHashCollisionResistantEqualityComparer) && m.IsGenericMethod); + private readonly MessagePackSecurity security; + private readonly ThreadsafeTypeKeyHashTable equalityComparerCache = new ThreadsafeTypeKeyHashTable(); + + internal ObjectFallbackEqualityComparer(MessagePackSecurity security) + { + this.security = security ?? throw new ArgumentNullException(nameof(security)); + } + + bool IEqualityComparer.Equals(object x, object y) => EqualityComparer.Default.Equals(x, y); + + bool IEqualityComparer.Equals(object x, object y) => ((IEqualityComparer)EqualityComparer.Default).Equals(x, y); + + public int GetHashCode(object value) + { + if (value is null) + { + return 0; + } + + Type valueType = value.GetType(); + + // Take care to avoid recursion. + if (valueType == typeof(object)) + { + // We can trust object.GetHashCode() to be collision resistant. + return value.GetHashCode(); + } + + if (!equalityComparerCache.TryGetValue(valueType, out IEqualityComparer equalityComparer)) + { + try + { + equalityComparer = (IEqualityComparer)GetHashCollisionResistantEqualityComparerOpenGenericMethod.MakeGenericMethod(valueType).Invoke(this.security, EmptyObjectArray); + } + catch (TargetInvocationException ex) + { + ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); + } + + equalityComparerCache.TryAdd(valueType, equalityComparer); + } + + return equalityComparer.GetHashCode(value); + } + } + + private class UInt64EqualityComparer : CollisionResistantHasher + { + internal static new readonly UInt64EqualityComparer Instance = new UInt64EqualityComparer(); + + public override int GetHashCode(ulong value) => HashCode.Combine((uint)(value >> 32), unchecked((uint)value)); + } + + private class Int64EqualityComparer : CollisionResistantHasher + { + internal static new readonly Int64EqualityComparer Instance = new Int64EqualityComparer(); + + public override int GetHashCode(long value) => HashCode.Combine((int)(value >> 32), unchecked((int)value)); + } + + private class StringEqualityComparer : CollisionResistantHasher + { + internal static new readonly StringEqualityComparer Instance = new StringEqualityComparer(); + + public override int GetHashCode(string value) + { +#if NETCOREAPP + // .NET Core already has a secure string hashing function. Just use it. + return value?.GetHashCode() ?? 0; +#else + var hash = default(HashCode); + for (int i = 0; i < value.Length; i++) + { + hash.Add(value[i]); + } + + return hash.ToHashCode(); +#endif + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.Json.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.Json.cs new file mode 100644 index 0000000000..3184f92678 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.Json.cs @@ -0,0 +1,339 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.Globalization; +using System.IO; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + // JSON API + internal static partial class MessagePackSerializer + { + /// + /// Dump to JSON string. + /// + public static string ToJson(T obj) + { + return ToJson(Serialize(obj)); + } + + /// + /// Dump to JSON string. + /// + public static string ToJson(T obj, IFormatterResolver resolver) + { + return ToJson(Serialize(obj, resolver)); + } + + /// + /// Dump message-pack binary to JSON string. + /// + public static string ToJson(byte[] bytes) + { + if (bytes == null || bytes.Length == 0) return ""; + + var sb = new StringBuilder(); + ToJsonCore(bytes, 0, sb); + return sb.ToString(); + } + + public static byte[] FromJson(string str) + { + using (var sr = new StringReader(str)) + { + return FromJson(sr); + } + } + + /// + /// From Json String to MessagePack binary + /// + public static byte[] FromJson(TextReader reader) + { + var offset = 0; + byte[] binary = null; + using (var jr = new TinyJsonReader(reader, false)) + { + FromJsonCore(jr, ref binary, ref offset); + } + MessagePackBinary.FastResize(ref binary, offset); + return binary; + } + + /// + /// return buffer is from memory pool, be careful to use. + /// + internal static ArraySegment FromJsonUnsafe(TextReader reader) + { + var offset = 0; + byte[] binary = InternalMemoryPool.GetBuffer(); // from memory pool. + using (var jr = new TinyJsonReader(reader, false)) + { + FromJsonCore(jr, ref binary, ref offset); + } + return new ArraySegment(binary, 0, offset); + } + + static uint FromJsonCore(TinyJsonReader jr, ref byte[] binary, ref int offset) + { + uint count = 0; + while (jr.Read()) + { + switch (jr.TokenType) + { + case TinyJsonToken.None: + break; + case TinyJsonToken.StartObject: + { + var startOffset = offset; + offset += 5; + var mapCount = FromJsonCore(jr, ref binary, ref offset); + mapCount = mapCount / 2; // remove propertyname string count. + MessagePackBinary.WriteMapHeaderForceMap32Block(ref binary, startOffset, mapCount); + count++; + break; + } + case TinyJsonToken.EndObject: + return count; // break + case TinyJsonToken.StartArray: + { + var startOffset = offset; + offset += 5; + var arrayCount = FromJsonCore(jr, ref binary, ref offset); + MessagePackBinary.WriteArrayHeaderForceArray32Block(ref binary, startOffset, arrayCount); + count++; + break; + } + case TinyJsonToken.EndArray: + return count; // break + case TinyJsonToken.Number: + var v = jr.ValueType; + if (v == ValueType.Double) + { + offset += MessagePackBinary.WriteDouble(ref binary, offset, jr.DoubleValue); + } + else if (v == ValueType.Long) + { + offset += MessagePackBinary.WriteInt64(ref binary, offset, jr.LongValue); + } + else if (v == ValueType.ULong) + { + offset += MessagePackBinary.WriteUInt64(ref binary, offset, jr.ULongValue); + } + else if (v == ValueType.Decimal) + { + offset += DecimalFormatter.Instance.Serialize(ref binary, offset, jr.DecimalValue, null); + } + count++; + break; + case TinyJsonToken.String: + offset += MessagePackBinary.WriteString(ref binary, offset, jr.StringValue); + count++; + break; + case TinyJsonToken.True: + offset += MessagePackBinary.WriteBoolean(ref binary, offset, true); + count++; + break; + case TinyJsonToken.False: + offset += MessagePackBinary.WriteBoolean(ref binary, offset, false); + count++; + break; + case TinyJsonToken.Null: + offset += MessagePackBinary.WriteNil(ref binary, offset); + count++; + break; + default: + break; + } + } + return count; + } + + static int ToJsonCore(byte[] bytes, int offset, StringBuilder builder) + { + var readSize = 0; + var type = MessagePackBinary.GetMessagePackType(bytes, offset); + switch (type) + { + case MessagePackType.Integer: + var code = bytes[offset]; + if (MessagePackCode.MinNegativeFixInt <= code && code <= MessagePackCode.MaxNegativeFixInt) builder.Append(MessagePackBinary.ReadSByte(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (MessagePackCode.MinFixInt <= code && code <= MessagePackCode.MaxFixInt) builder.Append(MessagePackBinary.ReadByte(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.Int8) builder.Append(MessagePackBinary.ReadSByte(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.Int16) builder.Append(MessagePackBinary.ReadInt16(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.Int32) builder.Append(MessagePackBinary.ReadInt32(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.Int64) builder.Append(MessagePackBinary.ReadInt64(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.UInt8) builder.Append(MessagePackBinary.ReadByte(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.UInt16) builder.Append(MessagePackBinary.ReadUInt16(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.UInt32) builder.Append(MessagePackBinary.ReadUInt32(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + else if (code == MessagePackCode.UInt64) builder.Append(MessagePackBinary.ReadUInt64(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + break; + case MessagePackType.Boolean: + builder.Append(MessagePackBinary.ReadBoolean(bytes, offset, out readSize) ? "true" : "false"); + break; + case MessagePackType.Float: + var floatCode = bytes[offset]; + if (floatCode == MessagePackCode.Float32) + { + builder.Append(MessagePackBinary.ReadSingle(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + } + else + { + builder.Append(MessagePackBinary.ReadDouble(bytes, offset, out readSize).ToString(System.Globalization.CultureInfo.InvariantCulture)); + } + break; + case MessagePackType.String: + WriteJsonString(MessagePackBinary.ReadString(bytes, offset, out readSize), builder); + break; + case MessagePackType.Binary: + builder.Append("\"" + Convert.ToBase64String(MessagePackBinary.ReadBytes(bytes, offset, out readSize)) + "\""); + break; + case MessagePackType.Array: + { + var length = MessagePackBinary.ReadArrayHeaderRaw(bytes, offset, out readSize); + var totalReadSize = readSize; + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + builder.Append("["); + for (int i = 0; i < length; i++) + { + readSize = ToJsonCore(bytes, offset, builder); + offset += readSize; + totalReadSize += readSize; + + if (i != length - 1) + { + builder.Append(","); + } + } + builder.Append("]"); + } + + return totalReadSize; + } + case MessagePackType.Map: + { + var length = MessagePackBinary.ReadMapHeaderRaw(bytes, offset, out readSize); + var totalReadSize = readSize; + offset += readSize; + using (MessagePackSecurity.DepthStep()) + { + builder.Append("{"); + for (int i = 0; i < length; i++) + { + // write key + { + var keyType = MessagePackBinary.GetMessagePackType(bytes, offset); + if (keyType == MessagePackType.String || keyType == MessagePackType.Binary) + { + readSize = ToJsonCore(bytes, offset, builder); + } + else + { + builder.Append("\""); + readSize = ToJsonCore(bytes, offset, builder); + builder.Append("\""); + } + offset += readSize; + totalReadSize += readSize; + } + + builder.Append(":"); + + // write body + { + readSize = ToJsonCore(bytes, offset, builder); + offset += readSize; + totalReadSize += readSize; + } + + if (i != length - 1) + { + builder.Append(","); + } + } + builder.Append("}"); + } + + return totalReadSize; + } + case MessagePackType.Extension: + var extHeader = MessagePackBinary.ReadExtensionFormatHeader(bytes, offset, out readSize); + if (extHeader.TypeCode == ReservedMessagePackExtensionTypeCode.DateTime) + { + var dt = MessagePackBinary.ReadDateTime(bytes, offset, out readSize); + builder.Append("\""); + builder.Append(dt.ToString("o", CultureInfo.InvariantCulture)); + builder.Append("\""); + } + else + { + var ext = MessagePackBinary.ReadExtensionFormat(bytes, offset, out readSize); + builder.Append("["); + builder.Append(ext.TypeCode); + builder.Append(","); + builder.Append("\""); + builder.Append(Convert.ToBase64String(ext.Data)); + builder.Append("\""); + builder.Append("]"); + } + break; + case MessagePackType.Unknown: + case MessagePackType.Nil: + default: + readSize = 1; + builder.Append("null"); + break; + } + + return readSize; + } + + // escape string + static void WriteJsonString(string value, StringBuilder builder) + { + builder.Append('\"'); + + var len = value.Length; + for (int i = 0; i < len; i++) + { + var c = value[i]; + switch (c) + { + case '"': + builder.Append("\\\""); + break; + case '\\': + builder.Append("\\\\"); + break; + case '\b': + builder.Append("\\b"); + break; + case '\f': + builder.Append("\\f"); + break; + case '\n': + builder.Append("\\n"); + break; + case '\r': + builder.Append("\\r"); + break; + case '\t': + builder.Append("\\t"); + break; + default: + builder.Append(c); + break; + } + } + + builder.Append('\"'); + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.NonGeneric.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.NonGeneric.cs new file mode 100644 index 0000000000..dbde2a5fb9 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.NonGeneric.cs @@ -0,0 +1,324 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if NETSTANDARD || NETFRAMEWORK + +using System; +using System.IO; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack +{ + // NonGeneric API + internal static partial class MessagePackSerializer + { + internal static class NonGeneric + { + delegate int RawFormatterSerialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver); + delegate object RawFormatterDeserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize); + + static readonly Func CreateCompiledMethods; + static readonly MessagePack.Internal.ThreadsafeTypeKeyHashTable serializes = new MessagePack.Internal.ThreadsafeTypeKeyHashTable(capacity: 64); + + static NonGeneric() + { + CreateCompiledMethods = t => new CompiledMethods(t); + } + + public static byte[] Serialize(Type type, object obj) + { + return GetOrAdd(type).serialize1.Invoke(obj); + } + + public static byte[] Serialize(Type type, object obj, IFormatterResolver resolver) + { + return GetOrAdd(type).serialize2.Invoke(obj, resolver); + } + + public static void Serialize(Type type, Stream stream, object obj) + { + GetOrAdd(type).serialize3.Invoke(stream, obj); + } + + public static void Serialize(Type type, Stream stream, object obj, IFormatterResolver resolver) + { + GetOrAdd(type).serialize4.Invoke(stream, obj, resolver); + } + + public static int Serialize(Type type, ref byte[] bytes, int offset, object value, IFormatterResolver resolver) + { + return GetOrAdd(type).serialize5.Invoke(ref bytes, offset, value, resolver); + } + + public static object Deserialize(Type type, byte[] bytes) + { + return GetOrAdd(type).deserialize1.Invoke(bytes); + } + + public static object Deserialize(Type type, byte[] bytes, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize2.Invoke(bytes, resolver); + } + + public static object Deserialize(Type type, Stream stream) + { + return GetOrAdd(type).deserialize3.Invoke(stream); + } + + public static object Deserialize(Type type, Stream stream, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize4.Invoke(stream, resolver); + } + + public static object Deserialize(Type type, Stream stream, bool readStrict) + { + return GetOrAdd(type).deserialize5.Invoke(stream, readStrict); + } + + public static object Deserialize(Type type, Stream stream, IFormatterResolver resolver, bool readStrict) + { + return GetOrAdd(type).deserialize6.Invoke(stream, resolver, readStrict); + } + + public static object Deserialize(Type type, ArraySegment bytes) + { + return GetOrAdd(type).deserialize7.Invoke(bytes); + } + + public static object Deserialize(Type type, ArraySegment bytes, IFormatterResolver resolver) + { + return GetOrAdd(type).deserialize8.Invoke(bytes, resolver); + } + + public static object Deserialize(Type type, byte[] bytes, int offset, IFormatterResolver resolver, out int readSize) + { + return GetOrAdd(type).deserialize9.Invoke(bytes, offset, resolver, out readSize); + } + + static CompiledMethods GetOrAdd(Type type) + { + return serializes.GetOrAdd(type, CreateCompiledMethods); + } + + class CompiledMethods + { + public readonly Func serialize1; + public readonly Func serialize2; + public readonly Action serialize3; + public readonly Action serialize4; + public readonly RawFormatterSerialize serialize5; + + public readonly Func deserialize1; + public readonly Func deserialize2; + public readonly Func deserialize3; + public readonly Func deserialize4; + public readonly Func deserialize5; + public readonly Func deserialize6; + + public readonly Func, object> deserialize7; + public readonly Func, IFormatterResolver, object> deserialize8; + public readonly RawFormatterDeserialize deserialize9; + + public CompiledMethods(Type type) + { + var ti = type.GetTypeInfo(); + { + // public static byte[] Serialize(T obj) + var serialize = GetMethod(type, new Type[] { null }); + + var param1 = Expression.Parameter(typeof(object), "obj"); + var body = Expression.Call(serialize, ti.IsValueType + ? Expression.Unbox(param1, type) + : Expression.Convert(param1, type)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.serialize1 = lambda; + } + { + // public static byte[] Serialize(T obj, IFormatterResolver resolver) + var serialize = GetMethod(type, new Type[] { null, typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(object), "obj"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var body = Expression.Call(serialize, ti.IsValueType + ? Expression.Unbox(param1, type) + : Expression.Convert(param1, type), param2); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.serialize2 = lambda; + } + { + // public static void Serialize(Stream stream, T obj) + var serialize = GetMethod(type, new Type[] { typeof(Stream), null }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(object), "obj"); + + var body = Expression.Call(serialize, param1, ti.IsValueType + ? Expression.Unbox(param2, type) + : Expression.Convert(param2, type)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.serialize3 = lambda; + } + { + // public static void Serialize(Stream stream, T obj, IFormatterResolver resolver) + var serialize = GetMethod(type, new Type[] { typeof(Stream), null, typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(object), "obj"); + var param3 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var body = Expression.Call(serialize, param1, ti.IsValueType + ? Expression.Unbox(param2, type) + : Expression.Convert(param2, type), param3); + var lambda = Expression.Lambda>(body, param1, param2, param3).Compile(); + + this.serialize4 = lambda; + } + { + // delegate int RawFormatterSerialize(ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver); + var serialize = GetMethod(type, new Type[] { typeof(byte[]).MakeByRefType(), typeof(int), null, typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(byte[]).MakeByRefType(), "bytes"); + var param2 = Expression.Parameter(typeof(int), "offset"); + var param3 = Expression.Parameter(typeof(object), "value"); + var param4 = Expression.Parameter(typeof(IFormatterResolver), "formatterResolver"); + + var body = Expression.Call(serialize, param1, param2, ti.IsValueType + ? Expression.Unbox(param3, type) + : Expression.Convert(param3, type), param4); + var lambda = Expression.Lambda(body, param1, param2, param3, param4).Compile(); + + this.serialize5 = lambda; + } + { + // public static T Deserialize(byte[] bytes) + var deserialize = GetMethod(type, new Type[] { typeof(byte[]) }); + + var param1 = Expression.Parameter(typeof(byte[]), "bytes"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.deserialize1 = lambda; + } + { + // public static T Deserialize(byte[] bytes, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(byte[]), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(byte[]), "bytes"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize2 = lambda; + } + { + // public static T Deserialize(Stream stream) + var deserialize = GetMethod(type, new Type[] { typeof(Stream) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda>(body, param1).Compile(); + + this.deserialize3 = lambda; + } + { + // public static T Deserialize(Stream stream, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize4 = lambda; + } + { + // public static T Deserialize(Stream stream, bool readStrict) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(bool) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(bool), "readStrict"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2).Compile(); + + this.deserialize5 = lambda; + } + { + // public static T Deserialize(Stream stream, IFormatterResolver resolver, bool readStrict) + var deserialize = GetMethod(type, new Type[] { typeof(Stream), typeof(IFormatterResolver), typeof(bool) }); + + var param1 = Expression.Parameter(typeof(Stream), "stream"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var param3 = Expression.Parameter(typeof(bool), "readStrict"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2, param3), typeof(object)); + var lambda = Expression.Lambda>(body, param1, param2, param3).Compile(); + + this.deserialize6 = lambda; + } + + { + // public static T Deserialize(ArraySegment bytes) + var deserialize = GetMethod(type, new Type[] { typeof(ArraySegment) }); + + var param1 = Expression.Parameter(typeof(ArraySegment), "bytes"); + var body = Expression.Convert(Expression.Call(deserialize, param1), typeof(object)); + var lambda = Expression.Lambda, object>>(body, param1).Compile(); + + this.deserialize7 = lambda; + } + { + // public static T Deserialize(ArraySegment bytes, IFormatterResolver resolver) + var deserialize = GetMethod(type, new Type[] { typeof(ArraySegment), typeof(IFormatterResolver) }); + + var param1 = Expression.Parameter(typeof(ArraySegment), "bytes"); + var param2 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2), typeof(object)); + var lambda = Expression.Lambda, IFormatterResolver, object>>(body, param1, param2).Compile(); + + this.deserialize8 = lambda; + } + { + // public static T Deserialize(byte[] bytes, int offset, IFormatterResolver resolver, out int readSize) + var deserialize = GetMethod(type, new Type[] { typeof(byte[]), typeof(int), typeof(IFormatterResolver), typeof(int).MakeByRefType() }); + + var param1 = Expression.Parameter(typeof(byte[]), "bytes"); + var param2 = Expression.Parameter(typeof(int), "offset"); + var param3 = Expression.Parameter(typeof(IFormatterResolver), "resolver"); + var param4 = Expression.Parameter(typeof(int).MakeByRefType(), "readSize"); + var body = Expression.Convert(Expression.Call(deserialize, param1, param2, param3, param4), typeof(object)); + var lambda = Expression.Lambda(body, param1, param2, param3, param4).Compile(); + + this.deserialize9 = lambda; + } + } + + // null is generic type marker. + static MethodInfo GetMethod(Type type, Type[] parameters) + { + return typeof(MessagePackSerializer).GetRuntimeMethods().Where(x => + { + if (!(x.Name == "Serialize" || x.Name == "Deserialize")) return false; + var ps = x.GetParameters(); + if (ps.Length != parameters.Length) return false; + for (int i = 0; i < ps.Length; i++) + { + if (parameters[i] == null && ps[i].ParameterType.IsGenericParameter) continue; + if (ps[i].ParameterType != parameters[i]) return false; + } + return true; + }) + .Single() + .MakeGenericMethod(type); + } + } + } + } +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.cs b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.cs new file mode 100644 index 0000000000..10cbe08fa1 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/MessagePackSerializer.cs @@ -0,0 +1,331 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.IO; + +namespace Datadog.Trace.Vendors.MessagePack +{ + /// + /// High-Level API of MessagePack for C#. + /// + internal static partial class MessagePackSerializer + { + static IFormatterResolver defaultResolver; + + /// + /// FormatterResolver that used resolver less overloads. If does not set it, used StandardResolver. + /// + public static IFormatterResolver DefaultResolver + { + get + { + if (defaultResolver == null) + { + defaultResolver = MessagePack.Resolvers.StandardResolver.Instance; + } + + return defaultResolver; + } + } + + /// + /// Is resolver decided? + /// + public static bool IsInitialized + { + get + { + return defaultResolver != null; + } + } + + /// + /// Set default resolver of MessagePackSerializer APIs. + /// + /// + public static void SetDefaultResolver(IFormatterResolver resolver) + { + defaultResolver = resolver; + } + + /// + /// Serialize to binary with default resolver. + /// + public static byte[] Serialize(T obj) + { + return Serialize(obj, defaultResolver); + } + + /// + /// Serialize to binary with specified resolver. + /// + public static byte[] Serialize(T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + var buffer = InternalMemoryPool.GetBuffer(); + + var len = formatter.Serialize(ref buffer, 0, obj, resolver); + + // do not return MemoryPool.Buffer. + return MessagePackBinary.FastCloneWithResize(buffer, len); + } + + /// + /// Serialize to binary. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly. + /// + public static ArraySegment SerializeUnsafe(T obj) + { + return SerializeUnsafe(obj, defaultResolver); + } + + /// + /// Serialize to binary with specified resolver. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly. + /// + public static ArraySegment SerializeUnsafe(T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + var buffer = InternalMemoryPool.GetBuffer(); + + var len = formatter.Serialize(ref buffer, 0, obj, resolver); + + // return raw memory pool, unsafe! + return new ArraySegment(buffer, 0, len); + } + + /// + /// Serialize to stream. + /// + public static void Serialize(Stream stream, T obj) + { + Serialize(stream, obj, defaultResolver); + } + + /// + /// Serialize to stream with specified resolver. + /// + public static void Serialize(Stream stream, T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + var buffer = InternalMemoryPool.GetBuffer(); + + var len = formatter.Serialize(ref buffer, 0, obj, resolver); + + // do not need resize. + stream.Write(buffer, 0, len); + } + + /// + /// Reflect of resolver.GetFormatterWithVerify[T].Serialize. + /// + public static int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver resolver) + { + return resolver.GetFormatterWithVerify().Serialize(ref bytes, offset, value, resolver); + } + +#if NETSTANDARD || NETFRAMEWORK + + /// + /// Serialize to stream(async). + /// + public static System.Threading.Tasks.Task SerializeAsync(Stream stream, T obj) + { + return SerializeAsync(stream, obj, defaultResolver); + } + + /// + /// Serialize to stream(async) with specified resolver. + /// + public static async System.Threading.Tasks.Task SerializeAsync(Stream stream, T obj, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + var rentBuffer = BufferPool.Default.Rent(); + try + { + var buffer = rentBuffer; + var len = formatter.Serialize(ref buffer, 0, obj, resolver); + + // do not need resize. + await stream.WriteAsync(buffer, 0, len).ConfigureAwait(false); + } + finally + { + BufferPool.Default.Return(rentBuffer); + } + } + +#endif + + public static T Deserialize(byte[] bytes) + { + return Deserialize(bytes, defaultResolver); + } + + public static T Deserialize(byte[] bytes, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + int readSize; + return formatter.Deserialize(bytes, 0, resolver, out readSize); + } + + public static T Deserialize(ArraySegment bytes) + { + return Deserialize(bytes, defaultResolver); + } + + public static T Deserialize(ArraySegment bytes, IFormatterResolver resolver) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + int readSize; + return formatter.Deserialize(bytes.Array, bytes.Offset, resolver, out readSize); + } + + public static T Deserialize(Stream stream) + { + return Deserialize(stream, defaultResolver); + } + + public static T Deserialize(Stream stream, IFormatterResolver resolver) + { + return Deserialize(stream, resolver, false); + } + + public static T Deserialize(Stream stream, bool readStrict) + { + return Deserialize(stream, defaultResolver, readStrict); + } + + public static T Deserialize(Stream stream, IFormatterResolver resolver, bool readStrict) + { + if (resolver == null) resolver = DefaultResolver; + var formatter = resolver.GetFormatterWithVerify(); + + if (!readStrict) + { +#if NETSTANDARD && !NET45 + + var ms = stream as MemoryStream; + if (ms != null) + { + // optimize for MemoryStream + ArraySegment buffer; + if (ms.TryGetBuffer(out buffer)) + { + int readSize; + return formatter.Deserialize(buffer.Array, buffer.Offset, resolver, out readSize); + } + } +#endif + + // no else. + { + var buffer = InternalMemoryPool.GetBuffer(); + + FillFromStream(stream, ref buffer); + + int readSize; + return formatter.Deserialize(buffer, 0, resolver, out readSize); + } + } + else + { + int _; + var bytes = MessagePackBinary.ReadMessageBlockFromStreamUnsafe(stream, false, out _); + int readSize; + return formatter.Deserialize(bytes, 0, resolver, out readSize); + } + } + + /// + /// Reflect of resolver.GetFormatterWithVerify[T].Deserialize. + /// + public static T Deserialize(byte[] bytes, int offset, IFormatterResolver resolver, out int readSize) + { + return resolver.GetFormatterWithVerify().Deserialize(bytes, offset, resolver, out readSize); + } + +#if NETSTANDARD || NETFRAMEWORK + + public static System.Threading.Tasks.Task DeserializeAsync(Stream stream) + { + return DeserializeAsync(stream, defaultResolver); + } + + // readStrict async read is too slow(many Task garbage) so I don't provide async option. + + public static async System.Threading.Tasks.Task DeserializeAsync(Stream stream, IFormatterResolver resolver) + { + var rentBuffer = BufferPool.Default.Rent(); + var buf = rentBuffer; + try + { + int length = 0; + int read; + while ((read = await stream.ReadAsync(buf, length, buf.Length - length).ConfigureAwait(false)) > 0) + { + length += read; + if (length == buf.Length) + { + MessagePackBinary.FastResize(ref buf, length * 2); + } + } + + return Deserialize(buf, resolver); + } + finally + { + BufferPool.Default.Return(rentBuffer); + } + } + +#endif + + static int FillFromStream(Stream input, ref byte[] buffer) + { + int length = 0; + int read; + while ((read = input.Read(buffer, length, buffer.Length - length)) > 0) + { + length += read; + if (length == buffer.Length) + { + MessagePackBinary.FastResize(ref buffer, length * 2); + } + } + + return length; + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class InternalMemoryPool + { + [ThreadStatic] + static byte[] buffer = null; + + public static byte[] GetBuffer() + { + if (buffer == null) + { + buffer = new byte[65536]; + } + return buffer; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Nil.cs b/src/Datadog.Trace/Vendors/MessagePack/Nil.cs new file mode 100644 index 0000000000..b7ab5e6809 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Nil.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.MessagePack +{ + internal struct Nil : IEquatable + { + public static readonly Nil Default = new Nil(); + + public override bool Equals(object obj) + { + return obj is Nil; + } + + public bool Equals(Nil other) + { + return true; + } + + public override int GetHashCode() + { + return 0; + } + + public override string ToString() + { + return "()"; + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Formatters +{ + internal class NilFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new NilFormatter(); + + NilFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Nil value, IFormatterResolver typeResolver) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + public Nil Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize) + { + return MessagePackBinary.ReadNil(bytes, offset, out readSize); + } + } + + // NullableNil is same as Nil. + internal class NullableNilFormatter : IMessagePackFormatter + { + public static readonly IMessagePackFormatter Instance = new NullableNilFormatter(); + + NullableNilFormatter() + { + + } + + public int Serialize(ref byte[] bytes, int offset, Nil? value, IFormatterResolver typeResolver) + { + return MessagePackBinary.WriteNil(ref bytes, offset); + } + + public Nil? Deserialize(byte[] bytes, int offset, IFormatterResolver typeResolver, out int readSize) + { + return MessagePackBinary.ReadNil(bytes, offset, out readSize); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/AttributeFormatterResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/AttributeFormatterResolver.cs new file mode 100644 index 0000000000..1e652e3832 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/AttributeFormatterResolver.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using System; +using System.Reflection; +using System.Linq; // require UNITY_WSA + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + /// + /// Get formatter from [MessaegPackFromatter] attribute. + /// + internal sealed class AttributeFormatterResolver : IFormatterResolver + { + public static IFormatterResolver Instance = new AttributeFormatterResolver(); + + AttributeFormatterResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { +#if UNITY_WSA && !NETFX_CORE + var attr = (MessagePackFormatterAttribute)typeof(T).GetCustomAttributes(typeof(MessagePackFormatterAttribute), true).FirstOrDefault(); +#else + var attr = typeof(T).GetTypeInfo().GetCustomAttribute(); +#endif + if (attr == null) + { + return; + } + + if (attr.Arguments == null) + { + formatter = (IMessagePackFormatter)Activator.CreateInstance(attr.FormatterType); + } + else + { + formatter = (IMessagePackFormatter)Activator.CreateInstance(attr.FormatterType, attr.Arguments); + } + } + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/BuiltinResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/BuiltinResolver.cs new file mode 100644 index 0000000000..d655a0aea3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/BuiltinResolver.cs @@ -0,0 +1,155 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using Datadog.Trace.Vendors.MessagePack.Resolvers; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class BuiltinResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new BuiltinResolver(); + + BuiltinResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + // Reduce IL2CPP code generate size(don't write long code in ) + formatter = (IMessagePackFormatter)BuiltinResolverGetFormatterHelper.GetFormatter(typeof(T)); + } + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class BuiltinResolverGetFormatterHelper + { + static readonly Dictionary formatterMap = new Dictionary() + { + // Primitive + {typeof(Int16), Int16Formatter.Instance}, + {typeof(Int32), Int32Formatter.Instance}, + {typeof(Int64), Int64Formatter.Instance}, + {typeof(UInt16), UInt16Formatter.Instance}, + {typeof(UInt32), UInt32Formatter.Instance}, + {typeof(UInt64), UInt64Formatter.Instance}, + {typeof(Single), SingleFormatter.Instance}, + {typeof(Double), DoubleFormatter.Instance}, + {typeof(bool), BooleanFormatter.Instance}, + {typeof(byte), ByteFormatter.Instance}, + {typeof(sbyte), SByteFormatter.Instance}, + {typeof(DateTime), DateTimeFormatter.Instance}, + {typeof(char), CharFormatter.Instance}, + + // Nulllable Primitive + {typeof(Nullable), NullableInt16Formatter.Instance}, + {typeof(Nullable), NullableInt32Formatter.Instance}, + {typeof(Nullable), NullableInt64Formatter.Instance}, + {typeof(Nullable), NullableUInt16Formatter.Instance}, + {typeof(Nullable), NullableUInt32Formatter.Instance}, + {typeof(Nullable), NullableUInt64Formatter.Instance}, + {typeof(Nullable), NullableSingleFormatter.Instance}, + {typeof(Nullable), NullableDoubleFormatter.Instance}, + {typeof(Nullable), NullableBooleanFormatter.Instance}, + {typeof(Nullable), NullableByteFormatter.Instance}, + {typeof(Nullable), NullableSByteFormatter.Instance}, + {typeof(Nullable), NullableDateTimeFormatter.Instance}, + {typeof(Nullable), NullableCharFormatter.Instance}, + + // StandardClassLibraryFormatter + {typeof(string), NullableStringFormatter.Instance}, + {typeof(decimal), DecimalFormatter.Instance}, + {typeof(decimal?), new StaticNullableFormatter(DecimalFormatter.Instance)}, + {typeof(TimeSpan), TimeSpanFormatter.Instance}, + {typeof(TimeSpan?), new StaticNullableFormatter(TimeSpanFormatter.Instance)}, + {typeof(DateTimeOffset), DateTimeOffsetFormatter.Instance}, + {typeof(DateTimeOffset?), new StaticNullableFormatter(DateTimeOffsetFormatter.Instance)}, + {typeof(Guid), GuidFormatter.Instance}, + {typeof(Guid?), new StaticNullableFormatter(GuidFormatter.Instance)}, + {typeof(Uri), UriFormatter.Instance}, + {typeof(Version), VersionFormatter.Instance}, + {typeof(StringBuilder), StringBuilderFormatter.Instance}, + {typeof(BitArray), BitArrayFormatter.Instance}, + + // special primitive + {typeof(byte[]), ByteArrayFormatter.Instance}, + + // Nil + {typeof(Nil), NilFormatter.Instance}, + {typeof(Nil?), NullableNilFormatter.Instance}, + + // otpmitized primitive array formatter + {typeof(Int16[]), Int16ArrayFormatter.Instance}, + {typeof(Int32[]), Int32ArrayFormatter.Instance}, + {typeof(Int64[]), Int64ArrayFormatter.Instance}, + {typeof(UInt16[]), UInt16ArrayFormatter.Instance}, + {typeof(UInt32[]), UInt32ArrayFormatter.Instance}, + {typeof(UInt64[]), UInt64ArrayFormatter.Instance}, + {typeof(Single[]), SingleArrayFormatter.Instance}, + {typeof(Double[]), DoubleArrayFormatter.Instance}, + {typeof(Boolean[]), BooleanArrayFormatter.Instance}, + {typeof(SByte[]), SByteArrayFormatter.Instance}, + {typeof(DateTime[]), DateTimeArrayFormatter.Instance}, + {typeof(Char[]), CharArrayFormatter.Instance}, + {typeof(string[]), NullableStringArrayFormatter.Instance}, + + // well known collections + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + {typeof(List), new ListFormatter()}, + + { typeof(ArraySegment), ByteArraySegmentFormatter.Instance }, + { typeof(ArraySegment?),new StaticNullableFormatter>(ByteArraySegmentFormatter.Instance) }, + +#if NETSTANDARD || NETFRAMEWORK + {typeof(System.Numerics.BigInteger), BigIntegerFormatter.Instance}, + {typeof(System.Numerics.BigInteger?), new StaticNullableFormatter(BigIntegerFormatter.Instance)}, + {typeof(System.Numerics.Complex), ComplexFormatter.Instance}, + {typeof(System.Numerics.Complex?), new StaticNullableFormatter(ComplexFormatter.Instance)}, + {typeof(System.Threading.Tasks.Task), TaskUnitFormatter.Instance}, +#endif + }; + + internal static object GetFormatter(Type t) + { + object formatter; + if (formatterMap.TryGetValue(t, out formatter)) + { + return formatter; + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/CompositeResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/CompositeResolver.cs new file mode 100644 index 0000000000..b950558104 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/CompositeResolver.cs @@ -0,0 +1,111 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using System; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class CompositeResolver : IFormatterResolver + { + public static readonly CompositeResolver Instance = new CompositeResolver(); + + static bool isFreezed = false; + static IMessagePackFormatter[] formatters = new IMessagePackFormatter[0]; + static IFormatterResolver[] resolvers = new IFormatterResolver[0]; + + CompositeResolver() + { + } + + public static void Register(params IFormatterResolver[] resolvers) + { + if (isFreezed) + { + throw new InvalidOperationException("Register must call on startup(before use GetFormatter)."); + } + + CompositeResolver.resolvers = resolvers; + } + + public static void Register(params IMessagePackFormatter[] formatters) + { + if (isFreezed) + { + throw new InvalidOperationException("Register must call on startup(before use GetFormatter)."); + } + + CompositeResolver.formatters = formatters; + } + + public static void Register(IMessagePackFormatter[] formatters, IFormatterResolver[] resolvers) + { + if (isFreezed) + { + throw new InvalidOperationException("Register must call on startup(before use GetFormatter)."); + } + + CompositeResolver.resolvers = resolvers; + CompositeResolver.formatters = formatters; + } + + public static void RegisterAndSetAsDefault(params IFormatterResolver[] resolvers) + { + Register(resolvers); + MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); + } + + public static void RegisterAndSetAsDefault(params IMessagePackFormatter[] formatters) + { + Register(formatters); + MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); + } + + public static void RegisterAndSetAsDefault(IMessagePackFormatter[] formatters, IFormatterResolver[] resolvers) + { + Register(formatters); + Register(resolvers); + MessagePack.MessagePackSerializer.SetDefaultResolver(CompositeResolver.Instance); + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + isFreezed = true; + + foreach (var item in formatters) + { + foreach (var implInterface in item.GetType().GetTypeInfo().ImplementedInterfaces) + { + var ti = implInterface.GetTypeInfo(); + if (ti.IsGenericType && ti.GenericTypeArguments[0] == typeof(T)) + { + formatter = (IMessagePackFormatter)item; + return; + } + } + } + + foreach (var item in resolvers) + { + var f = item.GetFormatter(); + if (f != null) + { + formatter = f; + return; + } + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/ContractlessReflectionObjectResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/ContractlessReflectionObjectResolver.cs new file mode 100644 index 0000000000..defa59db7e --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/ContractlessReflectionObjectResolver.cs @@ -0,0 +1,309 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if NETSTANDARD || NETFRAMEWORK + +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + // MEMO: Not completely implemented. + + //internal static class ContractlessReflectionObjectResolver + //{ + // // TODO:CamelCase Option? AllowPrivate? + // public static readonly IFormatterResolver Default = new DefaultResolver(); + // public static readonly IFormatterResolver Contractless = new ContractlessResolver(); + // public static readonly IFormatterResolver ContractlessForceStringKey = new ContractlessForceStringResolver(); + + // class DefaultResolver : IFormatterResolver + // { + // const bool ForceStringKey = false; + // const bool Contractless = false; + // const bool AllowPrivate = false; + + // public IMessagePackFormatter GetFormatter() + // { + // return Cache.formatter; + // } + + // static class Cache + // { + // public static readonly IMessagePackFormatter formatter; + + // static Cache() + // { + // var metaInfo = ObjectSerializationInfo.CreateOrNull(typeof(T), ForceStringKey, Contractless, AllowPrivate); + // if (metaInfo != null) + // { + // formatter = new ReflectionObjectFormatter(metaInfo); + // } + // } + // } + // } + + // class ContractlessResolver : IFormatterResolver + // { + // const bool ForceStringKey = false; + // const bool Contractless = true; + // const bool AllowPrivate = false; + + // public IMessagePackFormatter GetFormatter() + // { + // return Cache.formatter; + // } + + // static class Cache + // { + // public static readonly IMessagePackFormatter formatter; + + // static Cache() + // { + // var metaInfo = ObjectSerializationInfo.CreateOrNull(typeof(T), ForceStringKey, Contractless, AllowPrivate); + // if (metaInfo != null) + // { + // formatter = new ReflectionObjectFormatter(metaInfo); + // } + // } + // } + // } + + // class ContractlessForceStringResolver : IFormatterResolver + // { + // const bool ForceStringKey = true; + // const bool Contractless = true; + // const bool AllowPrivate = false; + + // public IMessagePackFormatter GetFormatter() + // { + // return Cache.formatter; + // } + + // static class Cache + // { + // public static readonly IMessagePackFormatter formatter; + + // static Cache() + // { + // var metaInfo = ObjectSerializationInfo.CreateOrNull(typeof(T), ForceStringKey, Contractless, AllowPrivate); + // if (metaInfo != null) + // { + // formatter = new ReflectionObjectFormatter(metaInfo); + // } + // } + // } + // } + + //} + + + //internal class ReflectionObjectFormatter : IMessagePackFormatter + //{ + // readonly ObjectSerializationInfo metaInfo; + + // // for write + // readonly byte[][] writeMemberNames; + // readonly ObjectSerializationInfo.EmittableMember[] writeMembers; + + // // for read + // readonly int[] constructorParameterIndexes; + // readonly AutomataDictionary mapMemberDictionary; + // readonly ObjectSerializationInfo.EmittableMember[] readMembers; + + + // internal ReflectionObjectFormatter(ObjectSerializationInfo metaInfo) + // { + // this.metaInfo = metaInfo; + + // // for write + // { + // var memberNameList = new List(metaInfo.Members.Length); + // var emmitableMemberList = new List(metaInfo.Members.Length); + // foreach (var item in metaInfo.Members) + // { + // if (item.IsWritable) + // { + // emmitableMemberList.Add(item); + // memberNameList.Add(Encoding.UTF8.GetBytes(item.Name)); + // } + // } + // this.writeMemberNames = memberNameList.ToArray(); + // this.writeMembers = emmitableMemberList.ToArray(); + // } + // // for read + // { + // var automata = new AutomataDictionary(); + // var emmitableMemberList = new List(metaInfo.Members.Length); + // int index = 0; + // foreach (var item in metaInfo.Members) + // { + // if (item.IsReadable) + // { + // emmitableMemberList.Add(item); + // automata.Add(item.Name, index++); + // } + // } + // this.readMembers = emmitableMemberList.ToArray(); + // this.mapMemberDictionary = automata; + // } + // } + + // public int Serialize(ref byte[] bytes, int offset, T value, IFormatterResolver formatterResolver) + // { + // // reduce generic method size, avoid write code in type. + // if (metaInfo.IsIntKey) + // { + // return ReflectionObjectFormatterHelper.WriteArraySerialize(metaInfo, writeMembers, ref bytes, offset, value, formatterResolver); + // } + // else + // { + // return ReflectionObjectFormatterHelper.WriteMapSerialize(metaInfo, writeMembers, writeMemberNames, ref bytes, offset, value, formatterResolver); + // } + // } + + // public T Deserialize(byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + // { + // return (T)ReflectionObjectFormatterHelper.Deserialize(metaInfo, readMembers, constructorParameterIndexes, mapMemberDictionary, bytes, offset, formatterResolver, out readSize); + // } + //} + + //internal static class ReflectionObjectFormatterHelper + //{ + // internal static int WriteArraySerialize(ObjectSerializationInfo metaInfo, ObjectSerializationInfo.EmittableMember[] writeMembers, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver) + // { + // var startOffset = offset; + + // offset += MessagePackBinary.WriteArrayHeader(ref bytes, offset, writeMembers.Length); + // foreach (var item in metaInfo.Members) + // { + // if (item == null) + // { + // offset += MessagePackBinary.WriteNil(ref bytes, offset); + // } + // else + // { + // var memberValue = item.ReflectionLoadValue(value); + // offset += MessagePackSerializer.NonGeneric.Serialize(item.Type, ref bytes, offset, memberValue, formatterResolver); + // } + // } + + // return offset - startOffset; + // } + + // internal static int WriteMapSerialize(ObjectSerializationInfo metaInfo, ObjectSerializationInfo.EmittableMember[] writeMembers, byte[][] memberNames, ref byte[] bytes, int offset, object value, IFormatterResolver formatterResolver) + // { + // var startOffset = offset; + + // offset += MessagePackBinary.WriteMapHeader(ref bytes, offset, writeMembers.Length); + + // for (int i = 0; i < writeMembers.Length; i++) + // { + // offset += MessagePackBinary.WriteStringBytes(ref bytes, offset, memberNames[i]); + // var memberValue = writeMembers[i].ReflectionLoadValue(value); + // offset += MessagePackSerializer.NonGeneric.Serialize(writeMembers[i].Type, ref bytes, offset, memberValue, formatterResolver); + // } + + // return offset - startOffset; + // } + + // internal static object Deserialize(ObjectSerializationInfo metaInfo, ObjectSerializationInfo.EmittableMember[] readMembers, int[] constructorParameterIndexes, AutomataDictionary mapMemberDictionary, byte[] bytes, int offset, IFormatterResolver formatterResolver, out int readSize) + // { + // var startOffset = offset; + // object[] parameters = null; + + // var headerType = MessagePackBinary.GetMessagePackType(bytes, offset); + // if (headerType == MessagePackType.Nil) + // { + // readSize = 1; + // return null; + // } + // else if (headerType == MessagePackType.Array) + // { + // var arraySize = MessagePackBinary.ReadArrayHeader(bytes, offset, out readSize); + // offset += readSize; + + // // ReadValues + // parameters = new object[arraySize]; + // for (int i = 0; i < arraySize; i++) + // { + // var info = readMembers[i]; + // if (info != null) + // { + // parameters[i] = MessagePackSerializer.NonGeneric.Deserialize(info.Type, bytes, offset, formatterResolver, out readSize); + // offset += readSize; + // } + // else + // { + // offset += MessagePackBinary.ReadNextBlock(bytes, offset); + // } + // } + // } + // else if (headerType == MessagePackType.Map) + // { + // var mapSize = MessagePackBinary.ReadMapHeader(bytes, offset, out readSize); + // offset += readSize; + + // // ReadValues + // parameters = new object[mapSize]; + // for (int i = 0; i < mapSize; i++) + // { + // var rawPropName = MessagePackBinary.ReadStringSegment(bytes, offset, out readSize); + // offset += readSize; + + // int index; + // if (mapMemberDictionary.TryGetValue(rawPropName.Array, rawPropName.Offset, rawPropName.Count, out index)) + // { + // var info = readMembers[index]; + // parameters[index] = MessagePackSerializer.NonGeneric.Deserialize(info.Type, bytes, offset, formatterResolver, out readSize); + // offset += readSize; + // } + // else + // { + // offset += MessagePackBinary.ReadNextBlock(bytes, offset); + // } + // } + // } + // else + // { + // throw new InvalidOperationException("Invalid MessagePackType:" + MessagePackCode.ToFormatName(bytes[offset])); + // } + + // // CreateObject + // object result = null; + // if (constructorParameterIndexes.Length == 0) + // { + // result = Activator.CreateInstance(metaInfo.Type); + // } + // else + // { + // var args = new object[constructorParameterIndexes.Length]; + // for (int i = 0; i < constructorParameterIndexes.Length; i++) + // { + // args[i] = parameters[constructorParameterIndexes[i]]; + // } + + // result = Activator.CreateInstance(metaInfo.Type, args); + // } + + // // SetMembers + // for (int i = 0; i < readMembers.Length; i++) + // { + // var info = readMembers[i]; + // if (info != null) + // { + // info.ReflectionStoreValue(result, parameters[i]); + // } + // } + + // readSize = offset - startOffset; + // return result; + // } + //} +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicEnumAsStringResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicEnumAsStringResolver.cs new file mode 100644 index 0000000000..3626d57efd --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicEnumAsStringResolver.cs @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if !UNITY_WSA + +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.Reflection; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class DynamicEnumAsStringResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new DynamicEnumAsStringResolver(); + + DynamicEnumAsStringResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + var ti = typeof(T).GetTypeInfo(); + + if (ti.IsNullable()) + { + // build underlying type and use wrapped formatter. + ti = ti.GenericTypeArguments[0].GetTypeInfo(); + if (!ti.IsEnum) + { + return; + } + + var innerFormatter = DynamicEnumAsStringResolver.Instance.GetFormatterDynamic(ti.AsType()); + if (innerFormatter == null) + { + return; + } + formatter = (IMessagePackFormatter)Activator.CreateInstance(typeof(StaticNullableFormatter<>).MakeGenericType(ti.AsType()), new object[] { innerFormatter }); + return; + } + else if (!ti.IsEnum) + { + return; + } + + formatter = (IMessagePackFormatter)(object)new EnumAsStringFormatter(); + } + } + } +} + +#endif \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicGenericResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicGenericResolver.cs new file mode 100644 index 0000000000..72889ec00d --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/DynamicGenericResolver.cs @@ -0,0 +1,266 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +#if !UNITY_WSA + +using Datadog.Trace.Vendors.MessagePack.Formatters; +using System.Linq; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Collections.ObjectModel; +using System.Collections; + +#if NETSTANDARD || NETFRAMEWORK +using System.Threading.Tasks; +#endif + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class DynamicGenericResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new DynamicGenericResolver(); + + DynamicGenericResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + formatter = (IMessagePackFormatter)DynamicGenericResolverGetFormatterHelper.GetFormatter(typeof(T)); + } + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class DynamicGenericResolverGetFormatterHelper + { + static readonly Dictionary formatterMap = new Dictionary() + { + {typeof(List<>), typeof(ListFormatter<>)}, + {typeof(LinkedList<>), typeof(LinkedListFormatter<>)}, + {typeof(Queue<>), typeof(QeueueFormatter<>)}, + {typeof(Stack<>), typeof(StackFormatter<>)}, + {typeof(HashSet<>), typeof(HashSetFormatter<>)}, + {typeof(ReadOnlyCollection<>), typeof(ReadOnlyCollectionFormatter<>)}, + {typeof(IList<>), typeof(InterfaceListFormatter<>)}, + {typeof(ICollection<>), typeof(InterfaceCollectionFormatter<>)}, + {typeof(IEnumerable<>), typeof(InterfaceEnumerableFormatter<>)}, + {typeof(Dictionary<,>), typeof(DictionaryFormatter<,>)}, + {typeof(IDictionary<,>), typeof(InterfaceDictionaryFormatter<,>)}, + {typeof(SortedDictionary<,>), typeof(SortedDictionaryFormatter<,>)}, + {typeof(SortedList<,>), typeof(SortedListFormatter<,>)}, + {typeof(ILookup<,>), typeof(InterfaceLookupFormatter<,>)}, + {typeof(IGrouping<,>), typeof(InterfaceGroupingFormatter<,>)}, +#if NETSTANDARD || NETFRAMEWORK + {typeof(ObservableCollection<>), typeof(ObservableCollectionFormatter<>)}, + {typeof(ReadOnlyObservableCollection<>),(typeof(ReadOnlyObservableCollectionFormatter<>))}, + {typeof(IReadOnlyList<>), typeof(InterfaceReadOnlyListFormatter<>)}, + {typeof(IReadOnlyCollection<>), typeof(InterfaceReadOnlyCollectionFormatter<>)}, + {typeof(ISet<>), typeof(InterfaceSetFormatter<>)}, + {typeof(System.Collections.Concurrent.ConcurrentBag<>), typeof(ConcurrentBagFormatter<>)}, + {typeof(System.Collections.Concurrent.ConcurrentQueue<>), typeof(ConcurrentQueueFormatter<>)}, + {typeof(System.Collections.Concurrent.ConcurrentStack<>), typeof(ConcurrentStackFormatter<>)}, + {typeof(ReadOnlyDictionary<,>), typeof(ReadOnlyDictionaryFormatter<,>)}, + {typeof(IReadOnlyDictionary<,>), typeof(InterfaceReadOnlyDictionaryFormatter<,>)}, + {typeof(System.Collections.Concurrent.ConcurrentDictionary<,>), typeof(ConcurrentDictionaryFormatter<,>)}, + {typeof(Lazy<>), typeof(LazyFormatter<>)}, + {typeof(Task<>), typeof(TaskValueFormatter<>)}, +#endif + }; + + // Reduce IL2CPP code generate size(don't write long code in ) + internal static object GetFormatter(Type t) + { + var ti = t.GetTypeInfo(); + + if (t.IsArray) + { + var rank = t.GetArrayRank(); + if (rank == 1) + { + if (t.GetElementType() == typeof(byte)) // byte[] is also supported in builtin formatter. + { + return ByteArrayFormatter.Instance; + } + + return Activator.CreateInstance(typeof(ArrayFormatter<>).MakeGenericType(t.GetElementType())); + } + else if (rank == 2) + { + return Activator.CreateInstance(typeof(TwoDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); + } + else if (rank == 3) + { + return Activator.CreateInstance(typeof(ThreeDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); + } + else if (rank == 4) + { + return Activator.CreateInstance(typeof(FourDimentionalArrayFormatter<>).MakeGenericType(t.GetElementType())); + } + else + { + return null; // not supported built-in + } + } + else if (ti.IsGenericType) + { + var genericType = ti.GetGenericTypeDefinition(); + var genericTypeInfo = genericType.GetTypeInfo(); + var isNullable = genericTypeInfo.IsNullable(); + var nullableElementType = isNullable ? ti.GenericTypeArguments[0] : null; + + if (genericType == typeof(KeyValuePair<,>)) + { + return CreateInstance(typeof(KeyValuePairFormatter<,>), ti.GenericTypeArguments); + } + else if (isNullable && nullableElementType.GetTypeInfo().IsConstructedGenericType() && nullableElementType.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) + { + return CreateInstance(typeof(NullableFormatter<>), new[] { nullableElementType }); + } + +#if NETSTANDARD || NETFRAMEWORK + + // ValueTask + // Deleted, unneeded for Datadog.Trace + + // Tuple + else if (ti.FullName.StartsWith("System.Tuple")) + { + Type tupleFormatterType = null; + switch (ti.GenericTypeArguments.Length) + { + case 1: + tupleFormatterType = typeof(TupleFormatter<>); + break; + case 2: + tupleFormatterType = typeof(TupleFormatter<,>); + break; + case 3: + tupleFormatterType = typeof(TupleFormatter<,,>); + break; + case 4: + tupleFormatterType = typeof(TupleFormatter<,,,>); + break; + case 5: + tupleFormatterType = typeof(TupleFormatter<,,,,>); + break; + case 6: + tupleFormatterType = typeof(TupleFormatter<,,,,,>); + break; + case 7: + tupleFormatterType = typeof(TupleFormatter<,,,,,,>); + break; + case 8: + tupleFormatterType = typeof(TupleFormatter<,,,,,,,>); + break; + default: + break; + } + + return CreateInstance(tupleFormatterType, ti.GenericTypeArguments); + } + + // ValueTuple + // Deleted, unneeded for Datadog.Trace + +#endif + + // ArraySegement + else if (genericType == typeof(ArraySegment<>)) + { + if (ti.GenericTypeArguments[0] == typeof(byte)) + { + return ByteArraySegmentFormatter.Instance; + } + else + { + return CreateInstance(typeof(ArraySegmentFormatter<>), ti.GenericTypeArguments); + } + } + else if (isNullable && nullableElementType.GetTypeInfo().IsConstructedGenericType() && nullableElementType.GetGenericTypeDefinition() == typeof(ArraySegment<>)) + { + if (nullableElementType == typeof(ArraySegment)) + { + return new StaticNullableFormatter>(ByteArraySegmentFormatter.Instance); + } + else + { + return CreateInstance(typeof(NullableFormatter<>), new[] { nullableElementType }); + } + } + + // Mapped formatter + else + { + Type formatterType; + if (formatterMap.TryGetValue(genericType, out formatterType)) + { + return CreateInstance(formatterType, ti.GenericTypeArguments); + } + + // generic collection + else if (ti.GenericTypeArguments.Length == 1 + && ti.ImplementedInterfaces.Any(x => x.GetTypeInfo().IsConstructedGenericType() && x.GetGenericTypeDefinition() == typeof(ICollection<>)) + && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + var elemType = ti.GenericTypeArguments[0]; + return CreateInstance(typeof(GenericCollectionFormatter<,>), new[] { elemType, t }); + } + // generic dictionary + else if (ti.GenericTypeArguments.Length == 2 + && ti.ImplementedInterfaces.Any(x => x.GetTypeInfo().IsConstructedGenericType() && x.GetGenericTypeDefinition() == typeof(IDictionary<,>)) + && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + var keyType = ti.GenericTypeArguments[0]; + var valueType = ti.GenericTypeArguments[1]; + return CreateInstance(typeof(GenericDictionaryFormatter<,,>), new[] { keyType, valueType, t }); + } + } + } + else + { + // NonGeneric Collection + if (t == typeof(IList)) + { + return NonGenericInterfaceListFormatter.Instance; + } + else if (t == typeof(IDictionary)) + { + return NonGenericInterfaceDictionaryFormatter.Instance; + } + if (typeof(IList).GetTypeInfo().IsAssignableFrom(ti) && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + return Activator.CreateInstance(typeof(NonGenericListFormatter<>).MakeGenericType(t)); + } + else if (typeof(IDictionary).GetTypeInfo().IsAssignableFrom(ti) && ti.DeclaredConstructors.Any(x => x.GetParameters().Length == 0)) + { + return Activator.CreateInstance(typeof(NonGenericDictionaryFormatter<>).MakeGenericType(t)); + } + } + + return null; + } + + static object CreateInstance(Type genericType, Type[] genericTypeArguments, params object[] arguments) + { + return Activator.CreateInstance(genericType.MakeGenericType(genericTypeArguments), arguments); + } + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/NativeDateTimeResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/NativeDateTimeResolver.cs new file mode 100644 index 0000000000..977d1403d4 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/NativeDateTimeResolver.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class NativeDateTimeResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new NativeDateTimeResolver(); + + NativeDateTimeResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + formatter = (IMessagePackFormatter)NativeDateTimeResolverGetFormatterHelper.GetFormatter(typeof(T)); + } + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class NativeDateTimeResolverGetFormatterHelper + { + internal static object GetFormatter(Type t) + { + if (t == typeof(DateTime)) + { + return NativeDateTimeFormatter.Instance; + } + else if (t == typeof(DateTime?)) + { + return new StaticNullableFormatter(NativeDateTimeFormatter.Instance); + } + else if (t == typeof(DateTime[])) + { + return NativeDateTimeArrayFormatter.Instance; + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/OldSpecResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/OldSpecResolver.cs new file mode 100644 index 0000000000..bfc8405350 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/OldSpecResolver.cs @@ -0,0 +1,59 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using Datadog.Trace.Vendors.MessagePack.Internal; +using System; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class OldSpecResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new OldSpecResolver(); + + OldSpecResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + formatter = (IMessagePackFormatter)OldSpecResolverGetFormatterHelper.GetFormatter(typeof(T)); + } + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class OldSpecResolverGetFormatterHelper + { + internal static object GetFormatter(Type t) + { + if (t == typeof(string)) + { + return OldSpecStringFormatter.Instance; + } + else if (t == typeof(string[])) + { + return new ArrayFormatter(); + } + else if (t == typeof(byte[])) + { + return OldSpecBinaryFormatter.Instance; + } + + return null; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/PrimitiveObjectResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/PrimitiveObjectResolver.cs new file mode 100644 index 0000000000..9d3a5dbb20 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/PrimitiveObjectResolver.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + internal sealed class PrimitiveObjectResolver : IFormatterResolver + { + public static IFormatterResolver Instance = new PrimitiveObjectResolver(); + + PrimitiveObjectResolver() + { + + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + formatter = (typeof(T) == typeof(object)) + ? (IMessagePackFormatter)(object)PrimitiveObjectFormatter.Instance + : null; + } + } + } + +//#if NETSTANDARD || NETFRAMEWORK + +// /// +// /// In `object`, when serializing resolve by concrete type and when deserializing use primitive. +// /// +// internal sealed class DynamicObjectTypeFallbackResolver : IFormatterResolver +// { +// public static IFormatterResolver Instance = new DynamicObjectTypeFallbackResolver(); + +// DynamicObjectTypeFallbackResolver() +// { + +// } + +// public IMessagePackFormatter GetFormatter() +// { +// return FormatterCache.formatter; +// } + +// static class FormatterCache +// { +// public static readonly IMessagePackFormatter formatter; + +// static FormatterCache() +// { +// formatter = (typeof(T) == typeof(object)) +// ? (IMessagePackFormatter)(object)DynamicObjectTypeFallbackFormatter.Instance +// : null; +// } +// } +// } + +//#endif +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/MessagePack/Resolvers/StandardResolver.cs b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/StandardResolver.cs new file mode 100644 index 0000000000..f782cbfd36 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/Resolvers/StandardResolver.cs @@ -0,0 +1,349 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.MessagePack.Formatters; +using System.Linq; +using Datadog.Trace.Vendors.MessagePack.Internal; +using Datadog.Trace.Vendors.MessagePack.Resolvers; + +namespace Datadog.Trace.Vendors.MessagePack.Resolvers +{ + /// + /// Default composited resolver, builtin -> attribute -> dynamic enum -> dynamic generic -> dynamic union -> dynamic object -> primitive. + /// + internal sealed class StandardResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new StandardResolver(); + +#if NETSTANDARD || NETFRAMEWORK + public static readonly IMessagePackFormatter ObjectFallbackFormatter = new DynamicObjectTypeFallbackFormatter(StandardResolverCore.Instance); +#endif + + StandardResolver() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + if (typeof(T) == typeof(object)) + { + // final fallback +#if NETSTANDARD || NETFRAMEWORK + formatter = (IMessagePackFormatter)ObjectFallbackFormatter; +#else + formatter = PrimitiveObjectResolver.Instance.GetFormatter(); +#endif + } + else + { + formatter = StandardResolverCore.Instance.GetFormatter(); + } + } + } + } + + internal sealed class ContractlessStandardResolver : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new ContractlessStandardResolver(); + +#if NETSTANDARD || NETFRAMEWORK + public static readonly IMessagePackFormatter ObjectFallbackFormatter = new DynamicObjectTypeFallbackFormatter(ContractlessStandardResolverCore.Instance); +#endif + + ContractlessStandardResolver() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + if (typeof(T) == typeof(object)) + { + // final fallback +#if NETSTANDARD || NETFRAMEWORK + formatter = (IMessagePackFormatter)ObjectFallbackFormatter; +#else + formatter = PrimitiveObjectResolver.Instance.GetFormatter(); +#endif + } + else + { + formatter = ContractlessStandardResolverCore.Instance.GetFormatter(); + } + } + } + } + + internal sealed class StandardResolverAllowPrivate : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new StandardResolverAllowPrivate(); + +#if NETSTANDARD || NETFRAMEWORK + public static readonly IMessagePackFormatter ObjectFallbackFormatter = new DynamicObjectTypeFallbackFormatter(StandardResolverAllowPrivateCore.Instance); +#endif + + StandardResolverAllowPrivate() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + if (typeof(T) == typeof(object)) + { + // final fallback +#if NETSTANDARD || NETFRAMEWORK + formatter = (IMessagePackFormatter)ObjectFallbackFormatter; +#else + formatter = PrimitiveObjectResolver.Instance.GetFormatter(); +#endif + } + else + { + formatter = StandardResolverAllowPrivateCore.Instance.GetFormatter(); + } + } + } + } + + internal sealed class ContractlessStandardResolverAllowPrivate : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new ContractlessStandardResolverAllowPrivate(); + +#if NETSTANDARD || NETFRAMEWORK + public static readonly IMessagePackFormatter ObjectFallbackFormatter = new DynamicObjectTypeFallbackFormatter(ContractlessStandardResolverAllowPrivateCore.Instance); +#endif + + ContractlessStandardResolverAllowPrivate() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + if (typeof(T) == typeof(object)) + { + // final fallback +#if NETSTANDARD || NETFRAMEWORK + formatter = (IMessagePackFormatter)ObjectFallbackFormatter; +#else + formatter = PrimitiveObjectResolver.Instance.GetFormatter(); +#endif + } + else + { + formatter = ContractlessStandardResolverAllowPrivateCore.Instance.GetFormatter(); + } + } + } + } +} + +namespace Datadog.Trace.Vendors.MessagePack.Internal +{ + internal static class StandardResolverHelper + { + public static readonly IFormatterResolver[] DefaultResolvers = new[] + { + BuiltinResolver.Instance, // Try Builtin + AttributeFormatterResolver.Instance, // Try use [MessagePackFormatter] + +#if !(NETSTANDARD || NETFRAMEWORK) + MessagePack.Unity.UnityResolver.Instance, +#endif + +#if !ENABLE_IL2CPP && !UNITY_WSA && !NET_STANDARD_2_0 + + DynamicGenericResolver.Instance, // Try Array, Tuple, Collection +#endif + }; + } + + internal sealed class StandardResolverCore : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new StandardResolverCore(); + + static readonly IFormatterResolver[] resolvers = StandardResolverHelper.DefaultResolvers.Concat(new IFormatterResolver[] + { +#if !ENABLE_IL2CPP && !UNITY_WSA && !NET_STANDARD_2_0 +#endif + }).ToArray(); + + StandardResolverCore() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + foreach (var item in resolvers) + { + var f = item.GetFormatter(); + if (f != null) + { + formatter = f; + return; + } + } + } + } + } + + internal sealed class ContractlessStandardResolverCore : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new ContractlessStandardResolverCore(); + + static readonly IFormatterResolver[] resolvers = StandardResolverHelper.DefaultResolvers.Concat(new IFormatterResolver[] + { +#if !ENABLE_IL2CPP && !UNITY_WSA && !NET_STANDARD_2_0 +#endif + }).ToArray(); + + + ContractlessStandardResolverCore() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + foreach (var item in resolvers) + { + var f = item.GetFormatter(); + if (f != null) + { + formatter = f; + return; + } + } + } + } + } + + internal sealed class StandardResolverAllowPrivateCore : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new StandardResolverAllowPrivateCore(); + + static readonly IFormatterResolver[] resolvers = StandardResolverHelper.DefaultResolvers.Concat(new IFormatterResolver[] + { +#if !ENABLE_IL2CPP && !UNITY_WSA && !NET_STANDARD_2_0 +#endif + }).ToArray(); + + StandardResolverAllowPrivateCore() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + foreach (var item in resolvers) + { + var f = item.GetFormatter(); + if (f != null) + { + formatter = f; + return; + } + } + } + } + } + + internal sealed class ContractlessStandardResolverAllowPrivateCore : IFormatterResolver + { + public static readonly IFormatterResolver Instance = new ContractlessStandardResolverAllowPrivateCore(); + + static readonly IFormatterResolver[] resolvers = StandardResolverHelper.DefaultResolvers.Concat(new IFormatterResolver[] + { +#if !ENABLE_IL2CPP && !UNITY_WSA && !NET_STANDARD_2_0 +#endif + }).ToArray(); + + + ContractlessStandardResolverAllowPrivateCore() + { + } + + public IMessagePackFormatter GetFormatter() + { + return FormatterCache.formatter; + } + + static class FormatterCache + { + public static readonly IMessagePackFormatter formatter; + + static FormatterCache() + { + foreach (var item in resolvers) + { + var f = item.GetFormatter(); + if (f != null) + { + formatter = f; + return; + } + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/MessagePack/StringEncoding.cs b/src/Datadog.Trace/Vendors/MessagePack/StringEncoding.cs new file mode 100644 index 0000000000..ed9fdd2d22 --- /dev/null +++ b/src/Datadog.Trace/Vendors/MessagePack/StringEncoding.cs @@ -0,0 +1,13 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System.Text; + +namespace Datadog.Trace.Vendors.MessagePack +{ + internal static class StringEncoding + { + public static readonly Encoding UTF8 = new UTF8Encoding(false); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs new file mode 100644 index 0000000000..713705fc6f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/FileLoggerConfigurationExtensions.cs @@ -0,0 +1,343 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.ComponentModel; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Configuration; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting; +using Datadog.Trace.Vendors.Serilog.Formatting.Display; +using Datadog.Trace.Vendors.Serilog.Formatting.Json; +using Datadog.Trace.Vendors.Serilog.Sinks.File; + +// ReSharper disable MethodOverloadWithOptionalParameter + +namespace Datadog.Trace.Vendors.Serilog +{ + /// Extends with methods to add file sinks. + internal static class FileLoggerConfigurationExtensions + { + const int DefaultRetainedFileCountLimit = 31; // A long month of logs + const long DefaultFileSizeLimitBytes = 1L * 1024 * 1024 * 1024; + const string DefaultOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"; + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Supplies culture-specific formatting information, or null. + /// A message template describing the format used to write to the sink. + /// the default is "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}". + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Indicates if flushing to the output file can be buffered or not. The default + /// is false. + /// Allow the log file to be shared by multiple processes. The default is false. + /// If provided, a full disk flush will be performed periodically at the specified interval. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)] + public static LoggerConfiguration File( + this LoggerSinkConfiguration sinkConfiguration, + string path, + LogEventLevel restrictedToMinimumLevel, + string outputTemplate, + IFormatProvider formatProvider, + long? fileSizeLimitBytes, + LoggingLevelSwitch levelSwitch, + bool buffered, + bool shared, + TimeSpan? flushToDiskInterval) + { + // ReSharper disable once RedundantArgumentDefaultValue + return File(sinkConfiguration, path, restrictedToMinimumLevel, outputTemplate, formatProvider, fileSizeLimitBytes, + levelSwitch, buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, + null, null); + } + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// A formatter, such as , to convert the log events into + /// text for the file. If control of regular text formatting is required, use the other + /// overload of + /// and specify the outputTemplate parameter instead. + /// + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Indicates if flushing to the output file can be buffered or not. The default + /// is false. + /// Allow the log file to be shared by multiple processes. The default is false. + /// If provided, a full disk flush will be performed periodically at the specified interval. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + [Obsolete("New code should not be compiled against this obsolete overload"), EditorBrowsable(EditorBrowsableState.Never)] + public static LoggerConfiguration File( + this LoggerSinkConfiguration sinkConfiguration, + ITextFormatter formatter, + string path, + LogEventLevel restrictedToMinimumLevel, + long? fileSizeLimitBytes, + LoggingLevelSwitch levelSwitch, + bool buffered, + bool shared, + TimeSpan? flushToDiskInterval) + { + // ReSharper disable once RedundantArgumentDefaultValue + return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, + buffered, shared, flushToDiskInterval, RollingInterval.Infinite, false, null, null); + } + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Supplies culture-specific formatting information, or null. + /// A message template describing the format used to write to the sink. + /// the default is "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}". + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Indicates if flushing to the output file can be buffered or not. The default + /// is false. + /// Allow the log file to be shared by multiple processes. The default is false. + /// If provided, a full disk flush will be performed periodically at the specified interval. + /// The interval at which logging will roll over to a new file. + /// If true, a new file will be created when the file size limit is reached. Filenames + /// will have a number appended in the format _NNN, with the first filename given no number. + /// The maximum number of log files that will be retained, + /// including the current log file. For unlimited retention, pass null. The default is 31. + /// Character encoding used to write the text file. The default is UTF-8 without BOM. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + public static LoggerConfiguration File( + this LoggerSinkConfiguration sinkConfiguration, + string path, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + string outputTemplate = DefaultOutputTemplate, + IFormatProvider formatProvider = null, + long? fileSizeLimitBytes = DefaultFileSizeLimitBytes, + LoggingLevelSwitch levelSwitch = null, + bool buffered = false, + bool shared = false, + TimeSpan? flushToDiskInterval = null, + RollingInterval rollingInterval = RollingInterval.Infinite, + bool rollOnFileSizeLimit = false, + int? retainedFileCountLimit = DefaultRetainedFileCountLimit, + Encoding encoding = null) + { + if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration)); + if (path == null) throw new ArgumentNullException(nameof(path)); + if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate)); + + var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider); + return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, + levelSwitch, buffered, shared, flushToDiskInterval, + rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit, encoding); + } + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// A formatter, such as , to convert the log events into + /// text for the file. If control of regular text formatting is required, use the other + /// overload of + /// and specify the outputTemplate parameter instead. + /// + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Indicates if flushing to the output file can be buffered or not. The default + /// is false. + /// Allow the log file to be shared by multiple processes. The default is false. + /// If provided, a full disk flush will be performed periodically at the specified interval. + /// The interval at which logging will roll over to a new file. + /// If true, a new file will be created when the file size limit is reached. Filenames + /// will have a number appended in the format _NNN, with the first filename given no number. + /// The maximum number of log files that will be retained, + /// including the current log file. For unlimited retention, pass null. The default is 31. + /// Character encoding used to write the text file. The default is UTF-8 without BOM. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + public static LoggerConfiguration File( + this LoggerSinkConfiguration sinkConfiguration, + ITextFormatter formatter, + string path, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + long? fileSizeLimitBytes = DefaultFileSizeLimitBytes, + LoggingLevelSwitch levelSwitch = null, + bool buffered = false, + bool shared = false, + TimeSpan? flushToDiskInterval = null, + RollingInterval rollingInterval = RollingInterval.Infinite, + bool rollOnFileSizeLimit = false, + int? retainedFileCountLimit = DefaultRetainedFileCountLimit, + Encoding encoding = null) + { + return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, fileSizeLimitBytes, levelSwitch, + buffered, false, shared, flushToDiskInterval, encoding, rollingInterval, rollOnFileSizeLimit, retainedFileCountLimit); + } + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Supplies culture-specific formatting information, or null. + /// A message template describing the format used to write to the sink. + /// the default is "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}". + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + public static LoggerConfiguration File( + this LoggerAuditSinkConfiguration sinkConfiguration, + string path, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + string outputTemplate = DefaultOutputTemplate, + IFormatProvider formatProvider = null, + LoggingLevelSwitch levelSwitch = null) + { + if (sinkConfiguration == null) throw new ArgumentNullException(nameof(sinkConfiguration)); + if (path == null) throw new ArgumentNullException(nameof(path)); + if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate)); + + var formatter = new MessageTemplateTextFormatter(outputTemplate, formatProvider); + return File(sinkConfiguration, formatter, path, restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Write log events to the specified file. + /// + /// Logger sink configuration. + /// A formatter, such as , to convert the log events into + /// text for the file. If control of regular text formatting is required, use the other + /// overload of + /// and specify the outputTemplate parameter instead. + /// + /// Path to the file. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + public static LoggerConfiguration File( + this LoggerAuditSinkConfiguration sinkConfiguration, + ITextFormatter formatter, + string path, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + { + return ConfigureFile(sinkConfiguration.Sink, formatter, path, restrictedToMinimumLevel, null, levelSwitch, false, true, + false, null, null, RollingInterval.Infinite, false, null); + } + + static LoggerConfiguration ConfigureFile( + this Func addSink, + ITextFormatter formatter, + string path, + LogEventLevel restrictedToMinimumLevel, + long? fileSizeLimitBytes, + LoggingLevelSwitch levelSwitch, + bool buffered, + bool propagateExceptions, + bool shared, + TimeSpan? flushToDiskInterval, + Encoding encoding, + RollingInterval rollingInterval, + bool rollOnFileSizeLimit, + int? retainedFileCountLimit) + { + if (addSink == null) throw new ArgumentNullException(nameof(addSink)); + if (formatter == null) throw new ArgumentNullException(nameof(formatter)); + if (path == null) throw new ArgumentNullException(nameof(path)); + if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) throw new ArgumentException("Negative value provided; file size limit must be non-negative.", nameof(fileSizeLimitBytes)); + if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("At least one file must be retained.", nameof(retainedFileCountLimit)); + if (shared && buffered) throw new ArgumentException("Buffered writes are not available when file sharing is enabled.", nameof(buffered)); + + ILogEventSink sink; + + if (rollOnFileSizeLimit || rollingInterval != RollingInterval.Infinite) + { + sink = new RollingFileSink(path, formatter, fileSizeLimitBytes, retainedFileCountLimit, encoding, buffered, shared, rollingInterval, rollOnFileSizeLimit); + } + else + { + try + { +#pragma warning disable 618 + if (shared) + { + sink = new SharedFileSink(path, formatter, fileSizeLimitBytes); + } + else + { + sink = new FileSink(path, formatter, fileSizeLimitBytes, buffered: buffered); + } +#pragma warning restore 618 + } + catch (Exception ex) + { + SelfLog.WriteLine("Unable to open file sink for {0}: {1}", path, ex); + + if (propagateExceptions) + throw; + + return addSink(new NullSink(), LevelAlias.Maximum, null); + } + } + + if (flushToDiskInterval.HasValue) + { + sink = new PeriodicFlushToDiskSink(sink, flushToDiskInterval.Value); + } + + return addSink(sink, restrictedToMinimumLevel, levelSwitch); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/RollingInterval.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/RollingInterval.cs new file mode 100644 index 0000000000..bc7011fbec --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/RollingInterval.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog +{ + /// + /// Specifies the frequency at which the log file should roll. + /// + internal enum RollingInterval + { + /// + /// The log file will never roll; no time period information will be appended to the log file name. + /// + Infinite, + + /// + /// Roll every year. Filenames will have a four-digit year appended in the pattern yyyy. + /// + Year, + + /// + /// Roll every calendar month. Filenames will have yyyyMM appended. + /// + Month, + + /// + /// Roll every day. Filenames will have yyyyMMdd appended. + /// + Day, + + /// + /// Roll every hour. Filenames will have yyyyMMddHH appended. + /// + Hour, + + /// + /// Roll every minute. Filenames will have yyyyMMddHHmm appended. + /// + Minute + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Serilog.Sinks.File.csproj.txt b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Serilog.Sinks.File.csproj.txt new file mode 100644 index 0000000000..569e5b0b68 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Serilog.Sinks.File.csproj.txt @@ -0,0 +1,54 @@ + + + + Write Serilog events to text files in plain or JSON format. + 4.0.0 + Serilog Contributors + net45;netstandard1.3 + true + Serilog.Sinks.File + ../../assets/Serilog.snk + true + true + Serilog.Sinks.File + serilog;file + http://serilog.net/images/serilog-sink-nuget.png + http://serilog.net + http://www.apache.org/licenses/LICENSE-2.0 + false + Serilog + true + Serilog.Sinks.File + + true + + + + + + + + + + + + + + $(DefineConstants);ATOMIC_APPEND;HRESULTS + + + + $(DefineConstants);OS_MUTEX + + + + + + + + + + + + + diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/Clock.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/Clock.cs new file mode 100644 index 0000000000..b9f22ed740 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/Clock.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + static class Clock + { + static Func _dateTimeNow = () => DateTime.Now; + + [ThreadStatic] + static DateTime _testDateTimeNow; + + public static DateTime DateTimeNow => _dateTimeNow(); + + // Time is set per thread to support parallel + // If any thread uses the clock in test mode, all threads + // must use it in test mode; once set to test mode only + // terminating the application returns it to normal use. + public static void SetTestDateTimeNow(DateTime now) + { + _testDateTimeNow = now; + _dateTimeNow = () => _testDateTimeNow; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/FileSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/FileSink.cs new file mode 100644 index 0000000000..d84afbba14 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/FileSink.cs @@ -0,0 +1,125 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// Write log events to a disk file. + /// + [Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File()` instead.")] + internal sealed class FileSink : IFileSink, IDisposable + { + readonly TextWriter _output; + readonly FileStream _underlyingStream; + readonly ITextFormatter _textFormatter; + readonly long? _fileSizeLimitBytes; + readonly bool _buffered; + readonly object _syncRoot = new object(); + readonly WriteCountingStream _countingStreamWrapper; + + /// Construct a . + /// Path to the file. + /// Formatter used to convert log events to text. + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Character encoding used to write the text file. The default is UTF-8 without BOM. + /// Indicates if flushing to the output file can be buffered or not. The default + /// is false. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + /// + public FileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding encoding = null, bool buffered = false) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + if (textFormatter == null) throw new ArgumentNullException(nameof(textFormatter)); + if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) throw new ArgumentException("Negative value provided; file size limit must be non-negative."); + + _textFormatter = textFormatter; + _fileSizeLimitBytes = fileSizeLimitBytes; + _buffered = buffered; + + var directory = Path.GetDirectoryName(path); + if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + Stream outputStream = _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.Read); + if (_fileSizeLimitBytes != null) + { + outputStream = _countingStreamWrapper = new WriteCountingStream(_underlyingStream); + } + + _output = new StreamWriter(outputStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + bool IFileSink.EmitOrOverflow(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + lock (_syncRoot) + { + if (_fileSizeLimitBytes != null) + { + if (_countingStreamWrapper.CountedLength >= _fileSizeLimitBytes.Value) + return false; + } + + _textFormatter.Format(logEvent, _output); + if (!_buffered) + _output.Flush(); + + return true; + } + } + + /// + /// Emit the provided log event to the sink. + /// + /// The log event to write. + public void Emit(LogEvent logEvent) + { + ((IFileSink) this).EmitOrOverflow(logEvent); + } + + /// + public void Dispose() + { + lock (_syncRoot) + { + _output.Dispose(); + } + } + + /// + public void FlushToDisk() + { + lock (_syncRoot) + { + _output.Flush(); + _underlyingStream.Flush(true); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFileSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFileSink.cs new file mode 100644 index 0000000000..437db1eda7 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFileSink.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// Exists only for the convenience of , which + /// switches implementations based on sharing. Would refactor, but preserving + /// backwards compatibility. + /// + interface IFileSink : ILogEventSink, IFlushableFileSink + { + bool EmitOrOverflow(LogEvent logEvent); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs new file mode 100644 index 0000000000..36ec59b65b --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IFlushableFileSink.cs @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// Supported by (file-based) sinks that can be explicitly flushed. + /// + internal interface IFlushableFileSink + { + /// + /// Flush buffered contents to disk. + /// + void FlushToDisk(); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IOErrors.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IOErrors.cs new file mode 100644 index 0000000000..7db5b783fa --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/IOErrors.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + static class IOErrors + { + public static bool IsLockedFile(IOException ex) + { +#if HRESULTS + var errorCode = System.Runtime.InteropServices.Marshal.GetHRForException(ex) & ((1 << 16) - 1); + return errorCode == 32 || errorCode == 33; +#else + return true; +#endif + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/NullSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/NullSink.cs new file mode 100644 index 0000000000..a28e41e9a1 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/NullSink.cs @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// An instance of this sink may be substituted when an instance of the + /// is unable to be constructed. + /// + class NullSink : ILogEventSink + { + public void Emit(LogEvent logEvent) + { + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PathRoller.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PathRoller.cs new file mode 100644 index 0000000000..02146e5da6 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PathRoller.cs @@ -0,0 +1,120 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + class PathRoller + { + const string PeriodMatchGroup = "period"; + const string SequenceNumberMatchGroup = "sequence"; + + readonly string _directory; + readonly string _filenamePrefix; + readonly string _filenameSuffix; + readonly Regex _filenameMatcher; + + readonly RollingInterval _interval; + readonly string _periodFormat; + + public PathRoller(string path, RollingInterval interval) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + _interval = interval; + _periodFormat = interval.GetFormat(); + + var pathDirectory = Path.GetDirectoryName(path); + if (string.IsNullOrEmpty(pathDirectory)) + pathDirectory = Directory.GetCurrentDirectory(); + + _directory = Path.GetFullPath(pathDirectory); + _filenamePrefix = Path.GetFileNameWithoutExtension(path); + _filenameSuffix = Path.GetExtension(path); + _filenameMatcher = new Regex( + "^" + + Regex.Escape(_filenamePrefix) + + "(?<" + PeriodMatchGroup + ">\\d{" + _periodFormat.Length + "})" + + "(?<" + SequenceNumberMatchGroup + ">_[0-9]{3,}){0,1}" + + Regex.Escape(_filenameSuffix) + + "$"); + + DirectorySearchPattern = $"{_filenamePrefix}*{_filenameSuffix}"; + } + + public string LogFileDirectory => _directory; + + public string DirectorySearchPattern { get; } + + public void GetLogFilePath(DateTime date, int? sequenceNumber, out string path) + { + var currentCheckpoint = GetCurrentCheckpoint(date); + + var tok = currentCheckpoint?.ToString(_periodFormat, CultureInfo.InvariantCulture) ?? ""; + + if (sequenceNumber != null) + tok += "_" + sequenceNumber.Value.ToString("000", CultureInfo.InvariantCulture); + + path = Path.Combine(_directory, _filenamePrefix + tok + _filenameSuffix); + } + + public IEnumerable SelectMatches(IEnumerable filenames) + { + foreach (var filename in filenames) + { + var match = _filenameMatcher.Match(filename); + if (!match.Success) + continue; + + int? inc = null; + var incGroup = match.Groups[SequenceNumberMatchGroup]; + if (incGroup.Captures.Count != 0) + { + var incPart = incGroup.Captures[0].Value.Substring(1); + inc = int.Parse(incPart, CultureInfo.InvariantCulture); + } + + DateTime? period = null; + var periodGroup = match.Groups[PeriodMatchGroup]; + if (periodGroup.Captures.Count != 0) + { + var dateTimePart = periodGroup.Captures[0].Value; + if (DateTime.TryParseExact( + dateTimePart, + _periodFormat, + CultureInfo.InvariantCulture, + DateTimeStyles.None, + out var dateTime)) + { + period = dateTime; + } + } + + yield return new RollingLogFile(filename, period, inc); + } + } + + public DateTime? GetCurrentCheckpoint(DateTime instant) => _interval.GetCurrentCheckpoint(instant); + + public DateTime? GetNextCheckpoint(DateTime instant) => _interval.GetNextCheckpoint(instant); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs new file mode 100644 index 0000000000..53add4e95a --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/PeriodicFlushToDiskSink.cs @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Threading; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// A sink wrapper that periodically flushes the wrapped sink to disk. + /// + internal class PeriodicFlushToDiskSink : ILogEventSink, IDisposable + { + readonly ILogEventSink _sink; + readonly Timer _timer; + int _flushRequired; + + /// + /// Construct a that wraps + /// and flushes it at the specified . + /// + /// The sink to wrap. + /// The interval at which to flush the underlying sink. + /// + public PeriodicFlushToDiskSink(ILogEventSink sink, TimeSpan flushInterval) + { + if (sink == null) throw new ArgumentNullException(nameof(sink)); + + _sink = sink; + + var flushable = sink as IFlushableFileSink; + if (flushable != null) + { + _timer = new Timer(_ => FlushToDisk(flushable), null, flushInterval, flushInterval); + } + else + { + _timer = new Timer(_ => { }, null, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan); + SelfLog.WriteLine("{0} configured to flush {1}, but {2} not implemented", typeof(PeriodicFlushToDiskSink), sink, nameof(IFlushableFileSink)); + } + } + + /// + public void Emit(LogEvent logEvent) + { + _sink.Emit(logEvent); + Interlocked.Exchange(ref _flushRequired, 1); + } + + /// + public void Dispose() + { + _timer.Dispose(); + (_sink as IDisposable)?.Dispose(); + } + + void FlushToDisk(IFlushableFileSink flushable) + { + try + { + if (Interlocked.CompareExchange(ref _flushRequired, 0, 1) == 1) + { + // May throw ObjectDisposedException, since we're not trying to synchronize + // anything here in the wrapper. + flushable.FlushToDisk(); + } + } + catch (Exception ex) + { + SelfLog.WriteLine("{0} could not flush the underlying sink to disk: {1}", typeof(PeriodicFlushToDiskSink), ex); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs new file mode 100644 index 0000000000..b04b3b9948 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingFileSink.cs @@ -0,0 +1,237 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma warning disable 618 + +using System; +using System.IO; +using System.Linq; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + sealed class RollingFileSink : ILogEventSink, IFlushableFileSink, IDisposable + { + readonly PathRoller _roller; + readonly ITextFormatter _textFormatter; + readonly long? _fileSizeLimitBytes; + readonly int? _retainedFileCountLimit; + readonly Encoding _encoding; + readonly bool _buffered; + readonly bool _shared; + readonly bool _rollOnFileSizeLimit; + + readonly object _syncRoot = new object(); + bool _isDisposed; + DateTime? _nextCheckpoint; + IFileSink _currentFile; + int? _currentFileSequence; + + public RollingFileSink(string path, + ITextFormatter textFormatter, + long? fileSizeLimitBytes, + int? retainedFileCountLimit, + Encoding encoding, + bool buffered, + bool shared, + RollingInterval rollingInterval, + bool rollOnFileSizeLimit) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) throw new ArgumentException("Negative value provided; file size limit must be non-negative"); + if (retainedFileCountLimit.HasValue && retainedFileCountLimit < 1) throw new ArgumentException("Zero or negative value provided; retained file count limit must be at least 1"); + + _roller = new PathRoller(path, rollingInterval); + _textFormatter = textFormatter; + _fileSizeLimitBytes = fileSizeLimitBytes; + _retainedFileCountLimit = retainedFileCountLimit; + _encoding = encoding; + _buffered = buffered; + _shared = shared; + _rollOnFileSizeLimit = rollOnFileSizeLimit; + } + + public void Emit(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + lock (_syncRoot) + { + if (_isDisposed) throw new ObjectDisposedException("The log file has been disposed."); + + var now = Clock.DateTimeNow; + AlignCurrentFileTo(now); + + while (_currentFile?.EmitOrOverflow(logEvent) == false && _rollOnFileSizeLimit) + { + AlignCurrentFileTo(now, nextSequence: true); + } + } + } + + void AlignCurrentFileTo(DateTime now, bool nextSequence = false) + { + if (!_nextCheckpoint.HasValue) + { + OpenFile(now); + } + else if (nextSequence || now >= _nextCheckpoint.Value) + { + int? minSequence = null; + if (nextSequence) + { + if (_currentFileSequence == null) + minSequence = 1; + else + minSequence = _currentFileSequence.Value + 1; + } + + CloseFile(); + OpenFile(now, minSequence); + } + } + + void OpenFile(DateTime now, int? minSequence = null) + { + var currentCheckpoint = _roller.GetCurrentCheckpoint(now); + + // We only try periodically because repeated failures + // to open log files REALLY slow an app down. + _nextCheckpoint = _roller.GetNextCheckpoint(now) ?? now.AddMinutes(30); + + var existingFiles = Enumerable.Empty(); + try + { + existingFiles = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern) + .Select(Path.GetFileName); + } + catch (DirectoryNotFoundException) { } + + var latestForThisCheckpoint = _roller + .SelectMatches(existingFiles) + .Where(m => m.DateTime == currentCheckpoint) + .OrderByDescending(m => m.SequenceNumber) + .FirstOrDefault(); + + var sequence = latestForThisCheckpoint?.SequenceNumber; + if (minSequence != null) + { + if (sequence == null || sequence.Value < minSequence.Value) + sequence = minSequence; + } + + const int maxAttempts = 3; + for (var attempt = 0; attempt < maxAttempts; attempt++) + { + _roller.GetLogFilePath(now, sequence, out var path); + + try + { + _currentFile = _shared ? + (IFileSink)new SharedFileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding) : + new FileSink(path, _textFormatter, _fileSizeLimitBytes, _encoding, _buffered); + _currentFileSequence = sequence; + } + catch (IOException ex) + { + if (IOErrors.IsLockedFile(ex)) + { + SelfLog.WriteLine("File target {0} was locked, attempting to open next in sequence (attempt {1})", path, attempt + 1); + sequence = (sequence ?? 0) + 1; + continue; + } + + throw; + } + + ApplyRetentionPolicy(path); + return; + } + } + + void ApplyRetentionPolicy(string currentFilePath) + { + if (_retainedFileCountLimit == null) return; + + var currentFileName = Path.GetFileName(currentFilePath); + + // We consider the current file to exist, even if nothing's been written yet, + // because files are only opened on response to an event being processed. + var potentialMatches = Directory.GetFiles(_roller.LogFileDirectory, _roller.DirectorySearchPattern) + .Select(Path.GetFileName) + .Union(new [] { currentFileName }); + + var newestFirst = _roller + .SelectMatches(potentialMatches) + .OrderByDescending(m => m.DateTime) + .ThenByDescending(m => m.SequenceNumber) + .Select(m => m.Filename); + + var toRemove = newestFirst + .Where(n => StringComparer.OrdinalIgnoreCase.Compare(currentFileName, n) != 0) + .Skip(_retainedFileCountLimit.Value - 1) + .ToList(); + + foreach (var obsolete in toRemove) + { + var fullPath = Path.Combine(_roller.LogFileDirectory, obsolete); + try + { + System.IO.File.Delete(fullPath); + } + catch (Exception ex) + { + SelfLog.WriteLine("Error {0} while removing obsolete log file {1}", ex, fullPath); + } + } + } + + public void Dispose() + { + lock (_syncRoot) + { + if (_currentFile == null) return; + CloseFile(); + _isDisposed = true; + } + } + + void CloseFile() + { + if (_currentFile != null) + { + (_currentFile as IDisposable)?.Dispose(); + _currentFile = null; + } + + _nextCheckpoint = null; + } + + public void FlushToDisk() + { + lock (_syncRoot) + { + _currentFile?.FlushToDisk(); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs new file mode 100644 index 0000000000..98978b4cc5 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingIntervalExtensions.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + static class RollingIntervalExtensions + { + public static string GetFormat(this RollingInterval interval) + { + switch (interval) + { + case RollingInterval.Infinite: + return ""; + case RollingInterval.Year: + return "yyyy"; + case RollingInterval.Month: + return "yyyyMM"; + case RollingInterval.Day: + return "yyyyMMdd"; + case RollingInterval.Hour: + return "yyyyMMddHH"; + case RollingInterval.Minute: + return "yyyyMMddHHmm"; + default: + throw new ArgumentException("Invalid rolling interval"); + } + } + + public static DateTime? GetCurrentCheckpoint(this RollingInterval interval, DateTime instant) + { + switch (interval) + { + case RollingInterval.Infinite: + return null; + case RollingInterval.Year: + return new DateTime(instant.Year, 1, 1, 0, 0, 0, instant.Kind); + case RollingInterval.Month: + return new DateTime(instant.Year, instant.Month, 1, 0, 0, 0, instant.Kind); + case RollingInterval.Day: + return new DateTime(instant.Year, instant.Month, instant.Day, 0, 0, 0, instant.Kind); + case RollingInterval.Hour: + return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, 0, 0, instant.Kind); + case RollingInterval.Minute: + return new DateTime(instant.Year, instant.Month, instant.Day, instant.Hour, instant.Minute, 0, instant.Kind); + default: + throw new ArgumentException("Invalid rolling interval"); + } + } + + public static DateTime? GetNextCheckpoint(this RollingInterval interval, DateTime instant) + { + var current = GetCurrentCheckpoint(interval, instant); + if (current == null) + return null; + + switch (interval) + { + case RollingInterval.Year: + return current.Value.AddYears(1); + case RollingInterval.Month: + return current.Value.AddMonths(1); + case RollingInterval.Day: + return current.Value.AddDays(1); + case RollingInterval.Hour: + return current.Value.AddHours(1); + case RollingInterval.Minute: + return current.Value.AddMinutes(1); + default: + throw new ArgumentException("Invalid rolling interval"); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs new file mode 100644 index 0000000000..4884a3b68a --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/RollingLogFile.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + class RollingLogFile + { + public RollingLogFile(string filename, DateTime? dateTime, int? sequenceNumber) + { + Filename = filename; + DateTime = dateTime; + SequenceNumber = sequenceNumber; + } + + public string Filename { get; } + + public DateTime? DateTime { get; } + + public int? SequenceNumber { get; } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.AtomicAppend.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.AtomicAppend.cs new file mode 100644 index 0000000000..a939f578d2 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.AtomicAppend.cs @@ -0,0 +1,178 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if ATOMIC_APPEND + +using System; +using System.IO; +using System.Security.AccessControl; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// Write log events to a disk file. + /// + [Obsolete("This type will be removed from the public API in a future version; use `WriteTo.File(shared: true)` instead.")] + internal sealed class SharedFileSink : IFileSink, IDisposable + { + readonly MemoryStream _writeBuffer; + readonly string _path; + readonly TextWriter _output; + readonly ITextFormatter _textFormatter; + readonly long? _fileSizeLimitBytes; + readonly object _syncRoot = new object(); + + // The stream is reopened with a larger buffer if atomic writes beyond the current buffer size are needed. + FileStream _fileOutput; + int _fileStreamBufferLength = DefaultFileStreamBufferLength; + + const int DefaultFileStreamBufferLength = 4096; + + /// Construct a . + /// Path to the file. + /// Formatter used to convert log events to text. + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Character encoding used to write the text file. The default is UTF-8 without BOM. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + /// + public SharedFileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding encoding = null) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + if (textFormatter == null) throw new ArgumentNullException(nameof(textFormatter)); + if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) + throw new ArgumentException("Negative value provided; file size limit must be non-negative"); + + _path = path; + _textFormatter = textFormatter; + _fileSizeLimitBytes = fileSizeLimitBytes; + + var directory = Path.GetDirectoryName(path); + if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + // FileSystemRights.AppendData sets the Win32 FILE_APPEND_DATA flag. On Linux this is O_APPEND, but that API is not yet + // exposed by .NET Core. + _fileOutput = new FileStream( + path, + FileMode.Append, + FileSystemRights.AppendData, + FileShare.ReadWrite, + _fileStreamBufferLength, + FileOptions.None); + + _writeBuffer = new MemoryStream(); + _output = new StreamWriter(_writeBuffer, + encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + bool IFileSink.EmitOrOverflow(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + lock (_syncRoot) + { + try + { + _textFormatter.Format(logEvent, _output); + _output.Flush(); + var bytes = _writeBuffer.GetBuffer(); + var length = (int) _writeBuffer.Length; + if (length > _fileStreamBufferLength) + { + var oldOutput = _fileOutput; + + _fileOutput = new FileStream( + _path, + FileMode.Append, + FileSystemRights.AppendData, + FileShare.ReadWrite, + length, + FileOptions.None); + _fileStreamBufferLength = length; + + oldOutput.Dispose(); + } + + if (_fileSizeLimitBytes != null) + { + try + { + if (_fileOutput.Length >= _fileSizeLimitBytes.Value) + return false; + } + catch (FileNotFoundException) { } // Cheaper and more reliable than checking existence + } + + _fileOutput.Write(bytes, 0, length); + _fileOutput.Flush(); + return true; + } + catch + { + // Make sure there's no leftover cruft in there. + _output.Flush(); + throw; + } + finally + { + _writeBuffer.Position = 0; + _writeBuffer.SetLength(0); + } + } + } + + /// + /// Emit the provided log event to the sink. + /// + /// The log event to write. + public void Emit(LogEvent logEvent) + { + ((IFileSink)this).EmitOrOverflow(logEvent); + } + + /// + public void Dispose() + { + lock (_syncRoot) + { + _fileOutput.Dispose(); + } + } + + /// + public void FlushToDisk() + { + lock (_syncRoot) + { + _output.Flush(); + _fileOutput.Flush(true); + } + } + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs new file mode 100644 index 0000000000..96e95e45fd --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/SharedFileSink.OSMutex.cs @@ -0,0 +1,172 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#if OS_MUTEX + +using System; +using System.IO; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting; +using System.Threading; +using Datadog.Trace.Vendors.Serilog.Debugging; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + /// + /// Write log events to a disk file. + /// + internal sealed class SharedFileSink : IFileSink, IDisposable + { + readonly TextWriter _output; + readonly FileStream _underlyingStream; + readonly ITextFormatter _textFormatter; + readonly long? _fileSizeLimitBytes; + readonly object _syncRoot = new object(); + + const string MutexNameSuffix = ".serilog"; + const int MutexWaitTimeout = 10000; + readonly Mutex _mutex; + + /// Construct a . + /// Path to the file. + /// Formatter used to convert log events to text. + /// The approximate maximum size, in bytes, to which a log file will be allowed to grow. + /// For unrestricted growth, pass null. The default is 1 GB. To avoid writing partial events, the last event within the limit + /// will be written in full even if it exceeds the limit. + /// Character encoding used to write the text file. The default is UTF-8 without BOM. + /// Configuration object allowing method chaining. + /// The file will be written using the UTF-8 character set. + /// + public SharedFileSink(string path, ITextFormatter textFormatter, long? fileSizeLimitBytes, Encoding encoding = null) + { + if (path == null) throw new ArgumentNullException(nameof(path)); + if (textFormatter == null) throw new ArgumentNullException(nameof(textFormatter)); + if (fileSizeLimitBytes.HasValue && fileSizeLimitBytes < 0) + throw new ArgumentException("Negative value provided; file size limit must be non-negative"); + + _textFormatter = textFormatter; + _fileSizeLimitBytes = fileSizeLimitBytes; + + var directory = Path.GetDirectoryName(path); + if (!string.IsNullOrWhiteSpace(directory) && !Directory.Exists(directory)) + { + Directory.CreateDirectory(directory); + } + + var mutexName = Path.GetFullPath(path).Replace(Path.DirectorySeparatorChar, ':') + MutexNameSuffix; + _mutex = new Mutex(false, mutexName); + _underlyingStream = System.IO.File.Open(path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite); + _output = new StreamWriter(_underlyingStream, encoding ?? new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + bool IFileSink.EmitOrOverflow(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + lock (_syncRoot) + { + if (!TryAcquireMutex()) + return true; // We didn't overflow, but, roll-on-size should not be attempted + + try + { + _underlyingStream.Seek(0, SeekOrigin.End); + if (_fileSizeLimitBytes != null) + { + if (_underlyingStream.Length >= _fileSizeLimitBytes.Value) + return false; + } + + _textFormatter.Format(logEvent, _output); + _output.Flush(); + _underlyingStream.Flush(); + return true; + } + finally + { + ReleaseMutex(); + } + } + } + + /// + /// Emit the provided log event to the sink. + /// + /// The log event to write. + public void Emit(LogEvent logEvent) + { + ((IFileSink)this).EmitOrOverflow(logEvent); + } + + /// + public void Dispose() + { + lock (_syncRoot) + { + _output.Dispose(); + _mutex.Dispose(); + } + } + + /// + public void FlushToDisk() + { + lock (_syncRoot) + { + if (!TryAcquireMutex()) + return; + + try + { + _underlyingStream.Flush(true); + } + finally + { + ReleaseMutex(); + } + } + } + + bool TryAcquireMutex() + { + try + { + if (!_mutex.WaitOne(MutexWaitTimeout)) + { + SelfLog.WriteLine("Shared file mutex could not be acquired within {0} ms", MutexWaitTimeout); + return false; + } + } + catch (AbandonedMutexException) + { + SelfLog.WriteLine("Inherited shared file mutex after abandonment by another process"); + } + + return true; + } + + void ReleaseMutex() + { + _mutex.ReleaseMutex(); + } + } +} + +#endif diff --git a/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs new file mode 100644 index 0000000000..b4f6f7e444 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog.Sinks.File/Sinks/File/WriteCountingStream.cs @@ -0,0 +1,80 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Sinks.File +{ + sealed class WriteCountingStream : Stream + { + readonly Stream _stream; + long _countedLength; + + public WriteCountingStream(Stream stream) + { + if (stream == null) throw new ArgumentNullException(nameof(stream)); + _stream = stream; + _countedLength = stream.Length; + } + + public long CountedLength => _countedLength; + + protected override void Dispose(bool disposing) + { + if (disposing) + _stream.Dispose(); + + base.Dispose(disposing); + } + + public override void Write(byte[] buffer, int offset, int count) + { + _stream.Write(buffer, offset, count); + _countedLength += count; + } + + public override void Flush() => _stream.Flush(); + public override bool CanRead => false; + public override bool CanSeek => _stream.CanSeek; + public override bool CanWrite => true; + public override long Length => _stream.Length; + + + public override long Position + { + get { return _stream.Position; } + set { throw new NotSupportedException(); } + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new InvalidOperationException($"Seek operations are not available through `{nameof(WriteCountingStream)}`."); + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Capturing/DepthLimiter.cs b/src/Datadog.Trace/Vendors/Serilog/Capturing/DepthLimiter.cs new file mode 100644 index 0000000000..e5a761da4c --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Capturing/DepthLimiter.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; + +namespace Datadog.Trace.Vendors.Serilog.Capturing +{ + partial class PropertyValueConverter + { + class DepthLimiter : ILogEventPropertyValueFactory + { + [ThreadStatic] + static int _currentDepth; + + readonly int _maximumDestructuringDepth; + readonly PropertyValueConverter _propertyValueConverter; + + public DepthLimiter(int maximumDepth, PropertyValueConverter propertyValueConverter) + { + _maximumDestructuringDepth = maximumDepth; + _propertyValueConverter = propertyValueConverter; + } + + public void SetCurrentDepth(int depth) + { + _currentDepth = depth; + } + + public LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructuring) + { + var storedDepth = _currentDepth; + + var result = DefaultIfMaximumDepth(storedDepth) ?? + _propertyValueConverter.CreatePropertyValue(value, destructuring, storedDepth + 1); + + _currentDepth = storedDepth; + + return result; + } + + LogEventPropertyValue ILogEventPropertyValueFactory.CreatePropertyValue(object value, bool destructureObjects) + { + var storedDepth = _currentDepth; + + var result = DefaultIfMaximumDepth(storedDepth) ?? + _propertyValueConverter.CreatePropertyValue(value, destructureObjects, storedDepth + 1); + + _currentDepth = storedDepth; + + return result; + } + + LogEventPropertyValue DefaultIfMaximumDepth(int depth) + { + if (depth == _maximumDestructuringDepth) + { + SelfLog.WriteLine("Maximum destructuring depth reached."); + return new ScalarValue(null); + } + + return null; + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Capturing/GetablePropertyFinder.cs b/src/Datadog.Trace/Vendors/Serilog/Capturing/GetablePropertyFinder.cs new file mode 100644 index 0000000000..fdd3dba168 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Capturing/GetablePropertyFinder.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Datadog.Trace.Vendors.Serilog.Capturing +{ + static class GetablePropertyFinder + { + internal static IEnumerable GetPropertiesRecursive(this Type type) + { + var seenNames = new HashSet(); + + var currentTypeInfo = type.GetTypeInfo(); + + while (currentTypeInfo.AsType() != typeof(object)) + { + var unseenProperties = currentTypeInfo.DeclaredProperties.Where(p => p.CanRead && + p.GetMethod.IsPublic && !p.GetMethod.IsStatic && + (p.Name != "Item" || p.GetIndexParameters().Length == 0) && !seenNames.Contains(p.Name)); + + foreach (var propertyInfo in unseenProperties) + { + seenNames.Add(propertyInfo.Name); + yield return propertyInfo; + } + + var baseType = currentTypeInfo.BaseType; + if(baseType == null) + { + yield break; + } + + currentTypeInfo = baseType.GetTypeInfo(); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Capturing/MessageTemplateProcessor.cs b/src/Datadog.Trace/Vendors/Serilog/Capturing/MessageTemplateProcessor.cs new file mode 100644 index 0000000000..3dfe89a8d5 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Capturing/MessageTemplateProcessor.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Pipeline; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; + +namespace Datadog.Trace.Vendors.Serilog.Capturing +{ + class MessageTemplateProcessor : ILogEventPropertyFactory + { + readonly MessageTemplateCache _parser = new MessageTemplateCache(new MessageTemplateParser()); + readonly PropertyBinder _propertyBinder; + readonly PropertyValueConverter _propertyValueConverter; + + public MessageTemplateProcessor(PropertyValueConverter propertyValueConverter) + { + _propertyValueConverter = propertyValueConverter; + _propertyBinder = new PropertyBinder(_propertyValueConverter); + } + + public void Process(string messageTemplate, object[] messageTemplateParameters, out MessageTemplate parsedTemplate, out IEnumerable properties) + { + parsedTemplate = _parser.Parse(messageTemplate); + properties = _propertyBinder.ConstructProperties(parsedTemplate, messageTemplateParameters); + } + + public LogEventProperty CreateProperty(string name, object value, bool destructureObjects = false) + { + return _propertyValueConverter.CreateProperty(name, value, destructureObjects); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyBinder.cs b/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyBinder.cs new file mode 100644 index 0000000000..5a2edb09bf --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyBinder.cs @@ -0,0 +1,136 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; + +namespace Datadog.Trace.Vendors.Serilog.Capturing +{ + // Performance relevant - on the hot path when creating log events from existing templates. + class PropertyBinder + { + readonly PropertyValueConverter _valueConverter; + + static readonly LogEventProperty[] NoProperties = new LogEventProperty[0]; + + public PropertyBinder(PropertyValueConverter valueConverter) + { + _valueConverter = valueConverter; + } + + /// + /// Create properties based on an ordered list of provided values. + /// + /// The template that the parameters apply to. + /// Objects corresponding to the properties + /// represented in the message template. + /// A list of properties; if the template is malformed then + /// this will be empty. + public IEnumerable ConstructProperties(MessageTemplate messageTemplate, object[] messageTemplateParameters) + { + if (messageTemplateParameters == null || messageTemplateParameters.Length == 0) + { + if (messageTemplate.NamedProperties != null || messageTemplate.PositionalProperties != null) + SelfLog.WriteLine("Required properties not provided for: {0}", messageTemplate); + + return NoProperties; + } + + if (messageTemplate.PositionalProperties != null) + return ConstructPositionalProperties(messageTemplate, messageTemplateParameters); + + return ConstructNamedProperties(messageTemplate, messageTemplateParameters); + } + + IEnumerable ConstructPositionalProperties(MessageTemplate template, object[] messageTemplateParameters) + { + var positionalProperties = template.PositionalProperties; + + if (positionalProperties.Length != messageTemplateParameters.Length) + SelfLog.WriteLine("Positional property count does not match parameter count: {0}", template); + + var result = new LogEventProperty[messageTemplateParameters.Length]; + foreach (var property in positionalProperties) + { + int position; + if (property.TryGetPositionalValue(out position)) + { + if (position < 0 || position >= messageTemplateParameters.Length) + SelfLog.WriteLine("Unassigned positional value {0} in: {1}", position, template); + else + result[position] = ConstructProperty(property, messageTemplateParameters[position]); + } + } + + var next = 0; + for (var i = 0; i < result.Length; ++i) + { + if (result[i] != null) + { + result[next] = result[i]; + ++next; + } + } + + if (next != result.Length) + Array.Resize(ref result, next); + + return result; + } + + IEnumerable ConstructNamedProperties(MessageTemplate template, object[] messageTemplateParameters) + { + var namedProperties = template.NamedProperties; + if (namedProperties == null) + return Enumerable.Empty(); + + var matchedRun = namedProperties.Length; + if (namedProperties.Length != messageTemplateParameters.Length) + { + matchedRun = Math.Min(namedProperties.Length, messageTemplateParameters.Length); + SelfLog.WriteLine("Named property count does not match parameter count: {0}", template); + } + + var result = new LogEventProperty[messageTemplateParameters.Length]; + for (var i = 0; i < matchedRun; ++i) + { + var property = template.NamedProperties[i]; + var value = messageTemplateParameters[i]; + result[i] = ConstructProperty(property, value); + } + + for (var i = matchedRun; i < messageTemplateParameters.Length; ++i) + { + var value = _valueConverter.CreatePropertyValue(messageTemplateParameters[i]); + result[i] = new LogEventProperty("__" + i, value); + } + return result; + } + + LogEventProperty ConstructProperty(PropertyToken propertyToken, object value) + { + return new LogEventProperty( + propertyToken.PropertyName, + _valueConverter.CreatePropertyValue(value, propertyToken.Destructuring)); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyValueConverter.cs b/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyValueConverter.cs new file mode 100644 index 0000000000..ff53770804 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Capturing/PropertyValueConverter.cs @@ -0,0 +1,378 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; +using Datadog.Trace.Vendors.Serilog.Policies; +using System.Runtime.CompilerServices; + +namespace Datadog.Trace.Vendors.Serilog.Capturing +{ + // Values in Serilog are simplified down into a lowest-common-denominator internal + // type system so that there is a better chance of code written with one sink in + // mind working correctly with any other. This technique also makes the programmer + // writing a log event (roughly) in control of the cost of recording that event. + partial class PropertyValueConverter : ILogEventPropertyFactory, ILogEventPropertyValueFactory + { + static readonly HashSet BuiltInScalarTypes = new HashSet + { + typeof(bool), + typeof(char), + typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint), + typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(decimal), + typeof(string), + typeof(DateTime), typeof(DateTimeOffset), typeof(TimeSpan), + typeof(Guid), typeof(Uri) + }; + + readonly IDestructuringPolicy[] _destructuringPolicies; + readonly IScalarConversionPolicy[] _scalarConversionPolicies; + readonly DepthLimiter _depthLimiter; + readonly int _maximumStringLength; + readonly int _maximumCollectionCount; + readonly bool _propagateExceptions; + + public PropertyValueConverter( + int maximumDestructuringDepth, + int maximumStringLength, + int maximumCollectionCount, + IEnumerable additionalScalarTypes, + IEnumerable additionalDestructuringPolicies, + bool propagateExceptions) + { + if (additionalScalarTypes == null) throw new ArgumentNullException(nameof(additionalScalarTypes)); + if (additionalDestructuringPolicies == null) throw new ArgumentNullException(nameof(additionalDestructuringPolicies)); + if (maximumDestructuringDepth < 0) throw new ArgumentOutOfRangeException(nameof(maximumDestructuringDepth)); + if (maximumStringLength < 2) throw new ArgumentOutOfRangeException(nameof(maximumStringLength)); + if (maximumCollectionCount < 1) throw new ArgumentOutOfRangeException(nameof(maximumCollectionCount)); + + _propagateExceptions = propagateExceptions; + _maximumStringLength = maximumStringLength; + _maximumCollectionCount = maximumCollectionCount; + + _scalarConversionPolicies = new IScalarConversionPolicy[] + { + new SimpleScalarConversionPolicy(BuiltInScalarTypes.Concat(additionalScalarTypes)), + new EnumScalarConversionPolicy(), + new ByteArrayScalarConversionPolicy() + }; + + _destructuringPolicies = additionalDestructuringPolicies + .Concat(new IDestructuringPolicy [] + { + new DelegateDestructuringPolicy(), + new ReflectionTypesScalarDestructuringPolicy() + }) + .ToArray(); + + _depthLimiter = new DepthLimiter(maximumDestructuringDepth, this); + } + + public LogEventProperty CreateProperty(string name, object value, bool destructureObjects = false) + { + return new LogEventProperty(name, CreatePropertyValue(value, destructureObjects)); + } + + public LogEventPropertyValue CreatePropertyValue(object value, bool destructureObjects = false) + { + return CreatePropertyValue(value, destructureObjects, 1); + } + + public LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructuring) + { + try + { + return CreatePropertyValue(value, destructuring, 1); + } + catch (Exception ex) + { + SelfLog.WriteLine("Exception caught while converting property value: {0}", ex); + + if (_propagateExceptions) + throw; + + return new ScalarValue("Capturing the property value threw an exception: " + ex.GetType().Name); + } + } + + LogEventPropertyValue CreatePropertyValue(object value, bool destructureObjects, int depth) + { + return CreatePropertyValue( + value, + destructureObjects ? + Destructuring.Destructure : + Destructuring.Default, + depth); + } + + LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructuring, int depth) + { + if (value == null) + return new ScalarValue(null); + + if (destructuring == Destructuring.Stringify) + { + return Stringify(value); + } + + var valueType = value.GetType(); + _depthLimiter.SetCurrentDepth(depth); + + if (destructuring == Destructuring.Destructure) + { + if (value is string stringValue) + { + value = TruncateIfNecessary(stringValue); + } + } + + foreach (var scalarConversionPolicy in _scalarConversionPolicies) + { + if (scalarConversionPolicy.TryConvertToScalar(value, out var converted)) + return converted; + } + + if (destructuring == Destructuring.Destructure) + { + foreach (var destructuringPolicy in _destructuringPolicies) + { + if (destructuringPolicy.TryDestructure(value, _depthLimiter, out var result)) + return result; + } + } + + if (TryConvertEnumerable(value, destructuring, valueType, out var enumerableResult)) + return enumerableResult; + + if (TryConvertValueTuple(value, destructuring, valueType, out var tupleResult)) + return tupleResult; + + if (TryConvertCompilerGeneratedType(value, destructuring, valueType, out var compilerGeneratedResult)) + return compilerGeneratedResult; + + return new ScalarValue(value.ToString()); + } + + bool TryConvertEnumerable(object value, Destructuring destructuring, Type valueType, out LogEventPropertyValue result) + { + if (value is IEnumerable enumerable) + { + // Only dictionaries with 'scalar' keys are permitted, as + // more complex keys may not serialize to unique values for + // representation in sinks. This check strengthens the expectation + // that resulting dictionary is representable in JSON as well + // as richer formats (e.g. XML, .NET type-aware...). + // Only actual dictionaries are supported, as arbitrary types + // can implement multiple IDictionary interfaces and thus introduce + // multiple different interpretations. + if (TryGetDictionary(value, valueType, out var dictionary)) + { + result = new DictionaryValue(MapToDictionaryElements(dictionary, destructuring)); + return true; + + IEnumerable> MapToDictionaryElements(IDictionary dictionaryEntries, Destructuring destructure) + { + var count = 0; + foreach (DictionaryEntry entry in dictionaryEntries) + { + if (++count > _maximumCollectionCount) + { + yield break; + } + + var pair = new KeyValuePair( + (ScalarValue)_depthLimiter.CreatePropertyValue(entry.Key, destructure), + _depthLimiter.CreatePropertyValue(entry.Value, destructure)); + + if (pair.Key.Value != null) + yield return pair; + } + } + } + + result = new SequenceValue(MapToSequenceElements(enumerable, destructuring)); + return true; + + IEnumerable MapToSequenceElements(IEnumerable sequence, Destructuring destructure) + { + var count = 0; + foreach (var element in sequence) + { + if (++count > _maximumCollectionCount) + { + yield break; + } + + yield return _depthLimiter.CreatePropertyValue(element, destructure); + } + } + } + + result = null; + return false; + } + + bool TryConvertValueTuple(object value, Destructuring destructuring, Type valueType, out LogEventPropertyValue result) + { + if (!(value is IStructuralEquatable && valueType.IsConstructedGenericType)) + { + result = null; + return false; + } + + var definition = valueType.GetGenericTypeDefinition(); + + // Ignore the 8+ value case for now. +#if VALUETUPLE + if (definition == typeof(ValueTuple<>) || definition == typeof(ValueTuple<,>) || + definition == typeof(ValueTuple<,,>) || definition == typeof(ValueTuple<,,,>) || + definition == typeof(ValueTuple<,,,,>) || definition == typeof(ValueTuple<,,,,,>) || + definition == typeof(ValueTuple<,,,,,,>)) +#else + // ReSharper disable once PossibleNullReferenceException + var defn = definition.FullName; + if (defn == "System.ValueTuple`1" || defn == "System.ValueTuple`2" || + defn == "System.ValueTuple`3" || defn == "System.ValueTuple`4" || + defn == "System.ValueTuple`5" || defn == "System.ValueTuple`6" || + defn == "System.ValueTuple`7") +#endif + { + var elements = new List(); + foreach (var field in valueType.GetTypeInfo().DeclaredFields) + { + if (field.IsPublic && !field.IsStatic) + { + var fieldValue = field.GetValue(value); + var propertyValue = _depthLimiter.CreatePropertyValue(fieldValue, destructuring); + elements.Add(propertyValue); + } + } + + result = new SequenceValue(elements); + return true; + } + + result = null; + return false; + } + + bool TryConvertCompilerGeneratedType(object value, Destructuring destructuring, Type valueType, out LogEventPropertyValue result) + { + if (destructuring == Destructuring.Destructure) + { + var typeTag = valueType.Name; + if (typeTag.Length <= 0 || IsCompilerGeneratedType(valueType)) + { + typeTag = null; + } + + result = new StructureValue(GetProperties(value), typeTag); + return true; + } + + result = null; + return false; + } + + LogEventPropertyValue Stringify(object value) + { + var stringified = value.ToString(); + var truncated = TruncateIfNecessary(stringified); + return new ScalarValue(truncated); + } + + string TruncateIfNecessary(string text) + { + if (text.Length > _maximumStringLength) + { + return text.Substring(0, _maximumStringLength - 1) + "…"; + } + + return text; + } + + bool TryGetDictionary(object value, Type valueType, out IDictionary dictionary) + { + if (valueType.IsConstructedGenericType && + valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>) && + IsValidDictionaryKeyType(valueType.GenericTypeArguments[0])) + { + dictionary = (IDictionary)value; + return true; + } + + dictionary = null; + return false; + } + + bool IsValidDictionaryKeyType(Type valueType) + { + return BuiltInScalarTypes.Contains(valueType) || + valueType.GetTypeInfo().IsEnum; + } + + IEnumerable GetProperties(object value) + { + foreach (var prop in value.GetType().GetPropertiesRecursive()) + { + object propValue; + try + { + propValue = prop.GetValue(value); + } + catch (TargetParameterCountException) + { + // These properties would ideally be ignored; since they never produce values they're not + // of concern to auditing and exceptions can be suppressed. + SelfLog.WriteLine("The property accessor {0} is a non-default indexer", prop); + continue; + } + catch (TargetInvocationException ex) + { + SelfLog.WriteLine("The property accessor {0} threw exception: {1}", prop, ex); + + if (_propagateExceptions) + throw; + + propValue = "The property accessor threw an exception: " + ex.InnerException?.GetType().Name; + } + yield return new LogEventProperty(prop.Name, _depthLimiter.CreatePropertyValue(propValue, Destructuring.Destructure)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static bool IsCompilerGeneratedType(Type type) + { + var typeInfo = type.GetTypeInfo(); + var typeName = type.Name; + + //C# Anonymous types always start with "<>" and VB's start with "VB$" + return typeInfo.IsGenericType && typeInfo.IsSealed && typeInfo.IsNotPublic && type.Namespace == null + && (typeName[0] == '<' + || (typeName.Length > 2 && typeName[0] == 'V' && typeName[1] == 'B' && typeName[2] == '$')); + } + } +} + diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/ILoggerSettings.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/ILoggerSettings.cs new file mode 100644 index 0000000000..1a837529f0 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/ILoggerSettings.cs @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Implemented on types that apply settings to a logger configuration. + /// + internal interface ILoggerSettings + { + /// + /// Apply the settings to the logger configuration. + /// + /// The logger configuration to apply settings to. + void Configure(LoggerConfiguration loggerConfiguration); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerAuditSinkConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerAuditSinkConfiguration.cs new file mode 100644 index 0000000000..98fc850d0c --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerAuditSinkConfiguration.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls audit sink configuration. + /// + internal class LoggerAuditSinkConfiguration + { + readonly LoggerSinkConfiguration _sinkConfiguration; + + internal LoggerAuditSinkConfiguration(LoggerConfiguration loggerConfiguration, Action addSink, Action applyInheritedConfiguration) + { + _sinkConfiguration = new LoggerSinkConfiguration(loggerConfiguration, addSink, applyInheritedConfiguration); + } + + /// + /// Audit log events to the specified . + /// + /// The sink. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Sink( + ILogEventSink logEventSink, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + // ReSharper disable once MethodOverloadWithOptionalParameter + LoggingLevelSwitch levelSwitch = null) + { + return _sinkConfiguration.Sink(logEventSink, restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Audit log events to the specified . + /// + /// The sink. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Sink( + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + where TSink : ILogEventSink, new() + { + return _sinkConfiguration.Sink(restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Audit log events to a sub-logger, where further processing may occur. Events through + /// the sub-logger will be constrained by filters and enriched by enrichers that are + /// active in the parent. A sub-logger cannot be used to log at a more verbose level, but + /// a less verbose level is possible. + /// + /// An action that configures the sub-logger. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Logger( + Action configureLogger, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + { + return _sinkConfiguration.Logger(configureLogger, restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Audit log events to a sub-logger, where further processing may occur. Events through + /// the sub-logger will be constrained by filters and enriched by enrichers that are + /// active in the parent. A sub-logger cannot be used to log at a more verbose level, but + /// a less verbose level is possible. + /// + /// The sub-logger. This will not be shut down automatically when the + /// parent logger is disposed. + /// The minimum level for + /// events passed through the sink. + /// Configuration object allowing method chaining. + public LoggerConfiguration Logger( + ILogger logger, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum) + { + return _sinkConfiguration.Logger(logger, restrictedToMinimumLevel); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerDestructuringConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerDestructuringConfiguration.cs new file mode 100644 index 0000000000..38879dc85d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerDestructuringConfiguration.cs @@ -0,0 +1,198 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Policies; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls template parameter destructuring configuration. + /// + internal class LoggerDestructuringConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + readonly Action _addScalar; + readonly Action _addPolicy; + readonly Action _setMaximumDepth; + readonly Action _setMaximumStringLength; + readonly Action _setMaximumCollectionCount; + + internal LoggerDestructuringConfiguration( + LoggerConfiguration loggerConfiguration, + Action addScalar, + Action addPolicy, + Action setMaximumDepth, + Action setMaximumStringLength, + Action setMaximumCollectionCount) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + if (addScalar == null) throw new ArgumentNullException(nameof(addScalar)); + if (addPolicy == null) throw new ArgumentNullException(nameof(addPolicy)); + if (setMaximumDepth == null) throw new ArgumentNullException(nameof(setMaximumDepth)); + if (setMaximumStringLength == null) throw new ArgumentNullException(nameof(setMaximumStringLength)); + if (setMaximumCollectionCount == null) throw new ArgumentNullException(nameof(setMaximumCollectionCount)); + _loggerConfiguration = loggerConfiguration; + _addScalar = addScalar; + _addPolicy = addPolicy; + _setMaximumDepth = setMaximumDepth; + _setMaximumStringLength = setMaximumStringLength; + _setMaximumCollectionCount = setMaximumCollectionCount; + } + + /// + /// Treat objects of the specified type as scalar values, i.e., don't break + /// them down into properties event when destructuring complex types. + /// + /// Type to treat as scalar. + /// Configuration object allowing method chaining. + public LoggerConfiguration AsScalar(Type scalarType) + { + if (scalarType == null) throw new ArgumentNullException(nameof(scalarType)); + _addScalar(scalarType); + return _loggerConfiguration; + } + + /// + /// Treat objects of the specified type as scalar values, i.e., don't break + /// them down into properties event when destructuring complex types. + /// + /// Type to treat as scalar. + /// Configuration object allowing method chaining. + public LoggerConfiguration AsScalar() + { + return AsScalar(typeof(TScalar)); + } + + /// + /// When destructuring objects, transform instances with the provided policies. + /// + /// Policies to apply when destructuring. + /// Configuration object allowing method chaining. + // ReSharper disable once MemberCanBePrivate.Global + public LoggerConfiguration With(params IDestructuringPolicy[] destructuringPolicies) + { + if (destructuringPolicies == null) throw new ArgumentNullException(nameof(destructuringPolicies)); + foreach (var destructuringPolicy in destructuringPolicies) + { + if (destructuringPolicy == null) + throw new ArgumentException("Null policy is not allowed."); + _addPolicy(destructuringPolicy); + } + return _loggerConfiguration; + } + + /// + /// When destructuring objects, transform instances with the provided policy. + /// + /// Policy to apply when destructuring. + /// Configuration object allowing method chaining. + public LoggerConfiguration With() + where TDestructuringPolicy : IDestructuringPolicy, new() + { + return With(new TDestructuringPolicy()); + } + + /// + /// When destructuring objects, transform instances of the specified type with + /// the provided function. + /// + /// Function mapping instances of + /// to an alternative representation. + /// Type of values to transform. + /// Configuration object allowing method chaining. + /// + public LoggerConfiguration ByTransforming(Func transformation) + { + if (transformation == null) throw new ArgumentNullException(nameof(transformation)); + var policy = new ProjectedDestructuringPolicy(t => t == typeof(TValue), + o => transformation((TValue)o)); + return With(policy); + } + + /// + /// When destructuring objects, transform instances of the specified type with + /// the provided function, if the predicate returns true. Be careful to avoid any + /// intensive work in the predicate, as it can slow down the pipeline significantly. + /// + /// A predicate used to determine if the transform applies to + /// a specific type of value + /// Function mapping instances of + /// to an alternative representation. + /// Type of values to transform. + /// Configuration object allowing method chaining. + /// + public LoggerConfiguration ByTransformingWhere( + Func predicate, + Func transformation) + { + if (transformation == null) throw new ArgumentNullException(nameof(transformation)); + var policy = new ProjectedDestructuringPolicy(predicate, + o => transformation((TValue)o)); + return With(policy); + } + + /// + /// When destructuring objects, depth will be limited to 5 property traversals deep to + /// guard against ballooning space when recursive/cyclic structures are accidentally passed. To + /// increase this limit pass a higher value. + /// + /// The maximum depth to use. + /// Configuration object allowing method chaining. + /// + public LoggerConfiguration ToMaximumDepth(int maximumDestructuringDepth) + { + if (maximumDestructuringDepth < 0) throw new ArgumentOutOfRangeException(nameof(maximumDestructuringDepth)); + _setMaximumDepth(maximumDestructuringDepth); + return _loggerConfiguration; + } + + /// + /// When destructuring objects, string values can be restricted to specified length + /// thus avoiding bloating payload. Limit is applied to each value separately, + /// sum of length of strings can exceed limit. + /// + /// The maximum string length. + /// Configuration object allowing method chaining. + /// When passed length is less than 2 + public LoggerConfiguration ToMaximumStringLength(int maximumStringLength) + { + if (maximumStringLength < 2) throw new ArgumentOutOfRangeException(nameof(maximumStringLength), maximumStringLength, "Maximum string length must be at least two."); + _setMaximumStringLength(maximumStringLength); + return _loggerConfiguration; + } + + /// + /// When destructuring objects, collections be restricted to specified count + /// thus avoiding bloating payload. Limit is applied to each collection separately, + /// sum of length of collection can exceed limit. + /// Applies limit to all including dictionaries. + /// + /// Configuration object allowing method chaining. + /// When passed length is less than 1 + public LoggerConfiguration ToMaximumCollectionCount(int maximumCollectionCount) + { + if (maximumCollectionCount < 1) throw new ArgumentOutOfRangeException(nameof(maximumCollectionCount), maximumCollectionCount, "Maximum collection length must be at least one."); + _setMaximumCollectionCount(maximumCollectionCount); + return _loggerConfiguration; + } + } +} + diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerEnrichmentConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerEnrichmentConfiguration.cs new file mode 100644 index 0000000000..56a6743b4d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerEnrichmentConfiguration.cs @@ -0,0 +1,98 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Enrichers; +using Datadog.Trace.Vendors.Serilog.Enrichers; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls enrichment configuration. + /// + internal class LoggerEnrichmentConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + readonly Action _addEnricher; + + internal LoggerEnrichmentConfiguration( + LoggerConfiguration loggerConfiguration, + Action addEnricher) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + if (addEnricher == null) throw new ArgumentNullException(nameof(addEnricher)); + _loggerConfiguration = loggerConfiguration; + _addEnricher = addEnricher; + } + + /// + /// Specifies one or more enrichers that may add properties dynamically to + /// log events. + /// + /// Enrichers to apply to all events passing through + /// the logger. + /// Configuration object allowing method chaining. + public LoggerConfiguration With(params ILogEventEnricher[] enrichers) + { + if (enrichers == null) throw new ArgumentNullException(nameof(enrichers)); + foreach (var logEventEnricher in enrichers) + { + if (logEventEnricher == null) + throw new ArgumentException("Null enricher is not allowed."); + _addEnricher(logEventEnricher); + } + return _loggerConfiguration; + } + + /// + /// Specifies an enricher that may add properties dynamically to + /// log events. + /// + /// Enricher type to apply to all events passing through + /// the logger. + /// Configuration object allowing method chaining. + public LoggerConfiguration With() + where TEnricher : ILogEventEnricher, new() + { + return With(new TEnricher()); + } + + /// + /// Include the specified property value in all events logged to the logger. + /// + /// The name of the property to add. + /// The property value to add. + /// If true, objects of unknown type will be logged as structures; otherwise they will be converted using . + /// Configuration object allowing method chaining. + public LoggerConfiguration WithProperty(string name, object value, bool destructureObjects = false) + { + return With(new PropertyEnricher(name, value, destructureObjects)); + } + + /// + /// Enrich log events with properties from . + /// + /// Configuration object allowing method chaining. + /// + public LoggerConfiguration FromLogContext() + { + return With(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerFilterConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerFilterConfiguration.cs new file mode 100644 index 0000000000..b80ebc16f2 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerFilterConfiguration.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Filters; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls filter configuration. + /// + internal class LoggerFilterConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + readonly Action _addFilter; + + internal LoggerFilterConfiguration( + LoggerConfiguration loggerConfiguration, + Action addFilter) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + if (addFilter == null) throw new ArgumentNullException(nameof(addFilter)); + _loggerConfiguration = loggerConfiguration; + _addFilter = addFilter; + } + + + /// + /// Filter out log events from the stream based on the provided filter. + /// + /// The filters to apply. + /// Configuration object allowing method chaining. + public LoggerConfiguration With(params ILogEventFilter[] filters) + { + if (filters == null) throw new ArgumentNullException(nameof(filters)); + foreach (var logEventFilter in filters) + { + if (logEventFilter == null) + throw new ArgumentException("Null filter is not allowed."); + _addFilter(logEventFilter); + } + return _loggerConfiguration; + } + + /// + /// Filter out log events from the stream based on the provided filter. + /// + /// The filters to apply. + /// Configuration object allowing method chaining. + public LoggerConfiguration With() + where TFilter : ILogEventFilter, new() + { + return With(new TFilter()); + } + + /// + /// Filter out log events that match a predicate. + /// + /// Function that returns true when an event + /// should be excluded (silenced). + /// Configuration object allowing method chaining. + public LoggerConfiguration ByExcluding(Func exclusionPredicate) + { + return With(new DelegateFilter(logEvent => !exclusionPredicate(logEvent))); + } + + /// + /// Filter log events to include only those that match a predicate. + /// + /// Function that returns true when an event + /// should be included (emitted). + /// Configuration object allowing method chaining. + public LoggerConfiguration ByIncludingOnly(Func inclusionPredicate) + { + return With(new DelegateFilter(inclusionPredicate)); + } + } +} + diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerMinimumLevelConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerMinimumLevelConfiguration.cs new file mode 100644 index 0000000000..3e91b11545 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerMinimumLevelConfiguration.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls sink configuration. + /// + internal class LoggerMinimumLevelConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + readonly Action _setMinimum; + readonly Action _setLevelSwitch; + readonly Action _addOverride; + + internal LoggerMinimumLevelConfiguration(LoggerConfiguration loggerConfiguration, Action setMinimum, + Action setLevelSwitch, Action addOverride) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + if (setMinimum == null) throw new ArgumentNullException(nameof(setMinimum)); + if (addOverride == null) throw new ArgumentNullException(nameof(addOverride)); + _loggerConfiguration = loggerConfiguration; + _setMinimum = setMinimum; + _setLevelSwitch = setLevelSwitch; + _addOverride = addOverride; + } + + /// + /// Sets the minimum level at which events will be passed to sinks. + /// + /// The minimum level to set. + /// Configuration object allowing method chaining. + public LoggerConfiguration Is(LogEventLevel minimumLevel) + { + _setMinimum(minimumLevel); + return _loggerConfiguration; + } + + /// + /// Sets the minimum level to be dynamically controlled by the provided switch. + /// + /// The switch. + /// Configuration object allowing method chaining. + // ReSharper disable once UnusedMethodReturnValue.Global + public LoggerConfiguration ControlledBy(LoggingLevelSwitch levelSwitch) + { + if (levelSwitch == null) throw new ArgumentNullException(nameof(levelSwitch)); + _setLevelSwitch(levelSwitch); + return _loggerConfiguration; + } + + /// + /// Anything and everything you might want to know about + /// a running block of code. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Verbose() + { + return Is(LogEventLevel.Verbose); + } + + /// + /// Internal system events that aren't necessarily + /// observable from the outside. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Debug() + { + return Is(LogEventLevel.Debug); + } + + /// + /// The lifeblood of operational intelligence - things + /// happen. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Information() + { + return Is(LogEventLevel.Information); + } + + /// + /// Service is degraded or endangered. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Warning() + { + return Is(LogEventLevel.Warning); + } + + /// + /// Functionality is unavailable, invariants are broken + /// or data is lost. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Error() + { + return Is(LogEventLevel.Error); + } + + /// + /// If you have a pager, it goes off when one of these + /// occurs. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Fatal() + { + return Is(LogEventLevel.Fatal); + } + + /// + /// Override the minimum level for events from a specific namespace or type name. + /// + /// The (partial) namespace or type name to set the override for. + /// The switch controlling loggers for matching sources. + /// Configuration object allowing method chaining. + public LoggerConfiguration Override(string source, LoggingLevelSwitch levelSwitch) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + if (levelSwitch == null) throw new ArgumentNullException(nameof(levelSwitch)); + + var trimmed = source.Trim(); + if (trimmed.Length == 0) + throw new ArgumentException("A source name must be provided.", nameof(source)); + + _addOverride(trimmed, levelSwitch); + return _loggerConfiguration; + } + + /// + /// Override the minimum level for events from a specific namespace or type name. + /// + /// The (partial) namespace or type name to set the override for. + /// The minimum level applied to loggers for matching sources. + /// Configuration object allowing method chaining. + public LoggerConfiguration Override(string source, LogEventLevel minimumLevel) + { + return Override(source, new LoggingLevelSwitch(minimumLevel)); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSettingsConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSettingsConfiguration.cs new file mode 100644 index 0000000000..af8918a0b9 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSettingsConfiguration.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Settings.KeyValuePairs; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Allows additional setting sources to drive the logger configuration. + /// + internal class LoggerSettingsConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + + internal LoggerSettingsConfiguration(LoggerConfiguration loggerConfiguration) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + _loggerConfiguration = loggerConfiguration; + } + + /// + /// Apply external settings to the logger configuration. + /// + /// Configuration object allowing method chaining. + public LoggerConfiguration Settings(ILoggerSettings settings) + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + + settings.Configure(_loggerConfiguration); + + return _loggerConfiguration; + } + + /// + /// Apply settings specified in the Serilog key-value setting format to the logger configuration. + /// + /// A list of key-value pairs describing logger settings. + /// Configuration object allowing method chaining. + /// In case of duplicate keys, the last value for the key is kept and the previous ones are ignored. + public LoggerConfiguration KeyValuePairs(IEnumerable> settings) + { + if (settings == null) throw new ArgumentNullException(nameof(settings)); + var uniqueSettings = new Dictionary(); + foreach (var kvp in settings) + { + uniqueSettings[kvp.Key] = kvp.Value; + } + return KeyValuePairs(uniqueSettings); + } + + LoggerConfiguration KeyValuePairs(IReadOnlyDictionary settings) + { + return Settings(new KeyValuePairSettings(settings)); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSinkConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSinkConfiguration.cs new file mode 100644 index 0000000000..61176e716c --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Configuration/LoggerSinkConfiguration.cs @@ -0,0 +1,247 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Sinks; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Configuration +{ + /// + /// Controls sink configuration. + /// + internal class LoggerSinkConfiguration + { + readonly LoggerConfiguration _loggerConfiguration; + readonly Action _addSink; + readonly Action _applyInheritedConfiguration; + + internal LoggerSinkConfiguration(LoggerConfiguration loggerConfiguration, Action addSink, Action applyInheritedConfiguration) + { + _loggerConfiguration = loggerConfiguration ?? throw new ArgumentNullException(nameof(loggerConfiguration)); + _addSink = addSink ?? throw new ArgumentNullException(nameof(addSink)); + _applyInheritedConfiguration = applyInheritedConfiguration ?? throw new ArgumentNullException(nameof(applyInheritedConfiguration)); + } + + /// + /// Write log events to the specified . + /// + /// The sink. + /// The minimum level for + /// events passed through the sink. + /// Configuration object allowing method chaining. + /// Provided for binary compatibility for earlier versions, + /// should be removed in 3.0. Not marked obsolete because warnings + /// would be syntactically annoying to avoid. + [EditorBrowsable(EditorBrowsableState.Never)] + public LoggerConfiguration Sink( + ILogEventSink logEventSink, + LogEventLevel restrictedToMinimumLevel) + { + return Sink(logEventSink, restrictedToMinimumLevel, null); + } + + /// + /// Write log events to the specified . + /// + /// The sink. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Sink( + ILogEventSink logEventSink, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + // ReSharper disable once MethodOverloadWithOptionalParameter + LoggingLevelSwitch levelSwitch = null) + { + var sink = logEventSink; + if (levelSwitch != null) + { + if (restrictedToMinimumLevel != LevelAlias.Minimum) + SelfLog.WriteLine("Sink {0} was configured with both a level switch and minimum level '{1}'; the minimum level will be ignored and the switch level used", sink, restrictedToMinimumLevel); + + sink = new RestrictedSink(sink, levelSwitch); + } + else if (restrictedToMinimumLevel > LevelAlias.Minimum) + { + sink = new RestrictedSink(sink, new LoggingLevelSwitch(restrictedToMinimumLevel)); + } + + _addSink(sink); + return _loggerConfiguration; + } + + /// + /// Write log events to the specified . + /// + /// The sink. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Sink( + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + where TSink : ILogEventSink, new() + { + return Sink(new TSink(), restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Write log events to a sub-logger, where further processing may occur. Events through + /// the sub-logger will be constrained by filters and enriched by enrichers that are + /// active in the parent. A sub-logger cannot be used to log at a more verbose level, but + /// a less verbose level is possible. + /// + /// An action that configures the sub-logger. + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public LoggerConfiguration Logger( + Action configureLogger, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + { + if (configureLogger == null) throw new ArgumentNullException(nameof(configureLogger)); + var lc = new LoggerConfiguration(); + + _applyInheritedConfiguration(lc); + configureLogger(lc); + + var subLogger = lc.CreateLogger(); + if (subLogger.HasOverrideMap) + { + SelfLog.WriteLine("Minimum level overrides are not supported on sub-loggers " + + "and may be removed completely in a future version."); + } + + var secondarySink = new SecondaryLoggerSink(subLogger, attemptDispose: true); + return Sink(secondarySink, restrictedToMinimumLevel, levelSwitch); + } + + /// + /// Write log events to a sub-logger, where further processing may occur. Events through + /// the sub-logger will be constrained by filters and enriched by enrichers that are + /// active in the parent. A sub-logger cannot be used to log at a more verbose level, but + /// a less verbose level is possible. + /// + /// The sub-logger. This will not be shut down automatically when the + /// parent logger is disposed. + /// The minimum level for + /// events passed through the sink. + /// Configuration object allowing method chaining. + public LoggerConfiguration Logger( + ILogger logger, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum) + { + if (logger == null) throw new ArgumentNullException(nameof(logger)); + + if (logger is Logger concreteLogger && concreteLogger.HasOverrideMap) + { + SelfLog.WriteLine("Minimum level overrides are not supported on sub-loggers " + + "and may be removed completely in a future version."); + } + + var secondarySink = new SecondaryLoggerSink(logger, attemptDispose: false); + return Sink(secondarySink, restrictedToMinimumLevel); + } + + /// + /// Helper method for wrapping sinks. + /// + /// The parent sink configuration. + /// A function that allows for wrapping s + /// added in . + /// An action that configures sinks to be wrapped in . + /// Configuration object allowing method chaining. + [Obsolete("Please use `LoggerConfiguration.Wrap(loggerSinkConfiguration, wrapSink, configureWrappedSink, restrictedToMinimumLevel, levelSwitch)` instead.")] + public static LoggerConfiguration Wrap( + LoggerSinkConfiguration loggerSinkConfiguration, + Func wrapSink, + Action configureWrappedSink) + { + return Wrap(loggerSinkConfiguration, wrapSink, configureWrappedSink, LogEventLevel.Verbose, null); + } + + /// + /// Helper method for wrapping sinks. + /// + /// The parent sink configuration. + /// A function that allows for wrapping s + /// added in . + /// An action that configures sinks to be wrapped in . + /// The minimum level for + /// events passed through the sink. Ignored when is specified. + /// A switch allowing the pass-through minimum level + /// to be changed at runtime. + /// Configuration object allowing method chaining. + public static LoggerConfiguration Wrap( + LoggerSinkConfiguration loggerSinkConfiguration, + Func wrapSink, + Action configureWrappedSink, + LogEventLevel restrictedToMinimumLevel, + LoggingLevelSwitch levelSwitch) + { + if (loggerSinkConfiguration == null) throw new ArgumentNullException(nameof(loggerSinkConfiguration)); + if (wrapSink == null) throw new ArgumentNullException(nameof(wrapSink)); + if (configureWrappedSink == null) throw new ArgumentNullException(nameof(configureWrappedSink)); + + var sinksToWrap = new List(); + + var capturingConfiguration = new LoggerConfiguration(); + var capturingLoggerSinkConfiguration = new LoggerSinkConfiguration( + capturingConfiguration, + sinksToWrap.Add, + loggerSinkConfiguration._applyInheritedConfiguration); + + // `WriteTo.Sink()` will return the capturing configuration; this ensures chained `WriteTo` gets back + // to the capturing sink configuration, enabling `WriteTo.X().WriteTo.Y()`. + capturingConfiguration.WriteTo = capturingLoggerSinkConfiguration; + + configureWrappedSink(capturingLoggerSinkConfiguration); + + if (sinksToWrap.Count == 0) + return loggerSinkConfiguration._loggerConfiguration; + + var enclosed = sinksToWrap.Count == 1 ? + sinksToWrap.Single() : + new SafeAggregateSink(sinksToWrap); + + var wrappedSink = wrapSink(enclosed); + + if (!(wrappedSink is IDisposable)) + { + SelfLog.WriteLine("Wrapping sink {0} does not implement IDisposable; to ensure " + + "wrapped sinks are properly flushed, wrappers should dispose " + + "their wrapped contents", wrappedSink); + } + + return loggerSinkConfiguration.Sink(wrappedSink, restrictedToMinimumLevel, levelSwitch); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Context/ImmutableStack.cs b/src/Datadog.Trace/Vendors/Serilog/Context/ImmutableStack.cs new file mode 100644 index 0000000000..7f3976e8f6 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Context/ImmutableStack.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; + +// General-purpose type; not all features are used here. +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable MemberCanBeProtected.Global + +namespace Datadog.Trace.Vendors.Serilog.Context +{ + class ImmutableStack : IEnumerable + { + readonly ImmutableStack _under; + readonly T _top; + + ImmutableStack() + { + } + + ImmutableStack(ImmutableStack under, T top) + { + if (under == null) throw new ArgumentNullException(nameof(under)); + _under = under; + Count = under.Count + 1; + _top = top; + } + + public IEnumerator GetEnumerator() + { + var next = this; + while (!next.IsEmpty) + { + yield return next.Top; + next = next._under; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public int Count { get; } + + public static ImmutableStack Empty { get; } = new ImmutableStack(); + + public bool IsEmpty => _under == null; + + public ImmutableStack Push(T t) => new ImmutableStack(this, t); + + public T Top => _top; + + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Context/LogContext.cs b/src/Datadog.Trace/Vendors/Serilog/Context/LogContext.cs new file mode 100644 index 0000000000..92e4774025 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Context/LogContext.cs @@ -0,0 +1,283 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +using System; +using System.ComponentModel; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Enrichers; +using Datadog.Trace.Vendors.Serilog.Events; + +#if ASYNCLOCAL +using System.Threading; +#elif REMOTING +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; +using System.Runtime.Remoting.Messaging; +#endif + +namespace Datadog.Trace.Vendors.Serilog.Context +{ + /// + /// Holds ambient properties that can be attached to log events. To + /// configure, use the method. + /// + /// + /// Configuration: + /// + /// var log = new LoggerConfiguration() + /// .Enrich.FromLogContext() + /// ... + /// + /// Usage: + /// + /// using (LogContext.PushProperty("MessageId", message.Id)) + /// { + /// Log.Information("The MessageId property will be attached to this event"); + /// } + /// + /// + /// The scope of the context is the current logical thread, using AsyncLocal + /// (and so is preserved across async/await calls). + internal static class LogContext + { +#if ASYNCLOCAL + static readonly AsyncLocal> Data = new AsyncLocal>(); +#elif REMOTING + static readonly string DataSlotName = typeof(LogContext).FullName + "@" + Guid.NewGuid(); +#else // DOTNET_51 + [ThreadStatic] + static ImmutableStack Data; +#endif + + /// + /// Push a property onto the context, returning an + /// that must later be used to remove the property, along with any others that + /// may have been pushed on top of it and not yet popped. The property must + /// be popped from the same thread/logical call context. + /// + /// The name of the property. + /// The value of the property. + /// A handle to later remove the property from the context. + /// If true, and the value is a non-primitive, non-array type, + /// then the value will be converted to a structure; otherwise, unknown types will + /// be converted to scalars, which are generally stored as strings. + /// A token that must be disposed, in order, to pop properties back off the stack. + public static IDisposable PushProperty(string name, object value, bool destructureObjects = false) + { + return Push(new PropertyEnricher(name, value, destructureObjects)); + } + + /// + /// Push an enricher onto the context, returning an + /// that must later be used to remove the property, along with any others that + /// may have been pushed on top of it and not yet popped. The property must + /// be popped from the same thread/logical call context. + /// + /// An enricher to push onto the log context + /// A token that must be disposed, in order, to pop properties back off the stack. + /// + public static IDisposable Push(ILogEventEnricher enricher) + { + if (enricher == null) throw new ArgumentNullException(nameof(enricher)); + + var stack = GetOrCreateEnricherStack(); + var bookmark = new ContextStackBookmark(stack); + + Enrichers = stack.Push(enricher); + + return bookmark; + } + + /// + /// Push multiple enrichers onto the context, returning an + /// that must later be used to remove the property, along with any others that + /// may have been pushed on top of it and not yet popped. The property must + /// be popped from the same thread/logical call context. + /// + /// . + /// Enrichers to push onto the log context + /// A token that must be disposed, in order, to pop properties back off the stack. + /// + public static IDisposable Push(params ILogEventEnricher[] enrichers) + { + if (enrichers == null) throw new ArgumentNullException(nameof(enrichers)); + + var stack = GetOrCreateEnricherStack(); + var bookmark = new ContextStackBookmark(stack); + + for (var i = 0; i < enrichers.Length; ++i) + stack = stack.Push(enrichers[i]); + + Enrichers = stack; + + return bookmark; + } + + /// + /// Push enrichers onto the log context. This method is obsolete, please + /// use instead. + /// + /// Enrichers to push onto the log context + /// A token that must be disposed, in order, to pop properties back off the stack. + /// + [Obsolete("Please use `LogContext.Push(properties)` instead.")] + [EditorBrowsable(EditorBrowsableState.Never)] + public static IDisposable PushProperties(params ILogEventEnricher[] properties) + { + return Push(properties); + } + + /// + /// Obtain an enricher that represents the current contents of the . This + /// can be pushed back onto the context in a different location/thread when required. + /// + /// An enricher that represents the current contents of the . + public static ILogEventEnricher Clone() + { + var stack = GetOrCreateEnricherStack(); + return new SafeAggregateEnricher(stack); + } + + /// + /// Remove all enrichers from the , returning an + /// that must later be used to restore enrichers that were on the stack before was called. + /// + /// A token that must be disposed, in order, to restore properties back to the stack. + public static IDisposable Suspend() + { + var stack = GetOrCreateEnricherStack(); + var bookmark = new ContextStackBookmark(stack); + + Enrichers = ImmutableStack.Empty; + + return bookmark; + } + + /// + /// Remove all enrichers from for the current async scope. + /// + public static void Reset() + { + if (Enrichers != null && Enrichers != ImmutableStack.Empty) + { + Enrichers = ImmutableStack.Empty; + } + } + + static ImmutableStack GetOrCreateEnricherStack() + { + var enrichers = Enrichers; + if (enrichers == null) + { + enrichers = ImmutableStack.Empty; + Enrichers = enrichers; + } + return enrichers; + } + + internal static void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + var enrichers = Enrichers; + if (enrichers == null || enrichers == ImmutableStack.Empty) + return; + + foreach (var enricher in enrichers) + { + enricher.Enrich(logEvent, propertyFactory); + } + } + + sealed class ContextStackBookmark : IDisposable + { + readonly ImmutableStack _bookmark; + + public ContextStackBookmark(ImmutableStack bookmark) + { + _bookmark = bookmark; + } + + public void Dispose() + { + Enrichers = _bookmark; + } + } + +#if ASYNCLOCAL + + static ImmutableStack Enrichers + { + get => Data.Value; + set => Data.Value = value; + } + +#elif REMOTING + + static ImmutableStack Enrichers + { + get + { + var objectHandle = CallContext.LogicalGetData(DataSlotName) as ObjectHandle; + + return objectHandle?.Unwrap() as ImmutableStack; + } + set + { + if (CallContext.LogicalGetData(DataSlotName) is IDisposable oldHandle) + { + oldHandle.Dispose(); + } + + CallContext.LogicalSetData(DataSlotName, new DisposableObjectHandle(value)); + } + } + + sealed class DisposableObjectHandle : ObjectHandle, IDisposable + { + static readonly ISponsor LifeTimeSponsor = new ClientSponsor(); + + public DisposableObjectHandle(object o) : base(o) + { + } + + public override object InitializeLifetimeService() + { + var lease = base.InitializeLifetimeService() as ILease; + lease?.Register(LifeTimeSponsor); + return lease; + } + + public void Dispose() + { + if (GetLifetimeService() is ILease lease) + { + lease.Unregister(LifeTimeSponsor); + } + } + } + +#else // DOTNET_51 + + static ImmutableStack Enrichers + { + get => Data; + set => Data = value; + } +#endif + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Constants.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Constants.cs new file mode 100644 index 0000000000..b3c6b14d35 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Constants.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Constants used in the core logging pipeline and associated types. + /// + internal static class Constants + { + /// + /// The name of the property included in the emitted log events + /// when ForContext<T>() and overloads are + /// applied. + /// + public const string SourceContextPropertyName = "SourceContext"; + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/EmptyEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/EmptyEnricher.cs new file mode 100644 index 0000000000..b55a417ee5 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/EmptyEnricher.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Enrichers +{ + class EmptyEnricher : ILogEventEnricher + { + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/FixedPropertyEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/FixedPropertyEnricher.cs new file mode 100644 index 0000000000..91a0017d5b --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/FixedPropertyEnricher.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Enrichers +{ + class FixedPropertyEnricher : ILogEventEnricher + { + readonly LogEventProperty _logEventProperty; + + public FixedPropertyEnricher(LogEventProperty logEventProperty) + { + _logEventProperty = logEventProperty ?? throw new ArgumentNullException(nameof(logEventProperty)); + } + + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + logEvent.AddPropertyIfAbsent(_logEventProperty); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/PropertyEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/PropertyEnricher.cs new file mode 100644 index 0000000000..4879221d60 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/PropertyEnricher.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Enrichers +{ + /// + /// Adds a new property encricher to the log event. + /// + internal class PropertyEnricher : ILogEventEnricher + { + readonly string _name; + readonly object _value; + readonly bool _destructureObjects; + + /// + /// Create a new property enricher. + /// + /// The name of the property. + /// The value of the property. + /// A handle to later remove the property from the context. + /// If true, and the value is a non-primitive, non-array type, + /// then the value will be converted to a structure; otherwise, unknown types will + /// be converted to scalars, which are generally stored as strings. + /// + /// + public PropertyEnricher(string name, object value, bool destructureObjects = false) + { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Property name must not be null or empty.", nameof(name)); + _name = name; + _value = value; + _destructureObjects = destructureObjects; + } + + /// + /// Enrich the log event. + /// + /// The log event to enrich. + /// Factory for creating new properties to add to the event. + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + if (propertyFactory == null) throw new ArgumentNullException(nameof(propertyFactory)); + var property = propertyFactory.CreateProperty(_name, _value, _destructureObjects); + logEvent.AddPropertyIfAbsent(property); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/SafeAggregateEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/SafeAggregateEnricher.cs new file mode 100644 index 0000000000..2e6ac0e9de --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Enrichers/SafeAggregateEnricher.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Enrichers +{ + class SafeAggregateEnricher : ILogEventEnricher + { + readonly ILogEventEnricher[] _enrichers; + + public SafeAggregateEnricher(IEnumerable enrichers) + { + if (enrichers == null) throw new ArgumentNullException(nameof(enrichers)); + _enrichers = enrichers.ToArray(); + } + + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + foreach (var enricher in _enrichers) + { + try + { + enricher.Enrich(logEvent, propertyFactory); + } + catch (Exception ex) + { + SelfLog.WriteLine("Exception {0} caught while enriching {1} with {2}.", ex, logEvent, enricher); + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Filters/DelegateFilter.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Filters/DelegateFilter.cs new file mode 100644 index 0000000000..1aa6570626 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Filters/DelegateFilter.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Filters +{ + class DelegateFilter : ILogEventFilter + { + readonly Func _isEnabled; + + public DelegateFilter(Func isEnabled) + { + if (isEnabled == null) throw new ArgumentNullException(nameof(isEnabled)); + _isEnabled = isEnabled; + } + + public bool IsEnabled(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + return _isEnabled(logEvent); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/IDestructuringPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Core/IDestructuringPolicy.cs new file mode 100644 index 0000000000..c7882045f3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/IDestructuringPolicy.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Determine how, when destructuring, a supplied value is represented + /// as a complex log event property. + /// + internal interface IDestructuringPolicy + { + /// + /// If supported, destructure the provided value. + /// + /// The value to destructure. + /// Recursively apply policies to destructure additional values. + /// The destructured value, or null. + /// True if the value could be destructured under this policy. + bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventEnricher.cs new file mode 100644 index 0000000000..acdba12a09 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventEnricher.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Applied during logging to add additional information to log events. + /// + internal interface ILogEventEnricher + { + /// + /// Enrich the log event. + /// + /// The log event to enrich. + /// Factory for creating new properties to add to the event. + void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventFilter.cs b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventFilter.cs new file mode 100644 index 0000000000..b148832407 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventFilter.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Provides filtering of the log event stream. + /// + internal interface ILogEventFilter + { + /// + /// Returns true if the provided event is enabled. Otherwise, false. + /// + /// The event to test. + /// True if the event is enabled by this filter. If false + /// is returned, the event will not be emitted. + bool IsEnabled(LogEvent logEvent); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyFactory.cs b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyFactory.cs new file mode 100644 index 0000000000..b9db8bc58a --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyFactory.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Creates log event properties from regular .NET objects, applying policies as + /// required. + /// + internal interface ILogEventPropertyFactory + { + /// + /// Construct a with the specified name and value. + /// + /// The name of the property. + /// The value of the property. + /// If true, and the value is a non-primitive, non-array type, + /// then the value will be converted to a structure; otherwise, unknown types will + /// be converted to scalars, which are generally stored as strings. + /// + LogEventProperty CreateProperty(string name, object value, bool destructureObjects = false); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyValueFactory.cs b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyValueFactory.cs new file mode 100644 index 0000000000..6457f3a0c2 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventPropertyValueFactory.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Supports the policy-driven construction of s given + /// regular .NET objects. + /// + internal interface ILogEventPropertyValueFactory + { + /// + /// Create a given a .NET object and destructuring + /// strategy. + /// + /// The value of the property. + /// If true, and the value is a non-primitive, non-array type, + /// then the value will be converted to a structure; otherwise, unknown types will + /// be converted to scalars, which are generally stored as strings. + /// The value. + LogEventPropertyValue CreatePropertyValue(object value, bool destructureObjects = false); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventSink.cs new file mode 100644 index 0000000000..14f869c1ac --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/ILogEventSink.cs @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// A destination for log events. + /// + internal interface ILogEventSink + { + /// + /// Emit the provided log event to the sink. + /// + /// The log event to write. + void Emit(LogEvent logEvent); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/IMessageTemplateParser.cs b/src/Datadog.Trace/Vendors/Serilog/Core/IMessageTemplateParser.cs new file mode 100644 index 0000000000..deda6f507a --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/IMessageTemplateParser.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + interface IMessageTemplateParser + { + MessageTemplate Parse(string messageTemplate); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/IScalarConversionPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Core/IScalarConversionPolicy.cs new file mode 100644 index 0000000000..a02fa34aef --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/IScalarConversionPolicy.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Determine how a simple value is carried through the logging + /// pipeline as an immutable . + /// + interface IScalarConversionPolicy + { + /// + /// If supported, convert the provided value into an immutable scalar. + /// + /// The value to convert. + /// The converted value, or null. + /// True if the value could be converted under this policy. + bool TryConvertToScalar(object value, out ScalarValue result); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/LevelOverrideMap.cs b/src/Datadog.Trace/Vendors/Serilog/Core/LevelOverrideMap.cs new file mode 100644 index 0000000000..9ea7ecfb78 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/LevelOverrideMap.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + class LevelOverrideMap + { + readonly LogEventLevel _defaultMinimumLevel; + readonly LoggingLevelSwitch _defaultLevelSwitch; + + struct LevelOverride + { + public LevelOverride(string context, LoggingLevelSwitch levelSwitch) + { + Context = context; + ContextPrefix = context + "."; + LevelSwitch = levelSwitch; + } + + public string Context { get; } + public string ContextPrefix { get; } + public LoggingLevelSwitch LevelSwitch { get; } + } + + // There are two possible strategies to apply: + // 1. Keep some bookkeeping data to consult when a new context is encountered, and a concurrent dictionary + // for exact matching ~ O(1), but slow and requires fences/locks; or, + // 2. O(n) search over the raw configuration data every time (fast for small sets of overrides). + // This implementation assumes there will only be a few overrides in each application, so chooses (2). This + // is an assumption that's up for debate. + readonly LevelOverride[] _overrides; + + public LevelOverrideMap( + IDictionary overrides, + LogEventLevel defaultMinimumLevel, + LoggingLevelSwitch defaultLevelSwitch) + { + if (overrides == null) throw new ArgumentNullException(nameof(overrides)); + _defaultLevelSwitch = defaultLevelSwitch; + _defaultMinimumLevel = defaultLevelSwitch != null ? LevelAlias.Minimum : defaultMinimumLevel; + + // Descending order means that if we have a match, we're sure about it being the most specific. + _overrides = overrides + .OrderByDescending(o => o.Key) + .Select(o => new LevelOverride(o.Key, o.Value)) + .ToArray(); + } + + public void GetEffectiveLevel(string context, out LogEventLevel minimumLevel, out LoggingLevelSwitch levelSwitch) + { + foreach (var levelOverride in _overrides) + { + if (context.StartsWith(levelOverride.ContextPrefix) || context == levelOverride.Context) + { + minimumLevel = LevelAlias.Minimum; + levelSwitch = levelOverride.LevelSwitch; + return; + } + } + + minimumLevel = _defaultMinimumLevel; + levelSwitch = _defaultLevelSwitch; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Logger.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Logger.cs new file mode 100644 index 0000000000..e6f63d7540 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Logger.cs @@ -0,0 +1,1386 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Capturing; +using Datadog.Trace.Vendors.Serilog.Core.Enrichers; +using Datadog.Trace.Vendors.Serilog.Core.Pipeline; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +#pragma warning disable Serilog004 // Constant MessageTemplate verifier + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// The core Serilog logging pipeline. A must + /// be disposed to flush any events buffered within it. Most application + /// code should depend on , not this class. + /// + internal sealed class Logger : ILogger, ILogEventSink, IDisposable + { + static readonly object[] NoPropertyValues = new object[0]; + + readonly MessageTemplateProcessor _messageTemplateProcessor; + readonly ILogEventSink _sink; + readonly Action _dispose; + readonly ILogEventEnricher _enricher; + + // It's important that checking minimum level is a very + // quick (CPU-cacheable) read in the simple case, hence + // we keep a separate field from the switch, which may + // not be specified. If it is, we'll set _minimumLevel + // to its lower limit and fall through to the secondary check. + readonly LogEventLevel _minimumLevel; + readonly LoggingLevelSwitch _levelSwitch; + readonly LevelOverrideMap _overrideMap; + + internal Logger( + MessageTemplateProcessor messageTemplateProcessor, + LogEventLevel minimumLevel, + ILogEventSink sink, + ILogEventEnricher enricher, + Action dispose = null, + LevelOverrideMap overrideMap = null) + : this(messageTemplateProcessor, minimumLevel, sink, enricher, dispose, null, overrideMap) + { + } + + internal Logger( + MessageTemplateProcessor messageTemplateProcessor, + LoggingLevelSwitch levelSwitch, + ILogEventSink sink, + ILogEventEnricher enricher, + Action dispose = null, + LevelOverrideMap overrideMap = null) + : this(messageTemplateProcessor, LevelAlias.Minimum, sink, enricher, dispose, levelSwitch, overrideMap) + { + } + + // The messageTemplateProcessor, sink and enricher are required. Argument checks are dropped because + // throwing from here breaks the logger's no-throw contract, and callers are all in this file anyway. + Logger( + MessageTemplateProcessor messageTemplateProcessor, + LogEventLevel minimumLevel, + ILogEventSink sink, + ILogEventEnricher enricher, + Action dispose = null, + LoggingLevelSwitch levelSwitch = null, + LevelOverrideMap overrideMap = null) + { + _messageTemplateProcessor = messageTemplateProcessor; + _minimumLevel = minimumLevel; + _sink = sink; + _dispose = dispose; + _levelSwitch = levelSwitch; + _overrideMap = overrideMap; + _enricher = enricher; + } + + internal bool HasOverrideMap => _overrideMap != null; + + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enricher that applies in the context. + /// A logger that will enrich log events as specified. + public ILogger ForContext(ILogEventEnricher enricher) + { + if (enricher == null) + return this; // No context here, so little point writing to SelfLog. + + return new Logger( + _messageTemplateProcessor, + _minimumLevel, + this, + enricher, + null, + _levelSwitch, + _overrideMap); + } + + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enrichers that apply in the context. + /// A logger that will enrich log events as specified. + public ILogger ForContext(IEnumerable enrichers) + { + if (enrichers == null) + return this; // No context here, so little point writing to SelfLog. + + return ForContext(new SafeAggregateEnricher(enrichers)); + } + + /// + /// Create a logger that enriches log events with the specified property. + /// + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// A logger that will enrich log events as specified. + public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + if (!LogEventProperty.IsValidName(propertyName)) + { + SelfLog.WriteLine("Attempt to call ForContext() with invalid property name `{0}` (value: `{1}`)", propertyName, value); + return this; + } + + // It'd be nice to do the destructuring lazily, but unfortunately `value` may be mutated between + // now and the first log event written... + // A future optimization opportunity may be to implement ILogEventEnricher on LogEventProperty to + // remove one more allocation. + var enricher = new FixedPropertyEnricher(_messageTemplateProcessor.CreateProperty(propertyName, value, destructureObjects)); + + var minimumLevel = _minimumLevel; + var levelSwitch = _levelSwitch; + if (_overrideMap != null && propertyName == Constants.SourceContextPropertyName) + { + var context = value as string; + if (context != null) + _overrideMap.GetEffectiveLevel(context, out minimumLevel, out levelSwitch); + } + + return new Logger( + _messageTemplateProcessor, + minimumLevel, + this, + enricher, + null, + levelSwitch, + _overrideMap); + } + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + public ILogger ForContext(Type source) + { + if (source == null) + return this; // Little point in writing to SelfLog here because we don't have any contextual information + + return ForContext(Constants.SourceContextPropertyName, source.FullName); + } + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + public ILogger ForContext() + { + return ForContext(typeof(TSource)); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, string messageTemplate) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, messageTemplate, NoPropertyValues); + } + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, messageTemplate, new object[] { propertyValue }); + } + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, messageTemplate, new object[] { propertyValue0, propertyValue1 }); + } + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, messageTemplate, new object[] { propertyValue0, propertyValue1, propertyValue2 }); + } + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + Write(level, (Exception)null, messageTemplate, propertyValues); + } + + /// + /// Determine if events at the specified level will be passed through + /// to the log sinks. + /// + /// Level to check. + /// True if the level is enabled; otherwise, false. + public bool IsEnabled(LogEventLevel level) + { + if ((int)level < (int)_minimumLevel) + return false; + + return _levelSwitch == null || + (int)level >= (int)_levelSwitch.MinimumLevel; + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, exception, messageTemplate, NoPropertyValues); + } + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, exception, messageTemplate, new object[] { propertyValue }); + } + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, exception, messageTemplate, new object[] { propertyValue0, propertyValue1 }); + } + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + // Avoid the array allocation and any boxing allocations when the level isn't enabled + if (IsEnabled(level)) + { + Write(level, exception, messageTemplate, new object[] { propertyValue0, propertyValue1, propertyValue2 }); + } + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + if (!IsEnabled(level)) return; + if (messageTemplate == null) return; + + // Catch a common pitfall when a single non-object array is cast to object[] + if (propertyValues != null && + propertyValues.GetType() != typeof(object[])) + propertyValues = new object[] { propertyValues }; + + MessageTemplate parsedTemplate; + IEnumerable boundProperties; + _messageTemplateProcessor.Process(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + + var logEvent = new LogEvent(DateTimeOffset.Now, level, exception, parsedTemplate, boundProperties); + Dispatch(logEvent); + } + + /// + /// Write an event to the log. + /// + /// The event to write. + public void Write(LogEvent logEvent) + { + if (logEvent == null) return; + if (!IsEnabled(logEvent.Level)) return; + Dispatch(logEvent); + } + + void ILogEventSink.Emit(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + // Bypasses the level check so that child loggers + // using this one as a sink can increase verbosity. + Dispatch(logEvent); + } + + void Dispatch(LogEvent logEvent) + { + // The enricher may be a "safe" aggregate one, but is most commonly bare and so + // the exception handling from SafeAggregateEnricher is duplicated here. + try + { + _enricher.Enrich(logEvent, _messageTemplateProcessor); + } + catch (Exception ex) + { + SelfLog.WriteLine("Exception {0} caught while enriching {1} with {2}.", ex, logEvent, _enricher); + } + + _sink.Emit(logEvent); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate) + { + Write(LogEventLevel.Verbose, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(string messageTemplate, params object[] propertyValues) + { + Verbose((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate) + { + Write(LogEventLevel.Debug, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(string messageTemplate, params object[] propertyValues) + { + Debug((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Debug, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Debug(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate) + { + Write(LogEventLevel.Information, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(string messageTemplate, params object[] propertyValues) + { + Information((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Information, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Information(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate) + { + Write(LogEventLevel.Warning, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(string messageTemplate, params object[] propertyValues) + { + Warning((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Warning, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Warning(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate) + { + Write(LogEventLevel.Error, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(string messageTemplate, params object[] propertyValues) + { + Error((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Error, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Error(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate) + { + Write(LogEventLevel.Fatal, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(string messageTemplate, params object[] propertyValues) + { + Fatal((Exception)null, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, NoPropertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValues); + } + + /// + /// Uses configured scalar conversion and destructuring rules to bind a set of properties to a + /// message template. Returns false if the template or values are invalid (ILogger + /// methods never throw exceptions). + /// + /// Message template describing an event. + /// Objects positionally formatted into the message template. + /// The internal representation of the template, which may be used to + /// render the as text. + /// Captured properties from the template and . + /// + /// MessageTemplate template; + /// IEnumerable<LogEventProperty> properties>; + /// if (Log.BindMessageTemplate("Hello, {Name}!", new[] { "World" }, out template, out properties) + /// { + /// var propsByName = properties.ToDictionary(p => p.Name, p => p.Value); + /// Console.WriteLine(template.Render(propsByName, null)); + /// // -> "Hello, World!" + /// } + /// + [MessageTemplateFormatMethod("messageTemplate")] + public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties) + { + if (messageTemplate == null) + { + parsedTemplate = null; + boundProperties = null; + return false; + } + + _messageTemplateProcessor.Process(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + return true; + } + + /// + /// Uses configured scalar conversion and destructuring rules to bind a property value to its captured + /// representation. + /// + /// True if the property could be bound, otherwise false (ILogger + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// The resulting property. + /// methods never throw exceptions). + public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + if (!LogEventProperty.IsValidName(propertyName)) + { + property = null; + return false; + } + + property = _messageTemplateProcessor.CreateProperty(propertyName, value, destructureObjects); + return true; + } + + /// + /// Close and flush the logging pipeline. + /// + public void Dispose() + { + _dispose?.Invoke(); + } + + /// + /// An instance that efficiently ignores all method calls. + /// + public static ILogger None { get; } = SilentLogger.Instance; + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/LoggingLevelSwitch.cs b/src/Datadog.Trace/Vendors/Serilog/Core/LoggingLevelSwitch.cs new file mode 100644 index 0000000000..f93bb73a56 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/LoggingLevelSwitch.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Dynamically controls logging level. + /// + internal class LoggingLevelSwitch + { + volatile LogEventLevel _minimumLevel; + + /// + /// Create a at the initial + /// minimum level. + /// + /// The initial level to which the switch is set. + public LoggingLevelSwitch(LogEventLevel initialMinimumLevel = LogEventLevel.Information) + { + _minimumLevel = initialMinimumLevel; + } + + /// + /// The current minimum level, below which no events + /// should be generated. + /// + // Reading this property generates a memory barrier, + // so needs to be used judiciously in the logging pipeline. + public LogEventLevel MinimumLevel + { + get { return _minimumLevel; } + set { _minimumLevel = value; } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/MessageTemplateFormatMethodAttribute.cs b/src/Datadog.Trace/Vendors/Serilog/Core/MessageTemplateFormatMethodAttribute.cs new file mode 100644 index 0000000000..4ad6fcbfbf --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/MessageTemplateFormatMethodAttribute.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.Serilog.Core +{ + /// + /// Indicates that the marked method logs data using a message template and (optional) arguments. + /// The name of the parameter which contains the message template should be given in the constructor. + /// + /// + /// + /// [LoggerMethod("messageTemplate")] + /// public void Information(string messageTemplate, params object[] propertyValues) + /// { + /// // Do something + /// } + /// + /// public void Foo() + /// { + /// Information("Hello, {Name}!") // Warning: Non-existing argument in message template. + /// } + /// + /// + [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method)] + internal sealed class MessageTemplateFormatMethodAttribute : Attribute + { + /// + /// Initializes a new instance of the class. + /// + /// Name of the message template parameter. + public MessageTemplateFormatMethodAttribute(string messageTemplateParameterName) + { + MessageTemplateParameterName = messageTemplateParameterName; + } + + /// + /// Gets the name of the message template parameter. + /// + /// The name of the message template parameter. + public string MessageTemplateParameterName { get; private set; } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/MessageTemplateCache.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/MessageTemplateCache.cs new file mode 100644 index 0000000000..a734f9a177 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/MessageTemplateCache.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +#if HASHTABLE +using System.Collections; +#else +using System.Collections.Generic; +#endif + +namespace Datadog.Trace.Vendors.Serilog.Core.Pipeline +{ + class MessageTemplateCache : IMessageTemplateParser + { + readonly IMessageTemplateParser _innerParser; + readonly object _templatesLock = new object(); + +#if HASHTABLE + readonly Hashtable _templates = new Hashtable(); +#else + readonly Dictionary _templates = new Dictionary(); +#endif + + const int MaxCacheItems = 1000; + const int MaxCachedTemplateLength = 1024; + + public MessageTemplateCache(IMessageTemplateParser innerParser) + { + if (innerParser == null) throw new ArgumentNullException(nameof(innerParser)); + _innerParser = innerParser; + } + + public MessageTemplate Parse(string messageTemplate) + { + if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate)); + + if (messageTemplate.Length > MaxCachedTemplateLength) + return _innerParser.Parse(messageTemplate); + +#if HASHTABLE + // ReSharper disable once InconsistentlySynchronizedField + // ignored warning because this is by design + var result = (MessageTemplate)_templates[messageTemplate]; + if (result != null) + return result; +#else + MessageTemplate result; + lock(_templatesLock) + if (_templates.TryGetValue(messageTemplate, out result)) + return result; +#endif + + result = _innerParser.Parse(messageTemplate); + + lock (_templatesLock) + { + // Exceeding MaxCacheItems is *not* the sunny day scenario; all we're doing here is preventing out-of-memory + // conditions when the library is used incorrectly. Correct use (templates, rather than + // direct message strings) should barely, if ever, overflow this cache. + + // Changing workloads through the lifecycle of an app instance mean we can gain some ground by + // potentially dropping templates generated only in startup, or only during specific infrequent + // activities. + + if (_templates.Count == MaxCacheItems) + _templates.Clear(); + + _templates[messageTemplate] = result; + } + + return result; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/SilentLogger.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/SilentLogger.cs new file mode 100644 index 0000000000..eb68821c7d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Pipeline/SilentLogger.cs @@ -0,0 +1,361 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Pipeline +{ + class SilentLogger : ILogger + { + public static readonly ILogger Instance = new SilentLogger(); + + private SilentLogger() + { + } + + public ILogger ForContext(ILogEventEnricher enricher) + { + return this; + } + + public ILogger ForContext(IEnumerable enrichers) + { + return this; + } + + public ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + return this; + } + + public ILogger ForContext() + { + return this; + } + + public ILogger ForContext(Type source) + { + return this; + } + + public void Write(LogEvent logEvent) + { + } + + public void Write(LogEventLevel level, string messageTemplate) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public bool IsEnabled(LogEventLevel level) + { + return false; + } + + public void Verbose(string messageTemplate) + { + } + + public void Verbose(string messageTemplate, T propertyValue) + { + } + + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Verbose(string messageTemplate, params object[] propertyValues) + { + } + + public void Verbose(Exception exception, string messageTemplate) + { + } + + public void Verbose(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Verbose(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Debug(string messageTemplate) + { + } + + public void Debug(string messageTemplate, T propertyValue) + { + } + + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Debug(string messageTemplate, params object[] propertyValues) + { + } + + public void Debug(Exception exception, string messageTemplate) + { + } + + public void Debug(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Debug(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Information(string messageTemplate) + { + } + + public void Information(string messageTemplate, T propertyValue) + { + } + + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Information(string messageTemplate, params object[] propertyValues) + { + } + + public void Information(Exception exception, string messageTemplate) + { + } + + public void Information(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Information(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Warning(string messageTemplate) + { + } + + public void Warning(string messageTemplate, T propertyValue) + { + } + + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Warning(string messageTemplate, params object[] propertyValues) + { + } + + public void Warning(Exception exception, string messageTemplate) + { + } + + public void Warning(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Warning(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Error(string messageTemplate) + { + } + + public void Error(string messageTemplate, T propertyValue) + { + } + + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Error(string messageTemplate, params object[] propertyValues) + { + } + + public void Error(Exception exception, string messageTemplate) + { + } + + public void Error(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Error(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + public void Fatal(string messageTemplate) + { + } + + public void Fatal(string messageTemplate, T propertyValue) + { + } + + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Fatal(string messageTemplate, params object[] propertyValues) + { + } + + public void Fatal(Exception exception, string messageTemplate) + { + } + + public void Fatal(Exception exception, string messageTemplate, T propertyValue) + { + } + + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + } + + public void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + } + + public void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) + { + } + + [MessageTemplateFormatMethod("messageTemplate")] + public bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties) + { + parsedTemplate = null; + boundProperties = null; + return false; + } + + public bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + property = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/AggregateSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/AggregateSink.cs new file mode 100644 index 0000000000..d908a1c552 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/AggregateSink.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Sinks +{ + class AggregateSink : ILogEventSink + { + readonly ILogEventSink[] _sinks; + + public AggregateSink(IEnumerable sinks) + { + if (sinks == null) throw new ArgumentNullException(nameof(sinks)); + _sinks = sinks.ToArray(); + } + + public void Emit(LogEvent logEvent) + { + List exceptions = null; + foreach (var sink in _sinks) + { + try + { + sink.Emit(logEvent); + } + catch (Exception ex) + { + SelfLog.WriteLine("Caught exception while emitting to sink {0}: {1}", sink, ex); + exceptions = exceptions ?? new List(); + exceptions.Add(ex); + } + } + + if (exceptions != null) + throw new AggregateException("Failed to emit a log event.", exceptions); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/FilteringSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/FilteringSink.cs new file mode 100644 index 0000000000..95d5890890 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/FilteringSink.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Sinks +{ + class FilteringSink : ILogEventSink + { + readonly ILogEventSink _sink; + readonly bool _propagateExceptions; + readonly ILogEventFilter[] _filters; + + public FilteringSink(ILogEventSink sink, IEnumerable filters, bool propagateExceptions) + { + if (sink == null) throw new ArgumentNullException(nameof(sink)); + if (filters == null) throw new ArgumentNullException(nameof(filters)); + _sink = sink; + _propagateExceptions = propagateExceptions; + _filters = filters.ToArray(); + } + + public void Emit(LogEvent logEvent) + { + try + { + foreach (var logEventFilter in _filters) + { + if (!logEventFilter.IsEnabled(logEvent)) + return; + } + + _sink.Emit(logEvent); + } + catch (Exception ex) + { + SelfLog.WriteLine("Caught exception while applying filters: {0}", ex); + + if (_propagateExceptions) + throw; + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/RestrictedSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/RestrictedSink.cs new file mode 100644 index 0000000000..1b162bf87d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/RestrictedSink.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Sinks +{ + class RestrictedSink : ILogEventSink, IDisposable + { + readonly ILogEventSink _sink; + readonly LoggingLevelSwitch _levelSwitch; + + public RestrictedSink(ILogEventSink sink, LoggingLevelSwitch levelSwitch) + { + if (sink == null) throw new ArgumentNullException(nameof(sink)); + if (levelSwitch == null) throw new ArgumentNullException(nameof(levelSwitch)); + _sink = sink; + _levelSwitch = levelSwitch; + } + + public void Emit(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + if ((int)logEvent.Level < (int)_levelSwitch.MinimumLevel) + return; + + _sink.Emit(logEvent); + } + + public void Dispose() + { + (_sink as IDisposable)?.Dispose(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SafeAggregateSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SafeAggregateSink.cs new file mode 100644 index 0000000000..9c61274f1f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SafeAggregateSink.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Sinks +{ + class SafeAggregateSink : ILogEventSink + { + readonly ILogEventSink[] _sinks; + + public SafeAggregateSink(IEnumerable sinks) + { + if (sinks == null) throw new ArgumentNullException(nameof(sinks)); + _sinks = sinks.ToArray(); + } + + public void Emit(LogEvent logEvent) + { + foreach (var sink in _sinks) + { + try + { + sink.Emit(logEvent); + } + catch (Exception ex) + { + SelfLog.WriteLine("Caught exception while emitting to sink {0}: {1}", sink, ex); + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SecondaryLoggerSink.cs b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SecondaryLoggerSink.cs new file mode 100644 index 0000000000..a5116c2857 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Core/Sinks/SecondaryLoggerSink.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Core.Sinks +{ + /// + /// Forwards log events to another logging pipeline. Copies the events so + /// that mutations performed on the copies do not affect the originals. + /// + /// The properties dictionary is copied, however the values within + /// the dictionary (of type are expected to + /// be immutable. + sealed class SecondaryLoggerSink : ILogEventSink, IDisposable + { + readonly ILogger _logger; + readonly bool _attemptDispose; + + public SecondaryLoggerSink(ILogger logger, bool attemptDispose = false) + { + if (logger == null) throw new ArgumentNullException(nameof(logger)); + _logger = logger; + _attemptDispose = attemptDispose; + } + + public void Emit(LogEvent logEvent) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + + var copy = new LogEvent( + logEvent.Timestamp, + logEvent.Level, + logEvent.Exception, + logEvent.MessageTemplate, + logEvent.Properties.Select(p => new LogEventProperty(p.Key, p.Value))); + + _logger.Write(copy); + } + + public void Dispose() + { + if (!_attemptDispose) + return; + + (_logger as IDisposable)?.Dispose(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueRewriter.cs b/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueRewriter.cs new file mode 100644 index 0000000000..5360e24da8 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueRewriter.cs @@ -0,0 +1,158 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Data +{ + /// + /// A base class for visitors that rewrite the value with modifications. For example, implementations + /// might remove all structure properties with a certain name, apply size/length limits, or convert scalar properties of + /// one type into scalar properties of another. + /// + /// + internal abstract class LogEventPropertyValueRewriter : LogEventPropertyValueVisitor + { + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override LogEventPropertyValue VisitScalarValue(TState state, ScalarValue scalar) + { + if (scalar == null) throw new ArgumentNullException(nameof(scalar)); + return scalar; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override LogEventPropertyValue VisitSequenceValue(TState state, SequenceValue sequence) + { + if (sequence == null) throw new ArgumentNullException(nameof(sequence)); + + for (var i = 0; i < sequence.Elements.Count; ++i) + { + var original = sequence.Elements[i]; + if (!ReferenceEquals(original, Visit(state, original))) + { + var contents = new LogEventPropertyValue[sequence.Elements.Count]; + + // There's no need to visit any earlier elements: they all evaluated to + // a reference equal with the original so just fill in the array up until `i`. + for (var j = 0; j < i; ++j) + { + contents[j] = sequence.Elements[j]; + } + + for (var k = i; k < contents.Length; ++k) + { + contents[k] = Visit(state, sequence.Elements[k]); + } + + return new SequenceValue(contents); + } + } + + return sequence; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override LogEventPropertyValue VisitStructureValue(TState state, StructureValue structure) + { + if (structure == null) throw new ArgumentNullException(nameof(structure)); + + for (var i = 0; i < structure.Properties.Count; ++i) + { + var original = structure.Properties[i]; + if (!ReferenceEquals(original.Value, Visit(state, original.Value))) + { + var properties = new LogEventProperty[structure.Properties.Count]; + + // There's no need to visit any earlier elements: they all evaluated to + // a reference equal with the original so just fill in the array up until `i`. + for (var j = 0; j < i; ++j) + { + properties[j] = structure.Properties[j]; + } + + for (var k = i; k < properties.Length; ++k) + { + var property = structure.Properties[k]; + properties[k] = new LogEventProperty(property.Name, Visit(state, property.Value)); + } + + return new StructureValue(properties, structure.TypeTag); + } + } + + return structure; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override LogEventPropertyValue VisitDictionaryValue(TState state, DictionaryValue dictionary) + { + if (dictionary == null) throw new ArgumentNullException(nameof(dictionary)); + + foreach (var original in dictionary.Elements) + { + if (!ReferenceEquals(original.Value, Visit(state, original.Value))) + { + var elements = new Dictionary(dictionary.Elements.Count); + foreach (var element in dictionary.Elements) + { + elements[element.Key] = Visit(state, element.Value); + } + + return new DictionaryValue(elements); + } + } + + return dictionary; + } + + /// + /// Visit a value of an unsupported type. Returns the value unchanged. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + // ReSharper disable once UnusedParameter.Global + // ReSharper disable once VirtualMemberNeverOverriden.Global + protected override LogEventPropertyValue VisitUnsupportedValue(TState state, LogEventPropertyValue value) + { + return value; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueVisitor.cs b/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueVisitor.cs new file mode 100644 index 0000000000..f3ffe3b873 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Data/LogEventPropertyValueVisitor.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +// ReSharper disable VirtualMemberNeverOverridden.Global + +namespace Datadog.Trace.Vendors.Serilog.Data +{ + /// + /// An abstract base class for visitors that walk data in the + /// format. Subclasses, by + /// overriding appropriate methods, may search for, transform, + /// or print the value structures being visited. + /// + /// + /// Stateless, designed to accommodate allocation-free visiting of multiple + /// values by the same visitor instance. + /// + /// The type of a state object passed through + /// the visiting process. + /// The type of the result generated by visiting + /// a node. + internal abstract class LogEventPropertyValueVisitor + { + /// + /// Visit the root node type. This method delegates to + /// a concrete Visit*Value() method appropriate for the value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected virtual TResult Visit(TState state, LogEventPropertyValue value) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + + var sv = value as ScalarValue; + if (sv != null) + return VisitScalarValue(state, sv); + + var seqv = value as SequenceValue; + if (seqv != null) + return VisitSequenceValue(state, seqv); + + var strv = value as StructureValue; + if (strv != null) + return VisitStructureValue(state, strv); + + var dictv = value as DictionaryValue; + if (dictv != null) + return VisitDictionaryValue(state, dictv); + + return VisitUnsupportedValue(state, value); + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected abstract TResult VisitScalarValue(TState state, ScalarValue scalar); + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected abstract TResult VisitSequenceValue(TState state, SequenceValue sequence); + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected abstract TResult VisitStructureValue(TState state, StructureValue structure); + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected abstract TResult VisitDictionaryValue(TState state, DictionaryValue dictionary); + + /// + /// Visit a value of an unsupported type. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + // ReSharper disable once UnusedParameter.Global + protected virtual TResult VisitUnsupportedValue(TState state, LogEventPropertyValue value) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + throw new NotSupportedException($"The value {value} is not of a type supported by this visitor."); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Debugging/LoggingFailedException.cs b/src/Datadog.Trace/Vendors/Serilog/Debugging/LoggingFailedException.cs new file mode 100644 index 0000000000..8a134d53b4 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Debugging/LoggingFailedException.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Datadog.Trace.Vendors.Serilog.Debugging +{ + /// + /// May be thrown by log event sinks when a failure occurs. Should not be used in cases + /// where the exception would propagate out to callers. + /// + internal class LoggingFailedException : Exception + { + /// + /// Construct a to communicate a logging failure. + /// + /// A message describing the logging failure. + public LoggingFailedException(string message) + : base(message) + { + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Debugging/SelfLog.cs b/src/Datadog.Trace/Vendors/Serilog/Debugging/SelfLog.cs new file mode 100644 index 0000000000..d7dfd77d03 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Debugging/SelfLog.cs @@ -0,0 +1,106 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Debugging +{ + /// + /// A simple source of information generated by Serilog itself, + /// for example when exceptions are thrown and caught internally. + /// + internal static class SelfLog + { + static Action _output; + + /// + /// The output mechanism for self-log messages. + /// + /// + /// SelfLog.Out = Console.Error; + /// + // ReSharper disable once MemberCanBePrivate.Global, UnusedAutoPropertyAccessor.Global + [Obsolete("Use SelfLog.Enable(value) and SelfLog.Disable() instead")] + public static TextWriter Out + { + set + { + if (value != null) + Enable(value); + else + Disable(); + } + } + + /// + /// Set the output mechanism for self-log messages. + /// + /// A synchronized to which + /// self-log messages will be written. + // ReSharper disable once MemberCanBePrivate.Global + public static void Enable(TextWriter output) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + Enable(m => + { + output.WriteLine(m); + output.Flush(); + }); + } + + /// + /// Set the output mechanism for self-log messages. + /// + /// An action to invoke with self-log messages. + /// // ReSharper disable once MemberCanBePrivate.Global + public static void Enable(Action output) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + _output = output; + } + + /// + /// Clear the output mechanism and disable self-log events. + /// + /// // ReSharper disable once MemberCanBePrivate.Global + public static void Disable() + { + _output = null; + } + + /// + /// Write a message to the self-log. + /// + /// Standard .NET format string containing the message. + /// First argument, if supplied. + /// Second argument, if supplied. + /// Third argument, if supplied. + /// + /// The name is historical; because this is used from third-party sink packages, removing the "Line" + /// suffix as would seem sensible isn't worth the breakage. + /// + public static void WriteLine(string format, object arg0 = null, object arg1 = null, object arg2 = null) + { + var o = _output; + + o?.Invoke(string.Format(DateTime.UtcNow.ToString("o") + " " + format, arg0, arg1, arg2)); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Enrichers/LogContextEnricher.cs b/src/Datadog.Trace/Vendors/Serilog/Enrichers/LogContextEnricher.cs new file mode 100644 index 0000000000..d35abe4d6f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Enrichers/LogContextEnricher.cs @@ -0,0 +1,32 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Context; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Enrichers +{ + sealed class LogContextEnricher : ILogEventEnricher + { + public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) + { + LogContext.Enrich(logEvent, propertyFactory); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/DictionaryValue.cs b/src/Datadog.Trace/Vendors/Serilog/Events/DictionaryValue.cs new file mode 100644 index 0000000000..ba113cfbd8 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/DictionaryValue.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A value represented as a mapping from keys to values. + /// + internal class DictionaryValue : LogEventPropertyValue + { + /// + /// Create a with the provided . + /// + /// The key-value mappings represented in the dictionary. + /// + public DictionaryValue(IEnumerable> elements) + { + if (elements == null) throw new ArgumentNullException(nameof(elements)); + Elements = elements.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } + + /// + /// The dictionary mapping. + /// + public IReadOnlyDictionary Elements { get; } + + /// + /// Render the value to the output. + /// + /// The output. + /// A format string applied to the value, or null. + /// A format provider to apply to the value, or null to use the default. + /// . + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + output.Write('['); + var delim = "("; + foreach (var kvp in Elements) + { + output.Write(delim); + delim = ", ("; + kvp.Key.Render(output, null, formatProvider); + output.Write(": "); + kvp.Value.Render(output, null, formatProvider); + output.Write(")"); + } + + output.Write(']'); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/LevelAlias.cs b/src/Datadog.Trace/Vendors/Serilog/Events/LevelAlias.cs new file mode 100644 index 0000000000..426bc33d87 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/LevelAlias.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// Descriptive aliases for . + /// + /// These do not appear as members of the enumeration + /// as duplicated underlying values result in issues when presenting + /// enum values with . + internal static class LevelAlias + { + /// + /// The least significant level of event. + /// + public const LogEventLevel Minimum = LogEventLevel.Verbose; + + /// + /// The most significant level of event. + /// + public const LogEventLevel Maximum = LogEventLevel.Fatal; + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/LogEvent.cs b/src/Datadog.Trace/Vendors/Serilog/Events/LogEvent.cs new file mode 100644 index 0000000000..a580f13926 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/LogEvent.cs @@ -0,0 +1,132 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A log event. + /// + internal class LogEvent + { + readonly Dictionary _properties; + + /// + /// Construct a new . + /// + /// The time at which the event occurred. + /// The level of the event. + /// An exception associated with the event, or null. + /// The message template describing the event. + /// Properties associated with the event, including those presented in . + public LogEvent(DateTimeOffset timestamp, LogEventLevel level, Exception exception, MessageTemplate messageTemplate, IEnumerable properties) + { + if (messageTemplate == null) throw new ArgumentNullException(nameof(messageTemplate)); + if (properties == null) throw new ArgumentNullException(nameof(properties)); + Timestamp = timestamp; + Level = level; + Exception = exception; + MessageTemplate = messageTemplate; + _properties = new Dictionary(); + foreach (var p in properties) + AddOrUpdateProperty(p); + } + + /// + /// The time at which the event occurred. + /// + public DateTimeOffset Timestamp { get; } + + /// + /// The level of the event. + /// + public LogEventLevel Level { get; } + + /// + /// The message template describing the event. + /// + public MessageTemplate MessageTemplate { get; } + + /// + /// Render the message template to the specified output, given the properties associated + /// with the event. + /// + /// The output. + /// Supplies culture-specific formatting information, or null. + public void RenderMessage(TextWriter output, IFormatProvider formatProvider = null) + { + MessageTemplate.Render(Properties, output, formatProvider); + } + + /// + /// Render the message template given the properties associated + /// with the event, and return the result. + /// + /// Supplies culture-specific formatting information, or null. + public string RenderMessage(IFormatProvider formatProvider = null) + { + return MessageTemplate.Render(Properties, formatProvider); + } + + /// + /// Properties associated with the event, including those presented in . + /// + public IReadOnlyDictionary Properties => _properties; + + /// + /// An exception associated with the event, or null. + /// + public Exception Exception { get; } + + /// + /// Add a property to the event if not already present, otherwise, update its value. + /// + /// The property to add or update. + /// + public void AddOrUpdateProperty(LogEventProperty property) + { + if (property == null) throw new ArgumentNullException(nameof(property)); + _properties[property.Name] = property.Value; + } + + /// + /// Add a property to the event if not already present. + /// + /// The property to add. + /// + public void AddPropertyIfAbsent(LogEventProperty property) + { + if (property == null) throw new ArgumentNullException(nameof(property)); + if (!_properties.ContainsKey(property.Name)) + _properties.Add(property.Name, property.Value); + } + + /// + /// Remove a property from the event, if present. Otherwise no action + /// is performed. + /// + /// The name of the property to remove. + public void RemovePropertyIfPresent(string propertyName) + { + _properties.Remove(propertyName); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/LogEventLevel.cs b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventLevel.cs new file mode 100644 index 0000000000..cb6a07ccf7 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventLevel.cs @@ -0,0 +1,61 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// Specifies the meaning and relative importance of a log event. + /// + internal enum LogEventLevel + { + /// + /// Anything and everything you might want to know about + /// a running block of code. + /// + Verbose, + + /// + /// Internal system events that aren't necessarily + /// observable from the outside. + /// + Debug, + + /// + /// The lifeblood of operational intelligence - things + /// happen. + /// + Information, + + /// + /// Service is degraded or endangered. + /// + Warning, + + /// + /// Functionality is unavailable, invariants are broken + /// or data is lost. + /// + Error, + + /// + /// If you have a pager, it goes off when one of these + /// occurs. + /// + Fatal + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/LogEventProperty.cs b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventProperty.cs new file mode 100644 index 0000000000..f2fa8b3af0 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventProperty.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A property associated with a . + /// + internal class LogEventProperty + { + /// + /// Construct a with the specified name and value. + /// + /// The name of the property. + /// The value of the property. + /// + /// + public LogEventProperty(string name, LogEventPropertyValue value) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + if (!IsValidName(name)) + throw new ArgumentException("Property name is not valid."); + + Name = name; + Value = value; + } + + /// + /// The name of the property. + /// + public string Name { get; } + + /// + /// The value of the property. + /// + public LogEventPropertyValue Value { get; } + + /// + /// Test to determine if it is a valid property name. + /// + /// The name to check. + /// True if the name is valid; otherwise, false. + public static bool IsValidName(string name) + { + return !string.IsNullOrWhiteSpace(name); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/LogEventPropertyValue.cs b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventPropertyValue.cs new file mode 100644 index 0000000000..d1fde887c6 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/LogEventPropertyValue.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// The value associated with a . Divided into scalar, + /// sequence and structure values to direct serialization into various formats. + /// + internal abstract class LogEventPropertyValue : IFormattable + { + /// + /// Render the value to the output. + /// + /// The output. + /// A format string applied to the value, or null. + /// A format provider to apply to the value, or null to use the default. + /// . + public abstract void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null); + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() + { + return ToString(null, null); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// + /// The value of the current instance in the specified format. + /// + /// The format to use.-or- A null reference (Nothing in Visual Basic) to use + /// the default format defined for the type of the implementation. + /// The provider to use to format the value.-or- A null reference + /// (Nothing in Visual Basic) to obtain the numeric format information from the current locale + /// setting of the operating system. 2 + public string ToString(string format, IFormatProvider formatProvider) + { + var output = new StringWriter(); + Render(output, format, formatProvider); + return output.ToString(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/MessageTemplate.cs b/src/Datadog.Trace/Vendors/Serilog/Events/MessageTemplate.cs new file mode 100644 index 0000000000..cd4ddc5434 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/MessageTemplate.cs @@ -0,0 +1,170 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Debugging; +using Datadog.Trace.Vendors.Serilog.Parsing; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// Represents a message template passed to a log method. The template + /// can subsequently render the template in textual form given the list + /// of properties. + /// + internal class MessageTemplate + { + /// + /// Represents the empty message template. + /// + public static MessageTemplate Empty { get; } = new MessageTemplate(Enumerable.Empty()); + + readonly MessageTemplateToken[] _tokens; + + /// + /// Construct a message template using manually-defined text and property tokens. + /// + /// The text and property tokens defining the template. + public MessageTemplate(IEnumerable tokens) + // ReSharper disable PossibleMultipleEnumeration + : this(string.Join("", tokens), tokens) + // ReSharper enable PossibleMultipleEnumeration + { + } + + /// + /// Construct a message template using manually-defined text and property tokens. + /// + /// The full text of the template; used by Serilog internally to avoid unneeded + /// string concatenation. + /// The text and property tokens defining the template. + public MessageTemplate(string text, IEnumerable tokens) + { + if (text == null) throw new ArgumentNullException(nameof(text)); + if (tokens == null) throw new ArgumentNullException(nameof(tokens)); + + Text = text; + _tokens = tokens.ToArray(); + + var propertyTokens = GetElementsOfTypeToArray(_tokens); + if (propertyTokens.Length != 0) + { + var allPositional = true; + var anyPositional = false; + foreach (var propertyToken in propertyTokens) + { + if (propertyToken.IsPositional) + anyPositional = true; + else + allPositional = false; + } + + if (allPositional) + { + PositionalProperties = propertyTokens; + } + else + { + if (anyPositional) + SelfLog.WriteLine("Message template is malformed: {0}", text); + + NamedProperties = propertyTokens; + } + } + } + + /// + /// Similar to , but faster. + /// + static TResult[] GetElementsOfTypeToArray(MessageTemplateToken[] tokens) + where TResult: class + { + var result = new List(tokens.Length / 2); + for (var i = 0; i < tokens.Length; i++) + { + var token = tokens[i] as TResult; + if (token != null) + { + result.Add(token); + } + } + return result.ToArray(); + } + + /// + /// The raw text describing the template. + /// + public string Text { get; } + + /// + /// Render the template as a string. + /// + /// The string representation of the template. + public override string ToString() + { + return Text; + } + + /// + /// The tokens parsed from the template. + /// + public IEnumerable Tokens => _tokens; + + internal MessageTemplateToken[] TokenArray => _tokens; + + internal PropertyToken[] NamedProperties { get; } + + internal PropertyToken[] PositionalProperties { get; } + + /// + /// Convert the message template into a textual message, given the + /// properties matching the tokens in the message template. + /// + /// Properties matching template tokens. + /// Supplies culture-specific formatting information, or null. + /// The message created from the template and properties. If the + /// properties are mismatched with the template, the template will be + /// returned with incomplete substitution. + public string Render(IReadOnlyDictionary properties, IFormatProvider formatProvider = null) + { + var writer = new StringWriter(formatProvider); + Render(properties, writer, formatProvider); + return writer.ToString(); + } + + /// + /// Convert the message template into a textual message, given the + /// properties matching the tokens in the message template. + /// + /// Properties matching template tokens. + /// The message created from the template and properties. If the + /// properties are mismatched with the template, the template will be + /// returned with incomplete substitution. + /// Supplies culture-specific formatting information, or null. + public void Render(IReadOnlyDictionary properties, TextWriter output, IFormatProvider formatProvider = null) + { + if (properties == null) throw new ArgumentNullException(nameof(properties)); + if (output == null) throw new ArgumentNullException(nameof(output)); + MessageTemplateRenderer.Render(this, properties, output, null, formatProvider); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/ScalarValue.cs b/src/Datadog.Trace/Vendors/Serilog/Events/ScalarValue.cs new file mode 100644 index 0000000000..546c8963e8 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/ScalarValue.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; +using System.IO; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A property value corresponding to a simple, scalar type. + /// + internal class ScalarValue : LogEventPropertyValue + { + /// + /// Construct a with the specified + /// value. + /// + /// The value, which may be null. + public ScalarValue(object value) + { + Value = value; + } + + /// + /// The value, which may be null. + /// + public object Value { get; } + + /// + /// Render the value to the output. + /// + /// The output. + /// A format string applied to the value, or null. + /// A format provider to apply to the value, or null to use the default. + /// . + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + Render(Value, output, format, formatProvider); + } + + internal static void Render(object value, TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + if (value == null) + { + output.Write("null"); + return; + } + + var s = value as string; + if (s != null) + { + if (format != "l") + { + output.Write("\""); + output.Write(s.Replace("\"", "\\\"")); + output.Write("\""); + } + else + { + output.Write(s); + } + return; + } + + if (formatProvider != null) + { + var custom = (ICustomFormatter)formatProvider.GetFormat(typeof(ICustomFormatter)); + if (custom != null) + { + output.Write(custom.Format(format, value, formatProvider)); + return; + } + } + + var f = value as IFormattable; + if (f != null) + { + output.Write(f.ToString(format, formatProvider ?? CultureInfo.InvariantCulture)); + } + else + { + output.Write(value.ToString()); + } + } + + /// + /// Determine if this instance is equal to . + /// + /// The instance to compare with. + /// True if the instances are equal; otherwise, false. + public override bool Equals(object obj) + { + var sv = obj as ScalarValue; + if (sv == null) return false; + return Equals(Value, sv.Value); + } + + /// + /// Get a hash code representing the value. + /// + /// The instance's hash code. + public override int GetHashCode() + { + if (Value == null) return 0; + return Value.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/SequenceValue.cs b/src/Datadog.Trace/Vendors/Serilog/Events/SequenceValue.cs new file mode 100644 index 0000000000..0d3fb8fb1f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/SequenceValue.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A value represented as an ordered sequence of values. + /// + internal class SequenceValue : LogEventPropertyValue + { + readonly LogEventPropertyValue[] _elements; + + /// + /// Create a with the provided . + /// + /// The elements of the sequence. + /// + public SequenceValue(IEnumerable elements) + { + if (elements == null) throw new ArgumentNullException(nameof(elements)); + _elements = elements.ToArray(); + } + + /// + /// The elements of the sequence. + /// + public IReadOnlyList Elements => _elements; + + /// + /// Render the value to the output. + /// + /// The output. + /// A format string applied to the value, or null. + /// A format provider to apply to the value, or null to use the default. + /// . + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + output.Write('['); + var allButLast = _elements.Length - 1; + for (var i = 0; i < allButLast; ++i ) + { + _elements[i].Render(output, format, formatProvider); + output.Write(", "); + } + + if (_elements.Length > 0) + _elements[_elements.Length - 1].Render(output, format, formatProvider); + + output.Write(']'); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Events/StructureValue.cs b/src/Datadog.Trace/Vendors/Serilog/Events/StructureValue.cs new file mode 100644 index 0000000000..7581abbab5 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Events/StructureValue.cs @@ -0,0 +1,102 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Generic; +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.IO; +using System.Linq; + +namespace Datadog.Trace.Vendors.Serilog.Events +{ + /// + /// A value represented as a collection of name-value properties. + /// + internal class StructureValue : LogEventPropertyValue + { + readonly LogEventProperty[] _properties; + + /// + /// Construct a with the provided properties. + /// + /// Optionally, a piece of metadata describing the "type" of the + /// structure. + /// The properties of the structure. + /// + public StructureValue(IEnumerable properties, string typeTag = null) + { + if (properties == null) throw new ArgumentNullException(nameof(properties)); + TypeTag = typeTag; + _properties = properties.ToArray(); + } + + /// + /// A piece of metadata describing the "type" of the + /// structure, or null. + /// + public string TypeTag { get; } + + /// + /// The properties of the structure. + /// + /// Not presented as a dictionary because dictionary construction is + /// relatively expensive; it is cheaper to build a dictionary over properties only + /// when the structure is of interest. + public IReadOnlyList Properties => _properties; + + /// + /// Render the value to the output. + /// + /// The output. + /// A format string applied to the value, or null. + /// A format provider to apply to the value, or null to use the default. + /// . + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + + if (TypeTag != null) + { + output.Write(TypeTag); + output.Write(' '); + } + output.Write("{ "); + var allButLast = _properties.Length - 1; + for (var i = 0; i < allButLast; i++) + { + var property = _properties[i]; + Render(output, property, formatProvider); + output.Write(", "); + } + + if (_properties.Length > 0) + { + var last = _properties[_properties.Length - 1]; + Render(output, last, formatProvider); + } + + output.Write(" }"); + } + + static void Render(TextWriter output, LogEventProperty property, IFormatProvider formatProvider = null) + { + output.Write(property.Name); + output.Write(": "); + property.Value.Render(output, null, formatProvider); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Filters/Matching.cs b/src/Datadog.Trace/Vendors/Serilog/Filters/Matching.cs new file mode 100644 index 0000000000..72705f922f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Filters/Matching.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Filters +{ + /// + /// Predicates applied to log events that can be used + /// + internal static class Matching + { + /// + /// Matches events from the specified source type. + /// + /// The source type. + /// A predicate for matching events. + public static Func FromSource() + { + return WithProperty(Constants.SourceContextPropertyName, typeof(TSource).FullName); + } + + /// + /// Matches events from the specified source type or namespace and + /// nested types or namespaces. + /// + /// A dotted source type or namespace identifier. + /// A function that matches log events emitted by the source. + public static Func FromSource(string source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + var sourcePrefix = source + "."; + return WithProperty(Constants.SourceContextPropertyName, s => s != null && (s == source || s.StartsWith(sourcePrefix))); + } + + /// + /// Matches events with the specified property attached, + /// regardless of its value. + /// + /// The name of the property to match. + /// A predicate for matching events. + public static Func WithProperty(string propertyName) + { + if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); + return e => e.Properties.ContainsKey(propertyName); + } + + /// + /// Matches events with the specified property value. + /// + /// The name of the property to match. + /// The property value to match; must be a scalar type. + /// Null is allowed. + /// A predicate for matching events. + public static Func WithProperty(string propertyName, object scalarValue) + { + if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); + var scalar = new ScalarValue(scalarValue); + return e => + { + LogEventPropertyValue propertyValue; + return e.Properties.TryGetValue(propertyName, out propertyValue) && + scalar.Equals(propertyValue); + }; + } + + /// + /// Matches events with the specified property value. + /// + /// The name of the property to match. + /// A predicate for testing + /// The type of scalar values to match. + /// A predicate for matching events. + public static Func WithProperty(string propertyName, Func predicate) + { + if (propertyName == null) throw new ArgumentNullException(nameof(propertyName)); + if (predicate == null) throw new ArgumentNullException(nameof(predicate)); + + return e => + { + LogEventPropertyValue propertyValue; + if (!e.Properties.TryGetValue(propertyName, out propertyValue)) return false; + + var s = propertyValue as ScalarValue; + if (s == null) return false; + + return (s.Value is TScalar) && + predicate((TScalar)s.Value); + }; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/LevelOutputFormat.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/LevelOutputFormat.cs new file mode 100644 index 0000000000..8f5ca4e000 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/LevelOutputFormat.cs @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display +{ + /// + /// Implements the {Level} element. + /// can now have a fixed width applied to it, as well as casing rules. + /// Width is set through formats like "u3" (uppercase three chars), + /// "w1" (one lowercase char), or "t4" (title case four chars). + /// + static class LevelOutputFormat + { + static readonly string[][] _titleCaseLevelMap = { + new []{ "V", "Vb", "Vrb", "Verb" }, + new []{ "D", "De", "Dbg", "Dbug" }, + new []{ "I", "In", "Inf", "Info" }, + new []{ "W", "Wn", "Wrn", "Warn" }, + new []{ "E", "Er", "Err", "Eror" }, + new []{ "F", "Fa", "Ftl", "Fatl" } + }; + + static readonly string[][] _lowercaseLevelMap = { + new []{ "v", "vb", "vrb", "verb" }, + new []{ "d", "de", "dbg", "dbug" }, + new []{ "i", "in", "inf", "info" }, + new []{ "w", "wn", "wrn", "warn" }, + new []{ "e", "er", "err", "eror" }, + new []{ "f", "fa", "ftl", "fatl" } + }; + + static readonly string[][] _uppercaseLevelMap = { + new []{ "V", "VB", "VRB", "VERB" }, + new []{ "D", "DE", "DBG", "DBUG" }, + new []{ "I", "IN", "INF", "INFO" }, + new []{ "W", "WN", "WRN", "WARN" }, + new []{ "E", "ER", "ERR", "EROR" }, + new []{ "F", "FA", "FTL", "FATL" } + }; + + public static string GetLevelMoniker(LogEventLevel value, string format = null) + { + if (format == null || format.Length != 2 && format.Length != 3) + return Casing.Format(value.ToString(), format); + + // Using int.Parse() here requires allocating a string to exclude the first character prefix. + // Junk like "wxy" will be accepted but produce benign results. + var width = format[1] - '0'; + if (format.Length == 3) + { + width *= 10; + width += format[2] - '0'; + } + + if (width < 1) + return string.Empty; + + if (width > 4) + { + var stringValue = value.ToString(); + if (stringValue.Length > width) + stringValue = stringValue.Substring(0, width); + return Casing.Format(stringValue); + } + + var index = (int)value; + if (index >= 0 && index <= (int) LogEventLevel.Fatal) + { + switch (format[0]) + { + case 'w': + return _lowercaseLevelMap[index][width - 1]; + case 'u': + return _uppercaseLevelMap[index][width - 1]; + case 't': + return _titleCaseLevelMap[index][width - 1]; + } + } + + return Casing.Format(value.ToString(), format); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/MessageTemplateTextFormatter.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/MessageTemplateTextFormatter.cs new file mode 100644 index 0000000000..5ea190c227 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/MessageTemplateTextFormatter.cs @@ -0,0 +1,133 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display +{ + /// + /// A that supports the Serilog + /// message template format. Formatting log events for display + /// has a different set of requirements and expectations from + /// rendering the data within them. To meet this, the formatter + /// overrides some behavior: First, strings are always output + /// as literals (not quoted) unless some other format is applied + /// to them. Second, tokens without matching properties are skipped + /// rather than being written as raw text. + /// + internal class MessageTemplateTextFormatter : ITextFormatter + { + readonly IFormatProvider _formatProvider; + readonly MessageTemplate _outputTemplate; + + /// + /// Construct a . + /// + /// A message template describing the + /// output messages. + /// Supplies culture-specific formatting information, or null. + public MessageTemplateTextFormatter(string outputTemplate, IFormatProvider formatProvider) + { + if (outputTemplate == null) throw new ArgumentNullException(nameof(outputTemplate)); + _outputTemplate = new MessageTemplateParser().Parse(outputTemplate); + _formatProvider = formatProvider; + } + + /// + /// Format the log event into the output. + /// + /// The event to format. + /// The output. + public void Format(LogEvent logEvent, TextWriter output) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + if (output == null) throw new ArgumentNullException(nameof(output)); + + foreach (var token in _outputTemplate.Tokens) + { + if (token is TextToken tt) + { + MessageTemplateRenderer.RenderTextToken(tt, output); + continue; + } + + var pt = (PropertyToken)token; + if (pt.PropertyName == OutputProperties.LevelPropertyName) + { + var moniker = LevelOutputFormat.GetLevelMoniker(logEvent.Level, pt.Format); + Padding.Apply(output, moniker, pt.Alignment); + } + else if (pt.PropertyName == OutputProperties.NewLinePropertyName) + { + Padding.Apply(output, Environment.NewLine, pt.Alignment); + } + else if (pt.PropertyName == OutputProperties.ExceptionPropertyName) + { + var exception = logEvent.Exception == null ? "" : logEvent.Exception + Environment.NewLine; + Padding.Apply(output, exception, pt.Alignment); + } + else + { + // In this block, `writer` may be used to buffer output so that + // padding can be applied. + var writer = pt.Alignment.HasValue ? new StringWriter() : output; + + if (pt.PropertyName == OutputProperties.MessagePropertyName) + { + MessageTemplateRenderer.Render(logEvent.MessageTemplate, logEvent.Properties, writer, pt.Format, _formatProvider); + } + else if (pt.PropertyName == OutputProperties.TimestampPropertyName) + { + ScalarValue.Render(logEvent.Timestamp, writer, pt.Format, _formatProvider); + } + else if (pt.PropertyName == OutputProperties.PropertiesPropertyName) + { + PropertiesOutputFormat.Render(logEvent.MessageTemplate, logEvent.Properties, _outputTemplate, writer, pt.Format, _formatProvider); + } + else + { + // If a property is missing, don't render anything (message templates render the raw token here). + LogEventPropertyValue propertyValue; + if (!logEvent.Properties.TryGetValue(pt.PropertyName, out propertyValue)) + continue; + + // If the value is a scalar string, support some additional formats: 'u' for uppercase + // and 'w' for lowercase. + var sv = propertyValue as ScalarValue; + if (sv?.Value is string literalString) + { + var cased = Casing.Format(literalString, pt.Format); + writer.Write(cased); + } + else + { + propertyValue.Render(writer, pt.Format, _formatProvider); + } + } + + if (pt.Alignment.HasValue) + Padding.Apply(output, ((StringWriter)writer).ToString(), pt.Alignment); + } + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LiteralStringValue.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LiteralStringValue.cs new file mode 100644 index 0000000000..081abf534e --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LiteralStringValue.cs @@ -0,0 +1,54 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display.Obsolete +{ + // A special case (non-null) string value for use in output + // templates. Does not apply "quoted" formatting by default. + [Obsolete("Not used by the current output formatting implementation.")] + class LiteralStringValue : LogEventPropertyValue + { + readonly string _value; + + public LiteralStringValue(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + output.Write(Casing.Format(_value, format)); + } + + public override bool Equals(object obj) + { + var sv = obj as LiteralStringValue; + return sv != null && Equals(_value, sv._value); + } + + public override int GetHashCode() + { + return _value.GetHashCode(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventLevelValue.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventLevelValue.cs new file mode 100644 index 0000000000..f4a3945472 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventLevelValue.cs @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; + +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display.Obsolete +{ + [Obsolete("Not used by the current output formatting implementation.")] + class LogEventLevelValue : LogEventPropertyValue + { + readonly LogEventLevel _value; + + public LogEventLevelValue(LogEventLevel value) + { + _value = value; + } + + /// + /// This method will apply only upper or lower case formatting, not fixed width + /// + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + output.Write(LevelOutputFormat.GetLevelMoniker(_value, format)); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertiesValue.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertiesValue.cs new file mode 100644 index 0000000000..1af62aa76f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertiesValue.cs @@ -0,0 +1,45 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display.Obsolete +{ + [Obsolete("Not used by the current output formatting implementation.")] + class LogEventPropertiesValue : LogEventPropertyValue + { + readonly MessageTemplate _template; + readonly IReadOnlyDictionary _properties; + readonly MessageTemplate _outputTemplate; + + public LogEventPropertiesValue(MessageTemplate template, IReadOnlyDictionary properties, MessageTemplate outputTemplate) + { + _template = template; + _properties = properties; + _outputTemplate = outputTemplate; + } + + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + PropertiesOutputFormat.Render(_template, _properties, _outputTemplate, output, format, formatProvider); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertyMessageValue.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertyMessageValue.cs new file mode 100644 index 0000000000..f3078b94a2 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/Obsolete/LogEventPropertyMessageValue.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display.Obsolete +{ + [Obsolete("Not used by the current output formatting implementation.")] + class LogEventPropertyMessageValue : LogEventPropertyValue + { + readonly MessageTemplate _template; + readonly IReadOnlyDictionary _properties; + + public LogEventPropertyMessageValue(MessageTemplate template, IReadOnlyDictionary properties) + { + _template = template; + _properties = properties; + } + + public override void Render(TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + _template.Render(_properties, output, formatProvider); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/OutputProperties.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/OutputProperties.cs new file mode 100644 index 0000000000..74c9aa30c4 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/OutputProperties.cs @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting.Display.Obsolete; + +#pragma warning disable 618 + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display +{ + /// + /// Describes the properties available in standard message template-based + /// output format strings. + /// + internal static class OutputProperties + { + static readonly LiteralStringValue LiteralNewLine = new LiteralStringValue(Environment.NewLine); + + /// + /// The message rendered from the log event. + /// + public const string MessagePropertyName = "Message"; + + /// + /// The timestamp of the log event. + /// + public const string TimestampPropertyName = "Timestamp"; + + /// + /// The level of the log event. + /// + public const string LevelPropertyName = "Level"; + + /// + /// A new line. + /// + public const string NewLinePropertyName = "NewLine"; + + /// + /// The exception associated with the log event. + /// + public const string ExceptionPropertyName = "Exception"; + + /// + /// The properties of the log event. + /// + public const string PropertiesPropertyName = "Properties"; + + /// + /// Create properties from the provided log event. + /// + /// The log event. + /// A dictionary with properties representing the log event. + [Obsolete("These implementation details of output formatting will not be exposed in a future version.")] + public static IReadOnlyDictionary GetOutputProperties(LogEvent logEvent) + { + return GetOutputProperties(logEvent, MessageTemplate.Empty); + } + + /// + /// Create properties from the provided log event. + /// + /// The log event. + /// The output template. + /// A dictionary with properties representing the log event. + internal static IReadOnlyDictionary GetOutputProperties(LogEvent logEvent, MessageTemplate outputTemplate) + { + var result = logEvent.Properties.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + // "Special" output properties like Message will override any properties with the same name + // when used in format strings; this doesn't affect the rendering of the message template, + // which uses only the log event properties. + + result[MessagePropertyName] = new LogEventPropertyMessageValue(logEvent.MessageTemplate, logEvent.Properties); + result[TimestampPropertyName] = new ScalarValue(logEvent.Timestamp); + result[LevelPropertyName] = new LogEventLevelValue(logEvent.Level); + result[NewLinePropertyName] = LiteralNewLine; + result[PropertiesPropertyName] = new LogEventPropertiesValue(logEvent.MessageTemplate, logEvent.Properties, outputTemplate); + + var exception = logEvent.Exception == null ? "" : logEvent.Exception + Environment.NewLine; + result[ExceptionPropertyName] = new LiteralStringValue(exception); + + return result; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/PropertiesOutputFormat.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/PropertiesOutputFormat.cs new file mode 100644 index 0000000000..16b71618cc --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Display/PropertiesOutputFormat.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting.Json; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Display +{ + static class PropertiesOutputFormat + { + static readonly JsonValueFormatter JsonValueFormatter = new JsonValueFormatter("$type"); + + public static void Render(MessageTemplate template, IReadOnlyDictionary properties, MessageTemplate outputTemplate, TextWriter output, string format, IFormatProvider formatProvider = null) + { + if (format?.Contains("j") == true) + { + var sv = new StructureValue(properties + .Where(kvp => !(TemplateContainsPropertyName(template, kvp.Key) || + TemplateContainsPropertyName(outputTemplate, kvp.Key))) + .Select(kvp => new LogEventProperty(kvp.Key, kvp.Value))); + JsonValueFormatter.Format(sv, output); + return; + } + + output.Write("{ "); + + var delim = ""; + foreach (var kvp in properties) + { + if (TemplateContainsPropertyName(template, kvp.Key) || + TemplateContainsPropertyName(outputTemplate, kvp.Key)) + { + continue; + } + + output.Write(delim); + delim = ", "; + output.Write(kvp.Key); + output.Write(": "); + kvp.Value.Render(output, null, formatProvider); + } + + output.Write(" }"); + } + + static bool TemplateContainsPropertyName(MessageTemplate template, string propertyName) + { + if (template.PositionalProperties != null) + { + for (var i = 0; i < template.PositionalProperties.Length; i++) + { + var token = template.PositionalProperties[i]; + if (token.PropertyName == propertyName) + { + return true; + } + } + + return false; + } + + if (template.NamedProperties != null) + { + for (var i = 0; i < template.NamedProperties.Length; i++) + { + var namedProperty = template.NamedProperties[i]; + if (namedProperty.PropertyName == propertyName) + { + return true; + } + } + } + + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/ITextFormatter.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/ITextFormatter.cs new file mode 100644 index 0000000000..9a62e443b3 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/ITextFormatter.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting +{ + /// + /// Formats log events in a textual representation. + /// + internal interface ITextFormatter + { + /// + /// Format the log event into the output. + /// + /// The event to format. + /// The output. + void Format(LogEvent logEvent, TextWriter output); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonFormatter.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonFormatter.cs new file mode 100644 index 0000000000..d2bddfa522 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonFormatter.cs @@ -0,0 +1,454 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Parsing; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Json +{ + /// + /// Formats log events in a simple JSON structure. Instances of this class + /// are safe for concurrent access by multiple threads. + /// + internal class JsonFormatter : ITextFormatter + { + const string ExtensionPointObsoletionMessage = "Extension of JsonFormatter by subclassing is obsolete and will " + + "be removed in a future Serilog version. Write a custom formatter " + + "based on JsonValueFormatter instead. See https://github.com/serilog/serilog/pull/819."; + + // Ignore obsoletion errors + #pragma warning disable 618 + + readonly bool _omitEnclosingObject; + readonly string _closingDelimiter; + readonly bool _renderMessage; + readonly IFormatProvider _formatProvider; + readonly IDictionary> _literalWriters; + + /// + /// Construct a . + /// + /// A string that will be written after each log event is formatted. + /// If null, will be used. + /// If true, the message will be rendered and written to the output as a + /// property named RenderedMessage. + /// Supplies culture-specific formatting information, or null. + public JsonFormatter( + string closingDelimiter = null, + bool renderMessage = false, + IFormatProvider formatProvider = null) + :this(false, closingDelimiter, renderMessage, formatProvider) + { + } + + /// + /// Construct a . + /// + /// If true, the properties of the event will be written to + /// the output without enclosing braces. Otherwise, if false, each event will be written as a well-formed + /// JSON object. + /// A string that will be written after each log event is formatted. + /// If null, will be used. Ignored if + /// is true. + /// If true, the message will be rendered and written to the output as a + /// property named RenderedMessage. + /// Supplies culture-specific formatting information, or null. + [Obsolete("The omitEnclosingObject parameter is obsolete and will be removed in a future Serilog version.")] + public JsonFormatter( + bool omitEnclosingObject, + string closingDelimiter = null, + bool renderMessage = false, + IFormatProvider formatProvider = null) + { + _omitEnclosingObject = omitEnclosingObject; + _closingDelimiter = closingDelimiter ?? Environment.NewLine; + _renderMessage = renderMessage; + _formatProvider = formatProvider; + + _literalWriters = new Dictionary> + { + { typeof(bool), (v, q, w) => WriteBoolean((bool)v, w) }, + { typeof(char), (v, q, w) => WriteString(((char)v).ToString(), w) }, + { typeof(byte), WriteToString }, + { typeof(sbyte), WriteToString }, + { typeof(short), WriteToString }, + { typeof(ushort), WriteToString }, + { typeof(int), WriteToString }, + { typeof(uint), WriteToString }, + { typeof(long), WriteToString }, + { typeof(ulong), WriteToString }, + { typeof(float), (v, q, w) => WriteSingle((float)v, w) }, + { typeof(double), (v, q, w) => WriteDouble((double)v, w) }, + { typeof(decimal), WriteToString }, + { typeof(string), (v, q, w) => WriteString((string)v, w) }, + { typeof(DateTime), (v, q, w) => WriteDateTime((DateTime)v, w) }, + { typeof(DateTimeOffset), (v, q, w) => WriteOffset((DateTimeOffset)v, w) }, + { typeof(ScalarValue), (v, q, w) => WriteLiteral(((ScalarValue)v).Value, w, q) }, + { typeof(SequenceValue), (v, q, w) => WriteSequence(((SequenceValue)v).Elements, w) }, + { typeof(DictionaryValue), (v, q, w) => WriteDictionary(((DictionaryValue)v).Elements, w) }, + { typeof(StructureValue), (v, q, w) => WriteStructure(((StructureValue)v).TypeTag, ((StructureValue)v).Properties, w) }, + }; + } + + /// + /// Format the log event into the output. + /// + /// The event to format. + /// The output. + public void Format(LogEvent logEvent, TextWriter output) + { + if (logEvent == null) throw new ArgumentNullException(nameof(logEvent)); + if (output == null) throw new ArgumentNullException(nameof(output)); + + if (!_omitEnclosingObject) + output.Write("{"); + + var delim = ""; + WriteTimestamp(logEvent.Timestamp, ref delim, output); + WriteLevel(logEvent.Level, ref delim, output); + WriteMessageTemplate(logEvent.MessageTemplate.Text, ref delim, output); + if (_renderMessage) + { + var message = logEvent.RenderMessage(_formatProvider); + WriteRenderedMessage(message, ref delim, output); + } + + if (logEvent.Exception != null) + WriteException(logEvent.Exception, ref delim, output); + + if (logEvent.Properties.Count != 0) + WriteProperties(logEvent.Properties, output); + + var tokensWithFormat = logEvent.MessageTemplate.Tokens + .OfType() + .Where(pt => pt.Format != null) + .GroupBy(pt => pt.PropertyName) + .ToArray(); + + if (tokensWithFormat.Length != 0) + { + WriteRenderings(tokensWithFormat, logEvent.Properties, output); + } + + if (!_omitEnclosingObject) + { + output.Write("}"); + output.Write(_closingDelimiter); + } + } + + /// + /// Adds a writer function for a given type. + /// + /// The type of values, which handles. + /// The function, which writes the values. + [Obsolete(ExtensionPointObsoletionMessage)] + protected void AddLiteralWriter(Type type, Action writer) + { + if (type == null) throw new ArgumentNullException(nameof(type)); + if (writer == null) throw new ArgumentNullException(nameof(writer)); + + _literalWriters[type] = (v, _, w) => writer(v, w); + } + + /// + /// Writes out individual renderings of attached properties + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteRenderings(IGrouping[] tokensWithFormat, IReadOnlyDictionary properties, TextWriter output) + { + output.Write(",\"{0}\":{{", "Renderings"); + WriteRenderingsValues(tokensWithFormat, properties, output); + output.Write("}"); + } + + /// + /// Writes out the values of individual renderings of attached properties + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteRenderingsValues(IGrouping[] tokensWithFormat, IReadOnlyDictionary properties, TextWriter output) + { + var rdelim = ""; + foreach (var ptoken in tokensWithFormat) + { + output.Write(rdelim); + rdelim = ","; + output.Write("\""); + output.Write(ptoken.Key); + output.Write("\":["); + + var fdelim = ""; + foreach (var format in ptoken) + { + output.Write(fdelim); + fdelim = ","; + + output.Write("{"); + var eldelim = ""; + + WriteJsonProperty("Format", format.Format, ref eldelim, output); + + var sw = new StringWriter(); + MessageTemplateRenderer.RenderPropertyToken(format, properties, sw, _formatProvider, true, false); + WriteJsonProperty("Rendering", sw.ToString(), ref eldelim, output); + + output.Write("}"); + } + + output.Write("]"); + } + } + + /// + /// Writes out the attached properties + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteProperties(IReadOnlyDictionary properties, TextWriter output) + { + output.Write(",\"{0}\":{{", "Properties"); + WritePropertiesValues(properties, output); + output.Write("}"); + } + + /// + /// Writes out the attached properties values + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WritePropertiesValues(IReadOnlyDictionary properties, TextWriter output) + { + var precedingDelimiter = ""; + foreach (var property in properties) + { + WriteJsonProperty(property.Key, property.Value, ref precedingDelimiter, output); + } + } + + /// + /// Writes out the attached exception + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteException(Exception exception, ref string delim, TextWriter output) + { + WriteJsonProperty("Exception", exception, ref delim, output); + } + + /// + /// (Optionally) writes out the rendered message + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteRenderedMessage(string message, ref string delim, TextWriter output) + { + WriteJsonProperty("RenderedMessage", message, ref delim, output); + } + + /// + /// Writes out the message template for the logevent. + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteMessageTemplate(string template, ref string delim, TextWriter output) + { + WriteJsonProperty("MessageTemplate", template, ref delim, output); + } + + /// + /// Writes out the log level + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteLevel(LogEventLevel level, ref string delim, TextWriter output) + { + WriteJsonProperty("Level", level, ref delim, output); + } + + /// + /// Writes out the log timestamp + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteTimestamp(DateTimeOffset timestamp, ref string delim, TextWriter output) + { + WriteJsonProperty("Timestamp", timestamp, ref delim, output); + } + + /// + /// Writes out a structure property + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteStructure(string typeTag, IEnumerable properties, TextWriter output) + { + output.Write("{"); + + var delim = ""; + if (typeTag != null) + WriteJsonProperty("_typeTag", typeTag, ref delim, output); + + foreach (var property in properties) + WriteJsonProperty(property.Name, property.Value, ref delim, output); + + output.Write("}"); + } + + /// + /// Writes out a sequence property + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteSequence(IEnumerable elements, TextWriter output) + { + output.Write("["); + var delim = ""; + foreach (var value in elements) + { + output.Write(delim); + delim = ","; + WriteLiteral(value, output); + } + output.Write("]"); + } + + /// + /// Writes out a dictionary + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteDictionary(IReadOnlyDictionary elements, TextWriter output) + { + output.Write("{"); + var delim = ""; + foreach (var e in elements) + { + output.Write(delim); + delim = ","; + WriteLiteral(e.Key, output, true); + output.Write(":"); + WriteLiteral(e.Value, output); + } + output.Write("}"); + } + + /// + /// Writes out a json property with the specified value on output writer + /// + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteJsonProperty(string name, object value, ref string precedingDelimiter, TextWriter output) + { + output.Write(precedingDelimiter); + output.Write("\""); + output.Write(name); + output.Write("\":"); + WriteLiteral(value, output); + precedingDelimiter = ","; + } + + /// + /// Allows a subclass to write out objects that have no configured literal writer. + /// + /// The value to be written as a json construct + /// The writer to write on + [Obsolete(ExtensionPointObsoletionMessage)] + protected virtual void WriteLiteralValue(object value, TextWriter output) + { + WriteString(value.ToString(), output); + } + + void WriteLiteral(object value, TextWriter output, bool forceQuotation = false) + { + if (value == null) + { + output.Write("null"); + return; + } + + Action writer; + if (_literalWriters.TryGetValue(value.GetType(), out writer)) + { + writer(value, forceQuotation, output); + return; + } + + WriteLiteralValue(value, output); + } + + static void WriteToString(object number, bool quote, TextWriter output) + { + if (quote) output.Write('"'); + + var fmt = number as IFormattable; + if (fmt != null) + output.Write(fmt.ToString(null, CultureInfo.InvariantCulture)); + else + output.Write(number.ToString()); + + if (quote) output.Write('"'); + } + + static void WriteBoolean(bool value, TextWriter output) + { + output.Write(value ? "true" : "false"); + } + + static void WriteSingle(float value, TextWriter output) + { + output.Write(value.ToString("R", CultureInfo.InvariantCulture)); + } + + static void WriteDouble(double value, TextWriter output) + { + output.Write(value.ToString("R", CultureInfo.InvariantCulture)); + } + + static void WriteOffset(DateTimeOffset value, TextWriter output) + { + output.Write("\""); + output.Write(value.ToString("o")); + output.Write("\""); + } + + static void WriteDateTime(DateTime value, TextWriter output) + { + output.Write("\""); + output.Write(value.ToString("o")); + output.Write("\""); + } + + static void WriteString(string value, TextWriter output) + { + JsonValueFormatter.WriteQuotedJsonString(value, output); + } + + /// + /// Perform simple JSON string escaping on . + /// + /// A raw string. + /// A JSON-escaped version of . + [Obsolete("Use JsonValueFormatter.WriteQuotedJsonString() instead."), EditorBrowsable(EditorBrowsableState.Never)] + public static string Escape(string s) + { + if (s == null) return null; + + var escapedResult = new StringWriter(); + JsonValueFormatter.WriteQuotedJsonString(s, escapedResult); + var quoted = escapedResult.ToString(); + return quoted.Substring(1, quoted.Length - 2); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonValueFormatter.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonValueFormatter.cs new file mode 100644 index 0000000000..a7516d6925 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Json/JsonValueFormatter.cs @@ -0,0 +1,368 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Data; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Json +{ + /// + /// Converts Serilog's structured property value format into JSON. + /// + internal class JsonValueFormatter : LogEventPropertyValueVisitor + { + readonly string _typeTagName; + + const string DefaultTypeTagName = "_typeTag"; + + /// + /// Construct a . + /// + /// When serializing structured (object) values, + /// the property name to use for the Serilog field + /// in the resulting JSON. If null, no type tag field will be written. The default is + /// "_typeTag". + public JsonValueFormatter(string typeTagName = DefaultTypeTagName) + { + _typeTagName = typeTagName; + } + + /// + /// Format as JSON to . + /// + /// The value to format + /// The output + public void Format(LogEventPropertyValue value, TextWriter output) + { + // Parameter order of ITextFormatter is the reverse of the visitor one. + // In this class, public methods and methods with Format*() names use the + // (x, output) parameter naming convention. + Visit(output, value); + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override bool VisitScalarValue(TextWriter state, ScalarValue scalar) + { + if (scalar == null) throw new ArgumentNullException(nameof(scalar)); + FormatLiteralValue(scalar.Value, state); + return false; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override bool VisitSequenceValue(TextWriter state, SequenceValue sequence) + { + if (sequence == null) throw new ArgumentNullException(nameof(sequence)); + state.Write('['); + var delim = ""; + for (var i = 0; i < sequence.Elements.Count; i++) + { + state.Write(delim); + delim = ","; + Visit(state, sequence.Elements[i]); + } + state.Write(']'); + return false; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override bool VisitStructureValue(TextWriter state, StructureValue structure) + { + state.Write('{'); + + var delim = ""; + + for (var i = 0; i < structure.Properties.Count; i++) + { + state.Write(delim); + delim = ","; + var prop = structure.Properties[i]; + WriteQuotedJsonString(prop.Name, state); + state.Write(':'); + Visit(state, prop.Value); + } + + if (_typeTagName != null && structure.TypeTag != null) + { + state.Write(delim); + WriteQuotedJsonString(_typeTagName, state); + state.Write(':'); + WriteQuotedJsonString(structure.TypeTag, state); + } + + state.Write('}'); + return false; + } + + /// + /// Visit a value. + /// + /// Operation state. + /// The value to visit. + /// The result of visiting . + protected override bool VisitDictionaryValue(TextWriter state, DictionaryValue dictionary) + { + state.Write('{'); + var delim = ""; + foreach (var element in dictionary.Elements) + { + state.Write(delim); + delim = ","; + WriteQuotedJsonString((element.Key.Value ?? "null").ToString(), state); + state.Write(':'); + Visit(state, element.Value); + } + state.Write('}'); + return false; + } + + /// + /// Write a literal as a single JSON value, e.g. as a number or string. Override to + /// support more value types. Don't write arrays/structures through this method - the + /// active destructuring policies have already indicated the value should be scalar at + /// this point. + /// + /// The value to write. + /// The output + protected virtual void FormatLiteralValue(object value, TextWriter output) + { + if (value == null) + { + FormatNullValue(output); + return; + } + + // Although the linear switch-on-type has apparently worse algorithmic performance than the O(1) + // dictionary lookup alternative, in practice, it's much to make a few equality comparisons + // than the hash/bucket dictionary lookup, and since most data will be string (one comparison), + // numeric (a handful) or an object (two comparsions) the real-world performance of the code + // as written is as fast or faster. + + var str = value as string; + if (str != null) + { + FormatStringValue(str, output); + return; + } + + if (value is ValueType) + { + if (value is int || value is uint || value is long || value is ulong || value is decimal || + value is byte || value is sbyte || value is short || value is ushort) + { + FormatExactNumericValue((IFormattable)value, output); + return; + } + + if (value is double) + { + FormatDoubleValue((double)value, output); + return; + } + + if (value is float) + { + FormatFloatValue((float)value, output); + return; + } + + if (value is bool) + { + FormatBooleanValue((bool)value, output); + return; + } + + if (value is char) + { + FormatStringValue(value.ToString(), output); + return; + } + + if (value is DateTime || value is DateTimeOffset) + { + FormatDateTimeValue((IFormattable)value, output); + return; + } + + if (value is TimeSpan) + { + FormatTimeSpanValue((TimeSpan)value, output); + return; + } + } + + FormatLiteralObjectValue(value, output); + } + + static void FormatBooleanValue(bool value, TextWriter output) + { + output.Write(value ? "true" : "false"); + } + + static void FormatFloatValue(float value, TextWriter output) + { + if (float.IsNaN(value) || float.IsInfinity(value)) + { + FormatStringValue(value.ToString(CultureInfo.InvariantCulture), output); + return; + } + + output.Write(value.ToString("R", CultureInfo.InvariantCulture)); + } + + static void FormatDoubleValue(double value, TextWriter output) + { + if (double.IsNaN(value) || double.IsInfinity(value)) + { + FormatStringValue(value.ToString(CultureInfo.InvariantCulture), output); + return; + } + + output.Write(value.ToString("R", CultureInfo.InvariantCulture)); + } + + static void FormatExactNumericValue(IFormattable value, TextWriter output) + { + output.Write(value.ToString(null, CultureInfo.InvariantCulture)); + } + + static void FormatDateTimeValue(IFormattable value, TextWriter output) + { + output.Write('\"'); + output.Write(value.ToString("O", CultureInfo.InvariantCulture)); + output.Write('\"'); + } + + static void FormatTimeSpanValue(TimeSpan value, TextWriter output) + { + output.Write('\"'); + output.Write(value.ToString()); + output.Write('\"'); + } + + static void FormatLiteralObjectValue(object value, TextWriter output) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + FormatStringValue(value.ToString(), output); + } + + static void FormatStringValue(string str, TextWriter output) + { + WriteQuotedJsonString(str, output); + } + + static void FormatNullValue(TextWriter output) + { + output.Write("null"); + } + + /// + /// Write a valid JSON string literal, escaping as necessary. + /// + /// The string value to write. + /// The output. + public static void WriteQuotedJsonString(string str, TextWriter output) + { + output.Write('\"'); + + var cleanSegmentStart = 0; + var anyEscaped = false; + + for (var i = 0; i < str.Length; ++i) + { + var c = str[i]; + if (c < (char)32 || c == '\\' || c == '"') + { + anyEscaped = true; + + output.Write(str.Substring(cleanSegmentStart, i - cleanSegmentStart)); + cleanSegmentStart = i + 1; + + switch (c) + { + case '"': + { + output.Write("\\\""); + break; + } + case '\\': + { + output.Write("\\\\"); + break; + } + case '\n': + { + output.Write("\\n"); + break; + } + case '\r': + { + output.Write("\\r"); + break; + } + case '\f': + { + output.Write("\\f"); + break; + } + case '\t': + { + output.Write("\\t"); + break; + } + default: + { + output.Write("\\u"); + output.Write(((int)c).ToString("X4")); + break; + } + } + } + } + + if (anyEscaped) + { + if (cleanSegmentStart != str.Length) + output.Write(str.Substring(cleanSegmentStart)); + } + else + { + output.Write(str); + } + + output.Write('\"'); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Formatting/Raw/RawFormatter.cs b/src/Datadog.Trace/Vendors/Serilog/Formatting/Raw/RawFormatter.cs new file mode 100644 index 0000000000..dc65b8423a --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Formatting/Raw/RawFormatter.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Formatting.Raw +{ + /// + /// Formats log events as a raw dump of the message template and properties. + /// + [Obsolete("A JSON-based formatter such as `Serilog.Formatting.Compact.CompactJsonFormatter` is recommended for this task.")] + internal class RawFormatter : ITextFormatter + { + /// + /// Format the log event into the output. + /// + /// The event to format. + /// The output. + public void Format(LogEvent logEvent, TextWriter output) + { + output.Write("[" + logEvent.Timestamp + "] " + logEvent.Level + ": \""); + output.Write(logEvent.MessageTemplate); + output.WriteLine("\""); + if (logEvent.Exception != null) + output.WriteLine(logEvent.Exception); + foreach (var property in logEvent.Properties) + { + output.Write(property.Key + " = "); + property.Value.Render(output); + output.WriteLine(); + } + output.WriteLine(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/ILogger.cs b/src/Datadog.Trace/Vendors/Serilog/ILogger.cs new file mode 100644 index 0000000000..c8d2e85ac8 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/ILogger.cs @@ -0,0 +1,948 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog +{ + /// + /// The core Serilog logging API, used for writing log events. + /// + /// + /// var log = new LoggerConfiguration() + /// .WriteTo.Console() + /// .CreateLogger(); + /// + /// var thing = "World"; + /// log.Information("Hello, {Thing}!", thing); + /// + /// + /// The methods on (and its static sibling ) are guaranteed + /// never to throw exceptions. Methods on all other types may. + /// + internal interface ILogger + { + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enricher that applies in the context. + /// A logger that will enrich log events as specified. + ILogger ForContext(ILogEventEnricher enricher); + + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enrichers that apply in the context. + /// A logger that will enrich log events as specified. + ILogger ForContext(IEnumerable enrichers); + + /// + /// Create a logger that enriches log events with the specified property. + /// + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// A logger that will enrich log events as specified. + ILogger ForContext(string propertyName, object value, bool destructureObjects = false); + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + ILogger ForContext(); + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + ILogger ForContext(Type source); + + /// + /// Write an event to the log. + /// + /// The event to write. + void Write(LogEvent logEvent); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, string messageTemplate); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, Exception exception, string messageTemplate); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Determine if events at the specified level will be passed through + /// to the log sinks. + /// + /// Level to check. + /// True if the level is enabled; otherwise, false. + bool IsEnabled(LogEventLevel level); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(Exception exception, string messageTemplate); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Verbose(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(Exception exception, string messageTemplate); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Debug(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(Exception exception, string messageTemplate); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Information(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(Exception exception, string messageTemplate); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Warning(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate); + + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Error(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(string messageTemplate); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(string messageTemplate, params object[] propertyValues); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(Exception exception, string messageTemplate); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(Exception exception, string messageTemplate, T propertyValue); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2); + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + void Fatal(Exception exception, string messageTemplate, params object[] propertyValues); + + /// + /// Uses configured scalar conversion and destructuring rules to bind a set of properties to a + /// message template. Returns false if the template or values are invalid (ILogger + /// methods never throw exceptions). + /// + /// Message template describing an event. + /// Objects positionally formatted into the message template. + /// The internal representation of the template, which may be used to + /// render the as text. + /// Captured properties from the template and . + /// + /// MessageTemplate template; + /// IEnumerable<LogEventProperty> properties>; + /// if (Log.BindMessageTemplate("Hello, {Name}!", new[] { "World" }, out template, out properties) + /// { + /// var propsByName = properties.ToDictionary(p => p.Name, p => p.Value); + /// Console.WriteLine(template.Render(propsByName, null)); + /// // -> "Hello, World!" + /// } + /// + [MessageTemplateFormatMethod("messageTemplate")] + bool BindMessageTemplate(string messageTemplate, object[] propertyValues, + out MessageTemplate parsedTemplate, out IEnumerable boundProperties); + + /// + /// Uses configured scalar conversion and destructuring rules to bind a property value to its captured + /// representation. + /// + /// True if the property could be bound, otherwise false (ILogger + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// The resulting property. + /// methods never throw exceptions). + bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property); + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Log.cs b/src/Datadog.Trace/Vendors/Serilog/Log.cs new file mode 100644 index 0000000000..83a30aef6b --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Log.cs @@ -0,0 +1,1209 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Threading; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Pipeline; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog +{ + /// + /// An optional static entry point for logging that can be easily referenced + /// by different parts of an application. To configure the + /// set the Logger static property to a logger instance. + /// + /// + /// Log.Logger = new LoggerConfiguration() + /// .WithConsoleSink() + /// .CreateLogger(); + /// + /// var thing = "World"; + /// Log.Logger.Information("Hello, {Thing}!", thing); + /// + /// + /// The methods on (and its dynamic sibling ) are guaranteed + /// never to throw exceptions. Methods on all other types may. + /// + internal static class Log + { + static ILogger _logger = SilentLogger.Instance; + + /// + /// The globally-shared logger. + /// + /// + public static ILogger Logger + { + get { return _logger; } + set + { + if (value == null) throw new ArgumentNullException(nameof(value)); + _logger = value; + } + } + + /// + /// Resets to the default and disposes the original if possible + /// + public static void CloseAndFlush() + { + ILogger logger = Interlocked.Exchange(ref _logger, SilentLogger.Instance); + + (logger as IDisposable)?.Dispose(); + } + + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enricher that applies in the context. + /// A logger that will enrich log events as specified. + public static ILogger ForContext(ILogEventEnricher enricher) + { + return Logger.ForContext(enricher); + } + + /// + /// Create a logger that enriches log events via the provided enrichers. + /// + /// Enrichers that apply in the context. + /// A logger that will enrich log events as specified. + public static ILogger ForContext(ILogEventEnricher[] enrichers) + { + return Logger.ForContext(enrichers); + } + + /// + /// Create a logger that enriches log events with the specified property. + /// + /// A logger that will enrich log events as specified. + public static ILogger ForContext(string propertyName, object value, bool destructureObjects = false) + { + return Logger.ForContext(propertyName, value, destructureObjects); + } + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + public static ILogger ForContext() + { + return Logger.ForContext(); + } + + /// + /// Create a logger that marks log events as being from the specified + /// source type. + /// + /// Type generating log messages in the context. + /// A logger that will enrich log events as specified. + public static ILogger ForContext(Type source) + { + return Logger.ForContext(source); + } + + /// + /// Write an event to the log. + /// + /// The event to write. + public static void Write(LogEvent logEvent) + { + Logger.Write(logEvent); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, string messageTemplate) + { + Logger.Write(level, messageTemplate); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, string messageTemplate, T propertyValue) + { + Logger.Write(level, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Logger.Write(level, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Logger.Write(level, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the specified level. + /// + /// The level of the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, string messageTemplate, params object[] propertyValues) + { + Logger.Write(level, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, Exception exception, string messageTemplate) + { + Logger.Write(level, exception, messageTemplate); + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, Exception exception, string messageTemplate, T propertyValue) + { + Logger.Write(level, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Logger.Write(level, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the specified level and associated exception. + /// + /// The level of the event. + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + [MessageTemplateFormatMethod("messageTemplate")] + public static void Write(LogEventLevel level, Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Write(level, exception, messageTemplate, propertyValues); + } + + /// + /// Determine if events at the specified level will be passed through + /// to the log sinks. + /// + /// Level to check. + /// True if the level is enabled; otherwise, false. + public static bool IsEnabled(LogEventLevel level) + { + return Logger.IsEnabled(level); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(string messageTemplate) + { + Write(LogEventLevel.Verbose, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Verbose, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose("Staring into space, wondering if we're alone."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(string messageTemplate, params object[] propertyValues) + { + Logger.Verbose(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Verbose, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Verbose, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Verbose(ex, "Staring into space, wondering where this comet came from."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Verbose(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Verbose(exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(string messageTemplate) + { + Write(LogEventLevel.Debug, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Debug, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug("Starting up at {StartedAt}.", DateTime.Now); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(string messageTemplate, params object[] propertyValues) + { + Logger.Debug(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Debug, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Debug, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Debug(ex, "Swallowing a mundane exception."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Debug(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Debug(exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(string messageTemplate) + { + Write(LogEventLevel.Information, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Information, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information("Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(string messageTemplate, params object[] propertyValues) + { + Logger.Information(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Information, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Information, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Information(ex, "Processed {RecordCount} records in {TimeMS}.", records.Length, sw.ElapsedMilliseconds); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Information(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Information(exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(string messageTemplate) + { + Write(LogEventLevel.Warning, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Warning, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning("Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(string messageTemplate, params object[] propertyValues) + { + Logger.Warning(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Warning, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Warning, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Warning(ex, "Skipped {SkipCount} records.", skippedRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Warning(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Warning(exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(string messageTemplate) + { + Write(LogEventLevel.Error, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Error, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error("Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(string messageTemplate, params object[] propertyValues) + { + Logger.Error(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Error, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Error, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Error(ex, "Failed {ErrorCount} records.", brokenRecords.Length); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Error(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Error(exception, messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(string messageTemplate) + { + Write(LogEventLevel.Fatal, messageTemplate); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Fatal, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level. + /// + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal("Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(string messageTemplate, params object[] propertyValues) + { + Logger.Fatal(messageTemplate, propertyValues); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(Exception exception, string messageTemplate) + { + Write(LogEventLevel.Fatal, exception, messageTemplate); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(Exception exception, string messageTemplate, T propertyValue) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// Object positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(Exception exception, string messageTemplate, T0 propertyValue0, T1 propertyValue1, T2 propertyValue2) + { + Write(LogEventLevel.Fatal, exception, messageTemplate, propertyValue0, propertyValue1, propertyValue2); + } + + /// + /// Write a log event with the level and associated exception. + /// + /// Exception related to the event. + /// Message template describing the event. + /// Objects positionally formatted into the message template. + /// + /// Log.Fatal(ex, "Process terminating."); + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static void Fatal(Exception exception, string messageTemplate, params object[] propertyValues) + { + Logger.Fatal(exception, messageTemplate, propertyValues); + } + + /// + /// Uses configured scalar conversion and destructuring rules to bind a set of properties to a + /// message template. Returns false if the template or values are invalid (ILogger + /// methods never throw exceptions). + /// + /// Message template describing an event. + /// Objects positionally formatted into the message template. + /// The internal representation of the template, which may be used to + /// render the as text. + /// Captured properties from the template and . + /// + /// MessageTemplate template; + /// IEnumerable<LogEventProperty> properties>; + /// if (Log.BindMessageTemplate("Hello, {Name}!", new[] { "World" }, out template, out properties) + /// { + /// var propsByName = properties.ToDictionary(p => p.Name, p => p.Value); + /// Console.WriteLine(template.Render(propsByName, null)); + /// // -> "Hello, World!" + /// } + /// + [MessageTemplateFormatMethod("messageTemplate")] + public static bool BindMessageTemplate(string messageTemplate, object[] propertyValues, out MessageTemplate parsedTemplate, out IEnumerable boundProperties) + { + return Logger.BindMessageTemplate(messageTemplate, propertyValues, out parsedTemplate, out boundProperties); + } + + /// + /// Uses configured scalar conversion and destructuring rules to bind a property value to its captured + /// representation. + /// + /// True if the property could be bound, otherwise false (ILogger + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// The resulting property. + /// methods never throw exceptions). + public static bool BindProperty(string propertyName, object value, bool destructureObjects, out LogEventProperty property) + { + return Logger.BindProperty(propertyName, value, destructureObjects, out property); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/LoggerConfiguration.cs b/src/Datadog.Trace/Vendors/Serilog/LoggerConfiguration.cs new file mode 100644 index 0000000000..dcb6ca71a6 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/LoggerConfiguration.cs @@ -0,0 +1,208 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Capturing; +using Datadog.Trace.Vendors.Serilog.Configuration; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Core.Enrichers; +using Datadog.Trace.Vendors.Serilog.Core.Sinks; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog +{ + /// + /// Configuration object for creating instances. + /// + internal class LoggerConfiguration + { + readonly List _logEventSinks = new List(); + readonly List _auditSinks = new List(); + readonly List _enrichers = new List(); + readonly List _filters = new List(); + readonly List _additionalScalarTypes = new List(); + readonly List _additionalDestructuringPolicies = new List(); + readonly Dictionary _overrides = new Dictionary(); + LogEventLevel _minimumLevel = LogEventLevel.Information; + LoggingLevelSwitch _levelSwitch; + int _maximumDestructuringDepth = 10; + int _maximumStringLength = int.MaxValue; + int _maximumCollectionCount = int.MaxValue; + bool _loggerCreated; + + /// + /// Construct a . + /// + public LoggerConfiguration() + { + WriteTo = new LoggerSinkConfiguration(this, s => _logEventSinks.Add(s), ApplyInheritedConfiguration); + } + + void ApplyInheritedConfiguration(LoggerConfiguration child) + { + if (_levelSwitch != null) + child.MinimumLevel.ControlledBy(_levelSwitch); + else + child.MinimumLevel.Is(_minimumLevel); + } + + /// + /// Configures the sinks that log events will be emitted to. + /// + public LoggerSinkConfiguration WriteTo { get; internal set; } + + /// + /// Configures sinks for auditing, instead of regular (safe) logging. When auditing is used, + /// exceptions from sinks and any intermediate filters propagate back to the caller. Most callers + /// should use instead. + /// + /// + /// Not all sinks are compatible with transactional auditing requirements (many will use asynchronous + /// batching to improve write throughput and latency). Sinks need to opt-in to auditing support by + /// extending , though the generic + /// method allows any sink class to be adapted for auditing. + /// + public LoggerAuditSinkConfiguration AuditTo => new LoggerAuditSinkConfiguration(this, s => _auditSinks.Add(s), ApplyInheritedConfiguration); + + /// + /// Configures the minimum level at which events will be passed to sinks. If + /// not specified, only events at the + /// level and above will be passed through. + /// + /// Configuration object allowing method chaining. + public LoggerMinimumLevelConfiguration MinimumLevel + { + get + { + return new LoggerMinimumLevelConfiguration(this, + l => + { + _minimumLevel = l; + _levelSwitch = null; + }, + sw => _levelSwitch = sw, + (s, lls) => _overrides[s] = lls); + } + } + + /// + /// Configures enrichment of s. Enrichers can add, remove and + /// modify the properties associated with events. + /// + public LoggerEnrichmentConfiguration Enrich => new LoggerEnrichmentConfiguration(this, e => _enrichers.Add(e)); + + /// + /// Configures global filtering of s. + /// + public LoggerFilterConfiguration Filter => new LoggerFilterConfiguration(this, f => _filters.Add(f)); + + /// + /// Configures destructuring of message template parameters. + /// + public LoggerDestructuringConfiguration Destructure + { + get + { + return new LoggerDestructuringConfiguration( + this, + _additionalScalarTypes.Add, + _additionalDestructuringPolicies.Add, + depth => _maximumDestructuringDepth = depth, + length => _maximumStringLength = length, + count => _maximumCollectionCount = count); + } + } + + /// + /// Apply external settings to the logger configuration. + /// + public LoggerSettingsConfiguration ReadFrom => new LoggerSettingsConfiguration(this); + + /// + /// Create a logger using the configured sinks, enrichers and minimum level. + /// + /// The logger. + /// To free resources held by sinks ahead of program shutdown, + /// the returned logger may be cast to and + /// disposed. + public Logger CreateLogger() + { + if (_loggerCreated) + throw new InvalidOperationException("CreateLogger() was previously called and can only be called once."); + _loggerCreated = true; + + ILogEventSink sink = new SafeAggregateSink(_logEventSinks); + + var auditing = _auditSinks.Any(); + if (auditing) + sink = new AggregateSink(new[] { sink }.Concat(_auditSinks)); + + if (_filters.Any()) + { + // A throwing filter could drop an auditable event, so exceptions in filters must be propagated + // if auditing is used. + sink = new FilteringSink(sink, _filters, auditing); + } + + var converter = new PropertyValueConverter( + _maximumDestructuringDepth, + _maximumStringLength, + _maximumCollectionCount, + _additionalScalarTypes, + _additionalDestructuringPolicies, + auditing); + var processor = new MessageTemplateProcessor(converter); + + ILogEventEnricher enricher; + switch (_enrichers.Count) + { + case 0: + // Should be a rare case, so no problem making that extra interface dispatch. + enricher = new EmptyEnricher(); + break; + case 1: + enricher = _enrichers[0]; + break; + default: + enricher = new SafeAggregateEnricher(_enrichers); + break; + } + + LevelOverrideMap overrideMap = null; + if (_overrides.Count != 0) + { + overrideMap = new LevelOverrideMap(_overrides, _minimumLevel, _levelSwitch); + } + + var disposableSinks = _logEventSinks.Concat(_auditSinks).OfType().ToArray(); + void Dispose() + { + foreach (var disposable in disposableSinks) + { + disposable.Dispose(); + } + } + + return _levelSwitch == null ? + new Logger(processor, _minimumLevel, sink, enricher, Dispose, overrideMap) : + new Logger(processor, _levelSwitch, sink, enricher, Dispose, overrideMap); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/LoggerExtensions.cs b/src/Datadog.Trace/Vendors/Serilog/LoggerExtensions.cs new file mode 100644 index 0000000000..46751c6147 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/LoggerExtensions.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog +{ + /// + /// Extends with additional methods. + /// + internal static class LoggerExtensions + { + /// + /// Create a logger that enriches log events when the specified level is enabled. + /// + /// The type of the property value. + /// The logger. + /// The log event level used to determine if log is enriched with property. + /// The name of the property. Must be non-empty. + /// The property value. + /// If true, the value will be serialized as a structured + /// object if possible; if false, the object will be recorded as a scalar or simple array. + /// A logger that will enrich log events as specified. + /// + public static ILogger ForContext( + this ILogger logger, + LogEventLevel level, + string propertyName, + TValue value, + bool destructureObjects = false) + { + if (logger == null) + throw new ArgumentNullException(nameof(logger)); + + return logger.IsEnabled(level) + ? logger.ForContext(propertyName, value, destructureObjects) + : logger; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/Alignment.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/Alignment.cs new file mode 100644 index 0000000000..9b1903dc70 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/Alignment.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// A structure representing the alignment settings to apply when rendering a property. + /// + internal struct Alignment + { + /// + /// Initializes a new instance of . + /// + /// The text alignment direction. + /// The width of the text, in characters. + public Alignment(AlignmentDirection direction, int width) + { + Direction = direction; + Width = width; + } + + /// + /// The text alignment direction. + /// + public AlignmentDirection Direction { get; } + + /// + /// The width of the text. + /// + public int Width { get; } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/AlignmentDirection.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/AlignmentDirection.cs new file mode 100644 index 0000000000..f322e93b0f --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/AlignmentDirection.cs @@ -0,0 +1,35 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// Defines the direction of the alignment. + /// + internal enum AlignmentDirection + { + /// + /// Text will be left-aligned. + /// + Left, + /// + /// Text will be right-aligned. + /// + Right + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/Destructuring.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/Destructuring.cs new file mode 100644 index 0000000000..ca68b0cbc0 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/Destructuring.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// Instructs the logger on how to store information about provided + /// parameters. + /// + internal enum Destructuring + { + /// + /// Convert known types and objects to scalars, arrays to sequences. + /// + Default, + + /// + /// Convert all types to scalar strings. Prefix name with '$'. + /// + Stringify, + + /// + /// Convert known types to scalars, destructure objects and collections + /// into sequences and structures. Prefix name with '@'. + /// + Destructure + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateParser.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateParser.cs new file mode 100644 index 0000000000..86b7c52d8b --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateParser.cs @@ -0,0 +1,309 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Text; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// Parses message template strings into sequences of text or property + /// tokens. + /// + internal class MessageTemplateParser : IMessageTemplateParser + { + /// + /// Parse the supplied message template. + /// + /// The message template to parse. + /// A sequence of text or property tokens. Where the template + /// is not syntactically valid, text tokens will be returned. The parser + /// will make a best effort to extract valid property tokens even in the + /// presence of parsing issues. + public MessageTemplate Parse(string messageTemplate) + { + if (messageTemplate == null) + throw new ArgumentNullException(nameof(messageTemplate)); + return new MessageTemplate(messageTemplate, Tokenize(messageTemplate)); + } + + static IEnumerable Tokenize(string messageTemplate) + { + if (messageTemplate.Length == 0) + { + yield return new TextToken("", 0); + yield break; + } + + var nextIndex = 0; + while (true) + { + var beforeText = nextIndex; + var tt = ParseTextToken(nextIndex, messageTemplate, out nextIndex); + if (nextIndex > beforeText) + yield return tt; + + if (nextIndex == messageTemplate.Length) + yield break; + + var beforeProp = nextIndex; + var pt = ParsePropertyToken(nextIndex, messageTemplate, out nextIndex); + if (beforeProp < nextIndex) + yield return pt; + + if (nextIndex == messageTemplate.Length) + yield break; + } + } + + static MessageTemplateToken ParsePropertyToken(int startAt, string messageTemplate, out int next) + { + var first = startAt; + startAt++; + while (startAt < messageTemplate.Length && IsValidInPropertyTag(messageTemplate[startAt])) + startAt++; + + if (startAt == messageTemplate.Length || messageTemplate[startAt] != '}') + { + next = startAt; + return new TextToken(messageTemplate.Substring(first, next - first), first); + } + + next = startAt + 1; + + var rawText = messageTemplate.Substring(first, next - first); + var tagContent = rawText.Substring(1, next - (first + 2)); + if (tagContent.Length == 0) + return new TextToken(rawText, first); + + string propertyNameAndDestructuring, format, alignment; + if (!TrySplitTagContent(tagContent, out propertyNameAndDestructuring, out format, out alignment)) + return new TextToken(rawText, first); + + var propertyName = propertyNameAndDestructuring; + var destructuring = Destructuring.Default; + if (propertyName.Length != 0 && TryGetDestructuringHint(propertyName[0], out destructuring)) + propertyName = propertyName.Substring(1); + + if (propertyName.Length == 0) + return new TextToken(rawText, first); + + for (var i = 0; i < propertyName.Length; ++i) + { + var c = propertyName[i]; + if (!IsValidInPropertyName(c)) + return new TextToken(rawText, first); + } + + if (format != null) + { + for (var i = 0; i < format.Length; ++i) + { + var c = format[i]; + if (!IsValidInFormat(c)) + return new TextToken(rawText, first); + } + } + + Alignment? alignmentValue = null; + if (alignment != null) + { + for (var i = 0; i < alignment.Length; ++i) + { + var c = alignment[i]; + if (!IsValidInAlignment(c)) + return new TextToken(rawText, first); + } + + var lastDash = alignment.LastIndexOf('-'); + if (lastDash > 0) + return new TextToken(rawText, first); + + var width = 0; + if (!int.TryParse(lastDash == -1 ? alignment : alignment.Substring(1), out width) || width == 0) + return new TextToken(rawText, first); + + var direction = lastDash == -1 ? + AlignmentDirection.Right : + AlignmentDirection.Left; + + alignmentValue = new Alignment(direction, width); + } + + return new PropertyToken( + propertyName, + rawText, + format, + alignmentValue, + destructuring, + first); + } + + static bool TrySplitTagContent(string tagContent, out string propertyNameAndDestructuring, out string format, out string alignment) + { + var formatDelim = tagContent.IndexOf(':'); + var alignmentDelim = tagContent.IndexOf(','); + if (formatDelim == -1 && alignmentDelim == -1) + { + propertyNameAndDestructuring = tagContent; + format = null; + alignment = null; + } + else + { + if (alignmentDelim == -1 || (formatDelim != -1 && alignmentDelim > formatDelim)) + { + propertyNameAndDestructuring = tagContent.Substring(0, formatDelim); + format = formatDelim == tagContent.Length - 1 ? + null : + tagContent.Substring(formatDelim + 1); + alignment = null; + } + else + { + propertyNameAndDestructuring = tagContent.Substring(0, alignmentDelim); + if (formatDelim == -1) + { + if (alignmentDelim == tagContent.Length - 1) + { + alignment = format = null; + return false; + } + + format = null; + alignment = tagContent.Substring(alignmentDelim + 1); + } + else + { + if (alignmentDelim == formatDelim - 1) + { + alignment = format = null; + return false; + } + + alignment = tagContent.Substring(alignmentDelim + 1, formatDelim - alignmentDelim - 1); + format = formatDelim == tagContent.Length - 1 ? + null : + tagContent.Substring(formatDelim + 1); + } + } + } + + return true; + } + + static bool IsValidInPropertyTag(char c) + { + return IsValidInDestructuringHint(c) || + IsValidInPropertyName(c) || + IsValidInFormat(c) || + c == ':'; + } + + static bool IsValidInPropertyName(char c) + { + return char.IsLetterOrDigit(c) || c == '_'; + } + + static bool TryGetDestructuringHint(char c, out Destructuring destructuring) + { + switch (c) + { + case '@': + { + destructuring = Destructuring.Destructure; + return true; + } + case '$': + { + destructuring = Destructuring.Stringify; + return true; + } + default: + { + destructuring = Destructuring.Default; + return false; + } + } + } + + static bool IsValidInDestructuringHint(char c) + { + return c == '@' || + c == '$'; + } + + static bool IsValidInAlignment(char c) + { + return char.IsDigit(c) || + c == '-'; + } + + static bool IsValidInFormat(char c) + { + return c != '}' && + (char.IsLetterOrDigit(c) || + char.IsPunctuation(c) || + c == ' '); + } + + static TextToken ParseTextToken(int startAt, string messageTemplate, out int next) + { + var first = startAt; + + var accum = new StringBuilder(); + do + { + var nc = messageTemplate[startAt]; + if (nc == '{') + { + if (startAt + 1 < messageTemplate.Length && + messageTemplate[startAt + 1] == '{') + { + accum.Append(nc); + startAt++; + } + else + { + break; + } + } + else + { + accum.Append(nc); + if (nc == '}') + { + if (startAt + 1 < messageTemplate.Length && + messageTemplate[startAt + 1] == '}') + { + startAt++; + } + } + } + + startAt++; + } while (startAt < messageTemplate.Length); + + next = startAt; + return new TextToken(accum.ToString(), first); + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateToken.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateToken.cs new file mode 100644 index 0000000000..aa264ead80 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/MessageTemplateToken.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// An element parsed from a message template string. + /// + internal abstract class MessageTemplateToken + { + /// + /// Construct a . + /// + /// The token's start index in the template. + protected MessageTemplateToken(int startIndex) + { + StartIndex = startIndex; + } + + /// + /// The token's start index in the template. + /// + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public int StartIndex { get; } + + /// + /// The token's length. + /// + public abstract int Length { get; } + + /// + /// Render the token to the output. + /// + /// Properties that may be represented by the token. + /// Output for the rendered string. + /// Supplies culture-specific formatting information, or null. + // ReSharper disable once UnusedMemberInSuper.Global + public abstract void Render(IReadOnlyDictionary properties, TextWriter output, IFormatProvider formatProvider = null); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/PropertyToken.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/PropertyToken.cs new file mode 100644 index 0000000000..8ae21fd134 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/PropertyToken.cs @@ -0,0 +1,176 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// A message template token representing a log event property. + /// + internal sealed class PropertyToken : MessageTemplateToken + { + readonly string _rawText; + readonly int? _position; + + /// + /// Construct a . + /// + /// The name of the property. + /// The token as it appears in the message template. + /// The format applied to the property, if any. + /// The destructuring strategy applied to the property, if any. + /// + [Obsolete("Use named arguments with this method to guarantee forwards-compatibility."), EditorBrowsable(EditorBrowsableState.Never)] + public PropertyToken(string propertyName, string rawText, string formatObsolete, Destructuring destructuringObsolete) + : this(propertyName, rawText, formatObsolete, null, destructuringObsolete) + { + } + + /// + /// Construct a . + /// + /// The name of the property. + /// The token as it appears in the message template. + /// The format applied to the property, if any. + /// The alignment applied to the property, if any. + /// The destructuring strategy applied to the property, if any. + /// The token's start index in the template. + /// + public PropertyToken(string propertyName, string rawText, string format = null, Alignment? alignment = null, Destructuring destructuring = Destructuring.Default, int startIndex = -1) + : base(startIndex) + { + PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); + Format = format; + Destructuring = destructuring; + _rawText = rawText ?? throw new ArgumentNullException(nameof(rawText)); + Alignment = alignment; + + int position; + if (int.TryParse(PropertyName, NumberStyles.None, CultureInfo.InvariantCulture, out position) && + position >= 0) + { + _position = position; + } + } + + /// + /// The token's length. + /// + public override int Length => _rawText.Length; + + /// + /// Render the token to the output. + /// + /// Properties that may be represented by the token. + /// Output for the rendered string. + /// Supplies culture-specific formatting information, or null. + public override void Render(IReadOnlyDictionary properties, TextWriter output, IFormatProvider formatProvider = null) + { + if (properties == null) throw new ArgumentNullException(nameof(properties)); + if (output == null) throw new ArgumentNullException(nameof(output)); + + MessageTemplateRenderer.RenderPropertyToken(this, properties, output, formatProvider, false, false); + } + + /// + /// The property name. + /// + public string PropertyName { get; } + + /// + /// Destructuring strategy applied to the property. + /// + public Destructuring Destructuring { get; } + + /// + /// Format applied to the property. + /// + public string Format { get; } + + /// + /// Alignment applied to the property. + /// + public Alignment? Alignment { get; } + + /// + /// True if the property name is a positional index; otherwise, false. + /// + public bool IsPositional => _position.HasValue; + + internal string RawText => _rawText; + + /// + /// Try to get the integer value represented by the property name. + /// + /// The integer value, if present. + /// True if the property is positional, otherwise false. + public bool TryGetPositionalValue(out int position) + { + if (_position == null) + { + position = 0; + return false; + } + + position = _position.Value; + return true; + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// + /// true if the specified object is equal to the current object; otherwise, false. + /// + /// The object to compare with the current object. 2 + public override bool Equals(object obj) + { + var pt = obj as PropertyToken; + return pt != null && + pt.Destructuring == Destructuring && + pt.Format == Format && + pt.PropertyName == PropertyName && + pt._rawText == _rawText; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// + /// A hash code for the current . + /// + /// 2 + public override int GetHashCode() => PropertyName.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() => _rawText; + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Parsing/TextToken.cs b/src/Datadog.Trace/Vendors/Serilog/Parsing/TextToken.cs new file mode 100644 index 0000000000..3eff1ede9e --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Parsing/TextToken.cs @@ -0,0 +1,96 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Rendering; + +namespace Datadog.Trace.Vendors.Serilog.Parsing +{ + /// + /// A message template token representing literal text. + /// + internal sealed class TextToken : MessageTemplateToken + { + /// + /// Construct a . + /// + /// The text of the token. + /// The token's start index in the template. + /// + public TextToken(string text, int startIndex = -1) : base(startIndex) + { + Text = text ?? throw new ArgumentNullException(nameof(text)); + } + + /// + /// The token's length. + /// + public override int Length => Text.Length; + + /// + /// Render the token to the output. + /// + /// Properties that may be represented by the token. + /// Output for the rendered string. + /// Supplies culture-specific formatting information, or null. + public override void Render(IReadOnlyDictionary properties, TextWriter output, IFormatProvider formatProvider = null) + { + if (output == null) throw new ArgumentNullException(nameof(output)); + MessageTemplateRenderer.RenderTextToken(this, output); + } + + /// + /// Determines whether the specified is equal to the current . + /// + /// + /// true if the specified object is equal to the current object; otherwise, false. + /// + /// The object to compare with the current object. 2 + public override bool Equals(object obj) + { + var tt = obj as TextToken; + return tt != null && tt.Text == Text; + } + + /// + /// Serves as a hash function for a particular type. + /// + /// + /// A hash code for the current . + /// + /// 2 + public override int GetHashCode() => Text.GetHashCode(); + + /// + /// Returns a string that represents the current object. + /// + /// + /// A string that represents the current object. + /// + /// 2 + public override string ToString() => Text; + + /// + /// The text of the token. + /// + public string Text { get; } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/ByteArrayScalarConversionPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/ByteArrayScalarConversionPolicy.cs new file mode 100644 index 0000000000..6ea694baa4 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/ByteArrayScalarConversionPolicy.cs @@ -0,0 +1,55 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + // Byte arrays, when logged, need to be copied so that they are + // safe from concurrent modification when written to asynchronous + // sinks. Byte arrays larger than 1k are written as descriptive strings. + class ByteArrayScalarConversionPolicy : IScalarConversionPolicy + { + const int MaximumByteArrayLength = 1024; + + public bool TryConvertToScalar(object value, out ScalarValue result) + { + var bytes = value as byte[]; + if (bytes == null) + { + result = null; + return false; + } + + if (bytes.Length > MaximumByteArrayLength) + { + var start = string.Concat(bytes.Take(16).Select(b => b.ToString("X2"))); + var description = start + "... (" + bytes.Length + " bytes)"; + result = new ScalarValue(description); + } + else + { + result = new ScalarValue(string.Concat(bytes.Select(b => b.ToString("X2")))); + } + + return true; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/DelegateDestructuringPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/DelegateDestructuringPolicy.cs new file mode 100644 index 0000000000..a1f6a7acc7 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/DelegateDestructuringPolicy.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + class DelegateDestructuringPolicy : IDestructuringPolicy + { + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) + { + var del = value as Delegate; + if (del != null) + { + result = new ScalarValue(del.ToString()); + return true; + } + + result = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/EnumScalarConversionPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/EnumScalarConversionPolicy.cs new file mode 100644 index 0000000000..27ef070ddd --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/EnumScalarConversionPolicy.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; +using System.Reflection; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + class EnumScalarConversionPolicy : IScalarConversionPolicy + { + public bool TryConvertToScalar(object value, out ScalarValue result) + { + if (value.GetType().GetTypeInfo().IsEnum) + { + result = new ScalarValue(value); + return true; + } + + result = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/ProjectedDestructuringPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/ProjectedDestructuringPolicy.cs new file mode 100644 index 0000000000..c1abec464d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/ProjectedDestructuringPolicy.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + class ProjectedDestructuringPolicy : IDestructuringPolicy + { + readonly Func _canApply; + readonly Func _projection; + + public ProjectedDestructuringPolicy(Func canApply, Func projection) + { + if (canApply == null) throw new ArgumentNullException(nameof(canApply)); + if (projection == null) throw new ArgumentNullException(nameof(projection)); + _canApply = canApply; + _projection = projection; + } + + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) + { + if (value == null) throw new ArgumentNullException(nameof(value)); + + if (!_canApply(value.GetType())) + { + result = null; + return false; + } + + var projected = _projection(value); + result = propertyValueFactory.CreatePropertyValue(projected, true); + return true; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs new file mode 100644 index 0000000000..d0e4bf7167 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/ReflectionTypesScalarDestructuringPolicy.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2016 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Reflection; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + class ReflectionTypesScalarDestructuringPolicy : IDestructuringPolicy + { + public bool TryDestructure(object value, ILogEventPropertyValueFactory propertyValueFactory, out LogEventPropertyValue result) + { + // These types and their subclasses are property-laden and deep; + // most sinks will convert them to strings. + if (value is Type || value is MemberInfo) + { + result = new ScalarValue(value); + return true; + } + + result = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Policies/SimpleScalarConversionPolicy.cs b/src/Datadog.Trace/Vendors/Serilog/Policies/SimpleScalarConversionPolicy.cs new file mode 100644 index 0000000000..b25a33d470 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Policies/SimpleScalarConversionPolicy.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Policies +{ + class SimpleScalarConversionPolicy : IScalarConversionPolicy + { + readonly HashSet _scalarTypes; + + public SimpleScalarConversionPolicy(IEnumerable scalarTypes) + { + _scalarTypes = new HashSet(scalarTypes); + } + + public bool TryConvertToScalar(object value, out ScalarValue result) + { + if (_scalarTypes.Contains(value.GetType())) + { + result = new ScalarValue(value); + return true; + } + + result = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Rendering/Casing.cs b/src/Datadog.Trace/Vendors/Serilog/Rendering/Casing.cs new file mode 100644 index 0000000000..e861003021 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Rendering/Casing.cs @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Datadog.Trace.Vendors.Serilog.Rendering +{ + static class Casing + { + /// + /// Apply upper or lower casing to when is provided. + /// Returns when no or invalid format provided + /// + /// The provided with formatting applied + public static string Format(string value, string format = null) + { + switch (format) + { + case "u": + return value.ToUpperInvariant(); + case "w": + return value.ToLowerInvariant(); + default: + return value; + } + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Rendering/MessageTemplateRenderer.cs b/src/Datadog.Trace/Vendors/Serilog/Rendering/MessageTemplateRenderer.cs new file mode 100644 index 0000000000..d364cd313c --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Rendering/MessageTemplateRenderer.cs @@ -0,0 +1,113 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using Datadog.Trace.Vendors.Serilog.Events; +using Datadog.Trace.Vendors.Serilog.Formatting.Json; +using Datadog.Trace.Vendors.Serilog.Parsing; + +namespace Datadog.Trace.Vendors.Serilog.Rendering +{ + static class MessageTemplateRenderer + { + static readonly JsonValueFormatter JsonValueFormatter = new JsonValueFormatter("$type"); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Render(MessageTemplate messageTemplate, IReadOnlyDictionary properties, TextWriter output, string format = null, IFormatProvider formatProvider = null) + { + bool isLiteral = false, isJson = false; + + if (format != null) + { + for (var i = 0; i < format.Length; ++i) + { + if (format[i] == 'l') + isLiteral = true; + else if (format[i] == 'j') + isJson = true; + } + } + + for (var ti = 0; ti < messageTemplate.TokenArray.Length; ++ti) + { + var token = messageTemplate.TokenArray[ti]; + if (token is TextToken tt) + { + RenderTextToken(tt, output); + } + else + { + var pt = (PropertyToken) token; + RenderPropertyToken(pt, properties, output, formatProvider, isLiteral, isJson); + } + } + } + + public static void RenderTextToken(TextToken tt, TextWriter output) + { + output.Write(tt.Text); + } + + public static void RenderPropertyToken(PropertyToken pt, IReadOnlyDictionary properties, TextWriter output, IFormatProvider formatProvider, bool isLiteral, bool isJson) + { + LogEventPropertyValue propertyValue; + if (!properties.TryGetValue(pt.PropertyName, out propertyValue)) + { + output.Write(pt.RawText); + return; + } + + if (!pt.Alignment.HasValue) + { + RenderValue(propertyValue, isLiteral, isJson, output, pt.Format, formatProvider); + return; + } + + var valueOutput = new StringWriter(); + RenderValue(propertyValue, isLiteral, isJson, valueOutput, pt.Format, formatProvider); + var value = valueOutput.ToString(); + + if (value.Length >= pt.Alignment.Value.Width) + { + output.Write(value); + return; + } + + Padding.Apply(output, value, pt.Alignment.Value); + } + + static void RenderValue(LogEventPropertyValue propertyValue, bool literal, bool json, TextWriter output, string format, IFormatProvider formatProvider) + { + if (literal && propertyValue is ScalarValue sv && sv.Value is string str) + { + output.Write(str); + } + else if (json) + { + JsonValueFormatter.Format(propertyValue, output); + } + else + { + propertyValue.Render(output, format, formatProvider); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Rendering/Padding.cs b/src/Datadog.Trace/Vendors/Serilog/Rendering/Padding.cs new file mode 100644 index 0000000000..bc86744750 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Rendering/Padding.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2017 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.IO; +using System.Linq; +using Datadog.Trace.Vendors.Serilog.Parsing; + +namespace Datadog.Trace.Vendors.Serilog.Rendering +{ + static class Padding + { + static readonly char[] PaddingChars = Enumerable.Repeat(' ', 80).ToArray(); + + /// + /// Writes the provided value to the output, applying direction-based padding when is provided. + /// + public static void Apply(TextWriter output, string value, Alignment? alignment) + { + if (!alignment.HasValue || value.Length >= alignment.Value.Width) + { + output.Write(value); + return; + } + + var pad = alignment.Value.Width - value.Length; + + if (alignment.Value.Direction == AlignmentDirection.Left) + output.Write(value); + + if (pad <= PaddingChars.Length) + { + output.Write(PaddingChars, 0, pad); + } + else + { + output.Write(new string(' ', pad)); + } + + if (alignment.Value.Direction == AlignmentDirection.Right) + output.Write(value); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/Serilog/Serilog.csproj.txt b/src/Datadog.Trace/Vendors/Serilog/Serilog.csproj.txt new file mode 100644 index 0000000000..333ef29f8d --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Serilog.csproj.txt @@ -0,0 +1,63 @@ + + + + Simple .NET logging with fully-structured events + 2.8.0 + Serilog Contributors + net45;net46;netstandard1.0;netstandard1.3;netstandard2.0 + true + Serilog + ../../assets/Serilog.snk + true + true + Serilog + serilog;logging;semantic;structured + https://serilog.net/images/serilog-nuget.png + https://github.com/serilog/serilog + https://www.apache.org/licenses/LICENSE-2.0 + https://github.com/serilog/serilog + git + false + True + + + + + true + $(DefineConstants);REMOTING;HASHTABLE + + + + true + $(DefineConstants);ASYNCLOCAL;HASHTABLE + + + + $(DefineConstants);ASYNCLOCAL;HASHTABLE + + + + $(DefineConstants);ASYNCLOCAL;HASHTABLE + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/CallableConfigurationMethodFinder.cs b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/CallableConfigurationMethodFinder.cs new file mode 100644 index 0000000000..a2a16fcefb --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/CallableConfigurationMethodFinder.cs @@ -0,0 +1,69 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Datadog.Trace.Vendors.Serilog.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Datadog.Trace.Vendors.Serilog.Settings.KeyValuePairs +{ + static class CallableConfigurationMethodFinder + { + internal static IList FindConfigurationMethods(IEnumerable configurationAssemblies, Type configType) + { + var methods = configurationAssemblies + .SelectMany(a => a.ExportedTypes + .Select(t => t.GetTypeInfo()) + .Where(t => t.IsSealed && t.IsAbstract && !t.IsNested)) + .SelectMany(t => t.DeclaredMethods) + .Where(m => m.IsStatic && m.IsPublic && m.IsDefined(typeof(ExtensionAttribute), false)) + .Where(m => m.GetParameters()[0].ParameterType == configType) + .ToList(); + + // some configuration methods are not extension methods. They are added manually + // so they can be discovered + + // WriteTo.Sink(params ILogEventSink[]) is not an extension method + // and we want to expose WriteTo.Sink(ILogEventSink sink) to the config system + if (configType == typeof(LoggerSinkConfiguration)) + methods.AddRange(SurrogateConfigurationMethods.WriteTo); + + // AuditTo.Sink(params ILogEventSink[]) is not an extension method + // and we want to expose WriteTo.Sink(ILogEventSink sink) to the config system + if (configType == typeof(LoggerAuditSinkConfiguration)) + methods.AddRange(SurrogateConfigurationMethods.AuditTo); + + // FromLogContext is an instance method rather than an extension. + if (configType == typeof(LoggerEnrichmentConfiguration)) + methods.AddRange(SurrogateConfigurationMethods.Enrich); + + // Some of the useful Destructure configuration methods are defined as methods rather than extension methods + if (configType == typeof(LoggerDestructuringConfiguration)) + methods.AddRange(SurrogateConfigurationMethods.Destructure); + + // Some of the useful Filter configuration methods are defined as methods rather than extension methods + if (configType == typeof(LoggerFilterConfiguration)) + methods.AddRange(SurrogateConfigurationMethods.Filter); + + return methods; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs new file mode 100644 index 0000000000..d0f25a823c --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/KeyValuePairSettings.cs @@ -0,0 +1,287 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; +using Datadog.Trace.Vendors.Serilog.Configuration; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Settings.KeyValuePairs +{ + class KeyValuePairSettings : ILoggerSettings + { + const string UsingDirective = "using"; + const string LevelSwitchDirective = "level-switch"; + const string AuditToDirective = "audit-to"; + const string WriteToDirective = "write-to"; + const string MinimumLevelDirective = "minimum-level"; + const string MinimumLevelControlledByDirective = "minimum-level:controlled-by"; + const string EnrichWithDirective = "enrich"; + const string EnrichWithPropertyDirective = "enrich:with-property"; + const string FilterDirective = "filter"; + const string DestructureDirective = "destructure"; + + const string UsingDirectiveFullFormPrefix = "using:"; + const string EnrichWithPropertyDirectivePrefix = "enrich:with-property:"; + const string MinimumLevelOverrideDirectivePrefix = "minimum-level:override:"; + + const string CallableDirectiveRegex = @"^(?audit-to|write-to|enrich|filter|destructure):(?[A-Za-z0-9]*)(\.(?[A-Za-z0-9]*)){0,1}$"; + const string LevelSwitchDeclarationDirectiveRegex = @"^level-switch:(?.*)$"; + const string LevelSwitchNameRegex = @"^\$[A-Za-z]+[A-Za-z0-9]*$"; + + static readonly string[] _supportedDirectives = + { + UsingDirective, + LevelSwitchDirective, + AuditToDirective, + WriteToDirective, + MinimumLevelDirective, + MinimumLevelControlledByDirective, + EnrichWithPropertyDirective, + EnrichWithDirective, + FilterDirective, + DestructureDirective + }; + + static readonly Dictionary CallableDirectiveReceiverTypes = new Dictionary + { + ["audit-to"] = typeof(LoggerAuditSinkConfiguration), + ["write-to"] = typeof(LoggerSinkConfiguration), + ["enrich"] = typeof(LoggerEnrichmentConfiguration), + ["filter"] = typeof(LoggerFilterConfiguration), + ["destructure"] = typeof(LoggerDestructuringConfiguration), + }; + + static readonly Dictionary> CallableDirectiveReceivers = new Dictionary> + { + [typeof(LoggerAuditSinkConfiguration)] = lc => lc.AuditTo, + [typeof(LoggerSinkConfiguration)] = lc => lc.WriteTo, + [typeof(LoggerEnrichmentConfiguration)] = lc => lc.Enrich, + [typeof(LoggerFilterConfiguration)] = lc => lc.Filter, + [typeof(LoggerDestructuringConfiguration)] = lc => lc.Destructure, + }; + + readonly IReadOnlyDictionary _settings; + + public KeyValuePairSettings(IReadOnlyDictionary settings) + { + _settings = settings ?? throw new ArgumentNullException(nameof(settings)); + } + + public void Configure(LoggerConfiguration loggerConfiguration) + { + if (loggerConfiguration == null) throw new ArgumentNullException(nameof(loggerConfiguration)); + + var directives = _settings + .Where(kvp => _supportedDirectives.Any(kvp.Key.StartsWith)) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + var declaredLevelSwitches = ParseNamedLevelSwitchDeclarationDirectives(directives); + + string minimumLevelDirective; + LogEventLevel minimumLevel; + if (directives.TryGetValue(MinimumLevelDirective, out minimumLevelDirective) && + Enum.TryParse(minimumLevelDirective, out minimumLevel)) + { + loggerConfiguration.MinimumLevel.Is(minimumLevel); + } + + foreach (var enrichProperyDirective in directives.Where(dir => + dir.Key.StartsWith(EnrichWithPropertyDirectivePrefix) && dir.Key.Length > EnrichWithPropertyDirectivePrefix.Length)) + { + var name = enrichProperyDirective.Key.Substring(EnrichWithPropertyDirectivePrefix.Length); + loggerConfiguration.Enrich.WithProperty(name, enrichProperyDirective.Value); + } + + string minimumLevelControlledByLevelSwitchName; + if (directives.TryGetValue(MinimumLevelControlledByDirective, out minimumLevelControlledByLevelSwitchName)) + { + var globalMinimumLevelSwitch = LookUpSwitchByName(minimumLevelControlledByLevelSwitchName, declaredLevelSwitches); + loggerConfiguration.MinimumLevel.ControlledBy(globalMinimumLevelSwitch); + } + + foreach (var minimumLevelOverrideDirective in directives.Where(dir => + dir.Key.StartsWith(MinimumLevelOverrideDirectivePrefix) && dir.Key.Length > MinimumLevelOverrideDirectivePrefix.Length)) + { + var namespacePrefix = minimumLevelOverrideDirective.Key.Substring(MinimumLevelOverrideDirectivePrefix.Length); + + LogEventLevel overriddenLevel; + if (Enum.TryParse(minimumLevelOverrideDirective.Value, out overriddenLevel)) + { + loggerConfiguration.MinimumLevel.Override(namespacePrefix, overriddenLevel); + } + else + { + var overrideSwitch = LookUpSwitchByName(minimumLevelOverrideDirective.Value, declaredLevelSwitches); + loggerConfiguration.MinimumLevel.Override(namespacePrefix, overrideSwitch); + } + } + + var matchCallables = new Regex(CallableDirectiveRegex); + + var callableDirectives = (from wt in directives + where matchCallables.IsMatch(wt.Key) + let match = matchCallables.Match(wt.Key) + select new + { + ReceiverType = CallableDirectiveReceiverTypes[match.Groups["directive"].Value], + Call = new ConfigurationMethodCall + { + MethodName = match.Groups["method"].Value, + ArgumentName = match.Groups["argument"].Value, + Value = wt.Value + } + }).ToList(); + + if (callableDirectives.Any()) + { + var configurationAssemblies = LoadConfigurationAssemblies(directives).ToList(); + + foreach (var receiverGroup in callableDirectives.GroupBy(d => d.ReceiverType)) + { + var methods = CallableConfigurationMethodFinder.FindConfigurationMethods(configurationAssemblies, receiverGroup.Key); + + var calls = receiverGroup + .Select(d => d.Call) + .GroupBy(call => call.MethodName) + .ToList(); + + ApplyDirectives(calls, methods, CallableDirectiveReceivers[receiverGroup.Key](loggerConfiguration), declaredLevelSwitches); + } + } + } + + internal static bool IsValidSwitchName(string input) + { + return Regex.IsMatch(input, LevelSwitchNameRegex); + } + + static IReadOnlyDictionary ParseNamedLevelSwitchDeclarationDirectives(IReadOnlyDictionary directives) + { + var matchLevelSwitchDeclarations = new Regex(LevelSwitchDeclarationDirectiveRegex); + + var switchDeclarationDirectives = (from wt in directives + where matchLevelSwitchDeclarations.IsMatch(wt.Key) + let match = matchLevelSwitchDeclarations.Match(wt.Key) + select new + { + SwitchName = match.Groups["switchName"].Value, + InitialSwitchLevel = wt.Value + }).ToList(); + + var namedSwitches = new Dictionary(); + foreach (var switchDeclarationDirective in switchDeclarationDirectives) + { + var switchName = switchDeclarationDirective.SwitchName; + var switchInitialLevel = switchDeclarationDirective.InitialSwitchLevel; + // switchName must be something like $switch to avoid ambiguities + if (!IsValidSwitchName(switchName)) + { + throw new FormatException($"\"{switchName}\" is not a valid name for a Level Switch declaration. Level switch must be declared with a '$' sign, like \"level-switch:$switchName\""); + } + LoggingLevelSwitch newSwitch; + if (string.IsNullOrEmpty(switchInitialLevel)) + { + newSwitch = new LoggingLevelSwitch(); + } + else + { + var initialLevel = (LogEventLevel)SettingValueConversions.ConvertToType(switchInitialLevel, typeof(LogEventLevel)); + newSwitch = new LoggingLevelSwitch(initialLevel); + } + namedSwitches.Add(switchName, newSwitch); + } + return namedSwitches; + } + + static LoggingLevelSwitch LookUpSwitchByName(string switchName, IReadOnlyDictionary declaredLevelSwitches) + { + if (declaredLevelSwitches.TryGetValue(switchName, out var levelSwitch)) + { + return levelSwitch; + } + + throw new InvalidOperationException($"No LoggingLevelSwitch has been declared with name \"{switchName}\". You might be missing a key \"{LevelSwitchDirective}:{switchName}\""); + } + + static object ConvertOrLookupByName(string valueOrSwitchName, Type type, IReadOnlyDictionary declaredSwitches) + { + if (type == typeof(LoggingLevelSwitch)) + { + return LookUpSwitchByName(valueOrSwitchName, declaredSwitches); + } + return SettingValueConversions.ConvertToType(valueOrSwitchName, type); + } + + static void ApplyDirectives(List> directives, IList configurationMethods, object loggerConfigMethod, IReadOnlyDictionary declaredSwitches) + { + foreach (var directiveInfo in directives) + { + var target = SelectConfigurationMethod(configurationMethods, directiveInfo.Key, directiveInfo); + + if (target != null) + { + + var call = (from p in target.GetParameters().Skip(1) + let directive = directiveInfo.FirstOrDefault(s => s.ArgumentName == p.Name) + select directive == null ? p.DefaultValue : ConvertOrLookupByName(directive.Value, p.ParameterType, declaredSwitches)).ToList(); + + call.Insert(0, loggerConfigMethod); + + target.Invoke(null, call.ToArray()); + } + } + } + + internal static MethodInfo SelectConfigurationMethod(IEnumerable candidateMethods, string name, IEnumerable suppliedArgumentValues) + { + return candidateMethods + .Where(m => m.Name == name && + m.GetParameters().Skip(1).All(p => p.HasDefaultValue || suppliedArgumentValues.Any(s => s.ArgumentName == p.Name))) + .OrderByDescending(m => m.GetParameters().Count(p => suppliedArgumentValues.Any(s => s.ArgumentName == p.Name))) + .FirstOrDefault(); + } + + internal static IEnumerable LoadConfigurationAssemblies(IReadOnlyDictionary directives) + { + var configurationAssemblies = new List { typeof(ILogger).GetTypeInfo().Assembly }; + + foreach (var usingDirective in directives.Where(d => d.Key.Equals(UsingDirective) || + d.Key.StartsWith(UsingDirectiveFullFormPrefix))) + { + if (string.IsNullOrWhiteSpace(usingDirective.Value)) + throw new InvalidOperationException("A zero-length or whitespace assembly name was supplied to a serilog:using configuration statement."); + + configurationAssemblies.Add(Assembly.Load(new AssemblyName(usingDirective.Value))); + } + + return configurationAssemblies.Distinct(); + } + + internal class ConfigurationMethodCall + { + public string MethodName { get; set; } + public string ArgumentName { get; set; } + public string Value { get; set; } + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs new file mode 100644 index 0000000000..dbab080ff5 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SettingValueConversions.cs @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2015 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace Datadog.Trace.Vendors.Serilog.Settings.KeyValuePairs +{ + class SettingValueConversions + { + // should match "The.NameSpace.TypeName::MemberName" optionnally followed by + // usual assembly qualifiers like : + // ", MyAssembly, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" + static Regex StaticMemberAccessorRegex = new Regex("^(?[^:]+)::(?[A-Za-z][A-Za-z0-9]*)(?[^:]*)$"); + + static Dictionary> ExtendedTypeConversions = new Dictionary> + { + { typeof(Uri), s => new Uri(s) }, + { typeof(TimeSpan), s => TimeSpan.Parse(s) }, + { typeof(Type), s => Type.GetType(s, throwOnError:true) }, + }; + + public static object ConvertToType(string value, Type toType) + { + var toTypeInfo = toType.GetTypeInfo(); + if (toTypeInfo.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable<>)) + { + if (string.IsNullOrEmpty(value)) + return null; + + // unwrap Nullable<> type since we're not handling null situations + toType = toTypeInfo.GenericTypeArguments[0]; + toTypeInfo = toType.GetTypeInfo(); + } + + if (toTypeInfo.IsEnum) + return Enum.Parse(toType, value); + + var convertor = ExtendedTypeConversions + .Where(t => t.Key.GetTypeInfo().IsAssignableFrom(toTypeInfo)) + .Select(t => t.Value) + .FirstOrDefault(); + + if (convertor != null) + return convertor(value); + + if ((toTypeInfo.IsInterface || toTypeInfo.IsAbstract) && !string.IsNullOrWhiteSpace(value)) + { + // check if value looks like a static property or field directive + // like "Namespace.TypeName::StaticProperty, AssemblyName" + if (TryParseStaticMemberAccessor(value, out var accessorTypeName, out var memberName)) + { + var accessorType = Type.GetType(accessorTypeName, throwOnError: true); + // is there a public static property with that name ? + var publicStaticPropertyInfo = accessorType.GetTypeInfo().DeclaredProperties + .Where(x => x.Name == memberName) + .Where(x => x.GetMethod != null) + .Where(x => x.GetMethod.IsPublic) + .FirstOrDefault(x => x.GetMethod.IsStatic); + + if (publicStaticPropertyInfo != null) + { + return publicStaticPropertyInfo.GetValue(null); // static property, no instance to pass + } + + // no property ? look for a public static field + var publicStaticFieldInfo = accessorType.GetTypeInfo().DeclaredFields + .Where(x => x.Name == memberName) + .Where(x => x.IsPublic) + .FirstOrDefault(x => x.IsStatic); + + if (publicStaticFieldInfo != null) + { + return publicStaticFieldInfo.GetValue(null); // static field, no instance to pass + } + + throw new InvalidOperationException($"Could not find a public static property or field with name `{memberName}` on type `{accessorTypeName}`"); + } + + // maybe it's the assembly-qualified type name of a concrete implementation + // with a default constructor + var type = Type.GetType(value.Trim(), throwOnError: false); + if (type != null) + { + var ctor = type.GetTypeInfo().DeclaredConstructors.FirstOrDefault(ci => + { + var parameters = ci.GetParameters(); + return parameters.Length == 0 || parameters.All(pi => pi.HasDefaultValue); + }); + + if (ctor == null) + throw new InvalidOperationException($"A default constructor was not found on {type.FullName}."); + + var call = ctor.GetParameters().Select(pi => pi.DefaultValue).ToArray(); + return ctor.Invoke(call); + } + } + + return Convert.ChangeType(value, toType); + } + + internal static bool TryParseStaticMemberAccessor(string input, out string accessorTypeName, out string memberName) + { + if (input == null) + { + accessorTypeName = null; + memberName = null; + return false; + } + if (StaticMemberAccessorRegex.IsMatch(input)) + { + var match = StaticMemberAccessorRegex.Match(input); + var shortAccessorTypeName = match.Groups["shortTypeName"].Value; + var rawMemberName = match.Groups["memberName"].Value; + var extraQualifiers = match.Groups["typeNameExtraQualifiers"].Value; + + memberName = rawMemberName.Trim(); + accessorTypeName = shortAccessorTypeName.Trim() + extraQualifiers.TrimEnd(); + return true; + } + accessorTypeName = null; + memberName = null; + return false; + } + } +} diff --git a/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SurrogateConfigurationMethods.cs b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SurrogateConfigurationMethods.cs new file mode 100644 index 0000000000..2a2d4f54e0 --- /dev/null +++ b/src/Datadog.Trace/Vendors/Serilog/Settings/KeyValuePairs/SurrogateConfigurationMethods.cs @@ -0,0 +1,115 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +// Copyright 2013-2018 Serilog Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Datadog.Trace.Vendors.Serilog.Configuration; +using Datadog.Trace.Vendors.Serilog.Core; +using Datadog.Trace.Vendors.Serilog.Events; + +namespace Datadog.Trace.Vendors.Serilog.Settings.KeyValuePairs +{ + /// + /// Contains "fake extension" methods for the Serilog configuration API. + /// By default the settings knows how to find extension methods, but some configuration + /// are actually "regular" method calls and would not be found otherwise. + /// + /// This static class contains internal methods that can be used instead. + /// + /// See also + /// + static class SurrogateConfigurationMethods + { + static readonly Dictionary SurrogateMethodCandidates = typeof(SurrogateConfigurationMethods) + .GetTypeInfo().DeclaredMethods + .GroupBy(m => m.GetParameters().First().ParameterType) + .ToDictionary(g => g.Key, g => g.ToArray()); + + internal static readonly MethodInfo[] WriteTo = SurrogateMethodCandidates[typeof(LoggerSinkConfiguration)]; + internal static readonly MethodInfo[] AuditTo = SurrogateMethodCandidates[typeof(LoggerAuditSinkConfiguration)]; + internal static readonly MethodInfo[] Enrich = SurrogateMethodCandidates[typeof(LoggerEnrichmentConfiguration)]; + internal static readonly MethodInfo[] Destructure = SurrogateMethodCandidates[typeof(LoggerDestructuringConfiguration)]; + internal static readonly MethodInfo[] Filter = SurrogateMethodCandidates[typeof(LoggerFilterConfiguration)]; + + internal static LoggerConfiguration Sink( + LoggerSinkConfiguration loggerSinkConfiguration, + ILogEventSink sink, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + { + return loggerSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch); + } + + internal static LoggerConfiguration Sink( + LoggerAuditSinkConfiguration auditSinkConfiguration, + ILogEventSink sink, + LogEventLevel restrictedToMinimumLevel = LevelAlias.Minimum, + LoggingLevelSwitch levelSwitch = null) + { + return auditSinkConfiguration.Sink(sink, restrictedToMinimumLevel, levelSwitch); + } + + internal static LoggerConfiguration With(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration, ILogEventEnricher enricher) + { + return loggerEnrichmentConfiguration.With(enricher); + } + + internal static LoggerConfiguration FromLogContext(LoggerEnrichmentConfiguration loggerEnrichmentConfiguration) + { + return loggerEnrichmentConfiguration.FromLogContext(); + } + + internal static LoggerConfiguration With(LoggerDestructuringConfiguration loggerDestructuringConfiguration, + IDestructuringPolicy policy) + { + return loggerDestructuringConfiguration.With(policy); + } + + internal static LoggerConfiguration AsScalar(LoggerDestructuringConfiguration loggerDestructuringConfiguration, + Type scalarType) + { + return loggerDestructuringConfiguration.AsScalar(scalarType); + } + + internal static LoggerConfiguration ToMaximumCollectionCount(LoggerDestructuringConfiguration loggerDestructuringConfiguration, + int maximumCollectionCount) + { + return loggerDestructuringConfiguration.ToMaximumCollectionCount(maximumCollectionCount); + } + + internal static LoggerConfiguration ToMaximumDepth(LoggerDestructuringConfiguration loggerDestructuringConfiguration, + int maximumDestructuringDepth) + { + return loggerDestructuringConfiguration.ToMaximumDepth(maximumDestructuringDepth); + } + + internal static LoggerConfiguration ToMaximumStringLength(LoggerDestructuringConfiguration loggerDestructuringConfiguration, + int maximumStringLength) + { + return loggerDestructuringConfiguration.ToMaximumStringLength(maximumStringLength); + } + + internal static LoggerConfiguration With(LoggerFilterConfiguration loggerFilterConfiguration, + ILogEventFilter filter) + { + return loggerFilterConfiguration.With(filter); + } + } +} diff --git a/src/Datadog.Trace/Vendors/StatsdClient/ICommandType.cs b/src/Datadog.Trace/Vendors/StatsdClient/ICommandType.cs new file mode 100644 index 0000000000..fa046f4f5b --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/ICommandType.cs @@ -0,0 +1,10 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface ICommandType + { + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/IRandomGenerator.cs b/src/Datadog.Trace/Vendors/StatsdClient/IRandomGenerator.cs new file mode 100644 index 0000000000..7f1b54147d --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/IRandomGenerator.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface IRandomGenerator + { + bool ShouldSend(double sampleRate); + + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/IStatsd.cs b/src/Datadog.Trace/Vendors/StatsdClient/IStatsd.cs new file mode 100644 index 0000000000..559efa4b87 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/IStatsd.cs @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface IStatsd + { + ConcurrentBag Commands { get; } + void Send(string name, T value, double sampleRate, params string[] tags) where TCommandType : StatsdClient.Statsd.Metric; + void Add(string name, T value, double sampleRate, params string[] tags) where TCommandType : StatsdClient.Statsd.Metric; + void Send(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] tags, bool truncateIfTooLong = false); + void Add(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] tags, bool truncateIfTooLong = false); + void Send(string command); + void Send(); + void Add(Action actionToTime, string statName, double sampleRate, params string[] tags); + void Send(Action actionToTime, string statName, double sampleRate, params string[] tags); + /// + /// Add service check + /// + void Add(string name, int status, int? timestamp, string hostname, string[] tags, string serviceCheckMessage, bool truncateIfTooLong); + /// + /// Send service check + /// + void Send(string name, int status, int? timestamp, string hostname, string[] tags, string serviceCheckMessage, bool truncateIfTooLong); + } +} diff --git a/src/Datadog.Trace/Vendors/StatsdClient/IStatsdUDP.cs b/src/Datadog.Trace/Vendors/StatsdClient/IStatsdUDP.cs new file mode 100644 index 0000000000..dabeba3ffd --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/IStatsdUDP.cs @@ -0,0 +1,11 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface IStatsdUDP + { + void Send(string command); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/IStopWatchFactory.cs b/src/Datadog.Trace/Vendors/StatsdClient/IStopWatchFactory.cs new file mode 100644 index 0000000000..c561775f44 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/IStopWatchFactory.cs @@ -0,0 +1,11 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface IStopWatchFactory + { + IStopwatch Get(); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/IStopwatch.cs b/src/Datadog.Trace/Vendors/StatsdClient/IStopwatch.cs new file mode 100644 index 0000000000..4065267c23 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/IStopwatch.cs @@ -0,0 +1,13 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal interface IStopwatch + { + void Start(); + void Stop(); + int ElapsedMilliseconds(); + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/RandomGenerator.cs b/src/Datadog.Trace/Vendors/StatsdClient/RandomGenerator.cs new file mode 100644 index 0000000000..4cff29c279 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/RandomGenerator.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class RandomGenerator : IRandomGenerator + { + readonly ThreadSafeRandom _random; + public RandomGenerator() + { + _random = new ThreadSafeRandom(); + } + + public bool ShouldSend(double sampleRate) + { + return _random.NextDouble() < sampleRate; + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/Statsd.cs b/src/Datadog.Trace/Vendors/StatsdClient/Statsd.cs new file mode 100644 index 0000000000..6823fe7861 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/Statsd.cs @@ -0,0 +1,363 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; + +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class Statsd : IStatsd + { + private const string ENTITY_ID_INTERNAL_TAG_KEY = "dd.internal.entity_id"; + private static readonly string[] EmptyStringArray = new string[0]; + + private IStopWatchFactory StopwatchFactory { get; set; } + private IStatsdUDP Udp { get; set; } + private IRandomGenerator RandomGenerator { get; set; } + private readonly string _prefix; + private readonly string[] _constantTags; + public bool TruncateIfTooLong {get; set; } + + public ConcurrentBag Commands + { + get { return _commands; } + private set { _commands = value; } + } + + private ConcurrentBag _commands = new ConcurrentBag(); + + internal abstract class Metric : ICommandType + { + private static readonly Dictionary _commandToUnit = new Dictionary + { + {typeof (Counting), "c"}, + {typeof (Timing), "ms"}, + {typeof (Gauge), "g"}, + {typeof (Histogram), "h"}, + {typeof (Distribution), "d"}, + {typeof (Meter), "m"}, + {typeof (Set), "s"} + }; + + public static string GetCommand(string prefix, string name, T value, double sampleRate, string[] tags) where TCommandType : Metric + { + return GetCommand(prefix,name,value,sampleRate,null,tags); + } + + public static string GetCommand(string prefix, string name, T value, double sampleRate, string[] constantTags, string[] tags) where TCommandType : Metric + { + string full_name = prefix + name; + string unit = _commandToUnit[typeof(TCommandType)]; + var allTags = ConcatTags(constantTags, tags); + + return string.Format( + CultureInfo.InvariantCulture, + "{0}:{1}|{2}{3}{4}", + full_name, + value, + unit, + sampleRate == 1.0 ? "" : string.Format(CultureInfo.InvariantCulture, "|@{0}", sampleRate), + allTags); + } + } + + internal class Event : ICommandType + { + private const int MaxSize = 8 * 1024; + + public static string GetCommand(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] tags, bool truncateIfTooLong = false) + { + return GetCommand(title,text,alertType,aggregationKey,sourceType,dateHappened,priority,hostname,null,tags,truncateIfTooLong); + } + + public static string GetCommand(string title, string text, string alertType, string aggregationKey, string sourceType, int? dateHappened, string priority, string hostname, string[] constantTags, string[] tags, bool truncateIfTooLong = false) + { + string processedTitle = EscapeContent(title); + string processedText = EscapeContent(text); + string result = string.Format(CultureInfo.InvariantCulture, "_e{{{0},{1}}}:{2}|{3}", processedTitle.Length.ToString(), processedText.Length.ToString(), processedTitle, processedText); + if (dateHappened != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|d:{0}", dateHappened); + } + if (hostname != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|h:{0}", hostname); + } + if (aggregationKey != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|k:{0}", aggregationKey); + } + if (priority != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|p:{0}", priority); + } + if (sourceType != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|s:{0}", sourceType); + } + if (alertType != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|t:{0}", alertType); + } + + result += ConcatTags(constantTags, tags); + + if (result.Length > MaxSize) + { + if (truncateIfTooLong) + { + var overage = result.Length - MaxSize; + if (title.Length > text.Length) + title = TruncateOverage(title, overage); + else + text = TruncateOverage(text, overage); + return GetCommand(title, text, alertType, aggregationKey, sourceType, dateHappened, priority, hostname, tags, true); + } + else + throw new Exception(string.Format("Event {0} payload is too big (more than 8kB)", title)); + } + return result; + } + } + + internal class ServiceCheck : ICommandType + { + private const int MaxSize = 8 * 1024; + + public static string GetCommand(string name, int status, int? timestamp, string hostname, string[] tags, string serviceCheckMessage, bool truncateIfTooLong = false) + { + return GetCommand(name, status, timestamp, hostname, null, tags,serviceCheckMessage,truncateIfTooLong); + } + public static string GetCommand(string name, int status, int? timestamp, string hostname, string[] constantTags, string[] tags, string serviceCheckMessage, bool truncateIfTooLong = false) + { + string processedName = EscapeName(name); + string processedMessage = EscapeMessage(serviceCheckMessage); + + string result = string.Format(CultureInfo.InvariantCulture, "_sc|{0}|{1}", processedName, status); + + if (timestamp != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|d:{0}", timestamp); + } + if (hostname != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|h:{0}", hostname); + } + + result += ConcatTags(constantTags, tags); + + // Note: this must always be appended to the result last. + if (processedMessage != null) + { + result += string.Format(CultureInfo.InvariantCulture, "|m:{0}", processedMessage); + } + + if (result.Length > MaxSize) + { + if (!truncateIfTooLong) + throw new Exception(string.Format("ServiceCheck {0} payload is too big (more than 8kB)", name)); + + var overage = result.Length - MaxSize; + + if (processedMessage == null || overage > processedMessage.Length) + throw new ArgumentException(string.Format("ServiceCheck name is too long to truncate, payload is too big (more than 8Kb) for {0}", name), "name"); + + var truncMessage = TruncateOverage(processedMessage, overage); + return GetCommand(name, status, timestamp, hostname, tags, truncMessage, true); + } + + return result; + } + + // Service check name string, shouldn’t contain any | + private static string EscapeName(string name) + { + name = EscapeContent(name); + + if (name.Contains("|")) + throw new ArgumentException("Name must not contain any | (pipe) characters", "name"); + + return name; + } + + private static string EscapeMessage(string message) + { + if (!string.IsNullOrEmpty(message)) + return EscapeContent(message).Replace("m:", "m\\:"); + return message; + } + } + + private static string EscapeContent(string content) + { + return content + .Replace("\r", "") + .Replace("\n", "\\n"); + } + + private static string ConcatTags(string[] constantTags, string[] tags) + { + // avoid dealing with null arrays + constantTags = constantTags ?? EmptyStringArray; + tags = tags ?? EmptyStringArray; + + if (constantTags.Length == 0 && tags.Length == 0) + { + return ""; + } + + var allTags = constantTags.Concat(tags); + string concatenatedTags = string.Join(",", allTags); + return $"|#{concatenatedTags}"; + } + + private static string TruncateOverage(string str, int overage) + { + return str.Substring(0, str.Length - overage); + } + + internal class Counting : Metric { } + internal class Timing : Metric { } + internal class Gauge : Metric { } + internal class Histogram : Metric { } + internal class Distribution : Metric { } + internal class Meter : Metric { } + internal class Set : Metric { } + + public Statsd(IStatsdUDP udp, IRandomGenerator randomGenerator, IStopWatchFactory stopwatchFactory, string prefix, string[] constantTags) + { + StopwatchFactory = stopwatchFactory; + Udp = udp; + RandomGenerator = randomGenerator; + _prefix = prefix; + + string entityId = Environment.GetEnvironmentVariable(StatsdConfig.DD_ENTITY_ID_ENV_VAR); + + if (string.IsNullOrEmpty(entityId)) + { + // copy array to prevent changes, coalesce to empty array + _constantTags = constantTags?.ToArray() ?? EmptyStringArray; + } + else + { + var entityIdTags = new[] { $"{ENTITY_ID_INTERNAL_TAG_KEY}:{entityId}" }; + _constantTags = constantTags == null ? entityIdTags : constantTags.Concat(entityIdTags).ToArray(); + } + } + + public Statsd(IStatsdUDP udp, IRandomGenerator randomGenerator, IStopWatchFactory stopwatchFactory, string prefix) + : this(udp, randomGenerator, stopwatchFactory, prefix, null) { } + + public Statsd(IStatsdUDP udp, IRandomGenerator randomGenerator, IStopWatchFactory stopwatchFactory) + : this(udp, randomGenerator, stopwatchFactory, string.Empty) { } + + public Statsd(IStatsdUDP udp, string prefix) + : this(udp, new RandomGenerator(), new StopWatchFactory(), prefix) { } + + public Statsd(IStatsdUDP udp) + : this(udp, "") { } + + public void Add(string name, T value, double sampleRate = 1.0, string[] tags = null) where TCommandType : Metric + { + _commands.Add(Metric.GetCommand(_prefix, name, value, sampleRate, _constantTags, tags)); + } + + public void Add(string title, string text, string alertType = null, string aggregationKey = null, string sourceType = null, int? dateHappened = null, string priority = null, string hostname = null, string[] tags = null, bool truncateIfTooLong = false) + { + truncateIfTooLong = truncateIfTooLong || TruncateIfTooLong; + _commands.Add(Event.GetCommand(title, text, alertType, aggregationKey, sourceType, dateHappened, priority, hostname, _constantTags, tags, truncateIfTooLong)); + } + + public void Send(string title, string text, string alertType = null, string aggregationKey = null, string sourceType = null, int? dateHappened = null, string priority = null, string hostname = null, string[] tags = null, bool truncateIfTooLong = false) + { + truncateIfTooLong = truncateIfTooLong || TruncateIfTooLong; + Send(Event.GetCommand(title, text, alertType, aggregationKey, sourceType, dateHappened, priority, hostname, _constantTags, tags, truncateIfTooLong)); + } + + /// + /// Add a Service check + /// + public void Add(string name, int status, int? timestamp = null, string hostname = null, string[] tags = null, string serviceCheckMessage = null, bool truncateIfTooLong = false) + { + truncateIfTooLong = truncateIfTooLong || TruncateIfTooLong; + _commands.Add(ServiceCheck.GetCommand(name, status, timestamp, hostname, _constantTags, tags, serviceCheckMessage, truncateIfTooLong)); + } + + /// + /// Send a service check + /// + public void Send(string name, int status, int? timestamp = null, string hostname = null, string[] tags = null, string serviceCheckMessage = null, bool truncateIfTooLong = false) + { + truncateIfTooLong = truncateIfTooLong || TruncateIfTooLong; + Send(ServiceCheck.GetCommand(name, status, timestamp, hostname, _constantTags, tags, serviceCheckMessage, truncateIfTooLong)); + } + + public void Send(string name, T value, double sampleRate = 1.0, string[] tags = null) where TCommandType : Metric + { + if (RandomGenerator.ShouldSend(sampleRate)) + { + Send(Metric.GetCommand(_prefix, name, value, sampleRate, _constantTags, tags)); + } + } + + public void Send(string command) + { + try + { + Udp.Send(command); + // clear buffer (keep existing behavior) + if (Commands.Count > 0) + Commands = new ConcurrentBag(); + } + catch (Exception e) + { + Debug.WriteLine(e.Message); + } + } + + public void Send() + { + int count = Commands.Count; + if (count < 1) return; + + Send(1 == count ? Commands.Single() : string.Join("\n", Commands.ToArray())); + } + + public void Add(Action actionToTime, string statName, double sampleRate = 1.0, string[] tags = null) + { + var stopwatch = StopwatchFactory.Get(); + + try + { + stopwatch.Start(); + actionToTime(); + } + finally + { + stopwatch.Stop(); + Add(statName, stopwatch.ElapsedMilliseconds(), sampleRate, tags); + } + } + + public void Send(Action actionToTime, string statName, double sampleRate = 1.0, string[] tags = null) + { + var stopwatch = StopwatchFactory.Get(); + + try + { + stopwatch.Start(); + actionToTime(); + } + finally + { + stopwatch.Stop(); + Send(statName, stopwatch.ElapsedMilliseconds(), sampleRate, tags); + } + } + } +} diff --git a/src/Datadog.Trace/Vendors/StatsdClient/StatsdClient.csproj.txt b/src/Datadog.Trace/Vendors/StatsdClient/StatsdClient.csproj.txt new file mode 100644 index 0000000000..7f9e043449 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/StatsdClient.csproj.txt @@ -0,0 +1,19 @@ + + + + DogStatsD-CSharp-Client + A DogStatsD client for C#. DogStatsD is an extension of the StatsD metric server for use with Datadog. For more information visit http://datadoghq.com. + Datadog + netstandard1.3;netstandard1.6;netcoreapp1.1;netcoreapp2.0;net451;net461 + 3.3.0 + https://github.com/DataDog/dogstatsd-csharp-client/blob/master/MIT-LICENCE.md + https://github.com/DataDog/dogstatsd-csharp-client + + + + + 4.3.0 + + + + diff --git a/src/Datadog.Trace/Vendors/StatsdClient/StatsdConfig.cs b/src/Datadog.Trace/Vendors/StatsdClient/StatsdConfig.cs new file mode 100644 index 0000000000..be31a453db --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/StatsdConfig.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class StatsdConfig + { + public string StatsdServerName { get; set; } + public int StatsdPort { get; set; } + public int StatsdMaxUDPPacketSize { get; set; } + public bool StatsdTruncateIfTooLong { get; set; } = true; + public string Prefix { get; set; } + + public string[] ConstantTags { get; set; } + public const int DefaultStatsdPort = 8125; + public const int DefaultStatsdMaxUDPPacketSize = 512; + + public const string DD_ENTITY_ID_ENV_VAR = "DD_ENTITY_ID"; + public const string DD_DOGSTATSD_PORT_ENV_VAR = "DD_DOGSTATSD_PORT"; + public const string DD_AGENT_HOST_ENV_VAR = "DD_AGENT_HOST"; + + public StatsdConfig() + { + StatsdPort = 0; + StatsdMaxUDPPacketSize = DefaultStatsdMaxUDPPacketSize; + } + } +} diff --git a/src/Datadog.Trace/Vendors/StatsdClient/StatsdUDP.cs b/src/Datadog.Trace/Vendors/StatsdClient/StatsdUDP.cs new file mode 100644 index 0000000000..d0ef97bb96 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/StatsdUDP.cs @@ -0,0 +1,146 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; + +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class StatsdUDP : IDisposable, IStatsdUDP + { + private int MaxUDPPacketSize { get; set; } // In bytes; default is MetricsConfig.DefaultStatsdMaxUDPPacketSize. + // Set to zero for no limit. + public IPEndPoint IPEndpoint { get; private set; } + private Socket UDPSocket { get; set; } + private string Name { get; set; } + private int Port { get; set; } + + public StatsdUDP(int maxUDPPacketSize = StatsdConfig.DefaultStatsdMaxUDPPacketSize) + : this(GetHostNameFromEnvVar(),GetPortFromEnvVar(StatsdConfig.DefaultStatsdPort),maxUDPPacketSize) + { + } + public StatsdUDP(string name = null, int port = 0, int maxUDPPacketSize = StatsdConfig.DefaultStatsdMaxUDPPacketSize) + { + Port = port; + if (Port == 0) + { + Port = GetPortFromEnvVar(StatsdConfig.DefaultStatsdPort); + } + Name = name; + if (string.IsNullOrEmpty(Name)) + { + Name = GetHostNameFromEnvVar(); + } + + MaxUDPPacketSize = maxUDPPacketSize; + + UDPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + var ipAddress = GetIpv4Address(Name); + + IPEndpoint = new IPEndPoint(ipAddress, Port); + } + + private static string GetHostNameFromEnvVar() + { + return Environment.GetEnvironmentVariable(StatsdConfig.DD_AGENT_HOST_ENV_VAR); + } + + private static int GetPortFromEnvVar(int defaultValue) + { + int port = defaultValue; + string portString = Environment.GetEnvironmentVariable(StatsdConfig.DD_DOGSTATSD_PORT_ENV_VAR); + if (portString != null) + { + try + { + port = Int32.Parse(portString); + } + catch (FormatException) + { + throw new ArgumentException("Environment Variable 'DD_DOGSTATSD_PORT' bad format"); + } + } + return port; + } + private IPAddress GetIpv4Address(string name) + { + IPAddress ipAddress; + bool isValidIPAddress = IPAddress.TryParse(name, out ipAddress); + + if (!isValidIPAddress) + { + ipAddress = null; +#if NET451 + IPAddress[] addressList = Dns.GetHostEntry(name).AddressList; +#else + IPAddress[] addressList = Dns.GetHostEntryAsync(name).Result.AddressList; +#endif + //The IPv4 address is usually the last one, but not always + for(int positionToTest = addressList.Length - 1; positionToTest >= 0; --positionToTest) + { + if(addressList[positionToTest].AddressFamily == AddressFamily.InterNetwork) + { + ipAddress = addressList[positionToTest]; + break; + } + } + + //If no IPV4 address is found, throw an exception here, rather than letting it get squashed when encountered at sendtime + if(ipAddress == null) + throw new SocketException((int)SocketError.AddressFamilyNotSupported); + } + return ipAddress; + } + + public void Send(string command) + { + Send(Encoding.UTF8.GetBytes(command)); + } + + private void Send(byte[] encodedCommand) + { + if (MaxUDPPacketSize > 0 && encodedCommand.Length > MaxUDPPacketSize) + { + // If the command is too big to send, linear search backwards from the maximum + // packet size to see if we can find a newline delimiting two stats. If we can, + // split the message across the newline and try sending both componenets individually + byte newline = Encoding.UTF8.GetBytes("\n")[0]; + for (int i = MaxUDPPacketSize; i > 0; i--) + { + if (encodedCommand[i] == newline) + { + byte[] encodedCommandFirst = new byte[i]; + Array.Copy(encodedCommand, encodedCommandFirst, encodedCommandFirst.Length); // encodedCommand[0..i-1] + Send(encodedCommandFirst); + + int remainingCharacters = encodedCommand.Length - i - 1; + if (remainingCharacters > 0) + { + byte[] encodedCommandSecond = new byte[remainingCharacters]; + Array.Copy(encodedCommand, i + 1, encodedCommandSecond, 0, encodedCommandSecond.Length); // encodedCommand[i+1..end] + Send(encodedCommandSecond); + } + + return; // We're done here if we were able to split the message. + } + // At this point we found an oversized message but we weren't able to find a + // newline to split upon. We'll still send it to the UDP socket, which upon sending an oversized message + // will fail silently if the user is running in release mode or report a SocketException if the user is + // running in debug mode. + // Since we're conservative with our MAX_UDP_PACKET_SIZE, the oversized message might even + // be sent without issue. + } + } + UDPSocket.SendTo(encodedCommand, encodedCommand.Length, SocketFlags.None, IPEndpoint); + } + + public void Dispose() + { + UDPSocket.Dispose(); + } + } +} diff --git a/src/Datadog.Trace/Vendors/StatsdClient/StopWatchFactory.cs b/src/Datadog.Trace/Vendors/StatsdClient/StopWatchFactory.cs new file mode 100644 index 0000000000..ca4c772166 --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/StopWatchFactory.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class StopWatchFactory : IStopWatchFactory + { + public IStopwatch Get() + { + return new Stopwatch(); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/Stopwatch.cs b/src/Datadog.Trace/Vendors/StatsdClient/Stopwatch.cs new file mode 100644 index 0000000000..429519f11b --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/Stopwatch.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class Stopwatch : IStopwatch + { + private readonly System.Diagnostics.Stopwatch _stopwatch = new System.Diagnostics.Stopwatch(); + + public void Start() + { + _stopwatch.Start(); + } + + public void Stop() + { + _stopwatch.Stop(); + } + + public int ElapsedMilliseconds() + { + return (int) unchecked(_stopwatch.ElapsedMilliseconds); + } + } +} \ No newline at end of file diff --git a/src/Datadog.Trace/Vendors/StatsdClient/ThreadSafeRandom.cs b/src/Datadog.Trace/Vendors/StatsdClient/ThreadSafeRandom.cs new file mode 100644 index 0000000000..6723ad9d9b --- /dev/null +++ b/src/Datadog.Trace/Vendors/StatsdClient/ThreadSafeRandom.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +using System; + +namespace Datadog.Trace.Vendors.StatsdClient +{ + internal class ThreadSafeRandom + { + private static readonly Random _global = new Random(); + + [ThreadStatic] + private static Random _local; + + private Random Local + { + get + { + if (_local == null) + { + int seed; + lock (_global) + { + seed = _global.Next(); + } + _local = new Random(seed); + } + return _local; + } + } + + public double NextDouble() + { + return Local.NextDouble(); + } + } +} diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000000..93d7faa792 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,34 @@ + + + + + net45;net461;netstandard2.0 + true + + + true + https://github.com/DataDog/dd-trace-dotnet/raw/master/datadog-logo-64x64.png + packageIcon.png + https://docs.datadoghq.com/tracing/setup/dotnet/ + Apache-2.0 + false + See release notes at https://github.com/DataDog/dd-trace-dotnet/releases + Datadog;APM;tracing;profiling;instrumentation + git + https://github.com/DataDog/dd-trace-dotnet.git + Copyright 2017 Datadog, Inc. + Datadog + lucas.pimentel.datadog;colinhigginsdatadog;zachmontoyadd;bobuva + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/GlobalSuppressions.cs b/src/GlobalSuppressions.cs new file mode 100644 index 0000000000..147eabab9a --- /dev/null +++ b/src/GlobalSuppressions.cs @@ -0,0 +1,6 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 0000000000..679a86a9cd --- /dev/null +++ b/stylecop.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace" + }, + "documentationRules": { + "companyName": "Datadog", + "documentExposedElements": true, + + // TODO: document everything and remove this exclusions + "documentInternalElements": false, + "documentInterfaces": false + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj new file mode 100644 index 0000000000..167a063c14 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Datadog.Trace.ClrProfiler.Managed.Tests.csproj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationSignatureTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationSignatureTests.cs new file mode 100644 index 0000000000..e140d8fbe0 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationSignatureTests.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class IntegrationSignatureTests + { + // This is a list of instrumented methods that are static, i.e., the target method is static. + private static readonly List StaticInstrumentations = new List() + { + // This list is currently empty + }; + + public static IEnumerable GetWrapperMethodWithInterceptionAttributes() + { + var integrationsAssembly = typeof(Instrumentation).Assembly; + + foreach (var wrapperMethod in integrationsAssembly.GetTypes().SelectMany(t => t.GetRuntimeMethods())) + { + foreach (var interceptionAttribute in wrapperMethod.GetCustomAttributes(inherit: false)) + { + yield return new object[] { wrapperMethod, interceptionAttribute }; + } + } + } + + public static IEnumerable GetWrapperMethods() + { + return GetWrapperMethodWithInterceptionAttributes().Select(i => new[] { i[0] }).Distinct(); + } + + [Theory] + [MemberData(nameof(GetWrapperMethods))] + public void WrapperMethodHasOpCodeArgument(MethodInfo wrapperMethod) + { + // all wrapper methods should have an additional Int32 + // parameter for the original method call's opcode + var parameters = wrapperMethod.GetParameters(); + var param = parameters[parameters.Length - 3]; + Assert.Equal(typeof(int), param.ParameterType); + Assert.Equal("opCode", param.Name); + } + + [Theory] + [MemberData(nameof(GetWrapperMethods))] + public void WrapperMethodHasMdTokenArgument(MethodInfo wrapperMethod) + { + // all wrapper methods should have an additional Int32 + // parameter for the original method call's mdToken + var parameters = wrapperMethod.GetParameters(); + var param = parameters[parameters.Length - 2]; + Assert.Equal(typeof(int), param.ParameterType); + Assert.Equal("mdToken", param.Name); + } + + [Theory] + [MemberData(nameof(GetWrapperMethods))] + public void WrapperMethodHasModuleVersionPtrArgument(MethodInfo wrapperMethod) + { + // all wrapper methods should have an additional Int64 + // parameter for the address of calling module's moduleVersionId + var parameters = wrapperMethod.GetParameters(); + var param = parameters[parameters.Length - 1]; + Assert.Equal(typeof(long), param.ParameterType); + Assert.Equal("moduleVersionPtr", param.Name); + } + + [Theory] + [MemberData(nameof(GetWrapperMethodWithInterceptionAttributes))] + public void AllMethodsHaveProperlyFormedTargetSignatureTypes(MethodInfo wrapperMethod, InterceptMethodAttribute attribute) + { + Assert.True( + attribute.TargetSignatureTypes != null, + $"{wrapperMethod.DeclaringType.Name}.{wrapperMethod.Name}: {nameof(attribute.TargetSignatureTypes)} definition missing."); + + // add 1 for return type, subtract 3 for extra parameters (opcode, mdToken, moduleVersionPtr) + // 1 - 3 = -2 + var expectedParameterCount = wrapperMethod.GetParameters().Length - 2; + + if (!StaticInstrumentations.Contains(wrapperMethod)) + { + // Subtract the instance (this) parameter + expectedParameterCount--; + } + + var typeSigLength = attribute.TargetSignatureTypes.Length; + Assert.True( + expectedParameterCount == typeSigLength, + $"{wrapperMethod.DeclaringType.Name}.{wrapperMethod.Name}: {nameof(attribute.TargetSignatureTypes)} has {typeSigLength} items, expected {expectedParameterCount}."); + + Assert.False( + attribute.TargetSignatureTypes.Any(string.IsNullOrWhiteSpace), + $"{wrapperMethod.DeclaringType.Name}.{wrapperMethod.Name}: {nameof(attribute.TargetSignatureTypes)} has null or empty arguments."); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationVersionRangeTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationVersionRangeTests.cs new file mode 100644 index 0000000000..fa15089082 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/IntegrationVersionRangeTests.cs @@ -0,0 +1,116 @@ +using System; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class IntegrationVersionRangeTests + { + [Fact] + public void MinimumVersionTwoSetsResetsDefaultsForNonSpecifiedParts() + { + var range = new IntegrationVersionRange(); + range.MinimumVersion = "5.5.4"; + range.MinimumVersion = "6"; + Assert.Equal(expected: 6, actual: range.MinimumMajor); + Assert.Equal(expected: 0, actual: range.MinimumMinor); + Assert.Equal(expected: 0, actual: range.MinimumPatch); + } + + [Fact] + public void ParsesMinimumMajor() + { + var range = new IntegrationVersionRange(); + range.MinimumVersion = "5"; + Assert.Equal(expected: 5, actual: range.MinimumMajor); + } + + [Fact] + public void ParsesMinimumMajorAndMinor() + { + var range = new IntegrationVersionRange(); + range.MinimumVersion = "5.8"; + Assert.Equal(expected: 5, actual: range.MinimumMajor); + Assert.Equal(expected: 8, actual: range.MinimumMinor); + } + + [Fact] + public void ParsesMinimumMajorAndMinorAndPatch() + { + var range = new IntegrationVersionRange(); + range.MinimumVersion = "5.8.82"; + Assert.Equal(expected: 5, actual: range.MinimumMajor); + Assert.Equal(expected: 8, actual: range.MinimumMinor); + Assert.Equal(expected: 82, actual: range.MinimumPatch); + } + + [Fact] + public void MaximumVersionTwoSetsResetsDefaultsForNonSpecifiedParts() + { + var range = new IntegrationVersionRange(); + range.MaximumVersion = "5.5.4"; + range.MaximumVersion = "6"; + Assert.Equal(expected: 6, actual: range.MaximumMajor); + Assert.Equal(expected: ushort.MaxValue, actual: range.MaximumMinor); + Assert.Equal(expected: ushort.MaxValue, actual: range.MaximumPatch); + } + + [Fact] + public void ParsesMaximumMajor() + { + var range = new IntegrationVersionRange(); + range.MaximumVersion = "5"; + Assert.Equal(expected: 5, actual: range.MaximumMajor); + } + + [Fact] + public void ParsesMaximumMajorAndMinor() + { + var range = new IntegrationVersionRange(); + range.MaximumVersion = "5.8"; + Assert.Equal(expected: 5, actual: range.MaximumMajor); + Assert.Equal(expected: 8, actual: range.MaximumMinor); + } + + [Fact] + public void ParsesMaximumMajorAndMinorAndPatch() + { + var range = new IntegrationVersionRange(); + range.MaximumVersion = "5.8.82"; + Assert.Equal(expected: 5, actual: range.MaximumMajor); + Assert.Equal(expected: 8, actual: range.MaximumMinor); + Assert.Equal(expected: 82, actual: range.MaximumPatch); + } + + /// + /// We want to be sure that any versions we specify are explicit, so we'll throw as soon as we know there is anything unclear. + /// + [Fact] + public void ThrowsExceptionForNonNumbers() + { + Exception exMin = null; + Exception exMax = null; + var range = new IntegrationVersionRange(); + + try + { + range.MinimumVersion = "5.GARBAGE.82"; + } + catch (Exception e) + { + exMin = e; + } + + try + { + range.MaximumVersion = "5.35.MoreGarbage"; + } + catch (Exception e) + { + exMax = e; + } + + Assert.NotNull(exMin); + Assert.NotNull(exMax); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/MemberAccessorTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/MemberAccessorTests.cs new file mode 100644 index 0000000000..3073f1ae54 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/MemberAccessorTests.cs @@ -0,0 +1,87 @@ +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class MemberAccessorTests + { + public const string Name = "Smith"; + + public const int Age = 30; + + public Person TestPerson { get; } = new Person(Name, Age); + + [Fact] + public void TryCallMethod_Class() + { + var success = TestPerson.TryCallMethod("GetString", "test", out string result); + + Assert.True(success); + Assert.Equal("result: test", result); + } + + [Fact] + public void TryCallMethod_Struct() + { + var success = TestPerson.TryCallMethod("GetInt32", 5, out int result); + + Assert.True(success); + Assert.Equal(6, result); + } + + [Fact] + public void TryGetPropertyValue_Class() + { + var success = TestPerson.TryGetPropertyValue("Name", out string result); + + Assert.True(success); + Assert.Equal(Name, result); + } + + [Fact] + public void TryGetPropertyValue_Struct() + { + var success = TestPerson.TryGetPropertyValue("Age", out int result); + + Assert.True(success); + Assert.Equal(Age, result); + } + + [Fact] + public void TryGetFieldValue_Class() + { + var success = TestPerson.TryGetFieldValue("_name", out string result); + + Assert.True(success); + Assert.Equal(Name, result); + } + + [Fact] + public void TryGetFieldValue_Struct() + { + var success = TestPerson.TryGetFieldValue("_age", out int result); + + Assert.True(success); + Assert.Equal(Age, result); + } + + public class Person + { + private readonly string _name; + private readonly int _age; + + public Person(string name, int age) + { + _name = name; + _age = age; + } + + public string Name => _name; + + public int Age => _age; + + public string GetString(string value) => $"result: {value}"; + + public int GetInt32(int value) => value + 1; + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/ObjectExtensionTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ObjectExtensionTests.cs new file mode 100644 index 0000000000..ba5870dff3 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ObjectExtensionTests.cs @@ -0,0 +1,79 @@ +using Datadog.Trace.ClrProfiler.Emit; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ObjectExtensionTests + { + private enum SomeEnum + { + Zero = 0, + One = 1, + Two = 2 + } + + [Fact] + public void GetProperty_WithDifferentType_ShouldNotAffectResult() + { + SomeBaseClass someAbstractInstance = new SomeClass(); + var expected = someAbstractInstance.SomeIntProperty; + + var someCast = (object)someAbstractInstance; + + var objectResult = someCast.GetProperty("SomeIntProperty"); + var actualResult = someCast.GetProperty("SomeIntProperty"); + + Assert.Equal(expected, (int)objectResult.GetValueOrDefault()); + Assert.Equal(expected, actualResult.GetValueOrDefault()); + } + + [Fact] + public void GetProperty_WithNoDirectInheritance_ShouldNotAffectResult() + { + var someInstance = new SomeClass(); + var expected = someInstance.SomeEnumProperty; + + var someCast = (object)someInstance; + + var intResult = someCast.GetProperty("SomeEnumProperty"); + var actualResult = someCast.GetProperty("SomeEnumProperty"); + + Assert.Equal((int)expected, intResult.GetValueOrDefault()); + Assert.Equal(expected, actualResult.GetValueOrDefault()); + } + + [Fact] + public void GetField_WithDifferentType_ShouldNotAffectResult() + { + var someInstance = new SomeClass(); + var expected = someInstance.GetSomeIntField(); + + var someCast = (object)someInstance; + + var objectResult = someCast.GetField("someIntField"); + var actualResult = someCast.GetField("someIntField"); + + Assert.Equal(expected, (int)objectResult.GetValueOrDefault()); + Assert.Equal(expected, actualResult.GetValueOrDefault()); + } + + private class SomeClass : SomeBaseClass + { + private readonly int someIntField = 305; + + public override int SomeIntProperty { get; } = 205; + + public SomeEnum SomeEnumProperty { get; } = SomeEnum.Two; + + public int GetSomeIntField() + { + return someIntField; + } + } + + private abstract class SomeBaseClass + { + public abstract int SomeIntProperty { get; } + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/AbstractAlphabetClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/AbstractAlphabetClass.cs new file mode 100644 index 0000000000..f6b64fceb4 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/AbstractAlphabetClass.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class AbstractAlphabetClass + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassA.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassA.cs new file mode 100644 index 0000000000..de31bd2d95 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassA.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ClassA : AbstractAlphabetClass + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassB.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassB.cs new file mode 100644 index 0000000000..6c1b1549f0 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassB.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ClassB : ClassA + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassC.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassC.cs new file mode 100644 index 0000000000..d21f4b6ef9 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClassC.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ClassC : ClassB + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClosedGenericClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClosedGenericClass.cs new file mode 100644 index 0000000000..13e494e6af --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ClosedGenericClass.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ClosedGenericClass : OpenGenericClass + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodBuilderTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodBuilderTests.cs new file mode 100644 index 0000000000..6737db545e --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodBuilderTests.cs @@ -0,0 +1,262 @@ +using System; +using System.Reflection; +using Datadog.Trace.ClrProfiler.Emit; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + /// + /// All delegates we generate for instance methods include the instance as the first parameter + /// + public class MethodBuilderTests + { + private readonly Guid _moduleVersionId = Assembly.GetExecutingAssembly().ManifestModule.ModuleVersionId; + private readonly Type _testType = typeof(ObscenelyAnnoyingClass); + + [Fact] + public void AmbiguousParameters_ClassASystemObjectClassA_CallsExpectedMethod() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassA(); + var p2 = new object(); + var p3 = new ClassA(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + var methodResult = Build>(expected.Name).WithParameters(p1, p2, p3).Build(); + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void AmbiguousParameters_ClassAClassAClassA_CallsExpectedMethod() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassA(); + var p2 = new ClassA(); + var p3 = new ClassA(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + var methodResult = Build>(expected.Name).WithParameters(p1, p2, p3).Build(); + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void AmbiguousParameters_ClassAClassBClassB_CallsExpectedMethod() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassA(); + var p2 = new ClassB(); + var p3 = new ClassB(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + var methodResult = Build>(expected.Name).WithParameters(p1, p2, p3).Build(); + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void AmbiguousParameters_ClassBClassCClassC_CallsExpectedMethod() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassB(); + var p2 = new ClassC(); + var p3 = new ClassC(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + var methodResult = Build>(expected.Name).WithParameters(p1, p2, p3).Build(); + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void AmbiguousParameters_ClassCClassCClassC_CallsExpectedMethod_WithNamespaceNameFilter() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassC(); + var p2 = new ClassC(); + var p3 = new ClassC(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + + var methodResult = + Build>(expected.Name) + .WithParameters(p1, p2, p3) + .WithNamespaceAndNameFilters( + ClrNames.Void, + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassB", + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassC", + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassC") + .Build(); + + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void AmbiguousParameters_ClassCClassBClassA_CallsExpectedMethod_WithNamespaceNameFilter() + { + var instance = new ObscenelyAnnoyingClass(); + var p1 = new ClassC(); + var p2 = new ClassB(); + var p3 = new ClassA(); + var expected = MethodReference.Get(() => instance.Method(p1, p2, p3)); + + var methodResult = + Build>(expected.Name) + .WithParameters(p1, p2, p3) + .WithNamespaceAndNameFilters( + ClrNames.Void, + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassA", + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassA", + "Datadog.Trace.ClrProfiler.Managed.Tests.ClassA") + .Build(); + + methodResult(instance, p1, p2, p3); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void NoParameters_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + var expected = MethodReference.Get(() => instance.Method()); + var methodResult = Build>(expected.Name).Build(); + methodResult(instance); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void IntParameter_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + int parameter = 1; + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void LongParameter_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + long parameter = 1; + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void ShortParameter_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + short parameter = 1; + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void ObjectParameter_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + object parameter = new object(); + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void StringParameter_ProperlyCalled() + { + var instance = new ObscenelyAnnoyingClass(); + string parameter = string.Empty; + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void StringParameterAsObject_ProperlyCalls_ObjectMethod_WithNamespaceNameFilter() + { + var instance = new ObscenelyAnnoyingClass(); + object parameter = string.Empty; + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = + Build>(expected.Name) + .WithParameters(parameter) + .WithNamespaceAndNameFilters(ClrNames.Void, ClrNames.Object) + .Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + [Fact] + public void DeclaringTypeGenericParameter_ProperlyCalls_ClosedGenericMethod() + { + var instance = new ObscenelyAnnoyingGenericClass(); + var parameter = new ClassA(); + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = Build>(expected.Name, overrideType: instance.GetType()).WithParameters(parameter).Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.MetadataToken, instance.LastCall.MetadataToken); + } + + [Fact] + public void DeclaringTypeGenericParameter_WithOpenGenericMethod_ProperlyCalls_OpenGenericMethod() + { + var instance = new ObscenelyAnnoyingGenericClass(); + var parameter = new ClassA(); + var expected = MethodReference.Get(() => instance.Method(parameter)); + var methodResult = + Build>(expected.Name, overrideType: instance.GetType()) + .WithParameters(parameter) + .WithMethodGenerics(typeof(int)) + .Build(); + methodResult(instance, parameter); + Assert.Equal(expected: expected.MetadataToken, instance.LastCall.MetadataToken); + } + + [Fact] + public void DeclaringTypeGenericTypeParam_ThenMethodGenericParam_ProperlyCalls_Method() + { + var instance = new ObscenelyAnnoyingGenericClass(); + var parameter1 = new ClassA(); + int parameter2 = 1; + var expected = MethodReference.Get(() => instance.Method(parameter1, parameter2)); + var methodResult = + Build>(expected.Name, overrideType: instance.GetType()) + .WithParameters(parameter1, parameter2) + .WithMethodGenerics(typeof(int)) + .Build(); + methodResult(instance, parameter1, parameter2); + Assert.Equal(expected: expected.MetadataToken, instance.LastCall.MetadataToken); + } + + [Fact] + public void WrongMetadataToken_NonSpecificDelegateSignature_GetsCorrectMethodAnyways() + { + var instance = new ObscenelyAnnoyingClass(); + var wrongMethod = MethodReference.Get(() => instance.Method(1)); + + string parameter = string.Empty; + var expected = MethodReference.Get(() => instance.Method(parameter)); + + var methodResult = MethodBuilder> // Proper use should be Action + .Start(_moduleVersionId, wrongMethod.MetadataToken, (int)OpCodeValue.Callvirt, "Method") + .WithConcreteType(_testType) + .WithParameters(parameter) // The parameter is the saving grace + .Build(); + + methodResult(instance, parameter); + Assert.Equal(expected: expected.ToString(), instance.LastCall.MethodString); + } + + private MethodBuilder Build(string methodName, Type overrideType = null) + { + return MethodBuilder + .Start(_moduleVersionId, 0, (int)OpCodeValue.Callvirt, methodName) + .WithConcreteType(overrideType ?? _testType); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodCallMetadata.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodCallMetadata.cs new file mode 100644 index 0000000000..ed4c31a7d6 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodCallMetadata.cs @@ -0,0 +1,11 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class MethodCallMetadata + { + public string MethodString { get; set; } + + public int MetadataToken { get; set; } + + public object[] Parameters { get; set; } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodReference.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodReference.cs new file mode 100644 index 0000000000..4c4af8ef1f --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/MethodReference.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq.Expressions; +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + /// + /// Gives access to from expressions. This is useful + /// because it allows static checking of the existence of the method. + /// + internal static class MethodReference + { + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression method) + { + return GetMethodFromExpression(method); + } + + public static MethodInfo Get(Expression> method) + { + return GetMethodFromExpression(method); + } + + private static MethodInfo GetMethodFromExpression(LambdaExpression method) + { + var methodCall = method.Body as MethodCallExpression; + if (methodCall == null) + { + throw new ArgumentException("The expression must be a method call.", nameof(method)); + } + + return methodCall.Method; + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ModuleLookupTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ModuleLookupTests.cs new file mode 100644 index 0000000000..512ae0b56c --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ModuleLookupTests.cs @@ -0,0 +1,70 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.Emit; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ModuleLookupTests + { + [Fact] + public void Lookup_SystemData_Succeeds_WithTwentyConcurrentTries() + { + var tasks = new Task[20]; + var resetEvent = new ManualResetEventSlim(initialState: false); + var bag = new ConcurrentBag(); + var systemDataGuid = typeof(System.Data.DataTable).Assembly.ManifestModule.ModuleVersionId; + + for (var i = 0; i < 20; i++) + { + tasks[i] = Task.Run(() => + { + resetEvent.Wait(); + bag.Add(ModuleLookup.Get(systemDataGuid)); + }); + } + + resetEvent.Set(); + + Task.WaitAll(tasks); + + Assert.True(bag.All(m => m.ModuleVersionId == systemDataGuid) && bag.Count() == tasks.Length); + } + + [Fact] + public void Lookup_Self_Succeeds() + { + var expectedModule = typeof(ModuleLookupTests).Assembly.ManifestModule; + var lookup = ModuleLookup.Get(expectedModule.ModuleVersionId); + Assert.Equal(expectedModule, lookup); + } + + [Fact] + public void Lookup_DatadogTraceClrProfilerManaged_Succeeds() + { + var expectedModule = typeof(MethodBuilder<>).Assembly.ManifestModule; + var lookup = ModuleLookup.Get(expectedModule.ModuleVersionId); + Assert.Equal(expectedModule, lookup); + } + + [Fact] + public void Lookup_DatadogTrace_Succeeds() + { + var expectedModule = typeof(Span).Assembly.ManifestModule; + var lookup = ModuleLookup.Get(expectedModule.ModuleVersionId); + Assert.Equal(expectedModule, lookup); + } + + [Fact] + public void Lookup_SystemData_Succeeds() + { + var expectedModule = typeof(System.Data.DataTable).Assembly.ManifestModule; + var lookup = ModuleLookup.Get(expectedModule.ModuleVersionId); + Assert.Equal(expectedModule, lookup); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/NestedOpenGenericClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/NestedOpenGenericClass.cs new file mode 100644 index 0000000000..e7b71d4a2f --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/NestedOpenGenericClass.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class NestedOpenGenericClass : OpenGenericClass + { + } +} \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingClass.cs new file mode 100644 index 0000000000..69750a8584 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingClass.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ObscenelyAnnoyingClass + { + public MethodCallMetadata LastCall { get; private set; } + + public Dictionary> CallCountsPerMetadataToken { get; } = new Dictionary>(); + + public void Method() + { + SetLastCall(MethodBase.GetCurrentMethod()); + } + + public void Method(int i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(object i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(string i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(long i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(short i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(ClassB p1, ClassC p2, ClassC p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + public void Method(object p1, object p2, object p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + public void Method(ClassA p1, ClassA p2, ClassA p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + public void Method(ClassA p1, ClassB p2, ClassB p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + public void Method(AbstractAlphabetClass p1, AbstractAlphabetClass p2, AbstractAlphabetClass p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + public void Method(ClassB p1, ClassB p2, ClassB p3) + { + SetLastCall(MethodBase.GetCurrentMethod(), p1, p2, p3); + } + + // There is intentionally no method matching double ClassC signature to force non-explicit fuzzy matching + // public void Method(ClassC p1, ClassC p2) + + protected void SetLastCall(MethodBase currentMethod, params object[] wholeBunchOfGarbage) + { + if (CallCountsPerMetadataToken.ContainsKey(currentMethod.MetadataToken) == false) + { + CallCountsPerMetadataToken.Add(currentMethod.MetadataToken, new List()); + } + + LastCall = new MethodCallMetadata { MethodString = currentMethod.ToString(), MetadataToken = currentMethod.MetadataToken, Parameters = wholeBunchOfGarbage }; + CallCountsPerMetadataToken[currentMethod.MetadataToken].Add(LastCall); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingGenericClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingGenericClass.cs new file mode 100644 index 0000000000..ecbdc9832f --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/ObscenelyAnnoyingGenericClass.cs @@ -0,0 +1,32 @@ +using System.Reflection; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ObscenelyAnnoyingGenericClass : ObscenelyAnnoyingClass + { + public void Method(Tc1 i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(Tc1 i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i, default(Tm1)); + } + + public void Method(Tm1 i) + { + SetLastCall(MethodBase.GetCurrentMethod(), i); + } + + public void Method(Tm1 i, Tc1 i2) + { + SetLastCall(MethodBase.GetCurrentMethod(), i, i2); + } + + public void Method(Tc1 i, Tm1 i2) + { + SetLastCall(MethodBase.GetCurrentMethod(), i, i2); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/OpenGenericClass.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/OpenGenericClass.cs new file mode 100644 index 0000000000..ffdd02bee1 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/Reflection/OpenGenericClass.cs @@ -0,0 +1,6 @@ +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class OpenGenericClass + { + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/ReflectionHttpHeadersCollectionTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ReflectionHttpHeadersCollectionTests.cs new file mode 100644 index 0000000000..732760e252 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ReflectionHttpHeadersCollectionTests.cs @@ -0,0 +1,187 @@ +using System.Collections.Generic; +using System.Globalization; +using System.Net.Http; +using System.Net.Http.Headers; +using Datadog.Trace.ClrProfiler.Helpers; +using Datadog.Trace.Headers; +using Datadog.Trace.TestHelpers; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ReflectionHttpHeadersCollectionTests + { + public static IEnumerable GetInvalidIds() => HeadersCollectionTestHelpers.GetInvalidIds(); + + public static IEnumerable GetInvalidSamplingPriorities() => HeadersCollectionTestHelpers.GetInvalidSamplingPriorities(); + + [Fact] + public void ExtractHeaderTags_EmptyHeadersReturnsEmptyTagsList() + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + var tagsFromHeader = SpanContextPropagator.Instance.ExtractHeaderTags(headers, new Dictionary()); + + Assert.NotNull(tagsFromHeader); + Assert.Empty(tagsFromHeader); + } + + [Fact] + public void ExtractHeaderTags_MatchesCaseInsensitive() + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + // Initialize constants + const string customHeader1Name = "dd-custom-header1"; + const string customHeader1Value = "match1"; + const string customHeader1TagName = "custom-header1-tag"; + + const string customHeader2Name = "DD-CUSTOM-HEADER-MISMATCHING-CASE"; + const string customHeader2Value = "match2"; + const string customHeader2TagName = "custom-header2-tag"; + string customHeader2LowercaseHeaderName = customHeader2Name.ToLowerInvariant(); + + // Initialize WebRequest and add headers + headers.Add(customHeader1Name, customHeader1Value); + headers.Add(customHeader2Name, customHeader2Value); + + // Initialize header tag arguments + var headerToTagMap = new Dictionary(); + headerToTagMap.Add(customHeader1Name, customHeader1TagName); + headerToTagMap.Add(customHeader2LowercaseHeaderName, customHeader2TagName); + + // Set expectations + var expectedResults = new Dictionary(); + expectedResults.Add(customHeader1TagName, customHeader1Value); + expectedResults.Add(customHeader2TagName, customHeader2Value); + + // Test + var tagsFromHeader = SpanContextPropagator.Instance.ExtractHeaderTags(headers, headerToTagMap); + + // Assert + Assert.NotNull(tagsFromHeader); + Assert.Equal(expectedResults, tagsFromHeader); + } + + [Fact] + public void Extract_EmptyHeadersReturnsNull() + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + var resultContext = SpanContextPropagator.Instance.Extract(headers); + Assert.Null(resultContext); + } + + [Fact] + public void InjectExtract_Identity() + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + const int traceId = 9; + const int spanId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + var context = new SpanContext(traceId, spanId, samplingPriority, null, origin); + SpanContextPropagator.Instance.Inject(context, headers); + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(context.SpanId, resultContext.SpanId); + Assert.Equal(context.TraceId, resultContext.TraceId); + Assert.Equal(context.SamplingPriority, resultContext.SamplingPriority); + Assert.Equal(context.Origin, resultContext.Origin); + } + + [Theory] + [MemberData(nameof(GetInvalidIds))] + public void Extract_InvalidTraceId(string traceId) + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + const string spanId = "7"; + const string samplingPriority = "2"; + const string origin = "synthetics"; + + InjectContext(headers, traceId, spanId, samplingPriority, origin); + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + // invalid traceId should return a null context even if other values are set + Assert.Null(resultContext); + } + + [Theory] + [MemberData(nameof(GetInvalidIds))] + public void Extract_InvalidSpanId(string spanId) + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + const ulong traceId = 9; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + InjectContext( + headers, + traceId.ToString(CultureInfo.InvariantCulture), + spanId, + ((int)samplingPriority).ToString(CultureInfo.InvariantCulture), + origin); + + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(traceId, resultContext.TraceId); + Assert.Equal(default(ulong), resultContext.SpanId); + Assert.Equal(samplingPriority, resultContext.SamplingPriority); + Assert.Equal(origin, resultContext.Origin); + } + + [Theory] + [MemberData(nameof(GetInvalidSamplingPriorities))] + public void Extract_InvalidSamplingPriority(string samplingPriority) + { + // HttpRequestHeaders setup + var request = new HttpRequestMessage(); + var headers = new ReflectionHttpHeadersCollection(request.Headers); + + const ulong traceId = 9; + const ulong spanId = 7; + const string origin = "synthetics"; + + InjectContext( + headers, + traceId.ToString(CultureInfo.InvariantCulture), + spanId.ToString(CultureInfo.InvariantCulture), + samplingPriority, + origin); + + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(traceId, resultContext.TraceId); + Assert.Equal(spanId, resultContext.SpanId); + Assert.Null(resultContext.SamplingPriority); + Assert.Equal(origin, resultContext.Origin); + } + + private static void InjectContext(IHeadersCollection headers, string traceId, string spanId, string samplingPriority, string origin) + { + headers.Add(HttpHeaderNames.TraceId, traceId); + headers.Add(HttpHeaderNames.ParentId, spanId); + headers.Add(HttpHeaderNames.SamplingPriority, samplingPriority); + headers.Add(HttpHeaderNames.Origin, origin); + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/ScopeFactoryTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ScopeFactoryTests.cs new file mode 100644 index 0000000000..728dfb5751 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/ScopeFactoryTests.cs @@ -0,0 +1,125 @@ +using System; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Datadog.Trace.Util; +using Moq; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class ScopeFactoryTests + { + // declare here instead of using ScopeFactory.UrlIdPlaceholder so tests fails if value changes + private const string Id = "?"; + + [Theory] + [InlineData("users/", "users/")] + [InlineData("users", "users")] + [InlineData("123/", Id + "/")] + [InlineData("123", Id)] + [InlineData("4294967294/", Id + "/")] + [InlineData("4294967294", Id)] + [InlineData("E653C852-227B-4F0C-9E48-D30D83C68BF3/", Id + "/")] + [InlineData("E653C852-227B-4F0C-9E48-D30D83C68BF3", Id)] + [InlineData("E653C852227B4F0C9E48D30D83C68BF3/", Id + "/")] + [InlineData("E653C852227B4F0C9E48D30D83C68BF3", Id)] + public void CleanUriSegment(string segment, string expected) + { + string actual = UriHelpers.CleanUriSegment(segment); + + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData("https://username:password@example.com/path/to/file.aspx?query=1#fragment", "GET", "GET example.com/path/to/file.aspx")] + [InlineData("https://username@example.com/path/to/file.aspx", "GET", "GET example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/to/file.aspx?query=1", "GET", "GET example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/to/file.aspx#fragment", "GET", "GET example.com/path/to/file.aspx")] + [InlineData("http://example.com/path/to/file.aspx", "GET", "GET example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/123/file.aspx", "GET", "GET example.com/path/" + Id + "/file.aspx")] + [InlineData("https://example.com/path/123/", "GET", "GET example.com/path/" + Id + "/")] + [InlineData("https://example.com/path/123", "GET", "GET example.com/path/" + Id)] + [InlineData("https://example.com/path/4294967294/file.aspx", "GET", "GET example.com/path/" + Id + "/file.aspx")] + [InlineData("https://example.com/path/4294967294/", "GET", "GET example.com/path/" + Id + "/")] + [InlineData("https://example.com/path/4294967294", "GET", "GET example.com/path/" + Id)] + [InlineData("https://example.com/path/E653C852-227B-4F0C-9E48-D30D83C68BF3", "GET", "GET example.com/path/" + Id)] + [InlineData("https://example.com/path/E653C852227B4F0C9E48D30D83C68BF3", "GET", "GET example.com/path/" + Id)] + public void CleanUri_ResourceName(string uri, string method, string expected) + { + // Set up Tracer + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + var tracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + + const string integrationName = "HttpMessageHandler"; + + using (var automaticScope = ScopeFactory.CreateOutboundHttpScope(tracer, method, new Uri(uri), integrationName)) + { + Assert.Equal(expected, automaticScope.Span.ResourceName); + } + } + + [Theory] + [InlineData("https://username:password@example.com/path/to/file.aspx?query=1#fragment", "https://example.com/path/to/file.aspx")] + [InlineData("https://username@example.com/path/to/file.aspx", "https://example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/to/file.aspx?query=1", "https://example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/to/file.aspx#fragment", "https://example.com/path/to/file.aspx")] + [InlineData("http://example.com/path/to/file.aspx", "http://example.com/path/to/file.aspx")] + [InlineData("https://example.com/path/123/file.aspx", "https://example.com/path/123/file.aspx")] + [InlineData("https://example.com/path/123/", "https://example.com/path/123/")] + [InlineData("https://example.com/path/123", "https://example.com/path/123")] + [InlineData("https://example.com/path/E653C852-227B-4F0C-9E48-D30D83C68BF3", "https://example.com/path/E653C852-227B-4F0C-9E48-D30D83C68BF3")] + [InlineData("https://example.com/path/E653C852227B4F0C9E48D30D83C68BF3", "https://example.com/path/E653C852227B4F0C9E48D30D83C68BF3")] + public void CleanUri_HttpUrlTag(string uri, string expected) + { + // Set up Tracer + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + var tracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + + const string method = "GET"; + const string integrationName = "HttpMessageHandler"; + + using (var automaticScope = ScopeFactory.CreateOutboundHttpScope(tracer, method, new Uri(uri), integrationName)) + { + Assert.Equal(expected, automaticScope.Span.GetTag(Tags.HttpUrl)); + } + } + + [Theory] + [InlineData("HttpMessageHandler", "HttpMessageHandler")] // This scenario may occur on any .NET runtime with nested HttpMessageHandler's and HttpSocketHandler's + [InlineData("WebRequest", "HttpMessageHandler")] // This scenario may occur on .NET Core where the underlying transport for WebRequest is HttpMessageHandler + public void CreateOutboundHttpScope_AlwaysCreatesOneAutomaticInstrumentationScope(string integrationName1, string integrationName2) + { + // Set up Tracer + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + var tracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + + const string method = "GET"; + const string url = "http://www.contoso.com"; + + // Manually create a span decorated with HTTP information + using (var manualScope = tracer.StartActive("http.request")) + { + manualScope.Span.Type = SpanTypes.Http; + manualScope.Span.ResourceName = $"{method} {url}"; + manualScope.Span.ServiceName = $"{tracer.DefaultServiceName}-http-client"; + + using (var automaticScope1 = ScopeFactory.CreateOutboundHttpScope(tracer, method, new Uri(url), integrationName1)) + { + using (var automaticScope2 = ScopeFactory.CreateOutboundHttpScope(tracer, method, new Uri(url), integrationName2)) + { + Assert.NotNull(manualScope); + Assert.NotNull(automaticScope1); + Assert.Null(automaticScope2); + } + } + } + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Managed.Tests/TypeNameTests.cs b/test/Datadog.Trace.ClrProfiler.Managed.Tests/TypeNameTests.cs new file mode 100644 index 0000000000..6397928335 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Managed.Tests/TypeNameTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Xunit; + +namespace Datadog.Trace.ClrProfiler.Managed.Tests +{ + public class TypeNameTests + { + public static IEnumerable GetConstTypeAssociations() + { + yield return new object[] { ClrNames.Ignore, "_" }; + yield return new object[] { ClrNames.Void, typeof(void) }; + yield return new object[] { ClrNames.Object, typeof(object) }; + yield return new object[] { ClrNames.Bool, typeof(bool) }; + yield return new object[] { ClrNames.String, typeof(string) }; + yield return new object[] { ClrNames.SByte, typeof(sbyte) }; + yield return new object[] { ClrNames.Int16, typeof(short) }; + yield return new object[] { ClrNames.Int32, typeof(int) }; + yield return new object[] { ClrNames.Int64, typeof(long) }; + yield return new object[] { ClrNames.Byte, typeof(byte) }; + yield return new object[] { ClrNames.UInt16, typeof(ushort) }; + yield return new object[] { ClrNames.UInt32, typeof(uint) }; + yield return new object[] { ClrNames.UInt64, typeof(ulong) }; + yield return new object[] { ClrNames.CancellationToken, typeof(System.Threading.CancellationToken) }; + yield return new object[] { ClrNames.Task, typeof(Task) }; + yield return new object[] { ClrNames.IAsyncResult, typeof(IAsyncResult) }; + yield return new object[] { ClrNames.AsyncCallback, typeof(AsyncCallback) }; + yield return new object[] { ClrNames.HttpRequestMessage, typeof(System.Net.Http.HttpRequestMessage) }; + yield return new object[] { ClrNames.HttpResponseMessageTask, "System.Threading.Tasks.Task`1" }; // Generic full names have square brackets + yield return new object[] { ClrNames.GenericTask, typeof(Task<>) }; + } + + [Fact] + public void EveryMemberOfTypeNamesIsRepresented() + { + var associations = GetConstTypeAssociations().Select(i => i[0]).ToList(); + var expectedItems = + typeof(ClrNames) + .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy) + .Where(fi => fi.IsLiteral && !fi.IsInitOnly && fi.FieldType == typeof(string)) + .ToList(); + + Assert.Equal(actual: associations.Count, expected: expectedItems.Count); + + var missing = new List(); + foreach (var expectedItem in expectedItems) + { + var value = (string)expectedItem.GetRawConstantValue(); + if (associations.Contains(value)) + { + continue; + } + + missing.Add(value); + } + + Assert.Empty(missing); + } + + [Theory] + [MemberData(nameof(GetConstTypeAssociations))] + public void MatchesExpectedTypeName(string constant, object type) + { + if (type is Type) + { + Assert.Equal(constant, ((Type)type).FullName); + } + + if (type is string) + { + Assert.Equal(constant, (string)type); + } + } + } +} diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/Datadog.Trace.ClrProfiler.Native.Tests.vcxproj b/test/Datadog.Trace.ClrProfiler.Native.Tests/Datadog.Trace.ClrProfiler.Native.Tests.vcxproj new file mode 100644 index 0000000000..28c78c391a --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/Datadog.Trace.ClrProfiler.Native.Tests.vcxproj @@ -0,0 +1,181 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + {5728056a-51aa-4ff5-ad0c-e86e44e36102} + Win32Proj + 10.0 + Application + v142 + Unicode + v4.5 + + + + true + + + true + + + + + + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\$(Platform)\ + + + bin\$(Configuration)\x86\ + obj\$(Configuration)\x86\ + + + bin\$(Configuration)\x86\ + obj\$(Configuration)\x86\ + + + bin\$(Configuration)\$(Platform)\ + obj\$(Configuration)\$(Platform)\ + + + $(OutDir) + + + + + + + + + + + + + Create + Create + Create + Create + + + + + + + + + {4b243cf1-4269-45c6-a238-1a9bfa58b8cc} + + + {fdb5c8d0-018d-4ff9-9680-c6a5078f819b} + + + {91b6272f-5780-4c94-8071-dbba7b4f67f3} + + + + + + + + + + + Disabled + EnableFastChecks + MultiThreadedDebug + stdcpp17 + true + pch.h + Level3 + true + + + true + Console + + + + + Disabled + EnableFastChecks + MultiThreadedDebug + stdcpp17 + false + true + pch.h + Level3 + true + + + true + Console + + + + + MultiThreaded + Level3 + stdcpp17 + AnySuitable + true + Speed + true + true + true + pch.h + true + + + true + Console + true + true + + + + + MultiThreaded + Level3 + stdcpp17 + AnySuitable + true + Speed + true + true + true + pch.h + true + + + true + Console + true + true + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props b/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props new file mode 100644 index 0000000000..8c119d5413 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/Directory.Build.props @@ -0,0 +1,2 @@ + + diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_test.cpp new file mode 100644 index 0000000000..e6430f39d5 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_test.cpp @@ -0,0 +1,443 @@ +#include "pch.h" + +#include "../../src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h" +#include "test_helpers.h" + +using namespace trace; + +class CLRHelperTest : public ::CLRHelperTestBase {}; + +TEST_F(CLRHelperTest, EnumeratesTypeDefs) { + std::vector expected_types = { + L"Samples.ExampleLibrary.Class1", + L"Samples.ExampleLibrary.GenericTests.ComprehensiveCaller`2", + L"Samples.ExampleLibrary.GenericTests.GenericTarget`2", + L"Samples.ExampleLibrary.GenericTests.PointStruct", + L"Samples.ExampleLibrary.GenericTests.StructContainer`1", + L"Samples.ExampleLibrary.FakeClient.Biscuit`1", + L"Samples.ExampleLibrary.FakeClient.Biscuit", + L"Samples.ExampleLibrary.FakeClient.DogClient`2", + L"Samples.ExampleLibrary.FakeClient.DogTrick`1", + L"Samples.ExampleLibrary.FakeClient.DogTrick", + L"<>c", + L"Cookie", + L"d__4`2", + L"Raisin"}; + + std::vector actual_types; + + for (auto& def : EnumTypeDefs(metadata_import_)) { + std::wstring name(256, 0); + DWORD name_sz = 0; + DWORD flags = 0; + mdToken extends = 0; + auto hr = metadata_import_->GetTypeDefProps( + def, name.data(), (DWORD)(name.size()), &name_sz, &flags, &extends); + ASSERT_TRUE(SUCCEEDED(hr)); + + if (name_sz > 0) { + name = name.substr(0, name_sz - 1); + actual_types.push_back(name); + } + } + + EXPECT_EQ(expected_types, actual_types); +} + +TEST_F(CLRHelperTest, EnumeratesAssemblyRefs) { + std::vector expected_assemblies = { + L"System.Runtime", + L"System.Collections", + L"System.Threading.Tasks", + L"System.Diagnostics.Debug"}; + std::vector actual_assemblies; + for (auto& ref : EnumAssemblyRefs(assembly_import_)) { + auto name = GetReferencedAssemblyMetadata(assembly_import_, ref).name; + if (!name.empty()) { + actual_assemblies.push_back(name); + } + } + EXPECT_EQ(expected_assemblies, actual_assemblies); +} + +TEST_F(CLRHelperTest, FiltersEnabledIntegrations) { + Integration i1 = {L"integration-1", + {{{}, + {L"Samples.ExampleLibrary", + L"SomeType", + L"SomeMethod", + L"ReplaceTargetMethod", + min_ver_, + max_ver_, + {}, + empty_sig_type_}, + {}}}}; + Integration i2 = { + L"integration-2", + {{{}, + {L"Assembly.Two", L"SomeType", L"SomeMethod", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, + {}}}}; + Integration i3 = { + L"integration-3", + {{{}, {L"System.Runtime", L"", L"", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, {}}}}; + std::vector all = {i1, i2, i3}; + std::vector expected = {i1, i3}; + std::vector disabled_integrations = {"integration-2"_W}; + auto actual = FilterIntegrationsByName(all, disabled_integrations); + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, FiltersIntegrationsByCaller) { + Integration i1 = { + L"integration-1", + {{{L"Assembly.One", L"SomeType", L"SomeMethod", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, + {}, + {}}}}; + Integration i2 = { + L"integration-2", + {{{L"Assembly.Two", L"SomeType", L"SomeMethod", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, + {}, + {}}}}; + Integration i3 = {L"integration-3", {{{}, {}, {}}}}; + auto all = FlattenIntegrations({i1, i2, i3}); + auto expected = FlattenIntegrations({i1, i3}); + ModuleID manifest_module_id{}; + AppDomainID app_domain_id{}; + trace::AssemblyInfo assembly_info = { 1, L"Assembly.One", manifest_module_id, app_domain_id, L"AppDomain1"}; + auto actual = FilterIntegrationsByCaller(all, assembly_info); + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, FiltersIntegrationsByTarget) { + Integration i1 = {L"integration-1", + {{{}, + {L"Samples.ExampleLibrary", + L"SomeType", + L"SomeMethod", + L"ReplaceTargetMethod", + min_ver_, + max_ver_, + {}, + empty_sig_type_}, + {}}}}; + Integration i2 = { + L"integration-2", + {{{}, + {L"Assembly.Two", L"SomeType", L"SomeMethod", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, + {}}}}; + Integration i3 = { + L"integration-3", + {{{}, {L"System.Runtime", L"", L"", L"ReplaceTargetMethod", min_ver_, max_ver_, {}, empty_sig_type_}, {}}}}; + auto all = FlattenIntegrations({i1, i2, i3}); + auto expected = FlattenIntegrations({i1, i3}); + auto actual = FilterIntegrationsByTarget(all, assembly_import_); + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, FiltersFlattenedIntegrationMethodsByTargetAssembly) { + MethodReplacement included_method = {{}, + {L"Samples.Included", + L"SomeType", + L"SomeMethod", + L"ReplaceTargetMethod", + min_ver_, + max_ver_, + {}, + empty_sig_type_}, + {}}; + + MethodReplacement excluded_method = {{}, + {L"Samples.Excluded", + L"SomeType", + L"SomeMethod", + L"ReplaceTargetMethod", + min_ver_, + max_ver_, + {}, + empty_sig_type_}, + {}}; + + Integration mixed_integration = {L"integration-1", {included_method, excluded_method}}; + Integration included_integration = {L"integration-2", {included_method}}; + Integration excluded_integration = {L"integration-3", {excluded_method}}; + auto all = FlattenIntegrations({mixed_integration, included_integration, excluded_integration}); + auto expected = FlattenIntegrations({{L"integration-1", {included_method}}, included_integration}); + auto actual = FilterIntegrationsByTargetAssemblyName(all, {L"Samples.Excluded"}); + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, FiltersFlattenedIntegrationMethodsByTarget) { + MethodReference included = {L"Samples.ExampleLibrary", + L"SomeType", + L"SomeMethod", + L"ReplaceTargetMethod", + min_ver_, + max_ver_, + {}, + empty_sig_type_}; + + MethodReference excluded = {L"Samples.ExampleLibrary", + L"SomeType", + L"SomeOtherMethod", + L"ReplaceTargetMethod", + Version(0, 0, 0, 0), + Version(0, 1, 0, 0), + {}, + empty_sig_type_}; + + Integration i1 = {L"integration-1", {{{}, included, {}}, {{}, excluded, {}}}}; + auto all = FlattenIntegrations({i1}); + auto filtered = FilterIntegrationsByTarget(all, assembly_import_); + bool foundExclusion = false; + for (auto& item : filtered) { + if (item.replacement.target_method == excluded) { + foundExclusion = true; + } + } + EXPECT_FALSE(foundExclusion) + << "Expected method within integration to be filtered by version."; +} + +TEST_F(CLRHelperTest, GetsTypeInfoFromTypeDefs) { + std::set expected = { + L"<>c", + L"d__4`2", + L"Cookie", + L"Raisin", + L"Samples.ExampleLibrary.Class1", + L"Samples.ExampleLibrary.FakeClient.Biscuit", + L"Samples.ExampleLibrary.FakeClient.Biscuit`1", + L"Samples.ExampleLibrary.FakeClient.DogClient`2", + L"Samples.ExampleLibrary.FakeClient.DogTrick", + L"Samples.ExampleLibrary.FakeClient.DogTrick`1", + L"Samples.ExampleLibrary.GenericTests.ComprehensiveCaller`2", + L"Samples.ExampleLibrary.GenericTests.GenericTarget`2", + L"Samples.ExampleLibrary.GenericTests.PointStruct", + L"Samples.ExampleLibrary.GenericTests.StructContainer`1"}; + std::set actual; + for (auto& type_def : EnumTypeDefs(metadata_import_)) { + auto type_info = GetTypeInfo(metadata_import_, type_def); + if (type_info.IsValid()) { + actual.insert(type_info.name); + } + } + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, GetsTypeInfoFromTypeRefs) { + std::set expected = { + L"DebuggingModes", + L"Enumerator", + L"System.Array", + L"System.Collections.DictionaryEntry", + L"System.Collections.Generic.Dictionary`2", + L"System.Collections.Generic.IList`1", + L"System.Collections.Generic.List`1", + L"System.Diagnostics.DebuggableAttribute", + L"System.Diagnostics.DebuggerBrowsableAttribute", + L"System.Diagnostics.DebuggerBrowsableState", + L"System.Diagnostics.DebuggerHiddenAttribute", + L"System.Diagnostics.DebuggerStepThroughAttribute", + L"System.Exception", + L"System.Func`3", + L"System.Guid", + L"System.Int32", + L"System.Object", + L"System.Reflection.AssemblyCompanyAttribute", + L"System.Reflection.AssemblyConfigurationAttribute", + L"System.Reflection.AssemblyFileVersionAttribute", + L"System.Reflection.AssemblyInformationalVersionAttribute", + L"System.Reflection.AssemblyProductAttribute", + L"System.Reflection.AssemblyTitleAttribute", + L"System.Runtime.CompilerServices.AsyncStateMachineAttribute", + L"System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1", + L"System.Runtime.CompilerServices.CompilationRelaxationsAttribute", + L"System.Runtime.CompilerServices.CompilerGeneratedAttribute", + L"System.Runtime.CompilerServices.IAsyncStateMachine", + L"System.Runtime.CompilerServices.RuntimeCompatibilityAttribute", + L"System.Runtime.CompilerServices.TaskAwaiter", + L"System.Runtime.CompilerServices.TaskAwaiter`1", + L"System.Runtime.Versioning.TargetFrameworkAttribute", + L"System.RuntimeTypeHandle", + L"System.String", + L"System.Threading.Tasks.Task", + L"System.Threading.Tasks.Task`1", + L"System.Tuple`2", + L"System.Tuple`7", + L"System.Type", + L"System.ValueType"}; + std::set actual; + for (auto& type_ref : EnumTypeRefs(metadata_import_)) { + auto type_info = GetTypeInfo(metadata_import_, type_ref); + if (type_info.IsValid()) { + actual.insert(type_info.name); + } + } + EXPECT_EQ(expected, actual); +} + +TEST_F(CLRHelperTest, GetsTypeInfoFromModuleRefs) { + // TODO(cbd): figure out how to create a module ref, for now its empty + std::set expected = {}; + std::set actual; + for (auto& module_ref : EnumModuleRefs(metadata_import_)) { + auto type_info = GetTypeInfo(metadata_import_, module_ref); + actual.insert(type_info.name); + } + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, GetsTypeInfoFromMethods) { + std::set expected = { + L"<>c", + L"d__4`2", + L"Cookie", + L"Raisin", + L"Samples.ExampleLibrary.Class1", + L"Samples.ExampleLibrary.FakeClient.Biscuit", + L"Samples.ExampleLibrary.FakeClient.Biscuit`1", + L"Samples.ExampleLibrary.FakeClient.DogClient`2", + L"Samples.ExampleLibrary.FakeClient.DogTrick", + L"Samples.ExampleLibrary.FakeClient.DogTrick`1", + L"Samples.ExampleLibrary.GenericTests.ComprehensiveCaller`2", + L"Samples.ExampleLibrary.GenericTests.GenericTarget`2", + L"Samples.ExampleLibrary.GenericTests.PointStruct", + L"Samples.ExampleLibrary.GenericTests.StructContainer`1"}; + std::set actual; + for (auto& type_def : EnumTypeDefs(metadata_import_)) { + for (auto& method_def : EnumMethods(metadata_import_, type_def)) { + auto type_info = GetTypeInfo(metadata_import_, method_def); + if (type_info.IsValid()) { + actual.insert(type_info.name); + } + } + } + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, + ReturnTypeIsValueTypeOrGenericReturnsCorrectlyForMethodDefs) { + std::set> expected = { + {L".ctor", L""}, + {L"Add", L"System.Int32"}, + {L"Multiply", L"System.Int32"}, + {L"ToCustomString", L""}, + {L"ToObject", L""}, + {L"ToArray", L""}, + {L"ToCustomArray", L""}, + {L"ToMdArray", L""}, + {L"ToJaggedArray", L""}, + {L"ToList", L""}, + {L"ToEnumerator", L"Enumerator"}, + {L"ToDictionaryEntry", L"System.Collections.DictionaryEntry"}, + + // Primitive tests + {L"ToBool", L"System.Boolean"}, + {L"ToChar", L"System.Char"}, + {L"ToSByte", L"System.SByte"}, + {L"ToByte", L"System.Byte"}, + {L"ToInt16", L"System.Int16"}, + {L"ToUInt16", L"System.UInt16"}, + {L"ToInt32", L"System.Int32"}, + {L"ToUInt32", L"System.UInt32"}, + {L"ToInt64", L"System.Int64"}, + {L"ToUInt64", L"System.UInt64"}, + {L"ToSingle", L"System.Single"}, + {L"ToDouble", L"System.Double"}}; + std::set> actual; + + for (auto& type_def : EnumTypeDefs(metadata_import_)) { + for (auto& method_def : EnumMethods(metadata_import_, type_def)) { + auto type_info = GetTypeInfo(metadata_import_, method_def); + if (type_info.IsValid() && + type_info.name == L"Samples.ExampleLibrary.Class1") { + mdToken type_token = mdTokenNil; + auto target = GetFunctionInfo(metadata_import_, method_def); + bool result = ReturnTypeIsValueTypeOrGeneric(metadata_import_, + metadata_emit_, + assembly_emit_, + target.id, + target.signature, + &type_token) && + type_token != mdTokenNil; + if (result) { + auto new_type_ref_info = GetTypeInfo(metadata_import_, type_token); + actual.insert({target.name, new_type_ref_info.name}); + } else { + actual.insert({target.name, L""}); + } + } + } + } + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, + ReturnTypeIsValueTypeOrGenericReturnsCorrectlyForMemberRefs) { + std::vector> expected = { + {L"ReturnT1", true}, + {L"ReturnT1", true}, + {L"ReturnT1", false}, + {L"ReturnT1", true}, + {L"ReturnT1", false}, + {L"ReturnT1", true}, + + {L"ReturnT2", true}, + {L"ReturnT2", true}, + {L"ReturnT2", false}, + {L"ReturnT2", true}, + {L"ReturnT2", false}, + {L"ReturnT2", true}}; + std::vector> actual; + + for (mdMemberRef current = mdtMemberRef + 1; metadata_import_->IsValidToken(current); current++) { + auto target = GetFunctionInfo(metadata_import_, current); + if (target.name == L"ReturnT1" || target.name == L"ReturnT2") { + mdToken type_token = mdTokenNil; + bool result = ReturnTypeIsValueTypeOrGeneric(metadata_import_, + metadata_emit_, + assembly_emit_, + target.id, + target.signature, + &type_token) && + type_token != mdTokenNil; + actual.push_back({target.name, result}); + } + } + EXPECT_EQ(actual, expected); +} + +TEST_F(CLRHelperTest, + ReturnTypeIsValueTypeOrGenericReturnsCorrectlyForMethodSpecs) { + std::vector> expected = { + {L"ReturnM1", true}, + {L"ReturnM1", true}, + {L"ReturnM1", false}, + {L"ReturnM1", true}, + {L"ReturnM1", false}, + {L"ReturnM1", true}, + + {L"ReturnM2", true}, + {L"ReturnM2", true}, + {L"ReturnM2", false}, + {L"ReturnM2", true}, + {L"ReturnM2", false}, + {L"ReturnM2", true}}; + std::vector> actual; + + for (mdMethodSpec current = mdtMethodSpec + 1; metadata_import_->IsValidToken(current); current++) { + mdToken type_token = mdTokenNil; + auto target = GetFunctionInfo(metadata_import_, current); + if (target.name.find(L"ReturnM") != std::string::npos) { + bool result = ReturnTypeIsValueTypeOrGeneric(metadata_import_, + metadata_emit_, + assembly_emit_, + target.id, + target.signature, + &type_token) && + type_token != mdTokenNil; + actual.push_back({target.name, result}); + } + } + EXPECT_EQ(actual, expected); +} diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_type_check_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_type_check_test.cpp new file mode 100644 index 0000000000..34c2f8162c --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/clr_helper_type_check_test.cpp @@ -0,0 +1,123 @@ +#include "pch.h" + +#include "../../src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h" +#include "test_helpers.h" + +using namespace trace; + +class CLRHelperTypeCheckTest : public ::CLRHelperTestBase {}; + + +TEST_F(CLRHelperTypeCheckTest, SimpleNoSignatureMethodHasOnlyVoid) { + std::vector expected = { + L"System.Void"}; + std::vector actual; + + const auto target = FunctionToTest( + "Samples.ExampleLibrary.FakeClient.DogClient`2"_W, "Silence"_W); + + EXPECT_TRUE(target.name.size() > 1) << "Test target method not found."; + + TryParseSignatureTypes(metadata_import_, target, actual); + + EXPECT_EQ(expected, actual); +} + +TEST_F(CLRHelperTypeCheckTest, GetsVeryComplexNestedGenericTypeStrings) { + std::vector expected = { + L"System.Void", + L"System.String", + L"System.Int32", + L"System.Byte[]", + L"System.Guid[][]", + L"T[][][]", + L"System.Collections.Generic.List`1", + L"System.Collections.Generic.List`1>", + L"System.Tuple`7, System.Int64>, System.Threading.Tasks.Task, System.Guid>", + L"System.Collections.Generic.Dictionary`2>>>"}; + std::vector actual; + + const auto target = FunctionToTest( + "Samples.ExampleLibrary.FakeClient.DogClient`2"_W, "Sit"_W); + + EXPECT_TRUE(target.name.size() > 1) << "Test target method not found."; + + TryParseSignatureTypes(metadata_import_, target, actual); + + EXPECT_EQ(expected, actual); +} + + +TEST_F(CLRHelperTypeCheckTest, SimpleStringReturnWithNestedTypeParamsNoGenerics) { + std::vector expected = { + L"System.String", L"Samples.ExampleLibrary.FakeClient.Biscuit+Cookie", + L"Samples.ExampleLibrary.FakeClient.Biscuit+Cookie+Raisin"}; + std::vector actual; + + const auto target = FunctionToTest( + "Samples.ExampleLibrary.FakeClient.DogClient`2"_W, "TellMeIfTheCookieIsYummy"_W); + + EXPECT_TRUE(target.name.size() > 1) << "Test target method not found."; + + TryParseSignatureTypes(metadata_import_, target, actual); + + EXPECT_EQ(expected, actual); +} + + +TEST_F(CLRHelperTypeCheckTest, SimpleClassReturnWithSimpleParamsNoGenerics) { + std::vector expected = {L"Samples.ExampleLibrary.FakeClient.Biscuit", + L"System.Guid", L"System.Int16", + L"Samples.ExampleLibrary.FakeClient.DogTrick"}; + std::vector actual; + + const auto target = FunctionToTest( + "Samples.ExampleLibrary.FakeClient.DogClient`2"_W, "Rollover"_W); + + EXPECT_TRUE(target.name.size() > 1) << "Test target method not found."; + + TryParseSignatureTypes(metadata_import_, target, actual); + + EXPECT_EQ(expected, actual); +} + +TEST_F(CLRHelperTypeCheckTest, GenericAsyncMethodWithNestedGenericTask) { + std::vector expected = { + L"System.Threading.Tasks.Task`1>", + L"System.Guid", + L"System.Int16", + L"Samples.ExampleLibrary.FakeClient.DogTrick`1", + L"T", + L"T", + }; + std::vector actual; + + const auto target = FunctionToTest( + "Samples.ExampleLibrary.FakeClient.DogClient`2"_W, "StayAndLayDown"_W); + + EXPECT_TRUE(target.name.size() > 1) << "Test target method not found."; + + TryParseSignatureTypes(metadata_import_, target, actual); + + EXPECT_EQ(expected, actual); +} + +TEST_F(CLRHelperTypeCheckTest, SuccessfullyParsesEverySignature) { + std::set expected_failures = { + L"Samples.ExampleLibrary.Class1.ToMdArray", + L"Samples.ExampleLibrary.Class1.ToEnumerator" + }; + std::set actual_failures; + for (auto& type_def : EnumTypeDefs(metadata_import_)) { + for (auto& method_def : EnumMethods(metadata_import_, type_def)) { + auto target = GetFunctionInfo(metadata_import_, method_def); + std::vector actual; + auto success = TryParseSignatureTypes(metadata_import_, target, actual); + if (!success) { + actual_failures.insert(target.type.name + L"." + target.name); + } + } + } + + EXPECT_EQ(expected_failures, actual_failures); +} \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_loader_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_loader_test.cpp new file mode 100644 index 0000000000..ce48cb7b97 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_loader_test.cpp @@ -0,0 +1,225 @@ +#include "pch.h" + +#include +#include +#include +#include +#include +#include + +#include "../../src/Datadog.Trace.ClrProfiler.Native/integration_loader.h" +#include "../../src/Datadog.Trace.ClrProfiler.Native/environment_variables.h" + +using namespace trace; + +TEST(IntegrationLoaderTest, HandlesMissingFile) { + auto integrations = LoadIntegrationsFromFile(L"missing-file"); + EXPECT_EQ(0, integrations.size()); +} + +TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNoName) { + std::stringstream str("[{}]"); + auto integrations = LoadIntegrationsFromStream(str); + // 0 because name is required + EXPECT_EQ(0, integrations.size()); +} + +TEST(IntegrationLoaderTest, HandlesInvalidIntegrationBadJson) { + std::stringstream str("["); + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(0, integrations.size()); +} + +TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnObject) { + std::stringstream str("[1,2,3]"); + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(0, integrations.size()); +} + +TEST(IntegrationLoaderTest, HandlesInvalidIntegrationNotAnArray) { + std::stringstream str(R"TEXT( + {"name": "test-integration"} + )TEXT"); + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(0, integrations.size()); +} + +TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithNoMethods) { + std::stringstream str(R"TEXT( + [{ "name": "test-integration" }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); + EXPECT_EQ(0, integrations[0].method_replacements.size()); +} + +TEST(IntegrationLoaderTest, + HandlesSingleIntegrationWithInvalidMethodReplacementType) { + std::stringstream str(R"TEXT( + [{ "name": "test-integration", "method_replacements": 1234 }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); + EXPECT_EQ(0, integrations[0].method_replacements.size()); +} + +TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMethodReplacements) { + std::stringstream str(R"TEXT( + [{ + "name": "test-integration", + "method_replacements": [{ + "caller": { }, + "target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 10, "maximum_minor": 0 }, + "wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "signature": [0, 1, 1, 28] } + }] + }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); +} + +TEST(IntegrationLoaderTest, DoesNotCrashWithOutOfRangeVersion) { + std::stringstream str(R"TEXT( + [{ + "name": "test-integration", + "method_replacements": [{ + "caller": { }, + "target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 0, "minimum_minor": 1, "maximum_major": 75555, "maximum_minor": 0 }, + "wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "signature": [0, 1, 1, 28] } + }] + }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); + + EXPECT_EQ(1, integrations[0].method_replacements.size()); + auto mr = integrations[0].method_replacements[0]; + EXPECT_STREQ(L"", mr.caller_method.assembly.name.c_str()); + EXPECT_STREQ(L"", mr.caller_method.type_name.c_str()); + EXPECT_STREQ(L"", mr.caller_method.method_name.c_str()); + EXPECT_STREQ(L"Assembly.One", mr.target_method.assembly.name.c_str()); + EXPECT_STREQ(L"Type.One", mr.target_method.type_name.c_str()); + EXPECT_STREQ(L"Method.One", mr.target_method.method_name.c_str()); + EXPECT_STREQ(L"Assembly.Two", mr.wrapper_method.assembly.name.c_str()); + EXPECT_STREQ(L"Type.Two", mr.wrapper_method.type_name.c_str()); + EXPECT_STREQ(L"Method.Two", mr.wrapper_method.method_name.c_str()); + EXPECT_EQ(std::vector({0, 1, 1, 28}), + mr.wrapper_method.method_signature.data); +} + +TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithMissingCaller) { + std::stringstream str(R"TEXT( + [{ + "name": "test-integration", + "method_replacements": [{ + "target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "minimum_major": 1, "minimum_minor": 2, "maximum_major": 10, "maximum_minor": 99 }, + "wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two", "signature": [0, 1, 1, 28] } + }] + }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); + + EXPECT_EQ(1, integrations[0].method_replacements.size()); + auto mr = integrations[0].method_replacements[0]; + EXPECT_STREQ(L"", mr.caller_method.assembly.name.c_str()); + EXPECT_STREQ(L"", mr.caller_method.type_name.c_str()); + EXPECT_STREQ(L"", mr.caller_method.method_name.c_str()); + EXPECT_STREQ(L"Assembly.One", mr.target_method.assembly.name.c_str()); + EXPECT_STREQ(L"Type.One", mr.target_method.type_name.c_str()); + EXPECT_STREQ(L"Method.One", mr.target_method.method_name.c_str()); + EXPECT_STREQ(L"Assembly.Two", mr.wrapper_method.assembly.name.c_str()); + EXPECT_STREQ(L"Type.Two", mr.wrapper_method.type_name.c_str()); + EXPECT_STREQ(L"Method.Two", mr.wrapper_method.method_name.c_str()); + EXPECT_STREQ(L"Method.Two", mr.wrapper_method.method_name.c_str()); + EXPECT_EQ(1, mr.target_method.min_version.major); + EXPECT_EQ(2, mr.target_method.min_version.minor); + EXPECT_EQ(0, mr.target_method.min_version.build); + EXPECT_EQ(10, mr.target_method.max_version.major); + EXPECT_EQ(99, mr.target_method.max_version.minor); + EXPECT_EQ(USHRT_MAX, mr.target_method.max_version.build); + EXPECT_EQ(std::vector({0, 1, 1, 28}), + mr.wrapper_method.method_signature.data); +} + +TEST(IntegrationLoaderTest, HandlesSingleIntegrationWithInvalidTarget) { + std::stringstream str(R"TEXT( + [{ + "name": "test-integration", + "method_replacements": [{ + "target": 1234, + "wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.Two" } + }] + }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + EXPECT_EQ(1, integrations.size()); + EXPECT_STREQ(L"test-integration", integrations[0].integration_name.c_str()); + + EXPECT_EQ(1, integrations[0].method_replacements.size()); + auto mr = integrations[0].method_replacements[0]; + EXPECT_STREQ(L"", mr.target_method.assembly.name.c_str()); + EXPECT_STREQ(L"", mr.target_method.type_name.c_str()); + EXPECT_STREQ(L"", mr.target_method.method_name.c_str()); +} + +TEST(IntegrationLoaderTest, LoadsFromEnvironment) { + auto tmpname1 = std::filesystem::temp_directory_path() / "test-1.json"; + auto tmpname2 = std::filesystem::temp_directory_path() / "test-2.json"; + std::ofstream f; + f.open(tmpname1); + f << R"TEXT( + [{ "name": "test-integration-1" }] + )TEXT"; + f.close(); + f.open(tmpname2); + f << R"TEXT( + [{ "name": "test-integration-2" }] + )TEXT"; + f.close(); + + auto name = tmpname1.wstring() + L";" + tmpname2.wstring(); + + SetEnvironmentVariableW(trace::environment::integrations_path.data(), name.data()); + + std::vector expected_names = {L"test-integration-1", + L"test-integration-2"}; + std::vector actual_names; + for (auto& integration : LoadIntegrationsFromEnvironment()) { + actual_names.push_back(integration.integration_name); + } + EXPECT_EQ(expected_names, actual_names); + + std::filesystem::remove(tmpname1); + std::filesystem::remove(tmpname2); +} + +TEST(IntegrationLoaderTest, DeserializesSignatureTypeArray) { + std::stringstream str(R"TEXT( + [{ + "name": "test-integration", + "method_replacements": [{ + "caller": { }, + "target": { "assembly": "Assembly.One", "type": "Type.One", "method": "Method.One", "signature_types": ["System.Void", "_", "FakeClient.Pipeline'1"] }, + "wrapper": { "assembly": "Assembly.Two", "type": "Type.Two", "method": "Method.One", "signature": [0, 1, 1, 28] } + }] + }] + )TEXT"); + + auto integrations = LoadIntegrationsFromStream(str); + const auto target = integrations[0].method_replacements[0].target_method; + EXPECT_STREQ(L"System.Void", target.signature_types[0].c_str()); + EXPECT_STREQ(L"_", target.signature_types[1].c_str()); + EXPECT_STREQ(L"FakeClient.Pipeline'1", target.signature_types[2].c_str()); +} diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_test.cpp new file mode 100644 index 0000000000..3bcd499253 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/integration_test.cpp @@ -0,0 +1,46 @@ +#include "pch.h" + +#include "../../src/Datadog.Trace.ClrProfiler.Native/integration.h" + +using namespace trace; + +TEST(IntegrationTest, AssemblyReference) { + AssemblyReference ref( + L"Some.Assembly, Version=1.2.3.4, Culture=notneutral, " + L"PublicKeyToken=0123456789abcdef"); + + EXPECT_EQ(ref.name, L"Some.Assembly"); + EXPECT_EQ(ref.version, Version(1, 2, 3, 4)); + EXPECT_EQ(ref.locale, L"notneutral"); + EXPECT_EQ(ref.public_key, + PublicKey({0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef})); +} + +TEST(IntegrationTest, AssemblyReferenceNameOnly) { + AssemblyReference ref(L"Some.Assembly"); + + EXPECT_EQ(ref.name, L"Some.Assembly"); + EXPECT_EQ(ref.version, Version(0, 0, 0, 0)); + EXPECT_EQ(ref.locale, L"neutral"); + EXPECT_EQ(ref.public_key, PublicKey({0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(IntegrationTest, AssemblyReferenceInvalidPublicKey) { + AssemblyReference ref(L"Some.Assembly, PublicKeyToken=xyz"); + EXPECT_EQ(ref.public_key, PublicKey({0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(IntegrationTest, AssemblyReferenceNullPublicKey) { + AssemblyReference ref(L"Some.Assembly, PublicKeyToken=null"); + EXPECT_EQ(ref.public_key, PublicKey({0, 0, 0, 0, 0, 0, 0, 0})); +} + +TEST(IntegrationTest, AssemblyReferencePartialVersion) { + AssemblyReference ref(L"Some.Assembly, Version=1.2.3"); + EXPECT_EQ(ref.version, Version(0, 0, 0, 0)); +} + +TEST(IntegrationTest, AssemblyReferenceInvalidVersion) { + AssemblyReference ref(L"Some.Assembly, Version=xyz"); + EXPECT_EQ(ref.version, Version(0, 0, 0, 0)); +} \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/metadata_builder_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/metadata_builder_test.cpp new file mode 100644 index 0000000000..0ed0906675 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/metadata_builder_test.cpp @@ -0,0 +1,157 @@ +#include "pch.h" + +#include "../../src/Datadog.Trace.ClrProfiler.Native/clr_helpers.h" +#include "../../src/Datadog.Trace.ClrProfiler.Native/metadata_builder.h" + +using namespace trace; + +class MetadataBuilderTest : public ::testing::Test { + protected: + ModuleMetadata* module_metadata_ = nullptr; + MetadataBuilder* metadata_builder_ = nullptr; + ICLRStrongName* strong_name_ = nullptr; + IMetaDataDispenser* metadata_dispenser_ = nullptr; + std::vector empty_sig_type_; + + void SetUp() override { + ICLRMetaHost* metahost = nullptr; + HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, + (void**)&metahost); + ASSERT_TRUE(SUCCEEDED(hr)); + + IEnumUnknown* runtimes = nullptr; + hr = metahost->EnumerateInstalledRuntimes(&runtimes); + ASSERT_TRUE(SUCCEEDED(hr)); + + ICLRRuntimeInfo* latest = nullptr; + ICLRRuntimeInfo* runtime = nullptr; + ULONG fetched = 0; + while ((hr = runtimes->Next(1, (IUnknown**)&runtime, &fetched)) == S_OK && + fetched > 0) { + latest = runtime; + } + + hr = + latest->GetInterface(CLSID_CorMetaDataDispenser, IID_IMetaDataDispenser, + (void**)&metadata_dispenser_); + ASSERT_TRUE(SUCCEEDED(hr)); + + hr = latest->GetInterface(CLSID_CLRStrongName, IID_ICLRStrongName, + (void**)&strong_name_); + ASSERT_TRUE(SUCCEEDED(hr)); + + ComPtr metadataInterfaces; + hr = metadata_dispenser_->OpenScope(L"Samples.ExampleLibrary.dll", + ofReadWriteMask, IID_IMetaDataImport2, + metadataInterfaces.GetAddressOf()); + ASSERT_TRUE(SUCCEEDED(hr)) << "File not found: Samples.ExampleLibrary.dll"; + + const auto metadataImport = + metadataInterfaces.As(IID_IMetaDataImport2); + const auto metadataEmit = + metadataInterfaces.As(IID_IMetaDataEmit); + const auto assemblyImport = metadataInterfaces.As( + IID_IMetaDataAssemblyImport); + const auto assemblyEmit = + metadataInterfaces.As(IID_IMetaDataAssemblyEmit); + + const std::wstring assemblyName = L"Samples.ExampleLibrary"; + + const AppDomainID app_domain_id{}; + + GUID module_version_id; + metadataImport->GetScopeProps(NULL, 1024, nullptr, &module_version_id); + + const std::vector integrations; + module_metadata_ = + new ModuleMetadata(metadataImport, metadataEmit, assemblyImport, assemblyEmit, + assemblyName, app_domain_id, module_version_id, integrations); + + mdModule module; + hr = metadataImport->GetModuleFromScope(&module); + ASSERT_TRUE(SUCCEEDED(hr)); + + metadata_builder_ = + new MetadataBuilder(*module_metadata_, module, metadataImport, + metadataEmit, assemblyImport, assemblyEmit); + + hr = metadata_builder_->EmitAssemblyRef(trace::AssemblyReference( + L"Samples.ExampleLibraryTracer, Version=1.0.0.0")); + ASSERT_TRUE(SUCCEEDED(hr)); + } + + void TearDown() override { + delete this->module_metadata_; + delete this->metadata_builder_; + } +}; + +TEST_F(MetadataBuilderTest, StoresWrapperMemberRef) { + + const auto min_ver = Version(0, 0, 0, 0); + const auto max_ver = Version(USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX); + const MethodReference ref1(L"", L"", L"", L"", min_ver, max_ver, {}, empty_sig_type_); + const MethodReference ref2(L"Samples.ExampleLibrary", L"Class1", L"Add", L"", min_ver, max_ver, {}, empty_sig_type_); + const MethodReference ref3(L"Samples.ExampleLibrary", L"Class1", L"Add", L"ReplaceTargetMethod", min_ver, max_ver, {}, empty_sig_type_); + const MethodReplacement mr1(ref1, ref2, ref3); + auto hr = metadata_builder_->StoreWrapperMethodRef(mr1); + ASSERT_EQ(S_OK, hr); + + mdMemberRef tmp; + auto key_failed = module_metadata_->IsFailedWrapperMemberKey( + L"[Samples.ExampleLibrary]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535"); + auto ok = module_metadata_->TryGetWrapperMemberRef( + L"[Samples.ExampleLibrary]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535", tmp); + EXPECT_TRUE(ok); + EXPECT_FALSE(key_failed); + EXPECT_NE(tmp, 0); + + tmp = 0; + key_failed = module_metadata_->IsFailedWrapperMemberKey( + L"[Samples.ExampleLibrary]Class2.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535"); + ok = module_metadata_->TryGetWrapperMemberRef( + L"[Samples.ExampleLibrary]Class2.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535", tmp); + EXPECT_FALSE(ok); + EXPECT_FALSE(key_failed); + EXPECT_EQ(tmp, 0); +} + +TEST_F(MetadataBuilderTest, StoresWrapperMemberRefForSeparateAssembly) { + const auto min_ver = Version(0, 0, 0, 0); + const auto max_ver = Version(USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX); + const MethodReference ref1(L"", L"", L"", L"", min_ver, max_ver, {}, + empty_sig_type_); + const MethodReference ref2(L"Samples.ExampleLibrary", L"Class1", L"Add", L"", min_ver, max_ver, {}, empty_sig_type_); + const MethodReference ref3(L"Samples.ExampleLibraryTracer", L"Class1", L"Add", L"ReplaceTargetMethod", + min_ver, max_ver, {}, empty_sig_type_); + const MethodReplacement mr1(ref1, ref2, ref3); + auto hr = metadata_builder_->StoreWrapperMethodRef(mr1); + ASSERT_EQ(S_OK, hr); + + mdMemberRef tmp; + auto key_failed = module_metadata_->IsFailedWrapperMemberKey(L"[Samples.ExampleLibraryTracer]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535"); + auto ok = module_metadata_->TryGetWrapperMemberRef( + L"[Samples.ExampleLibraryTracer]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535", tmp); + EXPECT_TRUE(ok); + EXPECT_FALSE(key_failed); + EXPECT_NE(tmp, 0); +} + +TEST_F(MetadataBuilderTest, StoresWrapperMemberRefRecordsFailure) { + const auto min_ver = Version(0, 0, 0, 0); + const auto max_ver = Version(USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX); + const MethodReference ref1(L"", L"", L"", L"", min_ver, max_ver, {}, + empty_sig_type_); + const MethodReference ref2(L"Samples.ExampleLibrary", L"Class1", L"Add", L"", min_ver, max_ver, {}, empty_sig_type_); + const MethodReference ref3(L"Samples.ExampleLibraryTracer.AssemblyDoesNotExist", L"Class1", L"Add", L"ReplaceTargetMethod", + min_ver, max_ver, {}, empty_sig_type_); + const MethodReplacement mr1(ref1, ref2, ref3); + auto hr = metadata_builder_->StoreWrapperMethodRef(mr1); + ASSERT_NE(S_OK, hr); + + auto key_failed = module_metadata_->IsFailedWrapperMemberKey(L"[Samples.ExampleLibraryTracer.AssemblyDoesNotExist]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535"); + EXPECT_TRUE(key_failed); + + key_failed = module_metadata_->IsFailedWrapperMemberKey(L"[Samples.ExampleLibraryTracer]Class1.Add_vMin_0.0.0.0_vMax_65535.65535.65535.65535"); + EXPECT_FALSE(key_failed); +} \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/packages.config b/test/Datadog.Trace.ClrProfiler.Native.Tests/packages.config new file mode 100644 index 0000000000..d974a133db --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.cpp new file mode 100644 index 0000000000..97b544ec11 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.cpp @@ -0,0 +1,6 @@ +// +// pch.cpp +// Include the standard header and generate the precompiled header. +// + +#include "pch.h" diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.h b/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.h new file mode 100644 index 0000000000..b4b50837d6 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/pch.h @@ -0,0 +1,18 @@ +// +// pch.h +// Header for standard system include files. +// + +#ifndef DD_CLR_PROFILER_TESTS_PCH_H_ +#define DD_CLR_PROFILER_TESTS_PCH_H_ + +#define GTEST_LANG_CXX11 1 + +#include "gtest/gtest.h" + +#include +#include +#include +#pragma comment(lib, "mscoree.lib") + +#endif \ No newline at end of file diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/test_helpers.h b/test/Datadog.Trace.ClrProfiler.Native.Tests/test_helpers.h new file mode 100644 index 0000000000..1365ffdc98 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/test_helpers.h @@ -0,0 +1,77 @@ + +#pragma once +#include "../../src/Datadog.Trace.ClrProfiler.Native/com_ptr.h" +#include "../../src/Datadog.Trace.ClrProfiler.Native/integration.h" + +namespace trace { + +class CLRHelperTestBase : public ::testing::Test { + protected: + IMetaDataDispenser* metadata_dispenser_; + ComPtr metadata_import_; + ComPtr metadata_emit_; + ComPtr assembly_import_; + ComPtr assembly_emit_; + Version min_ver_ = Version(0, 0, 0, 0); + Version max_ver_ = Version(USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX); + std::vector empty_sig_type_; + + void LoadMetadataDependencies() { + ICLRMetaHost* metahost = nullptr; + HRESULT hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, + (void**)&metahost); + ASSERT_TRUE(SUCCEEDED(hr)); + + IEnumUnknown* runtimes = nullptr; + hr = metahost->EnumerateInstalledRuntimes(&runtimes); + ASSERT_TRUE(SUCCEEDED(hr)); + + ICLRRuntimeInfo* latest = nullptr; + ICLRRuntimeInfo* runtime = nullptr; + ULONG fetched = 0; + while ((hr = runtimes->Next(1, (IUnknown**)&runtime, &fetched)) == S_OK && + fetched > 0) { + latest = runtime; + } + + hr = + latest->GetInterface(CLSID_CorMetaDataDispenser, IID_IMetaDataDispenser, + (void**)&metadata_dispenser_); + ASSERT_TRUE(SUCCEEDED(hr)); + + ComPtr metadataInterfaces; + hr = metadata_dispenser_->OpenScope(L"Samples.ExampleLibrary.dll", + ofReadWriteMask, IID_IMetaDataImport2, + metadataInterfaces.GetAddressOf()); + ASSERT_TRUE(SUCCEEDED(hr)) << "Samples.ExampleLibrary.dll was not found."; + + metadata_import_ = + metadataInterfaces.As(IID_IMetaDataImport2); + metadata_emit_ = + metadataInterfaces.As(IID_IMetaDataEmit); + assembly_import_ = + metadataInterfaces.As(IID_IMetaDataAssemblyImport); + assembly_emit_ = + metadataInterfaces.As(IID_IMetaDataAssemblyEmit); + } + + void SetUp() override { LoadMetadataDependencies(); } + + FunctionInfo FunctionToTest(const WSTRING& type_name, const WSTRING& method_name) const { + for (auto& type_def : EnumTypeDefs(metadata_import_)) { + for (auto& method_def : EnumMethods(metadata_import_, type_def)) { + auto target = GetFunctionInfo(metadata_import_, method_def); + if (target.type.name != type_name) { + continue; + } + if (target.name != method_name) { + continue; + } + return target; + } + } + + return {}; + } +}; +} // namespace trace diff --git a/test/Datadog.Trace.ClrProfiler.Native.Tests/version_struct_test.cpp b/test/Datadog.Trace.ClrProfiler.Native.Tests/version_struct_test.cpp new file mode 100644 index 0000000000..9d3bc587e0 --- /dev/null +++ b/test/Datadog.Trace.ClrProfiler.Native.Tests/version_struct_test.cpp @@ -0,0 +1,50 @@ +#include "pch.h" + +#include "../../src/Datadog.Trace.ClrProfiler.Native/integration.h" + +using namespace trace; + +TEST(VersionStructTest, Major2GreaterThanMajor1) { + const auto v1 = Version(1, 0, 0, 0); + const auto v2 = Version(2, 0, 0, 0); + ASSERT_TRUE(v2 > v1) << "Expected v2 to be greater than v1."; +} + +TEST(VersionStructTest, Minor2GreaterThanMinor1) { + const auto v0_1 = Version(0, 1, 0, 0); + const auto v0_2 = Version(0, 2, 0, 0); + ASSERT_TRUE(v0_2 > v0_1) << "Expected v0_2 to be greater than v0_1."; +} + +TEST(VersionStructTest, Build1GreaterThanBuild0) { + const auto v0_0_0 = Version(0, 0, 0, 0); + const auto v0_0_1 = Version(0, 0, 1, 0); + ASSERT_TRUE(v0_0_1 > v0_0_0) << "Expected v0_0_1 to be greater than v0_0_0."; +} + +TEST(VersionStructTest, Major1LessThanMajor2) { + const auto v1 = Version(1, 0, 0, 0); + const auto v2 = Version(2, 0, 0, 0); + ASSERT_TRUE(v1 < v2) << "Expected v1 to be less than v2."; +} + +TEST(VersionStructTest, Minor1LessThanMinor2) { + const auto v0_1 = Version(0, 1, 0, 0); + const auto v0_2 = Version(0, 2, 0, 0); + ASSERT_TRUE(v0_1 < v0_2) << "Expected v0_1 to be less than v0_2."; +} + +TEST(VersionStructTest, Build0LessThanBuild1) { + const auto v0_0_0 = Version(0, 0, 0, 0); + const auto v0_0_1 = Version(0, 0, 1, 0); + ASSERT_TRUE(v0_0_0 < v0_0_1) << "Expected v0_0_0 to be less than v0_0_1."; +} + +TEST(VersionStructTest, RevisionDoesNotAffectComparison) { + const auto v1_2_3_4 = Version(1, 2, 3, 4); + const auto v1_2_3_5 = Version(1, 2, 3, 5); + ASSERT_FALSE(v1_2_3_5 > v1_2_3_4) + << "Expected v1_2_3_5 to not be greater than v1_2_3_4."; + ASSERT_FALSE(v1_2_3_4 < v1_2_3_5) + << "Expected v1_2_3_4 to not be less than v1_2_3_5."; +} diff --git a/test/Datadog.Trace.IntegrationTests/ContainerTaggingTests.cs b/test/Datadog.Trace.IntegrationTests/ContainerTaggingTests.cs new file mode 100644 index 0000000000..66688842fd --- /dev/null +++ b/test/Datadog.Trace.IntegrationTests/ContainerTaggingTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Threading.Tasks; +using Datadog.Core.Tools; +using Datadog.Trace.Configuration; +using Datadog.Trace.PlatformHelpers; +using Datadog.Trace.TestHelpers; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Trace.IntegrationTests +{ + public class ContainerTaggingTests + { + private readonly ITestOutputHelper _output; + + public ContainerTaggingTests(ITestOutputHelper output) + { + _output = output; + } + + [Fact] + public async Task Http_Headers_Contain_ContainerId() + { + string expectedContainedId = ContainerMetadata.GetContainerId(); + string actualContainerId = null; + var agentPort = TcpPortProvider.GetOpenPort(); + + using (var agent = new MockTracerAgent(agentPort)) + { + agent.RequestReceived += (sender, args) => + { + actualContainerId = args.Value.Request.Headers[AgentHttpHeaderNames.ContainerId]; + }; + + var settings = new TracerSettings { AgentUri = new Uri($"http://localhost:{agent.Port}") }; + var tracer = new Tracer(settings); + + using (var scope = tracer.StartActive("operationName")) + { + scope.Span.ResourceName = "resourceName"; + } + + await tracer.FlushAsync(); + + var spans = agent.WaitForSpans(1); + Assert.Equal(1, spans.Count); + Assert.Equal(expectedContainedId, actualContainerId); + + if (EnvironmentTools.IsWindows()) + { + // we don't extract the containerId on Windows (yet?) + Assert.Null(actualContainerId); + } + } + } + } +} diff --git a/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj new file mode 100644 index 0000000000..679a8265b3 --- /dev/null +++ b/test/Datadog.Trace.IntegrationTests/Datadog.Trace.IntegrationTests.csproj @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.IntegrationTests/SendTracesToAgent.cs b/test/Datadog.Trace.IntegrationTests/SendTracesToAgent.cs new file mode 100644 index 0000000000..c90d443cff --- /dev/null +++ b/test/Datadog.Trace.IntegrationTests/SendTracesToAgent.cs @@ -0,0 +1,118 @@ +using System; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.TestHelpers; +using Datadog.Trace.TestHelpers.HttpMessageHandlers; +using Xunit; + +namespace Datadog.Trace.IntegrationTests +{ + public class SendTracesToAgent + { + private readonly Tracer _tracer; + private readonly RecordHttpHandler _httpRecorder; + + public SendTracesToAgent() + { + var settings = new TracerSettings(); + + var endpoint = new Uri("http://localhost:8126"); + _httpRecorder = new RecordHttpHandler(); + var api = new Api(endpoint, apiRequestFactory: null, statsd: null); + var agentWriter = new AgentWriter(api, statsd: null); + + _tracer = new Tracer(settings, agentWriter, sampler: null, scopeManager: null, statsd: null); + } + + [Fact(Skip = "Run manually")] + public async Task MinimalSpan() + { + var scope = _tracer.StartActive("Operation"); + scope.Dispose(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(scope.Span, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public async Task CustomServiceName() + { + const string ServiceName = "MyService"; + + var scope = _tracer.StartActive("Operation", serviceName: ServiceName); + scope.Span.ResourceName = "This is a resource"; + scope.Dispose(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(scope.Span, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public async Task Utf8Everywhere() + { + var scope = _tracer.StartActive("Aᛗᚪᚾᚾᚪ", serviceName: "На берегу пустынных волн"); + scope.Span.ResourceName = "η γλώσσα μου έδωσαν ελληνική"; + scope.Span.SetTag("யாமறிந்த", "ნუთუ კვლა"); + scope.Dispose(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(scope.Span, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public async Task SubmitsOutOfOrderSpans() + { + var scope1 = _tracer.StartActive("op1"); + var scope2 = _tracer.StartActive("op2"); + scope1.Close(); + scope2.Close(); + + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(scope1.Span, trace[0].AsList()[0]); + MsgPackHelpers.AssertSpanEqual(scope2.Span, trace[0].AsList()[1]); + } + + [Fact(Skip = "Run manually")] + public void WithDefaultFactory() + { + // This test does not check anything it validates that this codepath runs without exceptions + var tracer = Tracer.Create(); + tracer.StartActive("Operation") + .Dispose(); + } + + [Fact(Skip = "Run manually")] + public void WithGlobalTracer() + { + // This test does not check anything it validates that this codepath runs without exceptions + Tracer.Instance.StartActive("Operation") + .Dispose(); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj new file mode 100644 index 0000000000..6f62f6b4a7 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.IntegrationTests/Datadog.Trace.OpenTracing.IntegrationTests.csproj @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.OpenTracing.IntegrationTests/OpenTracingSendTracesToAgent.cs b/test/Datadog.Trace.OpenTracing.IntegrationTests/OpenTracingSendTracesToAgent.cs new file mode 100644 index 0000000000..63c793dfba --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.IntegrationTests/OpenTracingSendTracesToAgent.cs @@ -0,0 +1,97 @@ +using System; +using System.Linq; +using System.Net; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.TestHelpers; +using Datadog.Trace.TestHelpers.HttpMessageHandlers; +using Xunit; + +namespace Datadog.Trace.OpenTracing.IntegrationTests +{ + public class OpenTracingSendTracesToAgent + { + private readonly OpenTracingTracer _tracer; + private readonly RecordHttpHandler _httpRecorder; + + public OpenTracingSendTracesToAgent() + { + var settings = new TracerSettings(); + + var endpoint = new Uri("http://localhost:8126"); + _httpRecorder = new RecordHttpHandler(); + var api = new Api(endpoint, apiRequestFactory: null, statsd: null); + var agentWriter = new AgentWriter(api, statsd: null); + + var tracer = new Tracer(settings, agentWriter, sampler: null, scopeManager: null, statsd: null); + _tracer = new OpenTracingTracer(tracer); + } + + [Fact(Skip = "Run manually")] + public async void MinimalSpan() + { + var span = (OpenTracingSpan)_tracer.BuildSpan("Operation") + .Start(); + span.Finish(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(span.DDSpan, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public async void CustomServiceName() + { + const string ServiceName = "MyService"; + + var span = (OpenTracingSpan)_tracer.BuildSpan("Operation") + .WithTag(DatadogTags.ResourceName, "This is a resource") + .WithTag(DatadogTags.ServiceName, ServiceName) + .Start(); + span.Finish(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(span.DDSpan, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public async void Utf8Everywhere() + { + var span = (OpenTracingSpan)_tracer.BuildSpan("Aᛗᚪᚾᚾᚪ") + .WithTag(DatadogTags.ResourceName, "η γλώσσα μου έδωσαν ελληνική") + .WithTag(DatadogTags.ServiceName, "На берегу пустынных волн") + .WithTag("யாமறிந்த", "ნუთუ კვლა") + .Start(); + span.Finish(); + + // Check that the HTTP calls went as expected + await _httpRecorder.WaitForCompletion(1); + Assert.Single(_httpRecorder.Requests); + Assert.Single(_httpRecorder.Responses); + Assert.All(_httpRecorder.Responses, (x) => Assert.Equal(HttpStatusCode.OK, x.StatusCode)); + + var trace = _httpRecorder.Traces.Single(); + MsgPackHelpers.AssertSpanEqual(span.DDSpan, trace.Single()); + } + + [Fact(Skip = "Run manually")] + public void WithDefaultFactory() + { + // This test does not check anything it validates that this codepath runs without exceptions + _tracer.BuildSpan("Operation") + .Start() + .Finish(); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj new file mode 100644 index 0000000000..721509ac97 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/Datadog.Trace.OpenTracing.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.OpenTracing.Tests/HttpHeaderCodecTests.cs b/test/Datadog.Trace.OpenTracing.Tests/HttpHeaderCodecTests.cs new file mode 100644 index 0000000000..3a60cdec26 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/HttpHeaderCodecTests.cs @@ -0,0 +1,69 @@ +using System; +using Xunit; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class HttpHeaderCodecTests + { + // The values are duplicated here to make sure that if they are changed it will break tests + private const string HttpHeaderTraceId = "x-datadog-trace-id"; + private const string HttpHeaderParentId = "x-datadog-parent-id"; + private const string HttpHeaderSamplingPriority = "x-datadog-sampling-priority"; + + private readonly HttpHeadersCodec _codec = new HttpHeadersCodec(); + + [Fact] + public void Extract_ValidParentAndTraceId_ProperSpanContext() + { + const ulong traceId = 10; + const ulong parentId = 120; + + var headers = new MockTextMap(); + headers.Set(HttpHeaderTraceId, traceId.ToString()); + headers.Set(HttpHeaderParentId, parentId.ToString()); + + var spanContext = _codec.Extract(headers) as OpenTracingSpanContext; + + Assert.NotNull(spanContext); + Assert.Equal(traceId, spanContext.Context.TraceId); + Assert.Equal(parentId, spanContext.Context.SpanId); + } + + [Fact] + public void Extract_WrongHeaderCase_ExtractionStillWorks() + { + const ulong traceId = 10; + const ulong parentId = 120; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + + var headers = new MockTextMap(); + headers.Set(HttpHeaderTraceId.ToUpper(), traceId.ToString()); + headers.Set(HttpHeaderParentId.ToUpper(), parentId.ToString()); + headers.Set(HttpHeaderSamplingPriority.ToUpper(), ((int)samplingPriority).ToString()); + + var spanContext = _codec.Extract(headers) as OpenTracingSpanContext; + + Assert.NotNull(spanContext); + Assert.Equal(traceId, spanContext.Context.TraceId); + Assert.Equal(parentId, spanContext.Context.SpanId); + } + + [Fact] + public void Inject_SpanContext_HeadersWithCorrectInfo() + { + const ulong spanId = 10; + const ulong traceId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + + var ddSpanContext = new SpanContext(traceId, spanId, samplingPriority); + var spanContext = new OpenTracingSpanContext(ddSpanContext); + var headers = new MockTextMap(); + + _codec.Inject(spanContext, headers); + + Assert.Equal(spanId.ToString(), headers.Get(HttpHeaderParentId)); + Assert.Equal(traceId.ToString(), headers.Get(HttpHeaderTraceId)); + Assert.Equal(((int)samplingPriority).ToString(), headers.Get(HttpHeaderSamplingPriority)); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/HttpHeadersCarrierTests.cs b/test/Datadog.Trace.OpenTracing.Tests/HttpHeadersCarrierTests.cs new file mode 100644 index 0000000000..42af2ca522 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/HttpHeadersCarrierTests.cs @@ -0,0 +1,62 @@ +using System.Linq; +using System.Net.Http; +using Xunit; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class HttpHeadersCarrierTests + { + private HttpRequestMessage _request; + private OpenTracingHttpHeadersCarrier _carrier; + + public HttpHeadersCarrierTests() + { + _request = new HttpRequestMessage(); + _carrier = new OpenTracingHttpHeadersCarrier(_request.Headers); + } + + [Fact] + public void Set_Value_HeaderIsSet() + { + _carrier.Set("key", "value"); + + Assert.Equal("value", _request.Headers.GetValues("key").Single()); + } + + [Fact] + public void Set_ExistingValue_Override() + { + _request.Headers.Add("key", "value1"); + + _carrier.Set("key", "value2"); + + Assert.Equal("value2", _request.Headers.GetValues("key").Single()); + } + + [Fact] + public void Get_SingleValue_ValueIsCorrectlyRead() + { + _request.Headers.Add("key", "value"); + + Assert.Equal("value", _carrier.Get("key")); + } + + [Fact] + public void Get_MultipleValues_CommaConcatenatedValues() + { + _request.Headers.Add("key", "value1"); + _request.Headers.Add("key", "value2"); + + Assert.Equal("value1,value2", _carrier.Get("key")); + } + + [Fact] + public void GetEntries_MultipleKeys_MultipleKeys() + { + _request.Headers.Add("key1", "value"); + _request.Headers.Add("key2", "value"); + + Assert.Equal(2, _carrier.Count()); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/MockTextMap.cs b/test/Datadog.Trace.OpenTracing.Tests/MockTextMap.cs new file mode 100644 index 0000000000..6bae426dfc --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/MockTextMap.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using OpenTracing.Propagation; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class MockTextMap : ITextMap + { + private Dictionary _dictionary = new Dictionary(); + + public string Get(string key) + { + _dictionary.TryGetValue(key, out string value); + return value; + } + + public IEnumerator> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + public void Set(string key, string value) + { + _dictionary[key] = value; + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanBuilderTests.cs b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanBuilderTests.cs new file mode 100644 index 0000000000..bafd5cc7a1 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanBuilderTests.cs @@ -0,0 +1,230 @@ +using System; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Moq; +using OpenTracing; +using Xunit; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class OpenTracingSpanBuilderTests + { + private static readonly string DefaultServiceName = $"{nameof(OpenTracingSpanBuilderTests)}"; + + private readonly OpenTracingTracer _tracer; + + public OpenTracingSpanBuilderTests() + { + var settings = new TracerSettings + { + ServiceName = DefaultServiceName + }; + + var writerMock = new Mock(MockBehavior.Strict); + var samplerMock = new Mock(); + + var datadogTracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + _tracer = new OpenTracingTracer(datadogTracer); + } + + [Fact] + public void Start_NoServiceName_DefaultServiceNameIsSet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null).Start(); + + Assert.Equal(DefaultServiceName, span.DDSpan.ServiceName); + } + + [Fact] + public void Start_NoParentProvided_RootSpan() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null).Start(); + var ddSpanContext = span.Context.Context as SpanContext; + + Assert.NotNull(ddSpanContext); + Assert.Null(ddSpanContext.ParentId); + Assert.NotEqual(0, ddSpanContext.SpanId); + Assert.NotEqual(0, ddSpanContext.TraceId); + } + + [Fact] + public void Start_AsChildOfSpan_ChildReferencesParent() + { + var root = (OpenTracingSpan)_tracer.BuildSpan(null).Start(); + var child = (OpenTracingSpan)_tracer.BuildSpan(null) + .AsChildOf(root) + .Start(); + + Assert.Null(root.DDSpan.Context.ParentId); + Assert.NotEqual(0, root.DDSpan.Context.SpanId); + Assert.NotEqual(0, root.DDSpan.Context.TraceId); + Assert.Equal(root.DDSpan.Context.SpanId, child.DDSpan.Context.ParentId); + Assert.Equal(root.DDSpan.Context.TraceId, child.DDSpan.Context.TraceId); + Assert.NotEqual(0, child.DDSpan.Context.SpanId); + } + + [Fact] + public void Start_AsChildOfSpanContext_ChildReferencesParent() + { + var root = (OpenTracingSpan)_tracer.BuildSpan(null).Start(); + var child = (OpenTracingSpan)_tracer.BuildSpan(null) + .AsChildOf(root.Context) + .Start(); + + Assert.Null(root.DDSpan.Context.ParentId); + Assert.NotEqual(0, root.DDSpan.Context.SpanId); + Assert.NotEqual(0, root.DDSpan.Context.TraceId); + Assert.Equal(root.DDSpan.Context.SpanId, child.DDSpan.Context.ParentId); + Assert.Equal(root.DDSpan.Context.TraceId, child.DDSpan.Context.TraceId); + Assert.NotEqual(0, child.DDSpan.Context.SpanId); + } + + [Fact] + public void Start_ReferenceAsChildOf_ChildReferencesParent() + { + var root = (OpenTracingSpan)_tracer.BuildSpan(null).Start(); + var child = (OpenTracingSpan)_tracer.BuildSpan(null) + .AddReference(References.ChildOf, root.Context) + .Start(); + + Assert.Null(root.DDSpan.Context.ParentId); + Assert.NotEqual(0, root.DDSpan.Context.SpanId); + Assert.NotEqual(0, root.DDSpan.Context.TraceId); + Assert.Equal(root.DDSpan.Context.SpanId, child.DDSpan.Context.ParentId); + Assert.Equal(root.DDSpan.Context.TraceId, child.DDSpan.Context.TraceId); + Assert.NotEqual(0, child.DDSpan.Context.SpanId); + } + + [Fact] + public void Start_WithTags_TagsAreProperlySet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag("StringKey", "What's tracing") + .WithTag("IntKey", 42) + .WithTag("DoubleKey", 1.618) + .WithTag("BoolKey", true) + .Start(); + + Assert.Equal("What's tracing", span.DDSpan.GetTag("StringKey")); + Assert.Equal("42", span.DDSpan.GetTag("IntKey")); + Assert.Equal("1.618", span.DDSpan.GetTag("DoubleKey")); + Assert.Equal("True", span.DDSpan.GetTag("BoolKey")); + } + + [Fact] + public void Start_SettingService_ServiceIsSet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "MyService") + .Start(); + + Assert.Equal("MyService", span.DDSpan.ServiceName); + } + + [Fact] + public void Start_SettingServiceInParent_ImplicitChildInheritServiceName() + { + IScope root = _tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "MyService") + .StartActive(finishSpanOnDispose: true); + IScope child = _tracer.BuildSpan(null) + .StartActive(finishSpanOnDispose: true); + + Assert.Equal("MyService", ((OpenTracingSpan)root.Span).Span.ServiceName); + Assert.Equal("MyService", ((OpenTracingSpan)child.Span).Span.ServiceName); + } + + [Fact] + public void Start_SettingServiceInParent_ExplicitChildInheritServiceName() + { + IScope root = _tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "MyService") + .StartActive(finishSpanOnDispose: true); + IScope child = _tracer.BuildSpan(null) + .AsChildOf(root.Span) + .StartActive(finishSpanOnDispose: true); + + Assert.Equal("MyService", ((OpenTracingSpan)root.Span).Span.ServiceName); + Assert.Equal("MyService", ((OpenTracingSpan)child.Span).Span.ServiceName); + } + + [Fact] + public void Start_SettingServiceInParent_NotChildDontInheritServiceName() + { + ISpan span1 = _tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "MyService") + .Start(); + IScope root = _tracer.BuildSpan(null) + .StartActive(finishSpanOnDispose: true); + + Assert.Equal("MyService", ((OpenTracingSpan)span1).Span.ServiceName); + Assert.Equal("OpenTracingSpanBuilderTests", ((OpenTracingSpan)root.Span).Span.ServiceName); + } + + [Fact] + public void Start_SettingServiceInChild_ServiceNameOverrideParent() + { + var root = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "MyService") + .Start(); + var child = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag(DatadogTags.ServiceName, "AnotherService") + .Start(); + + Assert.Equal("MyService", root.DDSpan.ServiceName); + Assert.Equal("AnotherService", child.DDSpan.ServiceName); + } + + [Fact] + public void Start_SettingResource_ResourceIsSet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag("resource.name", "MyResource") + .Start(); + + Assert.Equal("MyResource", span.DDSpan.ResourceName); + } + + [Fact] + public void Start_SettingType_TypeIsSet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag("span.type", "web") + .Start(); + + Assert.Equal("web", span.DDSpan.Type); + } + + [Fact] + public void Start_SettingError_ErrorIsSet() + { + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithTag(global::OpenTracing.Tag.Tags.Error.Key, true) + .Start(); + + Assert.True(span.DDSpan.Error); + } + + [Fact] + public void Start_WithStartTimeStamp_TimeStampProperlySet() + { + var startTime = new DateTimeOffset(2017, 01, 01, 0, 0, 0, TimeSpan.Zero); + var span = (OpenTracingSpan)_tracer.BuildSpan(null) + .WithStartTimestamp(startTime) + .Start(); + + Assert.Equal(startTime, span.DDSpan.StartTime); + } + + [Fact] + public void Start_SetOperationName_OperationNameProperlySet() + { + var spanBuilder = new OpenTracingSpanBuilder(_tracer, "Op1"); + + var span = (OpenTracingSpan)spanBuilder.Start(); + + Assert.Equal("Op1", span.DDSpan.OperationName); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanTests.cs b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanTests.cs new file mode 100644 index 0000000000..b0184e75cb --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingSpanTests.cs @@ -0,0 +1,169 @@ +using System; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Moq; +using OpenTracing; +using Xunit; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class OpenTracingSpanTests + { + private readonly OpenTracingTracer _tracer; + + public OpenTracingSpanTests() + { + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + var datadogTracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + _tracer = new OpenTracingTracer(datadogTracer); + } + + [Fact] + public void SetTag_Tags_TagsAreProperlySet() + { + ISpan span = GetScope("Op1").Span; + + span.SetTag("StringKey", "What's tracing"); + span.SetTag("IntKey", 42); + span.SetTag("DoubleKey", 1.618); + span.SetTag("BoolKey", true); + + var otSpan = (OpenTracingSpan)span; + Assert.Equal("What's tracing", otSpan.GetTag("StringKey")); + Assert.Equal("42", otSpan.GetTag("IntKey")); + Assert.Equal("1.618", otSpan.GetTag("DoubleKey")); + Assert.Equal("True", otSpan.GetTag("BoolKey")); + } + + [Fact] + public void SetTag_SpecialTags_ServiceNameSetsService() + { + ISpan span = GetScope("Op1").Span; + const string value = "value"; + + span.SetTag(DatadogTags.ServiceName, value); + + var otSpan = (OpenTracingSpan)span; + Assert.Equal(value, otSpan.Span.ServiceName); + } + + [Fact] + public void SetTag_SpecialTags_ServiceVersionSetsVersion() + { + ISpan span = GetScope("Op1").Span; + const string value = "value"; + + span.SetTag(DatadogTags.ServiceVersion, value); + + var otSpan = (OpenTracingSpan)span; + Assert.Equal(value, otSpan.GetTag(Tags.Version)); + Assert.Equal(value, otSpan.GetTag(DatadogTags.ServiceVersion)); + } + + [Fact] + public void SetOperationName_ValidOperationName_OperationNameIsProperlySet() + { + ISpan span = GetScope("Op0").Span; + + span.SetOperationName("Op1"); + + Assert.Equal("Op1", ((OpenTracingSpan)span).OperationName); + } + + [Fact] + public void Finish_StartTimeInThePastWithNoEndTime_DurationProperlyComputed() + { + TimeSpan expectedDuration = TimeSpan.FromMinutes(1); + var startTime = DateTimeOffset.UtcNow - expectedDuration; + + ISpan span = GetScope("Op1", startTime).Span; + span.Finish(); + + double durationDifference = Math.Abs((((OpenTracingSpan)span).Duration - expectedDuration).TotalMilliseconds); + Assert.True(durationDifference < 100); + } + + /* + [Fact] + public async Task Finish_NoEndTimeProvided_SpanWriten() + { + var span = new OpenTracingSpan(_tracer.StartActive(null, null, null, null)); + await Task.Delay(TimeSpan.FromMilliseconds(1)); + span.Finish(); + + _writerMock.Verify(x => x.WriteTrace(It.IsAny>()), Times.Once); + Assert.True(span.DDSpan.Duration > TimeSpan.Zero); + } + */ + + [Fact] + public void Finish_EndTimeProvided_SpanWritenWithCorrectDuration() + { + var startTime = DateTimeOffset.UtcNow; + var endTime = startTime.AddMilliseconds(10); + + ISpan span = GetScope("Op1", startTime).Span; + span.Finish(endTime); + + Assert.Equal(endTime - startTime, ((OpenTracingSpan)span).Duration); + } + + [Fact] + public void Finish_EndTimeInThePast_DurationIs0() + { + var startTime = DateTimeOffset.UtcNow; + var endTime = startTime.AddMilliseconds(-10); + + ISpan span = GetScope("Op1", startTime).Span; + span.Finish(endTime); + + Assert.Equal(TimeSpan.Zero, ((OpenTracingSpan)span).Duration); + } + + [Fact] + public void Dispose_ExitUsing_SpanWriten() + { + OpenTracingSpan span; + + using (IScope scope = GetScope("Op1")) + { + span = (OpenTracingSpan)scope.Span; + } + + Assert.True(span.Duration > TimeSpan.Zero); + } + + [Fact] + public void Context_TwoCalls_ContextStaysEqual() + { + ISpan span; + global::OpenTracing.ISpanContext firstContext; + + using (IScope scope = GetScope("Op1")) + { + span = scope.Span; + firstContext = span.Context; + } + + var secondContext = span.Context; + + Assert.Same(firstContext, secondContext); + } + + private IScope GetScope(string operationName, DateTimeOffset? startTime = null) + { + ISpanBuilder spanBuilder = new OpenTracingSpanBuilder(_tracer, operationName); + + if (startTime != null) + { + spanBuilder = spanBuilder.WithStartTimestamp(startTime.Value); + } + + return spanBuilder.StartActive(finishSpanOnDispose: true); + } + } +} diff --git a/test/Datadog.Trace.OpenTracing.Tests/OpenTracingTracerTests.cs b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingTracerTests.cs new file mode 100644 index 0000000000..5b0d8a2b99 --- /dev/null +++ b/test/Datadog.Trace.OpenTracing.Tests/OpenTracingTracerTests.cs @@ -0,0 +1,372 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Datadog.Trace.TestHelpers; +using Moq; +using OpenTracing; +using OpenTracing.Propagation; +using Xunit; + +namespace Datadog.Trace.OpenTracing.Tests +{ + public class OpenTracingTracerTests + { + private readonly OpenTracingTracer _tracer; + + public OpenTracingTracerTests() + { + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + var datadogTracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + + _tracer = new OpenTracingTracer(datadogTracer); + } + + [Fact] + public void BuildSpan_NoParameter_DefaultParameters() + { + var builder = _tracer.BuildSpan("Op1"); + var span = (OpenTracingSpan)builder.Start(); + + Assert.Contains(span.DDSpan.ServiceName, TestRunners.ValidNames); + Assert.Equal("Op1", span.DDSpan.OperationName); + } + + [Fact] + public void BuildSpan_OneChild_ChildParentProperlySet() + { + IScope root = _tracer + .BuildSpan("Root") + .StartActive(finishSpanOnDispose: true); + IScope child = _tracer + .BuildSpan("Child") + .StartActive(finishSpanOnDispose: true); + + Span rootDatadogSpan = ((OpenTracingSpan)root.Span).Span; + Span childDatadogSpan = ((OpenTracingSpan)child.Span).Span; + + Assert.Equal(rootDatadogSpan.Context.TraceContext, (ITraceContext)childDatadogSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, childDatadogSpan.Context.ParentId); + } + + [Fact] + public void BuildSpan_2ChildrenOfRoot_ChildrenParentProperlySet() + { + IScope root = _tracer + .BuildSpan("Root") + .StartActive(finishSpanOnDispose: true); + + IScope child1 = _tracer + .BuildSpan("Child1") + .StartActive(finishSpanOnDispose: true); + + child1.Dispose(); + + IScope child2 = _tracer + .BuildSpan("Child2") + .StartActive(finishSpanOnDispose: true); + + Span rootDatadogSpan = ((OpenTracingSpan)root.Span).Span; + Span child1DatadogSpan = ((OpenTracingSpan)child1.Span).Span; + Span child2DatadogSpan = ((OpenTracingSpan)child2.Span).Span; + + Assert.Same(rootDatadogSpan.Context.TraceContext, child1DatadogSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, child1DatadogSpan.Context.ParentId); + Assert.Same(rootDatadogSpan.Context.TraceContext, child2DatadogSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, child2DatadogSpan.Context.ParentId); + } + + [Fact] + public void BuildSpan_2LevelChildren_ChildrenParentProperlySet() + { + IScope root = _tracer + .BuildSpan("Root") + .StartActive(finishSpanOnDispose: true); + IScope child1 = _tracer + .BuildSpan("Child1") + .StartActive(finishSpanOnDispose: true); + IScope child2 = _tracer + .BuildSpan("Child2") + .StartActive(finishSpanOnDispose: true); + + Span rootDatadogSpan = ((OpenTracingSpan)root.Span).Span; + Span child1DatadogSpan = ((OpenTracingSpan)child1.Span).Span; + Span child2DatadogSpan = ((OpenTracingSpan)child2.Span).Span; + + Assert.Same(rootDatadogSpan.Context.TraceContext, child1DatadogSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, child1DatadogSpan.Context.ParentId); + Assert.Same(rootDatadogSpan.Context.TraceContext, child2DatadogSpan.Context.TraceContext); + Assert.Equal(child1DatadogSpan.Context.SpanId, child2DatadogSpan.Context.ParentId); + } + + [Fact] + public async Task BuildSpan_AsyncChildrenCreation_ChildrenParentProperlySet() + { + var tcs = new TaskCompletionSource(); + + IScope root = _tracer + .BuildSpan("Root") + .StartActive(finishSpanOnDispose: true); + + Func> createSpanAsync = async (t) => + { + await tcs.Task; + return (OpenTracingSpan)_tracer.BuildSpan("AsyncChild").Start(); + }; + var tasks = Enumerable.Range(0, 10).Select(x => createSpanAsync(_tracer)).ToArray(); + + var syncChild = (OpenTracingSpan)_tracer.BuildSpan("SyncChild").Start(); + tcs.SetResult(true); + + Span rootDatadogSpan = ((OpenTracingSpan)root.Span).Span; + + Assert.Equal(rootDatadogSpan.Context.TraceContext, (ITraceContext)syncChild.DDSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, syncChild.DDSpan.Context.ParentId); + + foreach (var task in tasks) + { + var span = await task; + Assert.Equal(rootDatadogSpan.Context.TraceContext, (ITraceContext)span.DDSpan.Context.TraceContext); + Assert.Equal(rootDatadogSpan.Context.SpanId, span.DDSpan.Context.ParentId); + } + } + + [Fact] + public void Inject_HttpHeadersFormat_CorrectHeaders() + { + var span = (OpenTracingSpan)_tracer.BuildSpan("Span").Start(); + var headers = new MockTextMap(); + + _tracer.Inject(span.Context, BuiltinFormats.HttpHeaders, headers); + + Assert.Equal(span.DDSpan.Context.TraceId.ToString(), headers.Get(HttpHeaderNames.TraceId)); + Assert.Equal(span.DDSpan.Context.SpanId.ToString(), headers.Get(HttpHeaderNames.ParentId)); + } + + [Fact] + public void Inject_TextMapFormat_CorrectHeaders() + { + var span = (OpenTracingSpan)_tracer.BuildSpan("Span").Start(); + var headers = new MockTextMap(); + + _tracer.Inject(span.Context, BuiltinFormats.TextMap, headers); + + Assert.Equal(span.DDSpan.Context.TraceId.ToString(), headers.Get(HttpHeaderNames.TraceId)); + Assert.Equal(span.DDSpan.Context.SpanId.ToString(), headers.Get(HttpHeaderNames.ParentId)); + } + + [Fact] + public void Inject_UnknownFormat_Throws() + { + var span = (OpenTracingSpan)_tracer.BuildSpan("Span").Start(); + var headers = new MockTextMap(); + var mockFormat = new Mock>(); + + Assert.Throws(() => _tracer.Inject(span.Context, mockFormat.Object, headers)); + } + + [Fact] + public void Extract_HttpHeadersFormat_HeadersProperlySet_SpanContext() + { + const ulong parentId = 10; + const ulong traceId = 42; + var headers = new MockTextMap(); + headers.Set(HttpHeaderNames.ParentId, parentId.ToString()); + headers.Set(HttpHeaderNames.TraceId, traceId.ToString()); + + var otSpanContext = (OpenTracingSpanContext)_tracer.Extract(BuiltinFormats.HttpHeaders, headers); + + Assert.Equal(parentId, otSpanContext.Context.SpanId); + Assert.Equal(traceId, otSpanContext.Context.TraceId); + } + + [Fact] + public void Extract_TextMapFormat_HeadersProperlySet_SpanContext() + { + const ulong parentId = 10; + const ulong traceId = 42; + var headers = new MockTextMap(); + headers.Set(HttpHeaderNames.ParentId, parentId.ToString()); + headers.Set(HttpHeaderNames.TraceId, traceId.ToString()); + + var otSpanContext = (OpenTracingSpanContext)_tracer.Extract(BuiltinFormats.TextMap, headers); + + Assert.Equal(parentId, otSpanContext.Context.SpanId); + Assert.Equal(traceId, otSpanContext.Context.TraceId); + } + + [Fact] + public void Extract_UnknownFormat_Throws() + { + const ulong parentId = 10; + const ulong traceId = 42; + var headers = new MockTextMap(); + headers.Set(HttpHeaderNames.ParentId, parentId.ToString()); + headers.Set(HttpHeaderNames.TraceId, traceId.ToString()); + var mockFormat = new Mock>(); + + Assert.Throws(() => _tracer.Extract(mockFormat.Object, headers)); + } + + [Fact] + public void StartActive_NoServiceName_DefaultServiceName() + { + var scope = _tracer.BuildSpan("Operation") + .StartActive(); + + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Contains(ddSpan.ServiceName, TestRunners.ValidNames); + } + + [Fact] + public void SetDefaultServiceName() + { + ITracer tracer = OpenTracingTracerFactory.CreateTracer(defaultServiceName: "DefaultServiceName"); + + var scope = tracer.BuildSpan("Operation") + .StartActive(); + + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("DefaultServiceName", ddSpan.ServiceName); + } + + [Fact] + public void SetServiceName_WithTag() + { + var scope = _tracer.BuildSpan("Operation") + .WithTag(DatadogTags.ServiceName, "MyAwesomeService") + .StartActive(); + + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void SetServiceName_SetTag() + { + var scope = _tracer.BuildSpan("Operation") + .StartActive(); + + scope.Span.SetTag(DatadogTags.ServiceName, "MyAwesomeService"); + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void OverrideDefaultServiceName_WithTag() + { + ITracer tracer = OpenTracingTracerFactory.CreateTracer(defaultServiceName: "DefaultServiceName"); + + var scope = tracer.BuildSpan("Operation") + .WithTag(DatadogTags.ServiceName, "MyAwesomeService") + .StartActive(); + + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void OverrideDefaultServiceName_SetTag() + { + ITracer tracer = OpenTracingTracerFactory.CreateTracer(defaultServiceName: "DefaultServiceName"); + + var scope = tracer.BuildSpan("Operation") + .StartActive(); + + scope.Span.SetTag(DatadogTags.ServiceName, "MyAwesomeService"); + var otSpan = (OpenTracingSpan)scope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void InheritParentServiceName_WithTag() + { + var parentScope = _tracer.BuildSpan("ParentOperation") + .WithTag(DatadogTags.ServiceName, "MyAwesomeService") + .StartActive(); + + var childScope = _tracer.BuildSpan("ChildOperation") + .AsChildOf(parentScope.Span) + .StartActive(); + + var otSpan = (OpenTracingSpan)childScope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void InheritParentServiceName_SetTag() + { + var parentScope = _tracer.BuildSpan("ParentOperation") + .StartActive(); + + parentScope.Span.SetTag(DatadogTags.ServiceName, "MyAwesomeService"); + + var childScope = _tracer.BuildSpan("ChildOperation") + .AsChildOf(parentScope.Span) + .StartActive(); + + var otSpan = (OpenTracingSpan)childScope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void Parent_OverrideDefaultServiceName_WithTag() + { + ITracer tracer = OpenTracingTracerFactory.CreateTracer(defaultServiceName: "DefaultServiceName"); + + var parentScope = tracer.BuildSpan("ParentOperation") + .WithTag(DatadogTags.ServiceName, "MyAwesomeService") + .StartActive(); + + var childScope = tracer.BuildSpan("ChildOperation") + .AsChildOf(parentScope.Span) + .StartActive(); + + var otSpan = (OpenTracingSpan)childScope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + + [Fact] + public void Parent_OverrideDefaultServiceName_SetTag() + { + ITracer tracer = OpenTracingTracerFactory.CreateTracer(defaultServiceName: "DefaultServiceName"); + + var parentScope = tracer.BuildSpan("ParentOperation") + .StartActive(); + + parentScope.Span.SetTag(DatadogTags.ServiceName, "MyAwesomeService"); + + var childScope = tracer.BuildSpan("ChildOperation") + .AsChildOf(parentScope.Span) + .StartActive(); + + var otSpan = (OpenTracingSpan)childScope.Span; + var ddSpan = otSpan.Span; + + Assert.Equal("MyAwesomeService", ddSpan.ServiceName); + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/AlphabeticalOrderer.cs b/test/Datadog.Trace.TestHelpers/AlphabeticalOrderer.cs new file mode 100644 index 0000000000..3cf1d0d53e --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/AlphabeticalOrderer.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Datadog.Trace.TestHelpers +{ + public class AlphabeticalOrderer : ITestCaseOrderer + { + public IEnumerable OrderTestCases(IEnumerable testCases) + where TTestCase : ITestCase + { + var result = testCases.ToList(); + result.Sort((x, y) => StringComparer.OrdinalIgnoreCase.Compare(x.TestMethod.Method.Name, y.TestMethod.Method.Name)); + return result; + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/Datadog.Trace.TestHelpers.csproj b/test/Datadog.Trace.TestHelpers/Datadog.Trace.TestHelpers.csproj new file mode 100644 index 0000000000..066615d26c --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/Datadog.Trace.TestHelpers.csproj @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs new file mode 100644 index 0000000000..8fbadd5f5a --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/EnvironmentHelper.cs @@ -0,0 +1,416 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using Datadog.Core.Tools; +using Xunit.Abstractions; + +namespace Datadog.Trace.TestHelpers +{ + public class EnvironmentHelper + { + private static readonly Assembly EntryAssembly = Assembly.GetEntryAssembly(); + private static readonly Assembly ExecutingAssembly = Assembly.GetExecutingAssembly(); + private static readonly string RuntimeFrameworkDescription = RuntimeInformation.FrameworkDescription.ToLower(); + + private readonly ITestOutputHelper _output; + private readonly int _major; + private readonly int _minor; + private readonly string _patch = null; + + private readonly string _appNamePrepend; + private readonly string _runtime; + private readonly bool _isCoreClr; + private readonly string _samplesDirectory; + private readonly Type _anchorType; + private readonly Assembly _anchorAssembly; + private readonly TargetFrameworkAttribute _targetFramework; + + private bool _requiresProfiling; + private string _integrationsFileLocation; + private string _profilerFileLocation; + + public EnvironmentHelper( + string sampleName, + Type anchorType, + ITestOutputHelper output, + string samplesDirectory = "samples", + bool prependSamplesToAppName = true, + bool requiresProfiling = true) + { + SampleName = sampleName; + _samplesDirectory = samplesDirectory ?? "samples"; + _anchorType = anchorType; + _anchorAssembly = Assembly.GetAssembly(_anchorType); + _targetFramework = Assembly.GetAssembly(anchorType).GetCustomAttribute(); + _output = output; + _requiresProfiling = requiresProfiling; + + var parts = _targetFramework.FrameworkName.Split(','); + _runtime = parts[0]; + _isCoreClr = _runtime.Equals(EnvironmentTools.CoreFramework); + + var versionParts = parts[1].Replace("Version=v", string.Empty).Split('.'); + _major = int.Parse(versionParts[0]); + _minor = int.Parse(versionParts[1]); + + if (versionParts.Length == 3) + { + _patch = versionParts[2]; + } + + _appNamePrepend = prependSamplesToAppName + ? "Samples." + : string.Empty; + } + + public bool DebugModeEnabled { get; set; } + + public Dictionary CustomEnvironmentVariables { get; set; } = new Dictionary(); + + public string SampleName { get; } + + public string FullSampleName => $"{_appNamePrepend}{SampleName}"; + + public static EnvironmentHelper NonProfiledHelper(Type anchor, string appName, string directory) + { + return new EnvironmentHelper( + sampleName: appName, + anchorType: anchor, + output: null, + samplesDirectory: directory, + prependSamplesToAppName: false, + requiresProfiling: false); + } + + public static string GetExecutingAssembly() + { + return ExecutingAssembly.Location; + } + + public static bool IsCoreClr() + { + return RuntimeFrameworkDescription.Contains("core"); + } + + public static string GetRuntimeIdentifier() + { + return IsCoreClr() + ? string.Empty + : $"{EnvironmentTools.GetOS()}-{EnvironmentTools.GetPlatform()}"; + } + + public static string GetSolutionDirectory() + { + return EnvironmentTools.GetSolutionDirectory(); + } + + public static void ClearProfilerEnvironmentVariables() + { + var environmentVariables = new[] + { + // .NET Core + "CORECLR_ENABLE_PROFILING", + "CORECLR_PROFILER", + "CORECLR_PROFILER_PATH", + "CORECLR_PROFILER_PATH_32", + "CORECLR_PROFILER_PATH_64", + + // .NET Framework + "COR_ENABLE_PROFILING", + "COR_PROFILER", + "COR_PROFILER_PATH", + + // Datadog + "DD_PROFILER_PROCESSES", + "DD_DOTNET_TRACER_HOME", + "DD_INTEGRATIONS", + "DD_DISABLED_INTEGRATIONS", + "DD_SERVICE", + "DD_VERSION", + "DD_TAGS" + }; + + foreach (string variable in environmentVariables) + { + Environment.SetEnvironmentVariable(variable, null); + } + } + + public void SetEnvironmentVariables( + int agentPort, + int aspNetCorePort, + string processPath, + StringDictionary environmentVariables) + { + var processName = processPath; + string profilerEnabled = _requiresProfiling ? "1" : "0"; + string profilerPath; + + if (IsCoreClr()) + { + environmentVariables["CORECLR_ENABLE_PROFILING"] = profilerEnabled; + environmentVariables["CORECLR_PROFILER"] = EnvironmentTools.ProfilerClsId; + + profilerPath = GetProfilerPath(); + environmentVariables["CORECLR_PROFILER_PATH"] = profilerPath; + environmentVariables["DD_DOTNET_TRACER_HOME"] = Path.GetDirectoryName(profilerPath); + } + else + { + environmentVariables["COR_ENABLE_PROFILING"] = profilerEnabled; + environmentVariables["COR_PROFILER"] = EnvironmentTools.ProfilerClsId; + + profilerPath = GetProfilerPath(); + environmentVariables["COR_PROFILER_PATH"] = profilerPath; + environmentVariables["DD_DOTNET_TRACER_HOME"] = Path.GetDirectoryName(profilerPath); + + processName = Path.GetFileName(processPath); + } + + if (DebugModeEnabled) + { + environmentVariables["DD_TRACE_DEBUG"] = "1"; + } + + environmentVariables["DD_PROFILER_PROCESSES"] = processName; + + string integrations = string.Join(";", GetIntegrationsFilePaths()); + environmentVariables["DD_INTEGRATIONS"] = integrations; + environmentVariables["DD_TRACE_AGENT_HOSTNAME"] = "localhost"; + environmentVariables["DD_TRACE_AGENT_PORT"] = agentPort.ToString(); + + // for ASP.NET Core sample apps, set the server's port + environmentVariables["ASPNETCORE_URLS"] = $"http://localhost:{aspNetCorePort}/"; + + foreach (var name in new[] { "SERVICESTACK_REDIS_HOST", "STACKEXCHANGE_REDIS_HOST" }) + { + var value = Environment.GetEnvironmentVariable(name); + if (!string.IsNullOrEmpty(value)) + { + environmentVariables[name] = value; + } + } + + foreach (var key in CustomEnvironmentVariables.Keys) + { + environmentVariables[key] = CustomEnvironmentVariables[key]; + } + } + + public string[] GetIntegrationsFilePaths() + { + if (_integrationsFileLocation == null) + { + string fileName = "integrations.json"; + + var directory = GetSampleApplicationOutputDirectory(); + + var relativePath = Path.Combine( + "profiler-lib", + fileName); + + _integrationsFileLocation = Path.Combine( + directory, + relativePath); + + // TODO: get rid of the fallback options when we have a consistent convention + + if (!File.Exists(_integrationsFileLocation)) + { + _output?.WriteLine($"Attempt 1: Unable to find integrations at {_integrationsFileLocation}."); + // Let's try the executing directory, as dotnet publish ignores the Copy attributes we currently use + _integrationsFileLocation = Path.Combine( + GetExecutingProjectBin(), + relativePath); + } + + if (!File.Exists(_integrationsFileLocation)) + { + _output?.WriteLine($"Attempt 2: Unable to find integrations at {_integrationsFileLocation}."); + // One last attempt at the solution root + _integrationsFileLocation = Path.Combine( + GetSolutionDirectory(), + fileName); + } + + if (!File.Exists(_integrationsFileLocation)) + { + throw new Exception($"Attempt 3: Unable to find integrations at {_integrationsFileLocation}"); + } + + _output?.WriteLine($"Found integrations at {_integrationsFileLocation}."); + } + + return new[] + { + _integrationsFileLocation + }; + } + + public string GetProfilerPath() + { + if (_profilerFileLocation == null) + { + string extension = EnvironmentTools.IsWindows() + ? "dll" + : "so"; + + string fileName = $"Datadog.Trace.ClrProfiler.Native.{extension}"; + + var directory = GetSampleApplicationOutputDirectory(); + + var relativePath = Path.Combine( + "profiler-lib", + fileName); + + _profilerFileLocation = Path.Combine( + directory, + relativePath); + + // TODO: get rid of the fallback options when we have a consistent convention + + if (!File.Exists(_profilerFileLocation)) + { + _output?.WriteLine($"Attempt 1: Unable to find profiler at {_profilerFileLocation}."); + // Let's try the executing directory, as dotnet publish ignores the Copy attributes we currently use + _profilerFileLocation = Path.Combine( + GetExecutingProjectBin(), + relativePath); + } + + if (!File.Exists(_profilerFileLocation)) + { + _output?.WriteLine($"Attempt 2: Unable to find profiler at {_profilerFileLocation}."); + // One last attempt at the actual native project directory + _profilerFileLocation = Path.Combine( + GetProfilerProjectBin(), + fileName); + } + + if (!File.Exists(_profilerFileLocation)) + { + throw new Exception($"Attempt 3: Unable to find profiler at {_profilerFileLocation}"); + } + + _output?.WriteLine($"Found profiler at {_profilerFileLocation}."); + } + + return _profilerFileLocation; + } + + public string GetSampleApplicationPath(string packageVersion = "", string framework = "") + { + string extension = "exe"; + + if (EnvironmentHelper.IsCoreClr() || _samplesDirectory.Contains("aspnet")) + { + extension = "dll"; + } + + var appFileName = $"{FullSampleName}.{extension}"; + var sampleAppPath = Path.Combine(GetSampleApplicationOutputDirectory(packageVersion: packageVersion, framework: framework), appFileName); + return sampleAppPath; + } + + public string GetSampleExecutionSource() + { + string executor; + + if (_samplesDirectory.Contains("aspnet")) + { + executor = $"C:\\Program Files{(Environment.Is64BitProcess ? string.Empty : " (x86)")}\\IIS Express\\iisexpress.exe"; + } + else if (IsCoreClr()) + { + executor = EnvironmentTools.IsWindows() ? "dotnet.exe" : "dotnet"; + } + else + { + var appFileName = $"{FullSampleName}.exe"; + executor = Path.Combine(GetSampleApplicationOutputDirectory(), appFileName); + + if (!File.Exists(executor)) + { + throw new Exception($"Unable to find executing assembly at {executor}"); + } + } + + return executor; + } + + public string GetSampleProjectDirectory() + { + var solutionDirectory = GetSolutionDirectory(); + var projectDir = Path.Combine( + solutionDirectory, + _samplesDirectory, + $"{FullSampleName}"); + return projectDir; + } + + public string GetSampleApplicationOutputDirectory(string packageVersion = "", string framework = "") + { + var targetFramework = string.IsNullOrEmpty(framework) ? GetTargetFramework() : framework; + var binDir = Path.Combine( + GetSampleProjectDirectory(), + "bin"); + + string outputDir; + + if (_samplesDirectory.Contains("aspnet")) + { + outputDir = binDir; + } + else if (EnvironmentTools.GetOS() == "win") + { + outputDir = Path.Combine( + binDir, + packageVersion, + EnvironmentTools.GetPlatform(), + EnvironmentTools.GetBuildConfiguration(), + targetFramework); + } + else + { + outputDir = Path.Combine( + binDir, + packageVersion, + EnvironmentTools.GetBuildConfiguration(), + targetFramework, + "publish"); + } + + return outputDir; + } + + public string GetTargetFramework() + { + if (_isCoreClr) + { + return $"netcoreapp{_major}.{_minor}"; + } + + return $"net{_major}{_minor}{_patch ?? string.Empty}"; + } + + private string GetProfilerProjectBin() + { + return Path.Combine( + GetSolutionDirectory(), + "src", + "Datadog.Trace.ClrProfiler.Native", + "bin", + EnvironmentTools.GetBuildConfiguration(), + EnvironmentTools.GetPlatform().ToLower()); + } + + private string GetExecutingProjectBin() + { + return Path.GetDirectoryName(ExecutingAssembly.Location); + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/EventArgs.cs b/test/Datadog.Trace.TestHelpers/EventArgs.cs new file mode 100644 index 0000000000..b29e87ff2f --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/EventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace Datadog.Trace.TestHelpers +{ + public class EventArgs : EventArgs + { + public EventArgs(T value) + { + Value = value; + } + + public T Value { get; } + } +} diff --git a/test/Datadog.Trace.TestHelpers/HeadersCollectionTestHelpers.cs b/test/Datadog.Trace.TestHelpers/HeadersCollectionTestHelpers.cs new file mode 100644 index 0000000000..848b8f8878 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/HeadersCollectionTestHelpers.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Datadog.Trace.TestHelpers +{ + public static class HeadersCollectionTestHelpers + { + public static IEnumerable GetInvalidIds() + { + yield return new object[] { "0" }; + yield return new object[] { "-1" }; + yield return new object[] { "id" }; + } + + public static IEnumerable GetInvalidSamplingPriorities() + { + yield return new object[] { "-2" }; + yield return new object[] { "3" }; + yield return new object[] { "sampling.priority" }; + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/RecordHttpHandler.cs b/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/RecordHttpHandler.cs new file mode 100644 index 0000000000..3d1e8def87 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/RecordHttpHandler.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using MsgPack; + +namespace Datadog.Trace.TestHelpers.HttpMessageHandlers +{ + /// + /// This class implements a handler that can be passed as parameter of a new HttpClient + /// and will record all requests made by that client. + /// + /// + public class RecordHttpHandler : DelegatingHandler + { + private object _lock = new object(); + private int _count = 0; + private int _target = 0; + private TaskCompletionSource _tcs; + + public RecordHttpHandler() + { + InnerHandler = new HttpClientHandler(); + Requests = new List>(); + Responses = new List(); + } + + public List> Requests { get; set; } + + public List> Traces => Requests + .Where(x => x.Item1.RequestUri.ToString().Contains("/v0.4/traces")) + .Select(x => Unpacking.UnpackObject(x.Item2).Value.AsList()) + .ToList(); + + public List Services => Requests + .Where(x => x.Item1.RequestUri.ToString().Contains("/v0.4/services")) + .Select(x => Unpacking.UnpackObject(x.Item2).Value.AsDictionary()) + .ToList(); + + public List Responses { get; set; } + + public Task WaitForCompletion(int target, TimeSpan? timeout = null) + { + timeout = timeout ?? TimeSpan.FromSeconds(10); + lock (_lock) + { + if (_count >= target) + { + return Task.FromResult(true); + } + + if (_tcs == null) + { + _target = target; + _tcs = new TaskCompletionSource(); + var cancellationSource = new CancellationTokenSource(timeout.Value); + cancellationSource.Token.Register(() => _tcs?.SetException(new TimeoutException())); + return _tcs.Task; + } + else + { + throw new InvalidOperationException("This method should not be called twice on the same instance"); + } + } + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + var requestContent = await request.Content.ReadAsByteArrayAsync(); + var response = await base.SendAsync(request, cancellationToken); + lock (_lock) + { + Requests.Add(Tuple.Create(request, requestContent)); + Responses.Add(response); + _count++; + if (_tcs != null && _count >= _target) + { + _tcs.SetResult(true); + _tcs = null; + } + } + + return response; + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/SetResponseHandler.cs b/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/SetResponseHandler.cs new file mode 100644 index 0000000000..08378060d8 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/HttpMessageHandlers/SetResponseHandler.cs @@ -0,0 +1,24 @@ +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Datadog.Trace.TestHelpers.HttpMessageHandlers +{ + public class SetResponseHandler : DelegatingHandler + { + private readonly HttpResponseMessage _response; + + public SetResponseHandler(HttpResponseMessage response) + { + _response = response; + } + + public int RequestsCount { get; set; } + + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + RequestsCount++; + return Task.FromResult(_response); + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/MockTracerAgent.cs b/test/Datadog.Trace.TestHelpers/MockTracerAgent.cs new file mode 100644 index 0000000000..d1e5c334c0 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/MockTracerAgent.cs @@ -0,0 +1,262 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Collections.Specialized; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading; +using Datadog.Core.Tools; +using Datadog.Trace.ExtensionMethods; +using MessagePack; + +namespace Datadog.Trace.TestHelpers +{ + public class MockTracerAgent : IDisposable + { + private readonly HttpListener _listener; + private readonly Thread _listenerThread; + + public MockTracerAgent(int port = 8126, int retries = 5) + { + // try up to 5 consecutive ports before giving up + while (true) + { + // seems like we can't reuse a listener if it fails to start, + // so create a new listener each time we retry + var listener = new HttpListener(); + listener.Prefixes.Add($"http://localhost:{port}/"); + + try + { + listener.Start(); + + // successfully listening + Port = port; + _listener = listener; + + _listenerThread = new Thread(HandleHttpRequests); + _listenerThread.Start(); + + return; + } + catch (HttpListenerException) when (retries > 0) + { + // only catch the exception if there are retries left + port = TcpPortProvider.GetOpenPort(); + retries--; + } + + // always close listener if exception is thrown, + // whether it was caught or not + listener.Close(); + } + } + + public event EventHandler> RequestReceived; + + public event EventHandler>>> RequestDeserialized; + + /// + /// Gets or sets a value indicating whether to skip serialization of traces. + /// + public bool ShouldDeserializeTraces { get; set; } = true; + + /// + /// Gets the TCP port that this Agent is listening on. + /// Can be different from 's initialPort + /// parameter if listening on that port fails. + /// + public int Port { get; } + + /// + /// Gets the filters used to filter out spans we don't want to look at for a test. + /// + public List> SpanFilters { get; private set; } = new List>(); + + public IImmutableList Spans { get; private set; } = ImmutableList.Empty; + + public IImmutableList RequestHeaders { get; private set; } = ImmutableList.Empty; + + /// + /// Wait for the given number of spans to appear. + /// + /// The expected number of spans. + /// The timeout + /// The integration we're testing + /// Minimum time to check for spans from + /// When true, returns every span regardless of operation name + /// The list of spans. + public IImmutableList WaitForSpans( + int count, + int timeoutInMilliseconds = 20000, + string operationName = null, + DateTimeOffset? minDateTime = null, + bool returnAllOperations = false) + { + var deadline = DateTime.Now.AddMilliseconds(timeoutInMilliseconds); + var minimumOffset = (minDateTime ?? DateTimeOffset.MinValue).ToUnixTimeNanoseconds(); + + IImmutableList relevantSpans = ImmutableList.Empty; + + while (DateTime.Now < deadline) + { + relevantSpans = + Spans + .Where(s => SpanFilters.All(shouldReturn => shouldReturn(s))) + .Where(s => s.Start > minimumOffset) + .ToImmutableList(); + + if (relevantSpans.Count(s => operationName == null || s.Name == operationName) >= count) + { + break; + } + + Thread.Sleep(500); + } + + foreach (var headers in RequestHeaders) + { + // This is the place to check against headers we expect + AssertHeader( + headers, + "X-Datadog-Trace-Count", + header => + { + if (int.TryParse(header, out int traceCount)) + { + return traceCount >= 0; + } + + return false; + }); + } + + if (!returnAllOperations) + { + relevantSpans = + relevantSpans + .Where(s => operationName == null || s.Name == operationName) + .ToImmutableList(); + } + + return relevantSpans; + } + + public void Dispose() + { + _listener?.Stop(); + } + + protected virtual void OnRequestReceived(HttpListenerContext context) + { + RequestReceived?.Invoke(this, new EventArgs(context)); + } + + protected virtual void OnRequestDeserialized(IList> traces) + { + RequestDeserialized?.Invoke(this, new EventArgs>>(traces)); + } + + private void AssertHeader( + NameValueCollection headers, + string headerKey, + Func assertion) + { + var header = headers.Get(headerKey); + + if (string.IsNullOrEmpty(header)) + { + throw new Exception($"Every submission to the agent should have a {headerKey} header."); + } + + if (!assertion(header)) + { + throw new Exception($"Failed assertion for {headerKey} on {header}"); + } + } + + private void HandleHttpRequests() + { + while (_listener.IsListening) + { + try + { + var ctx = _listener.GetContext(); + OnRequestReceived(ctx); + + if (ShouldDeserializeTraces) + { + var spans = MessagePackSerializer.Deserialize>>(ctx.Request.InputStream); + OnRequestDeserialized(spans); + + lock (this) + { + // we only need to lock when replacing the span collection, + // not when reading it because it is immutable + Spans = Spans.AddRange(spans.SelectMany(trace => trace)); + RequestHeaders = RequestHeaders.Add(new NameValueCollection(ctx.Request.Headers)); + } + } + + ctx.Response.ContentType = "application/json"; + var buffer = Encoding.UTF8.GetBytes("{}"); + ctx.Response.OutputStream.Write(buffer, 0, buffer.Length); + ctx.Response.Close(); + } + catch (HttpListenerException) + { + // listener was stopped, + // ignore to let the loop end and the method return + } + catch (ObjectDisposedException) + { + // the response has been already disposed. + } + } + } + + [MessagePackObject] + [DebuggerDisplay("TraceId={TraceId}, SpanId={SpanId}, Service={Service}, Name={Name}, Resource={Resource}")] + public struct Span + { + [Key("trace_id")] + public ulong TraceId { get; set; } + + [Key("span_id")] + public ulong SpanId { get; set; } + + [Key("name")] + public string Name { get; set; } + + [Key("resource")] + public string Resource { get; set; } + + [Key("service")] + public string Service { get; set; } + + [Key("type")] + public string Type { get; set; } + + [Key("start")] + public long Start { get; set; } + + [Key("duration")] + public long Duration { get; set; } + + [Key("parent_id")] + public ulong? ParentId { get; set; } + + [Key("error")] + public byte Error { get; set; } + + [Key("meta")] + public Dictionary Tags { get; set; } + + [Key("metrics")] + public Dictionary Metrics { get; set; } + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/MsgPackHelpers.cs b/test/Datadog.Trace.TestHelpers/MsgPackHelpers.cs new file mode 100644 index 0000000000..89d440d657 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/MsgPackHelpers.cs @@ -0,0 +1,108 @@ +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.ExtensionMethods; +using MsgPack; +using Xunit; + +namespace Datadog.Trace.TestHelpers +{ + /// + /// This class provides a bunch of helpers to read Span and ServiceInfo data + /// from their serialized MsgPack representation. (It is not straightforward + /// to create deserializer for them since they are not public and don't provide + /// setters for all fields) + /// + public static class MsgPackHelpers + { + public static ulong TraceId(this MessagePackObject obj) + { + return obj.FirstDictionary()["trace_id"].AsUInt64(); + } + + public static ulong SpanId(this MessagePackObject obj) + { + return obj.FirstDictionary()["span_id"].AsUInt64(); + } + + public static ulong ParentId(this MessagePackObject obj) + { + return obj.FirstDictionary()["parent_id"].AsUInt64(); + } + + public static string OperationName(this MessagePackObject obj) + { + return obj.FirstDictionary()["name"].AsString(); + } + + public static string ResourceName(this MessagePackObject obj) + { + return obj.FirstDictionary()["resource"].AsString(); + } + + public static string ServiceName(this MessagePackObject obj) + { + return obj.FirstDictionary()["service"].AsString(); + } + + public static long StartTime(this MessagePackObject obj) + { + return obj.FirstDictionary()["start"].AsInt64(); + } + + public static long Duration(this MessagePackObject obj) + { + return obj.FirstDictionary()["duration"].AsInt64(); + } + + public static string Type(this MessagePackObject obj) + { + return obj.FirstDictionary()["type"].AsString(); + } + + public static string Error(this MessagePackObject obj) + { + return obj.FirstDictionary()["error"].AsString(); + } + + public static Dictionary Tags(this MessagePackObject obj) + { + return obj.FirstDictionary()["meta"].AsDictionary().ToDictionary(kv => kv.Key.AsString(), kv => kv.Value.AsString()); + } + + public static void AssertSpanEqual(Span expected, MessagePackObject actual) + { + Assert.Equal(expected.Context.TraceId, actual.TraceId()); + Assert.Equal(expected.Context.SpanId, actual.SpanId()); + if (expected.Context.ParentId.HasValue) + { + Assert.Equal(expected.Context.ParentId, actual.ParentId()); + } + + Assert.Equal(expected.OperationName, actual.OperationName()); + Assert.Equal(expected.ResourceName, actual.ResourceName()); + Assert.Equal(expected.ServiceName, actual.ServiceName()); + Assert.Equal(expected.Type, actual.Type()); + Assert.Equal(expected.StartTime.ToUnixTimeNanoseconds(), actual.StartTime()); + Assert.Equal(expected.Duration.ToNanoseconds(), actual.Duration()); + if (expected.Error) + { + Assert.Equal("1", actual.Error()); + } + + if (expected.Tags != null) + { + Assert.Equal(expected.Tags, actual.Tags()); + } + } + + private static MessagePackObjectDictionary FirstDictionary(this MessagePackObject obj) + { + if (obj.IsList) + { + return obj.AsList().First().FirstDictionary(); + } + + return obj.AsDictionary(); + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/ProfilerHelper.cs b/test/Datadog.Trace.TestHelpers/ProfilerHelper.cs new file mode 100644 index 0000000000..e6c5942eb0 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/ProfilerHelper.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Datadog.Trace.TestHelpers +{ + public class ProfilerHelper + { + public static Process StartProcessWithProfiler( + string executable, + string applicationPath, + EnvironmentHelper environmentHelper, + IEnumerable integrationPaths, + string arguments = null, + bool redirectStandardInput = false, + int traceAgentPort = 9696, + int aspNetCorePort = 5000) + { + if (environmentHelper == null) + { + throw new ArgumentNullException(nameof(environmentHelper)); + } + + if (integrationPaths == null) + { + throw new ArgumentNullException(nameof(integrationPaths)); + } + + // clear all relevant environment variables to start with a clean slate + EnvironmentHelper.ClearProfilerEnvironmentVariables(); + + ProcessStartInfo startInfo; + + if (EnvironmentHelper.IsCoreClr()) + { + // .NET Core + startInfo = new ProcessStartInfo(executable, $"{applicationPath} {arguments ?? string.Empty}"); + } + else + { + // .NET Framework + startInfo = new ProcessStartInfo(applicationPath, $"{arguments ?? string.Empty}"); + } + + environmentHelper.SetEnvironmentVariables(traceAgentPort, aspNetCorePort, executable, startInfo.EnvironmentVariables); + + startInfo.UseShellExecute = false; + startInfo.CreateNoWindow = true; + startInfo.RedirectStandardOutput = true; + startInfo.RedirectStandardError = true; + startInfo.RedirectStandardInput = redirectStandardInput; + + return Process.Start(startInfo); + } + } +} diff --git a/test/Datadog.Trace.TestHelpers/TestRunners.cs b/test/Datadog.Trace.TestHelpers/TestRunners.cs new file mode 100644 index 0000000000..793ff184aa --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/TestRunners.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace Datadog.Trace.TestHelpers +{ + public class TestRunners + { + public static readonly IEnumerable ValidNames = new[] + { + "testhost", + "testhost.x86", + "vstest.console", + "xunit.console.x86", + "xunit.console.x64", + "ReSharperTestRunner64", + "ReSharperTestRunner64c" + }; + } +} diff --git a/test/Datadog.Trace.TestHelpers/TestSpan.cs b/test/Datadog.Trace.TestHelpers/TestSpan.cs new file mode 100644 index 0000000000..9be44250d3 --- /dev/null +++ b/test/Datadog.Trace.TestHelpers/TestSpan.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Abstractions; + +namespace Datadog.Trace.TestHelpers +{ + public class TestSpan : ISpan + { + public string ResourceName { get; set; } + + public string Type { get; set; } + + public bool Error { get; set; } + + private Dictionary Tags { get; } = new Dictionary(); + + ISpan ISpan.SetTag(string key, string value) + { + SetTagInternal(key, value); + + return this; + } + + public string GetTag(string key) + => Tags.TryGetValue(key, out var tagValue) + ? tagValue + : null; + + public void SetException(Exception exception) + { + Error = true; + + SetTagInternal(Trace.Tags.ErrorMsg, exception.Message); + SetTagInternal(Trace.Tags.ErrorStack, exception.StackTrace); + SetTagInternal(Trace.Tags.ErrorType, exception.GetType().ToString()); + } + + private void SetTagInternal(string key, string value) + { + if (value == null) + { + Tags.Remove(key); + } + else + { + Tags[key] = value; + } + } + } +} diff --git a/test/Datadog.Trace.Tests/AgentWriterBufferTests.cs b/test/Datadog.Trace.Tests/AgentWriterBufferTests.cs new file mode 100644 index 0000000000..617ce9c5ac --- /dev/null +++ b/test/Datadog.Trace.Tests/AgentWriterBufferTests.cs @@ -0,0 +1,52 @@ +using System.Linq; +using Datadog.Trace.Agent; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class AgentWriterBufferTests + { + [Fact] + public void PushPop_1ElementIn_1ElementOut() + { + var buffer = new AgentWriterBuffer(100); + buffer.Push(42); + var vals = buffer.Pop(); + Assert.Equal(42, vals.Single()); + } + + [Fact] + public void Pop_Empty_Empty() + { + var buffer = new AgentWriterBuffer(100); + var vals = buffer.Pop(); + + Assert.False(vals.Any()); + } + + [Fact] + public void Push_MoreThanCapacity_False() + { + var buffer = new AgentWriterBuffer(100); + for (int i = 0; i < 100; i++) + { + Assert.True(buffer.Push(i)); + } + + Assert.False(buffer.Push(101)); + + // Check that one random element of the queue was replaced + var vals = buffer.Pop(); + var replaced = 0; + for (int i = 0; i < 100; i++) + { + if (vals[i] != i) + { + replaced++; + } + } + + Assert.Equal(1, replaced); + } + } +} diff --git a/test/Datadog.Trace.Tests/AgentWriterTests.cs b/test/Datadog.Trace.Tests/AgentWriterTests.cs new file mode 100644 index 0000000000..cba54d627a --- /dev/null +++ b/test/Datadog.Trace.Tests/AgentWriterTests.cs @@ -0,0 +1,52 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class AgentWriterTests + { + private readonly AgentWriter _agentWriter; + private readonly Mock _api; + private readonly SpanContext _spanContext; + + public AgentWriterTests() + { + var tracer = new Mock(); + tracer.Setup(x => x.DefaultServiceName).Returns("Default"); + + _api = new Mock(); + _agentWriter = new AgentWriter(_api.Object, statsd: null); + + var parentSpanContext = new Mock(); + var traceContext = new Mock(); + _spanContext = new SpanContext(parentSpanContext.Object, traceContext.Object, serviceName: null); + } + + [Fact] + public async Task WriteTrace_2Traces_SendToApi() + { + // TODO:bertrand it is too complicated to setup such a simple test + var trace = new[] { new Span(_spanContext, start: null) }; + _agentWriter.WriteTrace(trace); + await Task.Delay(TimeSpan.FromSeconds(2)); + _api.Verify(x => x.SendTracesAsync(It.Is(y => y.Single().Equals(trace))), Times.Once); + + trace = new[] { new Span(_spanContext, start: null) }; + _agentWriter.WriteTrace(trace); + await Task.Delay(TimeSpan.FromSeconds(2)); + _api.Verify(x => x.SendTracesAsync(It.Is(y => y.Single().Equals(trace))), Times.Once); + } + + [Fact] + public async Task FlushTwice() + { + var w = new AgentWriter(_api.Object, statsd: null); + await w.FlushAndCloseAsync(); + await w.FlushAndCloseAsync(); + } + } +} diff --git a/test/Datadog.Trace.Tests/ApiTests.cs b/test/Datadog.Trace.Tests/ApiTests.cs new file mode 100644 index 0000000000..bf36408d37 --- /dev/null +++ b/test/Datadog.Trace.Tests/ApiTests.cs @@ -0,0 +1,78 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Agent.MessagePack; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Datadog.Trace.TestHelpers.HttpMessageHandlers; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class ApiTests + { + private readonly Tracer _tracer; + + public ApiTests() + { + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + _tracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + } + + [Fact] + public async Task SendTraceAsync_200OK_AllGood() + { + var responseMock = new Mock(); + responseMock.Setup(x => x.StatusCode).Returns(200); + + var requestMock = new Mock(); + requestMock.Setup(x => x.PostAsync(It.IsAny(), It.IsAny())).ReturnsAsync(responseMock.Object); + + var factoryMock = new Mock(); + factoryMock.Setup(x => x.Create(It.IsAny())).Returns(requestMock.Object); + + var api = new Api(new Uri("http://localhost:1234"), apiRequestFactory: factoryMock.Object, statsd: null); + + var span = _tracer.StartSpan("Operation"); + var traces = new[] { new[] { span } }; + await api.SendTracesAsync(traces); + + requestMock.Verify(x => x.PostAsync(It.IsAny(), It.IsAny()), Times.Once()); + } + + [Fact] + public async Task SendTracesAsync_500_ErrorIsCaught() + { + var responseMock = new Mock(); + responseMock.Setup(x => x.StatusCode).Returns(500); + + var requestMock = new Mock(); + requestMock.Setup(x => x.PostAsync(It.IsAny(), It.IsAny())).ReturnsAsync(responseMock.Object); + + var factoryMock = new Mock(); + factoryMock.Setup(x => x.Create(It.IsAny())).Returns(requestMock.Object); + + var api = new Api(new Uri("http://localhost:1234"), apiRequestFactory: factoryMock.Object, statsd: null); + + var sw = new Stopwatch(); + sw.Start(); + var span = _tracer.StartSpan("Operation"); + var traces = new[] { new[] { span } }; + await api.SendTracesAsync(traces); + sw.Stop(); + + requestMock.Verify(x => x.PostAsync(It.IsAny(), It.IsAny()), Times.Exactly(5)); + Assert.InRange(sw.ElapsedMilliseconds, 1000, 16000); // should be ~ 3200ms + + // TODO:bertrand check that it's properly logged + } + } +} diff --git a/test/Datadog.Trace.Tests/ApiWebRequestFactoryTests.cs b/test/Datadog.Trace.Tests/ApiWebRequestFactoryTests.cs new file mode 100644 index 0000000000..dbdb2d24e2 --- /dev/null +++ b/test/Datadog.Trace.Tests/ApiWebRequestFactoryTests.cs @@ -0,0 +1,57 @@ +using System; +using System.Net; +using System.Reflection; +using Datadog.Trace.Agent; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class ApiWebRequestFactoryTests + { + /// + /// This test ensures that the ApiWebRequestFactory behaves correctly when + /// a different type of WebRequest is assigned to the http:// prefix + /// + [Fact] + public void OverrideHttpPrefix() + { + // Couldn't find a way to "officially" unregister a prefix but that shouldn't stop us + var prefixListProperty = typeof(WebRequest).GetProperty("PrefixList", BindingFlags.Static | BindingFlags.NonPublic); + var oldPrefixList = prefixListProperty.GetValue(null); + + WebRequest.RegisterPrefix("http://", new CustomWebRequestCreator()); + + // Make sure we properly hooked the WebRequest factory + Assert.IsType(WebRequest.Create("http://localhost/")); + + try + { + var factory = new ApiWebRequestFactory(); + + var request = factory.Create(new Uri("http://localhost")); + + Assert.NotNull(request); + } + finally + { + // Unregister the prefix + prefixListProperty.SetValue(null, oldPrefixList); + } + + // Make sure we properly restored the old WebRequest factory + Assert.IsType(WebRequest.Create("http://localhost/")); + } + + private class CustomWebRequestCreator : IWebRequestCreate + { + public WebRequest Create(Uri uri) + { + return new FakeWebRequest(); + } + } + + private class FakeWebRequest : WebRequest + { + } + } +} diff --git a/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs b/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs new file mode 100644 index 0000000000..210b2007be --- /dev/null +++ b/test/Datadog.Trace.Tests/Configuration/ConfigurationSourceTests.cs @@ -0,0 +1,275 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using Datadog.Trace.Configuration; +using Newtonsoft.Json; +using Xunit; + +namespace Datadog.Trace.Tests.Configuration +{ + public class ConfigurationSourceTests + { + private static readonly Dictionary TagsK1V1K2V2 = new Dictionary { { "k1", "v1" }, { "k2", "v2" } }; + private static readonly Dictionary TagsK2V2 = new Dictionary { { "k2", "v2" } }; + private static readonly Dictionary HeaderTags = new Dictionary { { "header1", "tag1" } }; + private static readonly Dictionary HeaderTagsSameTag = new Dictionary { { "header1", "tag1" }, { "header2", "tag1" } }; + + public static IEnumerable GetGlobalDefaultTestData() + { + yield return new object[] { CreateGlobalFunc(s => s.DebugEnabled), false }; + } + + public static IEnumerable GetGlobalTestData() + { + yield return new object[] { ConfigurationKeys.DebugEnabled, 1, CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, 0, CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, true, CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, false, CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "true", CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "false", CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "tRUe", CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "fALse", CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "1", CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "0", CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "yes", CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "no", CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "T", CreateGlobalFunc(s => s.DebugEnabled), true }; + yield return new object[] { ConfigurationKeys.DebugEnabled, "F", CreateGlobalFunc(s => s.DebugEnabled), false }; + + // garbage checks + yield return new object[] { ConfigurationKeys.DebugEnabled, "what_even_is_this", CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, 42, CreateGlobalFunc(s => s.DebugEnabled), false }; + yield return new object[] { ConfigurationKeys.DebugEnabled, string.Empty, CreateGlobalFunc(s => s.DebugEnabled), false }; + } + + public static IEnumerable GetDefaultTestData() + { + yield return new object[] { CreateFunc(s => s.TraceEnabled), true }; + yield return new object[] { CreateFunc(s => s.AgentUri), new Uri("http://localhost:8126/") }; + yield return new object[] { CreateFunc(s => s.Environment), null }; + yield return new object[] { CreateFunc(s => s.ServiceName), null }; + yield return new object[] { CreateFunc(s => s.DisabledIntegrationNames.Count), 0 }; + yield return new object[] { CreateFunc(s => s.LogsInjectionEnabled), false }; + yield return new object[] { CreateFunc(s => s.GlobalTags.Count), 0 }; + yield return new object[] { CreateFunc(s => s.AnalyticsEnabled), false }; + yield return new object[] { CreateFunc(s => s.CustomSamplingRules), null }; + yield return new object[] { CreateFunc(s => s.MaxTracesSubmittedPerSecond), 100 }; + yield return new object[] { CreateFunc(s => s.TracerMetricsEnabled), false }; + yield return new object[] { CreateFunc(s => s.DogStatsdPort), 8125 }; + } + + public static IEnumerable GetTestData() + { + yield return new object[] { ConfigurationKeys.TraceEnabled, "true", CreateFunc(s => s.TraceEnabled), true }; + yield return new object[] { ConfigurationKeys.TraceEnabled, "false", CreateFunc(s => s.TraceEnabled), false }; + + yield return new object[] { ConfigurationKeys.AgentHost, "test-host", CreateFunc(s => s.AgentUri), new Uri("http://test-host:8126/") }; + yield return new object[] { ConfigurationKeys.AgentPort, "9000", CreateFunc(s => s.AgentUri), new Uri("http://localhost:9000/") }; + + yield return new object[] { ConfigurationKeys.Environment, "staging", CreateFunc(s => s.Environment), "staging" }; + + yield return new object[] { ConfigurationKeys.ServiceVersion, "1.0.0", CreateFunc(s => s.ServiceVersion), "1.0.0" }; + + yield return new object[] { ConfigurationKeys.ServiceName, "web-service", CreateFunc(s => s.ServiceName), "web-service" }; + yield return new object[] { "DD_SERVICE_NAME", "web-service", CreateFunc(s => s.ServiceName), "web-service" }; + + yield return new object[] { ConfigurationKeys.DisabledIntegrations, "integration1;integration2", CreateFunc(s => s.DisabledIntegrationNames.Count), 2 }; + + yield return new object[] { ConfigurationKeys.GlobalTags, "k1:v1, k2:v2", CreateFunc(s => s.GlobalTags), TagsK1V1K2V2 }; + yield return new object[] { ConfigurationKeys.GlobalTags, "keyonly:,nocolon,:,:valueonly,k2:v2", CreateFunc(s => s.GlobalTags), TagsK2V2 }; + yield return new object[] { "DD_TRACE_GLOBAL_TAGS", "k1:v1, k2:v2", CreateFunc(s => s.GlobalTags), TagsK1V1K2V2 }; + yield return new object[] { ConfigurationKeys.GlobalTags, "k1:v1,k1:v2", CreateFunc(s => s.GlobalTags.Count), 1 }; + + yield return new object[] { ConfigurationKeys.GlobalAnalyticsEnabled, "true", CreateFunc(s => s.AnalyticsEnabled), true }; + yield return new object[] { ConfigurationKeys.GlobalAnalyticsEnabled, "false", CreateFunc(s => s.AnalyticsEnabled), false }; + + yield return new object[] { ConfigurationKeys.HeaderTags, "header1:tag1,:tagonly,headeronly:,:,nocolon", CreateFunc(s => s.HeaderTags), HeaderTags }; + yield return new object[] { ConfigurationKeys.HeaderTags, "header1:tag1,header2:tag1", CreateFunc(s => s.HeaderTags), HeaderTagsSameTag }; + yield return new object[] { ConfigurationKeys.HeaderTags, "header1:tag1,header1:tag2", CreateFunc(s => s.HeaderTags.Count), 1 }; + } + + // JsonConfigurationSource needs to be tested with JSON data, which cannot be used with the other IConfigurationSource implementations. + public static IEnumerable GetJsonTestData() + { + yield return new object[] { @"{ ""DD_TRACE_GLOBAL_TAGS"": { ""k1"":""v1"", ""k2"": ""v2""} }", CreateFunc(s => s.GlobalTags), TagsK1V1K2V2 }; + } + + public static IEnumerable GetBadJsonTestData1() + { + // Extra opening brace + yield return new object[] { @"{ ""DD_TRACE_GLOBAL_TAGS"": { { ""name1"":""value1"", ""name2"": ""value2""} }" }; + } + + public static IEnumerable GetBadJsonTestData2() + { + // Missing closing brace + yield return new object[] { @"{ ""DD_TRACE_GLOBAL_TAGS"": { ""name1"":""value1"", ""name2"": ""value2"" }" }; + } + + public static IEnumerable GetBadJsonTestData3() + { + // Json doesn't represent dictionary of string to string + yield return new object[] { @"{ ""DD_TRACE_GLOBAL_TAGS"": { ""name1"": { ""name2"": [ ""vers"" ] } } }", CreateFunc(s => s.GlobalTags.Count), 0 }; + } + + public static Func CreateFunc(Func settingGetter) + { + return settingGetter; + } + + public static Func CreateGlobalFunc(Func settingGetter) + { + return settingGetter; + } + + [Theory] + [MemberData(nameof(GetDefaultTestData))] + public void DefaultSetting(Func settingGetter, object expectedValue) + { + var settings = new TracerSettings(); + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetTestData))] + public void NameValueConfigurationSource( + string key, + string value, + Func settingGetter, + object expectedValue) + { + var collection = new NameValueCollection { { key, value } }; + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new TracerSettings(source); + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetTestData))] + public void EnvironmentConfigurationSource( + string key, + string value, + Func settingGetter, + object expectedValue) + { + // save original value so we can restore later + var originalValue = Environment.GetEnvironmentVariable(key); + + Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process); + IConfigurationSource source = new EnvironmentConfigurationSource(); + var settings = new TracerSettings(source); + + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + + // restore original value + Environment.SetEnvironmentVariable(key, originalValue, EnvironmentVariableTarget.Process); + } + + [Theory] + [MemberData(nameof(GetTestData))] + public void JsonConfigurationSource( + string key, + string value, + Func settingGetter, + object expectedValue) + { + var config = new Dictionary { [key] = value }; + string json = JsonConvert.SerializeObject(config); + IConfigurationSource source = new JsonConfigurationSource(json); + var settings = new TracerSettings(source); + + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetGlobalDefaultTestData))] + public void GlobalDefaultSetting(Func settingGetter, object expectedValue) + { + var settings = new GlobalSettings(); + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetGlobalTestData))] + public void GlobalNameValueConfigurationSource( + string key, + string value, + Func settingGetter, + object expectedValue) + { + var collection = new NameValueCollection { { key, value } }; + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new GlobalSettings(source); + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetGlobalTestData))] + public void GlobalEnvironmentConfigurationSource( + string key, + string value, + Func settingGetter, + object expectedValue) + { + // save original value so we can restore later + var originalValue = Environment.GetEnvironmentVariable(key); + Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process); + IConfigurationSource source = new EnvironmentConfigurationSource(); + var settings = new GlobalSettings(source); + object actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + Environment.SetEnvironmentVariable(key, originalValue, EnvironmentVariableTarget.Process); + } + + // Special case for dictionary-typed settings in JSON + [Theory] + [MemberData(nameof(GetJsonTestData))] + public void JsonConfigurationSourceWithJsonTypedSetting( + string value, + Func settingGetter, + object expectedValue) + { + IConfigurationSource source = new JsonConfigurationSource(value); + var settings = new TracerSettings(source); + + var actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + + [Theory] + [MemberData(nameof(GetBadJsonTestData1))] + public void JsonConfigurationSource_BadData1( + string value) + { + Assert.Throws(() => { new JsonConfigurationSource(value); }); + } + + [Theory] + [MemberData(nameof(GetBadJsonTestData2))] + public void JsonConfigurationSource_BadData2( + string value) + { + Assert.Throws(() => { new JsonConfigurationSource(value); }); + } + + [Theory] + [MemberData(nameof(GetBadJsonTestData3))] + public void JsonConfigurationSource_BadData3( + string value, + Func settingGetter, + object expectedValue) + { + IConfigurationSource source = new JsonConfigurationSource(value); + var settings = new TracerSettings(source); + + var actualValue = settingGetter(settings); + Assert.Equal(expectedValue, actualValue); + } + } +} diff --git a/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs b/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs new file mode 100644 index 0000000000..c333420ba6 --- /dev/null +++ b/test/Datadog.Trace.Tests/Configuration/IntegrationSettingsTests.cs @@ -0,0 +1,55 @@ +using System.Collections.Specialized; +using Datadog.Trace.Configuration; +using Xunit; + +namespace Datadog.Trace.Tests.Configuration +{ + public class IntegrationSettingsTests + { + [Theory] + [InlineData("DD_TRACE_FOO_ENABLED", "true", true)] + [InlineData("DD_TRACE_FOO_ENABLED", "false", false)] + [InlineData("DD_FOO_ENABLED", "true", true)] + [InlineData("DD_FOO_ENABLED", "false", false)] + public void IntegrationEnabled(string settingName, string settingValue, bool expected) + { + var source = new NameValueConfigurationSource(new NameValueCollection + { + { settingName, settingValue } + }); + + var settings = new IntegrationSettings("FOO", source); + Assert.Equal(expected, settings.Enabled); + } + + [Theory] + [InlineData("DD_TRACE_FOO_ANALYTICS_ENABLED", "true", true)] + [InlineData("DD_TRACE_FOO_ANALYTICS_ENABLED", "false", false)] + [InlineData("DD_FOO_ANALYTICS_ENABLED", "true", true)] + [InlineData("DD_FOO_ANALYTICS_ENABLED", "false", false)] + public void IntegrationAnalyticsEnabled(string settingName, string settingValue, bool expected) + { + var source = new NameValueConfigurationSource(new NameValueCollection + { + { settingName, settingValue } + }); + + var settings = new IntegrationSettings("FOO", source); + Assert.Equal(expected, settings.AnalyticsEnabled); + } + + [Theory] + [InlineData("DD_TRACE_FOO_ANALYTICS_SAMPLE_RATE", "0.2", 0.2)] + [InlineData("DD_FOO_ANALYTICS_SAMPLE_RATE", "0.6", 0.6)] + public void IntegrationAnalyticsSampleRate(string settingName, string settingValue, double expected) + { + var source = new NameValueConfigurationSource(new NameValueCollection + { + { settingName, settingValue } + }); + + var settings = new IntegrationSettings("FOO", source); + Assert.Equal(expected, settings.AnalyticsSampleRate); + } + } +} diff --git a/test/Datadog.Trace.Tests/CorrelationIdentifierTests.cs b/test/Datadog.Trace.Tests/CorrelationIdentifierTests.cs new file mode 100644 index 0000000000..e4c2372818 --- /dev/null +++ b/test/Datadog.Trace.Tests/CorrelationIdentifierTests.cs @@ -0,0 +1,102 @@ +using System; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Datadog.Trace.TestHelpers; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class CorrelationIdentifierTests + { + [Fact] + public void TraceIdSpanId_MatchActiveSpan() + { + using (var parentScope = Tracer.Instance.StartActive("parent")) + { + using (var childScope = Tracer.Instance.StartActive("child")) + { + Assert.Equal(childScope.Span.SpanId, CorrelationIdentifier.SpanId); + Assert.Equal(childScope.Span.TraceId, CorrelationIdentifier.TraceId); + } + } + } + + [Fact(Skip = "This test is not compatible with the xUnit integration. Neither TraceId or SpanId are Zero.")] + public void TraceIdSpanId_ZeroOutsideActiveSpan() + { + using (var parentScope = Tracer.Instance.StartActive("parent")) + using (var childScope = Tracer.Instance.StartActive("child")) + { + // Do nothing + } + + Assert.Equal(0, CorrelationIdentifier.SpanId); + Assert.Equal(0, CorrelationIdentifier.TraceId); + } + + [Fact] + public void ServiceIdentifiers_MatchTracerInstanceSettings() + { + const string service = "unit-test"; + const string version = "1.0.0"; + const string env = "staging"; + + var settings = new TracerSettings() + { + ServiceName = service, + ServiceVersion = version, + Environment = env + }; + var tracer = new Tracer(settings); + Tracer.Instance = tracer; + + using (var parentScope = Tracer.Instance.StartActive("parent")) + using (var childScope = Tracer.Instance.StartActive("child")) + { + Assert.Equal(service, CorrelationIdentifier.Service); + Assert.Equal(version, CorrelationIdentifier.Version); + Assert.Equal(env, CorrelationIdentifier.Env); + } + + Assert.Equal(service, CorrelationIdentifier.Service); + Assert.Equal(version, CorrelationIdentifier.Version); + Assert.Equal(env, CorrelationIdentifier.Env); + } + + [Fact] + public void VersionAndEnv_EmptyStringIfUnset() + { + var settings = new TracerSettings(); + var tracer = new Tracer(settings); + Tracer.Instance = tracer; + + using (var parentScope = Tracer.Instance.StartActive("parent")) + using (var childScope = Tracer.Instance.StartActive("child")) + { + Assert.Equal(string.Empty, CorrelationIdentifier.Version); + Assert.Equal(string.Empty, CorrelationIdentifier.Env); + } + + Assert.Equal(string.Empty, CorrelationIdentifier.Version); + Assert.Equal(string.Empty, CorrelationIdentifier.Env); + } + + [Fact] + public void Service_DefaultServiceNameIfUnset() + { + var settings = new TracerSettings(); + var tracer = new Tracer(settings); + Tracer.Instance = tracer; + + using (var parentScope = Tracer.Instance.StartActive("parent")) + using (var childScope = Tracer.Instance.StartActive("child")) + { + Assert.Equal(CorrelationIdentifier.Service, Tracer.Instance.DefaultServiceName); + } + + Assert.Equal(CorrelationIdentifier.Service, Tracer.Instance.DefaultServiceName); + } + } +} diff --git a/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj new file mode 100644 index 0000000000..2b169c126c --- /dev/null +++ b/test/Datadog.Trace.Tests/Datadog.Trace.Tests.csproj @@ -0,0 +1,26 @@ + + + + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Datadog.Trace.Tests/DistributedTraceTests.cs b/test/Datadog.Trace.Tests/DistributedTraceTests.cs new file mode 100644 index 0000000000..9e74103091 --- /dev/null +++ b/test/Datadog.Trace.Tests/DistributedTraceTests.cs @@ -0,0 +1,41 @@ +using System; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class DistributedTraceTests + { + [Fact] + public void ManuallyDistributedTrace_CarriesExpectedValues() + { + var tracer = new Tracer(); + + ulong traceId; + ulong parentSpanId; + string samplingPriorityText = null; + var expectedSamplingPriority = (int)SamplingPriority.UserKeep; + + using (var scope = tracer.StartActive("manual.trace")) + { + scope.Span.SetTag(Tags.SamplingPriority, expectedSamplingPriority.ToString()); + traceId = scope.Span.TraceId; + + using (var parentSpanOfDistributedTrace = tracer.StartActive("SortOrders")) + { + parentSpanId = scope.Span.SpanId; + samplingPriorityText = parentSpanOfDistributedTrace.Span.GetTag(Tags.SamplingPriority); + } + } + + var distributedTraceContext = new SpanContext(traceId, parentSpanId); + + using (var scope = Tracer.Instance.StartActive("manual.trace", parent: distributedTraceContext)) + { + scope.Span.SetTag(Tags.SamplingPriority, samplingPriorityText); + Assert.True(scope.Span.TraceId == traceId, "Trace ID must match the parent trace."); + var actualSamplingPriorityText = scope.Span.GetTag(Tags.SamplingPriority); + Assert.True(actualSamplingPriorityText.Equals(expectedSamplingPriority.ToString()), "Sampling priority of manual distributed trace must match the original trace."); + } + } + } +} diff --git a/test/Datadog.Trace.Tests/DogStatsDTests.cs b/test/Datadog.Trace.Tests/DogStatsDTests.cs new file mode 100644 index 0000000000..ae1de47af1 --- /dev/null +++ b/test/Datadog.Trace.Tests/DogStatsDTests.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Immutable; +using System.Threading; +using Datadog.Core.Tools; +using Datadog.Trace.Configuration; +using Datadog.Trace.DogStatsd; +using Datadog.Trace.TestHelpers; +using Datadog.Trace.Vendors.StatsdClient; +using Moq; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Trace.Tests +{ + public class DogStatsDTests + { + private readonly ITestOutputHelper _output; + + public DogStatsDTests(ITestOutputHelper output) + { + _output = output; + } + + [Fact] + public void Do_not_send_metrics_when_disabled() + { + var statsd = new Mock(); + var spans = SendSpan(tracerMetricsEnabled: false, statsd); + + Assert.True(spans.Count == 1, "Expected one span"); + + // no methods should be called on the IStatsd + statsd.VerifyNoOtherCalls(); + } + + [Fact] + public void Send_metrics_when_enabled() + { + var statsd = new Mock(); + + // Setup mock to set a bool when receiving a successful response from the agent, so we know to verify success or error. + var markOneSuccess = false; + var markOneError = false; + statsd.Setup(s => s.Add(TracerMetricNames.Api.Responses, 1, 1, "status:200")).Callback(() => markOneSuccess = true); + statsd.Setup(s => s.Add(TracerMetricNames.Api.Errors, 1, 1, null)).Callback(() => markOneError = true); + + var spans = SendSpan(tracerMetricsEnabled: true, statsd); + + Assert.True(spans.Count == 1, "Expected one span"); + + // for a single trace, these methods are called once with a value of "1" + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.EnqueuedTraces, 1, 1, null), + Times.Once()); + + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.EnqueuedSpans, 1, 1, null), + Times.Once()); + + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.DequeuedTraces, 1, 1, null), + Times.Once()); + + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.DequeuedSpans, 1, 1, null), + Times.Once()); + + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Requests, 1, 1, null), + Times.Once()); + + if (markOneSuccess) + { + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Responses, 1, 1, "status:200"), + Times.Once()); + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Errors, 1, 1, null), + Times.Never()); + } + else if (markOneError) + { + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Errors, 1, 1, null), + Times.Once()); + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Responses, 1, 1, "status:200"), + Times.Never()); + } + else + { + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Responses, 1, 1, "status:200"), + Times.Never()); + statsd.Verify( + s => s.Add(TracerMetricNames.Api.Errors, 1, 1, null), + Times.Never()); + } + + // these methods can be called multiple times with a "0" value (no more traces left) + /* + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.DequeuedTraces, 0, 1, null), + Times.AtLeastOnce); + + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.DequeuedSpans, 0, 1, null), + Times.AtLeastOnce()); + */ + + // these method can be called multiple times with a "1000" value (the max buffer size, constant) + statsd.Verify( + s => s.Add(TracerMetricNames.Queue.MaxTraces, 1000, 1, null), + Times.AtLeastOnce()); + + // these method can be called multiple times (send buffered commands) + statsd.Verify( + s => s.Send(), + Times.AtLeastOnce()); + + // these method can be called multiple times (send heartbeat) + statsd.Verify( + s => s.Add(TracerMetricNames.Health.Heartbeat, It.IsAny(), 1, null), + Times.AtLeastOnce()); + + // no other methods should be called on the IStatsd + statsd.VerifyNoOtherCalls(); + } + + private static IImmutableList SendSpan(bool tracerMetricsEnabled, Mock statsd) + { + IImmutableList spans; + var agentPort = TcpPortProvider.GetOpenPort(); + + using (var agent = new MockTracerAgent(agentPort)) + { + var settings = new TracerSettings + { + AgentUri = new Uri($"http://localhost:{agent.Port}"), + TracerMetricsEnabled = tracerMetricsEnabled + }; + + var tracer = new Tracer(settings, agentWriter: null, sampler: null, scopeManager: null, statsd.Object); + + using (var scope = tracer.StartActive("root")) + { + scope.Span.ResourceName = "resource"; + Thread.Sleep(5); + } + + spans = agent.WaitForSpans(1); + } + + return spans; + } + } +} diff --git a/test/Datadog.Trace.Tests/ExtensionMethods/SpanExtensionsTests.cs b/test/Datadog.Trace.Tests/ExtensionMethods/SpanExtensionsTests.cs new file mode 100644 index 0000000000..c91df359d0 --- /dev/null +++ b/test/Datadog.Trace.Tests/ExtensionMethods/SpanExtensionsTests.cs @@ -0,0 +1,97 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Data; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Util; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests.ExtensionMethods +{ + public class SpanExtensionsTests + { + public SpanExtensionsTests() + { + // Reset the cache + DbCommandCache.Cache = new ConcurrentDictionary[]>(); + } + + [Theory] + [InlineData("Server=myServerName,myPortNumber;Database=myDataBase;User Id=myUsername;Password=myPassword;", "myDataBase", "myUsername", "myServerName,myPortNumber")] + [InlineData(@"Server=myServerName\myInstanceName;Database=myDataBase;User Id=myUsername;Password=myPassword;", "myDataBase", "myUsername", @"myServerName\myInstanceName")] + [InlineData(@"Server=.\SQLExpress;AttachDbFilename=|DataDirectory|mydbfile.mdf;Database=dbname;Trusted_Connection=Yes;", "dbname", null, @".\SQLExpress")] + public void ExtractProperTagsFromConnectionString( + string connectionString, + string expectedDbName, + string expectedUserId, + string expectedHost) + { + var spanContext = new SpanContext(Mock.Of(), Mock.Of(), "test"); + var span = new Span(spanContext, null); + + span.AddTagsFromDbCommand(CreateDbCommand(connectionString)); + + Assert.Equal(expectedDbName, span.GetTag(Tags.DbName)); + Assert.Equal(expectedUserId, span.GetTag(Tags.DbUser)); + Assert.Equal(expectedHost, span.GetTag(Tags.OutHost)); + } + + [Fact] + public void SetSpanTypeToSql() + { + const string connectionString = "Server=myServerName;Database=myDataBase;User Id=myUsername;Password=myPassword;"; + const string commandText = "SELECT * FROM Table ORDER BY id"; + + var spanContext = new SpanContext(Mock.Of(), Mock.Of(), "test"); + var span = new Span(spanContext, null); + + span.AddTagsFromDbCommand(CreateDbCommand(connectionString, commandText)); + + Assert.Equal(SpanTypes.Sql, span.Type); + Assert.Equal(commandText, span.ResourceName); + } + + [Fact] + public void ShouldDisableCacheIfTooManyConnectionStrings() + { + const string connectionStringTemplate = "Server=myServerName{0};Database=myDataBase;User Id=myUsername;Password=myPassword;"; + + var spanContext = new SpanContext(Mock.Of(), Mock.Of(), "test"); + var span = new Span(spanContext, null); + + // Fill-up the cache and test the logic with cache enabled + for (int i = 0; i <= DbCommandCache.MaxConnectionStrings; i++) + { + var connectionString = string.Format(connectionStringTemplate, i); + + span.AddTagsFromDbCommand(CreateDbCommand(connectionString)); + + Assert.NotNull(DbCommandCache.Cache); + Assert.Equal("myServerName" + i, span.GetTag(Tags.OutHost)); + } + + // Test the logic with cache disabled + for (int i = 0; i <= 10; i++) + { + var connectionString = string.Format(connectionStringTemplate, "NoCache" + i); + + span.AddTagsFromDbCommand(CreateDbCommand(connectionString)); + + Assert.Null(DbCommandCache.Cache); + Assert.Equal("myServerName" + "NoCache" + i, span.GetTag(Tags.OutHost)); + } + } + + private static IDbCommand CreateDbCommand(string connectionString, string commandText = null) + { + var dbConnection = new Mock(); + dbConnection.SetupGet(c => c.ConnectionString).Returns(connectionString); + + var dbCommand = new Mock(); + dbCommand.SetupGet(c => c.Connection).Returns(dbConnection.Object); + dbCommand.SetupGet(c => c.CommandText).Returns(commandText); + + return dbCommand.Object; + } + } +} diff --git a/test/Datadog.Trace.Tests/ExtensionMethods/StringExtensionsTests.cs b/test/Datadog.Trace.Tests/ExtensionMethods/StringExtensionsTests.cs new file mode 100644 index 0000000000..c4269bf7f9 --- /dev/null +++ b/test/Datadog.Trace.Tests/ExtensionMethods/StringExtensionsTests.cs @@ -0,0 +1,24 @@ +using System; +using Datadog.Trace.ExtensionMethods; +using Xunit; + +namespace Datadog.Trace.Tests.ExtensionMethods +{ + public class StringExtensionsTests + { + [Theory] + [InlineData("NameSuffix", "Suffix", "Name")] + [InlineData("Name", "Suffix", "Name")] + [InlineData("Suffix", "Suffix", "")] + [InlineData("NameSuffix", "Name", "NameSuffix")] + [InlineData("Name", "", "Name")] + [InlineData("Name", null, "Name")] + [InlineData("", "Name", "")] + [InlineData("", "", "")] + public void TrimEnd(string original, string suffix, string expected) + { + string actual = original.TrimEnd(suffix, StringComparison.Ordinal); + Assert.Equal(expected, actual); + } + } +} diff --git a/test/Datadog.Trace.Tests/HeadersCollectionTests.cs b/test/Datadog.Trace.Tests/HeadersCollectionTests.cs new file mode 100644 index 0000000000..65aad7cbfb --- /dev/null +++ b/test/Datadog.Trace.Tests/HeadersCollectionTests.cs @@ -0,0 +1,187 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.Linq; +using System.Net; +using System.Net.Http; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Headers; +using Datadog.Trace.TestHelpers; +using Xunit; + +namespace Datadog.Trace.Tests +{ + // TODO: for now, these tests cover all of this, + // but we should probably split them up into actual *unit* tests for: + // - HttpHeadersCollection wrapper over HttpHeaders (Get, Set, Add, Remove) + // - NameValueHeadersCollection wrapper over NameValueCollection (Get, Set, Add, Remove) + // - SpanContextPropagator.Inject() + // - SpanContextPropagator.Extract() + public class HeadersCollectionTests + { + public static IEnumerable GetHeaderCollectionImplementations() + { + yield return new object[] { WebRequest.CreateHttp("http://localhost").Headers.Wrap() }; + yield return new object[] { new NameValueCollection().Wrap() }; + yield return new object[] { new DictionaryHeadersCollection() }; + } + + public static IEnumerable GetHeadersInvalidIdsCartesianProduct() + { + return from header in GetHeaderCollectionImplementations().SelectMany(i => i) + from invalidId in HeadersCollectionTestHelpers.GetInvalidIds().SelectMany(i => i) + select new[] { header, invalidId }; + } + + public static IEnumerable GetHeadersInvalidSamplingPrioritiesCartesianProduct() + { + return from header in GetHeaderCollectionImplementations().SelectMany(i => i) + from invalidSamplingPriority in HeadersCollectionTestHelpers.GetInvalidSamplingPriorities().SelectMany(i => i) + select new[] { header, invalidSamplingPriority }; + } + + [Theory] + [MemberData(nameof(GetHeaderCollectionImplementations))] + internal void ExtractHeaderTags_EmptyHeadersReturnsEmptyTagsList(IHeadersCollection headers) + { + var tagsFromHeader = SpanContextPropagator.Instance.ExtractHeaderTags(headers, new Dictionary()); + + Assert.NotNull(tagsFromHeader); + Assert.Empty(tagsFromHeader); + } + + [Theory] + [MemberData(nameof(GetHeaderCollectionImplementations))] + internal void ExtractHeaderTags_MatchesCaseInsensitive(IHeadersCollection headers) + { + // Initialize constants + const string customHeader1Name = "dd-custom-header1"; + const string customHeader1Value = "match1"; + const string customHeader1TagName = "custom-header1-tag"; + + const string customHeader2Name = "DD-CUSTOM-HEADER-MISMATCHING-CASE"; + const string customHeader2Value = "match2"; + const string customHeader2TagName = "custom-header2-tag"; + string customHeader2LowercaseHeaderName = customHeader2Name.ToLowerInvariant(); + + // Add headers + headers.Add(customHeader1Name, customHeader1Value); + headers.Add(customHeader2Name, customHeader2Value); + + // Initialize header-tag arguments and expectations + var headerToTagMap = new Dictionary(); + headerToTagMap.Add(customHeader1Name, customHeader1TagName); + headerToTagMap.Add(customHeader2LowercaseHeaderName, customHeader2TagName); + + var expectedResults = new Dictionary(); + expectedResults.Add(customHeader1TagName, customHeader1Value); + expectedResults.Add(customHeader2TagName, customHeader2Value); + + // Test + var tagsFromHeader = SpanContextPropagator.Instance.ExtractHeaderTags(headers, headerToTagMap); + + // Assert + Assert.NotNull(tagsFromHeader); + Assert.Equal(expectedResults, tagsFromHeader); + } + + [Theory] + [MemberData(nameof(GetHeaderCollectionImplementations))] + internal void Extract_EmptyHeadersReturnsNull(IHeadersCollection headers) + { + var resultContext = SpanContextPropagator.Instance.Extract(headers); + Assert.Null(resultContext); + } + + [Theory] + [MemberData(nameof(GetHeaderCollectionImplementations))] + internal void InjectExtract_Identity(IHeadersCollection headers) + { + const int traceId = 9; + const int spanId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + var context = new SpanContext(traceId, spanId, samplingPriority, null, origin); + SpanContextPropagator.Instance.Inject(context, headers); + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(context.SpanId, resultContext.SpanId); + Assert.Equal(context.TraceId, resultContext.TraceId); + Assert.Equal(context.SamplingPriority, resultContext.SamplingPriority); + Assert.Equal(context.Origin, resultContext.Origin); + } + + [Theory] + [MemberData(nameof(GetHeadersInvalidIdsCartesianProduct))] + internal void Extract_InvalidTraceId(IHeadersCollection headers, string traceId) + { + const string spanId = "7"; + const string samplingPriority = "2"; + const string origin = "synthetics"; + + InjectContext(headers, traceId, spanId, samplingPriority, origin); + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + // invalid traceId should return a null context even if other values are set + Assert.Null(resultContext); + } + + [Theory] + [MemberData(nameof(GetHeadersInvalidIdsCartesianProduct))] + internal void Extract_InvalidSpanId(IHeadersCollection headers, string spanId) + { + const ulong traceId = 9; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + InjectContext( + headers, + traceId.ToString(CultureInfo.InvariantCulture), + spanId, + ((int)samplingPriority).ToString(CultureInfo.InvariantCulture), + origin); + + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(traceId, resultContext.TraceId); + Assert.Equal(default(ulong), resultContext.SpanId); + Assert.Equal(samplingPriority, resultContext.SamplingPriority); + Assert.Equal(origin, resultContext.Origin); + } + + [Theory] + [MemberData(nameof(GetHeadersInvalidSamplingPrioritiesCartesianProduct))] + internal void Extract_InvalidSamplingPriority(IHeadersCollection headers, string samplingPriority) + { + const ulong traceId = 9; + const ulong spanId = 7; + const string origin = "synthetics"; + + InjectContext( + headers, + traceId.ToString(CultureInfo.InvariantCulture), + spanId.ToString(CultureInfo.InvariantCulture), + samplingPriority, + origin); + + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(traceId, resultContext.TraceId); + Assert.Equal(spanId, resultContext.SpanId); + Assert.Null(resultContext.SamplingPriority); + Assert.Equal(origin, resultContext.Origin); + } + + private static void InjectContext(IHeadersCollection headers, string traceId, string spanId, string samplingPriority, string origin) + { + headers.Add(HttpHeaderNames.TraceId, traceId); + headers.Add(HttpHeaderNames.ParentId, spanId); + headers.Add(HttpHeaderNames.SamplingPriority, samplingPriority); + headers.Add(HttpHeaderNames.Origin, origin); + } + } +} diff --git a/test/Datadog.Trace.Tests/Logging/Log4NetLogProviderTests.cs b/test/Datadog.Trace.Tests/Logging/Log4NetLogProviderTests.cs new file mode 100644 index 0000000000..2d0680f91b --- /dev/null +++ b/test/Datadog.Trace.Tests/Logging/Log4NetLogProviderTests.cs @@ -0,0 +1,191 @@ +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using Datadog.Trace.Logging; +using Datadog.Trace.Logging.LogProviders; +using log4net.Appender; +using log4net.Config; +using log4net.Core; +using log4net.Layout; +using Newtonsoft.Json; +using Xunit; + +namespace Datadog.Trace.Tests.Logging +{ + [Collection(nameof(Datadog.Trace.Tests.Logging))] + public class Log4NetLogProviderTests + { + private const string Log4NetExpectedStringFormat = "\"{0}\":\"{1}\""; + private readonly ILogProvider _logProvider; + private readonly ILog _logger; + private readonly MemoryAppender _memoryAppender; + + public Log4NetLogProviderTests() + { + _memoryAppender = new MemoryAppender(); + var repository = log4net.LogManager.GetRepository(Assembly.GetAssembly(typeof(log4net.LogManager))); + BasicConfigurator.Configure(repository, _memoryAppender); + + _logProvider = new Log4NetLogProvider(); + LogProvider.SetCurrentLogProvider(_logProvider); + _logger = new LoggerExecutionWrapper(_logProvider.GetLogger("Test")); + } + + [Fact] + public void LogsInjectionEnabledAddsParentCorrelationIdentifiers() + { + // Assert that the Log4Net log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInParentSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_memoryAppender.GetEvents()); + filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, parentScope)); + } + + [Fact] + public void LogsInjectionEnabledAddsChildCorrelationIdentifiers() + { + // Assert that the Log4Net log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInChildSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_memoryAppender.GetEvents()); + filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, childScope)); + } + + [Fact] + public void LogsInjectionEnabledDoesNotAddCorrelationIdentifiersOutsideSpans() + { + // Assert that the Log4Net log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogOutsideSpans(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_memoryAppender.GetEvents()); + filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + [Fact] + public void LogsInjectionEnabledUsesTracerServiceName() + { + // Assert that the Log4Net log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInSpanWithServiceName(tracer, _logger, _logProvider.OpenMappedContext, "custom-service", out var scope); + + // Filter the logs + List filteredLogs = new List(_memoryAppender.GetEvents()); + filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, scope)); + } + + [Fact] + public void DisabledLibLogSubscriberDoesNotAddCorrelationIdentifiers() + { + // Assert that the Log4Net log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: false); + LoggingProviderTestHelpers.LogEverywhere(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_memoryAppender.GetEvents()); + filteredLogs.RemoveAll(log => !log.MessageObject.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + internal static void LogEventContains(log4net.Core.LoggingEvent logEvent, string service, string version, string env, Scope scope) + { + LogEventContains(logEvent, service, version, env, scope.Span.TraceId, scope.Span.SpanId); + } + + internal static void LogEventContains(log4net.Core.LoggingEvent logEvent, string service, string version, string env, ulong traceId, ulong spanId) + { + Assert.Contains(CorrelationIdentifier.ServiceKey, logEvent.Properties.GetKeys()); + Assert.Equal(service, logEvent.Properties[CorrelationIdentifier.ServiceKey].ToString()); + + Assert.Contains(CorrelationIdentifier.VersionKey, logEvent.Properties.GetKeys()); + Assert.Equal(version, logEvent.Properties[CorrelationIdentifier.VersionKey].ToString()); + + Assert.Contains(CorrelationIdentifier.EnvKey, logEvent.Properties.GetKeys()); + Assert.Equal(env, logEvent.Properties[CorrelationIdentifier.EnvKey].ToString()); + + Assert.Contains(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys()); + Assert.Equal(traceId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.TraceIdKey].ToString())); + + Assert.Contains(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys()); + Assert.Equal(spanId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.SpanIdKey].ToString())); + } + + internal static void LogEventContains(log4net.Core.LoggingEvent logEvent, ulong traceId, ulong spanId) + { + Assert.Contains(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys()); + Assert.Equal(traceId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.TraceIdKey].ToString())); + + Assert.Contains(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys()); + Assert.Equal(spanId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.SpanIdKey].ToString())); + } + + internal static void LogEventDoesNotContainCorrelationIdentifiers(log4net.Core.LoggingEvent logEvent) + { + if (logEvent.Properties.Contains(CorrelationIdentifier.SpanIdKey) && + logEvent.Properties.Contains(CorrelationIdentifier.TraceIdKey)) + { + LogEventContains(logEvent, traceId: 0, spanId: 0); + } + else + { + Assert.DoesNotContain(CorrelationIdentifier.SpanIdKey, logEvent.Properties.GetKeys()); + Assert.DoesNotContain(CorrelationIdentifier.TraceIdKey, logEvent.Properties.GetKeys()); + } + } + + /// + /// Lightweight JSON-formatter for Log4Net inspired by https://github.com/Litee/log4net.Layout.Json + /// + internal class Log4NetJsonLayout : LayoutSkeleton + { + public override void ActivateOptions() + { + } + + public override void Format(TextWriter writer, LoggingEvent e) + { + var dic = new Dictionary + { + ["level"] = e.Level.DisplayName, + ["messageObject"] = e.MessageObject, + ["renderedMessage"] = e.RenderedMessage, + ["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"), + ["logger"] = e.LoggerName, + ["thread"] = e.ThreadName, + ["exceptionObject"] = e.ExceptionObject, + ["exceptionObjectString"] = e.ExceptionObject == null ? null : e.GetExceptionString(), + ["userName"] = e.UserName, + ["domain"] = e.Domain, + ["identity"] = e.Identity, + ["location"] = e.LocationInformation.FullInfo, + ["properties"] = e.GetProperties() + }; + writer.Write(JsonConvert.SerializeObject(dic)); + } + } + } +} diff --git a/test/Datadog.Trace.Tests/Logging/LoggingProviderTestHelpers.cs b/test/Datadog.Trace.Tests/Logging/LoggingProviderTestHelpers.cs new file mode 100644 index 0000000000..472ff279b7 --- /dev/null +++ b/test/Datadog.Trace.Tests/Logging/LoggingProviderTestHelpers.cs @@ -0,0 +1,117 @@ +using System; +using System.Globalization; +using System.IO; +using System.Text; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Logging; +using Datadog.Trace.Sampling; +using Moq; +using Serilog.Formatting.Display; +using Xunit; + +namespace Datadog.Trace.Tests.Logging +{ + internal static class LoggingProviderTestHelpers + { + internal static readonly string CustomPropertyName = "custom"; + internal static readonly int CustomPropertyValue = 1; + internal static readonly string LogPrefix = "[Datadog.Trace.Tests.Logging]"; + + internal static Tracer InitializeTracer(bool enableLogsInjection) + { + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + settings.LogsInjectionEnabled = enableLogsInjection; + settings.ServiceVersion = "custom-version"; + settings.Environment = "custom-env"; + + return new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + } + + internal static void LogInSpanWithServiceName(Tracer tracer, ILog logger, Func openMappedContext, string service, out Scope scope) + { + using (scope = tracer.StartActive("span", serviceName: service)) + { + using (var mappedContext = openMappedContext(CustomPropertyName, CustomPropertyValue, false)) + { + logger.Log(LogLevel.Info, () => $"{LogPrefix}Entered single scope with a different service name."); + } + } + } + + internal static void LogInParentSpan(Tracer tracer, ILog logger, Func openMappedContext, out Scope parentScope, out Scope childScope) + { + using (parentScope = tracer.StartActive("parent")) + { + using (var mappedContext = openMappedContext(CustomPropertyName, CustomPropertyValue, false)) + { + logger.Log(LogLevel.Info, () => $"Started and activated parent scope."); + + using (childScope = tracer.StartActive("child")) + { + // Empty + } + + logger.Log(LogLevel.Info, () => $"{LogPrefix}Closed child scope and reactivated parent scope."); + } + } + } + + internal static void LogInChildSpan(Tracer tracer, ILog logger, Func openMappedContext, out Scope parentScope, out Scope childScope) + { + using (parentScope = tracer.StartActive("parent")) + { + using (var mappedContext = openMappedContext(CustomPropertyName, CustomPropertyValue, false)) + { + using (childScope = tracer.StartActive("child")) + { + logger.Log(LogLevel.Info, () => $"{LogPrefix}Started and activated child scope."); + } + } + } + } + + internal static void LogOutsideSpans(Tracer tracer, ILog logger, Func openMappedContext, out Scope parentScope, out Scope childScope) + { + logger.Log(LogLevel.Info, () => $"{LogPrefix}Logged before starting/activating a scope"); + + using (parentScope = tracer.StartActive("parent")) + { + using (var mappedContext = openMappedContext(CustomPropertyName, CustomPropertyValue, false)) + { + using (childScope = tracer.StartActive("child")) + { + // Empty + } + } + } + + logger.Log(LogLevel.Info, () => $"{LogPrefix}Closed child scope so there is no active scope."); + } + + internal static void LogEverywhere(Tracer tracer, ILog logger, Func openMappedContext, out Scope parentScope, out Scope childScope) + { + logger.Log(LogLevel.Info, () => $"{LogPrefix}Logged before starting/activating a scope"); + + using (parentScope = tracer.StartActive("parent")) + { + logger.Log(LogLevel.Info, () => $"Started and activated parent scope."); + + using (var mappedContext = openMappedContext(CustomPropertyName, CustomPropertyValue, false)) + { + using (childScope = tracer.StartActive("child")) + { + logger.Log(LogLevel.Info, () => $"{LogPrefix}Started and activated child scope."); + } + } + + logger.Log(LogLevel.Info, () => $"{LogPrefix}Closed child scope and reactivated parent scope."); + } + + logger.Log(LogLevel.Info, () => $"{LogPrefix}Closed child scope so there is no active scope."); + } + } +} diff --git a/test/Datadog.Trace.Tests/Logging/NLogLogProviderTests.cs b/test/Datadog.Trace.Tests/Logging/NLogLogProviderTests.cs new file mode 100644 index 0000000000..99d0a67e89 --- /dev/null +++ b/test/Datadog.Trace.Tests/Logging/NLogLogProviderTests.cs @@ -0,0 +1,145 @@ +using System.Collections.Generic; +using Datadog.Trace.Logging; +using Datadog.Trace.Logging.LogProviders; +using NLog; +using NLog.Config; +using NLog.Layouts; +using NLog.Targets; +using Xunit; + +namespace Datadog.Trace.Tests.Logging +{ + [Collection(nameof(Datadog.Trace.Tests.Logging))] + [TestCaseOrderer("Datadog.Trace.TestHelpers.AlphabeticalOrderer", "Datadog.Trace.TestHelpers")] + public class NLogLogProviderTests + { + private const string NLogExpectedStringFormat = "\"{0}\": \"{1}\""; + + private readonly ILogProvider _logProvider; + private readonly ILog _logger; + private readonly MemoryTarget _target; + + public NLogLogProviderTests() + { + var config = new LoggingConfiguration(); + var layout = new JsonLayout(); + layout.IncludeMdc = true; + layout.Attributes.Add(new JsonAttribute("time", Layout.FromString("${longdate}"))); + layout.Attributes.Add(new JsonAttribute("level", Layout.FromString("${level:uppercase=true}"))); + layout.Attributes.Add(new JsonAttribute("message", Layout.FromString("${message}"))); + _target = new MemoryTarget + { + Layout = layout + }; + + config.AddTarget("memory", _target); + config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Trace, _target)); + LogManager.Configuration = config; + SimpleConfigurator.ConfigureForTargetLogging(_target, NLog.LogLevel.Trace); + + _logProvider = new NLogLogProvider(); + LogProvider.SetCurrentLogProvider(_logProvider); + _logger = new LoggerExecutionWrapper(_logProvider.GetLogger("test")); + } + + [Fact] + public void LogsInjectionEnabledAddsParentCorrelationIdentifiers() + { + // Assert that the NLog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInParentSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_target.Logs); + filteredLogs.RemoveAll(log => !log.Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, parentScope)); + } + + [Fact] + public void LogsInjectionEnabledAddsChildCorrelationIdentifiers() + { + // Assert that the NLog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInChildSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_target.Logs); + filteredLogs.RemoveAll(log => !log.Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, childScope)); + } + + [Fact] + public void LogsInjectionEnabledDoesNotAddCorrelationIdentifiersOutsideSpans() + { + // Assert that the NLog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogOutsideSpans(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_target.Logs); + filteredLogs.RemoveAll(log => !log.Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + [Fact] + public void LogsInjectionEnabledUsesTracerServiceName() + { + // Assert that the NLog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInSpanWithServiceName(tracer, _logger, _logProvider.OpenMappedContext, "custom-service", out var scope); + + // Filter the logs + List filteredLogs = new List(_target.Logs); + filteredLogs.RemoveAll(log => !log.Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, scope)); + } + + [Fact] + public void DisabledLibLogSubscriberDoesNotAddCorrelationIdentifiers() + { + // Assert that the NLog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: false); + LoggingProviderTestHelpers.LogEverywhere(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + List filteredLogs = new List(_target.Logs); + filteredLogs.RemoveAll(log => !log.Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(filteredLogs, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + internal static void LogEventContains(string nLogString, string service, string version, string env, Scope scope) + { + Assert.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.ServiceKey, service), nLogString); + Assert.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.EnvKey, env), nLogString); + Assert.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.VersionKey, version), nLogString); + Assert.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.SpanIdKey, scope.Span.SpanId), nLogString); + Assert.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.TraceIdKey, scope.Span.TraceId), nLogString); + } + + internal static void LogEventDoesNotContainCorrelationIdentifiers(string nLogString) + { + // Do not assert on the service property + Assert.True( + nLogString.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.SpanIdKey, 0)) || + !nLogString.Contains($"\"{CorrelationIdentifier.SpanIdKey}\"")); + Assert.True( + nLogString.Contains(string.Format(NLogExpectedStringFormat, CorrelationIdentifier.TraceIdKey, 0)) || + !nLogString.Contains($"\"{CorrelationIdentifier.TraceIdKey}\"")); + } + } +} diff --git a/test/Datadog.Trace.Tests/Logging/SerilogLogProviderTests.cs b/test/Datadog.Trace.Tests/Logging/SerilogLogProviderTests.cs new file mode 100644 index 0000000000..527f336526 --- /dev/null +++ b/test/Datadog.Trace.Tests/Logging/SerilogLogProviderTests.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Logging; +using Datadog.Trace.Logging.LogProviders; +using Serilog; +using Serilog.Events; +using Xunit; + +namespace Datadog.Trace.Tests.Logging +{ + [Collection(nameof(Datadog.Trace.Tests.Logging))] + public class SerilogLogProviderTests + { + private readonly ILogProvider _logProvider; + private readonly ILog _logger; + private readonly List _logEvents; + + public SerilogLogProviderTests() + { + Serilog.Log.Logger = new LoggerConfiguration() + .Enrich.FromLogContext() + .WriteTo.Observers(obs => obs.Subscribe(logEvent => _logEvents.Add(logEvent))) + .CreateLogger(); + _logEvents = new List(); + + _logProvider = new SerilogLogProvider(); + LogProvider.SetCurrentLogProvider(_logProvider); + _logger = new LoggerExecutionWrapper(_logProvider.GetLogger("Test")); + } + + [Fact] + public void LogsInjectionEnabledAddsParentCorrelationIdentifiers() + { + // Assert that the Serilog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInParentSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + _logEvents.RemoveAll(log => !log.MessageTemplate.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(_logEvents, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, parentScope)); + } + + [Fact] + public void LogsInjectionEnabledAddsChildCorrelationIdentifiers() + { + // Assert that the Serilog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInChildSpan(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + _logEvents.RemoveAll(log => !log.MessageTemplate.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(_logEvents, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, childScope)); + } + + [Fact] + public void LogsInjectionEnabledDoesNotAddCorrelationIdentifiersOutsideSpans() + { + // Assert that the Serilog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogOutsideSpans(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + _logEvents.RemoveAll(log => !log.MessageTemplate.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(_logEvents, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + [Fact] + public void LogsInjectionEnabledUsesTracerServiceName() + { + // Assert that the Serilog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: true); + LoggingProviderTestHelpers.LogInSpanWithServiceName(tracer, _logger, _logProvider.OpenMappedContext, "custom-service", out var scope); + + // Filter the logs + _logEvents.RemoveAll(log => !log.MessageTemplate.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(_logEvents, e => LogEventContains(e, tracer.DefaultServiceName, tracer.Settings.ServiceVersion, tracer.Settings.Environment, scope)); + } + + [Fact] + public void DisabledLibLogSubscriberDoesNotAddCorrelationIdentifiers() + { + // Assert that the Serilog log provider is correctly being used + Assert.IsType(LogProvider.CurrentLogProvider); + + // Instantiate a tracer for this test with default settings and set LogsInjectionEnabled to TRUE + var tracer = LoggingProviderTestHelpers.InitializeTracer(enableLogsInjection: false); + LoggingProviderTestHelpers.LogEverywhere(tracer, _logger, _logProvider.OpenMappedContext, out var parentScope, out var childScope); + + // Filter the logs + _logEvents.RemoveAll(log => !log.MessageTemplate.ToString().Contains(LoggingProviderTestHelpers.LogPrefix)); + Assert.All(_logEvents, e => LogEventDoesNotContainCorrelationIdentifiers(e)); + } + + internal static void LogEventContains(Serilog.Events.LogEvent logEvent, string service, string version, string env, Scope scope) + { + Contains(logEvent, service, version, env, scope.Span.TraceId, scope.Span.SpanId); + } + + internal static void Contains(Serilog.Events.LogEvent logEvent, string service, string version, string env, ulong traceId, ulong spanId) + { + Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.ServiceKey)); + Assert.Equal(service, logEvent.Properties[CorrelationIdentifier.ServiceKey].ToString().Trim(new[] { '\"' }), ignoreCase: true); + + Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.VersionKey)); + Assert.Equal(version, logEvent.Properties[CorrelationIdentifier.VersionKey].ToString().Trim(new[] { '\"' }), ignoreCase: true); + + Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.EnvKey)); + Assert.Equal(env, logEvent.Properties[CorrelationIdentifier.EnvKey].ToString().Trim(new[] { '\"' }), ignoreCase: true); + + Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.TraceIdKey)); + Assert.Equal(traceId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.TraceIdKey].ToString().Trim(new[] { '\"' }))); + + Assert.True(logEvent.Properties.ContainsKey(CorrelationIdentifier.SpanIdKey)); + Assert.Equal(spanId, ulong.Parse(logEvent.Properties[CorrelationIdentifier.SpanIdKey].ToString().Trim(new[] { '\"' }))); + } + + internal static void LogEventDoesNotContainCorrelationIdentifiers(Serilog.Events.LogEvent logEvent) + { + // Do not assert on the version property + // Do not assert on the service property + Assert.False(logEvent.Properties.ContainsKey(CorrelationIdentifier.SpanIdKey)); + Assert.False(logEvent.Properties.ContainsKey(CorrelationIdentifier.TraceIdKey)); + } + } +} diff --git a/test/Datadog.Trace.Tests/PlatformHelpers/AzureAppServicesMetadataTests.cs b/test/Datadog.Trace.Tests/PlatformHelpers/AzureAppServicesMetadataTests.cs new file mode 100644 index 0000000000..7c1bb105ed --- /dev/null +++ b/test/Datadog.Trace.Tests/PlatformHelpers/AzureAppServicesMetadataTests.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using Datadog.Trace.PlatformHelpers; +using Xunit; + +namespace Datadog.Trace.Tests.PlatformHelpers +{ + public class AzureAppServicesMetadataTests + { + private static readonly List EnvVars = new List() + { + AzureAppServices.AzureAppServicesContextKey, + AzureAppServices.WebsiteOwnerNameKey, + AzureAppServices.ResourceGroupKey, + AzureAppServices.SiteNameKey + }; + + private static readonly string SubscriptionId = "8c500027-5f00-400e-8f00-60000000000f"; + private static readonly string PlanResourceGroup = "apm-dotnet"; + private static readonly string DeploymentId = "AzureExampleSiteName"; + private static readonly string SiteResourceGroup = "apm-dotnet-site-resource-group"; + private static readonly string ExpectedResourceId = + $"/subscriptions/{SubscriptionId}/resourcegroups/{SiteResourceGroup}/providers/microsoft.web/sites/{DeploymentId}".ToLowerInvariant(); + + [Fact] + public void ResourceId_Created_WhenAllRequirementsExist() + { + var vars = GetMockVariables(SubscriptionId, DeploymentId, PlanResourceGroup, SiteResourceGroup); + var metadata = new AzureAppServices(vars); + var resourceId = metadata.ResourceId; + Assert.Equal(expected: ExpectedResourceId, actual: resourceId); + } + + [Fact] + public void IsRelevant_True_WhenVariableSetTrue() + { + var vars = GetMockVariables(null, null, null, null); + var metadata = new AzureAppServices(vars); + Assert.True(metadata.IsRelevant); + } + + [Fact] + public void IsRelevant_False_WhenVariableDoesNotExist() + { + var vars = GetMockVariables(null, null, null, null); + vars.Remove(AzureAppServices.AzureAppServicesContextKey); + var metadata = new AzureAppServices(vars); + Assert.False(metadata.IsRelevant); + } + + [Theory] + [InlineData(null, "deploymentId", "siteResourceGroup")] + [InlineData("123", null, "siteResourceGroup")] + [InlineData("123", "deploymentId", null)] + [InlineData(null, null, "siteResourceGroup")] + [InlineData(null, "deploymentId", null)] + [InlineData("123", null, null)] + [InlineData(null, null, null)] + public void ResourceId_IsNull_WhenAnyRequirementsMissing(string subscriptionId, string deploymentId, string siteResourceGroup) + { + // plan resource group actually doesn't matter for the resource id we build + var vars = GetMockVariables(subscriptionId, deploymentId, "some-resource-group", siteResourceGroup); + var metadata = new AzureAppServices(vars); + Assert.Null(metadata.ResourceId); + } + + [Fact] + public void PopulatesOnlyRootSpans() + { + var vars = GetMockVariables(SubscriptionId, DeploymentId, PlanResourceGroup, SiteResourceGroup); + AzureAppServices.Metadata = new AzureAppServices(vars); + var tracer = new Tracer(); + var rootSpans = new List(); + var nonRootSpans = new List(); + var iterations = 5; + var remaining = iterations; + + while (remaining-- > 0) + { + using (var rootScope = tracer.StartActive("root")) + { + rootSpans.Add(rootScope.Span); + + using (var nestedScope = tracer.StartActive("nest-a")) + { + nonRootSpans.Add(nestedScope.Span); + } + + using (var nestedScope = tracer.StartActive("nest-b")) + { + nonRootSpans.Add(nestedScope.Span); + + using (var doublyNestedScope = tracer.StartActive("nest-b-1")) + { + nonRootSpans.Add(doublyNestedScope.Span); + } + } + } + } + + Assert.Equal(expected: iterations, actual: rootSpans.Count); + Assert.NotEmpty(nonRootSpans); + + var rootSpansMissingExpectedTag = + rootSpans.Where(s => s.GetTag(Tags.AzureAppServicesResourceId) != ExpectedResourceId).ToList(); + + var nonRootSpansWithTag = + nonRootSpans.Where(s => s.GetTag(Tags.AzureAppServicesResourceId) == ExpectedResourceId); + + var newLine = Environment.NewLine; + var detailedMessage = + string.Join( + Environment.NewLine, + rootSpansMissingExpectedTag.Select( + r => $"Expected {ExpectedResourceId} {newLine}but received {r.GetTag(Tags.AzureAppServicesResourceId) ?? "NULL"} {newLine}{newLine}({r}) {newLine}")); + + var envVarValues = string.Join(", ", EnvVars.Select(e => $"{e}: {Environment.GetEnvironmentVariable(e)}")); + + Assert.True(!rootSpansMissingExpectedTag.Any(), $"All root spans should have the resource id: {newLine}{envVarValues}{newLine}{detailedMessage}"); + Assert.True(!nonRootSpansWithTag.Any(), "No non root spans should have the resource id."); + } + + private IDictionary GetMockVariables(string subscriptionId, string deploymentId, string planResourceGroup, string siteResourceGroup) + { + var vars = Environment.GetEnvironmentVariables(); + vars.Add(AzureAppServices.AzureAppServicesContextKey, "1"); + vars.Add(AzureAppServices.WebsiteOwnerNameKey, $"{subscriptionId}+{planResourceGroup}-EastUSwebspace"); + vars.Add(AzureAppServices.ResourceGroupKey, siteResourceGroup); + vars.Add(AzureAppServices.SiteNameKey, deploymentId); + return vars; + } + } +} diff --git a/test/Datadog.Trace.Tests/PlatformHelpers/ContainerMetadataTests.cs b/test/Datadog.Trace.Tests/PlatformHelpers/ContainerMetadataTests.cs new file mode 100644 index 0000000000..e06308cb15 --- /dev/null +++ b/test/Datadog.Trace.Tests/PlatformHelpers/ContainerMetadataTests.cs @@ -0,0 +1,115 @@ +using System.Collections.Generic; +using System.IO; +using Datadog.Trace.PlatformHelpers; +using Xunit; + +namespace Datadog.Trace.Tests.PlatformHelpers +{ + public class ContainerMetadataTests + { + public const string Docker = @" +13:name=systemd:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +12:pids:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +11:hugetlb:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +10:net_prio:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +9:perf_event:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +8:net_cls:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +7:freezer:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +6:devices:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +5:memory:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +4:blkio:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +3:cpuacct:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +2:cpu:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860 +1:cpuset:/docker/3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860"; + + public const string Kubernetes = @" +11:perf_event:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +10:pids:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +9:memory:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +8:cpu,cpuacct:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +7:blkio:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +6:cpuset:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +5:devices:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +4:freezer:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +3:net_cls,net_prio:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +2:hugetlb:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +1:name=systemd:/kubepods/besteffort/pod3d274242-8ee0-11e9-a8a6-1e68d864ef1a/3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1 +"; + + public const string Ecs = @" +9:perf_event:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +8:memory:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +7:hugetlb:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +6:freezer:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +5:devices:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +4:cpuset:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +3:cpuacct:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +2:cpu:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +1:blkio:/ecs/haissam-ecs-classic/5a0d5ceddf6c44c1928d367a815d890f/38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce +"; + + public const string Fargate = @" +11:hugetlb:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +10:pids:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +9:cpuset:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +8:net_cls,net_prio:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +7:cpu,cpuacct:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +6:perf_event:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +5:freezer:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +4:devices:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +3:blkio:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +2:memory:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +1:name=systemd:/ecs/55091c13-b8cf-4801-b527-f4601742204d/432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da +"; + + public static IEnumerable GetCgroupFiles() + { + yield return new object[] { Docker, "3726184226f5d3147c25fdeab5b60097e378e8a720503a5e19ecfdf29f869860" }; + yield return new object[] { Kubernetes, "3e74d3fd9db4c9dd921ae05c2502fb984d0cde1b36e581b13f79c639da4518a1" }; + yield return new object[] { Ecs, "38fac3e99302b3622be089dd41e7ccf38aff368a86cc339972075136ee2710ce" }; + yield return new object[] { Fargate, "432624d2150b349fe35ba397284dea788c2bf66b885d14dfc1569b01890ca7da" }; + } + + /// + /// Splits multi-line string into individual strings, one string per line. + /// + /// The multi-line string. + /// An enumerable that returns each line from when iterated. + public static IEnumerable SplitLines(string contents) + { + if (contents == null) + { + yield break; + } + + using (var reader = new StringReader(contents)) + { + while (true) + { + string line = reader.ReadLine(); + + if (line == null) + { + yield break; + } + + yield return line; + } + } + } + + [Theory] + [MemberData(nameof(GetCgroupFiles))] + public void Parse_ContainerId_From_Cgroup_File(string file, string expected) + { + // arrange + var lines = SplitLines(file); + + // act + string actual = ContainerMetadata.ParseCgroupLines(lines); + + // assert + Assert.Equal(expected, actual); + } + } +} diff --git a/test/Datadog.Trace.Tests/Sampling/CustomSamplingRuleTests.cs b/test/Datadog.Trace.Tests/Sampling/CustomSamplingRuleTests.cs new file mode 100644 index 0000000000..a3bf68f62c --- /dev/null +++ b/test/Datadog.Trace.Tests/Sampling/CustomSamplingRuleTests.cs @@ -0,0 +1,124 @@ +using System; +using System.IO; +using System.Linq; +using Datadog.Trace.Sampling; +using Xunit; + +namespace Datadog.Trace.Tests.Sampling +{ + [Collection(nameof(Datadog.Trace.Tests.Sampling))] + public class CustomSamplingRuleTests + { + private static readonly ulong Id = 1; + private static readonly Span CartCheckoutSpan = new Span(new SpanContext(Id++, Id++, null, serviceName: "shopping-cart-service"), DateTimeOffset.Now) { OperationName = "checkout" }; + private static readonly Span AddToCartSpan = new Span(new SpanContext(Id++, Id++, null, serviceName: "shopping-cart-service"), DateTimeOffset.Now) { OperationName = "cart-add" }; + private static readonly Span ShippingAuthSpan = new Span(new SpanContext(Id++, Id++, null, serviceName: "shipping-auth-service"), DateTimeOffset.Now) { OperationName = "authorize" }; + private static readonly Span ShippingRevertSpan = new Span(new SpanContext(Id++, Id++, null, serviceName: "shipping-auth-service"), DateTimeOffset.Now) { OperationName = "authorize-revert" }; + private static readonly Span RequestShippingSpan = new Span(new SpanContext(Id++, Id++, null, serviceName: "request-shipping"), DateTimeOffset.Now) { OperationName = "submit" }; + + [Fact] + public void Constructs_ZeroRateOnly_From_Config_String() + { + var config = "[{\"sample_rate\":0}]"; + VerifyRate(config, 0f); + VerifySingleRule(config, CartCheckoutSpan, true); + VerifySingleRule(config, AddToCartSpan, true); + VerifySingleRule(config, ShippingAuthSpan, true); + VerifySingleRule(config, ShippingRevertSpan, true); + VerifySingleRule(config, RequestShippingSpan, true); + } + + [Fact] + public void Constructs_CartOnlyRule_From_Config_String() + { + var config = "[{\"sample_rate\":0.3, \"service\":\"shopping-cart.*\"}]"; + VerifyRate(config, 0.3f); + VerifySingleRule(config, CartCheckoutSpan, true); + VerifySingleRule(config, AddToCartSpan, true); + VerifySingleRule(config, ShippingAuthSpan, false); + VerifySingleRule(config, ShippingRevertSpan, false); + VerifySingleRule(config, RequestShippingSpan, false); + } + + [Fact] + public void Constructs_AuthOperationRule_From_Config_String() + { + var config = "[{\"sample_rate\":0.5, \"name\":\"auth.*\"}]"; + VerifyRate(config, 0.5f); + VerifySingleRule(config, CartCheckoutSpan, false); + VerifySingleRule(config, AddToCartSpan, false); + VerifySingleRule(config, ShippingAuthSpan, true); + VerifySingleRule(config, ShippingRevertSpan, true); + VerifySingleRule(config, RequestShippingSpan, false); + } + + [Fact] + public void Constructs_All_Expected_From_Config_String() + { + var config = "[{\"sample_rate\":0.5, \"service\":\".*cart.*\"}, {\"sample_rate\":1, \"service\":\".*shipping.*\", \"name\":\"authorize\"}, {\"sample_rate\":0.1, \"service\":\".*shipping.*\"}, {\"sample_rate\":0.05}]"; + var rules = CustomSamplingRule.BuildFromConfigurationString(config).ToArray(); + + var cartRule = rules[0]; + Assert.Equal(expected: 0.5f, actual: cartRule.GetSamplingRate(CartCheckoutSpan)); + + VerifySingleRule(cartRule, CartCheckoutSpan, true); + VerifySingleRule(cartRule, AddToCartSpan, true); + VerifySingleRule(cartRule, ShippingAuthSpan, false); + VerifySingleRule(cartRule, ShippingRevertSpan, false); + VerifySingleRule(cartRule, RequestShippingSpan, false); + + var shippingAuthRule = rules[1]; + Assert.Equal(expected: 1f, actual: shippingAuthRule.GetSamplingRate(CartCheckoutSpan)); + + VerifySingleRule(shippingAuthRule, CartCheckoutSpan, false); + VerifySingleRule(shippingAuthRule, AddToCartSpan, false); + VerifySingleRule(shippingAuthRule, ShippingAuthSpan, true); + VerifySingleRule(shippingAuthRule, ShippingRevertSpan, false); + VerifySingleRule(shippingAuthRule, RequestShippingSpan, false); + + var fallbackShippingRule = rules[2]; + Assert.Equal(expected: 0.1f, actual: fallbackShippingRule.GetSamplingRate(CartCheckoutSpan)); + + VerifySingleRule(fallbackShippingRule, CartCheckoutSpan, false); + VerifySingleRule(fallbackShippingRule, AddToCartSpan, false); + VerifySingleRule(fallbackShippingRule, ShippingAuthSpan, true); + VerifySingleRule(fallbackShippingRule, ShippingRevertSpan, true); + VerifySingleRule(fallbackShippingRule, RequestShippingSpan, true); + + var fallbackRule = rules[3]; + Assert.Equal(expected: 0.05f, actual: fallbackRule.GetSamplingRate(CartCheckoutSpan)); + + VerifySingleRule(fallbackRule, CartCheckoutSpan, true); + VerifySingleRule(fallbackRule, AddToCartSpan, true); + VerifySingleRule(fallbackRule, ShippingAuthSpan, true); + VerifySingleRule(fallbackRule, ShippingRevertSpan, true); + VerifySingleRule(fallbackRule, RequestShippingSpan, true); + } + + [Theory] + [InlineData("\"rate:0.5, \"name\":\"auth.*\"}]")] + [InlineData("[{\"name\":\"wat\"}]")] + public void Malformed_Rules_Do_Not_Register_Or_Crash(string ruleConfig) + { + var rules = CustomSamplingRule.BuildFromConfigurationString(ruleConfig).ToArray(); + Assert.Empty(rules); + } + + private void VerifyRate(string config, float expectedRate) + { + var rule = CustomSamplingRule.BuildFromConfigurationString(config).Single(); + Assert.Equal(expected: expectedRate, actual: rule.GetSamplingRate(CartCheckoutSpan)); + } + + private void VerifySingleRule(string config, Span span, bool isMatch) + { + var rule = CustomSamplingRule.BuildFromConfigurationString(config).Single(); + VerifySingleRule(rule, span, isMatch); + } + + private void VerifySingleRule(ISamplingRule rule, Span span, bool isMatch) + { + Assert.Equal(rule.IsMatch(span), isMatch); + } + } +} diff --git a/test/Datadog.Trace.Tests/Sampling/RateLimiterTests.cs b/test/Datadog.Trace.Tests/Sampling/RateLimiterTests.cs new file mode 100644 index 0000000000..a19f67bb1a --- /dev/null +++ b/test/Datadog.Trace.Tests/Sampling/RateLimiterTests.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.Sampling; +using Xunit; + +namespace Datadog.Trace.Tests.Sampling +{ + [Collection(nameof(Datadog.Trace.Tests.Sampling))] + public class RateLimiterTests + { + private const int DefaultLimitPerSecond = 100; + private static readonly ThreadLocal Random = new ThreadLocal(() => new Random()); + + [Fact] + public void One_Is_Allowed() + { + var traceContext = new TraceContext(Tracer.Instance); + var spanContext = new SpanContext(null, traceContext, "Weeeee"); + var span = new Span(spanContext, null); + var rateLimiter = new RateLimiter(maxTracesPerInterval: null); + var allowed = rateLimiter.Allowed(span); + Assert.True(allowed); + } + + [Fact] + public void All_Traces_Disabled() + { + var rateLimiter = new RateLimiter(maxTracesPerInterval: 0); + var allowedCount = AskTheRateLimiterABunchOfTimes(rateLimiter, 500); + Assert.Equal(expected: 0, actual: allowedCount); + } + + [Fact] + public void All_Traces_Allowed() + { + var rateLimiter = new RateLimiter(maxTracesPerInterval: -1); + var allowedCount = AskTheRateLimiterABunchOfTimes(rateLimiter, 500); + Assert.Equal(expected: 500, actual: allowedCount); + } + + [Fact] + public void Only_100_Allowed_In_500_Burst_For_Default() + { + var rateLimiter = new RateLimiter(maxTracesPerInterval: null); + var allowedCount = AskTheRateLimiterABunchOfTimes(rateLimiter, 500); + Assert.Equal(expected: DefaultLimitPerSecond, actual: allowedCount); + } + + [Fact] + public void Limits_Approximately_To_Defaults() + { + Run_Limit_Test(intervalLimit: null, numberPerBurst: 200, numberOfBursts: 18, millisecondsBetweenBursts: 247); + } + + [Fact] + public void Limits_To_Custom_Amount_Per_Second() + { + Run_Limit_Test(intervalLimit: 500, numberPerBurst: 200, numberOfBursts: 18, millisecondsBetweenBursts: 247); + } + + private static void Run_Limit_Test(int? intervalLimit, int numberPerBurst, int numberOfBursts, int millisecondsBetweenBursts) + { + var actualIntervalLimit = intervalLimit ?? DefaultLimitPerSecond; + + var test = new RateLimitLoadTest() + { + NumberPerBurst = numberPerBurst, + TimeBetweenBursts = TimeSpan.FromMilliseconds(millisecondsBetweenBursts), + NumberOfBursts = numberOfBursts + }; + + var result = RunTest(intervalLimit, test); + + var totalMilliseconds = result.TimeElapsed.TotalMilliseconds; + + var expectedLimit = totalMilliseconds * actualIntervalLimit / 1_000; + + var acceptableVariance = (actualIntervalLimit * 1.0); + var upperLimit = expectedLimit + acceptableVariance; + var lowerLimit = expectedLimit - acceptableVariance; + + Assert.True( + result.TotalAllowed >= lowerLimit && result.TotalAllowed <= upperLimit, + $"Expected between {lowerLimit} and {upperLimit}, received {result.TotalAllowed} out of {result.TotalAttempted} within {totalMilliseconds} milliseconds."); + + // Rate should match for the last two intervals, which is a total of two seconds + var numberOfBurstsWithinTwoIntervals = 2_000 / millisecondsBetweenBursts; + var totalExpectedSent = numberOfBurstsWithinTwoIntervals * numberPerBurst; + var totalExpectedAllowed = 2 * actualIntervalLimit; + var expectedRate = totalExpectedAllowed / (float)totalExpectedSent; + + var lowestRate = expectedRate - 0.40f; + if (lowestRate < 0) + { + lowestRate = expectedRate / 2; + } + + var highestRate = expectedRate + 0.40f; + + Assert.True( + result.ReportedRate >= lowestRate && result.ReportedRate <= highestRate, + $"Expected rate between {lowestRate} and {highestRate}, received {result.ReportedRate}."); + } + + private static int AskTheRateLimiterABunchOfTimes(RateLimiter rateLimiter, int howManyTimes) + { + var traceContext = new TraceContext(Tracer.Instance); + var spanContext = new SpanContext(null, traceContext, "Weeeee"); + var span = new Span(spanContext, null); + + var remaining = howManyTimes; + var allowedCount = 0; + while (remaining-- > 0) + { + var allowed = rateLimiter.Allowed(span); + if (allowed) + { + allowedCount++; + } + } + + return allowedCount; + } + + private static RateLimitResult RunTest(int? intervalLimit, RateLimitLoadTest test) + { + var parallelism = test.NumberPerBurst; + + if (parallelism > 10) + { + parallelism = 10; + } + + var result = new RateLimitResult(); + + var limiter = new RateLimiter(maxTracesPerInterval: intervalLimit); + + var traceContext = new TraceContext(Tracer.Instance); + + var barrier = new Barrier(parallelism + 1); + + var numberPerThread = test.NumberPerBurst / parallelism; + + var workers = new Task[parallelism]; + + for (int i = 0; i < workers.Length; i++) + { + workers[i] = Task.Factory.StartNew( + () => + { + var stopwatch = new Stopwatch(); + + for (var i = 0; i < test.NumberOfBursts; i++) + { + // Wait for every worker to be ready for next burst + barrier.SignalAndWait(); + + stopwatch.Restart(); + + for (int j = 0; j < numberPerThread; j++) + { + var spanContext = new SpanContext(null, traceContext, "Weeeee"); + var span = new Span(spanContext, null); + + if (limiter.Allowed(span)) + { + result.Allowed.Add(span.SpanId); + } + else + { + result.Denied.Add(span.SpanId); + } + } + + var remainingTime = (test.TimeBetweenBursts - stopwatch.Elapsed).TotalMilliseconds; + + if (remainingTime > 0) + { + Thread.Sleep((int)remainingTime); + } + } + }, + TaskCreationOptions.LongRunning); + } + + // Wait for all workers to be ready + barrier.SignalAndWait(); + + var sw = Stopwatch.StartNew(); + + // We do not need to synchronize with workers anymore + barrier.RemoveParticipant(); + + // Wait for workers to finish + Task.WaitAll(workers); + + result.TimeElapsed = sw.Elapsed; + result.RateLimiter = limiter; + result.ReportedRate = limiter.GetEffectiveRate(); + + return result; + } + + private class RateLimitLoadTest + { + public int NumberPerBurst { get; set; } + + public TimeSpan TimeBetweenBursts { get; set; } + + public int NumberOfBursts { get; set; } + } + + private class RateLimitResult + { + public RateLimiter RateLimiter { get; set; } + + public TimeSpan TimeElapsed { get; set; } + + public ConcurrentBag Allowed { get; } = new ConcurrentBag(); + + public ConcurrentBag Denied { get; } = new ConcurrentBag(); + + public float ReportedRate { get; set; } + + public int TotalAttempted => Allowed.Count + Denied.Count; + + public int TotalAllowed => Allowed.Count; + } + } +} diff --git a/test/Datadog.Trace.Tests/Sampling/RuleBasedSamplerTests.cs b/test/Datadog.Trace.Tests/Sampling/RuleBasedSamplerTests.cs new file mode 100644 index 0000000000..118d0df3dc --- /dev/null +++ b/test/Datadog.Trace.Tests/Sampling/RuleBasedSamplerTests.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using Datadog.Trace.Sampling; +using Xunit; + +namespace Datadog.Trace.Tests.Sampling +{ + [Collection(nameof(Datadog.Trace.Tests.Sampling))] + public class RuleBasedSamplerTests + { + private static readonly float FallbackRate = 0.25f; + private static readonly string ServiceName = "my-service-name"; + private static readonly string Env = "my-test-env"; + private static readonly string OperationName = "test"; + private static readonly IEnumerable> MockAgentRates = new List>() { new KeyValuePair($"service:{ServiceName},env:{Env}", FallbackRate) }; + + private static ulong _id = 1; + + [Fact] + public void RateLimiter_Denies_All_Traces() + { + var sampler = new RuleBasedSampler(new DenyAll()); + sampler.RegisterRule(new CustomSamplingRule(1, "Allow_all", ".*", ".*")); + RunSamplerTest( + sampler, + 500, + 0, + 0); + } + + [Fact] + public void Keep_Everything_Rule() + { + var sampler = new RuleBasedSampler(new NoLimits()); + sampler.RegisterRule(new CustomSamplingRule(1, "Allow_all", ".*", ".*")); + RunSamplerTest( + sampler, + 500, + 1, + 0); + } + + [Fact] + public void Keep_Nothing_Rule() + { + var sampler = new RuleBasedSampler(new NoLimits()); + sampler.RegisterRule(new CustomSamplingRule(0, "Allow_nothing", ".*", ".*")); + RunSamplerTest( + sampler, + 500, + 0, + 0); + } + + [Fact] + public void Keep_Half_Rule() + { + var sampler = new RuleBasedSampler(new NoLimits()); + sampler.RegisterRule(new CustomSamplingRule(0.5f, "Allow_nothing", ".*", ".*")); + RunSamplerTest( + sampler, + 10_000, // Higher number for lower variance + 0.5f, + 0.05f); + } + + [Fact] + public void No_Registered_Rules_Uses_Legacy_Rates() + { + var sampler = new RuleBasedSampler(new NoLimits()); + sampler.SetDefaultSampleRates(MockAgentRates); + + RunSamplerTest( + sampler, + 10_000, // Higher number for lower variance + FallbackRate, + 0.05f); + } + + private static Span GetMyServiceSpan() + { + var span = new Span(new SpanContext(_id++, _id++, null, serviceName: ServiceName), DateTimeOffset.Now) { OperationName = OperationName }; + span.SetTag(Tags.Env, Env); + return span; + } + + private void RunSamplerTest( + ISampler sampler, + int iterations, + float expectedAutoKeepRate, + float acceptableVariancePercent) + { + var sampleSize = iterations; + var autoKeeps = 0; + while (sampleSize-- > 0) + { + var span = GetMyServiceSpan(); + var priority = sampler.GetSamplingPriority(span); + if (priority == SamplingPriority.AutoKeep) + { + autoKeeps++; + } + } + + var autoKeepRate = autoKeeps / (float)iterations; + + var lowerLimit = expectedAutoKeepRate * (1 - acceptableVariancePercent); + var upperLimit = expectedAutoKeepRate * (1 + acceptableVariancePercent); + + Assert.True( + autoKeepRate >= lowerLimit && autoKeepRate <= upperLimit, + $"Expected between {lowerLimit} and {upperLimit}, actual rate is {autoKeepRate}."); + } + + private class NoLimits : IRateLimiter + { + public bool Allowed(Span span) + { + return true; + } + + public float GetEffectiveRate() + { + return 1; + } + } + + private class DenyAll : IRateLimiter + { + public bool Allowed(Span span) + { + return false; + } + + public float GetEffectiveRate() + { + return 0; + } + } + } +} diff --git a/test/Datadog.Trace.Tests/SpanStatisticalTests.cs b/test/Datadog.Trace.Tests/SpanStatisticalTests.cs new file mode 100644 index 0000000000..9bdb9182af --- /dev/null +++ b/test/Datadog.Trace.Tests/SpanStatisticalTests.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Trace.Tests +{ + public class SpanStatisticalTests + { + private static readonly object _populationLock = new object(); + private static readonly ConcurrentDictionary _generatedIds = new ConcurrentDictionary(); + + /// + /// The max value of the Ids we create should be a 63 bit unsigned number + /// + private static ulong _maxId = ulong.MaxValue / 2; + private static int _numberOfBuckets = 20; + private static ulong _numberOfIdsToGenerate = 1_500_000; + + // Helper numbers for logging and calculating + private static decimal _bucketSizePercentage = 100 / _numberOfBuckets; + private static ulong _bucketSize = _maxId / (ulong)_numberOfBuckets; + + private readonly ITestOutputHelper _output; + + public SpanStatisticalTests(ITestOutputHelper output) + { + _output = output; + BlastOff(); + } + + [Fact] + public void GeneratedIds_Contain_High_Numbers() + { + var rangeBound = _maxId - _bucketSize; + var keysWithinRange = _generatedIds.Keys.Where(i => i >= rangeBound).ToList(); + _output.WriteLine($"Found {keysWithinRange.Count()} above {rangeBound}, the top {_bucketSizePercentage}% of values."); + Assert.True(keysWithinRange.Count() > 0); + } + + [Fact] + public void GeneratedIds_Contain_Low_Numbers() + { + var rangeBound = _bucketSize; + var keysWithinRange = _generatedIds.Keys.Where(i => i <= rangeBound).ToList(); + _output.WriteLine($"Found {keysWithinRange.Count()} below {rangeBound}, the bottom {_bucketSizePercentage}% of values."); + Assert.True(keysWithinRange.Count() > 0); + } + + [Fact] + public void GeneratedIds_Contain_Nothing_Above_Expected_Max() + { + var keysOutOfRange = _generatedIds.Keys.Any(i => i > _maxId); + Assert.False(keysOutOfRange, $"We should never generate keys above {_maxId}."); + } + + [Fact] + public void GeneratedIds_Contain_Reasonably_Few_Duplicates() + { + var duplicateKeys = _generatedIds.Where(kvp => kvp.Value > 1).ToList(); + var acceptablePercentageOfDuplicates = 0.001m; + + ulong duplicateKeyCount = 0; + foreach (var kvp in duplicateKeys) + { + duplicateKeyCount += kvp.Value; + } + + var percentageOfDuplicates = (decimal)duplicateKeyCount / (decimal)_numberOfIdsToGenerate; + _output.WriteLine($"Found {duplicateKeyCount} duplicate keys."); + Assert.True(percentageOfDuplicates <= acceptablePercentageOfDuplicates); + } + + [Fact] + public void GeneratedIds_Are_Evenly_Distributed() + { + var expectedApproximateBucketSize = _numberOfIdsToGenerate / (ulong)_numberOfBuckets; + var actualApproximateBucketSize = (ulong)_generatedIds.Keys.Count() / (ulong)_numberOfBuckets; + var buckets = new List(); + for (var i = 0; i < _numberOfBuckets; i++) + { + buckets.Add(0); + } + + _output.WriteLine($"Requested {_numberOfIdsToGenerate} keys, received {_generatedIds.Keys.Count()} unique keys."); + _output.WriteLine($"Expected approximately {expectedApproximateBucketSize} keys per bucket."); + _output.WriteLine($"Receiving approximately {actualApproximateBucketSize} keys per bucket."); + _output.WriteLine($"Organizing {_numberOfBuckets} buckets with a range size of {_bucketSize} which is {_bucketSizePercentage}%."); + + foreach (var key in _generatedIds.Keys) + { + var percentile = ((decimal)key / _maxId) * 100m; + var bucketIndex = (int)(percentile / _bucketSizePercentage); + var numberOfHits = _generatedIds[key]; + buckets[bucketIndex] += numberOfHits; + } + + var bucketsWithNoKeys = new List(); + ulong minCount = ulong.MaxValue; + ulong maxCount = 0; + + for (var i = 0; i < _numberOfBuckets; i++) + { + var bucketCount = buckets[i]; + if (bucketCount == 0) + { + bucketsWithNoKeys.Add(i); + } + + if (bucketCount < minCount) + { + minCount = bucketCount; + } + + if (bucketCount > maxCount) + { + maxCount = bucketCount; + } + + var readableIndex = i + 1; + var lowerPercent = (readableIndex - 1) * _bucketSizePercentage; + var upperPercent = (readableIndex) * _bucketSizePercentage; + _output.WriteLine($"Bucket {readableIndex} has {buckets[i]} keys between {lowerPercent}-{upperPercent}%."); + } + + Assert.True(bucketsWithNoKeys.Count() == 0, "There should be no buckets which have no keys."); + + // Variance is the deviation from the expected mean or average + var maxDiff = Math.Abs((decimal)(maxCount - actualApproximateBucketSize)); + var minDiff = Math.Abs((decimal)(actualApproximateBucketSize - minCount)); + var biggestDiff = new[] { maxDiff, minDiff }.Max(); + var variance = biggestDiff / actualApproximateBucketSize; + + var maximumVariance = 0.05m; + _output.WriteLine($"The maximum variance in all buckets is {variance}."); + Assert.True(maximumVariance >= variance, $"The variance between buckets should be less than {maximumVariance}, but it is {variance}."); + } + + private void BlastOff() + { + lock (_populationLock) + { + if (_generatedIds.Keys.Count > 0) + { + return; + } + + _output.WriteLine($"Starting key generation."); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + // populate the dictionary for all tests + Parallel.For(0L, (long)_numberOfIdsToGenerate, i => + { + var id = GenerateId(); + _generatedIds.AddOrUpdate( + key: id, + addValue: 1, + updateValueFactory: (key, oldValue) => oldValue++); + }); + stopwatch.Stop(); + _output.WriteLine($"It took {stopwatch.ElapsedMilliseconds / 1000d} seconds to generate {_numberOfIdsToGenerate} keys."); + } + } + + private ulong GenerateId() + { + return new SpanContext(null, null, string.Empty).SpanId; + } + } +} diff --git a/test/Datadog.Trace.Tests/SpanTests.cs b/test/Datadog.Trace.Tests/SpanTests.cs new file mode 100644 index 0000000000..92f6badb10 --- /dev/null +++ b/test/Datadog.Trace.Tests/SpanTests.cs @@ -0,0 +1,139 @@ +using System; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Moq; +using Xunit; +using Xunit.Abstractions; + +namespace Datadog.Trace.Tests +{ + public class SpanTests + { + private readonly ITestOutputHelper _output; + private readonly Mock _writerMock; + private readonly Tracer _tracer; + + public SpanTests(ITestOutputHelper output) + { + _output = output; + + var settings = new TracerSettings(); + _writerMock = new Mock(); + var samplerMock = new Mock(); + + _tracer = new Tracer(settings, _writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + } + + [Fact] + public void SetTag_KeyValue_KeyValueSet() + { + const string key = "Key"; + const string value = "Value"; + var span = _tracer.StartSpan("Operation"); + Assert.Null(span.GetTag(key)); + + span.SetTag(key, value); + + _writerMock.Verify(x => x.WriteTrace(It.IsAny()), Times.Never); + Assert.Equal(span.GetTag(key), value); + } + + [Fact] + public void Finish_StartTimeInThePastWithNoEndTime_DurationProperlyComputed() + { + // The 100 additional milliseconds account for the clock precision + var startTime = DateTimeOffset.UtcNow.AddMinutes(-1).AddMilliseconds(-100); + var span = _tracer.StartSpan("Operation", startTime: startTime); + + span.Finish(); + + Assert.True(span.Duration >= TimeSpan.FromMinutes(1) && span.Duration < TimeSpan.FromMinutes(2)); + } + + [Fact] + public async Task Finish_NoEndTimeProvided_SpanWriten() + { + var span = _tracer.StartSpan("Operation"); + await Task.Delay(TimeSpan.FromMilliseconds(1)); + span.Finish(); + + _writerMock.Verify(x => x.WriteTrace(It.IsAny()), Times.Once); + Assert.True(span.Duration > TimeSpan.Zero); + } + + [Fact] + public void Finish_EndTimeProvided_SpanWritenWithCorrectDuration() + { + var startTime = DateTimeOffset.UtcNow; + var endTime = DateTime.UtcNow.AddMilliseconds(10); + var span = _tracer.StartSpan("Operation", startTime: startTime); + + span.Finish(endTime); + + Assert.Equal(endTime - startTime, span.Duration); + } + + [Fact] + public void Finish_EndTimeInThePast_DurationIs0() + { + var startTime = DateTimeOffset.UtcNow; + var endTime = DateTime.UtcNow.AddMilliseconds(-10); + var span = _tracer.StartSpan("Operation", startTime: startTime); + + span.Finish(endTime); + + Assert.Equal(TimeSpan.Zero, span.Duration); + } + + [Theory] + [InlineData(3)] + [InlineData(10)] + [InlineData(100)] + public void Accurate_Duration(int minimumSleepMilliseconds) + { + // TODO: refactor how we measure time so we can lower this threshold + const int iterations = 10; + const int maxDifference = 15; + TimeSpan totalStopwatchTime = TimeSpan.Zero; + TimeSpan totalSpanTime = TimeSpan.Zero; + Span span; + var stopwatch = new Stopwatch(); + + // execute once to ensure JIT compilation + using (span = _tracer.StartSpan("Operation")) + { + stopwatch.Restart(); + Thread.Sleep(1); + var spanMilliseconds = span.Duration.TotalMilliseconds; + var elapsedMilliseconds = stopwatch.ElapsedMilliseconds; + } + + // execute multiple times and average the results + for (int x = 0; x < iterations; x++) + { + using (span = _tracer.StartSpan("Operation")) + { + stopwatch.Restart(); + Thread.Sleep(minimumSleepMilliseconds); + totalStopwatchTime += stopwatch.Elapsed; + } + + totalSpanTime += span.Duration; + } + + var avgStopwatch = totalStopwatchTime.TotalMilliseconds / iterations; + var avgSpan = totalSpanTime.TotalMilliseconds / iterations; + var stopwatchSpanDiff = Math.Abs(avgSpan - avgStopwatch); + // The difference should be less than the threshold + _output.WriteLine($"Average elapsed time: {avgStopwatch:0.0} ms"); + _output.WriteLine($"Average span time: {avgSpan:0.0} ms"); + Assert.True( + stopwatchSpanDiff < maxDifference, + $"Span duration difference ({stopwatchSpanDiff}ms) outside of allowed threshold {maxDifference}ms. Expected average: {avgStopwatch}ms, actual average: {avgSpan}ms"); + } + } +} diff --git a/test/Datadog.Trace.Tests/TimeUtilsTests.cs b/test/Datadog.Trace.Tests/TimeUtilsTests.cs new file mode 100644 index 0000000000..a6792da7f2 --- /dev/null +++ b/test/Datadog.Trace.Tests/TimeUtilsTests.cs @@ -0,0 +1,25 @@ +#if !NET45 && !NET451 && !NET452 +using System; +using Datadog.Trace.ExtensionMethods; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class TimeUtilsTests + { + [Fact] + public void ToUnixTimeNanoseconds_UnixEpoch_Zero() + { + var date = DateTimeOffset.FromUnixTimeMilliseconds(0); + Assert.Equal(0, date.ToUnixTimeNanoseconds()); + } + + [Fact] + public void ToUnixTimeNanoseconds_Now_CorrectMillisecondRoundedValue() + { + var date = DateTimeOffset.UtcNow; + Assert.Equal(date.ToUnixTimeMilliseconds(), date.ToUnixTimeNanoseconds() / 1000000); + } + } +} +#endif \ No newline at end of file diff --git a/test/Datadog.Trace.Tests/TraceContextTests.cs b/test/Datadog.Trace.Tests/TraceContextTests.cs new file mode 100644 index 0000000000..a3a0051d4d --- /dev/null +++ b/test/Datadog.Trace.Tests/TraceContextTests.cs @@ -0,0 +1,33 @@ +using System; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class TraceContextTests + { + private readonly Mock _tracerMock = new Mock(); + + [Fact] + public void UtcNow_GivesLegitTime() + { + var traceContext = new TraceContext(_tracerMock.Object); + + var now = traceContext.UtcNow; + var expectedNow = DateTimeOffset.UtcNow; + + Assert.True(expectedNow.Subtract(now) < TimeSpan.FromMilliseconds(30)); + } + + [Fact] + public void UtcNow_IsMonotonic() + { + var traceContext = new TraceContext(_tracerMock.Object); + + var t1 = traceContext.UtcNow; + var t2 = traceContext.UtcNow; + + Assert.True(t2.Subtract(t1) > TimeSpan.Zero); + } + } +} diff --git a/test/Datadog.Trace.Tests/TracerSettingsTests.cs b/test/Datadog.Trace.Tests/TracerSettingsTests.cs new file mode 100644 index 0000000000..b8a80ce2b3 --- /dev/null +++ b/test/Datadog.Trace.Tests/TracerSettingsTests.cs @@ -0,0 +1,85 @@ +using System.Collections.Specialized; +using System.Linq; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.Sampling; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class TracerSettingsTests + { + private readonly Mock _writerMock; + private readonly Mock _samplerMock; + + public TracerSettingsTests() + { + _writerMock = new Mock(); + _samplerMock = new Mock(); + } + + [Theory] + [InlineData(ConfigurationKeys.Environment, Tags.Env, null)] + [InlineData(ConfigurationKeys.Environment, Tags.Env, "custom-env")] + [InlineData(ConfigurationKeys.ServiceVersion, Tags.Version, null)] + [InlineData(ConfigurationKeys.ServiceVersion, Tags.Version, "custom-version")] + public void ConfiguredTracerSettings_DefaultTagsSetFromEnvironmentVariable(string environmentVariableKey, string tagKey, string value) + { + var collection = new NameValueCollection { { environmentVariableKey, value } }; + + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new TracerSettings(source); + + var tracer = new Tracer(settings, _writerMock.Object, _samplerMock.Object, scopeManager: null, statsd: null); + var span = tracer.StartSpan("Operation"); + + Assert.Equal(span.GetTag(tagKey), value); + } + + [Theory] + [InlineData(ConfigurationKeys.Environment, Tags.Env)] + [InlineData(ConfigurationKeys.ServiceVersion, Tags.Version)] + public void DDVarTakesPrecedenceOverDDTags(string envKey, string tagKey) + { + string envValue = $"ddenv-custom-{tagKey}"; + string tagsLine = $"{tagKey}:ddtags-custom-{tagKey}"; + var collection = new NameValueCollection { { envKey, envValue }, { ConfigurationKeys.GlobalTags, tagsLine } }; + + IConfigurationSource source = new NameValueConfigurationSource(collection); + var settings = new TracerSettings(source); + Assert.True(settings.GlobalTags.Any()); + + var tracer = new Tracer(settings, _writerMock.Object, _samplerMock.Object, scopeManager: null, statsd: null); + var span = tracer.StartSpan("Operation"); + + Assert.Equal(span.GetTag(tagKey), envValue); + } + + [Theory] + [InlineData("", true)] + [InlineData("1", true)] + [InlineData("0", false)] + public void TraceEnabled(string value, bool areTracesEnabled) + { + var settings = new NameValueCollection + { + { ConfigurationKeys.TraceEnabled, value } + }; + + var tracerSettings = new TracerSettings(new NameValueConfigurationSource(settings)); + + Assert.Equal(areTracesEnabled, tracerSettings.TraceEnabled); + + _writerMock.ResetCalls(); + + var tracer = new Tracer(tracerSettings, _writerMock.Object, _samplerMock.Object, scopeManager: null, statsd: null); + var span = tracer.StartSpan("TestTracerDisabled"); + span.Dispose(); + + var assertion = areTracesEnabled ? Times.Once() : Times.Never(); + + _writerMock.Verify(w => w.WriteTrace(It.IsAny()), assertion); + } + } +} diff --git a/test/Datadog.Trace.Tests/TracerTests.cs b/test/Datadog.Trace.Tests/TracerTests.cs new file mode 100644 index 0000000000..8b41f2ae5a --- /dev/null +++ b/test/Datadog.Trace.Tests/TracerTests.cs @@ -0,0 +1,480 @@ +using System; +using System.Linq; +using System.Net; +#if NET452 +using System.Runtime.Remoting; +using System.Runtime.Remoting.Lifetime; +using System.Runtime.Remoting.Services; +#endif +using System.Threading; +using System.Threading.Tasks; +using Datadog.Trace.Agent; +using Datadog.Trace.Configuration; +using Datadog.Trace.ExtensionMethods; +using Datadog.Trace.Headers; +using Datadog.Trace.Sampling; +using Datadog.Trace.TestHelpers; +using Moq; +using Xunit; + +namespace Datadog.Trace.Tests +{ + public class TracerTests + { + private readonly Tracer _tracer; + + static TracerTests() + { +#if NET452 + LifetimeServices.LeaseTime = TimeSpan.FromMilliseconds(100); + LifetimeServices.LeaseManagerPollTime = TimeSpan.FromMilliseconds(10); +#endif + } + + public TracerTests() + { + var settings = new TracerSettings(); + var writerMock = new Mock(); + var samplerMock = new Mock(); + + _tracer = new Tracer(settings, writerMock.Object, samplerMock.Object, scopeManager: null, statsd: null); + } + + [Fact] + public void StartActive_SetOperationName_OperationNameIsSet() + { + var scope = _tracer.StartActive("Operation", null); + + Assert.Equal("Operation", scope.Span.OperationName); + } + + [Fact] + public void StartActive_SetOperationName_ActiveScopeIsSet() + { + var scope = _tracer.StartActive("Operation", null); + + var activeScope = _tracer.ActiveScope; + Assert.Equal(scope, activeScope); + } + + [Fact] + public void StartActive_NoActiveScope_RootSpan() + { + var scope = _tracer.StartActive("Operation", null); + + Assert.True(scope.Span.IsRootSpan); + } + + [Fact] + public void StartActive_ActiveScope_UseCurrentScopeAsParent() + { + var parentScope = _tracer.StartActive("Parent"); + var childScope = _tracer.StartActive("Child"); + + Assert.Equal(parentScope.Span.Context, childScope.Span.Context.Parent); + } + + [Fact] + public void StartActive_IgnoreActiveScope_RootSpan() + { + var firstScope = _tracer.StartActive("First"); + var secondScope = _tracer.StartActive("Second", ignoreActiveScope: true); + + Assert.True(secondScope.Span.IsRootSpan); + } + + [Fact] + public void StartActive_FinishOnClose_SpanIsFinishedWhenScopeIsClosed() + { + var scope = _tracer.StartActive("Operation"); + Assert.False(scope.Span.IsFinished); + + scope.Close(); + + Assert.True(scope.Span.IsFinished); + Assert.Null(_tracer.ActiveScope); + } + + [Fact] + public void StartActive_FinishOnClose_SpanIsFinishedWhenScopeIsDisposed() + { + Scope scope; + using (scope = _tracer.StartActive("Operation")) + { + Assert.False(scope.Span.IsFinished); + } + + Assert.True(scope.Span.IsFinished); + Assert.Null(_tracer.ActiveScope); + } + + [Fact] + public void StartActive_NoFinishOnClose_SpanIsNotFinishedWhenScopeIsClosed() + { + var scope = _tracer.StartActive("Operation", finishOnClose: false); + Assert.False(scope.Span.IsFinished); + + scope.Dispose(); + + Assert.False(scope.Span.IsFinished); + Assert.Null(_tracer.ActiveScope); + } + + [Fact] + public void StartActive_SetParentManually_ParentIsSet() + { + var parent = _tracer.StartSpan("Parent"); + var child = _tracer.StartActive("Child", parent.Context); + + Assert.Equal(parent.Context, child.Span.Context.Parent); + } + + [Fact] + public void StartActive_SetParentManuallyFromExternalContext_ParentIsSet() + { + const ulong traceId = 11; + const ulong parentId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + + var parent = new SpanContext(traceId, parentId, samplingPriority); + var child = _tracer.StartActive("Child", parent); + + Assert.True(child.Span.IsRootSpan); + Assert.Equal(traceId, parent.TraceId); + Assert.Equal(parentId, parent.SpanId); + Assert.Null(parent.TraceContext); + Assert.Equal(parent, child.Span.Context.Parent); + Assert.Equal(parentId, child.Span.Context.ParentId); + Assert.NotNull(child.Span.Context.TraceContext); + Assert.Equal(samplingPriority, child.Span.Context.TraceContext.SamplingPriority); + } + + [Fact] + public void StartActive_NoServiceName_DefaultServiceName() + { + var scope = _tracer.StartActive("Operation"); + + Assert.Contains(scope.Span.ServiceName, TestRunners.ValidNames); + } + + [Fact] + public void StartActive_SetServiceName_ServiceNameIsSet() + { + var scope = _tracer.StartActive("Operation", serviceName: "MyAwesomeService"); + + Assert.Equal("MyAwesomeService", scope.Span.ServiceName); + } + + [Fact] + public void StartActive_SetParentServiceName_ChildServiceNameIsSet() + { + var parent = _tracer.StartActive("Parent", serviceName: "MyAwesomeService"); + var child = _tracer.StartActive("Child"); + + Assert.Equal("MyAwesomeService", child.Span.ServiceName); + } + + [Fact] + public void StartActive_SetStartTime_StartTimeIsProperlySet() + { + var startTime = new DateTimeOffset(2017, 01, 01, 0, 0, 0, TimeSpan.Zero); + var scope = _tracer.StartActive("Operation", startTime: startTime); + + Assert.Equal(startTime, scope.Span.StartTime); + } + + [Fact] + public void StartManual_SetOperationName_OperationNameIsSet() + { + var span = _tracer.StartSpan("Operation", null); + + Assert.Equal("Operation", span.OperationName); + } + + [Fact] + public void StartManual_SetOperationName_ActiveScopeIsNotSet() + { + _tracer.StartSpan("Operation", null); + + Assert.Null(_tracer.ActiveScope); + } + + [Fact] + public void StartManual_NoActiveScope_RootSpan() + { + var scope = _tracer.StartActive("Operation", null); + + Assert.True(scope.Span.IsRootSpan); + } + + [Fact] + public void StartManula_ActiveScope_UseCurrentScopeAsParent() + { + var parentSpan = _tracer.StartSpan("Parent"); + _tracer.ActivateSpan(parentSpan); + var childSpan = _tracer.StartSpan("Child"); + + Assert.Equal(parentSpan.Context, childSpan.Context.Parent); + } + + [Fact] + public void StartManual_IgnoreActiveScope_RootSpan() + { + var firstSpan = _tracer.StartSpan("First"); + _tracer.ActivateSpan(firstSpan); + var secondSpan = _tracer.StartSpan("Second", ignoreActiveScope: true); + + Assert.True(secondSpan.IsRootSpan); + } + + [Fact] + public void StartActive_2ChildrenOfRoot_ChildrenParentProperlySet() + { + var root = _tracer.StartActive("Root"); + var child1 = _tracer.StartActive("Child1"); + child1.Dispose(); + var child2 = _tracer.StartActive("Child2"); + + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)child1.Span.Context.TraceContext); + Assert.Equal(root.Span.Context.SpanId, child1.Span.Context.ParentId); + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)child2.Span.Context.TraceContext); + Assert.Equal(root.Span.Context.SpanId, child2.Span.Context.ParentId); + } + + [Fact] + public void StartActive_2LevelChildren_ChildrenParentProperlySet() + { + var root = _tracer.StartActive("Root"); + var child1 = _tracer.StartActive("Child1"); + var child2 = _tracer.StartActive("Child2"); + + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)child1.Span.Context.TraceContext); + Assert.Equal(root.Span.Context.SpanId, child1.Span.Context.ParentId); + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)child2.Span.Context.TraceContext); + Assert.Equal(child1.Span.Context.SpanId, child2.Span.Context.ParentId); + } + + [Fact] + public async Task StartActive_AsyncChildrenCreation_ChildrenParentProperlySet() + { + var tcs = new TaskCompletionSource(); + + var root = _tracer.StartActive("Root"); + + Func> createSpanAsync = async (t) => + { + await tcs.Task; + return t.StartActive("AsyncChild"); + }; + var tasks = Enumerable.Range(0, 10).Select(x => createSpanAsync(_tracer)).ToArray(); + + var syncChild = _tracer.StartActive("SyncChild"); + tcs.SetResult(true); + + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)syncChild.Span.Context.TraceContext); + Assert.Equal(root.Span.Context.SpanId, syncChild.Span.Context.ParentId); + foreach (var task in tasks) + { + var span = await task; + Assert.Equal(root.Span.Context.TraceContext, (ITraceContext)span.Span.Context.TraceContext); + Assert.Equal(root.Span.Context.SpanId, span.Span.Context.ParentId); + } + } + + [Theory] + [InlineData(null)] + [InlineData("test")] + public void SetEnv(string env) + { + var settings = new TracerSettings() + { + Environment = env, + }; + + var tracer = new Tracer(settings); + Span span = tracer.StartSpan("operation"); + + Assert.Equal(env, span.GetTag(Tags.Env)); + } + + [Theory] + // if no service name is specified, fallback to a best guess (e.g. assembly name, process name) + [InlineData(null, null, null)] + // if only one is set, use that one + [InlineData("tracerService", null, "tracerService")] + [InlineData(null, "spanService", "spanService")] + // if more than one is set, follow precedence: span > tracer > default + [InlineData("tracerService", "spanService", "spanService")] + public void SetServiceName(string tracerServiceName, string spanServiceName, string expectedServiceName) + { + var settings = new TracerSettings() + { + ServiceName = tracerServiceName, + }; + + var tracer = new Tracer(settings); + Span span = tracer.StartSpan("operationName", serviceName: spanServiceName); + + if (expectedServiceName == null) + { + Assert.Contains(span.ServiceName, TestRunners.ValidNames); + } + else + { + Assert.Equal(expectedServiceName, span.ServiceName); + } + } + + [Fact] + public void OriginHeader_RootSpanTag() + { + const ulong traceId = 9; + const ulong spanId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + var propagatedContext = new SpanContext(traceId, spanId, samplingPriority, null, origin); + Assert.Equal(origin, propagatedContext.Origin); + + using var firstSpan = _tracer.StartActive("First Span", propagatedContext); + Assert.True(firstSpan.Span.IsRootSpan); + Assert.Equal(origin, firstSpan.Span.Context.Origin); + Assert.Equal(origin, firstSpan.Span.GetTag(Tags.Origin)); + + using var secondSpan = _tracer.StartActive("Child", firstSpan.Span.Context); + Assert.False(secondSpan.Span.IsRootSpan); + Assert.Equal(origin, secondSpan.Span.Context.Origin); + Assert.Null(secondSpan.Span.GetTag(Tags.Origin)); + } + + [Fact] + public void OriginHeader_InjectFromChildSpan() + { + const ulong traceId = 9; + const ulong spanId = 7; + const SamplingPriority samplingPriority = SamplingPriority.UserKeep; + const string origin = "synthetics"; + + var propagatedContext = new SpanContext(traceId, spanId, samplingPriority, null, origin); + + using var firstSpan = _tracer.StartActive("First Span", propagatedContext); + using var secondSpan = _tracer.StartActive("Child", firstSpan.Span.Context); + + IHeadersCollection headers = WebRequest.CreateHttp("http://localhost").Headers.Wrap(); + + SpanContextPropagator.Instance.Inject(secondSpan.Span.Context, headers); + var resultContext = SpanContextPropagator.Instance.Extract(headers); + + Assert.NotNull(resultContext); + Assert.Equal(firstSpan.Span.Context.Origin, resultContext.Origin); + Assert.Equal(secondSpan.Span.Context.Origin, resultContext.Origin); + Assert.Equal(origin, resultContext.Origin); + } +#if NET452 + + // Test that storage in the Logical Call Context does not expire + // See GitHub issue https://github.com/serilog/serilog/issues/987 + // and the associated PR https://github.com/serilog/serilog/pull/992 + [Fact] + public void DoesNotThrowOnCrossDomainCallsWhenLeaseExpired() + { + // Arrange + var remote = AppDomain.CreateDomain("Remote", null, AppDomain.CurrentDomain.SetupInformation); + string operationName = "test-span"; + + // Act + try + { + using (_tracer.StartActive(operationName)) + { + remote.DoCallBack(SleepForLeaseManagerPollCallback); + + // After the lease expires, access the active scope + Scope scope = _tracer.ActiveScope; + Assert.Equal(operationName, scope.Span.OperationName); + } + } + finally + { + AppDomain.Unload(remote); + } + + // Assert + // Nothing. We should just throw no exceptions here + } + + [Fact] + public void DisconnectRemoteObjectsAfterCrossDomainCallsOnDispose() + { + // Arrange + var cde = new CountdownEvent(2); + var tracker = new InMemoryRemoteObjectTracker(cde); + TrackingServices.RegisterTrackingHandler(tracker); + + var remote = AppDomain.CreateDomain("Remote", null, AppDomain.CurrentDomain.SetupInformation); + + // Act + try + { + using (_tracer.StartActive("test-span")) + { + remote.DoCallBack(EmptyCallback); + + using (_tracer.StartActive("test-span-inner")) + { + remote.DoCallBack(EmptyCallback); + } + } + } + finally + { + AppDomain.Unload(remote); + } + + // Ensure that we wait long enough for the lease manager poll to occur. + // Even though we reset LifetimeServices.LeaseManagerPollTime to a shorter duration, + // the default value is 10 seconds so the first poll may not be affected by our modification + bool eventSet = cde.Wait(TimeSpan.FromSeconds(30)); + + // Assert + Assert.True(eventSet); + Assert.Equal(2, tracker.DisconnectCount); + } + + // Ensure the remote call takes long enough for the lease manager poll to occur. + // Even though we reset LifetimeServices.LeaseManagerPollTime to a shorter duration, + // the default value is 10 seconds so the first poll may not be affected by our modification + private static void SleepForLeaseManagerPollCallback() => Thread.Sleep(TimeSpan.FromSeconds(12)); + + private static void EmptyCallback() + { + } + + private class InMemoryRemoteObjectTracker : ITrackingHandler + { + private CountdownEvent _cde; + + public InMemoryRemoteObjectTracker(CountdownEvent cde) + { + _cde = cde; + } + + public int DisconnectCount { get; set; } + + public void DisconnectedObject(object obj) + { + DisconnectCount++; + _cde.Signal(); + } + + public void MarshaledObject(object obj, ObjRef or) + { + } + + public void UnmarshaledObject(object obj, ObjRef or) + { + } + } +#endif + } +} diff --git a/test/Datadog.Trace.Tests/Util/DomainMetadataTests.cs b/test/Datadog.Trace.Tests/Util/DomainMetadataTests.cs new file mode 100644 index 0000000000..cb0da76ae9 --- /dev/null +++ b/test/Datadog.Trace.Tests/Util/DomainMetadataTests.cs @@ -0,0 +1,42 @@ +using System; +using Datadog.Trace.Util; +using Xunit; + +namespace Datadog.Trace.Tests.Util +{ + public class DomainMetadataTests + { +#if !NETCOREAPP + + private const string TestDataKey = "ShouldAvoidAppInsightsAppDomain"; + + [Fact] + public void ShouldAvoidAppInsightsAppDomain() + { + static void AppDomainCallback() + { + var result = DomainMetadata.ShouldAvoidAppDomain(); + AppDomain.CurrentDomain.SetData(TestDataKey, result); + } + + var domain1 = AppDomain.CreateDomain("ApplicationInsights", null, AppDomain.CurrentDomain.SetupInformation); + + domain1.DoCallBack(AppDomainCallback); + + var rawValue = domain1.GetData(TestDataKey); + + Assert.IsType(rawValue); + Assert.True((bool)rawValue); + + var domain2 = AppDomain.CreateDomain("Test", null, AppDomain.CurrentDomain.SetupInformation); + + domain2.DoCallBack(AppDomainCallback); + + rawValue = domain2.GetData(TestDataKey); + + Assert.IsType(rawValue); + Assert.False((bool)rawValue); + } +#endif + } +} diff --git a/test/Datadog.Trace.Tests/Util/StopwatchTests.cs b/test/Datadog.Trace.Tests/Util/StopwatchTests.cs new file mode 100644 index 0000000000..e07fc70f13 --- /dev/null +++ b/test/Datadog.Trace.Tests/Util/StopwatchTests.cs @@ -0,0 +1,30 @@ +using System.Diagnostics; +using System.Reflection; +using System.Threading; +using Datadog.Trace.Util; +using Xunit; + +namespace Datadog.Trace.Tests.Util +{ + public class StopwatchTests + { + [Fact] + public void ComputesCorrectTimespan() + { + var sw = Stopwatch.StartNew(); + + Thread.Sleep(50); + + sw.Stop(); + + // Extract the internal ticks + var stopwatchTicks = (long)typeof(Stopwatch) + .GetMethod("GetRawElapsedTicks", BindingFlags.Instance | BindingFlags.NonPublic) + .Invoke(sw, null); + + var elapsed = StopwatchHelpers.GetElapsed(stopwatchTicks); + + Assert.Equal(sw.Elapsed, elapsed); + } + } +} diff --git a/test/Directory.Build.props b/test/Directory.Build.props new file mode 100644 index 0000000000..b9e513aefa --- /dev/null +++ b/test/Directory.Build.props @@ -0,0 +1,21 @@ + + + + + net452;net461;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1 + netcoreapp2.1;netcoreapp3.0;netcoreapp3.1 + + + + + + + + + + + + + + + diff --git a/test/GlobalSuppressions.cs b/test/GlobalSuppressions.cs new file mode 100644 index 0000000000..33efba624a --- /dev/null +++ b/test/GlobalSuppressions.cs @@ -0,0 +1,10 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1652:EnableXmlDocumentationOutput", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code must not contain multiple whitespace in a row", Justification = "Reviewed. Used for pretty formatting.")] diff --git a/tools/Datadog.Core.Tools/ConcurrencyHelper.cs b/tools/Datadog.Core.Tools/ConcurrencyHelper.cs new file mode 100644 index 0000000000..209766fca2 --- /dev/null +++ b/tools/Datadog.Core.Tools/ConcurrencyHelper.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Datadog.Core.Tools +{ + public class ConcurrencyHelper + { + private readonly ManualResetEventSlim _initiateLevelsEvent = new ManualResetEventSlim(initialState: false); // Start blocked + private readonly ManualResetEventSlim _testFinishedEvent = new ManualResetEventSlim(initialState: false); // Start blocked + private int _remainingLevels; + + public enum HelperStatus + { + AwaitingConfig, + Ready, + Running, + Errored, + Finished + } + + public List Levels { get; set; } = new List(); + + public HelperStatus Status { get; private set; } = HelperStatus.AwaitingConfig; + + public DateTime Started { get; private set; } + + public DateTime Finished { get; private set; } + + public void RegisterLevel(Action action, int iterations, string friendlyName = null, int numberOfRegisters = 1) + { + for (var i = 0; i < numberOfRegisters; i++) + { + Levels.Add(new Level() + { + Status = HelperStatus.Ready, + Action = action, + Name = friendlyName, + Iterations = iterations, + }); + } + + Status = HelperStatus.Ready; + } + + public async Task Start() + { + Status = HelperStatus.Running; + + var registry = new ConcurrentQueue(); + + Started = DateTime.Now; + + var workers = + Levels + .Select(level => new Thread( + thread => + { + Interlocked.Increment(ref _remainingLevels); + _initiateLevelsEvent.Wait(); + level.Started = DateTime.Now; + level.Status = HelperStatus.Running; + + try + { + for (var i = 0; i < level.Iterations; i++) + { + try + { + level.Action(); + } + catch (Exception ex) + { + level.Exceptions.Add(ex); + } + } + } + finally + { + level.Finished = DateTime.Now; + level.Status = HelperStatus.Finished; + Interlocked.Decrement(ref _remainingLevels); + + if (_remainingLevels == 0) + { + // The run is finished + _testFinishedEvent.Set(); + } + } + })); + + foreach (var worker in workers) + { + registry.Enqueue(worker); + worker.Start(); + } + + // Run everything + _initiateLevelsEvent.Set(); + + // Wait for everything to finish + _testFinishedEvent.Wait(); + + Finished = DateTime.Now; + Status = HelperStatus.Finished; + + // Pause for the next run if this class is reused + _initiateLevelsEvent.Reset(); + + await Task.FromResult(0); + } + + public IReadOnlyDictionary GetExceptionSummary() + { + return Levels.SelectMany(l => l.Exceptions).GroupBy(ex => ex.Message).ToDictionary(group => group.Key, group => group.Count()); + } + + public double GetTotalRuntime() + { + return Levels.Sum(l => l.TotalMilliseconds); + } + + public double GetAverageActionRuntime() + { + return Levels.Average(l => l.AverageCallMilliseconds); + } + + public class Level + { + public string Name { get; set; } + + public Action Action { get; set; } + + public int Iterations { get; set; } + + public ConcurrentBag Exceptions { get; set; } = new ConcurrentBag(); + + public DateTime Started { get; set; } + + public DateTime Finished { get; set; } + + public double TotalMilliseconds => (Finished - Started).TotalMilliseconds; + + public double AverageCallMilliseconds => TotalMilliseconds / Iterations; + + public HelperStatus Status { get; set; } + } + } +} diff --git a/tools/Datadog.Core.Tools/Datadog.Core.Tools.csproj b/tools/Datadog.Core.Tools/Datadog.Core.Tools.csproj new file mode 100644 index 0000000000..82aee19206 --- /dev/null +++ b/tools/Datadog.Core.Tools/Datadog.Core.Tools.csproj @@ -0,0 +1,13 @@ + + + + net452;net461;netcoreapp2.1;netcoreapp3.0;netcoreapp3.1 + netcoreapp2.1;netcoreapp3.0;netcoreapp3.1 + + + + + + + + diff --git a/tools/Datadog.Core.Tools/DependencyHelpers.cs b/tools/Datadog.Core.Tools/DependencyHelpers.cs new file mode 100644 index 0000000000..835b7a0c5e --- /dev/null +++ b/tools/Datadog.Core.Tools/DependencyHelpers.cs @@ -0,0 +1,34 @@ +using System; +using System.IO; + +namespace Datadog.Core.Tools +{ + public static class DependencyHelpers + { + public static string[] GetTracerBinContent(string frameworkMoniker, string extension = "dll") + { + var solutionDirectory = EnvironmentTools.GetSolutionDirectory(); + var projectBin = + Path.Combine( + solutionDirectory, + "tools", + "PrepareRelease", + "bin", + "tracer-home"); + + var outputFolder = Path.Combine(projectBin, frameworkMoniker); + + var filePaths = Directory.GetFiles( + outputFolder, + $"*.{extension}", + SearchOption.AllDirectories); + + if (filePaths.Length == 0) + { + throw new Exception("Be sure to build in release mode before running this tool."); + } + + return filePaths; + } + } +} diff --git a/tools/Datadog.Core.Tools/EnvironmentTools.cs b/tools/Datadog.Core.Tools/EnvironmentTools.cs new file mode 100644 index 0000000000..c81823e2eb --- /dev/null +++ b/tools/Datadog.Core.Tools/EnvironmentTools.cs @@ -0,0 +1,127 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace Datadog.Core.Tools +{ + /// + /// General use utility methods for all tests and tools. + /// + public class EnvironmentTools + { + public const string ProfilerClsId = "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}"; + public const string DotNetFramework = ".NETFramework"; + public const string CoreFramework = ".NETCoreApp"; + + private static string _solutionDirectory = null; + + /// + /// Find the solution directory from anywhere in the hierarchy. + /// + /// The solution directory. + public static string GetSolutionDirectory() + { + if (_solutionDirectory == null) + { + var startDirectory = Environment.CurrentDirectory; + var currentDirectory = Directory.GetParent(startDirectory); + const string searchItem = @"Datadog.Trace.sln"; + + while (true) + { + var slnFile = currentDirectory.GetFiles(searchItem).SingleOrDefault(); + + if (slnFile != null) + { + break; + } + + currentDirectory = currentDirectory.Parent; + + if (currentDirectory == null || !currentDirectory.Exists) + { + throw new Exception($"Unable to find solution directory from: {startDirectory}"); + } + } + + _solutionDirectory = currentDirectory.FullName; + } + + return _solutionDirectory; + } + + public static string GetTracerVersion() + { + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + return $"{TracerVersion.Major}.{TracerVersion.Minor}.{TracerVersion.Patch}{(TracerVersion.IsPreRelease ? "-prerelease" : string.Empty)}"; + } + + public static string GetOS() + { + return IsWindows() ? "win" : + RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx" : + string.Empty; + } + + public static bool IsWindows() + { + return RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + } + + public static string GetPlatform() + { + return RuntimeInformation.ProcessArchitecture.ToString(); + } + + public static string GetBuildConfiguration() + { +#if DEBUG + return "Debug"; +#else + return "Release"; +#endif + } + + public static bool IsConfiguredToProfile(Type anchorType) + { + var anchorAssembly = Assembly.GetAssembly(anchorType); + var targetFramework = anchorAssembly.GetCustomAttribute(); + + var parts = targetFramework.FrameworkName.Split(','); + var runtime = parts[0]; + var isCoreClr = runtime.Equals(CoreFramework); + + var environmentVariables = Environment.GetEnvironmentVariables(); + + var prefix = "COR"; + + if (isCoreClr) + { + prefix = "CORECLR"; + } + + if ((string)environmentVariables[$"{prefix}_ENABLE_PROFILING"] != "1") + { + return false; + } + + if ((string)environmentVariables[$"{prefix}_PROFILER"] != ProfilerClsId) + { + return false; + } + + var profilerPath = (string)environmentVariables[$"{prefix}_PROFILER_PATH"]; + + if (!File.Exists(profilerPath)) + { + return false; + } + + return true; + } + } +} diff --git a/tools/Datadog.Core.Tools/Extensions/AssemblyExtensions.cs b/tools/Datadog.Core.Tools/Extensions/AssemblyExtensions.cs new file mode 100644 index 0000000000..00f10eceb1 --- /dev/null +++ b/tools/Datadog.Core.Tools/Extensions/AssemblyExtensions.cs @@ -0,0 +1,43 @@ +using System; +using System.Reflection; +using System.Runtime.Versioning; + +namespace Datadog.Core.Tools.Extensions +{ + public static class AssemblyExtensions + { + private const string DotNetFramework = ".NETFramework"; + private const string CoreFramework = ".NETCoreApp"; + + public static string GetTargetFrameworkMoniker(this Assembly assembly) + { + var targetFramework = assembly.GetCustomAttribute(); + var parts = targetFramework?.FrameworkName?.Split(','); + + if (parts?.Length > 1) + { + var runtime = parts[0]; + var versionParts = parts[1].Replace("Version=v", string.Empty).Split('.'); + + if (versionParts.Length > 1) + { + var major = int.Parse(versionParts[0]); + var minor = int.Parse(versionParts[1]); + + if (runtime.Equals(CoreFramework)) + { + return $"netcoreapp{major}.{minor}"; + } + + if (runtime.Equals(DotNetFramework)) + { + var patch = versionParts.Length > 2 ? versionParts[2] : null; + return $"net{major}{minor}{patch}"; + } + } + } + + return "unsupported"; + } + } +} diff --git a/tools/Datadog.Core.Tools/TcpPortProvider.cs b/tools/Datadog.Core.Tools/TcpPortProvider.cs new file mode 100644 index 0000000000..668913f841 --- /dev/null +++ b/tools/Datadog.Core.Tools/TcpPortProvider.cs @@ -0,0 +1,29 @@ +using System.Net; +using System.Net.Sockets; + +namespace Datadog.Core.Tools +{ + /// + /// Helper class that tries to provide unique ports numbers across processes and threads in the same machine. + /// Used avoid port conflicts in concurrent tests that use the Agent, IIS, HttpListener, HttpClient, etc. + /// This class cannot guarantee a port is actually available, but should help avoid most conflicts. + /// + public static class TcpPortProvider + { + public static int GetOpenPort() + { + TcpListener tcpListener = null; + try + { + tcpListener = new TcpListener(IPAddress.Loopback, 0); + tcpListener.Start(); + var port = ((IPEndPoint)tcpListener.LocalEndpoint).Port; + return port; + } + finally + { + tcpListener?.Stop(); + } + } + } +} diff --git a/tools/Datadog.Core.Tools/TracerVersion.cs b/tools/Datadog.Core.Tools/TracerVersion.cs new file mode 100644 index 0000000000..5cfbbf3127 --- /dev/null +++ b/tools/Datadog.Core.Tools/TracerVersion.cs @@ -0,0 +1,28 @@ +namespace Datadog.Core.Tools +{ + /// + /// The canonical version for the dd-trace-dotnet libraries and tools. + /// + public class TracerVersion + { + /// + /// The major portion of the current version. + /// + public const int Major = 1; + + /// + /// The minor portion of the current version. + /// + public const int Minor = 19; + + /// + /// The patch portion of the current version. + /// + public const int Patch = 1; + + /// + /// Whether the current release is a pre-release + /// + public const bool IsPreRelease = false; + } +} diff --git a/tools/Directory.Build.props b/tools/Directory.Build.props new file mode 100644 index 0000000000..5d8d7f9e29 --- /dev/null +++ b/tools/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tools/GlobalSuppressions.cs b/tools/GlobalSuppressions.cs new file mode 100644 index 0000000000..33efba624a --- /dev/null +++ b/tools/GlobalSuppressions.cs @@ -0,0 +1,10 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1652:EnableXmlDocumentationOutput", Justification = "Reviewed.")] +[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code must not contain multiple whitespace in a row", Justification = "Reviewed. Used for pretty formatting.")] diff --git a/tools/PrepareRelease/GenerateIntegrationDefinitions.cs b/tools/PrepareRelease/GenerateIntegrationDefinitions.cs new file mode 100644 index 0000000000..eb5acb88a7 --- /dev/null +++ b/tools/PrepareRelease/GenerateIntegrationDefinitions.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using Datadog.Trace.ClrProfiler; +using Newtonsoft.Json; + +namespace PrepareRelease +{ + public static class GenerateIntegrationDefinitions + { + public static void Run(params string[] outputDirectories) + { + Console.WriteLine("Updating the integrations definitions"); + + var assemblies = new List(); + assemblies.Add(typeof(Instrumentation).Assembly); + + // find all methods in Datadog.Trace.ClrProfiler.Managed.dll with [InterceptMethod] + // and create objects that will generate correct JSON schema + var integrations = from assembly in assemblies + from wrapperType in assembly.GetTypes() + from wrapperMethod in wrapperType.GetRuntimeMethods() + let attributes = wrapperMethod.GetCustomAttributes(inherit: false) + where attributes.Any() + from attribute in attributes + let integrationName = attribute.Integration ?? GetIntegrationName(wrapperType) + orderby integrationName + group new + { + assembly, + wrapperType, + wrapperMethod, + attribute + } + by integrationName into g + select new + { + name = g.Key, + method_replacements = from item in g + from targetAssembly in item.attribute.TargetAssemblies + select new + { + caller = new + { + assembly = item.attribute.CallerAssembly, + type = item.attribute.CallerType, + method = item.attribute.CallerMethod + }, + target = new + { + assembly = targetAssembly, + type = item.attribute.TargetType, + method = item.attribute.TargetMethod ?? item.wrapperMethod.Name, + signature = item.attribute.TargetSignature, + signature_types = item.attribute.TargetSignatureTypes, + minimum_major = item.attribute.TargetVersionRange.MinimumMajor, + minimum_minor = item.attribute.TargetVersionRange.MinimumMinor, + minimum_patch = item.attribute.TargetVersionRange.MinimumPatch, + maximum_major = item.attribute.TargetVersionRange.MaximumMajor, + maximum_minor = item.attribute.TargetVersionRange.MaximumMinor, + maximum_patch = item.attribute.TargetVersionRange.MaximumPatch + }, + wrapper = new + { + assembly = item.assembly.FullName, + type = item.wrapperType.FullName, + method = item.wrapperMethod.Name, + signature = GetMethodSignature(item.wrapperMethod, item.attribute), + action = item.attribute.MethodReplacementAction.ToString() + } + } + }; + + var serializerSettings = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + Formatting = Formatting.Indented + }; + + var json = JsonConvert.SerializeObject(integrations, serializerSettings); + Console.WriteLine(json); + + foreach (var outputDirectory in outputDirectories) + { + var filename = Path.Combine(outputDirectory, "integrations.json"); + var utf8NoBom = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); + File.WriteAllText(filename, json, utf8NoBom); + } + } + + private static string GetIntegrationName(Type wrapperType) + { + const string integrations = "Integration"; + var typeName = wrapperType.Name; + + if (typeName.EndsWith(integrations, StringComparison.OrdinalIgnoreCase)) + { + return typeName.Substring(startIndex: 0, length: typeName.Length - integrations.Length); + } + + return typeName; + } + + private static string GetMethodSignature(MethodInfo method, InterceptMethodAttribute attribute) + { + var returnType = method.ReturnType; + var parameters = method.GetParameters().Select(p => p.ParameterType).ToArray(); + + var requiredParameterTypes = new[] { typeof(int), typeof(int), typeof(long) }; + var lastParameterTypes = parameters.Skip(parameters.Length - requiredParameterTypes.Length); + + if (attribute.MethodReplacementAction == MethodReplacementActionType.ReplaceTargetMethod) + { + if (!lastParameterTypes.SequenceEqual(requiredParameterTypes)) + { + throw new Exception( + $"Method {method.DeclaringType.FullName}.{method.Name}() does not meet parameter requirements. " + + "Wrapper methods must have at least 3 parameters and the last 3 must be of types Int32 (opCode), Int32 (mdToken), and Int64 (moduleVersionPtr)."); + } + } + else if (attribute.MethodReplacementAction == MethodReplacementActionType.InsertFirst) + { + if (attribute.CallerAssembly == null || attribute.CallerType == null || attribute.CallerMethod == null) + { + throw new Exception( + $"Method {method.DeclaringType.FullName}.{method.Name}() does not meet InterceptMethodAttribute requirements. " + + "Currently, InsertFirst methods must have CallerAssembly, CallerType, and CallerMethod defined. " + + $"Current values: CallerAssembly=\"{attribute.CallerAssembly}\", CallerType=\"{attribute.CallerType}\", CallerMethod=\"{attribute.CallerMethod}\""); + } + else if (parameters.Any()) + { + throw new Exception( + $"Method {method.DeclaringType.FullName}.{method.Name}() does not meet parameter requirements. " + + "Currently, InsertFirst methods must have zero parameters."); + } + else if (returnType != typeof(void)) + { + throw new Exception( + $"Method {method.DeclaringType.FullName}.{method.Name}() does not meet return type requirements. " + + "Currently, InsertFirst methods must have a void return type."); + } + } + + var signatureHelper = SignatureHelper.GetMethodSigHelper(method.CallingConvention, returnType); + signatureHelper.AddArguments(parameters, requiredCustomModifiers: null, optionalCustomModifiers: null); + var signatureBytes = signatureHelper.GetSignature(); + + if (method.IsGenericMethod) + { + // if method is generic, fix first byte (calling convention) + // and insert a second byte with generic parameter count + const byte IMAGE_CEE_CS_CALLCONV_GENERIC = 0x10; + var genericArguments = method.GetGenericArguments(); + + var newSignatureBytes = new byte[signatureBytes.Length + 1]; + newSignatureBytes[0] = (byte)(signatureBytes[0] | IMAGE_CEE_CS_CALLCONV_GENERIC); + newSignatureBytes[1] = (byte)genericArguments.Length; + Array.Copy(signatureBytes, 1, newSignatureBytes, 2, signatureBytes.Length - 1); + + signatureBytes = newSignatureBytes; + } + + return string.Join(" ", signatureBytes.Select(b => b.ToString("X2"))); + } + } +} diff --git a/tools/PrepareRelease/PrepareRelease.csproj b/tools/PrepareRelease/PrepareRelease.csproj new file mode 100644 index 0000000000..64b25ee9aa --- /dev/null +++ b/tools/PrepareRelease/PrepareRelease.csproj @@ -0,0 +1,13 @@ + + + + Exe + net461 + + + + + + + + diff --git a/tools/PrepareRelease/Program.cs b/tools/PrepareRelease/Program.cs new file mode 100644 index 0000000000..b14b4353d0 --- /dev/null +++ b/tools/PrepareRelease/Program.cs @@ -0,0 +1,64 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Datadog.Core.Tools; + +namespace PrepareRelease +{ + public class Program + { + public const string Versions = "versions"; + public const string Integrations = "integrations"; + public const string Msi = "msi"; + + public static void Main(string[] args) + { + if (args.Length == 0) + { + throw new ArgumentException($@"You must specify at least one job name from [""{Versions}"", ""{Integrations}, ""{Msi}""]."); + } + + var solutionDir = EnvironmentTools.GetSolutionDirectory(); + + if (JobShouldRun(Integrations, args)) + { + Console.WriteLine("--------------- Integrations Job Started ---------------"); + GenerateIntegrationDefinitions.Run(solutionDir); + Console.WriteLine("--------------- Integrations Job Complete ---------------"); + } + + if (JobShouldRun(Versions, args)) + { + Console.WriteLine("--------------- Versions Job Started ---------------"); + SetAllVersions.Run(); + Console.WriteLine("--------------- Versions Job Complete ---------------"); + } + + if (JobShouldRun(Msi, args)) + { + Environment.SetEnvironmentVariable("SOLUTION_DIR", solutionDir); + var publishBatch = Path.Combine(solutionDir, "tools", "PrepareRelease", "publish-all.bat"); + ExecuteCommand(publishBatch); + + Console.WriteLine("--------------- MSI Job Started ---------------"); + SyncMsiContent.Run(); + Console.WriteLine("--------------- MSI Job Complete ---------------"); + } + } + + private static bool JobShouldRun(string jobName, string[] args) + { + return args.Any(a => string.Equals(a, jobName, StringComparison.OrdinalIgnoreCase)); + } + + private static void ExecuteCommand(string command) + { + var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command) { CreateNoWindow = true, UseShellExecute = true }; + var process = Process.Start(processInfo); + process.WaitForExit(120_000); + Console.WriteLine("Publish ExitCode: " + process.ExitCode, "ExecuteCommand"); + process?.Close(); + } + } +} diff --git a/tools/PrepareRelease/Properties/launchSettings.json b/tools/PrepareRelease/Properties/launchSettings.json new file mode 100644 index 0000000000..d1851bdbd0 --- /dev/null +++ b/tools/PrepareRelease/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "PrepareRelease": { + "commandName": "Project", + "commandLineArgs": "versions integrations msi" + } + } +} \ No newline at end of file diff --git a/tools/PrepareRelease/SetAllVersions.cs b/tools/PrepareRelease/SetAllVersions.cs new file mode 100644 index 0000000000..04df807d8c --- /dev/null +++ b/tools/PrepareRelease/SetAllVersions.cs @@ -0,0 +1,217 @@ +using System; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using Datadog.Core.Tools; + +namespace PrepareRelease +{ + public static class SetAllVersions + { + public static void Run() + { + Console.WriteLine($"Updating version instances to {VersionString()}"); + + // Dockerfile updates + SynchronizeVersion( + "customer-samples/ConsoleApp/Alpine3.9.dockerfile", + text => Regex.Replace(text, $"ARG TRACER_VERSION={VersionPattern()}", $"ARG TRACER_VERSION={VersionString()}")); + + SynchronizeVersion( + "customer-samples/ConsoleApp/Alpine3.10.dockerfile", + text => Regex.Replace(text, $"ARG TRACER_VERSION={VersionPattern()}", $"ARG TRACER_VERSION={VersionString()}")); + + SynchronizeVersion( + "customer-samples/ConsoleApp/Debian.dockerfile", + text => Regex.Replace(text, $"ARG TRACER_VERSION={VersionPattern()}", $"ARG TRACER_VERSION={VersionString()}")); + + SynchronizeVersion( + "reproductions/AutomapperTest/Dockerfile", + text => Regex.Replace(text, $"ARG TRACER_VERSION={VersionPattern()}", $"ARG TRACER_VERSION={VersionString()}")); + + // Managed project / NuGet package updates + SynchronizeVersion( + "src/Datadog.Trace/Datadog.Trace.csproj", + NugetVersionReplace); + + SynchronizeVersion( + "src/Datadog.Trace.AspNet/Datadog.Trace.AspNet.csproj", + NugetVersionReplace); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Managed/Datadog.Trace.ClrProfiler.Managed.csproj", + NugetVersionReplace); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Managed.Core/Datadog.Trace.ClrProfiler.Managed.Core.csproj", + NugetVersionReplace); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Managed.Loader/Datadog.Trace.ClrProfiler.Managed.Loader.csproj", + NugetVersionReplace); + + SynchronizeVersion( + "src/Datadog.Trace.OpenTracing/Datadog.Trace.OpenTracing.csproj", + NugetVersionReplace); + + // Fully qualified name updates + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Managed.Loader/Startup.cs", + FullAssemblyNameReplace); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Native/dd_profiler_constants.h", + FullAssemblyNameReplace); + + // Locked AssemblyVersion #.0.0.0 updates + SynchronizeVersion( + "src/Datadog.Trace.AspNet/AssemblyInfo.cs", + text => MajorAssemblyVersionReplace(text, ".")); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Managed.Core/AssemblyInfo.cs", + text => MajorAssemblyVersionReplace(text, ".")); + + // Native profiler updates + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Native/CMakeLists.txt", + text => FullVersionReplace(text, ".")); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Native/Resource.rc", + text => + { + text = FullVersionReplace(text, ","); + text = FullVersionReplace(text, "."); + return text; + }); + + SynchronizeVersion( + "src/Datadog.Trace.ClrProfiler.Native/version.h", + text => FullVersionReplace(text, ".")); + + // Deployment updates + SynchronizeVersion( + "integrations.json", + FullAssemblyNameReplace); + + SynchronizeVersion( + "docker/package.sh", + text => Regex.Replace(text, $"VERSION={VersionPattern()}", $"VERSION={VersionString()}")); + + SynchronizeVersion( + "deploy/Datadog.Trace.ClrProfiler.WindowsInstaller/Datadog.Trace.ClrProfiler.WindowsInstaller.wixproj", + WixProjReplace); + + Console.WriteLine($"Completed synchronizing versions to {VersionString()}"); + } + + private static string FullVersionReplace(string text, string split) + { + return Regex.Replace(text, VersionPattern(split), VersionString(split), RegexOptions.Singleline); + } + + private static string FullAssemblyNameReplace(string text) + { + return Regex.Replace(text, AssemblyString(VersionPattern()), AssemblyString(VersionString()), RegexOptions.Singleline); + } + + private static string MajorAssemblyVersionReplace(string text, string split) + { + return Regex.Replace(text, VersionPattern(fourPartVersion: true), MajorVersionString(split), RegexOptions.Singleline); + } + + private static string NugetVersionReplace(string text) + { + return Regex.Replace(text, $"{VersionPattern(withPrereleasePostfix: true)}", $"{VersionString(withPrereleasePostfix: true)}", RegexOptions.Singleline); + } + + private static string NuspecVersionReplace(string text) + { + return Regex.Replace(text, $"{VersionPattern(withPrereleasePostfix: true)}", $"{VersionString(withPrereleasePostfix: true)}", RegexOptions.Singleline); + } + + private static string WixProjReplace(string text) + { + text = Regex.Replace( + text, + $"datadog-dotnet-apm-{VersionPattern(withPrereleasePostfix: true)}-\\$\\(Platform\\)", + $"datadog-dotnet-apm-{VersionString(withPrereleasePostfix: true)}-$(Platform)", + RegexOptions.Singleline); + + text = Regex.Replace( + text, + $"InstallerVersion={VersionPattern()}", + $"InstallerVersion={VersionString()}", + RegexOptions.Singleline); + + return text; + } + + private static void SynchronizeVersion(string path, Func transform) + { + var solutionDirectory = EnvironmentTools.GetSolutionDirectory(); + var fullPath = Path.Combine(solutionDirectory, path); + + Console.WriteLine($"Updating version instances for {path}"); + + if (!File.Exists(fullPath)) + { + throw new Exception($"File not found to version: {path}"); + } + + var fileContent = File.ReadAllText(fullPath); + var newFileContent = transform(fileContent); + + File.WriteAllText(fullPath, newFileContent, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + private static string MajorVersionString(string split = ".") + { + return $"{TracerVersion.Major}{split}0{split}0{split}0"; + } + + private static string VersionString(string split = ".", bool withPrereleasePostfix = false) + { + var newVersion = $"{TracerVersion.Major}{split}{TracerVersion.Minor}{split}{TracerVersion.Patch}"; + + // this gets around a compiler warning about unreachable code below + var isPreRelease = TracerVersion.IsPreRelease; + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (withPrereleasePostfix && isPreRelease) + { + newVersion = newVersion + "-prerelease"; + } + + return newVersion; + } + + private static string VersionPattern(string split = ".", bool withPrereleasePostfix = false, bool fourPartVersion = false) + { + if (split == ".") + { + split = @"\."; + } + + var pattern = $@"\d+{split}\d+{split}\d+"; + + if (fourPartVersion) + { + pattern = pattern + $@"{split}\d+"; + } + + if (withPrereleasePostfix) + { + pattern = pattern + "(\\-prerelease)?"; + } + + return pattern; + } + + private static string AssemblyString(string versionText) + { + return $"Datadog.Trace.ClrProfiler.Managed, Version={versionText}.0, Culture=neutral, PublicKeyToken=def86d061d0d2eeb"; + } + } +} diff --git a/tools/PrepareRelease/SyncMsiContent.cs b/tools/PrepareRelease/SyncMsiContent.cs new file mode 100644 index 0000000000..2ad43df3df --- /dev/null +++ b/tools/PrepareRelease/SyncMsiContent.cs @@ -0,0 +1,110 @@ +using System; +using System.IO; +using System.Text; +using Datadog.Core.Tools; +using Datadog.Trace.TestHelpers; + +namespace PrepareRelease +{ + public class SyncMsiContent + { + private const string FileNameTemplate = @"{{file_name}}"; + private const string ComponentListTemplate = @"{{component_list}}"; + private const string ComponentGroupIdTemplate = @"{{component_group_id}}"; + private const string ComponentGroupDirectoryTemplate = @"{{component_group_directory}}"; + private const string FileIdPrefixTemplate = @"{{file_id_prefix}}"; + private const string FrameworkMonikerTemplate = @"{{framework_moniker}}"; + + private static readonly string Gac45ItemTemplate = $@" + + + "; + + private static readonly string Gac45FileTemplate = $@" + + + + + {ComponentListTemplate} + + + +"; + + public static void Run() + { + CreateWixFile( + groupId: "Files.Managed.Net45.GAC", + frameworkMoniker: "net45", + groupDirectory: "net45.GAC", + filePrefix: "net45_GAC_", + isGac: true); + CreateWixFile( + groupId: "Files.Managed.Net45", + frameworkMoniker: "net45"); + CreateWixFile( + groupId: "Files.Managed.Net461", + frameworkMoniker: "net461"); + CreateWixFile( + groupId: "Files.Managed.NetStandard20", + frameworkMoniker: "netstandard2.0"); + } + + private static void CreateWixFile( + string groupId, + string frameworkMoniker, + string groupDirectory = null, + string filePrefix = null, + bool isGac = false) + { + Console.WriteLine($"Creating the {groupId} Group"); + + groupDirectory = groupDirectory ?? $"{frameworkMoniker}"; + filePrefix = filePrefix ?? $"{frameworkMoniker.Replace(".", string.Empty)}_"; + + var solutionDirectory = EnvironmentHelper.GetSolutionDirectory(); + + var wixProjectRoot = + Path.Combine( + solutionDirectory, + "deploy", + "Datadog.Trace.ClrProfiler.WindowsInstaller"); + + var filePaths = DependencyHelpers.GetTracerBinContent(frameworkMoniker); + + var components = string.Empty; + + foreach (var filePath in filePaths) + { + var fileName = Path.GetFileName(filePath); + var component = + Gac45ItemTemplate + .Replace(FileIdPrefixTemplate, filePrefix) + .Replace(FrameworkMonikerTemplate, frameworkMoniker) + .Replace(FileNameTemplate, fileName); + + if (!isGac) + { + component = component.Replace(@" Assembly="".net""", string.Empty); + } + + components += component; + } + + var wixFileContent = + Gac45FileTemplate + .Replace(ComponentGroupDirectoryTemplate, groupDirectory) + .Replace(ComponentGroupIdTemplate, groupId) + .Replace(ComponentListTemplate, components); + + var wixFilePath = Path.Combine(wixProjectRoot, groupId + ".wxs"); + + File.WriteAllText(wixFilePath, wixFileContent, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + + Console.WriteLine($"{groupId} Group successfully created."); + } + } +} diff --git a/tools/PrepareRelease/publish-all.bat b/tools/PrepareRelease/publish-all.bat new file mode 100644 index 0000000000..5e9e883d63 --- /dev/null +++ b/tools/PrepareRelease/publish-all.bat @@ -0,0 +1,12 @@ + +REM SET SOLUTION_DIR=C:\Github\dd-trace-dotnet + +SET TOOL_BUILD_CONFIG=Release +SET INTEGRATIONS_PROJ=%SOLUTION_DIR%\src\Datadog.Trace.ClrProfiler.Managed\Datadog.Trace.ClrProfiler.Managed.csproj +SET OUTPUT_DIR=%SOLUTION_DIR%\tools\PrepareRelease\bin\tracer-home + +RMDIR "%OUTPUT_DIR%" /S /Q + +dotnet publish %INTEGRATIONS_PROJ% -c %TOOL_BUILD_CONFIG% -f net45 -o "%OUTPUT_DIR%\net45" +dotnet publish %INTEGRATIONS_PROJ% -c %TOOL_BUILD_CONFIG% -f net461 -o "%OUTPUT_DIR%\net461" +dotnet publish %INTEGRATIONS_PROJ% -c %TOOL_BUILD_CONFIG% -f netstandard2.0 -o "%OUTPUT_DIR%\netstandard2.0" diff --git a/tools/UpdateVendors/Program.cs b/tools/UpdateVendors/Program.cs new file mode 100644 index 0000000000..6281211a1f --- /dev/null +++ b/tools/UpdateVendors/Program.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Text; +using System.Text.RegularExpressions; + +namespace UpdateVendors +{ + public class Program + { + private const string AutoGeneratedMessage = @"//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +"; + + private static readonly string DownloadDirectory = Path.Combine(Environment.CurrentDirectory, "downloads"); + private static string _vendorProjectDirectory; + + public static void Main() + { + InitializeCleanDirectory(DownloadDirectory); + var solutionDirectory = GetSolutionDirectory(); + _vendorProjectDirectory = Path.Combine(solutionDirectory, "src", "Datadog.Trace", "Vendors"); + InitializeCleanDirectory(_vendorProjectDirectory); + + UpdateVendor( + libraryName: "Serilog", + branchDownload: "https://github.com/serilog/serilog/archive/v2.8.0.zip", + pathToSrc: new[] { "serilog-2.8.0", "src", "Serilog" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); + + UpdateVendor( + libraryName: "Serilog.Sinks.File", + branchDownload: "https://github.com/serilog/serilog-sinks-file/archive/v4.0.0.zip", + pathToSrc: new[] { "serilog-sinks-file-4.0.0", "src", "Serilog.Sinks.File" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); + + UpdateVendor( + libraryName: "StatsdClient", + branchDownload: "https://github.com/DataDog/dogstatsd-csharp-client/archive/3.3.0.zip", + pathToSrc: new[] { "dogstatsd-csharp-client-3.3.0", "src", "StatsdClient" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "StatsdClient")); + + UpdateVendor( + libraryName: "MessagePack", + branchDownload: "https://github.com/neuecc/MessagePack-CSharp/archive/v1.9.3.zip", + pathToSrc: new[] { "MessagePack-CSharp-1.9.3", "src", "MessagePack" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "MessagePack")); + } + + private static void RewriteCsFileWithStandardTransform(string filePath, string originalNamespace, Func extraTransform = null) + { + if (string.Equals(Path.GetExtension(filePath), ".cs", StringComparison.OrdinalIgnoreCase)) + { + RewriteFileWithTransform( + filePath, + content => + { + // Disable analyzer + var builder = new StringBuilder(AutoGeneratedMessage, content.Length * 2); + + builder.Append(content); + + // Prevent namespace conflicts + builder.Replace($"using {originalNamespace}", $"using Datadog.Trace.Vendors.{originalNamespace}"); + builder.Replace($"namespace {originalNamespace}", $"namespace Datadog.Trace.Vendors.{originalNamespace}"); + + // Don't expose anything we don't intend to + // by replacing all "public" access modifiers with "internal" + return Regex.Replace( + builder.ToString(), + @"public(\s+((abstract|sealed|static)\s+)?(partial\s+)?(class|struct|interface|enum|delegate))", + match => $"internal{match.Groups[1]}"); + }); + } + } + + private static void UpdateVendor( + string libraryName, + string branchDownload, + string[] pathToSrc, + Action transform = null) + { + Console.WriteLine($"Starting {libraryName} upgrade."); + + var zipLocation = Path.Combine(DownloadDirectory, $"{libraryName}.zip"); + var extractLocation = Path.Combine(DownloadDirectory, $"{libraryName}"); + + using (var repoDownloadClient = new WebClient()) + { + repoDownloadClient.DownloadFile(branchDownload, zipLocation); + } + + Console.WriteLine($"Downloaded {libraryName} upgrade."); + + ZipFile.ExtractToDirectory(zipLocation, extractLocation); + + Console.WriteLine($"Unzipped {libraryName} upgrade."); + + var sourceLocation = Path.Combine(pathToSrc.Prepend(extractLocation).ToArray()); + var projFile = Path.Combine(sourceLocation, $"{libraryName}.csproj"); + + // Rename the proj file to a txt for reference + File.Copy(projFile, projFile + ".txt"); + File.Delete(projFile); + Console.WriteLine($"Renamed {libraryName} project file."); + + // Delete the assembly properties + var assemblyPropertiesFolder = Path.Combine(sourceLocation, @"Properties"); + SafeDeleteDirectory(assemblyPropertiesFolder); + Console.WriteLine($"Deleted {libraryName} assembly properties file."); + + if (transform != null) + { + Console.WriteLine($"Running transforms on files for {libraryName}."); + + var files = Directory.GetFiles( + sourceLocation, + "*.*", + SearchOption.AllDirectories); + + foreach (var file in files) + { + if (ShouldDropFile(file)) + { + File.Delete(file); + } + else + { + transform(file); + } + } + + Console.WriteLine($"Finished transforms on files for {libraryName}."); + } + + // Move it all to the vendors directory + Console.WriteLine($"Copying source of {libraryName} to vendor project."); + var vendorFinalPath = Path.Combine(_vendorProjectDirectory, libraryName); + SafeDeleteDirectory(vendorFinalPath); + Directory.Move(sourceLocation, vendorFinalPath); + Console.WriteLine($"Finished {libraryName} upgrade."); + } + + private static bool ShouldDropFile(string filePath) + { + var drops = new List() + { + "StatsdClient\\DogStatsdService.cs", + "StatsdClient\\MetricsTimer.cs", + "StatsdClient\\IDogStatsD.cs", + "StatsdClient\\DogStatsD.cs", + }; + + foreach (var drop in drops) + { + if (filePath.Contains(drop, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + private static void RewriteFileWithTransform(string filePath, Func transform) + { + var fileContent = File.ReadAllText(filePath); + fileContent = transform(fileContent); + File.WriteAllText( + filePath, + fileContent, + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + + private static void InitializeCleanDirectory(string directoryPath) + { + SafeDeleteDirectory(directoryPath); + Directory.CreateDirectory(directoryPath); + } + + private static void SafeDeleteDirectory(string directoryPath) + { + if (Directory.Exists(directoryPath)) + { + Directory.Delete(directoryPath, recursive: true); + } + } + + private static string GetSolutionDirectory() + { + var startDirectory = Environment.CurrentDirectory; + var currentDirectory = Directory.GetParent(startDirectory); + const string searchItem = @"Datadog.Trace.sln"; + + while (true) + { + var slnFile = currentDirectory.GetFiles(searchItem).SingleOrDefault(); + + if (slnFile != null) + { + break; + } + + currentDirectory = currentDirectory.Parent; + + if (currentDirectory == null || !currentDirectory.Exists) + { + throw new Exception($"Unable to find solution directory from: {startDirectory}"); + } + } + + return currentDirectory.FullName; + } + } +} diff --git a/tools/UpdateVendors/UpdateVendors.csproj b/tools/UpdateVendors/UpdateVendors.csproj new file mode 100644 index 0000000000..5635c9dce4 --- /dev/null +++ b/tools/UpdateVendors/UpdateVendors.csproj @@ -0,0 +1,8 @@ + + + + Exe + netcoreapp3.0 + + +